140 lines
4.3 KiB
C++
140 lines
4.3 KiB
C++
|
#include "DataLinkLayer.h"
|
||
|
#include "../globalfunctions/CRC.h"
|
||
|
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||
|
|
||
|
DataLinkLayer::DataLinkLayer(uint8_t* set_frame_buffer, ClcwIF* setClcw,
|
||
|
uint8_t set_start_sequence_length, uint16_t set_scid) :
|
||
|
spacecraftId(set_scid), frameBuffer(set_frame_buffer), clcw(setClcw), receivedDataLength(0), currentFrame(
|
||
|
NULL), startSequenceLength(set_start_sequence_length) {
|
||
|
//Nothing to do except from setting the values above.
|
||
|
}
|
||
|
|
||
|
DataLinkLayer::~DataLinkLayer() {
|
||
|
|
||
|
}
|
||
|
|
||
|
ReturnValue_t DataLinkLayer::frameDelimitingAndFillRemoval() {
|
||
|
if ((receivedDataLength - startSequenceLength) < FRAME_PRIMARY_HEADER_LENGTH) {
|
||
|
return SHORTER_THAN_HEADER;
|
||
|
}
|
||
|
//Removing start sequence.
|
||
|
//SHOULDDO: Not implemented here.
|
||
|
while ( *frameBuffer == START_SEQUENCE_PATTERN ) {
|
||
|
frameBuffer++;
|
||
|
}
|
||
|
TcTransferFrame frame_candidate(frameBuffer);
|
||
|
this->currentFrame = frame_candidate; //should work with shallow copy.
|
||
|
|
||
|
return RETURN_OK;
|
||
|
}
|
||
|
|
||
|
ReturnValue_t DataLinkLayer::frameValidationCheck() {
|
||
|
//Check TF_version number
|
||
|
if (this->currentFrame.getVersionNumber() != FRAME_VERSION_NUMBER_DEFAULT) {
|
||
|
return WRONG_TF_VERSION;
|
||
|
}
|
||
|
//Check SpaceCraft ID
|
||
|
if (this->currentFrame.getSpacecraftId() != this->spacecraftId) {
|
||
|
return WRONG_SPACECRAFT_ID;
|
||
|
}
|
||
|
//Check other header limitations:
|
||
|
if (!this->currentFrame.bypassFlagSet() && this->currentFrame.controlCommandFlagSet()) {
|
||
|
return NO_VALID_FRAME_TYPE;
|
||
|
}
|
||
|
//- Spares are zero
|
||
|
if (!this->currentFrame.spareIsZero()) {
|
||
|
return NO_VALID_FRAME_TYPE;
|
||
|
}
|
||
|
//Compare detected frame length with the one in the header
|
||
|
uint16_t length = currentFrame.getFullSize();
|
||
|
if (length > receivedDataLength) {
|
||
|
//Frame is too long or just right
|
||
|
// error << "frameValidationCheck: Too short.";
|
||
|
// currentFrame.print();
|
||
|
return TOO_SHORT;
|
||
|
}
|
||
|
if (USE_CRC) {
|
||
|
return this->frameCheckCRC();
|
||
|
}
|
||
|
return RETURN_OK;
|
||
|
}
|
||
|
|
||
|
ReturnValue_t DataLinkLayer::frameCheckCRC() {
|
||
|
uint16_t checkValue = CRC::crc16ccitt(this->currentFrame.getFullFrame(),
|
||
|
this->currentFrame.getFullSize());
|
||
|
if (checkValue == 0) {
|
||
|
return RETURN_OK;
|
||
|
} else {
|
||
|
return CRC_FAILED;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
ReturnValue_t DataLinkLayer::allFramesReception() {
|
||
|
ReturnValue_t status = this->frameDelimitingAndFillRemoval();
|
||
|
if (status != RETURN_OK) {
|
||
|
return status;
|
||
|
}
|
||
|
return this->frameValidationCheck();
|
||
|
}
|
||
|
|
||
|
ReturnValue_t DataLinkLayer::masterChannelDemultiplexing() {
|
||
|
//Nothing to do at present. Ideally, there would be a map of MCID's identifying which MC to use.
|
||
|
return virtualChannelDemultiplexing();
|
||
|
}
|
||
|
|
||
|
ReturnValue_t DataLinkLayer::virtualChannelDemultiplexing() {
|
||
|
uint8_t vcId = currentFrame.getVirtualChannelId();
|
||
|
virtualChannelIterator iter = virtualChannels.find(vcId);
|
||
|
if (iter == virtualChannels.end()) {
|
||
|
//Do not report because passive board will get this error all the time.
|
||
|
return RETURN_OK;
|
||
|
} else {
|
||
|
return (iter->second)->frameAcceptanceAndReportingMechanism(¤tFrame, clcw);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ReturnValue_t DataLinkLayer::processFrame(uint16_t length) {
|
||
|
receivedDataLength = length;
|
||
|
ReturnValue_t status = allFramesReception();
|
||
|
if (status != RETURN_OK) {
|
||
|
sif::error << "DataLinkLayer::processFrame: frame reception failed. "
|
||
|
"Error code: " << std::hex << status << std::dec << std::endl;
|
||
|
// currentFrame.print();
|
||
|
return status;
|
||
|
} else {
|
||
|
return masterChannelDemultiplexing();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ReturnValue_t DataLinkLayer::addVirtualChannel(uint8_t virtualChannelId,
|
||
|
VirtualChannelReceptionIF* object) {
|
||
|
std::pair<virtualChannelIterator, bool> returnValue = virtualChannels.insert(
|
||
|
std::pair<uint8_t, VirtualChannelReceptionIF*>(virtualChannelId, object));
|
||
|
if (returnValue.second == true) {
|
||
|
return RETURN_OK;
|
||
|
} else {
|
||
|
return RETURN_FAILED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ReturnValue_t DataLinkLayer::initialize() {
|
||
|
ReturnValue_t returnValue = RETURN_FAILED;
|
||
|
//Set Virtual Channel ID to first virtual channel instance in this DataLinkLayer instance to avoid faulty information (e.g. 0) in the VCID.
|
||
|
if ( virtualChannels.begin() != virtualChannels.end() ) {
|
||
|
clcw->setVirtualChannel( virtualChannels.begin()->second->getChannelId() );
|
||
|
} else {
|
||
|
sif::error << "DataLinkLayer::initialize: No VC assigned to this DLL instance! " << std::endl;
|
||
|
return RETURN_FAILED;
|
||
|
}
|
||
|
|
||
|
for (virtualChannelIterator iterator = virtualChannels.begin();
|
||
|
iterator != virtualChannels.end(); iterator++) {
|
||
|
returnValue = iterator->second->initialize();
|
||
|
if (returnValue != RETURN_OK)
|
||
|
break;
|
||
|
}
|
||
|
return returnValue;
|
||
|
|
||
|
}
|