diff --git a/README.md b/README.md index f0c749be..dafbfbba 100644 --- a/README.md +++ b/README.md @@ -271,7 +271,7 @@ Copying a file from Q7S to flatsat PC scp -P 22 root@192.168.133.10:/tmp/kernel-config /tmp ```` -From a windows machine files can be copied with putty tools +From a windows machine files can be copied with putty tools (note: use IPv4 address) ```` pscp -scp -P 22 eive@192.168.199.227:/example-file ```` diff --git a/bsp_q7s/ObjectFactory.cpp b/bsp_q7s/ObjectFactory.cpp index 6cd3ec64..85d82a48 100644 --- a/bsp_q7s/ObjectFactory.cpp +++ b/bsp_q7s/ObjectFactory.cpp @@ -21,10 +21,12 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -327,6 +329,13 @@ void ObjectFactory::produce(){ IMTQHandler* imtqHandler = new IMTQHandler(objects::IMTQ_HANDLER, objects::I2C_COM_IF, imtqI2cCookie); imtqHandler->setStartUpImmediately(); + UartCookie* plocUartCookie = new UartCookie(std::string("/dev/ttyPS1"), 115200, + PLOC::MAX_REPLY_SIZE); + /* Testing PlocHandler on TE0720-03-1CFA */ + PlocHandler* plocHandler = new PlocHandler(objects::PLOC_HANDLER, objects::UART_COM_IF, + plocUartCookie); + plocHandler->setStartUpImmediately(); + #endif new TmTcUnixUdpBridge(objects::UDP_BRIDGE, @@ -348,5 +357,12 @@ void ObjectFactory::produce(){ heaterGpiosCookie->addGpio(gpioIds::HEATER_0, gpioConfigForDummyHeater); new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, heaterGpiosCookie, objects::PCDU_HANDLER, pcduSwitches::TCS_BOARD_8V_HEATER_IN); + + UartCookie* plocUartCookie = new UartCookie(std::string("/dev/ttyPS1"), 115200, + PLOC::MAX_REPLY_SIZE); + /* Testing PlocHandler on TE0720-03-1CFA */ + PlocHandler* plocHandler = new PlocHandler(objects::PLOC_HANDLER, objects::UART_COM_IF, + plocUartCookie); + plocHandler->setStartUpImmediately(); #endif } diff --git a/fsfwconfig/OBSWConfig.h b/fsfwconfig/OBSWConfig.h index 73c05edb..3f5ebfca 100644 --- a/fsfwconfig/OBSWConfig.h +++ b/fsfwconfig/OBSWConfig.h @@ -19,7 +19,7 @@ debugging. */ #define OBSW_ADD_TEST_CODE 1 #define TEST_LIBGPIOD 0 -#define TE0720 0 +#define TE0720 1 #define P60DOCK_DEBUG 0 #define PDU1_DEBUG 0 diff --git a/fsfwconfig/objects/systemObjectList.h b/fsfwconfig/objects/systemObjectList.h index c0c78a62..352c4ddc 100644 --- a/fsfwconfig/objects/systemObjectList.h +++ b/fsfwconfig/objects/systemObjectList.h @@ -52,6 +52,7 @@ namespace objects { GYRO_2_L3G_HANDLER = 0x44000013, IMTQ_HANDLER = 0x44000014, + PLOC_HANDLER = 0x44000015, /* Custom device handler */ PCDU_HANDLER = 0x44001000, diff --git a/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp b/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp index 43435cf3..86e3629e 100644 --- a/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp +++ b/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp @@ -36,6 +36,7 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) thisSequence->addSlot(objects::RTD_IC17, length * 0, DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::RTD_IC18, length * 0, DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::PLOC_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.2, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.2, DeviceHandlerIF::SEND_WRITE); @@ -56,6 +57,7 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) thisSequence->addSlot(objects::RTD_IC17, length * 0.2, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::RTD_IC18, length * 0.2, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.4, DeviceHandlerIF::GET_WRITE); @@ -76,6 +78,7 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) thisSequence->addSlot(objects::RTD_IC17, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::RTD_IC18, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.6, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.6, DeviceHandlerIF::SEND_READ); @@ -96,6 +99,7 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) thisSequence->addSlot(objects::RTD_IC17, length * 0.6, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::RTD_IC18, length * 0.6, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.8, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.8, DeviceHandlerIF::GET_READ); @@ -116,6 +120,7 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) thisSequence->addSlot(objects::RTD_IC17, length * 0.8, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::RTD_IC18, length * 0.8, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); + thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { return HasReturnvaluesIF::RETURN_OK; diff --git a/fsfwconfig/returnvalues/classIds.h b/fsfwconfig/returnvalues/classIds.h index 93349596..22bb0457 100644 --- a/fsfwconfig/returnvalues/classIds.h +++ b/fsfwconfig/returnvalues/classIds.h @@ -20,6 +20,7 @@ enum { SA_DEPL_HANDLER, SYRLINKS_HANDLER, IMTQ_HANDLER, + PLOC_HANDLER }; } diff --git a/mission/devices/CMakeLists.txt b/mission/devices/CMakeLists.txt index 6e8518b0..7d34aac9 100644 --- a/mission/devices/CMakeLists.txt +++ b/mission/devices/CMakeLists.txt @@ -13,6 +13,7 @@ target_sources(${TARGET_NAME} PUBLIC SyrlinksHkHandler.cpp Max31865PT1000Handler.cpp IMTQHandler.cpp + PlocHandler.cpp ) diff --git a/mission/devices/PlocHandler.cpp b/mission/devices/PlocHandler.cpp index 7070b51e..b88dde90 100644 --- a/mission/devices/PlocHandler.cpp +++ b/mission/devices/PlocHandler.cpp @@ -6,7 +6,7 @@ #include PlocHandler::PlocHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie) : - DeviceHandlerBase(objectId, comIF, comCookie), engHkDataset(this) { + DeviceHandlerBase(objectId, comIF, comCookie) { if (comCookie == NULL) { sif::error << "PlocHandler: Invalid com cookie" << std::endl; } @@ -28,8 +28,7 @@ void PlocHandler::doShutDown(){ ReturnValue_t PlocHandler::buildNormalDeviceCommand( DeviceCommandId_t * id) { - *id = IMTQ::GET_ENG_HK_DATA; - return buildCommandFromCommand(*id, NULL, 0); + return RETURN_OK; } ReturnValue_t PlocHandler::buildTransitionDeviceCommand( @@ -41,34 +40,37 @@ ReturnValue_t PlocHandler::buildCommandFromCommand( DeviceCommandId_t deviceCommand, const uint8_t * commandData, size_t commandDataLen) { switch(deviceCommand) { - case(IMTQ::GET_ENG_HK_DATA): { - commandBuffer[0] = IMTQ::CC::GET_ENG_HK_DATA; - rawPacket = commandBuffer; + case(PLOC::TC_MEM_WRITE): { + const uint32_t memoryAddress = *(commandData) << 24 | *(commandData + 1) << 16 + | *(commandData + 2) << 8 | *(commandData + 3); + const uint32_t memoryData = *(commandData + 4) << 24 | *(commandData + 5) << 16 + | *(commandData + 6) << 8 | *(commandData + 7); + PLOC::TcMemWrite tcMemWrite(memoryAddress, memoryData); + rawPacket = tcMemWrite.getWholeData(); + rawPacketLen = tcMemWrite.getFullSize(); + rememberCommandId = PLOC::TC_MEM_WRITE; return RETURN_OK; } - case(IMTQ::START_ACTUATION_DIPOLE): { - /* IMTQ expects low byte first */ - commandBuffer[0] = IMTQ::CC::START_ACTUATION_DIPOLE; - commandBuffer[1] = *(commandData + 1); - commandBuffer[2] = *(commandData); - commandBuffer[3] = *(commandData + 3); - commandBuffer[4] = *(commandData + 2); - commandBuffer[5] = *(commandData + 5); - commandBuffer[6] = *(commandData + 4); - commandBuffer[7] = *(commandData + 7); - commandBuffer[8] = *(commandData + 6); - rawPacket = commandBuffer; + case(PLOC::TC_MEM_READ): { + const uint32_t memoryAddress = *(commandData) << 24 | *(commandData + 1) << 16 + | *(commandData + 2) << 8 | *(commandData + 3); + PLOC::TcMemRead tcMemRead(memoryAddress); + rawPacket = tcMemRead.getWholeData(); + rawPacketLen = tcMemRead.getFullSize(); + rememberCommandId = PLOC::TC_MEM_READ; return RETURN_OK; } default: + sif::debug << "PlocHandler::buildCommandFromCommand: Command not implemented" << std::endl; return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; } return HasReturnvaluesIF::RETURN_FAILED; } void PlocHandler::fillCommandAndReplyMap() { - this->insertInCommandAndReplyMap(IMTQ::GET_ENG_HK_DATA, 1, &engHkDataset, - IMTQ::SIZE_ENG_HK_DATA_REPLY, false, true, IMTQ::SIZE_ENG_HK_DATA_REPLY); + this->insertInCommandAndReplyMap(PLOC::TC_MEM_READ, 1, nullptr, PLOC::SIZE_ACK_REPORT); + this->insertInReplyMap(PLOC::ACK_SUCCESS, 1); + this->insertInReplyMap(PLOC::ACK_FAILURE, 1); } ReturnValue_t PlocHandler::scanForReply(const uint8_t *start, @@ -76,34 +78,51 @@ ReturnValue_t PlocHandler::scanForReply(const uint8_t *start, ReturnValue_t result = RETURN_OK; - switch(*start) { - case(IMTQ::CC::GET_ENG_HK_DATA): - *foundLen = IMTQ::SIZE_ENG_HK_DATA_REPLY; - *foundId = IMTQ::GET_ENG_HK_DATA; + *foundId = *(start) << 8 | *(start + 1) & APID_MASK; + + switch(*foundId) { + case(PLOC::ACK_SUCCESS): + *foundLen = PLOC::SIZE_ACK_REPORT; + break; + case(PLOC::ACK_FAILURE): + *foundLen = PLOC::SIZE_ACK_REPORT; break; default: - sif::debug << "PlocHandler::scanForReply: Reply contains invalid command code" << std::endl; + sif::debug << "PlocHandler::scanForReply: Reply has invalid apid" << std::endl; result = IGNORE_REPLY_DATA; break; } + result = verifyPacket(start, foundLen); + return result; } +ReturnValue_t PlocHandler::verifyPacket(const uint8_t* start, size_t* foundLen) { + + uint16_t receivedCrc = *(start + *foundLen - 2) << 8 | *(start + *foundlen - 1); + + if (receivedCrc != CRC::crc16ccitt(start, *foundLen, 0)) { + return CRC_FAILURE; + } + + return RETURN_OK; +} + ReturnValue_t PlocHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { ReturnValue_t result = RETURN_OK; - result = parseStatusByte(packet); - - if (result != RETURN_OK) { - return result; - } - switch (id) { - case (IMTQ::GET_ENG_HK_DATA): - fillEngHkDataset(packet); + case (PLOC::ACK_SUCCESS): + receiveTm(); + receiveExecutionReport(); + break; + case (PLOC::ACK_FAILURE): + //TODO: Interpretation of status field in ack reply. + sif::error << "PlocHandler::interpretDeviceReply: Received ack failure reply" << std::endl; + triggerEvent(ACK_FAILURE, rememberCommandId); break; default: { sif::debug << "PlocHandler::interpretDeviceReply: Unknown device reply id" << std::endl; @@ -114,71 +133,116 @@ ReturnValue_t PlocHandler::interpretDeviceReply(DeviceCommandId_t id, return RETURN_OK; } -ReturnValue_t PlocHandler::parseStatusByte(const uint8_t* packet) { - uint8_t cmdErrorField = *(packet + 1) & 0xF; - switch (cmdErrorField) { - case 0: - return RETURN_OK; - case 1: - return REJECTED_WITHOUT_REASON; - case 2: - return INVALID_COMMAND_CODE; - case 3: - return PARAMETER_MISSING; - case 4: - return PARAMETER_INVALID; - case 5: - return CC_UNAVAILABLE; - case 7: - return INTERNAL_PROCESSING_ERROR; +ReturnValue_t PlocHandler::receiveTm() { + switch (rememberCommandId) { + case (PLOC::TC_MEM_WRITE): + break; + case (PLOC::TC_MEM_READ): + receiveTmMemoryReadReport(); + break; default: - sif::error << "PlocHandler::parseStatusByte: CMD Error field contains unknown error code " - << cmdErrorField << std::endl; - return CMD_ERR_UNKNOWN; + sif::debug << "PlocHandler::receiveTm: Rembered unknown command id" << std::endl; + break; } } -void PlocHandler::fillEngHkDataset(const uint8_t* packet) { - uint8_t offset = 2; - engHkDataset.digitalVoltageMv = *(packet + offset + 1) | *(packet + offset); - offset += 2; - engHkDataset.analogVoltageMv = *(packet + offset + 1) | *(packet + offset); - offset += 2; - engHkDataset.digitalCurrentA = (*(packet + offset + 1) | *(packet + offset)) * 0.0001; - offset += 2; - engHkDataset.analogCurrentA = (*(packet + offset + 1) | *(packet + offset)) * 0.0001; - offset += 2; - engHkDataset.coilXcurrentA = (*(packet + offset + 1) | *(packet + offset)) * 0.0001; - offset += 2; - engHkDataset.coilYcurrentA = (*(packet + offset + 1) | *(packet + offset)) * 0.0001; - offset += 2; - engHkDataset.coilZcurrentA = (*(packet + offset + 1) | *(packet + offset)) * 0.0001; - offset += 2; - engHkDataset.coilXTemperature = (*(packet + offset + 1) | *(packet + offset)); - offset += 2; - engHkDataset.coilYTemperature = (*(packet + offset + 1) | *(packet + offset)); - offset += 2; - engHkDataset.coilZTemperature = (*(packet + offset + 1) | *(packet + offset)); - offset += 2; - engHkDataset.mcuTemperature = (*(packet + offset + 1) | *(packet + offset)); +void PlocHandler::receiveExecutionReport() { -#if OBSW_VERBOSE_LEVEL >= 1 && IMTQ_DEBUG == 1 - sif::info << "IMTQ digital voltage: " << engHkDataset.digitalVoltageMv << " mV" << std::endl; - sif::info << "IMTQ analog voltage: " << engHkDataset.analogVoltageMv << " mV" << std::endl; - sif::info << "IMTQ digital current: " << engHkDataset.digitalCurrentA << " A" << std::endl; - sif::info << "IMTQ analog current: " << engHkDataset.analogCurrentA << " A" << std::endl; - sif::info << "IMTQ coil X current: " << engHkDataset.coilXcurrentA << " A" << std::endl; - sif::info << "IMTQ coil Y current: " << engHkDataset.coilYcurrentA << " A" << std::endl; - sif::info << "IMTQ coil Z current: " << engHkDataset.coilZcurrentA << " A" << std::endl; - sif::info << "IMTQ coil X temperature: " << engHkDataset.coilXTemperature << " °C" - << std::endl; - sif::info << "IMTQ coil Y temperature: " << engHkDataset.coilYTemperature << " °C" - << std::endl; - sif::info << "IMTQ coil Z temperature: " << engHkDataset.coilZTemperature << " °C" - << std::endl; - sif::info << "IMTQ coil MCU temperature: " << engHkDataset.mcuTemperature << " °C" - << std::endl; -#endif + size_t receivedDataLen = 0; + uint8_t *receivedData = nullptr; + + communicationInterface->requestReceiveMessage(comCookie, PLOC::SIZE_EXE_REPORT); + communicationInterface->readReceivedMessage(comCookie, &receivedData, &receivedDataLen); + + if(!verifyPacket(receivedData, receivedDataLen)) { + replyRawData(data, len, defaultRawReceiver); + triggerEvent(EXE_RPT_INVALID_CRC); + sif::error << "PlocHandler::receiveExecutionReport: Execution report has invalid crc" + << std::endl; + return; + } + + handleExecutionReport(receivedData, receivedDataLen); +} + +void PlocHandler::handleExecutionReport(const uint8_t* receivedData, size_t receivedDataLen) { + + uint16_t apid = *(start) << 8 | *(start + 1) & APID_MASK; + + switch (apid) { + case (PLOC::APID_EXE_SUCCESS): { + return; + } + case (PLOC::APID_EXE_FAILURE): { + //TODO: Interpretation of status field in execution report + sif::error << "PlocHandler::handleExecutionReport: Received execution failure report" + << std::endl; + triggerEvent(EXE_FAILURE, rememberCommandId); + return; + } + } + return; +} + +void PlocHandler::receiveTmMemoryReadReport() { + + size_t receivedDataLen = 0; + uint8_t *receivedData = nullptr; + + /* Receiving the telemetry packet */ + ReturnValue_t result = communicationInterface->requestReceiveMessage(comCookie, + PLOC::SIZE_TM_MEM_READ_REPORT); + if (result != RETURN_OK) { + sif::error << "PlocHandler::receiveExecutionReport: Failed to request memory read telemetry " + << std::endl; + triggerEvent(REQUESTING_TM_READ_REPORT_FAILED, result); + return; + } + result = communicationInterface->readReceivedMessage(comCookie, &receivedData, &receivedDataLen); + if (result != RETURN_OK) { + sif::error << "PlocHandler::receiveExecutionReport: Failed to request memory read telemetry " + << std::endl; + return; + } + + uint16_t apid = *(start) << 8 | *(start + 1) & APID_MASK; + if (apid != PLOC::APID_TM_READ_REPORT) { + sif::error << "PlocHandler::receiveTmReadReport: Tm read report has invalid apid" + << std::endl; + return; + } + + if(!verifyPacket(receivedData, receivedDataLen)) { + replyRawData(data, len, defaultRawReceiver); + triggerEvent(TM_READ_RPT_INVALID_CRC); + sif::error << "PlocHandler::receiveTmReadReport: TM read report has invalid crc" + << std::endl; + return; + } + + handleDeviceTM(receivedData, receivedDataLen, PLOC::TC_MEM_READ); + +} + +void PlocHandler::handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId) { + + ReturnValue_t result = RETURN_OK; + + DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId); + if (iter == deviceReplyMap.end()) { + sif::debug << "PlocHandler::handleDeviceTM: Unknown reply id" << std::endl; + return; + } + MessageQueueId_t queueId = iter->second.command->second.sendReplyTo; + + if (queueId == NO_COMMANDER) { + return; + } + + result = actionHelper.reportData(queueId, replyId, dataSet); + if (result != RETURN_OK) { + sif::debug << "PlocHandler::handleDeviceTM: Failed to report data" << std::endl; + } } void PlocHandler::setNormalDatapoolEntriesInvalid(){ @@ -192,18 +256,6 @@ uint32_t PlocHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo){ ReturnValue_t PlocHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { - localDataPoolMap.emplace(IMTQ::DIGITAL_VOLTAGE_MV, new PoolEntry( { 0 })); - localDataPoolMap.emplace(IMTQ::ANALOG_VOLTAGE_MV, new PoolEntry( { 0 })); - localDataPoolMap.emplace(IMTQ::DIGITAL_CURRENT_A, new PoolEntry( { 0 })); - localDataPoolMap.emplace(IMTQ::ANALOG_CURRENT_A, new PoolEntry( { 0 })); - localDataPoolMap.emplace(IMTQ::COIL_X_CURRENT_A, new PoolEntry( { 0 })); - localDataPoolMap.emplace(IMTQ::COIL_Y_CURRENT_A, new PoolEntry( { 0 })); - localDataPoolMap.emplace(IMTQ::COIL_Z_CURRENT_A, new PoolEntry( { 0 })); - localDataPoolMap.emplace(IMTQ::COIL_X_TEMPERATURE, new PoolEntry( { 0 })); - localDataPoolMap.emplace(IMTQ::COIL_Y_TEMPERATURE, new PoolEntry( { 0 })); - localDataPoolMap.emplace(IMTQ::COIL_Z_TEMPERATURE, new PoolEntry( { 0 })); - localDataPoolMap.emplace(IMTQ::MCU_TEMPERATURE, new PoolEntry( { 0 })); - return HasReturnvaluesIF::RETURN_OK; } diff --git a/mission/devices/PlocHandler.h b/mission/devices/PlocHandler.h index 2505f224..86e2e2dd 100644 --- a/mission/devices/PlocHandler.h +++ b/mission/devices/PlocHandler.h @@ -2,7 +2,7 @@ #define MISSION_DEVICES_PLOCHANDLER_H_ #include -#include +#include #include /** @@ -40,38 +40,67 @@ protected: private: - static const uint8_t INTERFACE_ID = CLASS_ID::IMTQ_HANDLER; + static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_HANDLER; - static const ReturnValue_t INVALID_COMMAND_CODE = MAKE_RETURN_CODE(0xA0); - static const ReturnValue_t PARAMETER_MISSING = MAKE_RETURN_CODE(0xA1); - static const ReturnValue_t PARAMETER_INVALID = MAKE_RETURN_CODE(0xA2); - static const ReturnValue_t CC_UNAVAILABLE = MAKE_RETURN_CODE(0xA3); - static const ReturnValue_t INTERNAL_PROCESSING_ERROR = MAKE_RETURN_CODE(0xA4); - static const ReturnValue_t REJECTED_WITHOUT_REASON = MAKE_RETURN_CODE(0xA5); - static const ReturnValue_t CMD_ERR_UNKNOWN = MAKE_RETURN_CODE(0xA6); + static const ReturnValue_t TC_ACK_FAILURE = MAKE_RETURN_CODE(0xA0); + static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA1); + static const Event REQUESTING_TM_READ_REPORT_FAILED = MAKE_EVENT(0, severity::LOW); + static const Event TM_READ_RPT_INVALID_CRC = MAKE_EVENT(1, severity::LOW); + static const Event ACK_FAILURE = MAKE_EVENT(2, severity::LOW); + static const Event EXE_FAILURE = MAKE_EVENT(3, severity::LOW); + static const Event EXE_RPT_INVALID_CRC = MAKE_EVENT(4, severity::LOW); - IMTQ::EngHkDataset engHkDataset; + static const uint16_t APID_MASK = 0x7FF; - uint8_t commandBuffer[IMTQ::MAX_COMMAND_SIZE]; + DeviceCommandId_t rememberCommandId = PLOC::NONE; + + /** + * @brief This function checks wheter a telemetry packet is expected or not. + */ + ReturnValue_t receiveTm(); /** - * @brief Each reply contains a status byte giving information about a request. This function - * parses this byte and returns the associated failure message. + * @brief This function checks the crc of the received PLOC reply. * - * @param packet Pointer to the received message containing the status byte. + * @param start Pointer to the first byte of the reply. + * @param foundLen Pointer to the length of the whole packet. * - * @return The return code derived from the received status byte. + * @return RETURN_OK if CRC is ok, otherwise CRC_FAILURE. */ - ReturnValue_t parseStatusByte(const uint8_t* packet); + ReturnValue_t verifyPacket(const uint8_t* start, size_t* foundLen); /** - * @brief This function fills the engineering housekeeping dataset with the received data. - - * @param packet Pointer to the received data. - * + * @brief This function reads and handles the execution reply. */ - void fillEngHkDataset(const uint8_t* packet); + void receiveExecutionReport(); + + /** + * @brief This function handles the data of a execution report. + * + * @param receivedData Pointer to the received data + * @param receivedDataLen Size in bytes of the received data + */ + void handleExecutionReport(const uint8_t* receivedData, size_t receivedDataLen); + + /** + * @brief This function reads and handles the memory read report telemetry packet received + * after requesting the packet with the TC_MEM_READ command. + * + * @details In case of a valid packet the received memory content will be forwarded to the + * commanding object via an action message. + */ + void receiveTmMemoryReadReport(); + + /** + * @brief This function handles action message replies in case the telemetry has been + * requested by another object. + * + * @param data Pointer to the telemtry data. + * @param dataSize Size of telemetry in bytes. + * @param replyId Id of the reply. This will be added to the ActionMessage. + */ + void handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId); }; #endif /* MISSION_DEVICES_PLOCHANDLER_H_ */ diff --git a/mission/devices/devicedefinitions/PlocDefinitions.h b/mission/devices/devicedefinitions/PlocDefinitions.h new file mode 100644 index 00000000..d468d0dd --- /dev/null +++ b/mission/devices/devicedefinitions/PlocDefinitions.h @@ -0,0 +1,131 @@ +#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_PLOCDEFINITIONS_H_ +#define MISSION_DEVICES_DEVICEDEFINITIONS_PLOCDEFINITIONS_H_ + +#include +#include + +namespace PLOC { + + static const DeviceCommandId_t NONE = 0x0; + static const DeviceCommandId_t TC_MEM_WRITE = 0x714; + static const DeviceCommandId_t TC_MEM_READ = 0x715; + static const DeviceCommandId_t ACK_SUCCESS = 0x400; + static const DeviceCommandId_t ACK_FAILURE = 0x401; + static const DeviceCommandId_t TM_READ_REPORT = 0x404; + + static const uint16_t SIZE_ACK_REPORT = 14; + static const uint16_t SIZE_EXE_REPORT = 14; + static const uint16_t SIZE_TM_MEM_READ_REPORT = 18; + + /** + * SpacePacket apids of PLOC telecommands and telemetry. + */ + static const uint16_t APID_TC_MEM_WRITE = 0x714; + static const uint16_t APID_TM_READ_REPORT = 0x404; + static const uint16_t APID_EXE_SUCCESS = 0x402; + static const uint16_t APID_EXE_FAILURE = 0x403; + + /** + * PLOC space packet length for fixed size packets. This is the size of the whole packet data + * field. For the length field in the space packet this size will be substracted by one. + */ + static const uint16_t LENGTH_TC_MEM_WRITE = 12; + static const uint16_t LENGTH_TC_MEM_READ = 8; + + static const size_t MAX_REPLY_SIZE = SIZE_TM_MEM_READ_REPORT; + + /** + * @brief This class helps to build the memory read command for the PLOC. + * + * @details The last two bytes of the packet data field contain a CRC calculated over the whole + * space packet. This is the CRC-16-CCITT as specified in + * ECSS-E-ST-70-41C – Telemetry and telecommand packet utilization. + */ + class TcMemRead : public SpacePacket { + public: + /** + * @brief Constructor + * + * @param memAddr The memory address to read from. + */ + TcMemRead(const uint32_t memAddr) : + SpacePacket(LENGTH_TC_MEM_READ - 1, true, APID_TC_MEM_READ) { + fillPacketDataField(&memAddr); + } + + private: + + /** + * @brief This function builds the packet data field for the mem read command. + * + * @param memAddrPtr Pointer to the memory address to read from. + */ + void fillPacketDataField(const uint32_t* memAddrPtr) { + /* Add memAddr to packet data field */ + memcpy(this->localData.fields.buffer, memAddrPtr, sizeof(memAddrPtr)); + /* Add memLen to packet data field */ + this->localData.fields.buffer[OFFSET_MEM_LEN_FIELD] = 0; + this->localData.fields.buffer[OFFSET_MEM_LEN_FIELD + 1] = 1; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + LENGTH_TC_MEM_READ - CRC_SIZE, 0); + /* Add crc to packet data field of space packet */ + memcpy(this->localData.fields.buffer + CRC_OFFSET, &crc, sizeof(crc)); + } + + static const uint8_t CRC_OFFSET = 12; + static const uint8_t OFFSET_MEM_LEN_FIELD = 10; + + }; + + /** + * @brief This class helps to generate the space packet to write to a memory address within + * the PLOC. + * @details The last two bytes of the packet data field contain a CRC calculated over the whole + * space packet. This is the CRC-16-CCITT as specified in + * ECSS-E-ST-70-41C – Telemetry and telecommand packet utilization. + */ + class TcMemWrite : public SpacePacket { + public: + /** + * @brief Constructor + * + * @param memAddr The PLOC memory address where to write to. + * @param memoryData The data to write to the specified memory address. + */ + TcMemWrite(const uint32_t memAddr, const uint32_t memoryData) : + SpacePacket(LENGTH_TC_MEM_WRITE - 1, true, APID_TC_MEM_WRITE) { + fillPacketDataField(&memAddr, &memoryData); + } + + private: + + /** + * @brief This function builds the packet data field for the mem write command. + * + * @param memAddrPtr Pointer to the PLOC memory address where to write to. + * @param memoryDataPtr Pointer to the memoryData to write + */ + void fillPacketDataField(const uint32_t* memAddrPtr, const uint32_t* memoryDataPtr) { + /* Add memAddr to packet data field */ + memcpy(this->localData.fields.buffer, memAddrPtr, sizeof(memAddrPtr)); + /* Add memLen to packet data field */ + this->localData.fields.buffer[OFFSET_MEM_LEN_FIELD] = 0; + this->localData.fields.buffer[OFFSET_MEM_LEN_FIELD + 1] = 1; + /* Add memData to packet data field */ + memcpy(this->localData.fields.buffer + OFFSET_MEM_DATA_FIELD, memAddrPtr, + sizeof(memAddrPtr)); + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + LENGTH_TC_MEM_WRITE - CRC_SIZE, 0); + /* Add crc to packet data field of space packet */ + memcpy(this->localData.fields.buffer + CRC_OFFSET, &crc, sizeof(crc)); + } + + static const uint8_t OFFSET_MEM_LEN_FIELD = 10; + static const uint8_t OFFSET_MEM_DATA_FIELD = 12; + static const uint8_t CRC_OFFSET = 16; + }; + +} + + +#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_PLOCDEFINITIONS_H_ */ diff --git a/tmtc b/tmtc index f40b70f6..73105138 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit f40b70f66eba176d3c36533a779e4e0ed13ae701 +Subproject commit 73105138050b5661a6cff76e1d64af40981f9c7f