##// END OF EJS Templates
Plugin modified to allow the launch of interactiv tests from the python interpreter...
Plugin modified to allow the launch of interactiv tests from the python interpreter the signal processPacketStoreNowSig is sent by the SLOT processPacketStoreLater(unsigned int delay) the SLOT WriteSPWDelay(QList<int> dataList, unsigned int delay) allows the storage of a TC for a sending after "delay" ms

File last commit:

r11:0c9852fa341b default
r11:0c9852fa341b default
Show More
stardundee.cpp
855 lines | 35.0 KiB | text/x-c | CppLexer
#include "stardundee.h"
#include <QTime>
#include <math.h>
#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 link not running"));
//*** QPUSHBUTTON ***//
starDundeeStatusQueryRetryButton = new QPushButton(tr("Retry"));
starDundeeStatusQueryAbortButton = new QPushButton(tr("Abort"));
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(starDundeeStatusQueryRetryButton, 1, 0, 0);
starDundeeStatusQueryDialogLayout->addWidget(starDundeeStatusQueryAbortButton, 1, 1, 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->setRowStretch(2, 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(this->timer, SIGNAL(timeout()), this, SLOT(receivePollingLoop()));
timer->start(100); // starts the periodical timer, period = 100ms
}
StarDundee::~StarDundee()
{
free(rmapPacket);
free(ccsdsPacket);
free(spwPacket);
USBSpaceWire_Close(hDevice); // Close the device
}
void StarDundee::Open()
{
int status;
U32 statusControl;
if (!USBSpaceWire_Open(&hDevice, usbDeviceNumber_SPINBOX->value())) // Open the USB device
{
emit sendMessage("stardundee *** Open *** ERROR: USBSpaceWire_Open(&hDevice, 0))");
return;
}
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
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");
// read the link status
if (CFGSpaceWire_GetLinkStatusControl(hDevice, linkNumber_SPINBOX->value(), &statusControl) != CFG_TRANSFER_SUCCESS)
{
emit sendMessage("Could not read link status control for link " + QString::number(linkNumber_SPINBOX->value()));
}
else
{
emit sendMessage("OK CFGSpaceWire_GetLinkStatusControl of link " + QString::number(linkNumber_SPINBOX->value()));
// 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_SPINBOX->value(), statusControl) != CFG_TRANSFER_SUCCESS)
{
emit sendMessage("Could not set the link status control for link " + QString::number(linkNumber_SPINBOX->value()));
}
else emit sendMessage("Set the link status control for link " + QString::number(linkNumber_SPINBOX->value()));
}
if (CFGSpaceWire_SetAsInterface(hDevice, 1, 0) != CFG_TRANSFER_SUCCESS)
{
emit sendMessage("Could not set the device to be an interface");
}
else
{
emit sendMessage("Device set to be an interface");
}
//setRoutingTableEntry(rmapTargetLogicalAddress, (1<<linkNumber_SPINBOX->value()));
//setRoutingTableEntry(rmapSourceLogicalAddress, (1<<3));
//GetRoutingTableEntry(rmapTargetLogicalAddress);
//GetRoutingTableEntry(rmapSourceLogicalAddress);
USBSpaceWire_RegisterReceiveOnAllPorts(hDevice); // Register to receive on all ports
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();
if (getLinkStatus(linkNumber_SPINBOX->value()))
{
emit isOpen(true);
}
else
{
starDundeeStatusQueryDialog->exec();
}
}
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));
while (remainingCount > READ_WRITE_MAX_COUNTS)
{
for (int i = 0; i<READ_WRITE_MAX_COUNTS; i++)
{
data[i*4+3] = (char) ((unsigned int) Value[i+iOffset]);
data[i*4+2] = (char) ((unsigned int) Value[i+iOffset]>>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<remainingCount; i++)
{
data[i*4+3] = (char) ((unsigned int) Value[i+iOffset]);
data[i*4+2] = (char) ((unsigned int) Value[i+iOffset]>>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;
}
}
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));
while (remainingCount > READ_WRITE_MAX_COUNTS)
{
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;i<READ_WRITE_MAX_COUNTS;i++)
{
Value[i+iOffset] = (unsigned char) rmapPacket[i*4+RMAP_READ_REPLY_HEADER_LENGTH];
for(int j=1;j<4;j++)
{
Value[i+iOffset]= ((unsigned char) (rmapPacket[i*4+j+RMAP_READ_REPLY_HEADER_LENGTH]))
+ Value[i+iOffset]*256;
}
}
remainingCount = remainingCount - READ_WRITE_MAX_COUNTS;
address = address + READ_WRITE_MAX_COUNTS * 4;
iOffset = iOffset + READ_WRITE_MAX_COUNTS;
this->acquireRMAPSemaphore();
}
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;i<remainingCount;i++)
{
Value[i+iOffset] = (unsigned char) rmapPacket[i*4+RMAP_READ_REPLY_HEADER_LENGTH];
for(int j=1;j<4;j++)
{
Value[i+iOffset]= ((unsigned char)(rmapPacket[i*4+j+RMAP_READ_REPLY_HEADER_LENGTH])) + Value[i+iOffset]*256;
}
}
this->acquireRMAPSemaphore();
}
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] = this->linkNumber_SPINBOX->value();
for(unsigned int i = 0; i<headerSize; i++) packet[i+PATH_ADDRESSING_OFFSET] = aux[i];
offset = headerSize;
for(unsigned int i = 0; i<nbBytes; i++)
{
packet[i+offset+PATH_ADDRESSING_OFFSET] = data[i];
}
packet[nbBytes+offset+PATH_ADDRESSING_OFFSET] = RMAPCommand->dataCRC;
//****************
// 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] = this->linkNumber_SPINBOX->value();
for (unsigned int i = 0; i<sizeof(RMAPCommand->RMAPHeader); 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] = this->linkNumber_SPINBOX->value(); // 1 by default, value can be 1 or 2
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; i<count; i++)
{
SPWData[i+4+PATH_ADDRESSING_OFFSET] = Value[i];
}
//****************
// SEND THE PACKET
result = USBSpaceWire_SendPacket(hDevice,
SPWData,
totalSize,
BWAIT_1, &pIdentifier);
if (result != TRANSFER_SUCCESS)
{
emit sendMessage("ERROR *** WriteSPW when sending packet of size "
+ QString::number(totalSize) +", with code: " + QString::number(result));
USBSpaceWire_FreeSend(hDevice, pIdentifier);
free(SPWData);
return 0;
}
else emit sendMessage("OK *** WriteSPW when sending packet of size " + QString::number(totalSize-1));
emit appendToLog("packet sent, B0 = " + QString::number(SPWData[0])
+ " *** B1 = " + QString::number(SPWData[1])
+ " *** B2 = " + QString::number(SPWData[2])
+ " *** B3 = " + QString::number(SPWData[3])
+ " *** B4 = " + QString::number(SPWData[4])
+ " *** B5 = " + QString::number(SPWData[5])
+ " *** B6 = " + QString::number(SPWData[6])
+ " *** B7 = " + QString::number(SPWData[7])
+ " *** B8 = " + QString::number(SPWData[8])
+ " *** B9 = " + QString::number(SPWData[9])
+ " *** B10 = " + QString::number(SPWData[10])
+ " *** B11 = " + QString::number(SPWData[11])
+ " *** B12 = " + QString::number(SPWData[12])
);
//**************
// Free the send
USBSpaceWire_FreeSend(hDevice, pIdentifier);
free(SPWData);
emit appendToLog(QString("*** CCSDS packet sent"));
return 1;
}
unsigned int StarDundee::getLinkStatus(unsigned char link)
{
U32 statusControl, errorStatus, portType;
U32 linkStatus, operatingSpeed, outputPortConnection;
char isLinkRunning, isAutoStart, isStart, isDisabled, isTristate;
// Read the link status control register
if (CFGSpaceWire_GetLinkStatusControl(hDevice, 1, &statusControl) != CFG_TRANSFER_SUCCESS)
{
emit appendToLog("Could not read link status control for link" + QString::number(link));
}
else
{
// Display the link status control register properties
CFGSpaceWire_LSPortType(statusControl, &portType);
if (portType == CFG_CONFIGURATION_PORT)
{
CFGSpaceWire_LSConfigErrorStatus(statusControl, &errorStatus);
//emit appendToLog("Configuration port error status = " + QString::number(errorStatus));
}
else if (portType == CFG_SPACEWIRE_EXTERNAL_PORT)
{
CFGSpaceWire_LSExternalErrorStatus(statusControl, &errorStatus);
//emit appendToLog("External port error status = " + QString::number(errorStatus));
}
else
{
CFGSpaceWire_LSErrorStatus(statusControl, &errorStatus);
//emit appendToLog("SpaceWire link error status = " + QString::number(errorStatus));
}
CFGSpaceWire_LSLinkState(statusControl, &linkStatus);
CFGSpaceWire_LSIsLinkRunning(statusControl, &isLinkRunning);
CFGSpaceWire_LSIsAutoStart(statusControl, &isAutoStart);
CFGSpaceWire_LSIsStart(statusControl, &isStart);
CFGSpaceWire_LSIsDisabled(statusControl, &isDisabled);
CFGSpaceWire_LSIsTristate(statusControl, &isTristate);
CFGSpaceWire_LSOperatingSpeed(statusControl, &operatingSpeed);
CFGSpaceWire_LSOutputPortConnection(statusControl, &outputPortConnection);
//emit appendToLog("The link state is = " + QString::number(linkStatus));
//emit appendToLog("The link is running = " + QString::number(isLinkRunning));
//emit appendToLog("The autostart bit is enabled = " + QString::number(isAutoStart));
//emit appendToLog("The start bit is enabled = " + QString::number(isStart));
//emit appendToLog("The link is disabled = " + QString::number(isDisabled));
//emit appendToLog("The tri-state bit is enabled = " + QString::number(isAutoStart));
//emit appendToLog("The operating speed is = " + QString::number(operatingSpeed));
//emit appendToLog("This port is currently connected to output port = " + QString::number(outputPortConnection));
}
if (linkStatus == 5) return 1;
else return 0;
}
void StarDundee::receivePollingLoop()
{
timer->blockSignals(true);
if (USBSpaceWire_WaitOnReadPacketAvailable(hDevice, 0)) receiveSPWPacketLoop(0);
timer->blockSignals(false);
}
int StarDundee::receiveSPWPacketLoop(unsigned char requestID)
{
int result = 0;
emit appendToLog("Number of packets dropped by the driver: " +
QString::number(USBSpaceWire_GetDriverDroppedPackets(hDevice)));
while (USBSpaceWire_WaitOnReadPacketAvailable(hDevice, 0))
{
//sendMessage("trying to get a packet");
result = receiveSPWPacket(requestID);
}
if (!ccsdsPacketStore.isEmpty())
{
emit packetStoreNotEmpty();
}
return result;
}
int StarDundee::receiveSPWPacket(unsigned char requestID) // SLOT
{
unsigned int packetLength;
unsigned int nbBytes;
unsigned nPacketNum;
USB_SPACEWIRE_PACKET_PROPERTIES properties; // The properties of the read
if (requestID==1)
{
if (rmapPacketSEMAPHORE->available())
{
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");
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; i<packetLength; i++) rmapPacket[i] = spwPacket[i];
rmapPacketSize = packetLength;
rmapPacketSEMAPHORE->release();
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; i<packetLength; i++) ccsdsPacket[i] = spwPacket[i];
ccsdsPacketSize = packetLength;
//ccsdsPacketSEMAPHORE->release();
//emit(ccsdsPacketAvailable(ccsdsPacket, packetLength));
emit appendToLog("CCSDS packet of size " + QString::number(packetLength) + " received");
emit appendToLog("packet received, byte0 " + QString::number(spwPacket[0], 16)
+ " *** byte1 " + QString::number(spwPacket[1], 16)
+ " *** byte2 " + QString::number(spwPacket[2], 16)
+ " *** byte3 " + QString::number(spwPacket[3], 16));
storeCCSDSPacket(ccsdsPacket, packetLength);
return packetLength;
default:
emit appendToLog("packet received, byte0 " + QString::number(spwPacket[0], 16)
+ " *** byte1 " + QString::number(spwPacket[1], 16)
+ " *** byte2 " + QString::number(spwPacket[2], 16)
+ " *** byte3 " + QString::number(spwPacket[3], 16));
}
return 0;
}
unsigned int StarDundee::storeCCSDSPacket(unsigned char *ccsdsPacket, unsigned int size)
{
unsigned int i;
ccsdsPacketToProcess_t ccsdsPacketToStore;
ccsdsPacketToStore.size = size;
for(i=0; i<size; i++)
{
ccsdsPacketToStore.data[i] = ccsdsPacket[i];
}
ccsdsPacketStore << ccsdsPacketToStore;
//emit(ccsdsPacketAvailable(ccsdsPacket, packetLength));
//emit ccsdsPacketIsAvailable(size);
return 1;
}
void StarDundee::reTestSPWLink() // SLOT
{
if (getLinkStatus(linkNumber_SPINBOX->value()))
{
emit isOpen(true);
starDundeeStatusQueryDialog->accept();
}
}