diff --git a/mission/devices/PlocHandler.cpp b/mission/devices/PlocHandler.cpp new file mode 100644 index 00000000..7070b51e --- /dev/null +++ b/mission/devices/PlocHandler.cpp @@ -0,0 +1,213 @@ +#include "PlocHandler.h" + +#include +#include +#include +#include + +PlocHandler::PlocHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie) : + DeviceHandlerBase(objectId, comIF, comCookie), engHkDataset(this) { + if (comCookie == NULL) { + sif::error << "PlocHandler: Invalid com cookie" << std::endl; + } +} + +PlocHandler::~PlocHandler() { +} + + +void PlocHandler::doStartUp(){ + if(mode == _MODE_START_UP){ + setMode(MODE_ON); + } +} + +void PlocHandler::doShutDown(){ + +} + +ReturnValue_t PlocHandler::buildNormalDeviceCommand( + DeviceCommandId_t * id) { + *id = IMTQ::GET_ENG_HK_DATA; + return buildCommandFromCommand(*id, NULL, 0); +} + +ReturnValue_t PlocHandler::buildTransitionDeviceCommand( + DeviceCommandId_t * id){ + return HasReturnvaluesIF::RETURN_OK; +} + +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; + 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; + return RETURN_OK; + } + default: + 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); +} + +ReturnValue_t PlocHandler::scanForReply(const uint8_t *start, + size_t remainingSize, DeviceCommandId_t *foundId, size_t *foundLen) { + + 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; + break; + default: + sif::debug << "PlocHandler::scanForReply: Reply contains invalid command code" << std::endl; + result = IGNORE_REPLY_DATA; + break; + } + + return result; +} + +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); + break; + default: { + sif::debug << "PlocHandler::interpretDeviceReply: Unknown device reply id" << std::endl; + return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY; + } + } + + 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; + default: + sif::error << "PlocHandler::parseStatusByte: CMD Error field contains unknown error code " + << cmdErrorField << std::endl; + return CMD_ERR_UNKNOWN; + } +} + +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)); + +#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 +} + +void PlocHandler::setNormalDatapoolEntriesInvalid(){ + +} + +uint32_t PlocHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo){ + return 500; +} + +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; +} + +void PlocHandler::setModeNormal() { + mode = MODE_NORMAL; +} + diff --git a/mission/devices/PlocHandler.h b/mission/devices/PlocHandler.h new file mode 100644 index 00000000..2505f224 --- /dev/null +++ b/mission/devices/PlocHandler.h @@ -0,0 +1,77 @@ +#ifndef MISSION_DEVICES_PLOCHANDLER_H_ +#define MISSION_DEVICES_PLOCHANDLER_H_ + +#include +#include +#include + +/** + * @brief This is the device handler for the ISIS Magnetorquer iMTQ. + * + * @author J. Meier + */ +class PlocHandler: public DeviceHandlerBase { +public: + + PlocHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie); + virtual ~PlocHandler(); + + /** + * @brief Sets mode to MODE_NORMAL. Can be used for debugging. + */ + void setModeNormal(); + +protected: + void doStartUp() override; + void doShutDown() override; + ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) override; + ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) override; + void fillCommandAndReplyMap() override; + ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, + const uint8_t * commandData,size_t commandDataLen) override; + ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize, + DeviceCommandId_t *foundId, size_t *foundLen) override; + ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, + const uint8_t *packet) override; + void setNormalDatapoolEntriesInvalid() override; + uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; + ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; + +private: + + static const uint8_t INTERFACE_ID = CLASS_ID::IMTQ_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); + + + IMTQ::EngHkDataset engHkDataset; + + uint8_t commandBuffer[IMTQ::MAX_COMMAND_SIZE]; + + /** + * @brief Each reply contains a status byte giving information about a request. This function + * parses this byte and returns the associated failure message. + * + * @param packet Pointer to the received message containing the status byte. + * + * @return The return code derived from the received status byte. + */ + ReturnValue_t parseStatusByte(const uint8_t* packet); + + /** + * @brief This function fills the engineering housekeeping dataset with the received data. + + * @param packet Pointer to the received data. + * + */ + void fillEngHkDataset(const uint8_t* packet); +}; + +#endif /* MISSION_DEVICES_PLOCHANDLER_H_ */ diff --git a/tmtc b/tmtc index 80ee4208..f40b70f6 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 80ee42089e5baadd60479178417299a8c660c80a +Subproject commit f40b70f66eba176d3c36533a779e4e0ed13ae701