124 lines
3.9 KiB
C++
124 lines
3.9 KiB
C++
/**
|
|
* @file VirtualChannelReception.cpp
|
|
* @brief This file defines the VirtualChannelReception class.
|
|
* @date 26.03.2013
|
|
* @author baetz
|
|
*/
|
|
|
|
#include "BCFrame.h"
|
|
#include "VirtualChannelReception.h"
|
|
#include "../serviceinterface/ServiceInterfaceStream.h"
|
|
|
|
VirtualChannelReception::VirtualChannelReception(uint8_t setChannelId,
|
|
uint8_t setSlidingWindowWidth) :
|
|
channelId(setChannelId), slidingWindowWidth(setSlidingWindowWidth), positiveWindow(
|
|
setSlidingWindowWidth / 2), negativeWindow(setSlidingWindowWidth / 2), currentState(
|
|
&openState), openState(this), waitState(this), lockoutState(this), vR(0), farmBCounter(
|
|
0) {
|
|
internalClcw.setVirtualChannel(channelId);
|
|
}
|
|
|
|
ReturnValue_t VirtualChannelReception::mapDemultiplexing(TcTransferFrame* frame) {
|
|
uint8_t mapId = frame->getMAPId();
|
|
mapChannelIterator iter = mapChannels.find(mapId);
|
|
if (iter == mapChannels.end()) {
|
|
// error << "VirtualChannelReception::mapDemultiplexing on VC " << std::hex << (int) channelId
|
|
// << ": MapChannel " << (int) mapId << std::dec << " not found." << std::endl;
|
|
return VC_NOT_FOUND;
|
|
} else {
|
|
return (iter->second)->extractPackets(frame);
|
|
}
|
|
}
|
|
|
|
ReturnValue_t VirtualChannelReception::doFARM(TcTransferFrame* frame, ClcwIF* clcw) {
|
|
uint8_t bypass = frame->bypassFlagSet();
|
|
uint8_t controlCommand = frame->controlCommandFlagSet();
|
|
uint8_t typeValue = (bypass << 1) + controlCommand;
|
|
switch (typeValue) {
|
|
case AD_FRAME:
|
|
return currentState->handleADFrame(frame, clcw);
|
|
case BD_FRAME:
|
|
return handleBDFrame(frame, clcw);
|
|
case BC_FRAME:
|
|
return handleBCFrame(frame, clcw);
|
|
default:
|
|
return ILLEGAL_FLAG_COMBINATION;
|
|
}
|
|
}
|
|
|
|
ReturnValue_t VirtualChannelReception::frameAcceptanceAndReportingMechanism(TcTransferFrame* frame,
|
|
ClcwIF* clcw) {
|
|
ReturnValue_t result = RETURN_OK;
|
|
result = doFARM(frame, &internalClcw);
|
|
internalClcw.setReceiverFrameSequenceNumber(vR);
|
|
internalClcw.setFarmBCount(farmBCounter);
|
|
clcw->setWhole(internalClcw.getAsWhole());
|
|
switch (result) {
|
|
case RETURN_OK:
|
|
return mapDemultiplexing(frame);
|
|
case BC_IS_SET_VR_COMMAND:
|
|
case BC_IS_UNLOCK_COMMAND:
|
|
//Need to catch these codes to avoid error reporting later.
|
|
return RETURN_OK;
|
|
default:
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
ReturnValue_t VirtualChannelReception::addMapChannel(uint8_t mapId, MapPacketExtractionIF* object) {
|
|
std::pair<mapChannelIterator, bool> returnValue = mapChannels.insert(
|
|
std::pair<uint8_t, MapPacketExtractionIF*>(mapId, object));
|
|
if (returnValue.second == true) {
|
|
return RETURN_OK;
|
|
} else {
|
|
return RETURN_FAILED;
|
|
}
|
|
}
|
|
|
|
ReturnValue_t VirtualChannelReception::handleBDFrame(TcTransferFrame* frame, ClcwIF* clcw) {
|
|
farmBCounter++;
|
|
return RETURN_OK;
|
|
}
|
|
|
|
ReturnValue_t VirtualChannelReception::handleBCFrame(TcTransferFrame* frame, ClcwIF* clcw) {
|
|
BcFrame content;
|
|
ReturnValue_t returnValue = content.initialize(frame->getFullDataField(),
|
|
frame->getFullDataLength());
|
|
if (returnValue == BC_IS_UNLOCK_COMMAND) {
|
|
returnValue = currentState->handleBCUnlockCommand(clcw);
|
|
} else if (returnValue == BC_IS_SET_VR_COMMAND) {
|
|
returnValue = currentState->handleBCSetVrCommand(clcw, content.vR);
|
|
} else {
|
|
//Do nothing
|
|
}
|
|
return returnValue;
|
|
}
|
|
|
|
uint8_t VirtualChannelReception::getChannelId() const {
|
|
return channelId;
|
|
}
|
|
|
|
ReturnValue_t VirtualChannelReception::initialize() {
|
|
ReturnValue_t returnValue = RETURN_FAILED;
|
|
if ((slidingWindowWidth > 254) || (slidingWindowWidth % 2 != 0)) {
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
sif::error << "VirtualChannelReception::initialize: Illegal sliding window width: "
|
|
<< (int) slidingWindowWidth << std::endl;
|
|
#endif
|
|
return RETURN_FAILED;
|
|
}
|
|
for (mapChannelIterator iterator = mapChannels.begin(); iterator != mapChannels.end();
|
|
iterator++) {
|
|
returnValue = iterator->second->initialize();
|
|
if (returnValue != RETURN_OK)
|
|
break;
|
|
}
|
|
return returnValue;
|
|
}
|
|
|
|
void VirtualChannelReception::setToWaitState() {
|
|
internalClcw.setWaitFlag(true);
|
|
this->currentState = &waitState;
|
|
}
|