rmapplugin.cpp
923 lines
| 36.2 KiB
| text/x-c
|
CppLexer
/ rmapplugin / rmapplugin.cpp
r0 | /*------------------------------------------------------------------------------ | |||
-- This file is a part of the LPPMON Software | ||||
-- Copyright (C) 2012, Laboratory of Plasma Physics - CNRS | ||||
-- | ||||
-- This program is free software; you can redistribute it and/or modify | ||||
-- it under the terms of the GNU General Public License as published by | ||||
-- the Free Software Foundation; either version 3 of the License, or | ||||
-- (at your option) any later version. | ||||
-- | ||||
-- This program is distributed in the hope that it will be useful, | ||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
-- GNU General Public License for more details. | ||||
-- | ||||
-- You should have received a copy of the GNU General Public License | ||||
-- along with this program; if not, write to the Free Software | ||||
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
-------------------------------------------------------------------------------*/ | ||||
/*-- Author : Paul LEROY | ||||
-- Mail : paul.leroy@lpp.polytechnique.fr | ||||
----------------------------------------------------------------------------*/ | ||||
#include "rmapplugin.h" | ||||
#include <QHostAddress> | ||||
#include <QIODevice> | ||||
#include <QApplication> | ||||
#include <rmappluginpythonwrapper.h> | ||||
rmapplugin::rmapplugin(QWidget *parent) | ||||
:lppmonplugin(parent,false) | ||||
{ | ||||
this->UI = new rmapPluginUI(); | ||||
this->setWindowTitle(tr("RMAP and SPW Communication")); | ||||
this->setWidget((QWidget*)this->UI); | ||||
RMAPSend_SOCKET = new QTcpSocket; | ||||
RMAPReceive_SOCKET = new QTcpSocket; | ||||
GRESBStatusQuery_SOCKET = new QTcpSocket; | ||||
spwPacketReceiverOBJECT = new spwpacketreceiver; | ||||
spwPacketReceiverOBJECT->gresbReceptionSocket = RMAPReceive_SOCKET; | ||||
timeCode = 0; | ||||
time_COARSE = 0; | ||||
time_FINE = 0; | ||||
|
r1 | currentBridge = selectedBridgeIsUnknown; | ||
r0 | ||||
/*Python wrapper*/ | ||||
this->pyObject = new rmappluginPythonWrapper(); | ||||
connect(this->pyObject,SIGNAL(ReadSig(uint*,uint,uint)),this,SLOT(Read(uint*,uint,uint))); | ||||
connect(this->pyObject,SIGNAL(WriteSig(uint*,uint,uint)),this,SLOT(Write(uint*,uint,uint))); | ||||
/*==============*/ | ||||
|
r1 | connect(UI->rmapOpenCommunicationButton, SIGNAL(clicked()), this, SLOT(openBridge())); | ||
connect(UI->rmapCloseCommunicationButton, SIGNAL(clicked()), this, SLOT(closeBridge())); | ||||
r0 | connect(RMAPSend_SOCKET, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(RMAPSendConnectionState(QAbstractSocket::SocketState))); | |||
connect(RMAPReceive_SOCKET, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(RMAPReceiveConnectionState(QAbstractSocket::SocketState))); | ||||
connect(GRESBStatusQuery_SOCKET, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(GRESBConnectionState(QAbstractSocket::SocketState))); | ||||
connect(UI->gresbStatusQueryRetryButton, SIGNAL(clicked()), this, SLOT(reTestSPWLink())); | ||||
connect(this->UI->spwLinkStatusEnquiry->readSPWStatusButton, SIGNAL(clicked()), this, SLOT(GRESBStatusQuery())); | ||||
connect(this->RMAPReceive_SOCKET, SIGNAL(readyRead()), this->spwPacketReceiverOBJECT, SLOT(receiveSPWPacket())); | ||||
// CCSDS | ||||
connect(this->UI->sendCCSDSCommandButton, SIGNAL(clicked()), this, SLOT(sendCCSDS())); | ||||
connect(this->UI->send_TC_LFR_UPDATE_TIME_Button, SIGNAL(clicked()), this, SLOT(send_TC_LFR_UPDATE_TIME())); | ||||
connect(this->UI->reset_TC_LFR_UPDATE_TIME_Button, SIGNAL(clicked()), this, SLOT(reset_TC_LFR_UPDATE_TIME())); | ||||
// CONSOLE | ||||
connect(this->spwPacketReceiverOBJECT, SIGNAL(sendMessage(QString)), this, SLOT(displayOnConsole(QString))); | ||||
connect(this->UI->starDundee, SIGNAL(sendMessage(QString)), this, SLOT(displayOnConsole(QString))); | ||||
// spectralMAtricesDMASimulator | ||||
connect(this->UI->spectralMatricesDMASimulator, SIGNAL(rmapplugginRead(uint*,uint,uint)), this, SLOT(Read(uint*,uint,uint))); | ||||
connect(this->UI->spectralMatricesDMASimulator, SIGNAL(rmapplugginWrite(uint*,uint,uint)), this, SLOT(Write(uint*,uint,uint))); | ||||
connect(this->UI->spectralMatricesDMASimulator, SIGNAL(sendMessage(QString)), this, SLOT(displayOnConsole(QString))); | ||||
|
r1 | |||
// GRESB | ||||
connect(this, SIGNAL(gresbIsOpen(bool)), this, SLOT(gresbSelection(bool))); | ||||
// Star Dundee | ||||
r3 | connect(this->UI->starDundee, SIGNAL(isOpen(bool)), this, SLOT(activatePluginViaStarDundee(bool))); | |||
|
r1 | connect(this->UI->starDundee, SIGNAL(RMAP_write_reply_setText(QString)), this, SLOT(RMAP_write_reply_setText(QString))); | ||
connect(this->UI->starDundee, SIGNAL(appendToLog(QString)), this, SLOT(appendToLog(QString))); | ||||
connect(this->UI, SIGNAL(bridgeHasChanged(selectedBridge)), this, SLOT(bridgeHasChanged(selectedBridge))); | ||||
r0 | } | |||
rmapplugin::~rmapplugin() | ||||
{ | ||||
if (!RMAPSend_SOCKET->isOpen()) RMAPSend_SOCKET->disconnectFromHost(); | ||||
if (!RMAPReceive_SOCKET->isOpen()) RMAPReceive_SOCKET->disconnectFromHost(); | ||||
if (!GRESBStatusQuery_SOCKET->isOpen()) GRESBStatusQuery_SOCKET->disconnectFromHost(); | ||||
} | ||||
unsigned int rmapplugin::Write(unsigned int *Value, unsigned int count, unsigned int address) | ||||
{ | ||||
|
r1 | unsigned int result; | ||
switch(currentBridge) | ||||
{ | ||||
case selectedBridgeIsGRESB : | ||||
result = WriteGRESB(Value, count, address); | ||||
break; | ||||
case selectedBridgeIsStarDundee : | ||||
r3 | result = UI->starDundee->Write(Value, count, address); | |||
|
r1 | break; | ||
default: | ||||
result = 1; | ||||
break; | ||||
} | ||||
return result; | ||||
} | ||||
unsigned int rmapplugin::Read(unsigned int *Value, unsigned int count, unsigned int address) | ||||
{ | ||||
unsigned int result; | ||||
switch(currentBridge) | ||||
{ | ||||
case selectedBridgeIsGRESB : | ||||
result = ReadGRESB(Value, count, address); | ||||
break; | ||||
case selectedBridgeIsStarDundee : | ||||
r3 | result = UI->starDundee->Read(Value, count, address); | |||
|
r1 | break; | ||
default: | ||||
result = 1; | ||||
break; | ||||
} | ||||
return result; | ||||
} | ||||
unsigned int rmapplugin::WriteGRESB(unsigned int *Value, unsigned int count, unsigned int address) | ||||
{ | ||||
r0 | unsigned int remainingCount = count; | |||
unsigned int iOffset = 0; | ||||
QString console_message; | ||||
char* data; | ||||
if(spwPacketReceiverOBJECT->rmapPacketSEMAPHORE->available()!=0) | ||||
{ | ||||
APPENDTOLOG("WARNING === in function WRITE of rmapplugin *** RMAP request already running, WRITE access stopped"); | ||||
return 1; | ||||
} | ||||
UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: unavailable"); | ||||
data = (char*) malloc(READ_WRITE_MAX_COUNTS*4); | ||||
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); | ||||
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) | ||||
{ | ||||
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); | ||||
APPENDTOLOG(console_message + QString("Write ")+ QString::number(remainingCount*4) + QString(" byte(s) @0x")+ QString::number(address,16)); | ||||
if (WriteBLOCK(data, remainingCount*4, address)==0) | ||||
{ | ||||
APPENDTOLOG("WARNING === in function WRITE of rmapplugin *** RMAP write command failed"); | ||||
return 1; | ||||
} | ||||
} | ||||
APPENDTOLOG(QString("*** STOP *** WRITE")); | ||||
free(data); | ||||
return count; | ||||
} | ||||
|
r1 | unsigned int rmapplugin::ReadGRESB(unsigned int *Value, unsigned int count, unsigned int address) | ||
r0 | { | |||
unsigned int remainingCount = count; | ||||
unsigned int iOffset = 0; | ||||
QString console_message; | ||||
if(spwPacketReceiverOBJECT->rmapPacketSEMAPHORE->available()!=0) | ||||
{ | ||||
APPENDTOLOG("WARNING === in function READ of rmapplugin *** RMAP request already running, READ access stopped"); | ||||
return 1; | ||||
} | ||||
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); | ||||
APPENDTOLOG(console_message + QString("Read ")+ QString::number(4*READ_WRITE_MAX_COUNTS) + QString(" byte(s) @0x")+ QString::number(address,16)); | ||||
if (ReadBLOCK(READ_WRITE_MAX_COUNTS*4, address)==0) | ||||
{ | ||||
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) spwPacketReceiverOBJECT->rmapPacket[i*4+RMAP_READ_REPLY_HEADER_LENGTH]; | ||||
for(int j=1;j<4;j++) | ||||
{ | ||||
Value[i+iOffset]= ((unsigned char)(spwPacketReceiverOBJECT->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; | ||||
spwPacketReceiverOBJECT->acquireRMAPSemaphore(); | ||||
} | ||||
if (remainingCount > 0) | ||||
{ | ||||
console_message.sprintf("remainingCount: %d => ", remainingCount); | ||||
APPENDTOLOG(console_message + QString("Read ")+ QString::number(4*remainingCount) + QString(" byte(s) @0x")+ QString::number(address,16)); | ||||
if (ReadBLOCK(4*remainingCount, address)==0) | ||||
{ | ||||
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) spwPacketReceiverOBJECT->rmapPacket[i*4+RMAP_READ_REPLY_HEADER_LENGTH]; | ||||
for(int j=1;j<4;j++) | ||||
{ | ||||
Value[i+iOffset]= ((unsigned char)(spwPacketReceiverOBJECT->rmapPacket[i*4+j+RMAP_READ_REPLY_HEADER_LENGTH])) + Value[i+iOffset]*256; | ||||
} | ||||
} | ||||
spwPacketReceiverOBJECT->acquireRMAPSemaphore(); | ||||
} | ||||
APPENDTOLOG(QString("*** STOP *** READ ")); | ||||
return count; | ||||
} | ||||
unsigned int rmapplugin::WriteBLOCK(char *data, unsigned int nbBytes, unsigned int address) | ||||
{ | ||||
QTime RMAPTimeout; | ||||
RMAP *RMAPCommand; | ||||
int errorCode; | ||||
QString console_message; | ||||
if (GRESBStatusQueryRequest(LinkStatus, UI->spwLinkSpinBox->value()) == 1) | ||||
{ | ||||
RMAP_DISCONNECT(); | ||||
return 1; | ||||
} | ||||
RMAPCommand = new RMAP(UI->getCommandCode(), | ||||
UI->rmapTargetLogicalAddressSpinBox->value(), | ||||
UI->rmapSourceLogicalAddressSpinBox->value(), | ||||
address, | ||||
nbBytes, | ||||
data); | ||||
// SEND GRESB HEADER | ||||
RMAPSend_SOCKET->write((char*) ((void*) &RMAPCommand->GRESBHeader), 4); | ||||
// SEND SPACEWIRE PACKET HEADER | ||||
RMAPSend_SOCKET->write((char*) ((void*) &RMAPCommand->RMAPHeader), sizeof(RMAPCommand->RMAPHeader)); | ||||
// SEND DATA | ||||
RMAPSend_SOCKET->write( data, nbBytes); | ||||
// SEND DATA CRC | ||||
RMAPSend_SOCKET->write((char*) ((void*) &RMAPCommand->dataCRC), 1); | ||||
RMAPTimeout.start(); | ||||
while(RMAPSend_SOCKET->bytesToWrite() > 0) | ||||
{ | ||||
RMAPSend_SOCKET->waitForBytesWritten(100); | ||||
if(RMAPTimeout.elapsed()>1000) | ||||
{ | ||||
APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** sending Write RMAP Command timeout"); | ||||
return 0; | ||||
} | ||||
} | ||||
if (UI->RMAP_write_reply->isChecked()) | ||||
{ | ||||
// WAIT FOR THE RMAP REPLY PACKET | ||||
errorCode = spwPacketReceiverOBJECT->receiveSPWPacket(1); | ||||
if (errorCode<=0) | ||||
{ | ||||
APPENDTOLOG("WARNING === in function WriteBLOCK of rmapplugin *** RMAP packet reception failed with code " + QString::number(errorCode)); | ||||
return 0; | ||||
} | ||||
if(spwPacketReceiverOBJECT->rmapPacketSize != 8) | ||||
{ | ||||
console_message.sprintf("WARNING === in function WRITE (with reply) of rmapplugin *** write reply format not compliant\n"); | ||||
APPENDTOLOG(console_message); | ||||
return 0; | ||||
} | ||||
switch (spwPacketReceiverOBJECT->rmapPacket[3]) // byte 4 is the status byte in the reply | ||||
{ | ||||
case 0: | ||||
UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 0 Successfull"); | ||||
break; | ||||
case 1: | ||||
APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** General error code"); | ||||
UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 1 General error code"); | ||||
break; | ||||
case 2: | ||||
APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Unused RMAP packet type or command code"); | ||||
UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 2 Unused RMAP packet type or command code"); | ||||
break; | ||||
case 3: | ||||
APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Invalid key"); | ||||
UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 3 Invalid key"); | ||||
break; | ||||
case 4: | ||||
APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Invalid data CRC"); | ||||
UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 4 Invalid data CRC"); | ||||
break; | ||||
case 5: | ||||
APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Early EOP"); | ||||
UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 5 Early EOP"); | ||||
break; | ||||
case 6: | ||||
APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Too much data"); | ||||
UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 6 Too much data"); | ||||
break; | ||||
case 7: | ||||
APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** EEP"); | ||||
UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 7 EEP"); | ||||
break; | ||||
case 8: | ||||
APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Reserved"); | ||||
UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 8 Reserved"); | ||||
break; | ||||
case 9: | ||||
APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Verify buffer overrun"); | ||||
UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 9 Verify buffer overrun"); | ||||
break; | ||||
case 10: | ||||
APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** RMAP command not implemented or not authorised"); | ||||
UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 10 RMAP command not implemented or not authorised"); | ||||
break; | ||||
case 11: | ||||
APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** RMW data length error"); | ||||
UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 11 RMAP RMW data length error"); | ||||
break; | ||||
case 12: | ||||
APPENDTOLOG("WARNING === in function WRITE (with reply) of rmapplugin *** Invalid target logical address"); | ||||
UI->RMAP_write_reply->setText("reply to the write command required\nlast reply status: 12 Invalid target logical address"); | ||||
break; | ||||
} | ||||
spwPacketReceiverOBJECT->acquireRMAPSemaphore(); | ||||
} | ||||
return nbBytes; | ||||
} | ||||
|
r1 | unsigned int rmapplugin::ReadBLOCK(unsigned int nbBytes, unsigned int address) | ||
{ | ||||
int errorCode; | ||||
RMAP *RMAPCommand; | ||||
QTime RMAPTimeout; | ||||
unsigned int dataLength; | ||||
if (GRESBStatusQueryRequest(LinkStatus, UI->spwLinkSpinBox->value()) == 1) | ||||
{ | ||||
RMAP_DISCONNECT(); | ||||
return 1; | ||||
} | ||||
if (nbBytes > 4) | ||||
{ | ||||
RMAPCommand = new RMAP(read_Inc, | ||||
UI->rmapTargetLogicalAddressSpinBox->value(), | ||||
UI->rmapSourceLogicalAddressSpinBox->value(), | ||||
address, | ||||
nbBytes, | ||||
NULL); | ||||
} | ||||
else | ||||
{ | ||||
RMAPCommand = new RMAP(read_Single, | ||||
UI->rmapTargetLogicalAddressSpinBox->value(), | ||||
UI->rmapSourceLogicalAddressSpinBox->value(), | ||||
address, | ||||
nbBytes, | ||||
NULL); | ||||
} | ||||
// SEND THE GRESB HEADER FOR THE RMAP READ COMMAND | ||||
RMAPSend_SOCKET->write((char*) ((void*) &RMAPCommand->GRESBHeader), 4); | ||||
// SEND THE SPACEWIRE PACKET FOR THE RMAP READ COMMAND | ||||
RMAPSend_SOCKET->write((char*) ((void*) &RMAPCommand->RMAPHeader), sizeof(RMAPCommand->RMAPHeader)); | ||||
RMAPSend_SOCKET->waitForBytesWritten(100); | ||||
RMAPTimeout.start(); | ||||
// write timeout | ||||
while(RMAPSend_SOCKET->bytesToWrite() > 0) | ||||
{ | ||||
RMAPSend_SOCKET->waitForBytesWritten(100); | ||||
if(RMAPTimeout.elapsed()>1000) | ||||
{ | ||||
APPENDTOLOG("WARNING === in function READ of rmapplugin *** sending Read RMAP Command timeout\n"); | ||||
return 0; | ||||
} | ||||
} | ||||
// RECEIVE THE INCOMING RMAP PACKET | ||||
errorCode = spwPacketReceiverOBJECT->receiveSPWPacket(1); // request ID 1 is for RMAP packet | ||||
if (errorCode<=0) | ||||
{ | ||||
APPENDTOLOG("WARNING === in function ReadBLOCK of rmapplugin *** RMAP packet reception failed with code " + QString::number(errorCode)); | ||||
return 0; | ||||
} | ||||
dataLength = spwPacketReceiverOBJECT->rmapPacketSize - RMAP_READ_REPLY_HEADER_LENGTH - RMAP_DATA_CRC_LENGTH; | ||||
if(dataLength != nbBytes) | ||||
{ | ||||
APPENDTOLOG("WARNING === in function READ of rmapplugin *** number of data received (" | ||||
+QString::number(dataLength) | ||||
+") not equal to number of data requested (" | ||||
+QString::number(READ_WRITE_MAX_COUNTS*4) | ||||
+")"); | ||||
return 0; | ||||
} | ||||
return dataLength; | ||||
} | ||||
r0 | //////// | |||
// SLOTS | ||||
unsigned int rmapplugin::WriteSPW(char *Value, unsigned int count, char targetLogicalAddress, char userApplication) // SLOT | ||||
{ | ||||
r3 | unsigned int result; | |||
switch(currentBridge) | ||||
{ | ||||
case selectedBridgeIsGRESB : | ||||
result = WriteSPWGRESB(Value, count, targetLogicalAddress, userApplication); | ||||
break; | ||||
case selectedBridgeIsStarDundee : | ||||
result = UI->starDundee->WriteSPW(Value, count, targetLogicalAddress, userApplication); | ||||
break; | ||||
default: | ||||
result = 1; | ||||
break; | ||||
} | ||||
return result; | ||||
} | ||||
unsigned int rmapplugin::WriteSPWGRESB(char *Value, unsigned int count, char targetLogicalAddress, char userApplication) | ||||
{ | ||||
r0 | char protocoleIdentifier = 0x02; | |||
char reserved = 0x00; | ||||
char gresbProtocole = 0x00; | ||||
unsigned char size[3]; | ||||
unsigned int spwPacketSize = count + 4; | ||||
QTime SPWTimeout; | ||||
if (count>248) | ||||
{ | ||||
APPENDTOLOG("WARNING === in function WRITE of rmapplugin *** CCSDS packet size > 248 bytes\n"); | ||||
return 1; | ||||
} | ||||
APPENDTOLOG(QString("*** START *** Send CCSDS packet of ")+ QString::number(count) + QString(" byte(s)")); | ||||
if (GRESBStatusQueryRequest(LinkStatus, UI->spwLinkSpinBox->value()) == 1) | ||||
{ | ||||
RMAP_DISCONNECT(); | ||||
APPENDTOLOG("WARNING === in function WRITE of rmapplugin *** SPW link not running\n"); | ||||
return 1; | ||||
} | ||||
// SEND GRESB HEADER | ||||
size[0] = (unsigned char) ((unsigned int) spwPacketSize>>16); | ||||
size[1] = (unsigned char) ((unsigned int) spwPacketSize>>8); | ||||
size[2] = (unsigned char) ((unsigned int) spwPacketSize); | ||||
RMAPSend_SOCKET->write(&gresbProtocole, 1); | ||||
RMAPSend_SOCKET->write((char*) size, 3); | ||||
// SEND SPW HEADER | ||||
RMAPSend_SOCKET->write(&targetLogicalAddress, 1); | ||||
RMAPSend_SOCKET->write(&protocoleIdentifier, 1); | ||||
RMAPSend_SOCKET->write(&reserved, 1); | ||||
RMAPSend_SOCKET->write(&userApplication, 1); | ||||
// SEND CCSDS PACKET | ||||
RMAPSend_SOCKET->write(Value, count); | ||||
SPWTimeout.start(); | ||||
while(RMAPSend_SOCKET->bytesToWrite() > 0) | ||||
{ | ||||
RMAPSend_SOCKET->waitForBytesWritten(100); | ||||
if(SPWTimeout.elapsed()>1000) | ||||
{ | ||||
APPENDTOLOG("WARNING === in function WRITE of rmapplugin *** sending CCSDS packet timeout\n"); | ||||
return 1; | ||||
} | ||||
} | ||||
APPENDTOLOG(QString("*** CCSDS packet sent")); | ||||
return count; | ||||
} | ||||
void rmapplugin::sendCCSDS() // SLOT | ||||
{ | ||||
unsigned int nbBYTES_application_data = 8; | ||||
unsigned int count; | ||||
char *tab; | ||||
unsigned char packetErrorControl1 = 0xaa; | ||||
unsigned char packetErrorControl0 = 0xbb; | ||||
ccsds_command = new ccsds(1, 0, 0, nbBYTES_application_data+12, 0, 0, 0, 0, 0); // +12 => packet header 6 bytes + data field header 4 bytes + packet error control 2 bytes | ||||
/* unsigned char data_field_header, | ||||
unsigned char processID, | ||||
unsigned int sequence_count, | ||||
unsigned int packet_length, | ||||
unsigned char acceptance, | ||||
unsigned int completion, | ||||
unsigned char service_type, | ||||
unsigned char service_subtype, | ||||
unsigned char sourceID*/ | ||||
count = nbBYTES_application_data+12; // 12 is the size in bytes of the header | ||||
tab = (char*) malloc(count); | ||||
tab[0] = ccsds_command->ccsds_header->packetId1; | ||||
tab[1] = ccsds_command->ccsds_header->packetId0; | ||||
tab[2] = ccsds_command->ccsds_header->packetSequenceControl1; | ||||
tab[3] = ccsds_command->ccsds_header->packetSequenceControl0; | ||||
tab[4] = ccsds_command->ccsds_header->packetLength1; | ||||
tab[5] = ccsds_command->ccsds_header->packetLength0; | ||||
tab[6] = ccsds_command->ccsds_header->dataFieldHeader3; | ||||
tab[7] = ccsds_command->ccsds_header->dataFieldHeader2; | ||||
tab[8] = ccsds_command->ccsds_header->dataFieldHeader1; | ||||
tab[9] = ccsds_command->ccsds_header->dataFieldHeader0; | ||||
tab[10]=0x00; | ||||
tab[11]=0x00; | ||||
tab[12]=0x00; | ||||
tab[13]=0x00; | ||||
tab[14]=0x00; | ||||
tab[15]=0x00; | ||||
tab[nbBYTES_application_data+10] = packetErrorControl1; | ||||
tab[nbBYTES_application_data+11] = packetErrorControl0; | ||||
WriteSPW(tab, count, UI->CCSDSTargetLogicalAddressSpinBox->value(), 0x00); | ||||
free(tab); | ||||
} | ||||
void rmapplugin::send_TC_LFR_UPDATE_TIME() | ||||
{ | ||||
unsigned int nbBYTES_application_data = 6; // Time at CUC format is on 48 bits / 6 bytes | ||||
unsigned int count; | ||||
char *tab; | ||||
unsigned char packetErrorControl1 = 0xaa; | ||||
unsigned char packetErrorControl0 = 0xbb; | ||||
ccsds_command = new ccsds(1, 11, 0, nbBYTES_application_data, 1, 1, 9, 129, 0); | ||||
/* unsigned char data_field_header, | ||||
unsigned char processID, | ||||
unsigned int sequence_count, | ||||
unsigned int packet_length, | ||||
unsigned char acceptance, | ||||
unsigned int completion, | ||||
unsigned char service_type, | ||||
unsigned char service_subtype, | ||||
unsigned char sourceID*/ | ||||
count = nbBYTES_application_data+12; // +12 => packet header 6 bytes + data field header 4 bytes + packet error control 2 bytes | ||||
tab = (char*) malloc(count); | ||||
tab[0] = ccsds_command->ccsds_header->packetId1; | ||||
tab[1] = ccsds_command->ccsds_header->packetId0; | ||||
tab[2] = ccsds_command->ccsds_header->packetSequenceControl1; | ||||
tab[3] = ccsds_command->ccsds_header->packetSequenceControl0; | ||||
tab[4] = ccsds_command->ccsds_header->packetLength1; | ||||
tab[5] = ccsds_command->ccsds_header->packetLength0; | ||||
tab[6] = ccsds_command->ccsds_header->dataFieldHeader3; | ||||
tab[7] = ccsds_command->ccsds_header->dataFieldHeader2; | ||||
tab[8] = ccsds_command->ccsds_header->dataFieldHeader1; | ||||
tab[9] = ccsds_command->ccsds_header->dataFieldHeader0; | ||||
tab[10] = (unsigned char) (time_COARSE>>24); | ||||
tab[11] = (unsigned char) (time_COARSE>>18); | ||||
tab[12] = (unsigned char) (time_COARSE>>8); | ||||
tab[13] = (unsigned char) (time_COARSE); | ||||
tab[14] = (unsigned char) (time_FINE>>8); | ||||
tab[15] = (unsigned char) (time_FINE); | ||||
tab[nbBYTES_application_data+10] = packetErrorControl1; | ||||
tab[nbBYTES_application_data+11] = packetErrorControl0; | ||||
WriteSPW(tab, count, UI->CCSDSTargetLogicalAddressSpinBox->value(), 0x00); | ||||
time_COARSE = time_COARSE+1; | ||||
free(tab); | ||||
} | ||||
void rmapplugin::reset_TC_LFR_UPDATE_TIME() | ||||
{ | ||||
time_COARSE = 0; | ||||
time_FINE = 0; | ||||
} | ||||
|
r1 | void rmapplugin::openBridge() | ||
{ | ||||
switch(currentBridge) | ||||
{ | ||||
case selectedBridgeIsGRESB : | ||||
RMAP_CONNECT(); | ||||
break; | ||||
case selectedBridgeIsStarDundee : | ||||
r3 | this->UI->starDundee->Open(); | |||
|
r1 | break; | ||
default: | ||||
break; | ||||
} | ||||
} | ||||
void rmapplugin::closeBridge() | ||||
{ | ||||
switch(currentBridge) | ||||
{ | ||||
case selectedBridgeIsGRESB : | ||||
RMAP_DISCONNECT(); | ||||
break; | ||||
case selectedBridgeIsStarDundee : | ||||
r3 | this->UI->starDundee->Close(); | |||
|
r1 | break; | ||
default: | ||||
break; | ||||
} | ||||
} | ||||
r0 | void rmapplugin::RMAP_CONNECT() // SLOT | |||
{ | ||||
bool spwRunning = true; | ||||
RMAPSend_SOCKET->connectToHost( QHostAddress(UI->gresbBridgeIPDialogBox->getGRESBIP()), | ||||
3000 + UI->gresbVirtualLinkSpinBox->value()*2, | ||||
QIODevice::WriteOnly); | ||||
RMAPReceive_SOCKET->connectToHost( QHostAddress(UI->gresbBridgeIPDialogBox->getGRESBIP()), | ||||
3000 + UI->gresbVirtualLinkSpinBox->value()*2+1, | ||||
QIODevice::ReadOnly); | ||||
GRESBStatusQuery_SOCKET->connectToHost( QHostAddress(UI->gresbBridgeIPDialogBox->getGRESBIP()), | ||||
3010, | ||||
QIODevice::ReadWrite); | ||||
GRESBStatusQuery_SOCKET->waitForConnected(10000); | ||||
RMAPReceive_SOCKET->readAll(); // read all remaining data from the reception socket | ||||
// initialize SPW packet semaphores | ||||
while (spwPacketReceiverOBJECT->rmapPacketSEMAPHORE->available()!=0) spwPacketReceiverOBJECT->rmapPacketSEMAPHORE->acquire(); | ||||
while (spwPacketReceiverOBJECT->ccsdsPacketSEMAPHORE->available()!=0) spwPacketReceiverOBJECT->ccsdsPacketSEMAPHORE->acquire(); | ||||
if (GRESBStatusQueryRequest(LinkStatus, UI->spwLinkSpinBox->value()) != 0) | ||||
{ | ||||
spwRunning = UI->gresbStatusQueryDialog->exec(); | ||||
} | ||||
if (spwRunning == false) RMAP_DISCONNECT(); | ||||
else | ||||
{ | ||||
APPENDTOLOG(QString("SpaceWire running on virtual link ")+ QString::number(UI->spwLinkSpinBox->value())); | ||||
emit this->activateSig(true); | ||||
|
r1 | emit gresbIsOpen(true); | ||
r0 | } | |||
} | ||||
void rmapplugin::RMAP_DISCONNECT() // SLOT | ||||
{ | ||||
RMAPSend_SOCKET->disconnectFromHost(); | ||||
RMAPReceive_SOCKET->disconnectFromHost(); | ||||
GRESBStatusQuery_SOCKET->disconnectFromHost(); | ||||
emit this->activateSig(false); | ||||
|
r1 | emit gresbIsOpen(false); | ||
r0 | } | |||
void rmapplugin::RMAPSendConnectionState(QAbstractSocket::SocketState socketState) // SLOT | ||||
{ | ||||
UI->rmapSendStateLabel->setText(""); | ||||
QString socketMessage = "RMAP Send Socket State: "; | ||||
switch(socketState) | ||||
{ | ||||
case QAbstractSocket::UnconnectedState : | ||||
socketMessage.append("0 => Unconnected"); | ||||
UI->rmapOpenCommunicationButton->setEnabled(true); | ||||
UI->rmapCloseCommunicationButton->setEnabled(false); | ||||
emit this->activateSig(false); | ||||
break; | ||||
case 1: | ||||
socketMessage.append("1 => HostLookup"); | ||||
break; | ||||
case 2: | ||||
socketMessage.append("2 => Connecting"); | ||||
break; | ||||
case 3: | ||||
socketMessage.append("3 => Connected"); | ||||
UI->rmapOpenCommunicationButton->setEnabled(false); | ||||
UI->rmapCloseCommunicationButton->setEnabled(true); | ||||
break; | ||||
case 4: | ||||
socketMessage.append("4 => Bound"); | ||||
break; | ||||
case 5: | ||||
socketMessage.append("5 => Closing"); | ||||
break; | ||||
case 6: | ||||
socketMessage.append("6 => Listening"); | ||||
break; | ||||
} | ||||
UI->rmapSendStateLabel->setText(socketMessage); | ||||
APPENDTOLOG(socketMessage); | ||||
} | ||||
void rmapplugin::RMAPReceiveConnectionState(QAbstractSocket::SocketState socketState) // SLOT | ||||
{ | ||||
UI->rmapReceiveStateLabel->setText(""); | ||||
QString socketMessage = "RMAP Receive Socket State: "; | ||||
switch(socketState) | ||||
{ | ||||
case QAbstractSocket::UnconnectedState : | ||||
socketMessage.append("0 => Unconnected"); | ||||
break; | ||||
case 1: | ||||
socketMessage.append("1 => HostLookup"); | ||||
break; | ||||
case 2: | ||||
socketMessage.append("2 => Connecting"); | ||||
break; | ||||
case 3: | ||||
socketMessage.append("3 => Connected"); | ||||
break; | ||||
case 4: | ||||
socketMessage.append("4 => Bound"); | ||||
break; | ||||
case 5: | ||||
socketMessage.append("5 => Closing"); | ||||
break; | ||||
case 6: | ||||
socketMessage.append("6 => Listening"); | ||||
break; | ||||
} | ||||
UI->rmapReceiveStateLabel->setText(socketMessage); | ||||
APPENDTOLOG(socketMessage); | ||||
} | ||||
void rmapplugin::GRESBConnectionState(QAbstractSocket::SocketState socketState) // SLOT | ||||
{ | ||||
UI->gresbStatusQueryLabel->setText(""); | ||||
QString socketMessage = "GRESB status query socket (port 3010): "; | ||||
switch(socketState) | ||||
{ | ||||
case QAbstractSocket::UnconnectedState : | ||||
socketMessage.append("0 => Unconnected"); | ||||
break; | ||||
case 1: | ||||
socketMessage.append("1 => HostLookup"); | ||||
break; | ||||
case 2: | ||||
socketMessage.append("2 => Connecting"); | ||||
break; | ||||
case 3: | ||||
socketMessage.append("3 => Connected"); | ||||
break; | ||||
case 4: | ||||
socketMessage.append("4 => Bound"); | ||||
break; | ||||
case 5: | ||||
socketMessage.append("5 => Closing"); | ||||
break; | ||||
case 6: | ||||
socketMessage.append("6 => Listening"); | ||||
break; | ||||
} | ||||
UI->gresbStatusQueryLabel->setText(socketMessage); | ||||
} | ||||
void rmapplugin::reTestSPWLink() // SLOT | ||||
{ | ||||
if (GRESBStatusQueryRequest(LinkStatus, UI->spwLinkSpinBox->value()) == 0) | ||||
{ | ||||
UI->gresbStatusQueryDialog->accept(); | ||||
} | ||||
} | ||||
int rmapplugin::GRESBStatusQuery() // SLOT | ||||
{ | ||||
GRESBStatusQueryRequest(LinkStatus, 0); | ||||
GRESBStatusQueryRequest(LinkStatus, 1); | ||||
GRESBStatusQueryRequest(LinkStatus, 2); | ||||
GRESBStatusQueryRequest(LinkStatistics, 0); | ||||
GRESBStatusQueryRequest(LinkStatistics, 1); | ||||
GRESBStatusQueryRequest(LinkStatistics, 2); | ||||
return 0; | ||||
} | ||||
|
r1 | void rmapplugin::RMAP_write_reply_setText(QString text) | ||
{ | ||||
this->UI->RMAP_write_reply->setText(text); | ||||
} | ||||
void rmapplugin::appendToLog(QString text) | ||||
{ | ||||
APPENDTOLOG(text); | ||||
} | ||||
r0 | ///////////////////// | |||
// INTERNAL FUNCTIONS | ||||
int rmapplugin::GRESBStatusQueryRequest(GresbStatusQueryOption option, char link) | ||||
{ | ||||
gresb_status_query_t statusQueryCommand; | ||||
gresb_link_status_reply_t linkStatusReply; | ||||
gresb_link_statistics_reply_t linkStatisticsReply; | ||||
QTime statusQueryTimeout; | ||||
QString console_message; | ||||
statusQueryCommand.protocolIdentifier = (char) 0x02; | ||||
statusQueryCommand.reserved1 = (char) 0x00; | ||||
statusQueryCommand.reserved0 = (char) 0x00; | ||||
statusQueryCommand.option = (char) option; | ||||
statusQueryCommand.value3 = (char) 0x00; | ||||
statusQueryCommand.value2 = (char) 0x00; | ||||
statusQueryCommand.value1 = (char) 0x00; | ||||
statusQueryCommand.value0 = (char) link; | ||||
GRESBStatusQuery_SOCKET->write((char*) ((void*) &statusQueryCommand), sizeof(statusQueryCommand)); | ||||
GRESBStatusQuery_SOCKET->flush(); | ||||
GRESBStatusQuery_SOCKET->waitForBytesWritten(1000); | ||||
statusQueryTimeout.start(); | ||||
while(GRESBStatusQuery_SOCKET->bytesToWrite() > 0) | ||||
{ | ||||
GRESBStatusQuery_SOCKET->waitForBytesWritten(100); | ||||
if(statusQueryTimeout.elapsed()>1000) | ||||
{ | ||||
APPENDTOLOG("WARNING === in function GRESBStatusQueryRequest of rmapplugin *** sending StatusQueryCommand timeout"); | ||||
return 1; | ||||
} | ||||
} | ||||
switch (option) | ||||
{ | ||||
case LinkStatus: | ||||
{ | ||||
statusQueryTimeout.start(); | ||||
while(GRESBStatusQuery_SOCKET->bytesAvailable() < (int) sizeof(linkStatusReply)) | ||||
{ | ||||
GRESBStatusQuery_SOCKET->waitForReadyRead(100); | ||||
if(statusQueryTimeout.elapsed()>1000) | ||||
{ | ||||
console_message.sprintf("GRESBStatusQueryRequest / LinkStatus => error timeout bytesAvailable()\n"); | ||||
APPENDTOLOG(console_message); | ||||
return 1; | ||||
} | ||||
} | ||||
GRESBStatusQuery_SOCKET->read((char*) ((void*) &linkStatusReply), (int) sizeof(linkStatusReply)); | ||||
console_message.sprintf("%x", linkStatusReply.byte0); | ||||
UI->spwLinkStatusEnquiry->statusQueryTable->item(0, link)->setText(console_message); | ||||
console_message.sprintf("%d", linkStatusReply.byte1); | ||||
UI->spwLinkStatusEnquiry->statusQueryTable->item(1, link)->setText(console_message); | ||||
if (linkStatusReply.byte0 == 0) return 1; | ||||
break; | ||||
} | ||||
case LinkStatistics: | ||||
{ | ||||
statusQueryTimeout.start(); | ||||
while(GRESBStatusQuery_SOCKET->bytesAvailable() < (int) sizeof(linkStatisticsReply)) | ||||
{ | ||||
GRESBStatusQuery_SOCKET->waitForReadyRead(100); | ||||
if(statusQueryTimeout.elapsed()>1000) | ||||
{ | ||||
console_message.sprintf("GRESBStatusQueryRequest / LinkStatistics => error timeout bytesAvailable()\n"); | ||||
APPENDTOLOG(console_message); | ||||
return 1; | ||||
} | ||||
} | ||||
GRESBStatusQuery_SOCKET->read((char*) ((void*) &linkStatisticsReply), sizeof(linkStatisticsReply)); | ||||
console_message.sprintf("%d", charTab_TO_int(linkStatisticsReply.sizeOfDataTransmitted)); | ||||
UI->spwLinkStatusEnquiry->statusQueryTable->item(9, link)->setText(console_message); | ||||
console_message.sprintf("%d", charTab_TO_int(linkStatisticsReply.numberOfPacketsTransmitted)); | ||||
UI->spwLinkStatusEnquiry->statusQueryTable->item(8, link)->setText(console_message); | ||||
console_message.sprintf("%d", charTab_TO_int(linkStatisticsReply.numberOfTruncatedPacketsReceived)); | ||||
UI->spwLinkStatusEnquiry->statusQueryTable->item(6, link)->setText(console_message); | ||||
console_message.sprintf("%d", charTab_TO_int(linkStatisticsReply.numberOfPacketsWithEEPReceived)); | ||||
UI->spwLinkStatusEnquiry->statusQueryTable->item(5, link)->setText(console_message); | ||||
console_message.sprintf("%d", charTab_TO_int(linkStatisticsReply.sizeOfDataReceived)); | ||||
UI->spwLinkStatusEnquiry->statusQueryTable->item(4, link)->setText(console_message); | ||||
console_message.sprintf("%d", charTab_TO_int(linkStatisticsReply.numberOfPacketsReceived)); | ||||
UI->spwLinkStatusEnquiry->statusQueryTable->item(3, link)->setText(console_message); | ||||
break; | ||||
} | ||||
case NodeAddressStatistics: | ||||
{ | ||||
break; | ||||
} | ||||
case GetRoute: | ||||
{ | ||||
break; | ||||
} | ||||
} | ||||
return 0; | ||||
} | ||||
int rmapplugin::charTab_TO_int(char *charTab) | ||||
{ | ||||
int result = 0; | ||||
result = (charTab[0]<<24) +(charTab[1]<<16) +(charTab[2]<<8) + charTab[3]; | ||||
return result; | ||||
} | ||||
|
r1 | void rmapplugin::gresbSelection(bool flag) | ||
{ | ||||
if (flag == true) UI->selection_GROUPBOX->setEnabled(false); | ||||
if (flag == false) UI->selection_GROUPBOX->setEnabled(true); | ||||
} | ||||