#include "stardundee.h" #include #include #include #include #include "ccsds.h" StarDundee::StarDundee(QWidget *parent) : QWidget(parent) { // Packet receiver timer = new QTimer; rmapPacketSEMAPHORE = new QSemaphore; ccsdsPacketSEMAPHORE = new QSemaphore; rmapPacket = (char*) malloc(RMAP_MAX_PACKET_LENGTH); ccsdsPacket = (unsigned char*) malloc(CCSDS_MAX_PACKET_LENGTH); spwPacket = (char*) malloc( qMax(RMAP_MAX_PACKET_LENGTH, CCSDS_MAX_PACKET_LENGTH) ); starDundeeStatusQueryDialog = new QDialog; commandCode = invalid0; // initialization of the cmmand code for the RMAP transfers rmapTargetLogicalAddress = DEFAULT_TARGET; rmapSourceLogicalAddress = DEFAULT_SOURCE; connection_LAYOUT = new QGridLayout; usbDeviceNumber_LABEL = new QLabel(tr("USB device number: ")); linkNumber_LABEL = new QLabel(tr("SpaceWire link number: ")); starDundeeStatusQueryDialogLabel = new QLabel(tr("SpaceWire links state")); statusLink1 = new QLabel(tr("Link 1 status code: -")); statusLink2 = new QLabel(tr("Link 2 status code: -")); //*** QPUSHBUTTON ***// starDundeeStatusQueryContinueButton = new QPushButton(tr("Continue")); starDundeeStatusQueryRetryButton = new QPushButton(tr("Retry")); starDundeeStatusQueryAbortButton = new QPushButton(tr("Abort")); starDundeeSendOneTimecode = new QPushButton(tr("send one timecode")); starDundeeSendOneTimePacketAndOneTimecode = new QPushButton(tr("send one update time\n+ one time code")); starDundeeSendTimecodePeriodically = new QPushButton(tr("start timecodes at 1 Hz")); starDundeeSendOneTimePacketAndTimecodePeriodically = new QPushButton(tr("send one update time\n+ timecodes at 1 Hz")); arbitraryTime = new ArbitraryTime(1); // 1 is for the horizontal layout arbitraryTimeToSend = 0x80000000; paulCommonCRC = new PaulCommonCRC(); flag_sendTimecodePeriodically = false; starDundeeSendOneTimecode->setEnabled( false ); starDundeeSendTimecodePeriodically->setEnabled( false ); starDundeeSendOneTimePacketAndOneTimecode->setEnabled( false ); starDundeeSendOneTimePacketAndTimecodePeriodically->setEnabled( false ); usbDeviceNumber_SPINBOX = new QSpinBox; usbDeviceNumber_SPINBOX->setRange(0,32); usbDeviceNumber_SPINBOX->setValue(0); linkNumber_SPINBOX = new QSpinBox; linkNumber_SPINBOX->setRange(1,2); linkNumber_SPINBOX->setValue(1); // STAR DUNDEE STATUS QUERY DIALOG starDundeeStatusQueryDialogLayout = new QGridLayout; starDundeeStatusQueryDialogLayout->addWidget(starDundeeStatusQueryDialogLabel, 0, 0, 1, 2); starDundeeStatusQueryDialogLayout->addWidget(starDundeeStatusQueryContinueButton, 1, 0, 0); starDundeeStatusQueryDialogLayout->addWidget(starDundeeStatusQueryRetryButton, 1, 1, 0); starDundeeStatusQueryDialogLayout->addWidget(starDundeeStatusQueryAbortButton, 1, 2, 0); starDundeeStatusQueryDialogLayout->addWidget(statusLink1, 2, 0, 0); starDundeeStatusQueryDialogLayout->addWidget(statusLink2, 3, 0, 0); starDundeeStatusQueryDialog->setLayout(starDundeeStatusQueryDialogLayout); connection_LAYOUT->addWidget(usbDeviceNumber_LABEL, 0, 0, 1, 1); connection_LAYOUT->addWidget(usbDeviceNumber_SPINBOX, 0, 1, 1, 1); connection_LAYOUT->addWidget(linkNumber_LABEL, 1, 0, 1, 1); connection_LAYOUT->addWidget(linkNumber_SPINBOX, 1, 1, 1, 1); connection_LAYOUT->addWidget(starDundeeSendOneTimecode, 2, 0, 1, 1); connection_LAYOUT->addWidget(starDundeeSendOneTimePacketAndOneTimecode, 2, 1, 1, 1); connection_LAYOUT->addWidget(starDundeeSendTimecodePeriodically, 3, 0, 1, 1 ); connection_LAYOUT->addWidget(starDundeeSendOneTimePacketAndTimecodePeriodically, 3, 1, 1, 1); connection_LAYOUT->addWidget(arbitraryTime, 6, 0, 1, 2); connection_LAYOUT->setRowStretch(7, 1); connection_LAYOUT->setColumnStretch(2, 1); this->setLayout(connection_LAYOUT); connect(starDundeeStatusQueryRetryButton, SIGNAL(clicked()), this, SLOT(reTestSPWLink())); connect(starDundeeStatusQueryAbortButton, SIGNAL(clicked()), starDundeeStatusQueryDialog, SLOT(reject())); connect(starDundeeStatusQueryContinueButton, SIGNAL(clicked()), starDundeeStatusQueryDialog, SLOT(accept())); // TIMECODES connect(this->starDundeeSendOneTimecode, SIGNAL(clicked()), this, SLOT(sendOneTimecode())); connect(this->starDundeeSendTimecodePeriodically, SIGNAL(clicked()), this, SLOT(sendTimecodePeriodically())); connect(this->starDundeeSendOneTimePacketAndOneTimecode, SIGNAL(clicked()), this, SLOT(sendOneTimePacketAndOneTimecode())); connect(this->starDundeeSendOneTimePacketAndTimecodePeriodically, SIGNAL(clicked()), this, SLOT(sendOneTimePacketAndTimecodePeriodically())); connect(this->arbitraryTime, SIGNAL(timeToSendChanged(long)), this, SLOT(updateTimeToSend(long))); connect(this->timer, SIGNAL(timeout()), this, SLOT(receivePollingLoop())); } StarDundee::~StarDundee() { free(rmapPacket); free(ccsdsPacket); free(spwPacket); USBSpaceWire_Close(hDevice); // Close the device } bool StarDundee::Open() { int status; U32 statusControl; unsigned int linkStatus1; unsigned int linkStatus2; unsigned char linkNumber; unsigned char deviceIsAnInterface; if (!USBSpaceWire_Open(&hDevice, usbDeviceNumber_SPINBOX->value())) // Open the USB device { emit sendMessage("stardundee *** Open *** ERROR: USBSpaceWire_Open(&hDevice, 0))"); return false; } emit sendMessage("stardundee *** Open *** USBSpaceWire_Open successful, device number: " + QString::number(usbDeviceNumber_SPINBOX->value())); USBSpaceWire_EnableNetworkMode(hDevice, 0); // deactivate the network mode CFGSpaceWire_EnableRMAP(1); // Enable the use of RMAP for the StarDundee brick configuration CFGSpaceWire_SetRMAPDestinationKey(0x20); // Set the destination key expected by STAR-Dundee devices // Set the path and return path to the device // This affects just the operations performed by the Configuration Library and does not affect the packets // sent and received using the driver API. CFGSpaceWire_StackClear(); CFGSpaceWire_AddrStackPush(0); CFGSpaceWire_AddrStackPush(254); CFGSpaceWire_RetAddrStackPush(254); // set the base transmit rate to 100 MHz status = CFGSpaceWire_SetBrickBaseTransmitRate( hDevice, CFG_BRK_CLK_100_MHZ, CFG_BRK_DVDR_1, 0xff); if (status != CFG_TRANSFER_SUCCESS) { emit sendMessage("ERROR CFGSpaceWire_SetBrickBaseTransmitRate"); } else emit sendMessage("OK CFGSpaceWire_SetBrickBaseTransmitRate, base rate = 100 MHz"); //********************* // LINK 1 CONFIGURATION linkNumber = 1; if (CFGSpaceWire_GetLinkStatusControl(hDevice, linkNumber, &statusControl) != CFG_TRANSFER_SUCCESS) emit sendMessage("Could not read link status control for link " + QString::number(linkNumber)); else { emit sendMessage("OK CFGSpaceWire_GetLinkStatusControl of link " + QString::number(linkNumber)); // Set the link status control register properties CFGSpaceWire_LSEnableAutoStart(&statusControl, 1); CFGSpaceWire_LSEnableStart(&statusControl, 1); CFGSpaceWire_LSEnableDisabled(&statusControl, 0); CFGSpaceWire_LSEnableTristate(&statusControl, 0); CFGSpaceWire_LSSetOperatingSpeed(&statusControl, 9); // sets the link speed to ( 100 MHz / (9+1) ) = 10 MHz // Set the link status control register if (CFGSpaceWire_SetLinkStatusControl(hDevice, linkNumber, statusControl) != CFG_TRANSFER_SUCCESS) emit sendMessage("Could not set the link status control for link " + QString::number(linkNumber)); else emit sendMessage("link status control for link " + QString::number(0x01) + " is set"); } //********************* // LINK 2 CONFIGURATION linkNumber = 2; if (CFGSpaceWire_GetLinkStatusControl(hDevice, linkNumber, &statusControl) != CFG_TRANSFER_SUCCESS) emit sendMessage("Could not read link status control for link " + QString::number(linkNumber)); else { emit sendMessage("OK CFGSpaceWire_GetLinkStatusControl of link " + QString::number(linkNumber)); // Set the link status control register properties CFGSpaceWire_LSEnableAutoStart(&statusControl, 1); CFGSpaceWire_LSEnableStart(&statusControl, 1); CFGSpaceWire_LSEnableDisabled(&statusControl, 0); CFGSpaceWire_LSEnableTristate(&statusControl, 0); CFGSpaceWire_LSSetOperatingSpeed(&statusControl, 9); // sets the link speed to ( 100 MHz / (9+1) ) = 10 MHz // Set the link status control register if (CFGSpaceWire_SetLinkStatusControl(hDevice, linkNumber, statusControl) != CFG_TRANSFER_SUCCESS) emit sendMessage("Could not set the link status control for link " + QString::number(linkNumber)); else emit sendMessage("link status control for link " + QString::number(linkNumber) + " is set"); } //******************************* // SET THE DEVICE AS AN INTERFACE deviceIsAnInterface = 1; if (CFGSpaceWire_SetAsInterface(hDevice, deviceIsAnInterface, 0) != CFG_TRANSFER_SUCCESS) emit sendMessage("Could not set the device to be an interface"); else emit sendMessage("Device is an interface: " + QString::number(deviceIsAnInterface) + " (1 => true, 0 => false)"); // setRoutingTableEntry(0xfe, 0x02); // [0010] => connect LFR on the [Link 1] port // setRoutingTableEntry(0xfd, 0x04); // [0100] => connect TIMEGEN on the [Link 2] port // GetRoutingTableEntry(0xfe); // GetRoutingTableEntry(0xfd); // GetRoutingTableEntry(0x01); USBSpaceWire_RegisterReceiveOnAllPorts(hDevice); // Register to receive on port 1 only // USBSpaceWire_RegisterReceiveOnPort(hDevice, 0x01); // Register to receive on port 1 only // USBSpaceWire_RegisterReceiveOnPort(hDevice, 0xfe); // Register to receive on port 254 only USBSpaceWire_ClearEndpoints(hDevice); // clear the USB endpoints emit sendMessage("The driver's current send buffer size is " + QString::number(USBSpaceWire_GetDriverSendBufferSize(hDevice)) + " bytes"); emit sendMessage("The driver's current read buffer size is " + QString::number(USBSpaceWire_GetDriverReadBufferSize(hDevice)) + " bytes"); emit sendMessage("USBSpaceWire_IsReadThrottling is " + QString::number(USBSpaceWire_IsReadThrottling(hDevice))); // initialize SPW packet semaphores while (rmapPacketSEMAPHORE->available()!=0) rmapPacketSEMAPHORE->acquire(); while (ccsdsPacketSEMAPHORE->available()!=0) ccsdsPacketSEMAPHORE->acquire(); //************ // test Link 1 and Link 2 linkStatus1 = getLinkStatus(0x01); linkStatus2 = getLinkStatus(0x02); if ((linkStatus1==1) || (linkStatus2==1)) { // statusLink1->setText("Link 1 status code: " + QString::number(linkStatus1)); // statusLink2->setText("Link 2 status code: " + QString::number(linkStatus2)); // starDundeeStatusQueryDialog->exec(); emit isOpen(true); timer->start(100); // starts the periodical timer, period = 100ms initializeTimecodeGeneration(); return true; } else { statusLink1->setText("Link 1 status code: " + QString::number(linkStatus1)); statusLink2->setText("Link 2 status code: " + QString::number(linkStatus2)); starDundeeStatusQueryDialog->exec(); return false; } } void StarDundee::Close() { USBSpaceWire_Close(hDevice); // Close the device emit sendMessage("stardundee *** Close *** USBSpaceWire_Close, device: " + QString::number(usbDeviceNumber_SPINBOX->value())); USBSpaceWire_UnregisterReceiveOnAllPorts(hDevice); // Stop receiving on all ports emit isOpen(false); } unsigned char StarDundee::setRoutingTableEntry(int tableEntry, U32 dwOutputPorts) { U32 routingTableEntry; // SET THE ROUTING TABLE ENTRY FOR LOGICAL ADDRESSING, TARGET entryNumber if (CFGSpaceWire_ClearRoutingTableEntry(hDevice, tableEntry) != CFG_TRANSFER_SUCCESS) { emit sendMessage("Could not clear routing table entry " + QString::number(tableEntry)); } // Build the routing table entry CFGSpaceWire_RTBuildRoutingTableEntry(&routingTableEntry, dwOutputPorts, // route out of port dwOutputPorts 0, // header deletion disabled 0); // priority normal // Set the routing table entry for logical address tableEntry if (CFGSpaceWire_SetRoutingTableEntry(hDevice, tableEntry, routingTableEntry) != CFG_TRANSFER_SUCCESS) { emit sendMessage("Could not set routing table entry [" + QString::number(tableEntry) + "]"); } else emit sendMessage("Routing table entry [" + QString::number(tableEntry) + "] set" ); return 1; } unsigned int StarDundee::GetRoutingTableEntry(int tableEntry) { U32 routingTableEntry, outputPorts; char enabled, delHead, priority; int portNum; emit sendMessage("GetRoutingTableEntry [" + QString::number(tableEntry) + "]"); // Read the routing table entry if (CFGSpaceWire_GetRoutingTableEntry(hDevice, tableEntry, &routingTableEntry) != CFG_TRANSFER_SUCCESS) { emit sendMessage("Could not read routing table entry [" + QString::number(tableEntry) + "]"); } else { // Display the routing table entry properties CFGSpaceWire_RTIsEnabled(routingTableEntry, &enabled); CFGSpaceWire_RTIsDelHead(routingTableEntry, &delHead); CFGSpaceWire_RTIsPriority(routingTableEntry, &priority); CFGSpaceWire_RTGetOutputPorts(routingTableEntry, &outputPorts); emit sendMessage("CFGSpaceWire_RTIsEnabled : " + QString::number(enabled)); emit sendMessage("CFGSpaceWire_RTIsDelHead : " + QString::number(delHead)); emit sendMessage("CFGSpaceWire_RTIsPriority : " + QString::number(priority)); emit sendMessage("CFGSpaceWire_RTGetOutputPorts : "); for (portNum = 0; portNum < 32; portNum++) { if (outputPorts & (1 << portNum)) { emit sendMessage(QString::number(portNum)); } } } return 1; } unsigned int StarDundee::Write(unsigned int *Value, unsigned int count, unsigned int address) { unsigned int remainingCount = count; unsigned int iOffset = 0; QString console_message; char* data; if(rmapPacketSEMAPHORE->available()!=0) { emit appendToLog("WARNING === in function WRITE of rmapplugin *** RMAP request already running, WRITE access stopped"); return 1; } emit this->RMAP_write_reply_setText("reply to the write command required\nlast reply status: unavailable"); data = (char*) malloc(READ_WRITE_MAX_COUNTS*4); emit appendToLog(QString("*** START *** WRITE ")+ QString::number(count) + QString(" word(s) @0x")+ QString::number(address,16)); QProgressBar* progress=NULL; if (count > READ_WRITE_MAX_COUNTS) { progress = lppmonEngine::getProgressBar("Reading on spw @0x"+QString::number(address,16)+" %v of "+QString::number(count)+" words ",count); } while (remainingCount > READ_WRITE_MAX_COUNTS) { // progress bar progress->setValue(count-remainingCount); qApp->processEvents(); for (int i = 0; i>8); data[i*4+1] = (char) ((unsigned int) Value[i+iOffset]>>16); data[i*4+0] = (char) ((unsigned int) Value[i+iOffset]>>24); } console_message.sprintf("remainingCount: %d => ", remainingCount); emit appendToLog(console_message + QString("Write ")+ QString::number(READ_WRITE_MAX_COUNTS*4) + QString(" byte(s) @0x")+ QString::number(address,16)); if(WriteBLOCK(data, READ_WRITE_MAX_COUNTS*4, address)==0) { emit appendToLog("WARNING === in function WRITE of rmapplugin *** RMAP write command failed"); return 1; } remainingCount = remainingCount - READ_WRITE_MAX_COUNTS; address = address + READ_WRITE_MAX_COUNTS * 4; iOffset = iOffset + READ_WRITE_MAX_COUNTS; } if (remainingCount > 0) { for (unsigned int i = 0; i>8); data[i*4+1] = (char) ((unsigned int) Value[i+iOffset]>>16); data[i*4+0] = (char) ((unsigned int) Value[i+iOffset]>>24); } console_message.sprintf("remainingCount: %d => ", remainingCount); emit appendToLog(console_message + QString("Write ")+ QString::number(remainingCount*4) + QString(" byte(s) @0x")+ QString::number(address,16)); if (WriteBLOCK(data, remainingCount*4, address)==0) { emit appendToLog("WARNING === in function WRITE of rmapplugin *** RMAP write command failed"); return 1; } } if (count > READ_WRITE_MAX_COUNTS) { lppmonEngine::deleteProgressBar(progress); } emit appendToLog(QString("*** STOP *** WRITE")); free(data); return count; } unsigned int StarDundee::Read(unsigned int *Value, unsigned int count, unsigned int address) { unsigned int remainingCount = count; unsigned int iOffset = 0; QString console_message; if(rmapPacketSEMAPHORE->available()!=0) { emit appendToLog("WARNING === in function READ of rmapplugin *** RMAP request already running, READ access stopped"); return 1; } emit appendToLog(QString("*** START *** READ ")+ QString::number(count) + QString(" word(s) @0x")+ QString::number(address,16)); QProgressBar* progress=NULL; if (count > READ_WRITE_MAX_COUNTS) { progress = lppmonEngine::getProgressBar("Reading on spw @0x"+QString::number(address,16)+" %v of "+QString::number(count)+" words ",count); } while (remainingCount > READ_WRITE_MAX_COUNTS) { // progress bar progress->setValue(count-remainingCount); qApp->processEvents(); console_message.sprintf("remainingCount: %d => ", remainingCount); emit appendToLog(console_message + QString("Read ")+ QString::number(4*READ_WRITE_MAX_COUNTS) + QString(" byte(s) @0x")+ QString::number(address,16)); if (this->ReadBLOCK(READ_WRITE_MAX_COUNTS*4, address)==0) { emit appendToLog("WARNING === in function READ of rmapplugin *** RMAP packet not received"); return 1; } for(int i=0;iacquireRMAPSemaphore(); } if (remainingCount > 0) { console_message.sprintf("remainingCount: %d => ", remainingCount); emit appendToLog(console_message + QString("Read ")+ QString::number(4*remainingCount) + QString(" byte(s) @0x")+ QString::number(address,16)); if (this->ReadBLOCK(4*remainingCount, address)==0) { emit appendToLog("WARNING === in function READ of rmapplugin *** RMAP packet not received"); return 1; } for(unsigned int i=0;iacquireRMAPSemaphore(); } if (count > READ_WRITE_MAX_COUNTS) { lppmonEngine::deleteProgressBar(progress); } emit appendToLog(QString("*** STOP *** READ ")); return count; } unsigned int StarDundee::WriteBLOCK(char *data, unsigned int nbBytes, unsigned int address) { RMAP *RMAPCommand; char * packet; char* aux; unsigned char offset, headerSize, CRCSize; unsigned int totalSize; int errorCode; QString console_message; if (getLinkStatus(this->linkNumber_SPINBOX->value()) == 0) { this->Close(); return 1; } RMAPCommand = new RMAP(this->commandCode, rmapTargetLogicalAddress, rmapSourceLogicalAddress, address, nbBytes, data); headerSize = sizeof(RMAPCommand->RMAPHeader); CRCSize = 1; //************************* // BUILD THE PACKET TO SEND totalSize = headerSize + nbBytes + CRCSize + PATH_ADDRESSING_OFFSET; packet = (char*) malloc( totalSize ); aux = (char*) ((void*) &RMAPCommand->RMAPHeader); packet[0] = getPacketFirstByte(); // TO BE SUPPRESSED for(unsigned int i = 0; idataCRC; //**************** // SEND THE PACKET result = USBSpaceWire_SendPacket(hDevice, packet, totalSize, BWAIT_1, &pIdentifier); if (result != TRANSFER_SUCCESS) { emit sendMessage("ERROR *** WriteStarDundee when sending packet of size " + QString::number(totalSize) +", with code: " + QString::number(result)); USBSpaceWire_FreeSend(hDevice, pIdentifier); free(data); return 1; } // else emit sendMessage("OK *** WriteStarDundee when sending packet of size " + QString::number(totalSize)); //************** // Free the send USBSpaceWire_FreeSend(hDevice, pIdentifier); free(packet); if ( (commandCode == writeSingle_noVer_Rep) | (commandCode == writeInc_noVer_Rep) | (commandCode == writeSingle_ver_rep) | (commandCode == writeInc_ver_rep) ) { // WAIT FOR THE RMAP REPLY PACKET errorCode = this->receiveSPWPacket(1); if (errorCode<=0) { emit appendToLog("WARNING === in function WriteBLOCK of rmapplugin *** RMAP packet reception failed with code " + QString::number(errorCode)); return 0; } if(rmapPacketSize != 8) { console_message.sprintf("WARNING === in function WRITE (with reply) of rmapplugin *** write reply format not compliant\n"); emit appendToLog(console_message); return 0; } switch (this->rmapPacket[3]) // byte 4 is the status byte in the reply { case 0: emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: 0 Successfull"); break; case 1: emit appendToLog("WARNING === in function WRITE (with reply) of rmapplugin *** General error code"); emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: 1 General error code"); break; case 2: emit appendToLog("WARNING === in function WRITE (with reply) of rmapplugin *** Unused RMAP packet type or command code"); emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: 2 Unused RMAP packet type or command code"); break; case 3: emit appendToLog("WARNING === in function WRITE (with reply) of rmapplugin *** Invalid key"); emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: 3 Invalid key"); break; case 4: emit appendToLog("WARNING === in function WRITE (with reply) of rmapplugin *** Invalid data CRC"); emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: 4 Invalid data CRC"); break; case 5: emit appendToLog("WARNING === in function WRITE (with reply) of rmapplugin *** Early EOP"); emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: 5 Early EOP"); break; case 6: emit appendToLog("WARNING === in function WRITE (with reply) of rmapplugin *** Too much data"); emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: 6 Too much data"); break; case 7: emit appendToLog("WARNING === in function WRITE (with reply) of rmapplugin *** EEP"); emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: 7 EEP"); break; case 8: emit appendToLog("WARNING === in function WRITE (with reply) of rmapplugin *** Reserved"); emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: 8 Reserved"); break; case 9: emit appendToLog("WARNING === in function WRITE (with reply) of rmapplugin *** Verify buffer overrun"); emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: 9 Verify buffer overrun"); break; case 10: emit appendToLog("WARNING === in function WRITE (with reply) of rmapplugin *** RMAP command not implemented or not authorised"); emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: 10 RMAP command not implemented or not authorised"); break; case 11: emit appendToLog("WARNING === in function WRITE (with reply) of rmapplugin *** RMW data length error"); emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: 11 RMAP RMW data length error"); break; case 12: emit appendToLog("WARNING === in function WRITE (with reply) of rmapplugin *** Invalid target logical address"); emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: 12 Invalid target logical address"); break; } this->acquireRMAPSemaphore(); } else emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: unavailable"); return nbBytes; } unsigned int StarDundee::ReadBLOCK(unsigned int nbBytes, unsigned int address) { int errorCode; RMAP *RMAPCommand; char *packet; char *aux; unsigned int dataLength = 0; unsigned int totalSize = 0; //********************** // Check the link status if ( getLinkStatus( this->linkNumber_SPINBOX->value() ) == 0 ) { this->Close(); emit appendToLog("WARNING === in function WriteSPW of StarDundee *** SPW link not running\n"); return 0; } //********************** // SEND THE READ COMMAND if (nbBytes > 4) { RMAPCommand = new RMAP(read_Inc, rmapTargetLogicalAddress, rmapSourceLogicalAddress, address, nbBytes, NULL); } else { RMAPCommand = new RMAP(read_Single, rmapTargetLogicalAddress, rmapSourceLogicalAddress, address, nbBytes, NULL); } //************************* // BUILD THE PACKET TO SEND totalSize = sizeof(RMAPCommand->RMAPHeader) + PATH_ADDRESSING_OFFSET; packet = (char*) malloc( totalSize ); aux = (char*) ((void*) &RMAPCommand->RMAPHeader); packet[0] = getPacketFirstByte(); // TO BE SUPPRESSED for (unsigned int i = 0; iRMAPHeader); i++) packet[i+PATH_ADDRESSING_OFFSET] = aux[i]; //**************** // SEND THE PACKET result = USBSpaceWire_SendPacket(hDevice, packet, totalSize, BWAIT_1, &pIdentifier); if (result != TRANSFER_SUCCESS) emit sendMessage("ERR *** ReadStarDundee *** ReadBLOCK *** sending the READ command "); else { // emit sendMessage("OK *** ReadStarDundee *** ReadBLOCK *** sending the READ command"); // emit appendToLog("packet sent, B0 = " + QString::number(packet[0], 16) // + " *** B1 = " + QString::number(packet[1], 16) // + " *** B2 = " + QString::number(packet[2], 16) // + " *** B3 = " + QString::number(packet[3], 16) // + " *** B4 = " + QString::number(packet[4], 16) // + " *** B5 = " + QString::number(packet[5], 16) // ); } //************** // Free the send USBSpaceWire_FreeSend(hDevice, pIdentifier); free(packet); //********************************* // RECEIVE THE INCOMING RMAP PACKET errorCode = this->receiveSPWPacket(1); // request ID 1 is for RMAP packet if (errorCode<=0) { emit appendToLog("WARNING === in function ReadBLOCK of StarDundee *** RMAP packet reception failed with code " + QString::number(errorCode)); return 0; } dataLength = rmapPacketSize - RMAP_READ_REPLY_HEADER_LENGTH - RMAP_DATA_CRC_LENGTH; if(dataLength != nbBytes) { emit appendToLog("WARNING === in function READ of StarDundee *** number of data received (" +QString::number(dataLength) +") not equal to number of data requested (" +QString::number(nbBytes) +")"); return 0; } return dataLength; } unsigned int StarDundee::WriteSPW(char *Value, unsigned int count, char targetLogicalAddress, char userApplication) { char protocoleIdentifier = 0x02; char reserved = 0x00; char *SPWData; unsigned int totalSize; if (count>248) { emit appendToLog("WARNING === in function WRITE of rmapplugin *** CCSDS packet size > 248 bytes\n"); return 1; } emit appendToLog("*** START *** Send CCSDS packet of "+ QString::number(count) + " byte(s)"); if ( getLinkStatus( this->linkNumber_SPINBOX->value() ) == 0 ) { this->Close(); emit appendToLog("WARNING === in function WriteSPW of StarDundee *** SPW link not running\n"); return 1; } totalSize = count + 4 + PATH_ADDRESSING_OFFSET; // The StarDundee brick is in PATH addressing SPWData = (char*) malloc(totalSize); // SPW HEADER SPWData[0] = getPacketFirstByte(); SPWData[0+PATH_ADDRESSING_OFFSET] = targetLogicalAddress; SPWData[1+PATH_ADDRESSING_OFFSET] = protocoleIdentifier; SPWData[2+PATH_ADDRESSING_OFFSET] = reserved; SPWData[3+PATH_ADDRESSING_OFFSET] = userApplication; // CCSDS PACKET for (unsigned int i = 0; iavailable()) { return rmapPacketSize; } } //******************** // TRY TO RECEIVE DATA nbBytes = qMax(RMAP_MAX_PACKET_LENGTH, CCSDS_MAX_PACKET_LENGTH); // maximum size of the packet to receive nPacketNum = 1; result = USBSpaceWire_ReadPackets(hDevice, spwPacket, nbBytes, nPacketNum, BWAIT_1, &properties, &pIdentifierRead); if (result != TRANSFER_SUCCESS) { emit sendMessage("Error: Could not receive the packet, result = " + QString::number(result)); USBSpaceWire_FreeRead(hDevice, pIdentifierRead); // Free the read buffer return 0; } else { packetLength = properties.len; if (properties.eop == SPACEWIRE_USB_NO_EOP) { emit appendToLog("No end of packet marker received"); } // else if (properties.eop == SPACEWIRE_USB_EOP) // { // emit appendToLog("Normal end of packet marker received"); // } else if (properties.eop == SPACEWIRE_USB_EEP) { emit appendToLog("Error end of packet marker received"); } USBSpaceWire_FreeRead(hDevice, pIdentifierRead); // Free the read buffer } switch(spwPacket[1]) // byte 1 is the protocole identifier in the SPW packet { case 1: // 0x01 is the protocole identifier for RMAP packets if (rmapPacketSEMAPHORE->available()!=0) return -3; // ERROR === previous RMAP packet not processed yet for(unsigned int i=0; irelease(); // emit appendToLog("RMAP packet of size " + QString::number(packetLength) + " received"); // emit appendToLog("packet received, B0 = " + QString::number(spwPacket[0], 16) // + " *** B1 = " + QString::number(spwPacket[1], 16) // + " *** B2 = " + QString::number(spwPacket[2], 16) // + " *** B3 = " + QString::number(spwPacket[3], 16) // + " *** B4 = " + QString::number(spwPacket[4], 16) // + " *** B5 = " + QString::number(spwPacket[5], 16) // ); return packetLength; case 2: // 0x02 is the protocole identifier for CCSDS packets if (ccsdsPacketSEMAPHORE->available()!=0) { emit sendMessage("in function [receiveSPWPacket] === ERROR === previous CCSDS packet not processed yet"); return -4; // ERROR === previous CCSDS packet not processed yet } for(unsigned int i=0; ivalue())) { emit isOpen(true); starDundeeStatusQueryDialog->accept(); } } unsigned char StarDundee::getPacketFirstByte() { unsigned char firstByte; firstByte = (unsigned char) this->linkNumber_SPINBOX->value(); return firstByte; } //********** // TIMECODES void StarDundee::initializeTimecodeGeneration() { U32 dwTickEnableStatus; U32 rtr_clk_freq; // (1) RESET if (!USBSpaceWire_TC_Reset(hDevice)) emit sendMessage("ERR *** in Open *** Could not reset timecodes\n"); // (2) Clear the tick enable register if (CFGSpaceWire_SetTickEnableStatus(hDevice, 6) != CFG_TRANSFER_SUCCESS) emit sendMessage("Could not clear the tick enable register"); else emit sendMessage("Cleared the tick enable register"); // (3) get the tick status CFGSpaceWire_GetTickEnableStatus(hDevice, &dwTickEnableStatus); emit sendMessage("OK *** in Open *** CFGSpaceWire_GetTickEnableStatus, code is " + QString::number(dwTickEnableStatus, 2)); // (4) enable external timecode selection if(!USBSpaceWire_TC_EnableExternalTimecodeSelection(hDevice,0)) emit sendMessage("ERR *** disable external timecode selection"); rtr_clk_freq = USBSpaceWire_TC_GetClockFrequency(hDevice); emit sendMessage("clock frequency = " + QString::number(rtr_clk_freq) ); if (!USBSpaceWire_TC_SetAutoTickInFrequency(hDevice, rtr_clk_freq) ) emit sendMessage("Could not set the tick-in frequency"); starDundeeSendOneTimecode->setEnabled( true ); starDundeeSendTimecodePeriodically->setEnabled( true ); starDundeeSendOneTimePacketAndOneTimecode->setEnabled( true ); starDundeeSendOneTimePacketAndTimecodePeriodically->setEnabled( true ); } void StarDundee::sendOneTimecode() { if(!USBSpaceWire_TC_PerformTickIn(hDevice, 0)) emit sendMessage("ERR *** in sendOneTimecode *** perform TickIn"); } void StarDundee::sendOneTimePacketAndOneTimecode() { sendUpdateTime( arbitraryTimeToSend ); QTimer::singleShot(300, this, SLOT(sendOneTimecode())); } void StarDundee::sendOneTimePacketAndTimecodePeriodically() { sendUpdateTime( arbitraryTimeToSend ); starDundeeSendOneTimePacketAndTimecodePeriodically->setEnabled( false ); QTimer::singleShot(300, this, SLOT(sendTimecodePeriodically())); } void StarDundee::sendTimecodePeriodically() { if (flag_sendTimecodePeriodically == false) { if (!USBSpaceWire_TC_EnableAutoTickIn(hDevice, 1, 1)) emit sendMessage("Could not enable auto tick-in"); flag_sendTimecodePeriodically = true; this->starDundeeSendTimecodePeriodically->setText("stop timecodes at 1 Hz"); starDundeeSendOneTimePacketAndTimecodePeriodically->setEnabled( false ); } else { if (!USBSpaceWire_TC_EnableAutoTickIn(hDevice, 0, 0)) emit sendMessage("Could not disable auto tick-in"); flag_sendTimecodePeriodically = false; this->starDundeeSendTimecodePeriodically->setText("start timecodes at 1 Hz"); starDundeeSendOneTimePacketAndTimecodePeriodically->setEnabled( true ); } } void StarDundee::startSendingTimecodePeriodically(unsigned char onOff) { if (onOff == 0) { if (!USBSpaceWire_TC_EnableAutoTickIn(hDevice, 0, 0)) emit sendMessage("Could not disable auto tick-in"); flag_sendTimecodePeriodically = false; this->starDundeeSendTimecodePeriodically->setText("start timecodes at 1 Hz"); starDundeeSendOneTimePacketAndTimecodePeriodically->setEnabled( true ); } else { if (!USBSpaceWire_TC_EnableAutoTickIn(hDevice, 1, 1)) emit sendMessage("Could not enable auto tick-in"); flag_sendTimecodePeriodically = true; this->starDundeeSendTimecodePeriodically->setText("stop timecodes at 1 Hz"); starDundeeSendOneTimePacketAndTimecodePeriodically->setEnabled( false ); } } void StarDundee::sendUpdateTime(long time) { Packet_TC_LFR_UPDATE_TIME_t packet; unsigned char crcAsTwoBytes[2]; packet.packetID[0] = (unsigned char) (TC_LFR_PACKET_ID >> 8); packet.packetID[1] = (unsigned char) (TC_LFR_PACKET_ID ); packet.packetSequenceControl[0] = (unsigned char) (TC_LFR_PACKET_SEQUENCE_CONTROL >> 8); packet.packetSequenceControl[1] = (unsigned char) (TC_LFR_PACKET_SEQUENCE_CONTROL ); packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_TC_LFR_UPDATE_TIME >> 8); packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_TC_LFR_UPDATE_TIME ); packet.ccsdsSecHeaderFlag_pusVersion_ack = 0x19; packet.serviceType = TC_TYPE_LFR_UPDATE_TIME; packet.serviceSubType = TC_SUBTYPE_UPDATE_TIME; packet.sourceID = SID_TC_RPW_INTERNAL; packet.cp_rpw_time[0] = (unsigned char) (time >> 24); packet.cp_rpw_time[1] = (unsigned char) (time >> 16); packet.cp_rpw_time[2] = (unsigned char) (time >> 8); packet.cp_rpw_time[3] = (unsigned char) (time); packet.cp_rpw_time[4] = 0; // fine time MSB packet.cp_rpw_time[5] = 0; // fine time LSB paulCommonCRC->GetCRCAsTwoBytes((unsigned char*) &packet, crcAsTwoBytes, PACKET_LENGTH_TC_LFR_UPDATE_TIME + CCSDS_TC_TM_PACKET_OFFSET - 2); packet.crc[0] = crcAsTwoBytes[0]; packet.crc[1] = crcAsTwoBytes[1]; WriteSPW((char*) &packet, PACKET_LENGTH_TC_LFR_UPDATE_TIME + CCSDS_TC_TM_PACKET_OFFSET, CCSDS_NODE_ADDRESS, CCSDS_USER_APP); } void StarDundee::updateTimeToSend(long timeToSend) { arbitraryTimeToSend = timeToSend; }