##// END OF EJS Templates
Initial commit
Initial commit

File last commit:

r1:45ff379330d3 default
r2:14442728add6 default
Show More
stardundee.cpp
529 lines | 23.0 KiB | text/x-c | CppLexer
#include "stardundee.h"
#include <QTime>
#include <math.h>
StarDundee::StarDundee(QWidget *parent) :
QWidget(parent)
{
commandCode = invalid0; // initialization of the cmmand code for the RMAP transfers
rmapPacket = (unsigned char*) malloc(RMAP_MAX_PACKET_LENGTH);
rmapTargetLogicalAddress = 0xfe;
rmapSourceLogicalAddress = 0x20;
connection_LAYOUT = new QGridLayout;
sendPacket_BUTTON = new QPushButton(tr("Send a packet"));
sendRMAPPacket_BUTTON = new QPushButton(tr("Write RMAP packet to the specified target"));
readRMAPPacket_BUTTON = new QPushButton(tr("Read RMAP packet from the specified target"));
getRoutingTableEntry_BUTTON = new QPushButton(tr("Get routing table entry (target logical address)"));
usbDeviceNumber_LABEL = new QLabel(tr("USB device number: "));
linkNumber_LABEL = new QLabel(tr("SpaceWire link number: "));
routingTableEntry_LABEL = new QLabel(tr("Target logical address: "));
sourceLogicalAddress_LABEL = new QLabel(tr("Source logical address: "));
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);
routingTableEntry_SPINBOX = new QSpinBox;
routingTableEntry_SPINBOX->setRange(0, 254);
routingTableEntry_SPINBOX->setValue(254);
sourceLogicalAddress_SPINBOX = new QSpinBox;
sourceLogicalAddress_SPINBOX->setRange(0,254);
sourceLogicalAddress_SPINBOX->setValue(32);
sendPacket_BUTTON->setEnabled(false);
sendRMAPPacket_BUTTON->setEnabled(false);
readRMAPPacket_BUTTON->setEnabled(false);
getRoutingTableEntry_BUTTON->setEnabled(false);
connection_LAYOUT->addWidget(usbDeviceNumber_LABEL, 0, 0, 1, 1);
connection_LAYOUT->addWidget(usbDeviceNumber_SPINBOX, 0, 1, 1, 1);
connection_LAYOUT->addWidget(sendPacket_BUTTON, 1, 0, 1, 2);
connection_LAYOUT->addWidget(linkNumber_LABEL, 2, 0, 1, 1);
connection_LAYOUT->addWidget(linkNumber_SPINBOX, 2, 1, 1, 1);
connection_LAYOUT->addWidget(sourceLogicalAddress_LABEL, 3, 0, 1, 1);
connection_LAYOUT->addWidget(sourceLogicalAddress_SPINBOX, 3, 1, 1, 1);
connection_LAYOUT->addWidget(routingTableEntry_LABEL, 4, 0, 1, 1);
connection_LAYOUT->addWidget(routingTableEntry_SPINBOX, 4, 1, 1, 1);
connection_LAYOUT->addWidget(sendRMAPPacket_BUTTON, 5, 0, 1, 2);
connection_LAYOUT->addWidget(readRMAPPacket_BUTTON, 6, 0, 1, 2);
connection_LAYOUT->addWidget(getRoutingTableEntry_BUTTON, 7, 0, 1, 2);
connection_LAYOUT->setRowStretch(8, 1);
connection_LAYOUT->setColumnStretch(2, 1);
this->setLayout(connection_LAYOUT);
connect(this->sendPacket_BUTTON, SIGNAL(clicked()), this, SLOT(SendPacket()));
connect(this->readRMAPPacket_BUTTON, SIGNAL(clicked()),this, SLOT(ReadRMAP()));
connect(this->sendRMAPPacket_BUTTON, SIGNAL(clicked()), this, SLOT(SendRMAP()));
connect(this->getRoutingTableEntry_BUTTON, SIGNAL(clicked()), this, SLOT(GetRoutingTableEntry()));
}
StarDundee::~StarDundee()
{
USBSpaceWire_Close(hDevice); // Close the device
}
unsigned int StarDundee::OpenStarDundee()
{
int status;
U32 statusControl;
U32 routingTableEntry;
int tableEntry;
if (!USBSpaceWire_Open(&hDevice, usbDeviceNumber_SPINBOX->value())) // Open the USB device
{
emit sendMessage("stardundee *** Open *** ERROR: USBSpaceWire_Open(&hDevice, 0))");
return -1;
}
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
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()));
}
// SET THE ROUTING TABLE ENTRY FOR LOGICAL ADDRESSING, TARGET 254 <=> 0xfe
tableEntry = routingTableEntry_SPINBOX->value();
if (CFGSpaceWire_ClearRoutingTableEntry(hDevice, tableEntry) != CFG_TRANSFER_SUCCESS)
{
emit sendMessage("Could not clear routing table entry " + QString::number(tableEntry));
}
else emit sendMessage("Routing table entry [" + QString::number(tableEntry) + "] cleared");
// Build the routing table entry to route out of port 1 with header deletion disabled and priority normal
CFGSpaceWire_RTBuildRoutingTableEntry(&routingTableEntry,
(1<<linkNumber_SPINBOX->value()), // 0x02 = 0000 0010
0,
0);
// 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" );
// SET THE ROUTING TABLE ENTRY FOR LOGICAL ADDRESSING, TARGET 32 <=> 0x20
tableEntry = sourceLogicalAddress_SPINBOX->value();
if (CFGSpaceWire_ClearRoutingTableEntry(hDevice, tableEntry) != CFG_TRANSFER_SUCCESS)
{
emit sendMessage("Could not clear routing table entry " + QString::number(tableEntry));
}
else emit sendMessage("Routing table entry [" + QString::number(tableEntry) + "] cleared");
// Build the routing table entry to route out of port 3 with header deletion disabled and priority normal
CFGSpaceWire_RTBuildRoutingTableEntry(&routingTableEntry,
(1<<3), // 0x02 = 0000 0010
0,
0);
// 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" );
emit sendMessage("The driver's current send buffer size is " + QString::number(USBSpaceWire_GetDriverSendBufferSize(hDevice)) + " bytes");
sendPacket_BUTTON->setEnabled(true);
sendRMAPPacket_BUTTON->setEnabled(true);
readRMAPPacket_BUTTON->setEnabled(true);
getRoutingTableEntry_BUTTON->setEnabled(true);
USBSpaceWire_RegisterReceiveOnAllPorts(hDevice); // Register to receive on all ports
emit starDundeeIsOpen(true);
emit sendMessage("command code: " + QString::number(commandCode,16) );
return 1;
}
unsigned int StarDundee::CloseStarDundee()
{
USBSpaceWire_Close(hDevice); // Close the device
emit sendMessage("stardundee *** Close *** USBSpaceWire_Close, device: " + QString::number(usbDeviceNumber_SPINBOX->value()));
sendPacket_BUTTON->setEnabled(false);
sendRMAPPacket_BUTTON->setEnabled(false);
readRMAPPacket_BUTTON->setEnabled(false);
getRoutingTableEntry_BUTTON->setEnabled(false);
USBSpaceWire_UnregisterReceiveOnAllPorts(hDevice); // Stop receiving on all ports
emit starDundeeIsOpen(false);
return 1;
}
unsigned int StarDundee::GetRoutingTableEntry()
{
U32 routingTableEntry, outputPorts;
char enabled, delHead, priority;
int portNum;
int tableEntry;
tableEntry = routingTableEntry_SPINBOX->value();
// Set the path and return path to the device
CFGSpaceWire_StackClear();
CFGSpaceWire_AddrStackPush(0);
CFGSpaceWire_AddrStackPush(254);
CFGSpaceWire_RetAddrStackPush(254);
// 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::SendPacket()
{
U32 nBufferSize; // The amount of data, in bytes, to be transmitted.
char bWait; // If bWait is 0 then the transfer is started and the function returns immediately.
// If bWait is not 0 then the function will return only when the transfer is completed or an error is detected.
nBufferSize = 10;
bWait = 1;
// Send the packet and wait on it completing
result = USBSpaceWire_SendPacket(hDevice, pBuffer, nBufferSize, bWait, &pIdentifier);
if (result != TRANSFER_SUCCESS)
{
emit sendMessage("Error: Could not send the packet");
}
else emit sendMessage("The packet has been successfully sent");
// Free the send
USBSpaceWire_FreeSend(hDevice, pIdentifier);
return 1;
}
unsigned int StarDundee::SendRMAP()
{
unsigned int Value[4];
unsigned int count = 4;
unsigned int address = 0x40000000;
Value[0] = 0xabcd1234;
Value[1] = 0xbb;
Value[2] = 0xab;
Value[3] = 0xcd;
WriteStarDundee(Value, count, address);
return 1;
}
unsigned int StarDundee::ReadRMAP()
{
unsigned int Value[100000];
unsigned int count = 100000;
unsigned int address = 0x40000000;
unsigned int result;
result = ReadStarDundee(Value, count, address);
emit sendMessage("ReadRMAP, nbBytes: " + QString::number(result));
emit sendMessage("Value[0]: " + QString::number(Value[0], 16));
emit sendMessage("Value[1]: " + QString::number(Value[1], 16));
emit sendMessage("Value[2]: " + QString::number(Value[2], 16));
emit sendMessage("Value[3]: " + QString::number(Value[3], 16));
return 1;
}
unsigned int StarDundee::ReadStarDundee(unsigned int *Value, unsigned int count, unsigned int address)
{
RMAP *RMAPCommand;
rmap_read_reply_PcktHdr_t rmapReplyHeader;
USB_SPACEWIRE_STATUS result; // The result of the receive operation
USB_SPACEWIRE_PACKET_PROPERTIES properties; // The properties of the read
unsigned int nbBytes;
unsigned char* packet;
U32 nPacketNum;
unsigned int offset;
unsigned int i;
//**********************
// SEND THE READ COMMAND
nbBytes = 4 * count;
if (nbBytes > 4)
{
RMAPCommand = new RMAP(read_Inc, // build the command
rmapTargetLogicalAddress,
rmapSourceLogicalAddress,
address,
nbBytes,
NULL);
}
else
{
RMAPCommand = new RMAP(read_Single, // build the command
rmapTargetLogicalAddress,
rmapSourceLogicalAddress,
address,
nbBytes,
NULL);
}
result = USBSpaceWire_SendPacket(hDevice,
(unsigned char*) ((void*) &RMAPCommand->RMAPHeader),
sizeof(RMAPCommand->RMAPHeader),
BWAIT_1, &pIdentifier);
if (result != TRANSFER_SUCCESS) emit sendMessage("ERROR *** ReadStarDundee when sending the READ command ");
else emit sendMessage("OK *** ReadStarDundee when sending the READ command");
//*****************
// RECEIVE THE DATA
nbBytes = sizeof(rmapReplyHeader) + 4 * count + 1; // 1 is for the data CRC
packet = (unsigned char *) malloc(nbBytes);
nPacketNum = 1;
result = USBSpaceWire_ReadPackets(hDevice, packet, nbBytes, nPacketNum, BWAIT_1, &properties, &pIdentifier);
if (result != TRANSFER_SUCCESS) emit sendMessage("Error: Could not receive the packet");
else
{
emit sendMessage("A packet of length " + QString::number(properties.len) + " has been successfully received");
offset = sizeof(rmapReplyHeader);
for(i=0; i<count; i++)
{
Value[i] = packet[offset+3];
Value[i] = Value[i] + packet[offset+2] * pow(2, 8);
Value[i] = Value[i] + packet[offset+1] * pow(2, 16);
Value[i] = Value[i] + packet[offset+0] * pow(2, 24);
offset = offset + 4;
}
free(packet);
USBSpaceWire_FreeRead(hDevice, pIdentifier); // Free the receive
return count;
}
return 1;
}
unsigned int StarDundee::WriteStarDundee(unsigned int *Value, unsigned int count, unsigned int address)
{
RMAP *RMAPCommand;
unsigned char *data;
char *dataCHAR;
unsigned char *aux;
unsigned int offset;
U32 dataSize, headerSize, CRCSize, totalSize; // sizes in bytes
U32 nPacketNum;
USB_SPACEWIRE_PACKET_PROPERTIES properties; // The properties of the read
rmap_write_reply_t rmapReplyHeader;
dataSize = count * 4;
dataCHAR = (char *) malloc(dataSize);
for (unsigned int i = 0; i<count; i++)
{
dataCHAR[i*4+3] = (char) ((unsigned int) Value[i]);
dataCHAR[i*4+2] = (char) ((unsigned int) Value[i]>>8);
dataCHAR[i*4+1] = (char) ((unsigned int) Value[i]>>16);
dataCHAR[i*4+0] = (char) ((unsigned int) Value[i]>>24);
}
RMAPCommand = new RMAP(commandCode,
rmapTargetLogicalAddress,
rmapSourceLogicalAddress,
address,
dataSize,
dataCHAR);
free(dataCHAR);
headerSize = sizeof(RMAPCommand->RMAPHeader);
CRCSize = 1;
//*************************
// BUILD THE PACKET TO SEND
totalSize = headerSize + dataSize + CRCSize;
data = (unsigned char*) malloc( totalSize );
aux = (unsigned char*) ((void*) &RMAPCommand->RMAPHeader);
for(unsigned int i = 0; i<headerSize; i++) data[i] = aux[i];
offset = headerSize;
for(unsigned int i = 0; i<count; i++)
{
data[offset+3] = (unsigned char) (Value[i]);
data[offset+2] = (unsigned char) (Value[i]>>8);
data[offset+1] = (unsigned char) (Value[i]>>16);
data[offset] = (unsigned char) (Value[i]>>24);
offset = offset + 4;
}
data[offset] = RMAPCommand->dataCRC;
//************
// SEND THE PACKET
result = USBSpaceWire_SendPacket(hDevice,
data,
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(data);
if ( (commandCode == writeSingle_noVer_Rep) | (commandCode == writeInc_noVer_Rep) |
(commandCode == writeSingle_ver_rep) | (commandCode == writeInc_ver_rep) )
{
//***********************
// RECEIVE THE RMAP REPLY
totalSize = sizeof(rmapReplyHeader);
nPacketNum = 1;
result = USBSpaceWire_ReadPackets(hDevice, (char *) &rmapReplyHeader, totalSize, nPacketNum, BWAIT_1, &properties, &pIdentifier);
if (result != TRANSFER_SUCCESS)
{
emit sendMessage("Error: Could not receive the RMAP reply");
USBSpaceWire_FreeRead(hDevice, pIdentifier); // Free the receive
return 1;
}
else
{
emit sendMessage("An RMAP reply of length " + QString::number(properties.len) + " has been successfully received");
USBSpaceWire_FreeRead(hDevice, pIdentifier); // Free the receive
}
if(properties.len != 8)
{
emit appendToLog("WARNING === in function WRITE (with reply) of rmapplugin *** write reply format not compliant\n");
return 1;
}
emit sendMessage("data CRC " + QString::number(RMAPCommand->dataCRC, 16) );
emit sendMessage("rmapReplyHeader " + QString::number(rmapReplyHeader.initiatorLogicalAddress, 16) );
emit sendMessage("rmapReplyHeader " + QString::number(rmapReplyHeader.protocolIdentifier, 16) );
emit sendMessage("rmapReplyHeader " + QString::number(rmapReplyHeader.instruction, 16) );
emit sendMessage("rmapReplyHeader " + QString::number(rmapReplyHeader.status, 16) );
emit sendMessage("rmapReplyHeader " + QString::number(rmapReplyHeader.targetLogicalAddress, 16) );
emit sendMessage("rmapReplyHeader " + QString::number(rmapReplyHeader.transactionIdentifier1, 16) );
emit sendMessage("rmapReplyHeader " + QString::number(rmapReplyHeader.transactionIdentifier2, 16) );
emit sendMessage("rmapReplyHeader " + QString::number(rmapReplyHeader.headerCRC, 16) );
switch (rmapReplyHeader.status) // 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;
}
}
else
emit RMAP_write_reply_setText("reply to the write command required\nlast reply status: unavailable");
return count;
}
//******
// SLOTS
void StarDundee::updateCommandCode(RMAP_command_codes code)
{
this->commandCode = code;
}