diff --git a/bsp_q7s/core/InitMission.cpp b/bsp_q7s/core/InitMission.cpp index 80e95732..803339a2 100644 --- a/bsp_q7s/core/InitMission.cpp +++ b/bsp_q7s/core/InitMission.cpp @@ -126,6 +126,13 @@ void initmission::initTasks() { if(result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("FILE_SYSTEM_TASK", objects::FILE_SYSTEM_HANDLER); } + + PeriodicTaskIF* strImgLoaderTask = factory->createPeriodicTask( + "FILE_SYSTEM_TASK", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); + result = strImgLoaderTask->addComponent(objects::STR_HELPER); + if(result != HasReturnvaluesIF::RETURN_OK) { + initmission::printAddObjectError("FILE_SYSTEM_TASK", objects::STR_HELPER); + } #endif /* BOARD_TE0720 */ #if OBSW_TEST_CCSDS_BRIDGE == 1 @@ -187,6 +194,7 @@ void initmission::initTasks() { #if BOARD_TE0720 == 0 fsTask->startTask(); + strImgLoaderTask->startTask(); #endif sif::info << "Tasks started.." << std::endl; @@ -213,21 +221,21 @@ void initmission::createPstTasks(TaskFactory& factory, #endif FixedTimeslotTaskIF* uartPst = factory.createFixedTimeslotTask( - "UART_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, missedDeadlineFunc); + "UART_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.2, missedDeadlineFunc); result = pst::pstUart(uartPst); if (result != HasReturnvaluesIF::RETURN_OK) { sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; } taskVec.push_back(uartPst); FixedTimeslotTaskIF* gpioPst = factory.createFixedTimeslotTask( - "GPIO_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, missedDeadlineFunc); + "GPIO_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.2, missedDeadlineFunc); result = pst::pstGpio(gpioPst); if (result != HasReturnvaluesIF::RETURN_OK) { sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; } taskVec.push_back(gpioPst); FixedTimeslotTaskIF* i2cPst = factory.createFixedTimeslotTask( - "I2C_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, missedDeadlineFunc); + "I2C_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.2, missedDeadlineFunc); result = pst::pstI2c(i2cPst); if (result != HasReturnvaluesIF::RETURN_OK) { sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index 3b35f89e..f01ed223 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -1,5 +1,8 @@ #include #include "ObjectFactory.h" + +#include "bsp_q7s/devices/startracker/StrHelper.h" +#include "bsp_q7s/devices/startracker/StarTrackerDefinitions.h" #include "OBSWConfig.h" #include "devConf.h" #include "ccsdsConfig.h" @@ -16,16 +19,15 @@ #include "bsp_q7s/devices/PlocSupervisorHandler.h" #include "bsp_q7s/devices/PlocUpdater.h" #include "bsp_q7s/devices/PlocMemoryDumper.h" +#include "bsp_q7s/devices/startracker/StarTrackerHandler.h" #include "bsp_q7s/callbacks/rwSpiCallback.h" #include "bsp_q7s/callbacks/gnssCallback.h" -#include "linux/devices/StarTrackerHandler.h" #include "linux/devices/SolarArrayDeploymentHandler.h" #include "linux/devices/devicedefinitions/SusDefinitions.h" #include "linux/devices/SusHandler.h" #include "linux/csp/CspCookie.h" #include "linux/csp/CspComIF.h" -#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h" #include "mission/devices/HeaterHandler.h" #include "mission/core/GenericFactory.h" @@ -169,11 +171,15 @@ void ObjectFactory::produce(void* args) { new FileSystemHandler(objects::FILE_SYSTEM_HANDLER); #if OBSW_ADD_STAR_TRACKER == 1 - UartCookie* starTrackerCookie = new UartCookie(objects::START_TRACKER, + UartCookie* starTrackerCookie = new UartCookie(objects::STAR_TRACKER, q7s::UART_STAR_TRACKER_DEV, UartModes::NON_CANONICAL, uart::STAR_TRACKER_BAUD, StarTracker::MAX_FRAME_SIZE* 2 + 2); starTrackerCookie->setNoFixedSizeReply(); - new StarTrackerHandler(objects::START_TRACKER, objects::UART_COM_IF, starTrackerCookie); + StrHelper* strHelper = new StrHelper(objects::STR_HELPER); + StarTrackerHandler* starTrackerHandler = new StarTrackerHandler(objects::STAR_TRACKER, + objects::UART_COM_IF, starTrackerCookie, strHelper); + starTrackerHandler->setStartUpImmediately(); + #endif /* OBSW_ADD_STAR_TRACKER == 1 */ #endif /* TE7020 == 0 */ diff --git a/bsp_q7s/devices/CMakeLists.txt b/bsp_q7s/devices/CMakeLists.txt index 6347b5f8..70705e83 100644 --- a/bsp_q7s/devices/CMakeLists.txt +++ b/bsp_q7s/devices/CMakeLists.txt @@ -2,4 +2,6 @@ target_sources(${TARGET_NAME} PRIVATE PlocSupervisorHandler.cpp PlocUpdater.cpp PlocMemoryDumper.cpp -) \ No newline at end of file +) + +add_subdirectory(startracker) \ No newline at end of file diff --git a/bsp_q7s/devices/PlocUpdater.cpp b/bsp_q7s/devices/PlocUpdater.cpp index 5a94495b..592a2c0d 100644 --- a/bsp_q7s/devices/PlocUpdater.cpp +++ b/bsp_q7s/devices/PlocUpdater.cpp @@ -168,14 +168,14 @@ ReturnValue_t PlocUpdater::getImageLocation(const uint8_t* data, size_t size) { #if BOARD_TE0720 == 0 // Check if file is stored on SD card and if associated SD card is mounted if (std::string(reinterpret_cast(data), SD_PREFIX_LENGTH) == std::string(SdCardManager::SD_0_MOUNT_POINT)) { - if (!isSdCardMounted(sd::SLOT_0)) { - sif::warning << "PlocUpdater::prepareNvm0AUpdate: SD card 0 not mounted" << std::endl; + if (!sdcMan->isSdCardMounted(sd::SLOT_0)) { + sif::warning << "PlocUpdater::getImageLocation: SD card 0 not mounted" << std::endl; return SD_NOT_MOUNTED; } } else if (std::string(reinterpret_cast(data), SD_PREFIX_LENGTH) == std::string(SdCardManager::SD_1_MOUNT_POINT)) { - if (!isSdCardMounted(sd::SLOT_0)) { - sif::warning << "PlocUpdater::prepareNvm0AUpdate: SD card 1 not mounted" << std::endl; + if (!sdcMan->isSdCardMounted(sd::SLOT_0)) { + sif::warning << "PlocUpdater::getImageLocation: SD card 1 not mounted" << std::endl; return SD_NOT_MOUNTED; } } @@ -193,37 +193,6 @@ ReturnValue_t PlocUpdater::getImageLocation(const uint8_t* data, size_t size) { return RETURN_OK; } -#if BOARD_TE0720 == 0 -bool PlocUpdater::isSdCardMounted(sd::SdCard sdCard) { - SdCardManager::SdStatePair active; - ReturnValue_t result = sdcMan->getSdCardActiveStatus(active); - if (result != RETURN_OK) { - sif::debug << "PlocUpdater::isSdCardMounted: Failed to get SD card active state"; - return false; - } - if (sdCard == sd::SLOT_0) { - if (active.first == sd::MOUNTED) { - return true; - } - else { - return false; - } - } - else if (sdCard == sd::SLOT_1) { - if (active.second == sd::MOUNTED) { - return true; - } - else { - return false; - } - } - else { - sif::debug << "PlocUpdater::isSdCardMounted: Unknown SD card specified" << std::endl; - } - return false; -} -#endif /* #if BOARD_TE0720 == 0 */ - void PlocUpdater::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) { } diff --git a/bsp_q7s/devices/PlocUpdater.h b/bsp_q7s/devices/PlocUpdater.h index 50404d14..d016b9e5 100644 --- a/bsp_q7s/devices/PlocUpdater.h +++ b/bsp_q7s/devices/PlocUpdater.h @@ -174,13 +174,6 @@ private: */ void commandUpdateVerify(); -#if BOARD_TE0720 == 0 - /** - * @brief Checks whether the SD card to read from is mounted or not. - */ - bool isSdCardMounted(sd::SdCard sdCard); -#endif - void calcImageCrc(); void adjustSequenceFlags(PLOC_SPV::UpdatePacket& packet); diff --git a/bsp_q7s/devices/startracker/ArcsecDatalinkLayer.cpp b/bsp_q7s/devices/startracker/ArcsecDatalinkLayer.cpp new file mode 100644 index 00000000..4e7c9458 --- /dev/null +++ b/bsp_q7s/devices/startracker/ArcsecDatalinkLayer.cpp @@ -0,0 +1,78 @@ +#include "ArcsecDatalinkLayer.h" + +ArcsecDatalinkLayer::ArcsecDatalinkLayer() { + slipInit(); +} + +ArcsecDatalinkLayer::~ArcsecDatalinkLayer() { +} + +void ArcsecDatalinkLayer::slipInit() { + slipInfo.buffer = rxBuffer; + slipInfo.maxlength = StarTracker::MAX_FRAME_SIZE; + slipInfo.length = 0; + slipInfo.unescape_next = 0; + slipInfo.prev_state = SLIP_COMPLETE; +} + +ReturnValue_t ArcsecDatalinkLayer::decodeFrame(const uint8_t* rawData, size_t rawDataSize, + size_t* bytesLeft) { + size_t bytePos = 0; + for (bytePos = 0; bytePos < rawDataSize; bytePos++) { + enum arc_dec_result decResult = arc_transport_decode_body(*(rawData + bytePos), &slipInfo, + decodedFrame, &decFrameSize); + *bytesLeft = rawDataSize - bytePos - 1; + switch (decResult) { + case ARC_DEC_INPROGRESS: { + if (bytePos == rawDataSize - 1) { + return DEC_IN_PROGRESS; + } + continue; + } + case ARC_DEC_ERROR_FRAME_SHORT: + return REPLY_TOO_SHORT; + case ARC_DEC_ERROR_CHECKSUM: + return CRC_FAILURE; + case ARC_DEC_ASYNC: + case ARC_DEC_SYNC: { + // Reset length of SLIP struct for next frame + slipInfo.length = 0; + return RETURN_OK; + } + default: + sif::debug << "ArcsecDatalinkLayer::decodeFrame: Unknown result code" << std::endl; + break; + return RETURN_FAILED; + } + } + return RETURN_FAILED; +} + +uint8_t ArcsecDatalinkLayer::getReplyFrameType() { + return decodedFrame[0]; +} + +const uint8_t* ArcsecDatalinkLayer::getReply() { + return &decodedFrame[1]; +} + +void ArcsecDatalinkLayer::encodeFrame(const uint8_t* data, uint32_t length) { + arc_transport_encode_body(data, length, encBuffer, &encFrameSize); +} + +uint8_t* ArcsecDatalinkLayer::getEncodedFrame() { + return encBuffer; +} + +uint32_t ArcsecDatalinkLayer::getEncodedLength() { + return encFrameSize; +} + +uint8_t ArcsecDatalinkLayer::getStatusField() { + return *(decodedFrame + STATUS_OFFSET); +} + +uint8_t ArcsecDatalinkLayer::getId() { + return *(decodedFrame + ID_OFFSET); +} + diff --git a/bsp_q7s/devices/startracker/ArcsecDatalinkLayer.h b/bsp_q7s/devices/startracker/ArcsecDatalinkLayer.h new file mode 100644 index 00000000..a65881c7 --- /dev/null +++ b/bsp_q7s/devices/startracker/ArcsecDatalinkLayer.h @@ -0,0 +1,100 @@ +#ifndef BSP_Q7S_DEVICES_ARCSECDATALINKLAYER_H_ +#define BSP_Q7S_DEVICES_ARCSECDATALINKLAYER_H_ + +#include "StarTrackerDefinitions.h" +#include "fsfw/returnvalues/HasReturnvaluesIF.h" + +extern "C" { + #include "common/misc.h" +} + +/** + * @brief Helper class to handle the datalinklayer of replies from the star tracker of arcsec. + */ +class ArcsecDatalinkLayer: public HasReturnvaluesIF { +public: + + static const uint8_t INTERFACE_ID = CLASS_ID::STR_HANDLER; + + //! [EXPORT] : [COMMENT] More data required to complete frame + static const ReturnValue_t DEC_IN_PROGRESS = MAKE_RETURN_CODE(0xA0); + //! [EXPORT] : [COMMENT] Data too short to represent a valid frame + static const ReturnValue_t REPLY_TOO_SHORT = MAKE_RETURN_CODE(0xA1); + //! [EXPORT] : [COMMENT] Detected CRC failure in received frame + static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA2); + + static const uint8_t STATUS_OK = 0; + + ArcsecDatalinkLayer(); + virtual ~ArcsecDatalinkLayer(); + + /** + * @brief Applies decoding to data referenced by rawData pointer + * + * @param rawData Pointer to raw data received from star tracker + * @param rawDataSize Size of raw data stream + * @param remainingBytes Number of bytes left + */ + ReturnValue_t decodeFrame(const uint8_t* rawData, size_t rawDataSize, size_t* bytesLeft); + + /** + * @brief SLIP encodes data pointed to by data pointer. + * + * @param data Pointer to data to encode + * @param length Length of buffer to encode + */ + void encodeFrame(const uint8_t* data, uint32_t length); + + /** + * @brief Returns the frame type field of a decoded frame. + */ + uint8_t getReplyFrameType(); + + /** + * @brief Returns pointer to reply packet (first entry normally action ID, telemetry ID etc.) + */ + const uint8_t* getReply(); + + /** + * @brief Returns size of encoded frame + */ + uint32_t getEncodedLength(); + + /** + * @brief Returns pointer to encoded frame + */ + uint8_t* getEncodedFrame(); + + /** + * @brief Returns status of reply + */ + uint8_t getStatusField(); + + /** + * @brief Returns ID of reply + */ + uint8_t getId(); + +private: + + static const uint8_t ID_OFFSET = 1; + static const uint8_t STATUS_OFFSET = 2; + + // Used by arcsec slip decoding function process received data + uint8_t rxBuffer[StarTracker::MAX_FRAME_SIZE]; + // Decoded frame will be copied to this buffer + uint8_t decodedFrame[StarTracker::MAX_FRAME_SIZE]; + // Buffer where encoded frames will be stored. First byte of encoded frame represents type of + // reply + uint8_t encBuffer[StarTracker::MAX_FRAME_SIZE * 2 + 2]; + // Size of decoded frame + uint32_t decFrameSize = 0; + // Size of encoded frame + uint32_t encFrameSize = 0; + + slip_decode_state slipInfo; + + void slipInit(); +}; + +#endif /* BSP_Q7S_DEVICES_ARCSECDATALINKLAYER_H_ */ diff --git a/bsp_q7s/devices/startracker/ArcsecJsonKeys.h b/bsp_q7s/devices/startracker/ArcsecJsonKeys.h new file mode 100644 index 00000000..2c598b43 --- /dev/null +++ b/bsp_q7s/devices/startracker/ArcsecJsonKeys.h @@ -0,0 +1,126 @@ +#ifndef BSP_Q7S_DEVICES_DEVICEDEFINITIONS_ARCSECJSONKEYS_H_ +#define BSP_Q7S_DEVICES_DEVICEDEFINITIONS_ARCSECJSONKEYS_H_ + +/** + * @brief Keys used in JSON file of ARCSEC. + */ +namespace arcseckeys { + static const char PROPERTIES[] = "properties"; + static const char NAME[] = "name"; + static const char VALUE[] = "value"; + + static const char LIMITS[] = "limits"; + static const char ACTION[] = "action"; + static const char FPGA18CURRENT[] = "FPGA18Current"; + static const char FPGA25CURRENT[] = "FPGA25Current"; + static const char FPGA10CURRENT[] = "FPGA10Current"; + static const char MCUCURRENT[] = "MCUCurrent"; + static const char CMOS21CURRENT[] = "CMOS21Current"; + static const char CMOSPIXCURRENT[] = "CMOSPixCurrent"; + static const char CMOS33CURRENT[] = "CMOS33Current"; + static const char CMOSVRESCURRENT[] = "CMOSVResCurrent"; + static const char CMOS_TEMPERATURE[] = "CMOSTemperature"; + static const char MCU_TEMPERATURE[] = "MCUTemperature"; + + static const char MOUNTING[] = "mounting"; + static const char qw[] = "qw"; + static const char qx[] = "qx"; + static const char qy[] = "qy"; + static const char qz[] = "qz"; + + static const char CAMERA[] = "camera"; + static const char MODE[] = "mode"; + static const char FOCALLENGTH[] = "focallength"; + static const char EXPOSURE[] = "exposure"; + static const char INTERVAL[] = "interval"; + static const char OFFSET[] = "offset"; + static const char PGAGAIN[] = "PGAGain"; + static const char ADCGAIN[] = "ADCGain"; + static const char REG_1[] = "reg1"; + static const char VAL_1[] = "val1"; + static const char REG_2[] = "reg2"; + static const char VAL_2[] = "val2"; + static const char REG_3[] = "reg3"; + static const char VAL_3[] = "val3"; + static const char REG_4[] = "reg4"; + static const char VAL_4[] = "val4"; + static const char REG_5[] = "reg5"; + static const char VAL_5[] = "val5"; + static const char REG_6[] = "reg6"; + static const char VAL_6[] = "val6"; + static const char REG_7[] = "reg7"; + static const char VAL_7[] = "val7"; + static const char REG_8[] = "reg8"; + static const char VAL_8[] = "val8"; + static const char FREQ_1[] = "freq1"; + static const char FREQ_2[] = "freq2"; + + static const char BLOB[] = "blob"; + static const char MIN_VALUE[] = "minValue"; + static const char MIN_DISTANCE[] = "minDistance"; + static const char NEIGHBOUR_DISTANCE[] = "neighbourDistance"; + static const char NEIGHBOUR_BRIGHT_PIXELS[] = "neighbourBrightPixels"; + static const char MIN_TOTAL_VALUE[] = "minTotalValue"; + static const char MAX_TOTAL_VALUE[] = "maxTotalValue"; + static const char MIN_BRIGHT_NEIGHBOURS[] = "minBrightNeighbours"; + static const char MAX_BRIGHT_NEIGHBOURS[] = "maxBrightNeighbours"; + static const char MAX_PIXEL_TO_CONSIDER[] = "maxPixelsToConsider"; + static const char SIGNAL_THRESHOLD[] = "signalThreshold"; + static const char DARK_THRESHOLD[] = "darkThreshold"; + static const char ENABLE_HISTOGRAM[] = "enableHistogram"; + static const char ENABLE_CONTRAST[] = "enableContrast"; + static const char BIN_MODE[] = "binMode"; + + static const char CENTROIDING[] = "centroiding"; + static const char ENABLE_FILTER[] = "enableFilter"; + static const char MAX_QUALITY[] = "maxquality"; + static const char MIN_QUALITY[] = "minquality"; + static const char MAX_INTENSITY[] = "maxintensity"; + static const char MIN_INTENSITY[] = "minintensity"; + static const char MAX_MAGNITUDE[] = "maxmagnitude"; + static const char GAUSSIAN_CMAX[] = "gaussianCmax"; + static const char GAUSSIAN_CMIN[] = "gaussianCmin"; + static const char TRANSMATRIX_00[] = "transmatrix00"; + static const char TRANSMATRIX_01[] = "transmatrix01"; + static const char TRANSMATRIX_10[] = "transmatrix10"; + static const char TRANSMATRIX_11[] = "transmatrix11"; + + static const char LISA[] = "lisa"; + static const char PREFILTER_DIST_THRESHOLD[] = "prefilterDistThreshold"; + static const char PREFILTER_ANGLE_THRESHOLD[] = "prefilterAngleThreshold"; + static const char FOV_WIDTH[] = "fov_width"; + static const char FOV_HEIGHT[] = "fov_height"; + static const char FLOAT_STAR_LIMIT[] = "float_star_limit"; + static const char CLOSE_STAR_LIMIT[] = "close_star_limit"; + static const char RATING_WEIGHT_CLOSE_STAR_COUNT[] = "rating_weight_close_star_count"; + static const char RATING_WEIGHT_FRACTION_CLOSE[] = "rating_weight_fraction_close"; + static const char RATING_WEIGHT_MEAN_SUM[] = "rating_weight_mean_sum"; + static const char RATING_WEIGHT_DB_STAR_COUNT[] = "rating_weight_db_star_count"; + static const char MAX_COMBINATIONS[] = "max_combinations"; + static const char NR_STARS_STOP[] = "nr_stars_stop"; + static const char FRACTION_CLOSE_STOP[] = "fraction_close_stop"; + + static const char MATCHING[] = "matching"; + static const char SQUARED_DISTANCE_LIMIT[] = "squaredDistanceLimit"; + static const char SQUARED_SHIFT_LIMIT[] = "squaredShiftLimit"; + + static const char VALIDATION[] = "validation"; + static const char STABLE_COUNT[] = "stable_count"; + static const char MAX_DIFFERENCE[] = "max_difference"; + static const char MIN_TRACKER_CONFIDENCE[] = "min_trackerConfidence"; + static const char MIN_MATCHED_STARS[] = "min_matchedStars"; + + static const char TRACKING[] = "tracking"; + static const char THIN_LIMIT[] = "thinLimit"; + static const char OUTLIER_THRESHOLD[] = "outlierThreshold"; + static const char OUTLIER_THRESHOLD_QUEST[] = "outlierThresholdQUEST"; + static const char TRACKER_CHOICE[] = "trackerChoice"; + + static const char ALGO[] = "algo"; + static const char L2T_MIN_CONFIDENCE[] = "l2t_minConfidence"; + static const char L2T_MIN_MATCHED[] = "l2t_minConfidence"; + static const char T2L_MIN_CONFIDENCE[] = "t2l_minConfidence"; + static const char T2L_MIN_MATCHED[] = "t2l_minMatched"; +} + +#endif /* BSP_Q7S_DEVICES_DEVICEDEFINITIONS_ARCSECJSONKEYS_H_ */ diff --git a/bsp_q7s/devices/startracker/ArcsecJsonParamBase.cpp b/bsp_q7s/devices/startracker/ArcsecJsonParamBase.cpp new file mode 100644 index 00000000..339c3fe7 --- /dev/null +++ b/bsp_q7s/devices/startracker/ArcsecJsonParamBase.cpp @@ -0,0 +1,94 @@ +#include "ArcsecJsonParamBase.h" +#include "ArcsecJsonKeys.h" + +ArcsecJsonParamBase::ArcsecJsonParamBase(std::string setName) : setName(setName) {} + +ReturnValue_t ArcsecJsonParamBase::create(std::string fullname, uint8_t* buffer) { + ReturnValue_t result = RETURN_OK; + result = init(fullname); + if (result != RETURN_OK) { + return result; + } + result = createCommand(buffer); + return result; +} + +ReturnValue_t ArcsecJsonParamBase::getParam(const std::string name, std::string& value) { + for (json::iterator it = set.begin(); it != set.end(); ++it) { + if ((*it)[arcseckeys::NAME] == name) { + value = (*it)[arcseckeys::VALUE]; + convertEmpty(value); + return RETURN_OK; + } + } + return PARAM_NOT_EXISTS; +} + +void ArcsecJsonParamBase::convertEmpty(std::string& value) { + if (value == "") { + value = "0"; + } +} + +void ArcsecJsonParamBase::addfloat(const std::string value, uint8_t* buffer) { + float param = std::stof(value); + std::memcpy(buffer, ¶m, sizeof(param)); +} + +void ArcsecJsonParamBase::adduint8(const std::string value, uint8_t* buffer) { + uint8_t param = std::stoi(value); + std::memcpy(buffer, ¶m, sizeof(param)); +} + +void ArcsecJsonParamBase::addint16(const std::string value, uint8_t* buffer) { + int16_t param = std::stoi(value); + std::memcpy(buffer, ¶m, sizeof(param)); +} + +void ArcsecJsonParamBase::adduint16(const std::string value, uint8_t* buffer) { + uint16_t param = std::stoi(value); + std::memcpy(buffer, ¶m, sizeof(param)); +} + +void ArcsecJsonParamBase::adduint32(const std::string value, uint8_t* buffer) { + uint32_t param = std::stoi(value); + std::memcpy(buffer, ¶m, sizeof(param)); +} + +void ArcsecJsonParamBase::addSetParamHeader(uint8_t* buffer, uint8_t setId) { + *buffer = static_cast(TMTC_SETPARAMREQ); + *(buffer + 1) = setId; +} + +ReturnValue_t ArcsecJsonParamBase::init(const std::string filename) { + ReturnValue_t result = RETURN_OK; + if (not std::filesystem::exists(filename)) { + sif::warning << "ArcsecJsonParamBase::init: JSON file " << filename << " does not exist" + << std::endl; + return JSON_FILE_NOT_EXISTS; + } + createJsonObject(filename); + result = initSet(); + if (result != RETURN_OK) { + return result; + } + return RETURN_OK; +} + +void ArcsecJsonParamBase::createJsonObject(const std::string fullname) { + json j; + std::ifstream file(fullname); + file >> j; + file.close(); + properties = j[arcseckeys::PROPERTIES]; +} + +ReturnValue_t ArcsecJsonParamBase::initSet() { + for (json::iterator it = properties.begin(); it != properties.end(); ++it) { + if ((*it)["name"] == setName) { + set = (*it)["fields"]; + return RETURN_OK; + } + } + return SET_NOT_EXISTS; +} diff --git a/bsp_q7s/devices/startracker/ArcsecJsonParamBase.h b/bsp_q7s/devices/startracker/ArcsecJsonParamBase.h new file mode 100644 index 00000000..320eff53 --- /dev/null +++ b/bsp_q7s/devices/startracker/ArcsecJsonParamBase.h @@ -0,0 +1,149 @@ +#ifndef BSP_Q7S_DEVICES_STARTRACKER_ARCSECJSONPARAMBASE_H_ +#define BSP_Q7S_DEVICES_STARTRACKER_ARCSECJSONPARAMBASE_H_ + +#include +#include +#include + +#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "StarTrackerDefinitions.h" + +extern "C" { + #include "thirdparty/arcsec_star_tracker/common/generated/tmtcstructs.h" + #include "thirdparty/arcsec_star_tracker/common/genericstructs.h" +} + +using json = nlohmann::json; + +/** + * @brief Base class for creation of parameter configuration commands. Reads parameter set + * from a json file located on the filesystem and generates the appropriate command + * to apply the parameters to the star tracker software. + * + * @author J. Meier + */ +class ArcsecJsonParamBase : public HasReturnvaluesIF { +public: + + static const uint8_t INTERFACE_ID = CLASS_ID::ARCSEC_JSON_BASE; + //! [EXPORT] : [COMMENT] Specified json file does not exist + static const ReturnValue_t JSON_FILE_NOT_EXISTS = MAKE_RETURN_CODE(1); + //! [EXPORT] : [COMMENT] Requested set does not exist in json file + static const ReturnValue_t SET_NOT_EXISTS = MAKE_RETURN_CODE(2); + //! [EXPORT] : [COMMENT] Requested parameter does not exist in json file + static const ReturnValue_t PARAM_NOT_EXISTS = MAKE_RETURN_CODE(3); + + /** + * @brief Constructor + * + * @param fullname Name with absolute path of json file containing the parameters to set. + */ + ArcsecJsonParamBase(std::string setName); + + /** + * @brief Fills a buffer with a parameter set + * + * @param fullname The name including the absolute path of the json file containing the + * parameter set. + * @param buffer Pointer to the buffer the command will be written to + */ + ReturnValue_t create(std::string fullname, uint8_t* buffer); + + /** + * @brief Returns the size of the parameter command. + */ + virtual size_t getSize() = 0; + +protected: + + /** + * @brief Reads the value of a parameter from a json set + * + * @param name The name of the parameter + * @param value The string representation of the read value + * + * @return RETURN_OK if successful, otherwise PARAM_NOT_EXISTS + */ + ReturnValue_t getParam(const std::string name, std::string& value); + + /** + * @brief Converts empty string which is equal to define a value as zero. + */ + void convertEmpty(std::string& value); + + /** + * @brief This function adds a float represented as string to a buffer + * + * @param value The float in string representation to add + * @param buffer Pointer to the buffer the float will be written to + */ + void addfloat(const std::string value, uint8_t* buffer); + + /** + * @brief This function adds a uint8_t represented as string to a buffer + * + * @param value The uint8_t in string representation to add + * @param buffer Pointer to the buffer the uint8_t will be written to + */ + void adduint8(const std::string value, uint8_t* buffer); + + /** + * @brief This function adds a int16_t represented as string to a buffer + * + * @param value The int16_t in string representation to add + * @param buffer Pointer to the buffer the int16_t will be written to + */ + void addint16(const std::string value, uint8_t* buffer); + + /** + * @brief This function adds a uint16_t represented as string to a buffer + * + * @param value The uint16_t in string representation to add + * @param buffer Pointer to the buffer the uint16_t will be written to + */ + void adduint16(const std::string value, uint8_t* buffer); + + /** + * @brief This function adds a uint32_t represented as string to a buffer + * + * @param value The uint32_t in string representation to add + * @param buffer Pointer to the buffer the uint32_t will be written to + */ + void adduint32(const std::string value, uint8_t* buffer); + + void addSetParamHeader(uint8_t* buffer, uint8_t setId); + +private: + + json properties; + json set; + std::string setName; + + /** + * @brief This function must be implemented by the derived class to define creation of a + * parameter command. + */ + virtual ReturnValue_t createCommand(uint8_t* buffer) = 0; + + /** + * @brief Initializes the properties json object and the set json object + * + * @param fullname Name including absolute path to json file + * @param setName The name of the set to work on + * + * @param return JSON_FILE_NOT_EXISTS if specified file does not exist, otherwise + * RETURN_OK + */ + ReturnValue_t init(const std::string filename); + + void createJsonObject(const std::string fullname); + + /** + * @brief Extracts the json set object form the json file + * + * @param setName The name of the set to create the json object from + */ + ReturnValue_t initSet(); +}; + +#endif /* BSP_Q7S_DEVICES_STARTRACKER_ARCSECJSONPARAMBASE_H_ */ diff --git a/bsp_q7s/devices/startracker/CMakeLists.txt b/bsp_q7s/devices/startracker/CMakeLists.txt new file mode 100644 index 00000000..28704219 --- /dev/null +++ b/bsp_q7s/devices/startracker/CMakeLists.txt @@ -0,0 +1,7 @@ +target_sources(${TARGET_NAME} PRIVATE + StarTrackerHandler.cpp + StarTrackerJsonCommands.cpp + ArcsecDatalinkLayer.cpp + ArcsecJsonParamBase.cpp + StrHelper.cpp +) \ No newline at end of file diff --git a/bsp_q7s/devices/startracker/StarTrackerDefinitions.h b/bsp_q7s/devices/startracker/StarTrackerDefinitions.h new file mode 100644 index 00000000..22214cb0 --- /dev/null +++ b/bsp_q7s/devices/startracker/StarTrackerDefinitions.h @@ -0,0 +1,850 @@ +#ifndef MISSION_STARTRACKER_DEFINITIONS_H_ +#define MISSION_STARTRACKER_DEFINITIONS_H_ + +#include +#include +#include +#include +#include "objects/systemObjectList.h" +#include + +namespace StarTracker { + +/** This is the address of the star tracker */ +static const uint8_t ADDRESS = 33; + +static const uint8_t STATUS_OK = 0; + +enum PoolIds: lp_id_t { + TICKS_TIME_SET, + TIME_TIME_SET, + RUN_TIME, + UNIX_TIME, + TICKS_VERSION_SET, + TIME_VERSION_SET, + PROGRAM, + MAJOR, + MINOR, + TICKS_INTERFACE_SET, + TIME_INTERFACE_SET, + FRAME_COUNT, + CHECKSUM_ERROR_COUNT, + SET_PARAM_COUNT, + SET_PARAM_REPLY_COUNT, + PARAM_REQUEST_COUNT, + PARAM_REPLY_COUNT, + REQ_TM_COUNT, + TM_REPLY_COUNT, + ACTION_REQ_COUNT, + ACTION_REPLY_COUNT, + TICKS_POWER_SET, + TIME_POWER_SET, + MCU_CURRENT, + MCU_VOLTAGE, + FPGA_CORE_CURRENT, + FPGA_CORE_VOLTAGE, + FPGA_18_CURRENT, + FPGA_18_VOLTAGE, + FPGA_25_CURRENT, + FPGA_25_VOLTAGE, + CMV_21_CURRENT, + CMV_21_VOLTAGE, + CMV_PIX_CURRENT, + CMV_PIX_VOLTAGE, + CMV_33_CURRENT, + CMV_33_VOLTAGE, + CMV_RES_CURRENT, + CMV_RES_VOLTAGE, + TICKS_TEMPERATURE_SET, + TIME_TEMPERATURE_SET, + MCU_TEMPERATURE, + CMOS_TEMPERATURE, + + TICKS_SOLUTION_SET, + TIME_SOLUTION_SET, + CALI_QW, + CALI_QX, + CALI_QY, + CALI_QZ, + TRACK_CONFIDENCE, + TRACK_QW, + TRACK_QX, + TRACK_QY, + TRACK_QZ, + TRACK_REMOVED, + STARS_CENTROIDED, + STARS_MATCHED_DATABASE, + LISA_QW, + LISA_QX, + LISA_QY, + LISA_QZ, + LISA_PERC_CLOSE, + LISA_NR_CLOSE, + TRUST_WORTHY, + STABLE_COUNT, + SOLUTION_STRATEGY, + + TICKS_HISTOGRAM_SET, + TIME_HISTOGRAM_SET, + HISTOGRAM_BINA0, + HISTOGRAM_BINA1, + HISTOGRAM_BINA2, + HISTOGRAM_BINA3, + HISTOGRAM_BINA4, + HISTOGRAM_BINA5, + HISTOGRAM_BINA6, + HISTOGRAM_BINA7, + HISTOGRAM_BINA8, + HISTOGRAM_BINB0, + HISTOGRAM_BINB1, + HISTOGRAM_BINB2, + HISTOGRAM_BINB3, + HISTOGRAM_BINB4, + HISTOGRAM_BINB5, + HISTOGRAM_BINB6, + HISTOGRAM_BINB7, + HISTOGRAM_BINB8, + HISTOGRAM_BINC0, + HISTOGRAM_BINC1, + HISTOGRAM_BINC2, + HISTOGRAM_BINC3, + HISTOGRAM_BINC4, + HISTOGRAM_BINC5, + HISTOGRAM_BINC6, + HISTOGRAM_BINC7, + HISTOGRAM_BINC8, + HISTOGRAM_BIND0, + HISTOGRAM_BIND1, + HISTOGRAM_BIND2, + HISTOGRAM_BIND3, + HISTOGRAM_BIND4, + HISTOGRAM_BIND5, + HISTOGRAM_BIND6, + HISTOGRAM_BIND7, + HISTOGRAM_BIND8, + + TICKS_CONTRAST_SET, + TIME_CONTRAST_SET, + CONTRAST_BINA0, + CONTRAST_BINA1, + CONTRAST_BINA2, + CONTRAST_BINA3, + CONTRAST_BINA4, + CONTRAST_BINA5, + CONTRAST_BINA6, + CONTRAST_BINA7, + CONTRAST_BINA8, + CONTRAST_BINB0, + CONTRAST_BINB1, + CONTRAST_BINB2, + CONTRAST_BINB3, + CONTRAST_BINB4, + CONTRAST_BINB5, + CONTRAST_BINB6, + CONTRAST_BINB7, + CONTRAST_BINB8, + CONTRAST_BINC0, + CONTRAST_BINC1, + CONTRAST_BINC2, + CONTRAST_BINC3, + CONTRAST_BINC4, + CONTRAST_BINC5, + CONTRAST_BINC6, + CONTRAST_BINC7, + CONTRAST_BINC8, + CONTRAST_BIND0, + CONTRAST_BIND1, + CONTRAST_BIND2, + CONTRAST_BIND3, + CONTRAST_BIND4, + CONTRAST_BIND5, + CONTRAST_BIND6, + CONTRAST_BIND7, + CONTRAST_BIND8 +}; + +static const DeviceCommandId_t PING_REQUEST = 0; +// Boots image (works only in bootloader mode) +static const DeviceCommandId_t BOOT = 1; +static const DeviceCommandId_t REQ_VERSION = 2; +static const DeviceCommandId_t REQ_INTERFACE = 3; +static const DeviceCommandId_t REQ_TIME = 4; +static const DeviceCommandId_t ERASE = 5; +static const DeviceCommandId_t UNLOCK = 6; +static const DeviceCommandId_t SWITCH_TO_BOOTLOADER_PROGRAM = 7; +static const DeviceCommandId_t DOWNLOAD_IMAGE = 9; +static const DeviceCommandId_t UPLOAD_IMAGE = 10; +static const DeviceCommandId_t REQ_POWER = 11; +static const DeviceCommandId_t TAKE_IMAGE = 15; +static const DeviceCommandId_t DOWNLOAD_CENTROID = 16; +static const DeviceCommandId_t UPLOAD_CENTROID = 17; +static const DeviceCommandId_t SUBSCRIBE_TO_TM = 18; +static const DeviceCommandId_t REQ_SOLUTION = 24; +static const DeviceCommandId_t REQ_TEMPERATURE = 25; +static const DeviceCommandId_t REQ_HISTOGRAM = 28; +static const DeviceCommandId_t REQ_CONTRAST = 29; +static const DeviceCommandId_t LIMITS = 40; +static const DeviceCommandId_t MOUNTING = 41; +static const DeviceCommandId_t CAMERA = 42; +static const DeviceCommandId_t BLOB = 43; +static const DeviceCommandId_t CENTROIDING = 44; +static const DeviceCommandId_t LISA = 45; +static const DeviceCommandId_t MATCHING = 46; +static const DeviceCommandId_t TRACKING = 47; +static const DeviceCommandId_t VALIDATION = 48; +static const DeviceCommandId_t ALGO = 49; +static const DeviceCommandId_t CHECKSUM = 50; +static const DeviceCommandId_t READ = 51; +static const DeviceCommandId_t WRITE = 52; +static const DeviceCommandId_t DOWNLOAD_MATCHED_STAR = 53; +static const DeviceCommandId_t DOWNLOAD_DB_IMAGE = 54; +static const DeviceCommandId_t STOP_IMAGE_LOADER = 55; +static const DeviceCommandId_t RESET_ERROR = 56; +static const DeviceCommandId_t CHANGE_DOWNLOAD_FILE = 57; +static const DeviceCommandId_t SET_JSON_FILE_NAME = 58; +static const DeviceCommandId_t NONE = 0xFFFFFFFF; + +static const uint32_t VERSION_SET_ID = REQ_VERSION; +static const uint32_t INTERFACE_SET_ID = REQ_INTERFACE; +static const uint32_t POWER_SET_ID = REQ_POWER; +static const uint32_t TEMPERATURE_SET_ID = REQ_TEMPERATURE; +static const uint32_t TIME_SET_ID = REQ_TIME; +static const uint32_t SOLUTION_SET_ID = REQ_SOLUTION; +static const uint32_t HISTOGRAM_SET_ID = REQ_HISTOGRAM; +static const uint32_t CONTRAST_SET_ID = REQ_CONTRAST; + +/** Max size of unencoded frame */ +static const size_t MAX_FRAME_SIZE = 1200; + +static const uint8_t TEMPERATURE_SET_ENTRIES = 4; +static const uint8_t VERSION_SET_ENTRIES = 5; +static const uint8_t INTERFACE_SET_ENTRIES = 4; +static const uint8_t POWER_SET_ENTRIES = 18; +static const uint8_t TIME_SET_ENTRIES = 4; +static const uint8_t SOLUTION_SET_ENTRIES = 23; +static const uint8_t HISTOGRAM_SET_ENTRIES = 38; +static const uint8_t CONTRAST_SET_ENTRIES = 38; + +// Action, parameter and telemetry IDs +namespace ID { + static const uint8_t PING = 0; + static const uint8_t BOOT = 1; + static const uint8_t VERSION = 2; + static const uint8_t INTERFACE = 3; + static const uint8_t LIMITS = 5; + static const uint8_t MOUNTING = 6; + static const uint8_t CAMERA = 9; + static const uint8_t BLOB = 10; + static const uint8_t CENTROIDING = 11; + static const uint8_t LISA = 12; + static const uint8_t MATCHING = 13; + static const uint8_t TRACKING = 14; + static const uint8_t VALIDATION = 15; + static const uint8_t ALGO = 16; + static const uint8_t REBOOT = 7; + static const uint8_t UPLOAD_IMAGE = 10; + static const uint8_t POWER = 11; + static const uint8_t SUBSCRIBE = 18; + static const uint8_t SOLUTION = 24; + static const uint8_t TEMPERATURE = 25; + static const uint8_t HISTOGRAM = 28; + static const uint8_t CONTRAST = 29; + static const uint8_t TIME = 1; + static const uint8_t WRITE = 2; + static const uint8_t READ = 3; + static const uint8_t CHECKSUM = 4; + static const uint8_t ERASE = 5; + static const uint8_t UNLOCK = 6; + static const uint8_t TAKE_IMAGE = 15; + static const uint8_t ERROR_RESET = 12; +} + +namespace Program { + static const uint8_t BOOTLOADER = 1; + static const uint8_t FIRMWARE = 2; +} + +/** + * @brief This dataset can be used to store the temperature of a reaction wheel. + */ +class TemperatureSet: + public StaticLocalDataSet { +public: + + static const size_t SIZE = 20; + + TemperatureSet(HasLocalDataPoolIF* owner): + StaticLocalDataSet(owner, TEMPERATURE_SET_ID) { + } + + TemperatureSet(object_id_t objectId): + StaticLocalDataSet(sid_t(objectId, TEMPERATURE_SET_ID)) { + } + + // Ticks is time reference generated by interanl counter of the star tracker + lp_var_t ticks = lp_var_t(sid.objectId, + PoolIds::TICKS_TEMPERATURE_SET, this); + /** Unix time in microseconds */ + lp_var_t time = lp_var_t(sid.objectId, + PoolIds::TIME_TEMPERATURE_SET, this); + lp_var_t mcuTemperature = lp_var_t(sid.objectId, + PoolIds::MCU_TEMPERATURE, this); + lp_var_t cmosTemperature = lp_var_t(sid.objectId, + PoolIds::CMOS_TEMPERATURE, this); + + void printSet() { + sif::info << "TemperatureSet::printSet: Ticks: " + << this->ticks << std::endl; + sif::info << "TemperatureSet::printSet: Time: " + << this->time << " us" << std::endl; + sif::info << "TemperatureSet::printSet: MCU Temperature: " + << this->mcuTemperature << " °C" << std::endl; + sif::info << "TemperatureSet::printSet: CMOS Temperature: " + << this->cmosTemperature << " °C" << std::endl; + } +}; + +/** + * @brief Package to store version parameters + */ +class VersionSet: + public StaticLocalDataSet { +public: + + static const size_t SIZE = 15; + + VersionSet(HasLocalDataPoolIF* owner): + StaticLocalDataSet(owner, VERSION_SET_ID) { + } + + VersionSet(object_id_t objectId): + StaticLocalDataSet(sid_t(objectId, VERSION_SET_ID)) { + } + + // Ticks is time reference generated by interanl counter of the star tracker + lp_var_t ticks = lp_var_t(sid.objectId, + PoolIds::TICKS_VERSION_SET, this); + /** Unix time in microseconds */ + lp_var_t time = lp_var_t(sid.objectId, + PoolIds::TIME_VERSION_SET, this); + lp_var_t program = lp_var_t(sid.objectId, + PoolIds::PROGRAM, this); + lp_var_t major = lp_var_t(sid.objectId, + PoolIds::MAJOR, this); + lp_var_t minor = lp_var_t(sid.objectId, + PoolIds::MINOR, this); + + void printSet() { + PoolReadGuard rg(this); + sif::info << "VersionSet::printSet: Ticks: " + << this->ticks << std::endl; + sif::info << "VersionSet::printSet: Unix Time: " + << this->time << " us" << std::endl; + sif::info << "VersionSet::printSet: Program: " + << static_cast(this->program.value) << std::endl; + sif::info << "VersionSet::printSet: Major: " + << static_cast(this->major.value) << std::endl; + sif::info << "VersionSet::printSet: Minor: " + << static_cast(this->minor.value) << std::endl; + } +}; + +/** + * @brief Dataset to store the interface telemtry data. + */ +class InterfaceSet: + public StaticLocalDataSet { +public: + + static const size_t SIZE = 20; + + InterfaceSet(HasLocalDataPoolIF* owner): + StaticLocalDataSet(owner, REQ_INTERFACE) { + } + + InterfaceSet(object_id_t objectId): + StaticLocalDataSet(sid_t(objectId, REQ_INTERFACE)) { + } + + // Ticks is time reference generated by interanl counter of the star tracker + lp_var_t ticks = lp_var_t(sid.objectId, + PoolIds::TICKS_INTERFACE_SET, this); + /** Unix time in microseconds */ + lp_var_t time = lp_var_t(sid.objectId, + PoolIds::TIME_INTERFACE_SET, this); + lp_var_t frameCount = lp_var_t(sid.objectId, + PoolIds::FRAME_COUNT, this); + lp_var_t checksumerrorCount = lp_var_t(sid.objectId, + PoolIds::CHECKSUM_ERROR_COUNT, this); + + void printSet() { + PoolReadGuard rg(this); + sif::info << "InterfaceSet::printSet: Ticks: " + << this->ticks << std::endl; + sif::info << "InterfaceSet::printSet: Time: " + << this->time << " us" << std::endl; + sif::info << "InterfaceSet::printSet: Frame Count: " + << this->frameCount << std::endl; + sif::info << "InterfaceSet::printSet: Checksum Error Count: " + << this->checksumerrorCount << std::endl; + } +}; + +/** + * @brief Dataset to store the data of the power telemetry reply. + */ +class PowerSet: + public StaticLocalDataSet { +public: + + static const size_t SIZE = 76; + + PowerSet(HasLocalDataPoolIF* owner): + StaticLocalDataSet(owner, REQ_INTERFACE) { + } + + PowerSet(object_id_t objectId): + StaticLocalDataSet(sid_t(objectId, REQ_INTERFACE)) { + } + + // Ticks is time reference generated by interanl counter of the star tracker + lp_var_t ticks = lp_var_t(sid.objectId, + PoolIds::TICKS_POWER_SET, this); + /** Unix time in microseconds */ + lp_var_t time = lp_var_t(sid.objectId, + PoolIds::TIME_POWER_SET, this); + lp_var_t mcuCurrent = lp_var_t(sid.objectId, + PoolIds::MCU_CURRENT, this); + lp_var_t mcuVoltage = lp_var_t(sid.objectId, + PoolIds::MCU_VOLTAGE, this); + lp_var_t fpgaCoreCurrent = lp_var_t(sid.objectId, + PoolIds::FPGA_CORE_CURRENT, this); + lp_var_t fpgaCoreVoltage = lp_var_t(sid.objectId, + PoolIds::FPGA_CORE_VOLTAGE, this); + lp_var_t fpga18Current = lp_var_t(sid.objectId, + PoolIds::FPGA_18_CURRENT, this); + lp_var_t fpga18Voltage = lp_var_t(sid.objectId, + PoolIds::FPGA_18_VOLTAGE, this); + lp_var_t fpga25Current = lp_var_t(sid.objectId, + PoolIds::FPGA_25_CURRENT, this); + lp_var_t fpga25Voltage = lp_var_t(sid.objectId, + PoolIds::FPGA_25_VOLTAGE, this); + lp_var_t cmv21Current = lp_var_t(sid.objectId, + PoolIds::CMV_21_CURRENT, this); + lp_var_t cmv21Voltage = lp_var_t(sid.objectId, + PoolIds::CMV_21_VOLTAGE, this); + lp_var_t cmvPixCurrent = lp_var_t(sid.objectId, + PoolIds::CMV_PIX_CURRENT, this); + lp_var_t cmvPixVoltage = lp_var_t(sid.objectId, + PoolIds::CMV_PIX_VOLTAGE, this); + lp_var_t cmv33Current = lp_var_t(sid.objectId, + PoolIds::CMV_33_CURRENT, this); + lp_var_t cmv33Voltage = lp_var_t(sid.objectId, + PoolIds::CMV_33_VOLTAGE, this); + lp_var_t cmvResCurrent = lp_var_t(sid.objectId, + PoolIds::CMV_RES_CURRENT, this); + lp_var_t cmvResVoltage = lp_var_t(sid.objectId, + PoolIds::CMV_RES_VOLTAGE, this); + + void printSet() { + PoolReadGuard rg(this); + sif::info << "PowerSet::printSet: Ticks: " + << this->ticks << std::endl; + sif::info << "PowerSet::printSet: Time: " + << this->time << " us" << std::endl; + sif::info << "PowerSet::printSet: MCU Current: " + << this->mcuCurrent << " A" << std::endl; + sif::info << "PowerSet::printSet: MCU Voltage: " + << this->mcuVoltage << " V" << std::endl; + sif::info << "PowerSet::printSet: FPGA Core current: " + << this->fpgaCoreCurrent << " A" << std::endl; + sif::info << "PowerSet::printSet: FPGA Core voltage: " + << this->fpgaCoreVoltage << " V" << std::endl; + sif::info << "PowerSet::printSet: FPGA 18 current: " + << this->fpga18Current << " A" << std::endl; + sif::info << "PowerSet::printSet: FPGA 18 voltage: " + << this->fpga18Voltage << " V" << std::endl; + sif::info << "PowerSet::printSet: FPGA 25 current: " + << this->fpga25Current << " A" << std::endl; + sif::info << "PowerSet::printSet: FPGA 25 voltage: " + << this->fpga25Voltage << " V" << std::endl; + sif::info << "PowerSet::printSet: CMV 21 current: " + << this->cmv21Current << " A" << std::endl; + sif::info << "PowerSet::printSet: CMV 21 voltage: " + << this->cmv21Voltage << " V" << std::endl; + sif::info << "PowerSet::printSet: CMV Pix current: " + << this->cmvPixCurrent << " A" << std::endl; + sif::info << "PowerSet::printSet: CMV Pix voltage: " + << this->cmvPixVoltage << " V" << std::endl; + sif::info << "PowerSet::printSet: CMV 33 current: " + << this->cmv33Current << " A" << std::endl; + sif::info << "PowerSet::printSet: CMV 33 voltage: " + << this->cmv33Voltage << " V" << std::endl; + sif::info << "PowerSet::printSet: CMV Res current: " + << this->cmvResCurrent << " A" << std::endl; + sif::info << "PowerSet::printSet: CMV Res voltage: " + << this->cmvResVoltage << " V" << std::endl; + } +}; + +/** + * @brief Data set to store the time telemetry packet. + */ +class TimeSet: + public StaticLocalDataSet { +public: + + static const size_t SIZE = 24; + + TimeSet(HasLocalDataPoolIF* owner): + StaticLocalDataSet(owner, TIME_SET_ID) { + } + + TimeSet(object_id_t objectId): + StaticLocalDataSet(sid_t(objectId, TIME_SET_ID)) { + } + + lp_var_t ticks = lp_var_t(sid.objectId, + PoolIds::TICKS_TIME_SET, this); + /** Unix time in microseconds */ + lp_var_t time = lp_var_t(sid.objectId, + PoolIds::TIME_TIME_SET, this); + // Number of milliseconds since processor start-up + lp_var_t runTime = lp_var_t(sid.objectId, + PoolIds::RUN_TIME, this); + // Unix time in seconds?? --> maybe typo in datasheet. Seems to be microseconds + lp_var_t unixTime = lp_var_t(sid.objectId, + PoolIds::UNIX_TIME, this); + void printSet() { + PoolReadGuard rg(this); + sif::info << "TimeSet::printSet: Ticks: " + << this->ticks << std::endl; + sif::info << "TimeSet::printSet: Time (time stamp): " + << this->time << " us" << std::endl; + sif::info << "TimeSet::printSet: Run Time: " + << this->runTime << " ms" << std::endl; + sif::info << "TimeSet::printSet: Unix Time: " + << this->unixTime << " s" << std::endl; + } +}; + +/** + * @brief The solution dataset is the main dataset of the star tracker and contains the + * attitude information. + */ +class SolutionSet: + public StaticLocalDataSet { +public: + + static const size_t SIZE = 78; + + SolutionSet(HasLocalDataPoolIF* owner): + StaticLocalDataSet(owner, SOLUTION_SET_ID) { + } + + SolutionSet(object_id_t objectId): + StaticLocalDataSet(sid_t(objectId, SOLUTION_SET_ID)) { + } + + // Ticks timestamp + lp_var_t ticks = lp_var_t(sid.objectId, + PoolIds::TICKS_SOLUTION_SET, this); + /// Unix time stamp + lp_var_t time = lp_var_t(sid.objectId, + PoolIds::TIME_SOLUTION_SET, this); + // Calibrated quaternion (takes into account the mounting quaternion), typically same as + // track q values + lp_var_t caliQw = lp_var_t(sid.objectId, PoolIds::CALI_QW, this); + lp_var_t caliQx = lp_var_t(sid.objectId, PoolIds::CALI_QX, this); + lp_var_t caliQy = lp_var_t(sid.objectId, PoolIds::CALI_QY, this); + lp_var_t caliQz = lp_var_t(sid.objectId, PoolIds::CALI_QZ, this); + // The lower this value the more confidence that the star tracker solution is correct + lp_var_t trackConfidence = lp_var_t(sid.objectId, PoolIds::TRACK_CONFIDENCE, + this); + // Estimated attitude of spacecraft + lp_var_t trackQw = lp_var_t(sid.objectId, PoolIds::TRACK_QW, this); + lp_var_t trackQx = lp_var_t(sid.objectId, PoolIds::TRACK_QX, this); + lp_var_t trackQy = lp_var_t(sid.objectId, PoolIds::TRACK_QY, this); + lp_var_t trackQz = lp_var_t(sid.objectId, PoolIds::TRACK_QZ, this); + // Number of stars removed from tracking solution + lp_var_t trackRemoved = lp_var_t(sid.objectId, PoolIds::TRACK_REMOVED, this); + // Number of stars for which a valid centroid was found + lp_var_t starsCentroided = lp_var_t(sid.objectId, PoolIds::STARS_CENTROIDED, + this); + // Number of stars that matched to a database star + lp_var_t starsMatchedDatabase = lp_var_t(sid.objectId, + PoolIds::STARS_MATCHED_DATABASE, this); + // Result of LISA (lost in space algorithm), searches for stars without prior knowledge of + // attitude + lp_var_t lisaQw = lp_var_t(sid.objectId, PoolIds::LISA_QW, this); + lp_var_t lisaQx = lp_var_t(sid.objectId, PoolIds::LISA_QX, this); + lp_var_t lisaQy = lp_var_t(sid.objectId, PoolIds::LISA_QY, this); + lp_var_t lisaQz = lp_var_t(sid.objectId, PoolIds::LISA_QZ, this); + // Percentage of close stars in LISA solution + lp_var_t lisaPercentageClose = lp_var_t(sid.objectId, PoolIds::LISA_PERC_CLOSE, + this); + // Number of close stars in LISA solution + lp_var_t lisaNrClose = lp_var_t(sid.objectId, PoolIds::LISA_NR_CLOSE, this); + // Gives a combined overview of the validation parameters (1 for valid solution, otherwise 0) + lp_var_t isTrustWorthy = lp_var_t(sid.objectId, PoolIds::TRUST_WORTHY, this); + // Number of times the validation criteria was met + lp_var_t stableCount = lp_var_t(sid.objectId, PoolIds::STABLE_COUNT, this); + // Shows the autonomous mode used to obtain the star tracker attitude + lp_var_t solutionStrategy = lp_var_t(sid.objectId, PoolIds::SOLUTION_STRATEGY, + this); + + void printSet() { + PoolReadGuard rg(this); + sif::info << "SolutionSet::printSet: Ticks: " + << this->ticks << std::endl; + sif::info << "SolutionSet::printSet: Time: " + << this->time << std::endl; + sif::info << "SolutionSet::printSet: Calibrated quaternion Qw: " + << this->caliQw << std::endl; + sif::info << "SolutionSet::printSet: Calibrated quaternion Qx: " + << this->caliQx << std::endl; + sif::info << "SolutionSet::printSet: Calibrated quaternion Qy: " + << this->caliQy << std::endl; + sif::info << "SolutionSet::printSet: Calibrated quaternion Qz: " + << this->caliQz << std::endl; + sif::info << "SolutionSet::printSet: Track confidence: " + << this->trackConfidence << std::endl; + sif::info << "SolutionSet::printSet: Track Qw: " + << this->trackQw << std::endl; + sif::info << "SolutionSet::printSet: Track Qx: " + << this->trackQx << std::endl; + sif::info << "SolutionSet::printSet: Track Qy: " + << this->trackQy << std::endl; + sif::info << "SolutionSet::printSet: Track Qz: " + << this->trackQz << std::endl; + sif::info << "SolutionSet::printSet: Track removed: " + << static_cast(this->trackRemoved.value) << std::endl; + sif::info << "SolutionSet::printSet: Number of stars centroided: " + << static_cast(this->starsCentroided.value) << std::endl; + sif::info << "SolutionSet::printSet: Number of stars matched database: " + << static_cast(this->starsMatchedDatabase.value) << std::endl; + sif::info << "SolutionSet::printSet: LISA Qw: " + << this->lisaQw << std::endl; + sif::info << "SolutionSet::printSet: LISA Qx: " + << this->lisaQx << std::endl; + sif::info << "SolutionSet::printSet: LISA Qy: " + << this->lisaQy << std::endl; + sif::info << "SolutionSet::printSet: LISA Qz: " + << this->lisaQz << std::endl; + sif::info << "SolutionSet::printSet: LISA Percentage close: " + << this->lisaPercentageClose << std::endl; + sif::info << "SolutionSet::printSet: LISA number of close stars: " + << static_cast(this->lisaNrClose.value) << std::endl; + sif::info << "SolutionSet::printSet: Is trust worthy: " + << static_cast(this->isTrustWorthy.value) << std::endl; + sif::info << "SolutionSet::printSet: Stable count: " + << this->stableCount << std::endl; + sif::info << "SolutionSet::printSet: Solution strategy: " + << static_cast(this->solutionStrategy.value) << std::endl; + } +}; + +/** + * @brief Dataset to store the histogram + */ +class HistogramSet: + public StaticLocalDataSet { +public: + + // Size of dataset + static const size_t SIZE = 156; + + HistogramSet(HasLocalDataPoolIF* owner): + StaticLocalDataSet(owner, HISTOGRAM_SET_ID) { + } + + HistogramSet(object_id_t objectId): + StaticLocalDataSet(sid_t(objectId, HISTOGRAM_SET_ID)) { + } + + lp_var_t ticks = lp_var_t(sid.objectId, PoolIds::TICKS_HISTOGRAM_SET, this); + lp_var_t time = lp_var_t(sid.objectId, PoolIds::TIME_HISTOGRAM_SET, this); + lp_var_t binA0 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINA0, this); + lp_var_t binA1 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINA1, this); + lp_var_t binA2 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINA2, this); + lp_var_t binA3 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINA3, this); + lp_var_t binA4 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINA4, this); + lp_var_t binA5 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINA5, this); + lp_var_t binA6 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINA6, this); + lp_var_t binA7 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINA7, this); + lp_var_t binA8 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINA8, this); + lp_var_t binB0 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINB0, this); + lp_var_t binB1 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINB1, this); + lp_var_t binB2 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINB2, this); + lp_var_t binB3 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINB3, this); + lp_var_t binB4 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINB4, this); + lp_var_t binB5 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINB5, this); + lp_var_t binB6 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINB6, this); + lp_var_t binB7 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINB7, this); + lp_var_t binB8 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINB8, this); + lp_var_t binC0 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINC0, this); + lp_var_t binC1 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINC1, this); + lp_var_t binC2 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINC2, this); + lp_var_t binC3 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINC3, this); + lp_var_t binC4 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINC4, this); + lp_var_t binC5 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINC5, this); + lp_var_t binC6 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINC6, this); + lp_var_t binC7 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINC7, this); + lp_var_t binC8 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BINC8, this); + lp_var_t binD0 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BIND0, this); + lp_var_t binD1 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BIND1, this); + lp_var_t binD2 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BIND2, this); + lp_var_t binD3 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BIND3, this); + lp_var_t binD4 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BIND4, this); + lp_var_t binD5 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BIND5, this); + lp_var_t binD6 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BIND6, this); + lp_var_t binD7 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BIND7, this); + lp_var_t binD8 = lp_var_t(sid.objectId, PoolIds::HISTOGRAM_BIND8, this); + + void printSet() { + PoolReadGuard rg(this); + sif::info << "HistogramSet::printSet: Ticks: " << this->ticks << std::endl; + sif::info << "HistogramSet::printSet: Time (time stamp): " << this->time << " us" + << std::endl; + sif::info << "HistogramSet::printSet: BinA0: " << this->binA0 << std::endl; + sif::info << "HistogramSet::printSet: BinA1: " << this->binA1 << std::endl; + sif::info << "HistogramSet::printSet: BinA2: " << this->binA2 << std::endl; + sif::info << "HistogramSet::printSet: BinA3: " << this->binA3 << std::endl; + sif::info << "HistogramSet::printSet: BinA4: " << this->binA4 << std::endl; + sif::info << "HistogramSet::printSet: BinA5: " << this->binA5 << std::endl; + sif::info << "HistogramSet::printSet: BinA6: " << this->binA6 << std::endl; + sif::info << "HistogramSet::printSet: BinA7: " << this->binA7 << std::endl; + sif::info << "HistogramSet::printSet: BinA8: " << this->binA8 << std::endl; + sif::info << "HistogramSet::printSet: BinB0: " << this->binB0 << std::endl; + sif::info << "HistogramSet::printSet: BinB1: " << this->binB1 << std::endl; + sif::info << "HistogramSet::printSet: BinB2: " << this->binB2 << std::endl; + sif::info << "HistogramSet::printSet: BinB3: " << this->binB3 << std::endl; + sif::info << "HistogramSet::printSet: BinB4: " << this->binB4 << std::endl; + sif::info << "HistogramSet::printSet: BinB5: " << this->binB5 << std::endl; + sif::info << "HistogramSet::printSet: BinB6: " << this->binB6 << std::endl; + sif::info << "HistogramSet::printSet: BinB7: " << this->binB7 << std::endl; + sif::info << "HistogramSet::printSet: BinB8: " << this->binB8 << std::endl; + sif::info << "HistogramSet::printSet: BinC0: " << this->binC0 << std::endl; + sif::info << "HistogramSet::printSet: BinC1: " << this->binC1 << std::endl; + sif::info << "HistogramSet::printSet: BinC2: " << this->binC2 << std::endl; + sif::info << "HistogramSet::printSet: BinC3: " << this->binC3 << std::endl; + sif::info << "HistogramSet::printSet: BinC4: " << this->binC4 << std::endl; + sif::info << "HistogramSet::printSet: BinC5: " << this->binC5 << std::endl; + sif::info << "HistogramSet::printSet: BinC6: " << this->binC6 << std::endl; + sif::info << "HistogramSet::printSet: BinC7: " << this->binC7 << std::endl; + sif::info << "HistogramSet::printSet: BinC8: " << this->binC8 << std::endl; + sif::info << "HistogramSet::printSet: BinD0: " << this->binD0 << std::endl; + sif::info << "HistogramSet::printSet: BinD1: " << this->binD1 << std::endl; + sif::info << "HistogramSet::printSet: BinD2: " << this->binD2 << std::endl; + sif::info << "HistogramSet::printSet: BinD3: " << this->binD3 << std::endl; + sif::info << "HistogramSet::printSet: BinD4: " << this->binD4 << std::endl; + sif::info << "HistogramSet::printSet: BinD5: " << this->binD5 << std::endl; + sif::info << "HistogramSet::printSet: BinD6: " << this->binD6 << std::endl; + sif::info << "HistogramSet::printSet: BinD7: " << this->binD7 << std::endl; + sif::info << "HistogramSet::printSet: BinD8: " << this->binD8 << std::endl; + } +}; + +/** + * @brief Dataset to store the contrast telemetry data + */ +class ContrastSet: + public StaticLocalDataSet { +public: + + // Size of dataset + static const size_t SIZE = 156; + + ContrastSet(HasLocalDataPoolIF* owner): + StaticLocalDataSet(owner, CONTRAST_SET_ID) { + } + + ContrastSet(object_id_t objectId): + StaticLocalDataSet(sid_t(objectId, CONTRAST_SET_ID)) { + } + + lp_var_t ticks = lp_var_t(sid.objectId, PoolIds::TICKS_CONTRAST_SET, this); + lp_var_t time = lp_var_t(sid.objectId, PoolIds::TIME_CONTRAST_SET, this); + lp_var_t binA0 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINA0, this); + lp_var_t binA1 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINA1, this); + lp_var_t binA2 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINA2, this); + lp_var_t binA3 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINA3, this); + lp_var_t binA4 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINA4, this); + lp_var_t binA5 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINA5, this); + lp_var_t binA6 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINA6, this); + lp_var_t binA7 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINA7, this); + lp_var_t binA8 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINA8, this); + lp_var_t binb0 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINB0, this); + lp_var_t binB1 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINB1, this); + lp_var_t binB2 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINB2, this); + lp_var_t binB3 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINB3, this); + lp_var_t binB4 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINB4, this); + lp_var_t binB5 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINB5, this); + lp_var_t binB6 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINB6, this); + lp_var_t binB7 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINB7, this); + lp_var_t binB8 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINB8, this); + lp_var_t binC0 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINC0, this); + lp_var_t binC1 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINC1, this); + lp_var_t binC2 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINC2, this); + lp_var_t binC3 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINC3, this); + lp_var_t binC4 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINC4, this); + lp_var_t binC5 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINC5, this); + lp_var_t binC6 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINC6, this); + lp_var_t binC7 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINC7, this); + lp_var_t binC8 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BINC8, this); + lp_var_t binD0 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BIND0, this); + lp_var_t binD1 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BIND1, this); + lp_var_t binD2 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BIND2, this); + lp_var_t binD3 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BIND3, this); + lp_var_t binD4 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BIND4, this); + lp_var_t binD5 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BIND5, this); + lp_var_t binD6 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BIND6, this); + lp_var_t binD7 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BIND7, this); + lp_var_t binD8 = lp_var_t(sid.objectId, PoolIds::CONTRAST_BIND8, this); + + void printSet() { + PoolReadGuard rg(this); + sif::info << "ContrastSet::printSet: Ticks: " << this->ticks << std::endl; + sif::info << "ContrastSet::printSet: Time (time stamp): " << this->time << " us" + << std::endl; + sif::info << "ContrastSet::printSet: BinA0: " << this->binA0 << std::endl; + sif::info << "ContrastSet::printSet: BinA1: " << this->binA1 << std::endl; + sif::info << "ContrastSet::printSet: BinA2: " << this->binA2 << std::endl; + sif::info << "ContrastSet::printSet: BinA3: " << this->binA3 << std::endl; + sif::info << "ContrastSet::printSet: BinA4: " << this->binA4 << std::endl; + sif::info << "ContrastSet::printSet: BinA5: " << this->binA5 << std::endl; + sif::info << "ContrastSet::printSet: BinA6: " << this->binA6 << std::endl; + sif::info << "ContrastSet::printSet: BinA7: " << this->binA7 << std::endl; + sif::info << "ContrastSet::printSet: BinA8: " << this->binA8 << std::endl; + sif::info << "ContrastSet::printSet: BinB0: " << this->binA0 << std::endl; + sif::info << "ContrastSet::printSet: BinB1: " << this->binB1 << std::endl; + sif::info << "ContrastSet::printSet: BinB2: " << this->binB2 << std::endl; + sif::info << "ContrastSet::printSet: BinB3: " << this->binB3 << std::endl; + sif::info << "ContrastSet::printSet: BinB4: " << this->binB4 << std::endl; + sif::info << "ContrastSet::printSet: BinB5: " << this->binB5 << std::endl; + sif::info << "ContrastSet::printSet: BinB6: " << this->binB6 << std::endl; + sif::info << "ContrastSet::printSet: BinB7: " << this->binB7 << std::endl; + sif::info << "ContrastSet::printSet: BinB8: " << this->binB8 << std::endl; + sif::info << "ContrastSet::printSet: BinC0: " << this->binC0 << std::endl; + sif::info << "ContrastSet::printSet: BinC1: " << this->binC1 << std::endl; + sif::info << "ContrastSet::printSet: BinC2: " << this->binC2 << std::endl; + sif::info << "ContrastSet::printSet: BinC3: " << this->binC3 << std::endl; + sif::info << "ContrastSet::printSet: BinC4: " << this->binC4 << std::endl; + sif::info << "ContrastSet::printSet: BinC5: " << this->binC5 << std::endl; + sif::info << "ContrastSet::printSet: BinC6: " << this->binC6 << std::endl; + sif::info << "ContrastSet::printSet: BinC7: " << this->binC7 << std::endl; + sif::info << "ContrastSet::printSet: BinC8: " << this->binC8 << std::endl; + sif::info << "ContrastSet::printSet: BinD0: " << this->binD0 << std::endl; + sif::info << "ContrastSet::printSet: BinD1: " << this->binD1 << std::endl; + sif::info << "ContrastSet::printSet: BinD2: " << this->binD2 << std::endl; + sif::info << "ContrastSet::printSet: BinD3: " << this->binD3 << std::endl; + sif::info << "ContrastSet::printSet: BinD4: " << this->binD4 << std::endl; + sif::info << "ContrastSet::printSet: BinD5: " << this->binD5 << std::endl; + sif::info << "ContrastSet::printSet: BinD6: " << this->binD6 << std::endl; + sif::info << "ContrastSet::printSet: BinD7: " << this->binD7 << std::endl; + sif::info << "ContrastSet::printSet: BinD8: " << this->binD8 << std::endl; + } +}; +} + +#endif /* MISSION_STARTRACKER_DEFINITIONS_H_ */ diff --git a/bsp_q7s/devices/startracker/StarTrackerHandler.cpp b/bsp_q7s/devices/startracker/StarTrackerHandler.cpp new file mode 100644 index 00000000..bb9018be --- /dev/null +++ b/bsp_q7s/devices/startracker/StarTrackerHandler.cpp @@ -0,0 +1,1283 @@ +#include + +#include "StarTrackerHandler.h" +#include "OBSWConfig.h" +#include "StarTrackerJsonCommands.h" + +#include +#include + +extern "C" { + #include + #include + #include "common/misc.h" +} + +StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF, + CookieIF * comCookie, StrHelper* strHelper) : + DeviceHandlerBase(objectId, comIF, comCookie), temperatureSet(this), versionSet(this), powerSet( + this), interfaceSet(this), timeSet(this), solutionSet(this), histogramSet(this), + contrastSet(this), strHelper(strHelper) { + if (comCookie == nullptr) { + sif::error << "StarTrackerHandler: Invalid com cookie" << std::endl; + } + if (strHelper == nullptr) { + sif::error << "StarTrackerHandler: Invalid str image loader" << std::endl; + } + eventQueue = QueueFactory::instance()->createMessageQueue(EventMessage::EVENT_MESSAGE_SIZE * 5); +} + +StarTrackerHandler::~StarTrackerHandler() { +} + +ReturnValue_t StarTrackerHandler::initialize() { + ReturnValue_t result = RETURN_OK; + result = DeviceHandlerBase::initialize(); + if (result != RETURN_OK) { + return result; + } + + EventManagerIF* manager = ObjectManager::instance()->get( + objects::EVENT_MANAGER); + if (manager == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "StarTrackerHandler::initialize: Invalid event manager" << std::endl; +#endif + return ObjectManagerIF::CHILD_INIT_FAILED;; + } + result = manager->registerListener(eventQueue->getId()); + if (result != RETURN_OK) { + return result; + } + result = manager->subscribeToEventRange(eventQueue->getId(), + event::getEventId(StrHelper::IMAGE_UPLOAD_FAILED), + event::getEventId(StrHelper::FLASH_READ_FAILED)); + if (result != RETURN_OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "StarTrackerHandler::initialize: Failed to subscribe to events from " + " str helper" << std::endl; +#endif + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + result = strHelper->setComIF(communicationInterface); + if (result != RETURN_OK) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + strHelper->setComCookie(comCookie); + return RETURN_OK; +} + +ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) { + + ReturnValue_t result = RETURN_OK; + + switch(actionId) { + case(StarTracker::STOP_IMAGE_LOADER): { + strHelper->stopProcess(); + return EXECUTION_FINISHED; + } + case(StarTracker::SET_JSON_FILE_NAME): { + if (size > MAX_PATH_SIZE) { + return FILE_PATH_TOO_LONG; + } + paramJsonFile = std::string(reinterpret_cast(data), size); + return EXECUTION_FINISHED; + } + default: + break; + } + + if (strHelperExecuting == true) { + return IMAGE_LOADER_EXECUTING; + } + + result = checkMode(actionId); + if (result != RETURN_OK) { + return result; + } + + // Intercept image loader commands which do not follow the common DHB communication flow + switch(actionId) { + case(StarTracker::UPLOAD_IMAGE): { + result = DeviceHandlerBase::acceptExternalDeviceCommands(); + if (result != RETURN_OK) { + return result; + } + if (size > MAX_PATH_SIZE) { + return FILE_PATH_TOO_LONG; + } + result = strHelper->startImageUpload( + std::string(reinterpret_cast(data), size)); + if (result != RETURN_OK) { + return result; + } + strHelperExecuting = true; + return EXECUTION_FINISHED; + } + case(StarTracker::DOWNLOAD_IMAGE): { + result = DeviceHandlerBase::acceptExternalDeviceCommands(); + if (result != RETURN_OK) { + return result; + } + if (size > MAX_PATH_SIZE) { + return FILE_PATH_TOO_LONG; + } + result = strHelper->startImageDownload( + std::string(reinterpret_cast(data), size)); + if (result != RETURN_OK) { + return result; + } + strHelperExecuting = true; + return EXECUTION_FINISHED; + } + case(StarTracker::WRITE): { + result = DeviceHandlerBase::acceptExternalDeviceCommands(); + if (result != RETURN_OK) { + return result; + } + result = executeWriteCommand(data, size); + if (result != RETURN_OK) { + return result; + } + + strHelperExecuting = true; + return EXECUTION_FINISHED; + } + case(StarTracker::CHANGE_DOWNLOAD_FILE): { + if (size > MAX_FILE_NAME) { + return FILENAME_TOO_LONG; + } + strHelper->setDownloadImageName( + std::string(reinterpret_cast(data), size)); + return EXECUTION_FINISHED; + } + default: + break; + } + return DeviceHandlerBase::executeAction(actionId, commandedBy, data, size); +} + +void StarTrackerHandler::performOperationHook() { + EventMessage event; + for (ReturnValue_t result = eventQueue->receiveMessage(&event); + result == RETURN_OK; result = eventQueue->receiveMessage(&event)) { + switch (event.getMessageId()) { + case EventMessage::EVENT_MESSAGE: + handleEvent(&event); + break; + default: + sif::debug << "CCSDSHandler::checkEvents: Did not subscribe to this event message" + << std::endl; + break; + } + } +} + +void StarTrackerHandler::doStartUp() { + switch(startupState) { + case StartupState::IDLE: + startupState = StartupState::CHECK_BOOT_STATE; + return; + case StartupState::BOOT_DELAY: + if (bootCountdown.hasTimedOut()) { + startupState = StartupState::LIMITS; + } + return; + case StartupState::DONE: + break; + default: + return; + } + setMode(_MODE_TO_ON); +} + +void StarTrackerHandler::doShutDown() { + // If star tracker is shutdown also stop all running processes in the image loader task + strHelper->stopProcess(); + setMode(_MODE_POWER_DOWN); +} + +void StarTrackerHandler::doOffActivity() { + startupState = StartupState::IDLE; +} + +ReturnValue_t StarTrackerHandler::buildNormalDeviceCommand(DeviceCommandId_t * id) { + switch (internalState) { + case InternalState::TEMPERATURE_REQUEST: + *id = StarTracker::REQ_TEMPERATURE; + break; + default: + sif::debug << "StarTrackerHandler::buildNormalDeviceCommand: Invalid internal step" + << std::endl; + break; + } + return buildCommandFromCommand(*id, NULL, 0); +} + +ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t * id) { + if (mode != _MODE_START_UP) { + return NOTHING_TO_SEND; + } + switch (startupState) { + case StartupState::CHECK_BOOT_STATE: + *id = StarTracker::REQ_VERSION; + startupState = StartupState::WAIT_FOR_EXECUTION; + return buildCommandFromCommand(*id, nullptr, 0); + case StartupState::BOOT: + *id = StarTracker::BOOT; + bootCountdown.setTimeout(BOOT_TIMEOUT); + startupState = StartupState::BOOT_DELAY; + return buildCommandFromCommand(*id, nullptr, 0); + case StartupState::LIMITS: + startupState = StartupState::WAIT_FOR_EXECUTION; + *id = StarTracker::LIMITS; + return buildCommandFromCommand(*id, reinterpret_cast(paramJsonFile.c_str()), + paramJsonFile.size()); + case StartupState::TRACKING: + startupState = StartupState::WAIT_FOR_EXECUTION; + *id = StarTracker::TRACKING; + return buildCommandFromCommand(*id, reinterpret_cast(paramJsonFile.c_str()), + paramJsonFile.size()); + case StartupState::MOUNTING: + startupState = StartupState::WAIT_FOR_EXECUTION; + *id = StarTracker::MOUNTING; + return buildCommandFromCommand(*id, reinterpret_cast(paramJsonFile.c_str()), + paramJsonFile.size()); + case StartupState::CAMERA: + startupState = StartupState::WAIT_FOR_EXECUTION; + *id = StarTracker::CAMERA; + return buildCommandFromCommand(*id, reinterpret_cast(paramJsonFile.c_str()), + paramJsonFile.size()); + case StartupState::BLOB: + startupState = StartupState::WAIT_FOR_EXECUTION; + *id = StarTracker::BLOB; + return buildCommandFromCommand(*id, reinterpret_cast(paramJsonFile.c_str()), + paramJsonFile.size()); + case StartupState::CENTROIDING: + startupState = StartupState::WAIT_FOR_EXECUTION; + *id = StarTracker::CENTROIDING; + return buildCommandFromCommand(*id, reinterpret_cast(paramJsonFile.c_str()), + paramJsonFile.size()); + case StartupState::LISA: + startupState = StartupState::WAIT_FOR_EXECUTION; + *id = StarTracker::LISA; + return buildCommandFromCommand(*id, reinterpret_cast(paramJsonFile.c_str()), + paramJsonFile.size()); + case StartupState::MATCHING: + startupState = StartupState::WAIT_FOR_EXECUTION; + *id = StarTracker::MATCHING; + return buildCommandFromCommand(*id, reinterpret_cast(paramJsonFile.c_str()), + paramJsonFile.size()); + case StartupState::VALIDATION: + startupState = StartupState::WAIT_FOR_EXECUTION; + *id = StarTracker::VALIDATION; + return buildCommandFromCommand(*id, reinterpret_cast(paramJsonFile.c_str()), + paramJsonFile.size()); + case StartupState::ALGO: + startupState = StartupState::WAIT_FOR_EXECUTION; + *id = StarTracker::ALGO; + return buildCommandFromCommand(*id, reinterpret_cast(paramJsonFile.c_str()), + paramJsonFile.size()); + default: + break; + } + return NOTHING_TO_SEND; +} + +ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand, + const uint8_t * commandData, size_t commandDataLen) { + ReturnValue_t result = RETURN_OK; + switch (deviceCommand) { + case (StarTracker::PING_REQUEST): { + preparePingRequest(); + return RETURN_OK; + } + case (StarTracker::REQ_TIME): { + prepareTimeRequest(); + return RETURN_OK; + } + case (StarTracker::BOOT): { + prepareBootCommand(); + return RETURN_OK; + } + case (StarTracker::REQ_VERSION): { + prepareVersionRequest(); + return RETURN_OK; + } + case (StarTracker::REQ_INTERFACE): { + prepareInterfaceRequest(); + return RETURN_OK; + } + case (StarTracker::REQ_POWER): { + preparePowerRequest(); + return RETURN_OK; + } + case (StarTracker::SWITCH_TO_BOOTLOADER_PROGRAM): { + prepareRebootCommand(); + return RETURN_OK; + } + case (StarTracker::TAKE_IMAGE): { + prepareTakeImageCommand(commandData); + return RETURN_OK; + } + case (StarTracker::SUBSCRIBE_TO_TM): { + prepareSubscriptionCommand(commandData); + return RETURN_OK; + } + case (StarTracker::REQ_SOLUTION): { + prepareSolutionRequest(); + return RETURN_OK; + } + case (StarTracker::REQ_TEMPERATURE): { + prepareTemperatureRequest(); + return RETURN_OK; + } + case (StarTracker::REQ_HISTOGRAM): { + prepareHistogramRequest(); + return RETURN_OK; + } + case (StarTracker::REQ_CONTRAST): { + prepareContrastRequest(); + return RETURN_OK; + } + case (StarTracker::RESET_ERROR): { + prepareErrorResetRequest(); + return RETURN_OK; + } + case (StarTracker::LIMITS): { + Limits limits; + result = prepareParamCommand(commandData, commandDataLen, limits); + return result; + } + case (StarTracker::MOUNTING): { + Mounting mounting; + result = prepareParamCommand(commandData, commandDataLen, mounting); + return result; + } + case (StarTracker::CAMERA): { + Camera camera; + result = prepareParamCommand(commandData, commandDataLen, camera); + return result; + } + case (StarTracker::BLOB): { + Blob blob; + result = prepareParamCommand(commandData, commandDataLen, blob); + return result; + } + case (StarTracker::CENTROIDING): { + Centroiding centroiding; + result = prepareParamCommand(commandData, commandDataLen, centroiding); + return result; + } + case (StarTracker::LISA): { + Lisa lisa; + result = prepareParamCommand(commandData, commandDataLen, lisa); + return result; + } + case (StarTracker::MATCHING): { + Matching matching; + result = prepareParamCommand(commandData, commandDataLen, matching); + return result; + } + case (StarTracker::VALIDATION): { + Validation validation; + result = prepareParamCommand(commandData, commandDataLen, validation); + return result; + } + case (StarTracker::ALGO): { + Algo algo; + result = prepareParamCommand(commandData, commandDataLen, algo); + return result; + } + case (StarTracker::TRACKING): { + Tracking tracking; + result = prepareParamCommand(commandData, commandDataLen, tracking); + return result; + } + default: + return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; + } + return HasReturnvaluesIF::RETURN_FAILED; +} + +void StarTrackerHandler::fillCommandAndReplyMap() { + /** Reply lengths are unknown because of the slip encoding. Thus always maximum reply size + * is specified */ + this->insertInCommandAndReplyMap(StarTracker::PING_REQUEST, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandMap(StarTracker::BOOT); + this->insertInCommandAndReplyMap(StarTracker::REQ_VERSION, 3, &versionSet, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::REQ_TIME, 3, &timeSet, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandMap(StarTracker::UPLOAD_IMAGE); + this->insertInCommandMap(StarTracker::DOWNLOAD_IMAGE); + this->insertInCommandAndReplyMap(StarTracker::REQ_POWER, 3, &powerSet, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::REQ_INTERFACE, 3, &interfaceSet, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + // Reboot has no reply. Star tracker reboots immediately + this->insertInCommandMap(StarTracker::SWITCH_TO_BOOTLOADER_PROGRAM); + this->insertInCommandAndReplyMap(StarTracker::SUBSCRIBE_TO_TM, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::REQ_SOLUTION, 3, &solutionSet, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::REQ_TEMPERATURE, 3, &temperatureSet, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::REQ_HISTOGRAM, 3, &histogramSet, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::REQ_CONTRAST, 3, &contrastSet, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::LIMITS, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::MOUNTING, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::CAMERA, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::BLOB, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::CENTROIDING, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::LISA, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::MATCHING, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::TRACKING, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::VALIDATION, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::ALGO, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::TAKE_IMAGE, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::RESET_ERROR, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); +} + +ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t *start, size_t remainingSize, + DeviceCommandId_t *foundId, size_t *foundLen) { + + ReturnValue_t result = RETURN_OK; + size_t bytesLeft = 0; + + result = dataLinkLayer.decodeFrame(start, remainingSize, &bytesLeft); + switch(result) { + case ArcsecDatalinkLayer::DEC_IN_PROGRESS: { + remainingSize = bytesLeft; + // Need a second doSendRead pass to reaa in whole packet + return IGNORE_REPLY_DATA; + } + case RETURN_OK: { + break; + } + default: + remainingSize = bytesLeft; + return result; + } + + switch (dataLinkLayer.getReplyFrameType()) { + case TMTC_ACTIONREPLY: { + *foundLen = remainingSize - bytesLeft; + result = scanForActionReply(foundId); + break; + } + case TMTC_SETPARAMREPLY: { + *foundLen = remainingSize - bytesLeft; + result = scanForParameterReply(foundId); + break; + } + case TMTC_TELEMETRYREPLYA: + case TMTC_TELEMETRYREPLY: { + *foundLen = remainingSize - bytesLeft; + result = scanForTmReply(foundId); + break; + } + default: { + sif::debug << "StarTrackerHandler::scanForReply: Reply has invalid type id" << std::endl; + result = RETURN_FAILED; + } + } + + remainingSize = bytesLeft; + + return result; +} + +ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { + + ReturnValue_t result = RETURN_OK; + + switch (id) { + case (StarTracker::SUBSCRIBE_TO_TM): { + result = handleSetParamReply(); + break; + } + case (StarTracker::REQ_TIME): { + result = handleTm(timeSet, StarTracker::TimeSet::SIZE); + break; + } + case (StarTracker::PING_REQUEST): { + result = handlePingReply(); + break; + } + case (StarTracker::BOOT): { + result = handleActionReply(); + break; + } + case (StarTracker::RESET_ERROR): { + result = handleActionReply(); + break; + } + case (StarTracker::TAKE_IMAGE): { + result = handleActionReply(); + break; + } + case (StarTracker::REQ_VERSION): { + result = handleTm(versionSet, StarTracker::VersionSet::SIZE); + if (result != RETURN_OK) { + return result; + } + result = checkProgram(); + if (result != RETURN_OK) { + return result; + } + break; + } + case (StarTracker::REQ_INTERFACE): { + result = handleTm(interfaceSet, StarTracker::InterfaceSet::SIZE); + break; + } + case (StarTracker::REQ_POWER): { + result = handleTm(powerSet, StarTracker::PowerSet::SIZE); + break; + } + case (StarTracker::REQ_SOLUTION): { + result = handleTm(solutionSet, StarTracker::SolutionSet::SIZE); + break; + } + case (StarTracker::REQ_TEMPERATURE): { + result = handleTm(temperatureSet, StarTracker::TemperatureSet::SIZE); + break; + } + case (StarTracker::REQ_HISTOGRAM): { + result = handleTm(histogramSet, StarTracker::HistogramSet::SIZE); + break; + } + case (StarTracker::REQ_CONTRAST): { + result = handleTm(contrastSet, StarTracker::ContrastSet::SIZE); + break; + } + case (StarTracker::LIMITS): + case (StarTracker::MOUNTING): + case (StarTracker::CAMERA): + case (StarTracker::BLOB): + case (StarTracker::CENTROIDING): + case (StarTracker::LISA): + case (StarTracker::MATCHING): + case (StarTracker::TRACKING): + case (StarTracker::VALIDATION): + case (StarTracker::ALGO): { + result = handleSetParamReply(); + break; + } + default: { + sif::debug << "StarTrackerHandler::interpretDeviceReply: Unknown device reply id:" << id + << std::endl; + result = DeviceHandlerIF::UNKNOWN_DEVICE_REPLY; + } + } + + return result; +} + + +void StarTrackerHandler::setNormalDatapoolEntriesInvalid() { + +} + +uint32_t StarTrackerHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { + return 20000; +} + +ReturnValue_t StarTrackerHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) { + + localDataPoolMap.emplace(StarTracker::TICKS_TIME_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TIME_TIME_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::RUN_TIME, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::UNIX_TIME, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(StarTracker::TICKS_VERSION_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TIME_VERSION_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::PROGRAM, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::MAJOR, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::MINOR, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(StarTracker::TICKS_INTERFACE_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TIME_INTERFACE_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::FRAME_COUNT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CHECKSUM_ERROR_COUNT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::SET_PARAM_COUNT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::SET_PARAM_REPLY_COUNT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::PARAM_REQUEST_COUNT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::PARAM_REPLY_COUNT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::REQ_TM_COUNT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TM_REPLY_COUNT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::ACTION_REQ_COUNT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::ACTION_REPLY_COUNT, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(StarTracker::TICKS_POWER_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TIME_POWER_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::MCU_CURRENT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::MCU_VOLTAGE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::FPGA_CORE_CURRENT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::FPGA_CORE_VOLTAGE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::FPGA_18_CURRENT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::FPGA_18_VOLTAGE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::FPGA_25_CURRENT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::FPGA_25_VOLTAGE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CMV_21_CURRENT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CMV_21_VOLTAGE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CMV_PIX_CURRENT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CMV_PIX_VOLTAGE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CMV_33_CURRENT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CMV_33_VOLTAGE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CMV_RES_CURRENT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CMV_RES_VOLTAGE, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(StarTracker::TICKS_TEMPERATURE_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TIME_TEMPERATURE_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::MCU_TEMPERATURE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CMOS_TEMPERATURE, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(StarTracker::TICKS_SOLUTION_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TIME_SOLUTION_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CALI_QW, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CALI_QX, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CALI_QY, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CALI_QZ, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TRACK_CONFIDENCE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TRACK_QW, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TRACK_QX, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TRACK_QY, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TRACK_QZ, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TRACK_REMOVED, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::STARS_CENTROIDED, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::STARS_MATCHED_DATABASE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::LISA_QW, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::LISA_QX, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::LISA_QY, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::LISA_QZ, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::LISA_PERC_CLOSE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::LISA_NR_CLOSE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TRUST_WORTHY, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::STABLE_COUNT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::SOLUTION_STRATEGY, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(StarTracker::TICKS_HISTOGRAM_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TIME_HISTOGRAM_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINA0, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINA1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINA2, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINA3, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINA4, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINA5, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINA6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINA7, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINA8, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINB0, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINB1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINB2, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINB3, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINB4, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINB5, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINB6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINB7, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINB8, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINC0, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINC1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINC2, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINC3, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINC4, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINC5, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINC6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINC7, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BINC8, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BIND0, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BIND1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BIND2, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BIND3, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BIND4, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BIND5, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BIND6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BIND7, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::HISTOGRAM_BIND8, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(StarTracker::TICKS_CONTRAST_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TIME_CONTRAST_SET, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINA0, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINA1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINA2, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINA3, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINA4, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINA5, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINA6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINA7, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINA8, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINB0, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINB1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINB2, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINB3, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINB4, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINB5, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINB6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINB7, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINB8, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINC8, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINC0, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINC1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINC2, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINC3, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINC4, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINC5, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINC6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINC7, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BINC8, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BIND0, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BIND1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BIND2, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BIND3, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BIND4, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BIND5, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BIND6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BIND7, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CONTRAST_BIND8, new PoolEntry( { 0 })); + + return RETURN_OK; +} + +size_t StarTrackerHandler::getNextReplyLength(DeviceCommandId_t commandId){ + return StarTracker::MAX_FRAME_SIZE; +} + +ReturnValue_t StarTrackerHandler::doSendReadHook() { + // Prevent DHB from polling UART during commands executed by the image loader task + if(strHelperExecuting) { + return RETURN_FAILED; + } + return RETURN_OK; +} + +ReturnValue_t StarTrackerHandler::checkMode(ActionId_t actionId) { + switch(actionId) { + case StarTracker::UPLOAD_IMAGE: + case StarTracker::DOWNLOAD_IMAGE: { + return DeviceHandlerBase::acceptExternalDeviceCommands(); + default: + break; + } + } + return RETURN_OK; +} + +ReturnValue_t StarTrackerHandler::scanForActionReply(DeviceCommandId_t *foundId) { + const uint8_t* reply = dataLinkLayer.getReply(); + switch (*reply) { + case (StarTracker::ID::PING): { + *foundId = StarTracker::PING_REQUEST; + break; + } + case (StarTracker::ID::WRITE): { + *foundId = StarTracker::WRITE; + break; + } + case (StarTracker::ID::BOOT): { + *foundId = StarTracker::BOOT; + break; + } + case (StarTracker::ID::TAKE_IMAGE): { + *foundId = StarTracker::TAKE_IMAGE; + break; + } + case (StarTracker::ID::UPLOAD_IMAGE): { + *foundId = StarTracker::UPLOAD_IMAGE; + break; + } + case (StarTracker::ID::ERROR_RESET): { + *foundId = StarTracker::RESET_ERROR; + break; + } + default: + sif::warning << "StarTrackerHandler::scanForParameterReply: Unknown parameter reply id" + << std::endl; + return RETURN_FAILED; + } + return RETURN_OK; +} + +ReturnValue_t StarTrackerHandler::scanForParameterReply(DeviceCommandId_t *foundId) { + const uint8_t* reply = dataLinkLayer.getReply(); + switch (*reply) { + case (StarTracker::ID::SUBSCRIBE): { + *foundId = StarTracker::SUBSCRIBE_TO_TM; + break; + } + case (StarTracker::ID::LIMITS): { + *foundId = StarTracker::LIMITS; + break; + } + case (StarTracker::ID::MOUNTING): { + *foundId = StarTracker::MOUNTING; + break; + } + case (StarTracker::ID::CAMERA): { + *foundId = StarTracker::CAMERA; + break; + } + case (StarTracker::ID::BLOB): { + *foundId = StarTracker::BLOB; + break; + } + case (StarTracker::ID::CENTROIDING): { + *foundId = StarTracker::CENTROIDING; + break; + } + case (StarTracker::ID::LISA): { + *foundId = StarTracker::LISA; + break; + } + case (StarTracker::ID::MATCHING): { + *foundId = StarTracker::MATCHING; + break; + } + case (StarTracker::ID::TRACKING): { + *foundId = StarTracker::TRACKING; + break; + } + case (StarTracker::ID::VALIDATION): { + *foundId = StarTracker::VALIDATION; + break; + } + case (StarTracker::ID::ALGO): { + *foundId = StarTracker::ALGO; + break; + } + default: + sif::debug << "StarTrackerHandler::scanForParameterReply: Unknown parameter reply id" + << std::endl; + return RETURN_FAILED; + } + return RETURN_OK; +} + +ReturnValue_t StarTrackerHandler::scanForTmReply(DeviceCommandId_t *foundId) { + const uint8_t* reply = dataLinkLayer.getReply(); + switch (*reply) { + case (StarTracker::ID::VERSION): { + *foundId = StarTracker::REQ_VERSION; + break; + } + case (StarTracker::ID::INTERFACE): { + *foundId = StarTracker::REQ_INTERFACE; + break; + } + case (StarTracker::ID::POWER): { + *foundId = StarTracker::REQ_POWER; + break; + } + case (StarTracker::ID::TEMPERATURE): { + *foundId = StarTracker::REQ_TEMPERATURE; + break; + } + case (StarTracker::ID::HISTOGRAM): { + *foundId = StarTracker::REQ_HISTOGRAM; + break; + } + case (StarTracker::ID::CONTRAST): { + *foundId = StarTracker::REQ_CONTRAST; + break; + } + case (StarTracker::ID::TIME): { + *foundId = StarTracker::REQ_TIME; + break; + } + case (StarTracker::ID::SOLUTION): { + *foundId = StarTracker::REQ_SOLUTION; + break; + } + default: { + sif::debug << "StarTrackerHandler::scanForTmReply: Reply contains invalid reply id" + << std::endl; + return RETURN_FAILED; + break; + } + } + return RETURN_OK; +} + +void StarTrackerHandler::handleEvent(EventMessage* eventMessage) { + object_id_t objectId = eventMessage->getReporter(); + switch(objectId){ + case objects::STR_HELPER: { + // All events from image loader signal either that the operation was successful or that it + // failed + strHelperExecuting = false; + break; + } + default: + sif::debug << "StarTrackerHandler::handleEvent: Did not subscribe to this event" + << std::endl; + break; + } +} + +ReturnValue_t StarTrackerHandler::executeWriteCommand(const uint8_t* commandData, + size_t commandDataLen) { + ReturnValue_t result = RETURN_OK; + if (commandDataLen < WriteCmd::MIN_LENGTH) { + sif::warning << "StarTrackerHandler::executeWriteCommand: Command too short" << std::endl; + return COMMAND_TOO_SHORT; + } + uint8_t region = *(commandData); + uint32_t address; + size_t size = sizeof(address); + const uint8_t* addressPtr = commandData + WriteCmd::ADDRESS_OFFSET; + result = SerializeAdapter::deSerialize(&address, addressPtr, &size, + SerializeIF::Endianness::LITTLE); + if (result != RETURN_OK) { + sif::debug << "StarTrackerHandler::executeWriteCommand: Deserialization of address failed" + << std::endl; + return result; + } + if (commandDataLen - sizeof(address) - sizeof(region) > MAX_PATH_SIZE) { + sif::warning << "StarTrackerHandler::executeWriteCommand: Received command with invalid" + << " path and filename" << std::endl; + return FILE_PATH_TOO_LONG; + } + const uint8_t* filePtr = commandData + WriteCmd::FILE_OFFSET; + std::string fullname = std::string(reinterpret_cast(filePtr), + commandDataLen - sizeof(address) - sizeof(region)); + result = strHelper->startFlashWrite(fullname, region, address); + if (result != RETURN_OK) { + return result; + } + return result; +} + +void StarTrackerHandler::prepareBootCommand() { + uint32_t length = 0; + struct BootActionRequest bootRequest = {BOOT_REGION_ID}; + arc_pack_boot_action_req(&bootRequest, commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + +void StarTrackerHandler::prepareTimeRequest() { + uint32_t length = 0; + arc_tm_pack_time_req(commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + +void StarTrackerHandler::preparePingRequest() { + uint32_t length = 0; + struct PingActionRequest pingRequest = {PING_ID}; + arc_pack_ping_action_req(&pingRequest, commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + +void StarTrackerHandler::prepareVersionRequest() { + uint32_t length = 0; + arc_tm_pack_version_req(commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + +void StarTrackerHandler::prepareInterfaceRequest() { + uint32_t length = 0; + arc_tm_pack_interface_req(commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + +void StarTrackerHandler::preparePowerRequest() { + uint32_t length = 0; + arc_tm_pack_power_req(commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + +void StarTrackerHandler::prepareRebootCommand() { + uint32_t length = 0; + struct RebootActionRequest rebootReq; + arc_pack_reboot_action_req(&rebootReq, commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + +void StarTrackerHandler::prepareTakeImageCommand(const uint8_t* commandData) { + uint32_t length = 0; + struct CameraActionRequest camReq; + camReq.actionid = *commandData; + arc_pack_camera_action_req(&camReq, commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + +void StarTrackerHandler::prepareSubscriptionCommand(const uint8_t* tmId) { + uint32_t length = 18; + commandBuffer[0] = TMTC_SETPARAMREQ; + commandBuffer[1] = StarTracker::ID::SUBSCRIBE; + // Fill all other fields with invalid tm id + commandBuffer[2] = *tmId; + commandBuffer[3] = 0; + commandBuffer[4] = 0; + commandBuffer[5] = 0; + commandBuffer[6] = 0; + commandBuffer[7] = 0; + commandBuffer[8] = 0; + commandBuffer[9] = 0; + commandBuffer[10] = 0; + commandBuffer[11] = 0; + commandBuffer[12] = 0; + commandBuffer[13] = 0; + commandBuffer[14] = 0; + commandBuffer[15] = 0; + commandBuffer[16] = 0; + commandBuffer[17] = 0; + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + +void StarTrackerHandler::prepareSolutionRequest() { + uint32_t length = 0; + arc_tm_pack_solution_req(commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + +void StarTrackerHandler::prepareTemperatureRequest() { + uint32_t length = 0; + arc_tm_pack_temperature_req(commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + +void StarTrackerHandler::prepareHistogramRequest() { + uint32_t length = 0; + arc_tm_pack_histogram_req(commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + +void StarTrackerHandler::prepareContrastRequest() { + uint32_t length = 0; + arc_tm_pack_contrast_req(commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + +void StarTrackerHandler::prepareErrorResetRequest() { + uint32_t length = 0; + struct ResetErrorSignalActionRequest req; + arc_pack_reseterrorsignal_action_req(&req, commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); +} + +ReturnValue_t StarTrackerHandler::prepareParamCommand(const uint8_t* commandData, + size_t commandDataLen, ArcsecJsonParamBase& paramSet) { + ReturnValue_t result = RETURN_OK; + if (commandDataLen > MAX_PATH_SIZE) { + return FILE_PATH_TOO_LONG; + } + std::string fullName(reinterpret_cast(commandData), commandDataLen); + + result = paramSet.create(fullName, commandBuffer); + if (result != RETURN_OK) { + sif::warning << "StarTrackerHandler::prepareParamCommand: Failed to create parameter " + "command" << std::endl; + return result; + } + dataLinkLayer.encodeFrame(commandBuffer, paramSet.getSize()); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); + return RETURN_OK; +} + +ReturnValue_t StarTrackerHandler::handleSetParamReply() { + const uint8_t* reply = dataLinkLayer.getReply(); + uint8_t status = *(reply + STATUS_OFFSET); + if (status != StarTracker::STATUS_OK) { + sif::warning << "StarTrackerHandler::handleSetParamReply: Failed to execute parameter set " + " command with parameter ID" << + static_cast(*(reply + PARAMETER_ID_OFFSET)) << std::endl; + if (startupState != StartupState::IDLE) { + startupState = StartupState::IDLE; + } + return SET_PARAM_FAILED; + } + if (startupState != StartupState::IDLE) { + handleStartup(reply + PARAMETER_ID_OFFSET); + } + return RETURN_OK; +} + +ReturnValue_t StarTrackerHandler::handleActionReply() { + const uint8_t* reply = dataLinkLayer.getReply(); + uint8_t status = *(reply + STATUS_OFFSET); + if (status != StarTracker::STATUS_OK) { + sif::warning << "StarTrackerHandler::handleActionReply: Failed to execute action " + << " command with action ID " + << static_cast(*(reply + ACTION_ID_OFFSET)) + << " and status "<< static_cast(status) << std::endl; + return ACTION_FAILED; + } + return RETURN_OK; +} + +ReturnValue_t StarTrackerHandler::handlePingReply() { + ReturnValue_t result = RETURN_OK; + uint32_t pingId = 0; + const uint8_t* reply = dataLinkLayer.getReply(); + uint8_t status = dataLinkLayer.getStatusField(); + const uint8_t* buffer = reply + ACTION_DATA_OFFSET; + size_t size = sizeof(pingId); + SerializeAdapter::deSerialize(&pingId, &buffer, &size, SerializeIF::Endianness::LITTLE); +#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1 + sif::info << "StarTracker: Ping status: "<< static_cast(status) << std::endl; + sif::info << "Ping id: 0x"<< std::hex << pingId << std::endl; +#endif /* OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1 */ + if (status != StarTracker::STATUS_OK || pingId != PING_ID) { + sif::warning << "StarTrackerHandler::handlePingReply: Ping failed" << std::endl; + result = PING_FAILED; + } + else { +#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1 + sif::info << "StarTracker: Ping successful" << std::endl; +#endif + } + return result; +} + +ReturnValue_t StarTrackerHandler::checkProgram() { + PoolReadGuard pg(&versionSet); + switch(versionSet.program.value) { + case StarTracker::Program::BOOTLOADER: + // Star tracker currently in bootloader program. Need to send boot command to switch to + // firmware program + if (startupState != StartupState::IDLE) { + startupState = StartupState::BOOT; + } + break; + case StarTracker::Program::FIRMWARE: + // Firmware already booted + if (startupState != StartupState::IDLE) { + startupState = StartupState::LIMITS; + } + break; + default: + sif::warning << "StarTrackerHandler::checkProgram: Version set has invalid program ID" + << std::endl; + return INVALID_PROGRAM; + } + return RETURN_OK; +} + +ReturnValue_t StarTrackerHandler::handleTm(LocalPoolDataSetBase& dataset, size_t size) { + ReturnValue_t result = RETURN_OK; + uint8_t status = *(dataLinkLayer.getReply() + STATUS_OFFSET); + if(status != StarTracker::STATUS_OK) { + sif::warning << "StarTrackerHandler::handleTm: Reply error: " + << static_cast(status) << std::endl; + return TM_REPLY_ERROR; + } + result = dataset.read(TIMEOUT_TYPE, MUTEX_TIMEOUT); + if (result != RETURN_OK) { + return result; + } + const uint8_t* reply = dataLinkLayer.getReply() + TICKS_OFFSET; + dataset.setValidityBufferGeneration(false); + result = dataset.deSerialize(&reply, &size, SerializeIF::Endianness::LITTLE); + if (result != RETURN_OK) { + sif::warning << "StarTrackerHandler::handleTm: Deserialization failed" + << std::endl; + } + dataset.setValidityBufferGeneration(true); + dataset.setValidity(true, true); + result = dataset.commit(TIMEOUT_TYPE, MUTEX_TIMEOUT); + if (result != RETURN_OK) { + return result; + } +#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1 + dataset.printSet(); +#endif + return result; +} + +void StarTrackerHandler::handleStartup(const uint8_t* parameterId) { + switch(*parameterId) { + case (StarTracker::ID::LIMITS): { + startupState = StartupState::TRACKING; + break; + } + case (StarTracker::ID::TRACKING): { + startupState = StartupState::MOUNTING; + break; + } + case (StarTracker::ID::MOUNTING): { + startupState = StartupState::CAMERA; + break; + } + case (StarTracker::ID::CAMERA): { + startupState = StartupState::BLOB; + break; + } + case (StarTracker::ID::BLOB): { + startupState = StartupState::CENTROIDING; + break; + } + case (StarTracker::ID::CENTROIDING): { + startupState = StartupState::LISA; + break; + } + case (StarTracker::ID::LISA): { + startupState = StartupState::MATCHING; + break; + } + case (StarTracker::ID::MATCHING): { + startupState = StartupState::VALIDATION; + break; + } + case (StarTracker::ID::VALIDATION): { + startupState = StartupState::ALGO; + break; + } + case (StarTracker::ID::ALGO): { + startupState = StartupState::DONE; + break; + } + default: { + sif::debug << "StarTrackerHandler::handleStartup: Received parameter reply with unexpected" + << " parameter ID" << std::endl; + break; + } + } +} diff --git a/bsp_q7s/devices/startracker/StarTrackerHandler.h b/bsp_q7s/devices/startracker/StarTrackerHandler.h new file mode 100644 index 00000000..7d22592e --- /dev/null +++ b/bsp_q7s/devices/startracker/StarTrackerHandler.h @@ -0,0 +1,355 @@ +#ifndef MISSION_DEVICES_STARTRACKERHANDLER_H_ +#define MISSION_DEVICES_STARTRACKERHANDLER_H_ + +#include "fsfw/devicehandlers/DeviceHandlerBase.h" +#include "fsfw/src/fsfw/serialize/SerializeAdapter.h" +#include "fsfw/timemanager/Countdown.h" +#include "thirdparty/arcsec_star_tracker/common/SLIP.h" +#include +#include "ArcsecDatalinkLayer.h" +#include "StarTrackerDefinitions.h" +#include "ArcsecJsonParamBase.h" +#include "StrHelper.h" + +/** + * @brief This is the device handler for the star tracker from arcsec. + * + * @details Datasheet: https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/ + * Arbeitsdaten/08_Used%20Components/ArcSec_KULeuven_Startracker/ + * Sagitta%201.0%20Datapack&fileid=659181 + * @author J. Meier + */ +class StarTrackerHandler: public DeviceHandlerBase { +public: + + /** + * @brief Constructor + * + * @param objectId + * @param comIF + * @param comCookie + * @param gpioComIF Pointer to gpio communication interface + * @param enablePin GPIO connected to the enable pin of the reaction wheels. Must be pulled + * to high to enable the device. + */ + StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie, + StrHelper* strHelper); + virtual ~StarTrackerHandler(); + + ReturnValue_t initialize() override; + + /** + * @brief Overwrite this function from DHB to handle commands executed by the str image + * loader task. + */ + ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) override; + + void performOperationHook() override; + +protected: + void doStartUp() override; + void doShutDown() override; + void doOffActivity() 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; + /** + * @brief Overwritten here to always read all available data from the UartComIF. + */ + virtual size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override; + virtual ReturnValue_t doSendReadHook() override; + +private: + + static const uint8_t INTERFACE_ID = CLASS_ID::STR_HANDLER; + + //! [EXPORT] : [COMMENT] Received reply is too short + static const ReturnValue_t REPLY_TOO_SHORT = MAKE_RETURN_CODE(0xB0); + //! [EXPORT] : [COMMENT] Received reply with invalid CRC + static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xB1); + //! [EXPORT] : [COMMENT] Image loader executing + static const ReturnValue_t IMAGE_LOADER_EXECUTING = MAKE_RETURN_CODE(0xB2); + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::STR_HANDLER; + + //! [EXPORT] : [COMMENT] Status in temperature reply signals error + static const ReturnValue_t TEMPERATURE_REQ_FAILED = MAKE_RETURN_CODE(0xA0); + //! [EXPORT] : [COMMENT] Ping command failed + static const ReturnValue_t PING_FAILED = MAKE_RETURN_CODE(0xA1); + //! [EXPORT] : [COMMENT] Status in version reply signals error + static const ReturnValue_t VERSION_REQ_FAILED = MAKE_RETURN_CODE(0xA3); + //! [EXPORT] : [COMMENT] Status in interface reply signals error + static const ReturnValue_t INTERFACE_REQ_FAILED = MAKE_RETURN_CODE(0xA4); + //! [EXPORT] : [COMMENT] Status in power reply signals error + static const ReturnValue_t POWER_REQ_FAILED = MAKE_RETURN_CODE(0xA5); + //! [EXPORT] : [COMMENT] Status of reply to parameter set command signals error + static const ReturnValue_t SET_PARAM_FAILED = MAKE_RETURN_CODE(0xA6); + //! [EXPORT] : [COMMENT] Status of reply to action command signals error + static const ReturnValue_t ACTION_FAILED = MAKE_RETURN_CODE(0xA7); + //! [EXPORT] : [COMMENT] Received upload image command with invalid length + static const ReturnValue_t UPLOAD_TOO_SHORT = MAKE_RETURN_CODE(0xA8); + //! [EXPORT] : [COMMENT] Received upload image command with invalid position field + static const ReturnValue_t UPLOAD_INVALID_POSITION = MAKE_RETURN_CODE(0xA8); + //! [EXPORT] : [COMMENT] Position value in upload image reply not matching sent position + static const ReturnValue_t UPLOAD_IMAGE_FAILED = MAKE_RETURN_CODE(0xA9); + //! [EXPORT] : [COMMENT] Received upload image command with invalid length + static const ReturnValue_t INVALID_UPLOAD_COMMAND = MAKE_RETURN_CODE(0xAA); + //! [EXPORT] : [COMMENT] Received invalid path string. Exceeds allowed length + static const ReturnValue_t FILE_PATH_TOO_LONG = MAKE_RETURN_CODE(0xAB); + //! [EXPORT] : [COMMENT] Name of file received with command is too long + static const ReturnValue_t FILENAME_TOO_LONG = MAKE_RETURN_CODE(0xAC); + //! [EXPORT] : [COMMENT] Received version reply with invalid program ID + static const ReturnValue_t INVALID_PROGRAM = MAKE_RETURN_CODE(0xAD); + //! [EXPORT] : [COMMENT] Status field of tm reply signals error + static const ReturnValue_t TM_REPLY_ERROR = MAKE_RETURN_CODE(0xAE); + //! [EXPORT] : [COMMENT] Status field of contrast reply signals error + static const ReturnValue_t CONTRAST_REQ_FAILED = MAKE_RETURN_CODE(0xAE); + //! [EXPORT] : [COMMENT] Received command which is too short (some data is missing for proper execution) + static const ReturnValue_t COMMAND_TOO_SHORT = MAKE_RETURN_CODE(0xAF); + + static const size_t MAX_PATH_SIZE = 50; + static const size_t MAX_FILE_NAME = 30; + + // position (uint32) + 1024 image data + static const size_t UPLOAD_COMMAND_LEN = 1028; + // Max valid position value in upload image command + static const uint16_t MAX_POSITION= 4095; + static const uint8_t STATUS_OFFSET = 1; + static const uint8_t TICKS_OFFSET = 2; + static const uint8_t TIME_OFFSET = 6; + static const uint8_t TM_DATA_FIELD_OFFSET = 14; + static const uint8_t PARAMETER_ID_OFFSET = 0; + static const uint8_t ACTION_ID_OFFSET = 0; + static const uint8_t ACTION_DATA_OFFSET = 2; + // Ping request will reply ping with this ID (data field) + static const uint32_t PING_ID = 0x55; + static const uint32_t BOOT_REGION_ID = 1; + static const MutexIF::TimeoutType TIMEOUT_TYPE = MutexIF::TimeoutType::WAITING; + static const uint32_t MUTEX_TIMEOUT = 20; + static const uint32_t BOOT_TIMEOUT = 1000; + + class WriteCmd { + public: + static const uint8_t ADDRESS_OFFSET = 1; + static const uint8_t FILE_OFFSET = 5; + // Minimum length of a write command (region, address and filename) + static const size_t MIN_LENGTH = 7; + }; + + MessageQueueIF* eventQueue = nullptr; + + ArcsecDatalinkLayer dataLinkLayer; + + StarTracker::TemperatureSet temperatureSet; + StarTracker::VersionSet versionSet; + StarTracker::PowerSet powerSet; + StarTracker::InterfaceSet interfaceSet; + StarTracker::TimeSet timeSet; + StarTracker::SolutionSet solutionSet; + StarTracker::HistogramSet histogramSet; + StarTracker::ContrastSet contrastSet; + + // Pointer to object responsible for uploading and downloading images to/from the star tracker + StrHelper* strHelper = nullptr; + + uint8_t commandBuffer[StarTracker::MAX_FRAME_SIZE]; + + // Countdown to insert delay for star tracker to switch from bootloader to firmware program + Countdown bootCountdown; + + std::string paramJsonFile = "/mnt/sd0/startracker/full.json"; + + enum class InternalState { + TEMPERATURE_REQUEST + }; + + InternalState internalState = InternalState::TEMPERATURE_REQUEST; + + enum class StartupState { + IDLE, + CHECK_BOOT_STATE, + BOOT, + BOOT_DELAY, + LIMITS, + TRACKING, + MOUNTING, + CAMERA, + BLOB, + CENTROIDING, + LISA, + MATCHING, + VALIDATION, + ALGO, + WAIT_FOR_EXECUTION, + DONE + }; + + StartupState startupState = StartupState::IDLE; + + bool strHelperExecuting = false; + + /** + * @brief Handles internal state + */ + void handleInternalState(); + + /** + * @brief Checks mode for commands requiring MODE_ON of MODE_NORMAL for execution. + * + * @param actionId Action id of command to execute + */ + ReturnValue_t checkMode(ActionId_t actionId); + + /** + * @brief This function initializes the serial link ip protocol struct slipInfo. + */ + void slipInit(); + + ReturnValue_t scanForActionReply(DeviceCommandId_t *foundId); + ReturnValue_t scanForParameterReply(DeviceCommandId_t *foundId); + ReturnValue_t scanForTmReply(DeviceCommandId_t *foundId); + + /** + * @brief Fills command buffer with data to ping the star tracker + */ + void preparePingRequest(); + + /** + * @brief Fills command buffer with data to request the time telemetry. + */ + void prepareTimeRequest(); + + /** + * @brief Handles all received event messages + */ + void handleEvent(EventMessage* eventMessage); + + /** + * @brief Executes the write command + * + * @param commandData Pointer to received command data + * @param commandDataLen Size of received command data + * + * @return RETURN_OK if start of execution was successful, otherwise error return value + */ + ReturnValue_t executeWriteCommand(const uint8_t* commandData, size_t commandDataLen); + + /** + * @brief Fills command buffer with data to boot image (works only when star tracker is + * in bootloader mode). + */ + void prepareBootCommand(); + + /** + * @brief Fills the command buffer with the command to take an image. + */ + void prepareTakeImageCommand(const uint8_t* commandData); + + /** + * @brief Fills command buffer with data to request the version telemetry packet + */ + void prepareVersionRequest(); + + /** + * @brief Fills the command buffer with data to request the interface telemetry packet. + */ + void prepareInterfaceRequest(); + + /** + * @brief Fills the command buffer with data to request the power telemetry packet. + */ + void preparePowerRequest(); + + /** + * @brief Fills command buffer with data to reboot star tracker. + */ + void prepareRebootCommand(); + + /** + * @brief Fills command buffer with data to subscribe to a telemetry packet. + * + * @param tmId The ID of the telemetry packet to subscribe to + */ + void prepareSubscriptionCommand(const uint8_t* tmId); + + /** + * @brief Fills command buffer with data to request solution telemtry packet (contains + * attitude information) + */ + void prepareSolutionRequest(); + + /** + * @brief Fills command buffer with data to request temperature from star tracker + */ + void prepareTemperatureRequest(); + + /** + * @brief Fills command buffer with data to request histogram + */ + void prepareHistogramRequest(); + + void prepareContrastRequest(); + + /** + * @brief Fills command buffer with command to reset the error signal of the star tracker + */ + void prepareErrorResetRequest(); + + /** + * @brief Reads parameters from json file specified by string in commandData and + * prepares the command to apply the parameter set to the star tracker + * + * @param commandData Contains string with file name + * @param commandDataLen Length of command + * @param paramSet The object defining the command generation + * + * @return RETURN_OK if successful, otherwise error return Value + */ + ReturnValue_t prepareParamCommand(const uint8_t* commandData, size_t commandDataLen, + ArcsecJsonParamBase& paramSet); + + /** + * @brief Default function to handle action replies + */ + ReturnValue_t handleActionReply(); + + /** + * @brief Handles all set parameter replies + */ + ReturnValue_t handleSetParamReply(); + + ReturnValue_t handlePingReply(); + + /** + * @brief Checks the loaded program by means of the version set + */ + ReturnValue_t checkProgram(); + + /** + * @brief Handles the startup state machine + */ + void handleStartup(const uint8_t* parameterId); + + /** + * @brief Handles telemtry replies and fills the appropriate dataset + * + * @param dataset Dataset where reply data will be written to + * @param size Size of the dataset + * + * @return RETURN_OK if successful, otherwise error return value + */ + ReturnValue_t handleTm(LocalPoolDataSetBase& dataset, size_t size); +}; + +#endif /* MISSION_DEVICES_STARTRACKERHANDLER_H_ */ diff --git a/bsp_q7s/devices/startracker/StarTrackerJsonCommands.cpp b/bsp_q7s/devices/startracker/StarTrackerJsonCommands.cpp new file mode 100644 index 00000000..9c33e1c9 --- /dev/null +++ b/bsp_q7s/devices/startracker/StarTrackerJsonCommands.cpp @@ -0,0 +1,716 @@ +#include "StarTrackerJsonCommands.h" +#include "ArcsecJsonKeys.h" + +Limits::Limits() : ArcsecJsonParamBase(arcseckeys::LIMITS) {} + +size_t Limits::getSize() { + return COMMAND_SIZE; +} + +ReturnValue_t Limits::createCommand(uint8_t* buffer) { + ReturnValue_t result = RETURN_OK; + uint8_t offset = 0; + std::string param; + addSetParamHeader(buffer, StarTracker::ID::LIMITS); + offset = 2; + result = getParam(arcseckeys::ACTION, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::FPGA18CURRENT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::FPGA25CURRENT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::FPGA10CURRENT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::MCUCURRENT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::CMOS21CURRENT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::CMOSPIXCURRENT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::CMOS33CURRENT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::CMOSVRESCURRENT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::CMOS_TEMPERATURE, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::MCU_TEMPERATURE, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + return RETURN_OK; +} + + +Tracking::Tracking() : ArcsecJsonParamBase(arcseckeys::TRACKING) {} + +size_t Tracking::getSize() { + return COMMAND_SIZE; +} + +ReturnValue_t Tracking::createCommand(uint8_t* buffer) { + ReturnValue_t result = RETURN_OK; + uint8_t offset = 0; + std::string param; + addSetParamHeader(buffer, StarTracker::ID::TRACKING); + offset = 2; + result = getParam(arcseckeys::THIN_LIMIT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::OUTLIER_THRESHOLD, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::OUTLIER_THRESHOLD_QUEST, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::TRACKER_CHOICE, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + return RETURN_OK; +} + + +Mounting::Mounting() : ArcsecJsonParamBase(arcseckeys::MOUNTING) {} + +size_t Mounting::getSize() { + return COMMAND_SIZE; +} + +ReturnValue_t Mounting::createCommand(uint8_t* buffer) { + ReturnValue_t result = RETURN_OK; + uint8_t offset = 0; + std::string param; + addSetParamHeader(buffer, StarTracker::ID::MOUNTING); + offset = 2; + result = getParam(arcseckeys::qw, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::qx, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::qy, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::qz, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + return RETURN_OK; +} + + +Camera::Camera() : ArcsecJsonParamBase(arcseckeys::CAMERA) {} + +size_t Camera::getSize() { + return COMMAND_SIZE; +} + +ReturnValue_t Camera::createCommand(uint8_t* buffer) { + ReturnValue_t result = RETURN_OK; + uint8_t offset = 0; + std::string param; + addSetParamHeader(buffer, StarTracker::ID::CAMERA); + offset = 2; + result = getParam(arcseckeys::MODE, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::FOCALLENGTH, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::EXPOSURE, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::INTERVAL, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::OFFSET, param); + if (result != RETURN_OK) { + return result; + } + addint16(param, buffer + offset); + offset += sizeof(int16_t); + result = getParam(arcseckeys::PGAGAIN, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::ADCGAIN, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::REG_1, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::VAL_1, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::REG_2, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::VAL_2, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::REG_3, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::VAL_3, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::REG_4, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::VAL_4, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::REG_5, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::VAL_5, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::REG_6, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::VAL_6, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::REG_7, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::VAL_7, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::REG_8, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::VAL_8, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::FREQ_1, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::FREQ_2, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + return RETURN_OK; +} + + +Blob::Blob() : ArcsecJsonParamBase(arcseckeys::BLOB) {} + +size_t Blob::getSize() { + return COMMAND_SIZE; +} + +ReturnValue_t Blob::createCommand(uint8_t* buffer) { + ReturnValue_t result = RETURN_OK; + uint8_t offset = 0; + std::string param; + addSetParamHeader(buffer, StarTracker::ID::BLOB); + offset = 2; + result = getParam(arcseckeys::MODE, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::MIN_VALUE, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::MIN_DISTANCE, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::NEIGHBOUR_DISTANCE, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::NEIGHBOUR_BRIGHT_PIXELS, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::MIN_TOTAL_VALUE, param); + if (result != RETURN_OK) { + return result; + } + adduint16(param, buffer + offset); + offset += sizeof(uint16_t); + result = getParam(arcseckeys::MAX_TOTAL_VALUE, param); + if (result != RETURN_OK) { + return result; + } + adduint16(param, buffer + offset); + offset += sizeof(uint16_t); + result = getParam(arcseckeys::MIN_BRIGHT_NEIGHBOURS, param); + if (result != RETURN_OK) { + return result; + } + adduint16(param, buffer + offset); + offset += sizeof(uint16_t); + result = getParam(arcseckeys::MAX_BRIGHT_NEIGHBOURS, param); + if (result != RETURN_OK) { + return result; + } + adduint16(param, buffer + offset); + offset += sizeof(uint16_t); + result = getParam(arcseckeys::MAX_PIXEL_TO_CONSIDER, param); + if (result != RETURN_OK) { + return result; + } + adduint32(param, buffer + offset); + offset += sizeof(uint32_t); + result = getParam(arcseckeys::SIGNAL_THRESHOLD, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::DARK_THRESHOLD, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::ENABLE_HISTOGRAM, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::ENABLE_CONTRAST, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::BIN_MODE, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + return RETURN_OK; +} + + +Centroiding::Centroiding() : ArcsecJsonParamBase(arcseckeys::CENTROIDING) {} + +size_t Centroiding::getSize() { + return COMMAND_SIZE; +} + +ReturnValue_t Centroiding::createCommand(uint8_t* buffer) { + ReturnValue_t result = RETURN_OK; + uint8_t offset = 0; + std::string param; + addSetParamHeader(buffer, StarTracker::ID::CENTROIDING); + offset = 2; + result = getParam(arcseckeys::ENABLE_FILTER, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::MAX_QUALITY, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::MIN_QUALITY, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::MAX_INTENSITY, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::MIN_INTENSITY, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::MAX_MAGNITUDE, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::GAUSSIAN_CMAX, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::GAUSSIAN_CMIN, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::TRANSMATRIX_00, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::TRANSMATRIX_01, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::TRANSMATRIX_10, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::TRANSMATRIX_11, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + return RETURN_OK; +} + + +Lisa::Lisa() : ArcsecJsonParamBase(arcseckeys::LISA) {} + +size_t Lisa::getSize() { + return COMMAND_SIZE; +} + +ReturnValue_t Lisa::createCommand(uint8_t* buffer) { + ReturnValue_t result = RETURN_OK; + uint8_t offset = 0; + std::string param; + addSetParamHeader(buffer, StarTracker::ID::LISA); + offset = 2; + result = getParam(arcseckeys::PREFILTER_DIST_THRESHOLD, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::PREFILTER_ANGLE_THRESHOLD, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::FOV_WIDTH, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::FOV_HEIGHT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::FLOAT_STAR_LIMIT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::CLOSE_STAR_LIMIT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::RATING_WEIGHT_CLOSE_STAR_COUNT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::RATING_WEIGHT_FRACTION_CLOSE, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::RATING_WEIGHT_DB_STAR_COUNT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::MAX_COMBINATIONS, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::NR_STARS_STOP, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::FRACTION_CLOSE_STOP, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + return RETURN_OK; +} + + +Matching::Matching() : ArcsecJsonParamBase(arcseckeys::MATCHING) {} + +size_t Matching::getSize() { + return COMMAND_SIZE; +} + +ReturnValue_t Matching::createCommand(uint8_t* buffer) { + ReturnValue_t result = RETURN_OK; + uint8_t offset = 0; + std::string param; + addSetParamHeader(buffer, StarTracker::ID::MATCHING); + offset = 2; + result = getParam(arcseckeys::SQUARED_DISTANCE_LIMIT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::SQUARED_SHIFT_LIMIT, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + return RETURN_OK; +} + + +Validation::Validation() : ArcsecJsonParamBase(arcseckeys::VALIDATION) {} + +size_t Validation::getSize() { + return COMMAND_SIZE; +} + +ReturnValue_t Validation::createCommand(uint8_t* buffer) { + ReturnValue_t result = RETURN_OK; + uint8_t offset = 0; + std::string param; + addSetParamHeader(buffer, StarTracker::ID::VALIDATION); + offset = 2; + result = getParam(arcseckeys::STABLE_COUNT, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::MAX_DIFFERENCE, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::MIN_TRACKER_CONFIDENCE, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::MIN_MATCHED_STARS, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + return RETURN_OK; +} + +Algo::Algo() : ArcsecJsonParamBase(arcseckeys::ALGO) {} + +size_t Algo::getSize() { + return COMMAND_SIZE; +} + +ReturnValue_t Algo::createCommand(uint8_t* buffer) { + ReturnValue_t result = RETURN_OK; + uint8_t offset = 0; + std::string param; + addSetParamHeader(buffer, StarTracker::ID::ALGO); + offset = 2; + result = getParam(arcseckeys::MODE, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::L2T_MIN_CONFIDENCE, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::L2T_MIN_MATCHED, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + offset += sizeof(uint8_t); + result = getParam(arcseckeys::T2L_MIN_CONFIDENCE, param); + if (result != RETURN_OK) { + return result; + } + addfloat(param, buffer + offset); + offset += sizeof(float); + result = getParam(arcseckeys::T2L_MIN_MATCHED, param); + if (result != RETURN_OK) { + return result; + } + adduint8(param, buffer + offset); + return RETURN_OK; +} diff --git a/bsp_q7s/devices/startracker/StarTrackerJsonCommands.h b/bsp_q7s/devices/startracker/StarTrackerJsonCommands.h new file mode 100644 index 00000000..868c18ea --- /dev/null +++ b/bsp_q7s/devices/startracker/StarTrackerJsonCommands.h @@ -0,0 +1,215 @@ +#ifndef BSP_Q7S_DEVICES_DEVICEDEFINITIONS_STARTRACKERJSONCOMMANDS_H_ +#define BSP_Q7S_DEVICES_DEVICEDEFINITIONS_STARTRACKERJSONCOMMANDS_H_ + +/** + * @brief This file defines a few helper classes to generate commands by means of the parameters + * defined in the arcsec json files. + * @author J. Meier + */ + +#include + +#include "fsfw/serviceinterface/ServiceInterface.h" +#include "ArcsecJsonParamBase.h" + + +/** + * @brief Generates command to set the limit parameters + * + */ +class Limits : public ArcsecJsonParamBase { +public: + + Limits(); + + size_t getSize(); + +private: + + static const size_t COMMAND_SIZE = 43; + + virtual ReturnValue_t createCommand(uint8_t* buffer) override; +}; + + +/** + * @brief Generates the command to configure the tracking algorithm. + * + */ +class Tracking : public ArcsecJsonParamBase { +public: + + Tracking(); + + size_t getSize(); + +private: + + static const size_t COMMAND_SIZE = 15; + + ReturnValue_t createCommand(uint8_t* buffer) override; + +}; + + +/** + * @brief Generates the command to set the mounting quaternion + * + */ +class Mounting : public ArcsecJsonParamBase { +public: + + Mounting(); + + size_t getSize(); + +private: + + static const size_t COMMAND_SIZE = 18; + + ReturnValue_t createCommand(uint8_t* buffer) override; + +}; + + +/** + * @brief Generates the command to set the mounting quaternion + * + */ +class Camera : public ArcsecJsonParamBase { +public: + + Camera(); + + size_t getSize(); + +private: + + static const size_t COMMAND_SIZE = 43; + + ReturnValue_t createCommand(uint8_t* buffer) override; + +}; + + +/** + * @brief Generates the command to configure the blob algorithm + * + */ +class Blob : public ArcsecJsonParamBase { +public: + + Blob(); + + size_t getSize(); + +private: + + static const size_t COMMAND_SIZE = 24; + + ReturnValue_t createCommand(uint8_t* buffer) override; + +}; + + +/** + * @brief Generates the command to configure the centroiding algorithm + * + */ +class Centroiding : public ArcsecJsonParamBase { +public: + + Centroiding(); + + size_t getSize(); + +private: + + static const size_t COMMAND_SIZE = 47; + + ReturnValue_t createCommand(uint8_t* buffer) override; + +}; + + +/** + * @brief Generates the command to configure the LISA (lost in space algorithm) + * + */ +class Lisa : public ArcsecJsonParamBase { +public: + + Lisa(); + + size_t getSize(); + +private: + + static const size_t COMMAND_SIZE = 48; + + ReturnValue_t createCommand(uint8_t* buffer) override; + +}; + + +/** + * @brief Generates the command to configure the matching algorithm + * + */ +class Matching : public ArcsecJsonParamBase { +public: + + Matching(); + + size_t getSize(); + +private: + + static const size_t COMMAND_SIZE = 10; + + ReturnValue_t createCommand(uint8_t* buffer) override; + +}; + + +/** + * @brief Generates the command to configure the validation parameters + * + */ +class Validation : public ArcsecJsonParamBase { +public: + + Validation(); + + size_t getSize(); + +private: + + static const size_t COMMAND_SIZE = 12; + + ReturnValue_t createCommand(uint8_t* buffer) override; + +}; + + +/** + * @brief Generates command to configure the mechanism of automatically switching between the + * LISA and other algorithms. + * + */ +class Algo : public ArcsecJsonParamBase { +public: + + Algo(); + + size_t getSize(); + +private: + + static const size_t COMMAND_SIZE = 13; + + ReturnValue_t createCommand(uint8_t* buffer) override; + +}; + +#endif /* BSP_Q7S_DEVICES_DEVICEDEFINITIONS_STARTRACKERJSONCOMMANDS_H_ */ diff --git a/bsp_q7s/devices/startracker/StrHelper.cpp b/bsp_q7s/devices/startracker/StrHelper.cpp new file mode 100644 index 00000000..a3d28305 --- /dev/null +++ b/bsp_q7s/devices/startracker/StrHelper.cpp @@ -0,0 +1,430 @@ +#include "StrHelper.h" + +#include "mission/utility/Timestamp.h" + +#include +#include + +StrHelper::StrHelper(object_id_t objectId) : SystemObject(objectId){ + +} + +StrHelper::~StrHelper() { +} + +ReturnValue_t StrHelper::initialize() { + sdcMan = SdCardManager::instance(); + if (sdcMan == nullptr) { + sif::warning << "StrHelper::initialize: Invalid SD Card Manager" << std::endl; + return RETURN_FAILED; + } + return RETURN_OK; +} + +ReturnValue_t StrHelper::performOperation(uint8_t operationCode) { + ReturnValue_t result = RETURN_OK; + semaphore.acquire(); + while(true) { + switch(internalState) { + case InternalState::IDLE: { + semaphore.acquire(); + break; + } + case InternalState::UPLOAD_IMAGE: { + result = performImageUpload(); + if (result == RETURN_OK){ + triggerEvent(IMAGE_UPLOAD_SUCCESSFUL); + } + else { + triggerEvent(IMAGE_UPLOAD_FAILED); + } + internalState = InternalState::IDLE; + break; + } + case InternalState::DOWNLOAD_IMAGE: { + result = performImageDownload(); + if (result == RETURN_OK){ + triggerEvent(IMAGE_DOWNLOAD_SUCCESSFUL); + } + else { + triggerEvent(IMAGE_DOWNLOAD_FAILED); + } + internalState = InternalState::IDLE; + break; + } + case InternalState::FLASH_WRITE: { + result = performFlashWrite(); + if (result == RETURN_OK){ + triggerEvent(FLASH_WRITE_SUCCESSFUL); + } + else { + triggerEvent(FLASH_WRITE_FAILED); + } + internalState = InternalState::IDLE; + break; + } + default: + sif::debug << "StrHelper::performOperation: Invalid state" << std::endl; + break; + } + } +} + +ReturnValue_t StrHelper::setComIF(DeviceCommunicationIF* communicationInterface_) { + uartComIF = dynamic_cast(communicationInterface_); + if (uartComIF == nullptr) { + sif::warning << "StrHelper::initialize: Invalid uart com if" << std::endl; + return RETURN_FAILED; + } + return RETURN_OK; +} + +void StrHelper::setComCookie(CookieIF* comCookie_) { + comCookie = comCookie_; +} + +ReturnValue_t StrHelper::startImageUpload(std::string uploadImage_) { + ReturnValue_t result = checkPath(uploadImage_); + if (result != RETURN_OK) { + return result; + } + uploadImage = uploadImage_; + if(not std::filesystem::exists(uploadImage)) { + return FILE_NOT_EXISTS; + } + internalState = InternalState::UPLOAD_IMAGE; + semaphore.release(); + terminate = false; + return RETURN_OK; +} + +ReturnValue_t StrHelper::startImageDownload(std::string downloadPath_) { + ReturnValue_t result = checkPath(downloadPath_); + if (result != RETURN_OK) { + return result; + } + if(not std::filesystem::exists(downloadPath_)) { + return PATH_NOT_EXISTS; + } + downloadPath = downloadPath_; + internalState = InternalState::DOWNLOAD_IMAGE; + terminate = false; + semaphore.release(); + return RETURN_OK; +} + +void StrHelper::stopProcess() { + terminate = true; +} + +void StrHelper::setDownloadImageName(std::string image) { + downloadImage = image; +} + +ReturnValue_t StrHelper::startFlashWrite(std::string flashWriteFile_, uint8_t region, + uint32_t flashWriteAddress) { + ReturnValue_t result = checkPath(flashWriteFile_); + if (result != RETURN_OK) { + return result; + } + flashWriteFile = flashWriteFile_; + if(not std::filesystem::exists(flashWriteFile)) { + return FILE_NOT_EXISTS; + } + internalState = InternalState::FLASH_WRITE; + semaphore.release(); + terminate = false; + return RETURN_OK; +} + +ReturnValue_t StrHelper::performImageDownload() { + ReturnValue_t result; + struct DownloadActionRequest downloadReq; + uint32_t size = 0; + uint32_t retries = 0; + Timestamp timestamp; + std::string image = downloadPath + "/" + timestamp.str() + downloadImage ; + std::ofstream file(image, std::ios_base::app | std::ios_base::out); + if(not std::filesystem::exists(image)) { + return FILE_CREATION_FAILED; + } + downloadReq.position = 0; + while(downloadReq.position < LAST_POSITION) { + if (terminate) { + return RETURN_OK; + } + arc_pack_download_action_req(&downloadReq, commandBuffer, &size); + result = sendAndRead(size, downloadReq.position); + if (result != RETURN_OK) { + if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) { + uartComIF->flushUartRxBuffer(comCookie); + retries++; + continue; + } + file.close(); + return result; + } + result = checkReply(); + if (result != RETURN_OK) { + if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) { + uartComIF->flushUartRxBuffer(comCookie); + retries++; + continue; + } + file.close(); + return result; + } + result = checkReplyPosition(downloadReq.position); + if (result != RETURN_OK) { + if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) { + uartComIF->flushUartRxBuffer(comCookie); + retries++; + continue; + } + file.close(); + return result; + } + file.write(reinterpret_cast(datalinkLayer.getReply() + DATA_OFFSET), + IMAGE_DATA_SIZE); + downloadReq.position++; + retries = 0; + } + file.close(); + return RETURN_OK; +} + +ReturnValue_t StrHelper::performImageUpload() { + ReturnValue_t result = RETURN_OK; + uint32_t size = 0; + uint32_t imageSize = 0; + struct UploadActionRequest uploadReq; + uploadReq.position = 0; + std::memset(&uploadReq.data, 0, sizeof(uploadReq.data)); + if (not std::filesystem::exists(uploadImage)) { + triggerEvent(STR_HELPER_FILE_NOT_EXISTS, static_cast(internalState)); + internalState = InternalState::IDLE; + return RETURN_FAILED; + } + std::ifstream file(uploadImage, std::ifstream::binary); + // Set position of next character to end of file input stream + file.seekg(0, file.end); + // tellg returns position of character in input stream + imageSize = file.tellg(); + while((uploadReq.position + 1) * SIZE_IMAGE_PART < imageSize) { + if (terminate) { + return RETURN_OK; + } + file.seekg(uploadReq.position * SIZE_IMAGE_PART, file.beg); + file.read(reinterpret_cast(uploadReq.data), SIZE_IMAGE_PART); + arc_pack_upload_action_req(&uploadReq, commandBuffer, &size); + result = sendAndRead(size, uploadReq.position); + if (result != RETURN_OK) { + return RETURN_FAILED; + } + result = checkReply(); + if (result != RETURN_OK) { + return result; + } + uploadReq.position++; + } + std::memset(uploadReq.data, 0, sizeof(uploadReq.data)); + uint32_t remainder = imageSize - uploadReq.position * SIZE_IMAGE_PART; + file.seekg(uploadReq.position * SIZE_IMAGE_PART, file.beg); + file.read(reinterpret_cast(uploadReq.data), remainder); + file.close(); + uploadReq.position++; + arc_pack_upload_action_req(&uploadReq, commandBuffer, &size); + result = sendAndRead(size, uploadReq.position); + if (result != RETURN_OK) { + return RETURN_FAILED; + } + result = checkReply(); + if (result != RETURN_OK) { + return result; + } + return RETURN_OK; +} + +ReturnValue_t StrHelper::performFlashWrite() { + ReturnValue_t result = RETURN_OK; + uint32_t size = 0; + uint32_t remainingBytes = 0; + uint32_t fileSize = 0; + struct WriteActionRequest req; + if (not std::filesystem::exists(flashWriteFile)) { + triggerEvent(STR_HELPER_FILE_NOT_EXISTS, static_cast(internalState)); + internalState = InternalState::IDLE; + return RETURN_FAILED; + } + std::ifstream file(flashWriteFile, std::ifstream::binary); + file.seekg(0, file.end); + fileSize = file.tellg(); + remainingBytes = fileSize; + req.region = flashWriteRegion; + req.address = flashWriteAddress; + req.length = MAX_FLASH_DATA; + while(remainingBytes >= MAX_FLASH_DATA) { + if (terminate) { + return RETURN_OK; + } + file.seekg(fileSize - remainingBytes, file.beg); + file.read(reinterpret_cast(req.data), MAX_FLASH_DATA); + arc_pack_write_action_req(&req, commandBuffer, &size); + result = sendAndRead(size, req.address); + if (result != RETURN_OK) { + return RETURN_FAILED; + } + result = checkFlashWriteReply(req); + if (result != RETURN_OK) { + return result; + } + remainingBytes = remainingBytes - MAX_FLASH_DATA; + } + file.seekg(fileSize - remainingBytes, file.beg); + file.read(reinterpret_cast(req.data), remainingBytes); + file.close(); + arc_pack_write_action_req(&req, commandBuffer, &size); + result = sendAndRead(size, req.address); + if (result != RETURN_OK) { + return RETURN_FAILED; + } + result = checkFlashWriteReply(req); + if (result != RETURN_OK) { + return result; + } + return RETURN_OK; +} + +ReturnValue_t StrHelper::sendAndRead(size_t size, uint32_t parameter) { + ReturnValue_t result = RETURN_OK; + ReturnValue_t decResult = RETURN_OK; + size_t receivedDataLen = 0; + uint8_t *receivedData = nullptr; + size_t bytesLeft = 0; + uint32_t missedReplies = 0; + datalinkLayer.encodeFrame(commandBuffer, size); + result = uartComIF->sendMessage(comCookie, datalinkLayer.getEncodedFrame(), + datalinkLayer.getEncodedLength()); + if (result != RETURN_OK) { + sif::warning << "StrHelper::sendAndRead: Failed to send packet" << std::endl; + triggerEvent(STR_HELPER_SENDING_PACKET_FAILED, result, parameter); + return RETURN_FAILED; + } + decResult = ArcsecDatalinkLayer::DEC_IN_PROGRESS; + while (decResult == ArcsecDatalinkLayer::DEC_IN_PROGRESS) { + result = uartComIF->requestReceiveMessage(comCookie, + StarTracker::MAX_FRAME_SIZE * 2 + 2); + if (result != RETURN_OK) { + sif::warning << "StrHelper::sendAndRead: Failed to request reply" << std::endl; + triggerEvent(STR_HELPER_REQUESTING_MSG_FAILED, result, parameter); + return RETURN_FAILED; + } + result = uartComIF->readReceivedMessage(comCookie, &receivedData, &receivedDataLen); + if (result != RETURN_OK) { + sif::warning << "StrHelper::sendAndRead: Failed to read received message" << std::endl; + triggerEvent(STR_HELPER_READING_REPLY_FAILED, result, parameter); + return RETURN_FAILED; + } + if (receivedDataLen == 0 && missedReplies < MAX_POLLS) { + missedReplies++; + continue; + } + else if ((receivedDataLen == 0) && (missedReplies >= MAX_POLLS)) { + triggerEvent(STR_HELPER_NO_REPLY, parameter); + return RETURN_FAILED; + } + else { + missedReplies = 0; + } + decResult = datalinkLayer.decodeFrame(receivedData, receivedDataLen, &bytesLeft); + if (bytesLeft != 0) { + // This should never happen + sif::warning << "StrHelper::sendAndRead: Bytes left after decoding" << std::endl; + triggerEvent(STR_HELPER_COM_ERROR, result, parameter); + return RETURN_FAILED; + } + } + if (decResult != RETURN_OK) { + triggerEvent(STR_HELPER_DEC_ERROR, decResult, parameter); + return RETURN_FAILED; + } + return RETURN_OK; +} + +ReturnValue_t StrHelper::checkReply() { + uint8_t type = datalinkLayer.getReplyFrameType(); + if (type != TMTC_ACTIONREPLY) { + sif::warning << "StrHelper::checkReply: Received reply with invalid type ID" + << std::endl; + triggerEvent(INVALID_TYPE_ID); + return RETURN_FAILED; + } + uint8_t status = datalinkLayer.getStatusField(); + if (status != ArcsecDatalinkLayer::STATUS_OK) { + triggerEvent(STATUS_ERROR); + sif::warning << "StrHelper::checkReply: Status failure" << std::endl; + return RETURN_FAILED; + } + return RETURN_OK; +} + +ReturnValue_t StrHelper::checkReplyPosition(uint32_t expectedPosition) { + uint32_t receivedPosition = 0; + std::memcpy(&receivedPosition, datalinkLayer.getReply() + POS_OFFSET, sizeof(receivedPosition)); + if (receivedPosition != expectedPosition) { + triggerEvent(POSITION_MISMATCH, receivedPosition); + return RETURN_FAILED; + } + return RETURN_OK; +} + +ReturnValue_t StrHelper::checkFlashWriteReply(struct WriteActionRequest& req) { + ReturnValue_t result = RETURN_OK; + const uint8_t* data = datalinkLayer.getReply(); + uint8_t region = *(data + REGION_OFFSET); + uint32_t address; + const uint8_t* addressData = data + ADDRESS_OFFSET; + size_t size = sizeof(address); + result = SerializeAdapter::deSerialize(&address, &addressData, &size, + SerializeIF::Endianness::LITTLE); + if (result != RETURN_OK) { + sif::warning << "StrHelper::checkFlashWriteReply: Deserialization of address failed" + << std::endl; + } + uint16_t length; + size = sizeof(length); + const uint8_t* lengthData = data + LENGTH_OFFSET; + result = SerializeAdapter::deSerialize(&length, lengthData, &size, + SerializeIF::Endianness::LITTLE); + if (result != RETURN_OK) { + sif::warning << "StrHelper::checkFlashWriteReply: Deserialization of length failed" + << std::endl; + } + if (region != req.region) { + return REGION_MISMATCH; + } + if (address != req.address) { + return ADDRESS_MISMATCH; + } + if (region != req.length) { + return LENGTH_MISMATCH; + } + return RETURN_OK; +} + +ReturnValue_t StrHelper::checkPath(std::string name) { + if (name.substr(0, sizeof(SdCardManager::SD_0_MOUNT_POINT)) + == std::string(SdCardManager::SD_0_MOUNT_POINT)) { + if (!sdcMan->isSdCardMounted(sd::SLOT_0)) { + sif::warning << "StrHelper::checkPath: SD card 0 not mounted" << std::endl; + return SD_NOT_MOUNTED; + } + } else if (name.substr(0, sizeof(SdCardManager::SD_1_MOUNT_POINT)) + == std::string(SdCardManager::SD_1_MOUNT_POINT)) { + if (!sdcMan->isSdCardMounted(sd::SLOT_0)) { + sif::warning << "StrHelper::checkPath: SD card 1 not mounted" << std::endl; + return SD_NOT_MOUNTED; + } + } + return RETURN_OK; +} diff --git a/bsp_q7s/devices/startracker/StrHelper.h b/bsp_q7s/devices/startracker/StrHelper.h new file mode 100644 index 00000000..f7a994b4 --- /dev/null +++ b/bsp_q7s/devices/startracker/StrHelper.h @@ -0,0 +1,271 @@ +#ifndef BSP_Q7S_DEVICES_STRHELPER_H_ +#define BSP_Q7S_DEVICES_STRHELPER_H_ + +#include +#include "ArcsecDatalinkLayer.h" +#include "fsfw/osal/linux/BinarySemaphore.h" +#include "bsp_q7s/memory/SdCardManager.h" +#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/objectmanager/SystemObject.h" +#include "fsfw/tasks/ExecutableObjectIF.h" +#include "fsfw_hal/linux/uart/UartComIF.h" +#include "fsfw/devicehandlers/CookieIF.h" + +extern "C" { + #include "thirdparty/arcsec_star_tracker/common/generated/tmtcstructs.h" + #include "thirdparty/arcsec_star_tracker/client/generated/actionreq.h" +} + +/** + * @brief Helper class for the star tracker handler to accelerate large data transfers. + */ +class StrHelper: public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF { +public: + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::STR_HELPER; + + //! [EXPORT] : [COMMENT] Image upload failed + static const Event IMAGE_UPLOAD_FAILED = MAKE_EVENT(0, severity::LOW); + //! [EXPORT] : [COMMENT] Image download failed + static const Event IMAGE_DOWNLOAD_FAILED = MAKE_EVENT(1, severity::LOW); + //! [EXPORT] : [COMMENT] Uploading image to star tracker was successful + static const Event IMAGE_UPLOAD_SUCCESSFUL = MAKE_EVENT(2, severity::LOW); + //! [EXPORT] : [COMMENT] Image download was successful + static const Event IMAGE_DOWNLOAD_SUCCESSFUL = MAKE_EVENT(3, severity::LOW); + //! [EXPORT] : [COMMENT] Finished flash write procedure successfully + static const Event FLASH_WRITE_SUCCESSFUL = MAKE_EVENT(4, severity::LOW); + //! [EXPORT] : [COMMENT] Finished flash read procedure successfully + static const Event FLASH_READ_SUCCESSFUL = MAKE_EVENT(5, severity::LOW); + //! [EXPORT] : [COMMENT] Flash write procedure failed + static const Event FLASH_WRITE_FAILED = MAKE_EVENT(6, severity::LOW); + //! [EXPORT] : [COMMENT] Flash read procedure failed + static const Event FLASH_READ_FAILED = MAKE_EVENT(7, severity::LOW); + //! [EXPORT] : [COMMENT] Failed to read communication interface reply data + //!P1: Return code of failed communication interface read call + //!P1: Upload/download position for which the read call failed + static const Event STR_HELPER_READING_REPLY_FAILED = MAKE_EVENT(8, severity::LOW); + //! [EXPORT] : [COMMENT] Unexpected stop of decoding sequence + //!P1: Return code of failed communication interface read call + //!P1: Upload/download position for which the read call failed + static const Event STR_HELPER_COM_ERROR = MAKE_EVENT(9, severity::LOW); + //! [EXPORT] : [COMMENT] Star tracker did not send replies (maybe device is powered off) + //!P1: Position of upload or download packet for which no reply was sent + static const Event STR_HELPER_NO_REPLY = MAKE_EVENT(10, severity::LOW); + //! [EXPORT] : [COMMENT] Received reply with invalid type ID + static const Event INVALID_TYPE_ID = MAKE_EVENT(11, severity::LOW); + //! [EXPORT] : [COMMENT] Status field in reply signals error + static const Event STATUS_ERROR = MAKE_EVENT(12, severity::LOW); + //! [EXPORT] : [COMMENT] Error during decoding of received reply occurred + //P1: Return value of decoding function + //P2: Position of upload/download packet, or address of flash write/read request + static const Event STR_HELPER_DEC_ERROR = MAKE_EVENT(13, severity::LOW); + //! [EXPORT] : [COMMENT] Position mismatch + //! P1: The expected position and thus the position for which the image upload/download failed + static const Event POSITION_MISMATCH = MAKE_EVENT(14, severity::LOW); + //! [EXPORT] : [COMMENT] Specified file does not exist + //!P1: Internal state of str helper + static const Event STR_HELPER_FILE_NOT_EXISTS = MAKE_EVENT(15, severity::LOW); + //! [EXPORT] : [COMMENT] Sending packet to star tracker failed + //!P1: Return code of communication interface sendMessage function + //!P2: Position of upload/download packet, or address of flash write/read request for which sending failed + static const Event STR_HELPER_SENDING_PACKET_FAILED = MAKE_EVENT(16, severity::LOW); + //! [EXPORT] : [COMMENT] Communication interface requesting reply failed + //!P1: Return code of failed request + //!P1: Upload/download position, or address of flash write/read request for which transmission failed + static const Event STR_HELPER_REQUESTING_MSG_FAILED = MAKE_EVENT(17, severity::LOW); + + StrHelper(object_id_t objectId); + virtual ~StrHelper(); + + ReturnValue_t initialize() override; + ReturnValue_t performOperation(uint8_t operationCode = 0) override; + + ReturnValue_t setComIF(DeviceCommunicationIF* communicationInterface_); + void setComCookie(CookieIF* comCookie_); + + /** + * @brief Starts sequence to upload image to star tracker + * + * @param image Name including absolute path if to image to upload. Must be previously + * transferred to the OBC with the CFDP protocoll. + */ + ReturnValue_t startImageUpload(std::string uploadImage_); + + /** + * @brief Calling this function initiates the download of an image from the star tracker. + * + * @param Name of the image which will be created + */ + ReturnValue_t startImageDownload(std::string downloadPath_); + + /** + * @brief Starts the flash write procedure + * + * @param flashWriteFile_ Full name including absolute path of file to write to flash + * @param region Region ID of flash region to write to + * @param flashWriteAddress Start address of flash write procedure + */ + ReturnValue_t startFlashWrite(std::string flashWriteFile_, uint8_t region, + uint32_t flashWriteAddress); + + /** + * @brief Can be used to interrupt a running data transfer. + */ + void stopProcess(); + + /** + * @brief Changes the dafault name of downloaded images + */ + void setDownloadImageName(std::string image); + +private: + + static const uint8_t INTERFACE_ID = CLASS_ID::STR_HELPER; + + //! [EXPORT] : [COMMENT] SD card specified in path string not mounted + static const ReturnValue_t SD_NOT_MOUNTED = MAKE_RETURN_CODE(0xA0); + //! [EXPORT] : [COMMENT] Specified file does not exist on filesystem + static const ReturnValue_t FILE_NOT_EXISTS = MAKE_RETURN_CODE(0xA1); + //! [EXPORT] : [COMMENT] Specified path does not exist + static const ReturnValue_t PATH_NOT_EXISTS = MAKE_RETURN_CODE(0xA2); + //! [EXPORT] : [COMMENT] Failed to create download image or read flash file + static const ReturnValue_t FILE_CREATION_FAILED = MAKE_RETURN_CODE(0xA3); + //! [EXPORT] : [COMMENT] Region in flash write/read reply does not match expected region + static const ReturnValue_t REGION_MISMATCH = MAKE_RETURN_CODE(0xA4); + //! [EXPORT] : [COMMENT] Address in flash write/read reply does not match expected address + static const ReturnValue_t ADDRESS_MISMATCH = MAKE_RETURN_CODE(0xA5); + //! [EXPORT] : [COMMENT] Length in flash write/read reply does not match expected length + static const ReturnValue_t LENGTH_MISMATCH = MAKE_RETURN_CODE(0xA6); + + // Size of one image part which can be sent per action request + static const size_t SIZE_IMAGE_PART = 1024; + + static const uint32_t LAST_POSITION = 4095; + + static const uint32_t MAX_POLLS = 10000; + + static const uint8_t POS_OFFSET = 2; + static const uint8_t DATA_OFFSET = 5; + static const uint8_t REGION_OFFSET = 2; + static const uint8_t ADDRESS_OFFSET = 3; + static const uint8_t LENGTH_OFFSET = 7; + static const size_t IMAGE_DATA_SIZE = 1024; + static const size_t MAX_FLASH_DATA = 1024; + static const size_t CONFIG_MAX_DOWNLOAD_RETRIES = 3; + + enum class InternalState { + IDLE, + UPLOAD_IMAGE, + DOWNLOAD_IMAGE, + FLASH_WRITE, + FLASH_READ + }; + + InternalState internalState = InternalState::IDLE; + + ArcsecDatalinkLayer datalinkLayer; + + BinarySemaphore semaphore; + + // Name including absolute path of image to upload + std::string uploadImage; + // Path where the downloaded image will be stored + std::string downloadPath; + // File which contains data to write when executing the flash write command + std::string flashWriteFile; + // Path where the file containing the read data will be stored + std::string flashReadFilePath = ""; + + // Default name of downloaded image, can be changed via command + std::string downloadImage = "image"; + // Default name of file containing the data read from flash, can be changed via command + std::string flashReadImage = "flashread"; + // Will be set with the flash write command + uint8_t flashWriteRegion = 0; + // Will be set with the flash write command and specifies the start address where to write the + // flash data to + uint32_t flashWriteAddress = 0; + + SdCardManager* sdcMan = nullptr; + + uint8_t commandBuffer[StarTracker::MAX_FRAME_SIZE]; + + bool terminate = false; + + /** + * UART communication object responsible for low level access of star tracker + * Must be set by star tracker handler + */ + UartComIF* uartComIF = nullptr; + // Communication cookie. Must be set by the star tracker handler + CookieIF* comCookie = nullptr; + + // Queue id of raw data receiver + MessageQueueId_t rawDataReceiver = MessageQueueIF::NO_QUEUE; + + /** + * @brief Performs image uploading + */ + ReturnValue_t performImageUpload(); + + /** + * @brief Performs download of last taken image from the star tracker. + * + * @details Download is split over multiple packets transporting each a maximum of 1024 bytes. + * In case the download of one position fails, the same packet will be again + * requested. If the download of the packet fails CONFIG_MAX_DOWNLOAD_RETRIES times, + * the download will be stopped. + */ + ReturnValue_t performImageDownload(); + + /** + * @brief Handles flash write procedure + * + * @return RETURN_OK if successful, otherwise RETURN_FAILED + */ + ReturnValue_t performFlashWrite(); + + /** + * @brief Sends packet to the star tracker and reads reply by using the communication + * interface + * + * @param size Size of data beforehand written to the commandBuffer + * @param parameter Parameter 2 of trigger event function + * + * @return RETURN_OK if successful, otherwise RETURN_FAILED + */ + ReturnValue_t sendAndRead(size_t size, uint32_t parameter); + + /** + * @brief Checks the reply header (type id and status fields) + * + * @return RETURN_OK if reply confirms success of packet transfer, otherwise REUTRN_FAILED + */ + ReturnValue_t checkReply(); + + /** + * @brief Checks the position field in a star tracker upload/download reply. + * + * @param expectedPosition Value of expected position + * + * @return RETURN_OK if received position matches expected position, otherwise RETURN_FAILED + */ + ReturnValue_t checkReplyPosition(uint32_t expectedPosition); + + /** + * @brief Checks the region, address and length value of a flash write reply. + * + * @return RETURN_OK if values match expected values, otherwise appropriate error return + * value. + */ + ReturnValue_t checkFlashWriteReply(struct WriteActionRequest& req); + + /** + * @brief Checks if a path points to an sd card and whether the SD card is monuted. + * + * @return SD_NOT_MOUNTED id SD card is not mounted, otherwise RETURN_OK + */ + ReturnValue_t checkPath(std::string name); +}; + +#endif /* BSP_Q7S_DEVICES_STRHELPER_H_ */ diff --git a/bsp_q7s/memory/SdCardManager.cpp b/bsp_q7s/memory/SdCardManager.cpp index ebebf854..8a3d11f2 100644 --- a/bsp_q7s/memory/SdCardManager.cpp +++ b/bsp_q7s/memory/SdCardManager.cpp @@ -455,3 +455,33 @@ void SdCardManager::setPrintCommandOutput(bool print) { } +bool SdCardManager::isSdCardMounted(sd::SdCard sdCard) { + SdCardManager::SdStatePair active; + ReturnValue_t result = this->getSdCardActiveStatus(active); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::debug << "SdCardManager::isSdCardMounted: Failed to get SD card active state"; + return false; + } + if (sdCard == sd::SLOT_0) { + if (active.first == sd::MOUNTED) { + return true; + } + else { + return false; + } + } + else if (sdCard == sd::SLOT_1) { + if (active.second == sd::MOUNTED) { + return true; + } + else { + return false; + } + } + else { + sif::debug << "SdCardManager::isSdCardMounted: Unknown SD card specified" << std::endl; + } + return false; +} + + diff --git a/bsp_q7s/memory/SdCardManager.h b/bsp_q7s/memory/SdCardManager.h index 6f03e7f1..6e4930da 100644 --- a/bsp_q7s/memory/SdCardManager.h +++ b/bsp_q7s/memory/SdCardManager.h @@ -195,6 +195,15 @@ public: void setBlocking(bool blocking); void setPrintCommandOutput(bool print); + + /** + * @brief Checks if an SD card is mounted + * + * @param sdCard The SD crad to check + * + * @return true if mounted, otherwise false + */ + bool isSdCardMounted(sd::SdCard sdCard); private: CommandExecutor cmdExecutor; Operations currentOp = Operations::IDLE; diff --git a/common/config/commonClassIds.h b/common/config/commonClassIds.h index 00b5ca25..4c769260 100644 --- a/common/config/commonClassIds.h +++ b/common/config/commonClassIds.h @@ -19,10 +19,12 @@ enum commonClassIds: uint8_t { CCSDS_IP_CORE_BRIDGE, //IPCI PTME, //PTME PLOC_UPDATER, //PLUD + STR_HELPER, //STRHLP GOM_SPACE_HANDLER, //GOMS PLOC_MEMORY_DUMPER, //PLMEMDUMP PDEC_HANDLER, //PDEC - CCSDS_HANDLER, //PDEC + CCSDS_HANDLER, //CCSDS + ARCSEC_JSON_BASE, //JSONBASE COMMON_CLASS_ID_END // [EXPORT] : [END] }; diff --git a/common/config/commonObjects.h b/common/config/commonObjects.h index 8cf45e9a..cce3616f 100644 --- a/common/config/commonObjects.h +++ b/common/config/commonObjects.h @@ -87,10 +87,11 @@ enum commonObjects: uint32_t { RW3 = 0x44120249, RW4 = 0x44120350, - START_TRACKER = 0x44130001, + STAR_TRACKER = 0x44130001, PLOC_UPDATER = 0x44330000, - PLOC_MEMORY_DUMPER = 0x44330001 + PLOC_MEMORY_DUMPER = 0x44330001, + STR_HELPER = 0x44330002 }; } diff --git a/common/config/commonSubsystemIds.h b/common/config/commonSubsystemIds.h index 05fda61c..55a4bed4 100644 --- a/common/config/commonSubsystemIds.h +++ b/common/config/commonSubsystemIds.h @@ -18,6 +18,7 @@ enum: uint8_t { PLOC_UPDATER = 117, PLOC_MEMORY_DUMPER = 118, PDEC_HANDLER = 119, + STR_HELPER = 120, COMMON_SUBSYSTEM_ID_END }; } diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv index 8dfa9e78..a2a4784a 100644 --- a/generators/bsp_q7s_events.csv +++ b/generators/bsp_q7s_events.csv @@ -1,120 +1,138 @@ -2200;STORE_SEND_WRITE_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2201;STORE_WRITE_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2202;STORE_SEND_READ_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2203;STORE_READ_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2204;UNEXPECTED_MSG;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2205;STORING_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2206;TM_DUMP_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2207;STORE_INIT_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2208;STORE_INIT_EMPTY;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2209;STORE_CONTENT_CORRUPTED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2210;STORE_INITIALIZE;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2211;INIT_DONE;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2212;DUMP_FINISHED;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2213;DELETION_FINISHED;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2214;DELETION_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2215;AUTO_CATALOGS_SENDING_FAILED;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h -2600;GET_DATA_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/storagemanager/StorageManagerIF.h -2601;STORE_DATA_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/storagemanager/StorageManagerIF.h -2800;DEVICE_BUILDING_COMMAND_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h -2801;DEVICE_SENDING_COMMAND_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h -2802;DEVICE_REQUESTING_REPLY_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h -2803;DEVICE_READING_REPLY_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h -2804;DEVICE_INTERPRETING_REPLY_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h -2805;DEVICE_MISSED_REPLY;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h -2806;DEVICE_UNKNOWN_REPLY;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h -2807;DEVICE_UNREQUESTED_REPLY;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h -2808;INVALID_DEVICE_COMMAND;LOW;Indicates a SW bug in child class.;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h -2809;MONITORING_LIMIT_EXCEEDED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h -2810;MONITORING_AMBIGUOUS;HIGH;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h -4201;FUSE_CURRENT_HIGH;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/power/Fuse.h -4202;FUSE_WENT_OFF;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/power/Fuse.h -4204;POWER_ABOVE_HIGH_LIMIT;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/power/Fuse.h -4205;POWER_BELOW_LOW_LIMIT;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/power/Fuse.h -4300;SWITCH_WENT_OFF;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/power/PowerSwitchIF.h -5000;HEATER_ON;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/thermal/Heater.h -5001;HEATER_OFF;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/thermal/Heater.h -5002;HEATER_TIMEOUT;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/thermal/Heater.h -5003;HEATER_STAYED_ON;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/thermal/Heater.h -5004;HEATER_STAYED_OFF;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/thermal/Heater.h -5200;TEMP_SENSOR_HIGH;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/thermal/AbstractTemperatureSensor.h -5201;TEMP_SENSOR_LOW;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/thermal/AbstractTemperatureSensor.h -5202;TEMP_SENSOR_GRADIENT;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/thermal/AbstractTemperatureSensor.h -5901;COMPONENT_TEMP_LOW;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/thermal/ThermalComponentIF.h -5902;COMPONENT_TEMP_HIGH;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/thermal/ThermalComponentIF.h -5903;COMPONENT_TEMP_OOL_LOW;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/thermal/ThermalComponentIF.h -5904;COMPONENT_TEMP_OOL_HIGH;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/thermal/ThermalComponentIF.h -5905;TEMP_NOT_IN_OP_RANGE;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/thermal/ThermalComponentIF.h -7101;FDIR_CHANGED_STATE;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/fdir/FailureIsolationBase.h -7102;FDIR_STARTS_RECOVERY;MEDIUM;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/fdir/FailureIsolationBase.h -7103;FDIR_TURNS_OFF_DEVICE;MEDIUM;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/fdir/FailureIsolationBase.h -7201;MONITOR_CHANGED_STATE;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/monitoring/MonitoringIF.h -7202;VALUE_BELOW_LOW_LIMIT;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/monitoring/MonitoringIF.h -7203;VALUE_ABOVE_HIGH_LIMIT;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/monitoring/MonitoringIF.h -7204;VALUE_OUT_OF_RANGE;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/monitoring/MonitoringIF.h -7301;SWITCHING_TM_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/datapool/HkSwitchHelper.h -7400;CHANGING_MODE;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/modes/HasModesIF.h -7401;MODE_INFO;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/modes/HasModesIF.h -7402;FALLBACK_FAILED;HIGH;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/modes/HasModesIF.h -7403;MODE_TRANSITION_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/modes/HasModesIF.h -7404;CANT_KEEP_MODE;HIGH;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/modes/HasModesIF.h -7405;OBJECT_IN_INVALID_MODE;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/modes/HasModesIF.h -7406;FORCING_MODE;MEDIUM;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/modes/HasModesIF.h -7407;MODE_CMD_REJECTED;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/modes/HasModesIF.h -7506;HEALTH_INFO;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/health/HasHealthIF.h -7507;CHILD_CHANGED_HEALTH;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/health/HasHealthIF.h -7508;CHILD_PROBLEMS;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/health/HasHealthIF.h -7509;OVERWRITING_HEALTH;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/health/HasHealthIF.h -7510;TRYING_RECOVERY;MEDIUM;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/health/HasHealthIF.h -7511;RECOVERY_STEP;MEDIUM;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/health/HasHealthIF.h -7512;RECOVERY_DONE;MEDIUM;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/health/HasHealthIF.h -7900;RF_AVAILABLE;INFO;A RF available signal was detected. P1: raw RFA state, P2: 0;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/datalinklayer/DataLinkLayer.h -7901;RF_LOST;INFO;A previously found RF available signal was lost. P1: raw RFA state, P2: 0;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/datalinklayer/DataLinkLayer.h -7902;BIT_LOCK;INFO;A Bit Lock signal. Was detected. P1: raw BLO state, P2: 0;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/datalinklayer/DataLinkLayer.h -7903;BIT_LOCK_LOST;INFO;A previously found Bit Lock signal was lost. P1: raw BLO state, P2: 0;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/datalinklayer/DataLinkLayer.h -7905;FRAME_PROCESSING_FAILED;LOW;The CCSDS Board could not interpret a TC;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/datalinklayer/DataLinkLayer.h -8900;CLOCK_SET;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/pus/Service9TimeManagement.h -8901;CLOCK_SET_FAILURE;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/pus/Service9TimeManagement.h -9700;TEST;INFO;;/home/eive/EIVE/Robin/eive-obsw/fsfw/src/fsfw/pus/Service17Test.h -10600;CHANGE_OF_SETUP_PARAMETER;LOW;;/home/eive/EIVE/Robin/eive-obsw/fsfw/hal/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h -10900;GPIO_PULL_HIGH_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/linux/devices/HeaterHandler.h -10901;GPIO_PULL_LOW_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/linux/devices/HeaterHandler.h -10902;SWITCH_ALREADY_ON;LOW;;/home/eive/EIVE/Robin/eive-obsw/linux/devices/HeaterHandler.h -10903;SWITCH_ALREADY_OFF;LOW;;/home/eive/EIVE/Robin/eive-obsw/linux/devices/HeaterHandler.h -10904;MAIN_SWITCH_TIMEOUT;LOW;;/home/eive/EIVE/Robin/eive-obsw/linux/devices/HeaterHandler.h -11000;MAIN_SWITCH_ON_TIMEOUT;LOW;;/home/eive/EIVE/Robin/eive-obsw/linux/devices/SolarArrayDeploymentHandler.h -11001;MAIN_SWITCH_OFF_TIMEOUT;LOW;;/home/eive/EIVE/Robin/eive-obsw/linux/devices/SolarArrayDeploymentHandler.h -11002;DEPLOYMENT_FAILED;HIGH;;/home/eive/EIVE/Robin/eive-obsw/linux/devices/SolarArrayDeploymentHandler.h -11003;DEPL_SA1_GPIO_SWTICH_ON_FAILED;HIGH;;/home/eive/EIVE/Robin/eive-obsw/linux/devices/SolarArrayDeploymentHandler.h -11004;DEPL_SA2_GPIO_SWTICH_ON_FAILED;HIGH;;/home/eive/EIVE/Robin/eive-obsw/linux/devices/SolarArrayDeploymentHandler.h -11101;MEMORY_READ_RPT_CRC_FAILURE;LOW;;/home/eive/EIVE/Robin/eive-obsw/mission/devices/PlocMPSoCHandler.h -11102;ACK_FAILURE;LOW;;/home/eive/EIVE/Robin/eive-obsw/mission/devices/PlocMPSoCHandler.h -11103;EXE_FAILURE;LOW;;/home/eive/EIVE/Robin/eive-obsw/mission/devices/PlocMPSoCHandler.h -11104;CRC_FAILURE_EVENT;LOW;;/home/eive/EIVE/Robin/eive-obsw/mission/devices/PlocMPSoCHandler.h -11201;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;/home/eive/EIVE/Robin/eive-obsw/mission/devices/IMTQHandler.h -11202;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;/home/eive/EIVE/Robin/eive-obsw/mission/devices/IMTQHandler.h -11203;SELF_TEST_ADC_FAILURE;LOW;Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;/home/eive/EIVE/Robin/eive-obsw/mission/devices/IMTQHandler.h -11204;SELF_TEST_PWM_FAILURE;LOW;Get self test result returns PWM failure which concerns the coil actuation. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;/home/eive/EIVE/Robin/eive-obsw/mission/devices/IMTQHandler.h -11205;SELF_TEST_TC_FAILURE;LOW;Get self test result returns TC failure (system failure) P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;/home/eive/EIVE/Robin/eive-obsw/mission/devices/IMTQHandler.h -11206;SELF_TEST_MTM_RANGE_FAILURE;LOW;Get self test result returns failure that MTM values were outside of the expected range. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;/home/eive/EIVE/Robin/eive-obsw/mission/devices/IMTQHandler.h -11207;SELF_TEST_COIL_CURRENT_FAILURE;LOW;Get self test result returns failure indicating that the coil current was outside of the expected range P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;/home/eive/EIVE/Robin/eive-obsw/mission/devices/IMTQHandler.h -11208;INVALID_ERROR_BYTE;LOW;Received invalid error byte. This indicates an error of the communication link between IMTQ and OBC.;/home/eive/EIVE/Robin/eive-obsw/mission/devices/IMTQHandler.h -11301;ERROR_STATE;HIGH;Reaction wheel signals an error state;/home/eive/EIVE/Robin/eive-obsw/mission/devices/RwHandler.h -11501;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;/home/eive/EIVE/Robin/eive-obsw/bsp_q7s/devices/PlocSupervisorHandler.h -11502;SUPV_ACK_FAILURE;LOW;PLOC supervisor received acknowledgment failure report;/home/eive/EIVE/Robin/eive-obsw/bsp_q7s/devices/PlocSupervisorHandler.h -11503;SUPV_EXE_FAILURE;LOW;PLOC received execution failure report;/home/eive/EIVE/Robin/eive-obsw/bsp_q7s/devices/PlocSupervisorHandler.h -11504;SUPV_CRC_FAILURE_EVENT;LOW;PLOC supervisor reply has invalid crc;/home/eive/EIVE/Robin/eive-obsw/bsp_q7s/devices/PlocSupervisorHandler.h -11600;SANITIZATION_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/bsp_q7s/memory/SdCardManager.h -11700;UPDATE_FILE_NOT_EXISTS;LOW;;/home/eive/EIVE/Robin/eive-obsw/bsp_q7s/devices/PlocUpdater.h -11701;ACTION_COMMANDING_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/bsp_q7s/devices/PlocUpdater.h -11702;UPDATE_AVAILABLE_FAILED;LOW;Supervisor handler replied action message indicating a command execution failure of the update available command;/home/eive/EIVE/Robin/eive-obsw/bsp_q7s/devices/PlocUpdater.h -11703;UPDATE_TRANSFER_FAILED;LOW;Supervisor handler failed to transfer an update space packet. P1: Parameter holds the number of update packets already sent (inclusive the failed packet);/home/eive/EIVE/Robin/eive-obsw/bsp_q7s/devices/PlocUpdater.h -11704;UPDATE_VERIFY_FAILED;LOW;Supervisor failed to execute the update verify command.;/home/eive/EIVE/Robin/eive-obsw/bsp_q7s/devices/PlocUpdater.h -11705;UPDATE_FINISHED;INFO;MPSoC update successful completed;/home/eive/EIVE/Robin/eive-obsw/bsp_q7s/devices/PlocUpdater.h -11800;SEND_MRAM_DUMP_FAILED;LOW;;/home/eive/EIVE/Robin/eive-obsw/bsp_q7s/devices/PlocMemoryDumper.h -11801;MRAM_DUMP_FAILED;LOW;Received completion failure report form PLOC supervisor handler P1: MRAM start address of failing dump command;/home/eive/EIVE/Robin/eive-obsw/bsp_q7s/devices/PlocMemoryDumper.h -11802;MRAM_DUMP_FINISHED;LOW;MRAM dump finished successfully;/home/eive/EIVE/Robin/eive-obsw/bsp_q7s/devices/PlocMemoryDumper.h -11901;INVALID_TC_FRAME;HIGH;;/home/eive/EIVE/Robin/eive-obsw/linux/obc/PdecHandler.h -11902;INVALID_FAR;HIGH;Read invalid FAR from PDEC after startup;/home/eive/EIVE/Robin/eive-obsw/linux/obc/PdecHandler.h -11903;CARRIER_LOCK;INFO;Carrier lock detected;/home/eive/EIVE/Robin/eive-obsw/linux/obc/PdecHandler.h -11904;BIT_LOCK_PDEC;INFO;Bit lock detected (data valid);/home/eive/EIVE/Robin/eive-obsw/linux/obc/PdecHandler.h +2200;STORE_SEND_WRITE_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2201;STORE_WRITE_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2202;STORE_SEND_READ_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2203;STORE_READ_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2204;UNEXPECTED_MSG;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2205;STORING_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2206;TM_DUMP_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2207;STORE_INIT_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2208;STORE_INIT_EMPTY;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2209;STORE_CONTENT_CORRUPTED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2210;STORE_INITIALIZE;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2211;INIT_DONE;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2212;DUMP_FINISHED;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2213;DELETION_FINISHED;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2214;DELETION_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2215;AUTO_CATALOGS_SENDING_FAILED;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h +2600;GET_DATA_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/storagemanager/StorageManagerIF.h +2601;STORE_DATA_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/storagemanager/StorageManagerIF.h +2800;DEVICE_BUILDING_COMMAND_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h +2801;DEVICE_SENDING_COMMAND_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h +2802;DEVICE_REQUESTING_REPLY_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h +2803;DEVICE_READING_REPLY_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h +2804;DEVICE_INTERPRETING_REPLY_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h +2805;DEVICE_MISSED_REPLY;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h +2806;DEVICE_UNKNOWN_REPLY;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h +2807;DEVICE_UNREQUESTED_REPLY;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h +2808;INVALID_DEVICE_COMMAND;LOW;Indicates a SW bug in child class.;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h +2809;MONITORING_LIMIT_EXCEEDED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h +2810;MONITORING_AMBIGUOUS;HIGH;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h +4201;FUSE_CURRENT_HIGH;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/power/Fuse.h +4202;FUSE_WENT_OFF;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/power/Fuse.h +4204;POWER_ABOVE_HIGH_LIMIT;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/power/Fuse.h +4205;POWER_BELOW_LOW_LIMIT;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/power/Fuse.h +4300;SWITCH_WENT_OFF;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/power/PowerSwitchIF.h +5000;HEATER_ON;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/thermal/Heater.h +5001;HEATER_OFF;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/thermal/Heater.h +5002;HEATER_TIMEOUT;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/thermal/Heater.h +5003;HEATER_STAYED_ON;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/thermal/Heater.h +5004;HEATER_STAYED_OFF;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/thermal/Heater.h +5200;TEMP_SENSOR_HIGH;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/thermal/AbstractTemperatureSensor.h +5201;TEMP_SENSOR_LOW;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/thermal/AbstractTemperatureSensor.h +5202;TEMP_SENSOR_GRADIENT;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/thermal/AbstractTemperatureSensor.h +5901;COMPONENT_TEMP_LOW;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/thermal/ThermalComponentIF.h +5902;COMPONENT_TEMP_HIGH;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/thermal/ThermalComponentIF.h +5903;COMPONENT_TEMP_OOL_LOW;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/thermal/ThermalComponentIF.h +5904;COMPONENT_TEMP_OOL_HIGH;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/thermal/ThermalComponentIF.h +5905;TEMP_NOT_IN_OP_RANGE;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/thermal/ThermalComponentIF.h +7101;FDIR_CHANGED_STATE;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/fdir/FailureIsolationBase.h +7102;FDIR_STARTS_RECOVERY;MEDIUM;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/fdir/FailureIsolationBase.h +7103;FDIR_TURNS_OFF_DEVICE;MEDIUM;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/fdir/FailureIsolationBase.h +7201;MONITOR_CHANGED_STATE;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/monitoring/MonitoringIF.h +7202;VALUE_BELOW_LOW_LIMIT;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/monitoring/MonitoringIF.h +7203;VALUE_ABOVE_HIGH_LIMIT;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/monitoring/MonitoringIF.h +7204;VALUE_OUT_OF_RANGE;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/monitoring/MonitoringIF.h +7301;SWITCHING_TM_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/datapool/HkSwitchHelper.h +7400;CHANGING_MODE;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/modes/HasModesIF.h +7401;MODE_INFO;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/modes/HasModesIF.h +7402;FALLBACK_FAILED;HIGH;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/modes/HasModesIF.h +7403;MODE_TRANSITION_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/modes/HasModesIF.h +7404;CANT_KEEP_MODE;HIGH;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/modes/HasModesIF.h +7405;OBJECT_IN_INVALID_MODE;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/modes/HasModesIF.h +7406;FORCING_MODE;MEDIUM;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/modes/HasModesIF.h +7407;MODE_CMD_REJECTED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/modes/HasModesIF.h +7506;HEALTH_INFO;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/health/HasHealthIF.h +7507;CHILD_CHANGED_HEALTH;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/health/HasHealthIF.h +7508;CHILD_PROBLEMS;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/health/HasHealthIF.h +7509;OVERWRITING_HEALTH;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/health/HasHealthIF.h +7510;TRYING_RECOVERY;MEDIUM;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/health/HasHealthIF.h +7511;RECOVERY_STEP;MEDIUM;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/health/HasHealthIF.h +7512;RECOVERY_DONE;MEDIUM;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/health/HasHealthIF.h +7900;RF_AVAILABLE;INFO;A RF available signal was detected. P1: raw RFA state, P2: 0;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/datalinklayer/DataLinkLayer.h +7901;RF_LOST;INFO;A previously found RF available signal was lost. P1: raw RFA state, P2: 0;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/datalinklayer/DataLinkLayer.h +7902;BIT_LOCK;INFO;A Bit Lock signal. Was detected. P1: raw BLO state, P2: 0;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/datalinklayer/DataLinkLayer.h +7903;BIT_LOCK_LOST;INFO;A previously found Bit Lock signal was lost. P1: raw BLO state, P2: 0;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/datalinklayer/DataLinkLayer.h +7905;FRAME_PROCESSING_FAILED;LOW;The CCSDS Board could not interpret a TC;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/datalinklayer/DataLinkLayer.h +8900;CLOCK_SET;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/pus/Service9TimeManagement.h +8901;CLOCK_SET_FAILURE;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/pus/Service9TimeManagement.h +9700;TEST;INFO;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/pus/Service17Test.h +10600;CHANGE_OF_SETUP_PARAMETER;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/fsfw/hal/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h +10900;GPIO_PULL_HIGH_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/HeaterHandler.h +10901;GPIO_PULL_LOW_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/HeaterHandler.h +10902;SWITCH_ALREADY_ON;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/HeaterHandler.h +10903;SWITCH_ALREADY_OFF;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/HeaterHandler.h +10904;MAIN_SWITCH_TIMEOUT;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/HeaterHandler.h +11000;MAIN_SWITCH_ON_TIMEOUT;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/linux/devices/SolarArrayDeploymentHandler.h +11001;MAIN_SWITCH_OFF_TIMEOUT;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/linux/devices/SolarArrayDeploymentHandler.h +11002;DEPLOYMENT_FAILED;HIGH;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/linux/devices/SolarArrayDeploymentHandler.h +11003;DEPL_SA1_GPIO_SWTICH_ON_FAILED;HIGH;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/linux/devices/SolarArrayDeploymentHandler.h +11004;DEPL_SA2_GPIO_SWTICH_ON_FAILED;HIGH;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/linux/devices/SolarArrayDeploymentHandler.h +11101;MEMORY_READ_RPT_CRC_FAILURE;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocMPSoCHandler.h +11102;ACK_FAILURE;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocMPSoCHandler.h +11103;EXE_FAILURE;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocMPSoCHandler.h +11104;CRC_FAILURE_EVENT;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocMPSoCHandler.h +11201;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/IMTQHandler.h +11202;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/IMTQHandler.h +11203;SELF_TEST_ADC_FAILURE;LOW;Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/IMTQHandler.h +11204;SELF_TEST_PWM_FAILURE;LOW;Get self test result returns PWM failure which concerns the coil actuation. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/IMTQHandler.h +11205;SELF_TEST_TC_FAILURE;LOW;Get self test result returns TC failure (system failure) P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/IMTQHandler.h +11206;SELF_TEST_MTM_RANGE_FAILURE;LOW;Get self test result returns failure that MTM values were outside of the expected range. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/IMTQHandler.h +11207;SELF_TEST_COIL_CURRENT_FAILURE;LOW;Get self test result returns failure indicating that the coil current was outside of the expected range P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/IMTQHandler.h +11208;INVALID_ERROR_BYTE;LOW;Received invalid error byte. This indicates an error of the communication link between IMTQ and OBC.;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/IMTQHandler.h +11301;ERROR_STATE;HIGH;Reaction wheel signals an error state;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/RwHandler.h +11501;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocSupervisorHandler.h +11502;SUPV_ACK_FAILURE;LOW;PLOC supervisor received acknowledgment failure report;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocSupervisorHandler.h +11503;SUPV_EXE_FAILURE;LOW;PLOC received execution failure report;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocSupervisorHandler.h +11504;SUPV_CRC_FAILURE_EVENT;LOW;PLOC supervisor reply has invalid crc;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocSupervisorHandler.h +11600;SANITIZATION_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/memory/SdCardManager.h +11700;UPDATE_FILE_NOT_EXISTS;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h +11701;ACTION_COMMANDING_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h +11702;UPDATE_AVAILABLE_FAILED;LOW;Supervisor handler replied action message indicating a command execution failure of the update available command;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h +11703;UPDATE_TRANSFER_FAILED;LOW;Supervisor handler failed to transfer an update space packet. P1: Parameter holds the number of update packets already sent (inclusive the failed packet);C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h +11704;UPDATE_VERIFY_FAILED;LOW;Supervisor failed to execute the update verify command.;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h +11705;UPDATE_FINISHED;INFO;MPSoC update successful completed;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h +11800;SEND_MRAM_DUMP_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocMemoryDumper.h +11801;MRAM_DUMP_FAILED;LOW;Received completion failure report form PLOC supervisor handler P1: MRAM start address of failing dump command;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocMemoryDumper.h +11802;MRAM_DUMP_FINISHED;LOW;MRAM dump finished successfully;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocMemoryDumper.h +11901;INVALID_TC_FRAME;HIGH;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/linux/obc/PdecHandler.h +11902;INVALID_FAR;HIGH;Read invalid FAR from PDEC after startup;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/linux/obc/PdecHandler.h +11903;CARRIER_LOCK;INFO;Carrier lock detected;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/linux/obc/PdecHandler.h +11904;BIT_LOCK_PDEC;INFO;Bit lock detected (data valid);C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/linux/obc/PdecHandler.h +12000;IMAGE_UPLOAD_FAILED;LOW;Image upload failed;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12001;IMAGE_DOWNLOAD_FAILED;LOW;Image download failed;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12002;IMAGE_UPLOAD_SUCCESSFUL;LOW;Uploading image to star tracker was successful;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12003;IMAGE_DOWNLOAD_SUCCESSFUL;LOW;Image download was successful;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12004;FLASH_WRITE_SUCCESSFUL;LOW;Finished flash write procedure successfully;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12005;FLASH_READ_SUCCESSFUL;LOW;Finished flash read procedure successfully;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12006;FLASH_WRITE_FAILED;LOW;Flash write procedure failed;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12007;FLASH_READ_FAILED;LOW;Flash read procedure failed;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12008;STR_HELPER_READING_REPLY_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12009;STR_HELPER_COM_ERROR;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12010;STR_HELPER_NO_REPLY;LOW;Star tracker did not send replies (maybe device is powered off)P1: Position of upload or download packet for which no reply was sent;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12011;INVALID_TYPE_ID;LOW;Received reply with invalid type ID;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12012;STATUS_ERROR;LOW;Status field in reply signals error;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12013;STR_HELPER_DEC_ERROR;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12014;POSITION_MISMATCH;LOW;Position mismatch P1: The expected position and thus the position for which the image upload/download failed;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12015;STR_HELPER_FILE_NOT_EXISTS;LOW;Specified file does not existP1: Internal state of str helper;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12016;STR_HELPER_SENDING_PACKET_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h +12017;STR_HELPER_REQUESTING_MSG_FAILED;LOW;;C:\Users\jakob\OneDrive\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/startracker/StrHelper.h diff --git a/generators/bsp_q7s_objects.csv b/generators/bsp_q7s_objects.csv index fded183b..af48751f 100644 --- a/generators/bsp_q7s_objects.csv +++ b/generators/bsp_q7s_objects.csv @@ -27,7 +27,7 @@ 0x44120309;MGM_3_RM3100_HANDLER 0x44120313;GYRO_3_L3G_HANDLER 0x44120350;RW4 -0x44130001;START_TRACKER +0x44130001;STAR_TRACKER 0x44130045;GPS0_HANDLER 0x44130146;GPS1_HANDLER 0x44140014;IMTQ_HANDLER @@ -39,6 +39,7 @@ 0x443200A5;RAD_SENSOR 0x44330000;PLOC_UPDATER 0x44330001;PLOC_MEMORY_DUMPER +0x44330002;STR_HELPER 0x44330015;PLOC_MPSOC_HANDLER 0x44330016;PLOC_SUPERVISOR_HANDLER 0x444100A2;SOLAR_ARRAY_DEPL_HANDLER diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index 943468c5..76159e0c 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 120 translations. + * @brief Auto-generated event translation file. Contains 138 translations. * @details - * Generated on: 2021-11-25 14:09:00 + * Generated on: 2021-12-21 17:08:50 */ #include "translateEvents.h" @@ -125,6 +125,24 @@ const char *INVALID_TC_FRAME_STRING = "INVALID_TC_FRAME"; const char *INVALID_FAR_STRING = "INVALID_FAR"; const char *CARRIER_LOCK_STRING = "CARRIER_LOCK"; const char *BIT_LOCK_PDEC_STRING = "BIT_LOCK_PDEC"; +const char *IMAGE_UPLOAD_FAILED_STRING = "IMAGE_UPLOAD_FAILED"; +const char *IMAGE_DOWNLOAD_FAILED_STRING = "IMAGE_DOWNLOAD_FAILED"; +const char *IMAGE_UPLOAD_SUCCESSFUL_STRING = "IMAGE_UPLOAD_SUCCESSFUL"; +const char *IMAGE_DOWNLOAD_SUCCESSFUL_STRING = "IMAGE_DOWNLOAD_SUCCESSFUL"; +const char *FLASH_WRITE_SUCCESSFUL_STRING = "FLASH_WRITE_SUCCESSFUL"; +const char *FLASH_READ_SUCCESSFUL_STRING = "FLASH_READ_SUCCESSFUL"; +const char *FLASH_WRITE_FAILED_STRING = "FLASH_WRITE_FAILED"; +const char *FLASH_READ_FAILED_STRING = "FLASH_READ_FAILED"; +const char *STR_HELPER_READING_REPLY_FAILED_STRING = "STR_HELPER_READING_REPLY_FAILED"; +const char *STR_HELPER_COM_ERROR_STRING = "STR_HELPER_COM_ERROR"; +const char *STR_HELPER_NO_REPLY_STRING = "STR_HELPER_NO_REPLY"; +const char *INVALID_TYPE_ID_STRING = "INVALID_TYPE_ID"; +const char *STATUS_ERROR_STRING = "STATUS_ERROR"; +const char *STR_HELPER_DEC_ERROR_STRING = "STR_HELPER_DEC_ERROR"; +const char *POSITION_MISMATCH_STRING = "POSITION_MISMATCH"; +const char *STR_HELPER_FILE_NOT_EXISTS_STRING = "STR_HELPER_FILE_NOT_EXISTS"; +const char *STR_HELPER_SENDING_PACKET_FAILED_STRING = "STR_HELPER_SENDING_PACKET_FAILED"; +const char *STR_HELPER_REQUESTING_MSG_FAILED_STRING = "STR_HELPER_REQUESTING_MSG_FAILED"; const char * translateEvents(Event event) { switch( (event & 0xffff) ) { @@ -368,6 +386,42 @@ const char * translateEvents(Event event) { return CARRIER_LOCK_STRING; case(11904): return BIT_LOCK_PDEC_STRING; + case(12000): + return IMAGE_UPLOAD_FAILED_STRING; + case(12001): + return IMAGE_DOWNLOAD_FAILED_STRING; + case(12002): + return IMAGE_UPLOAD_SUCCESSFUL_STRING; + case(12003): + return IMAGE_DOWNLOAD_SUCCESSFUL_STRING; + case(12004): + return FLASH_WRITE_SUCCESSFUL_STRING; + case(12005): + return FLASH_READ_SUCCESSFUL_STRING; + case(12006): + return FLASH_WRITE_FAILED_STRING; + case(12007): + return FLASH_READ_FAILED_STRING; + case(12008): + return STR_HELPER_READING_REPLY_FAILED_STRING; + case(12009): + return STR_HELPER_COM_ERROR_STRING; + case(12010): + return STR_HELPER_NO_REPLY_STRING; + case(12011): + return INVALID_TYPE_ID_STRING; + case(12012): + return STATUS_ERROR_STRING; + case(12013): + return STR_HELPER_DEC_ERROR_STRING; + case(12014): + return POSITION_MISMATCH_STRING; + case(12015): + return STR_HELPER_FILE_NOT_EXISTS_STRING; + case(12016): + return STR_HELPER_SENDING_PACKET_FAILED_STRING; + case(12017): + return STR_HELPER_REQUESTING_MSG_FAILED_STRING; default: return "UNKNOWN_EVENT"; } diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index 48eb29e7..49900a5d 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -1,8 +1,8 @@ /** * @brief Auto-generated object translation file. * @details - * Contains 112 translations. - * Generated on: 2021-11-22 17:04:51 + * Contains 113 translations. + * Generated on: 2021-12-21 17:21:23 */ #include "translateObjects.h" @@ -35,7 +35,7 @@ const char *RW3_STRING = "RW3"; const char *MGM_3_RM3100_HANDLER_STRING = "MGM_3_RM3100_HANDLER"; const char *GYRO_3_L3G_HANDLER_STRING = "GYRO_3_L3G_HANDLER"; const char *RW4_STRING = "RW4"; -const char *START_TRACKER_STRING = "START_TRACKER"; +const char *STAR_TRACKER_STRING = "STAR_TRACKER"; const char *GPS0_HANDLER_STRING = "GPS0_HANDLER"; const char *GPS1_HANDLER_STRING = "GPS1_HANDLER"; const char *IMTQ_HANDLER_STRING = "IMTQ_HANDLER"; @@ -47,6 +47,7 @@ const char *ACU_HANDLER_STRING = "ACU_HANDLER"; const char *RAD_SENSOR_STRING = "RAD_SENSOR"; const char *PLOC_UPDATER_STRING = "PLOC_UPDATER"; const char *PLOC_MEMORY_DUMPER_STRING = "PLOC_MEMORY_DUMPER"; +const char *STR_HELPER_STRING = "STR_HELPER"; const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER"; const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER"; const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER"; @@ -180,7 +181,7 @@ const char* translateObject(object_id_t object) { case 0x44120350: return RW4_STRING; case 0x44130001: - return START_TRACKER_STRING; + return STAR_TRACKER_STRING; case 0x44130045: return GPS0_HANDLER_STRING; case 0x44130146: @@ -203,6 +204,8 @@ const char* translateObject(object_id_t object) { return PLOC_UPDATER_STRING; case 0x44330001: return PLOC_MEMORY_DUMPER_STRING; + case 0x44330002: + return STR_HELPER_STRING; case 0x44330015: return PLOC_MPSOC_HANDLER_STRING; case 0x44330016: diff --git a/linux/devices/CMakeLists.txt b/linux/devices/CMakeLists.txt index bf0a556e..b02c8e57 100644 --- a/linux/devices/CMakeLists.txt +++ b/linux/devices/CMakeLists.txt @@ -1,5 +1,4 @@ target_sources(${TARGET_NAME} PRIVATE SolarArrayDeploymentHandler.cpp SusHandler.cpp - StarTrackerHandler.cpp ) diff --git a/linux/devices/StarTrackerHandler.cpp b/linux/devices/StarTrackerHandler.cpp deleted file mode 100644 index c5718f02..00000000 --- a/linux/devices/StarTrackerHandler.cpp +++ /dev/null @@ -1,216 +0,0 @@ -#include "StarTrackerHandler.h" -#include "OBSWConfig.h" - -#include -#include - -extern "C" { - #include - #include "common/misc.h" -} - -StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF, - CookieIF * comCookie) : - DeviceHandlerBase(objectId, comIF, comCookie), temperatureSet(this) { - if (comCookie == NULL) { - sif::error << "StarTrackerHandler: Invalid com cookie" << std::endl; - } - slipInit(); -} - -StarTrackerHandler::~StarTrackerHandler() { -} - -void StarTrackerHandler::doStartUp() { - -#if OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP == 1 - setMode(MODE_NORMAL); -#else - setMode(_MODE_TO_ON); -#endif -} - -void StarTrackerHandler::doShutDown() { - setMode(_MODE_POWER_DOWN); -} - -ReturnValue_t StarTrackerHandler::buildNormalDeviceCommand(DeviceCommandId_t * id) { - switch (internalState) { - case InternalState::TEMPERATURE_REQUEST: - *id = StarTracker::REQ_TEMPERATURE; - break; - default: - sif::debug << "StarTrackerHandler::buildNormalDeviceCommand: Invalid internal step" - << std::endl; - break; - } - return buildCommandFromCommand(*id, NULL, 0); -} - -ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t * id) { - return NOTHING_TO_SEND; -} - -ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand, - const uint8_t * commandData, size_t commandDataLen) { - - switch (deviceCommand) { - case (StarTracker::REQ_TEMPERATURE): { - prepareTemperatureRequest(); - return RETURN_OK; - } - default: - return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; - } - return HasReturnvaluesIF::RETURN_FAILED; -} - -void StarTrackerHandler::fillCommandAndReplyMap() { - /** Reply lengths are unknown because of the slip encoding. Thus always maximum reply size - * is specified */ - this->insertInCommandAndReplyMap(StarTracker::REQ_TEMPERATURE, 1, &temperatureSet, - StarTracker::MAX_FRAME_SIZE * 2 + 2); -} - -ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t *start, size_t remainingSize, - DeviceCommandId_t *foundId, size_t *foundLen) { - - uint32_t decodedLength = 0; - - for (size_t idx = 0; idx < remainingSize; idx++) { - enum arc_dec_result decResult = arc_transport_decode_body(*(start + idx), &slipInfo, - decodedFrame, &decodedLength); - - switch (decResult) { - case ARC_DEC_INPROGRESS: { - continue; - } - case ARC_DEC_ASYNC: { - sif::debug << "StarTrackerHandler::scanForReply: Received asynchronous tm" << std::endl; - /** No asynchronous replies are expected as of now */ - return RETURN_FAILED; - } - case ARC_DEC_ERROR_FRAME_SHORT: - return REPLY_TOO_SHORT; - case ARC_DEC_ERROR_CHECKSUM: - return CRC_FAILURE; - case ARC_DEC_SYNC: { - /** Reset length of SLIP struct for next frame */ - slipInfo.length = 0; - break; - } - default: - sif::debug << "StarTrackerHandler::scanForReply: Unknown result code" << std::endl; - break; - } - } - - switch (decodedFrame[1]) { - case (static_cast(StarTracker::REQ_TEMPERATURE)): { - *foundLen = decodedLength; - *foundId = StarTracker::REQ_TEMPERATURE; - break; - } - default: { - sif::debug << "StarTrackerHandler::scanForReply: Reply contains invalid reply id" - << std::endl; - return RETURN_FAILED; - break; - } - } - - return RETURN_OK; -} - -ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { - - switch (id) { - case (StarTracker::REQ_TEMPERATURE): { - handleTemperatureTm(); - break; - } - default: { - sif::debug << "StarTrackerHandler::interpretDeviceReply: Unknown device reply id" << std::endl; - return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY; - } - } - - return RETURN_OK; -} - -void StarTrackerHandler::setNormalDatapoolEntriesInvalid() { - -} - -uint32_t StarTrackerHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { - return 5000; -} - -ReturnValue_t StarTrackerHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, - LocalDataPoolManager& poolManager) { - - localDataPoolMap.emplace(StarTracker::STATUS, new PoolEntry( { 0 })); - localDataPoolMap.emplace(StarTracker::TICKS, new PoolEntry( { 0 })); - localDataPoolMap.emplace(StarTracker::TIME, new PoolEntry( { 0 })); - localDataPoolMap.emplace(StarTracker::MCU_TEMPERATURE, new PoolEntry( { 0 })); - localDataPoolMap.emplace(StarTracker::CMOS_TEMPERATURE, new PoolEntry( { 0 })); - - return RETURN_OK; -} - -size_t StarTrackerHandler::getNextReplyLength(DeviceCommandId_t commandId){ - return StarTracker::MAX_FRAME_SIZE; -} - -void StarTrackerHandler::slipInit() { - slipInfo.buffer = rxBuffer; - slipInfo.maxlength = StarTracker::MAX_FRAME_SIZE; - slipInfo.length = 0; - slipInfo.unescape_next = 0; - slipInfo.prev_state = SLIP_COMPLETE; -} - -void StarTrackerHandler::prepareTemperatureRequest() { - uint32_t length = 0; - arc_tm_pack_temperature_req(commandBuffer, &length); - uint32_t encLength = 0; - arc_transport_encode_body(commandBuffer, length, encBuffer, &encLength); - rawPacket = encBuffer; - rawPacketLen = encLength; -} - -void StarTrackerHandler::handleTemperatureTm() { - PoolReadGuard rg(&temperatureSet); - uint32_t offset = 1; - temperatureSet.status = *(decodedFrame + offset); - offset += 1; - if(temperatureSet.status.value != 0) { - sif::warning << "StarTrackerHandler::handleTemperatureTm: Reply error: " - << static_cast(temperatureSet.status.value) << std::endl; - triggerEvent(TM_REPLY_ERROR, temperatureSet.status.value); - } - temperatureSet.ticks = *(decodedFrame + offset) << 24 - | *(decodedFrame + offset + 1) << 16 | *(decodedFrame + offset + 2) << 8 - | *(decodedFrame + offset + 3); - offset += 4; - temperatureSet.time = static_cast(*(decodedFrame + offset)) << 56 - | static_cast(*(decodedFrame + offset + 1)) << 48 - | static_cast(*(decodedFrame + offset + 2)) << 40 - | static_cast(*(decodedFrame + offset + 3)) << 32 - | *(decodedFrame + offset + 4) << 24 | *(decodedFrame + offset + 5) << 16 - | *(decodedFrame + offset + 6) << 8 | *(decodedFrame + offset + 7); - offset += 8; - temperatureSet.mcuTemperature = *(decodedFrame + offset) << 24 - | *(decodedFrame + offset + 1) << 16 | *(decodedFrame + offset + 2) << 8 - | *(decodedFrame + offset + 3); - offset += 4; - temperatureSet.cmosTemperature = *(decodedFrame + offset) << 24 - | *(decodedFrame + offset + 1) << 16 | *(decodedFrame + offset + 2) << 8 - | *(decodedFrame + offset + 3); -#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1 - sif::info << "StarTrackerHandler::handleTemperatureTm: MCU Temperature: " - << temperatureSet.mcuTemperature << " °C" << std::endl; - sif::info << "StarTrackerHandler::handleTemperatureTm: CMOS Temperature: " - << temperatureSet.mcuTemperature << " °C" << std::endl; -#endif -} diff --git a/linux/devices/StarTrackerHandler.h b/linux/devices/StarTrackerHandler.h deleted file mode 100644 index d659b9a8..00000000 --- a/linux/devices/StarTrackerHandler.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef MISSION_DEVICES_STARTRACKERHANDLER_H_ -#define MISSION_DEVICES_STARTRACKERHANDLER_H_ - -#include -#include -#include - -/** - * @brief This is the device handler for the star tracker from arcsec. - * - * @details Datasheet: https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/ - * Arbeitsdaten/08_Used%20Components/ArcSec_KULeuven_Startracker/ - * Sagitta%201.0%20Datapack&fileid=659181 - * - * @author J. Meier - */ -class StarTrackerHandler: public DeviceHandlerBase { -public: - - /** - * @brief Constructor - * - * @param objectId - * @param comIF - * @param comCookie - * @param gpioComIF Pointer to gpio communication interface - * @param enablePin GPIO connected to the enable pin of the reaction wheels. Must be pulled - * to high to enable the device. - */ - StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie); - virtual ~StarTrackerHandler(); - -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; - - /** - * @brief Overwritten here to always read all available data from the UartComIF. - */ - virtual size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override; - -private: - - static const uint8_t INTERFACE_ID = CLASS_ID::STR_HANDLER; - - //! [EXPORT] : [COMMENT] Received reply is too short - static const ReturnValue_t REPLY_TOO_SHORT = MAKE_RETURN_CODE(0xB0); - //! [EXPORT] : [COMMENT] Received reply with invalid CRC - static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xB0); - - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::STR_HANDLER; - - //! [EXPORT] : [COMMENT] Result code of tm reply indicates an error - static const ReturnValue_t TM_REPLY_ERROR = MAKE_RETURN_CODE(0xA0); - //! P1: TM id - - StarTracker::TemperatureSet temperatureSet; - - uint8_t commandBuffer[StarTracker::MAX_FRAME_SIZE]; - uint8_t rxBuffer[StarTracker::MAX_FRAME_SIZE]; - uint8_t decodedFrame[StarTracker::MAX_FRAME_SIZE]; - - /** Size of buffer derived from the egse source code */ - uint8_t encBuffer[StarTracker::MAX_FRAME_SIZE * 2 + 2]; - - slip_decode_state slipInfo; - - enum class InternalState { - TEMPERATURE_REQUEST - }; - - InternalState internalState = InternalState::TEMPERATURE_REQUEST; - - /** - * @brief This function initializes the serial link ip protocol struct slipInfo. - */ - void slipInit(); - - void prepareTemperatureRequest(); - - /** - * @brief This function handles the telemetry reply of a temperature request. - */ - void handleTemperatureTm(); -}; - -#endif /* MISSION_DEVICES_STARTRACKERHANDLER_H_ */ diff --git a/linux/devices/devicedefinitions/StarTrackerDefinitions.h b/linux/devices/devicedefinitions/StarTrackerDefinitions.h deleted file mode 100644 index 6c28219b..00000000 --- a/linux/devices/devicedefinitions/StarTrackerDefinitions.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef MISSION_STARTRACKER_DEFINITIONS_H_ -#define MISSION_STARTRACKER_DEFINITIONS_H_ - -#include -#include -#include -#include "objects/systemObjectList.h" - -namespace StarTracker { - -/** This is the address of the star tracker */ -static const uint8_t ADDRESS = 33; - -enum PoolIds: lp_id_t { - STATUS, - TICKS, - TIME, - MCU_TEMPERATURE, - CMOS_TEMPERATURE -}; - - - -static const DeviceCommandId_t REQ_TEMPERATURE = 25; - -static const uint32_t TEMPERATURE_SET_ID = REQ_TEMPERATURE; - -/** Max size of unencoded frame */ -static const size_t MAX_FRAME_SIZE = 1200; - -static const uint8_t TEMPERATURE_SET_ENTRIES = 5; - -/** - * @brief This dataset can be used to store the temperature of a reaction wheel. - */ -class TemperatureSet: - public StaticLocalDataSet { -public: - - TemperatureSet(HasLocalDataPoolIF* owner): - StaticLocalDataSet(owner, TEMPERATURE_SET_ID) { - } - - TemperatureSet(object_id_t objectId): - StaticLocalDataSet(sid_t(objectId, TEMPERATURE_SET_ID)) { - } - - lp_var_t status = lp_var_t(sid.objectId, - PoolIds::STATUS, this); - lp_var_t ticks = lp_var_t(sid.objectId, - PoolIds::TICKS, this); - /** Unix time in microseconds */ - lp_var_t time = lp_var_t(sid.objectId, - PoolIds::TIME, this); - lp_var_t mcuTemperature = lp_var_t(sid.objectId, - PoolIds::MCU_TEMPERATURE, this); - lp_var_t cmosTemperature = lp_var_t(sid.objectId, - PoolIds::CMOS_TEMPERATURE, this); -}; - -} - -#endif /* MISSION_STARTRACKER_DEFINITIONS_H_ */ - diff --git a/linux/fsfwconfig/OBSWConfig.h.in b/linux/fsfwconfig/OBSWConfig.h.in index 1f12b579..4a7bca35 100644 --- a/linux/fsfwconfig/OBSWConfig.h.in +++ b/linux/fsfwconfig/OBSWConfig.h.in @@ -109,7 +109,7 @@ debugging. */ #define OBSW_DEBUG_STARTRACKER 0 #define OBSW_DEBUG_PLOC_MPSOC 0 #define OBSW_DEBUG_PLOC_SUPERVISOR 0 -#define OBSW_DEBUG_PDEC_HANDLER 0 +#define OBSW_DEBUG_PDEC_HANDLER 1 /*******************************************************************/ /** Hardcoded */ @@ -131,6 +131,7 @@ namespace config { /* Add mission configuration flags here */ static constexpr uint32_t OBSW_FILESYSTEM_HANDLER_QUEUE_SIZE = 50; static constexpr uint32_t PLOC_UPDATER_QUEUE_SIZE = 50; +static constexpr uint32_t STR_IMG_HELPER_QUEUE_SIZE = 50; static constexpr uint8_t LIVE_TM = 0; diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index 943468c5..76159e0c 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 120 translations. + * @brief Auto-generated event translation file. Contains 138 translations. * @details - * Generated on: 2021-11-25 14:09:00 + * Generated on: 2021-12-21 17:08:50 */ #include "translateEvents.h" @@ -125,6 +125,24 @@ const char *INVALID_TC_FRAME_STRING = "INVALID_TC_FRAME"; const char *INVALID_FAR_STRING = "INVALID_FAR"; const char *CARRIER_LOCK_STRING = "CARRIER_LOCK"; const char *BIT_LOCK_PDEC_STRING = "BIT_LOCK_PDEC"; +const char *IMAGE_UPLOAD_FAILED_STRING = "IMAGE_UPLOAD_FAILED"; +const char *IMAGE_DOWNLOAD_FAILED_STRING = "IMAGE_DOWNLOAD_FAILED"; +const char *IMAGE_UPLOAD_SUCCESSFUL_STRING = "IMAGE_UPLOAD_SUCCESSFUL"; +const char *IMAGE_DOWNLOAD_SUCCESSFUL_STRING = "IMAGE_DOWNLOAD_SUCCESSFUL"; +const char *FLASH_WRITE_SUCCESSFUL_STRING = "FLASH_WRITE_SUCCESSFUL"; +const char *FLASH_READ_SUCCESSFUL_STRING = "FLASH_READ_SUCCESSFUL"; +const char *FLASH_WRITE_FAILED_STRING = "FLASH_WRITE_FAILED"; +const char *FLASH_READ_FAILED_STRING = "FLASH_READ_FAILED"; +const char *STR_HELPER_READING_REPLY_FAILED_STRING = "STR_HELPER_READING_REPLY_FAILED"; +const char *STR_HELPER_COM_ERROR_STRING = "STR_HELPER_COM_ERROR"; +const char *STR_HELPER_NO_REPLY_STRING = "STR_HELPER_NO_REPLY"; +const char *INVALID_TYPE_ID_STRING = "INVALID_TYPE_ID"; +const char *STATUS_ERROR_STRING = "STATUS_ERROR"; +const char *STR_HELPER_DEC_ERROR_STRING = "STR_HELPER_DEC_ERROR"; +const char *POSITION_MISMATCH_STRING = "POSITION_MISMATCH"; +const char *STR_HELPER_FILE_NOT_EXISTS_STRING = "STR_HELPER_FILE_NOT_EXISTS"; +const char *STR_HELPER_SENDING_PACKET_FAILED_STRING = "STR_HELPER_SENDING_PACKET_FAILED"; +const char *STR_HELPER_REQUESTING_MSG_FAILED_STRING = "STR_HELPER_REQUESTING_MSG_FAILED"; const char * translateEvents(Event event) { switch( (event & 0xffff) ) { @@ -368,6 +386,42 @@ const char * translateEvents(Event event) { return CARRIER_LOCK_STRING; case(11904): return BIT_LOCK_PDEC_STRING; + case(12000): + return IMAGE_UPLOAD_FAILED_STRING; + case(12001): + return IMAGE_DOWNLOAD_FAILED_STRING; + case(12002): + return IMAGE_UPLOAD_SUCCESSFUL_STRING; + case(12003): + return IMAGE_DOWNLOAD_SUCCESSFUL_STRING; + case(12004): + return FLASH_WRITE_SUCCESSFUL_STRING; + case(12005): + return FLASH_READ_SUCCESSFUL_STRING; + case(12006): + return FLASH_WRITE_FAILED_STRING; + case(12007): + return FLASH_READ_FAILED_STRING; + case(12008): + return STR_HELPER_READING_REPLY_FAILED_STRING; + case(12009): + return STR_HELPER_COM_ERROR_STRING; + case(12010): + return STR_HELPER_NO_REPLY_STRING; + case(12011): + return INVALID_TYPE_ID_STRING; + case(12012): + return STATUS_ERROR_STRING; + case(12013): + return STR_HELPER_DEC_ERROR_STRING; + case(12014): + return POSITION_MISMATCH_STRING; + case(12015): + return STR_HELPER_FILE_NOT_EXISTS_STRING; + case(12016): + return STR_HELPER_SENDING_PACKET_FAILED_STRING; + case(12017): + return STR_HELPER_REQUESTING_MSG_FAILED_STRING; default: return "UNKNOWN_EVENT"; } diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index 48eb29e7..49900a5d 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -1,8 +1,8 @@ /** * @brief Auto-generated object translation file. * @details - * Contains 112 translations. - * Generated on: 2021-11-22 17:04:51 + * Contains 113 translations. + * Generated on: 2021-12-21 17:21:23 */ #include "translateObjects.h" @@ -35,7 +35,7 @@ const char *RW3_STRING = "RW3"; const char *MGM_3_RM3100_HANDLER_STRING = "MGM_3_RM3100_HANDLER"; const char *GYRO_3_L3G_HANDLER_STRING = "GYRO_3_L3G_HANDLER"; const char *RW4_STRING = "RW4"; -const char *START_TRACKER_STRING = "START_TRACKER"; +const char *STAR_TRACKER_STRING = "STAR_TRACKER"; const char *GPS0_HANDLER_STRING = "GPS0_HANDLER"; const char *GPS1_HANDLER_STRING = "GPS1_HANDLER"; const char *IMTQ_HANDLER_STRING = "IMTQ_HANDLER"; @@ -47,6 +47,7 @@ const char *ACU_HANDLER_STRING = "ACU_HANDLER"; const char *RAD_SENSOR_STRING = "RAD_SENSOR"; const char *PLOC_UPDATER_STRING = "PLOC_UPDATER"; const char *PLOC_MEMORY_DUMPER_STRING = "PLOC_MEMORY_DUMPER"; +const char *STR_HELPER_STRING = "STR_HELPER"; const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER"; const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER"; const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER"; @@ -180,7 +181,7 @@ const char* translateObject(object_id_t object) { case 0x44120350: return RW4_STRING; case 0x44130001: - return START_TRACKER_STRING; + return STAR_TRACKER_STRING; case 0x44130045: return GPS0_HANDLER_STRING; case 0x44130146: @@ -203,6 +204,8 @@ const char* translateObject(object_id_t object) { return PLOC_UPDATER_STRING; case 0x44330001: return PLOC_MEMORY_DUMPER_STRING; + case 0x44330002: + return STR_HELPER_STRING; case 0x44330015: return PLOC_MPSOC_HANDLER_STRING; case 0x44330016: diff --git a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp index be38fd89..474483ca 100644 --- a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp +++ b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp @@ -568,7 +568,6 @@ ReturnValue_t pst::pstI2c(FixedTimeslotTaskIF *thisSequence) { ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { // Length of a communication cycle uint32_t length = thisSequence->getPeriodMs(); - static_cast(length); bool uartPstEmpty = true; #if OBSW_ADD_PLOC_MPSOC == 1 @@ -649,11 +648,11 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { #if OBSW_ADD_STAR_TRACKER == 1 uartPstEmpty = false; - thisSequence->addSlot(objects::START_TRACKER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); - thisSequence->addSlot(objects::START_TRACKER, length * 0.2, DeviceHandlerIF::SEND_WRITE); - thisSequence->addSlot(objects::START_TRACKER, length * 0.4, DeviceHandlerIF::GET_WRITE); - thisSequence->addSlot(objects::START_TRACKER, length * 0.6, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::START_TRACKER, length * 0.8, DeviceHandlerIF::GET_READ); + thisSequence->addSlot(objects::STAR_TRACKER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::STAR_TRACKER, length * 0.2, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::STAR_TRACKER, length * 0.4, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::STAR_TRACKER, length * 0.6, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::STAR_TRACKER, length * 0.8, DeviceHandlerIF::GET_READ); #endif if(uartPstEmpty) { diff --git a/linux/obc/PdecHandler.cpp b/linux/obc/PdecHandler.cpp index 1ac83d44..aa46c23c 100644 --- a/linux/obc/PdecHandler.cpp +++ b/linux/obc/PdecHandler.cpp @@ -262,7 +262,7 @@ bool PdecHandler::checkFrameAna(uint32_t pdecFar) { } case(FrameAna_t::FRAME_DIRTY): { triggerEvent(INVALID_TC_FRAME, FRAME_DIRTY); - sif::debug << "PdecHandler::checkFrameAna: Frame dirty" << std::endl; + sif::warning << "PdecHandler::checkFrameAna: Frame dirty" << std::endl; break; } case(FrameAna_t::FRAME_ILLEGAL): { @@ -314,50 +314,50 @@ void PdecHandler::handleIReason(uint32_t pdecFar, ReturnValue_t parameter1) { switch(ireason) { case(IReason_t::NO_REPORT): { triggerEvent(INVALID_TC_FRAME, parameter1, NO_REPORT); - sif::debug << "PdecHandler::handleIReason: No illegal report" << std::endl; + sif::info << "PdecHandler::handleIReason: No illegal report" << std::endl; break; } case(IReason_t::ERROR_VERSION_NUMBER): { triggerEvent(INVALID_TC_FRAME, parameter1, ERROR_VERSION_NUMBER); - sif::debug << "PdecHandler::handleIReason: Error in version number and reserved A and B " + sif::info << "PdecHandler::handleIReason: Error in version number and reserved A and B " << "fields" << std::endl; break; } case(IReason_t::ILLEGAL_COMBINATION): { triggerEvent(INVALID_TC_FRAME, parameter1, ILLEGAL_COMBINATION); - sif::debug << "PdecHandler::handleIReason: Illegal combination (AC) of bypass and control " + sif::info << "PdecHandler::handleIReason: Illegal combination (AC) of bypass and control " << "command flags" << std::endl; break; } case(IReason_t::INVALID_SC_ID): { triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_SC_ID); - sif::debug << "PdecHandler::handleIReason: Invalid spacecraft identifier " << std::endl; + sif::info << "PdecHandler::handleIReason: Invalid spacecraft identifier " << std::endl; break; } case(IReason_t::INVALID_VC_ID_MSB): { triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_VC_ID_MSB); - sif::debug << "PdecHandler::handleIReason: VC identifier bit 0 to 4 did not match " + sif::info << "PdecHandler::handleIReason: VC identifier bit 0 to 4 did not match " << std::endl; break; } case(IReason_t::INVALID_VC_ID_LSB): { triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_VC_ID_LSB); - sif::debug << "PdecHandler::handleIReason: VC identifier bit 5 did not match " << std::endl; + sif::info << "PdecHandler::handleIReason: VC identifier bit 5 did not match " << std::endl; break; } case(IReason_t::NS_NOT_ZERO): { triggerEvent(INVALID_TC_FRAME, parameter1, NS_NOT_ZERO); - sif::debug << "PdecHandler::handleIReason: N(S) of BC or BD frame not set to all zeros" + sif::info << "PdecHandler::handleIReason: N(S) of BC or BD frame not set to all zeros" << std::endl; break; } case(IReason_t::INCORRECT_BC_CC): { triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_BC_CC); - sif::debug << "PdecHandler::handleIReason: Invalid BC control command format" << std::endl; + sif::info << "PdecHandler::handleIReason: Invalid BC control command format" << std::endl; break; } default: { - sif::debug << "PdecHandler::handleIReason: Invalid reason id" << std::endl; + sif::info << "PdecHandler::handleIReason: Invalid reason id" << std::endl; break; } } @@ -373,7 +373,7 @@ void PdecHandler::handleNewTc() { } #if OBSW_DEBUG_PDEC_HANDLER == 1 unsigned int mapId = tcSegment[0] & MAP_ID_MASK; - sif::debug << "PdecHandler::handleNewTc: Received TC segment with map ID " << mapId + sif::info << "PdecHandler::handleNewTc: Received TC segment with map ID " << mapId << std::endl; printTC(tcLength); #endif /* OBSW_DEBUG_PDEC_HANDLER */ @@ -460,7 +460,7 @@ void PdecHandler::printTC(uint32_t tcLength) { tcSegmentStream << std::setfill('0') << std::setw(2) << std::hex << static_cast(tcSegment[idx]); } - sif::debug << tcSegmentStream.str() << std::endl; + sif::info << tcSegmentStream.str() << std::endl; } uint8_t PdecHandler::calcMapAddrEntry(uint8_t moduleId) { @@ -484,6 +484,10 @@ uint32_t PdecHandler::getClcw() { return *(registerBaseAddress + PDEC_CLCW_OFFSET); } +uint32_t PdecHandler::getPdecMon() { + return *(registerBaseAddress + PDEC_MON_OFFSET); +} + void PdecHandler::printClcw() { uint32_t clcw = getClcw(); uint8_t type = static_cast((clcw >> 31) & 0x1); @@ -525,6 +529,39 @@ void PdecHandler::printClcw() { << "0x" << static_cast(repValue) << std::endl; } +void PdecHandler::printPdecMon() { + uint32_t pdecMon = getPdecMon(); + uint32_t tc0ChannelStatus = (pdecMon & TC0_STATUS_MASK) >> TC0_STATUS_POS; + uint32_t tc1ChannelStatus = (pdecMon & TC1_STATUS_MASK) >> TC1_STATUS_POS; + uint32_t tc2ChannelStatus = (pdecMon & TC2_STATUS_MASK) >> TC2_STATUS_POS; + uint32_t tc3ChannelStatus = (pdecMon & TC3_STATUS_MASK) >> TC3_STATUS_POS; + uint32_t tc4ChannelStatus = (pdecMon & TC4_STATUS_MASK) >> TC4_STATUS_POS; + uint32_t tc5ChannelStatus = (pdecMon & TC5_STATUS_MASK) >> TC5_STATUS_POS; + uint32_t lock = (pdecMon & LOCK_MASK) >> LOCK_POS; + sif::info << std::setw(30) << std::left << "TC0 status: " << getMonStatusString(tc0ChannelStatus) << std::endl; + sif::info << std::setw(30) << std::left << "TC1 status: " << getMonStatusString(tc1ChannelStatus) << std::endl; + sif::info << std::setw(30) << std::left << "TC2 status: " << getMonStatusString(tc2ChannelStatus) << std::endl; + sif::info << std::setw(30) << std::left << "TC3 status: " << getMonStatusString(tc3ChannelStatus) << std::endl; + sif::info << std::setw(30) << std::left << "TC4 status: " << getMonStatusString(tc4ChannelStatus) << std::endl; + sif::info << std::setw(30) << std::left << "TC5 status: " << getMonStatusString(tc5ChannelStatus) << std::endl; + sif::info << std::setw(30) << std::left << "Start sequence lock: " << lock << std::endl; +} + +std::string PdecHandler::getMonStatusString(uint32_t status) { + switch(status) { + case TC_CHANNEL_INACTIVE: + return std::string("inactive"); + case TC_CHANNEL_ACTIVE: + return std::string("active"); + case TC_CHANNEL_TIMEDOUT: + return std::string("timed out"); + default: + sif::warning << "PdecHandler::getMonStatusString: Invalid status" << std::endl; + return std::string(); + break; + } +} + ReturnValue_t PdecHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size) { @@ -532,6 +569,9 @@ ReturnValue_t PdecHandler::executeAction(ActionId_t actionId, case PRINT_CLCW: printClcw(); return EXECUTION_FINISHED; + case PRINT_PDEC_MON: + printPdecMon(); + return EXECUTION_FINISHED; default: return COMMAND_NOT_IMPLEMENTED; } diff --git a/linux/obc/PdecHandler.h b/linux/obc/PdecHandler.h index 8819df22..8c8e8d9b 100644 --- a/linux/obc/PdecHandler.h +++ b/linux/obc/PdecHandler.h @@ -61,16 +61,6 @@ public: ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size) override; - /** - * brief Returns the 32-bit wide communication link control word (CLCW) - */ - uint32_t getClcw(); - - /** - * @rief Reads and prints the CLCW. Can be useful for debugging. - */ - void printClcw(); - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PDEC_HANDLER; //! [EXPORT] : [COMMENT] Frame acceptance report signals an invalid frame @@ -119,6 +109,8 @@ private: // Action IDs static const ActionId_t PRINT_CLCW = 0; + // Print PDEC monitor register + static const ActionId_t PRINT_PDEC_MON = 1; static const uint8_t STAT_POSITION = 31; static const uint8_t FRAME_ANA_POSITION = 28; @@ -129,6 +121,28 @@ private: static const uint32_t FRAME_ANA_MASK = 0x70000000; static const uint32_t IREASON_MASK = 0x0E000000; + static const uint32_t TC_CHANNEL_INACTIVE = 0x0; + static const uint32_t TC_CHANNEL_ACTIVE = 0x1; + static const uint32_t TC_CHANNEL_TIMEDOUT = 0x2; + + static const uint32_t TC0_STATUS_MASK = 0x3; + static const uint32_t TC1_STATUS_MASK = 0xC; + static const uint32_t TC2_STATUS_MASK = 0x300; + static const uint32_t TC3_STATUS_MASK = 0xC00; + static const uint32_t TC4_STATUS_MASK = 0x30000; + static const uint32_t TC5_STATUS_MASK = 0xc00000; + // Lock register set to 1 when start sequence has been found (CLTU is beeing processed) + static const uint32_t LOCK_MASK = 0xc00000; + + static const uint32_t TC0_STATUS_POS = 0; + static const uint32_t TC1_STATUS_POS = 2; + static const uint32_t TC2_STATUS_POS = 4; + static const uint32_t TC3_STATUS_POS = 6; + static const uint32_t TC4_STATUS_POS = 8; + static const uint32_t TC5_STATUS_POS = 10; + // Lock register set to 1 when start sequence has been found (CLTU is beeing processed) + static const uint32_t LOCK_POS = 12; + /** * UIO is 4 byte aligned. Thus offset is calculated with "true offset" / 4 * Example: PDEC_FAR = 0x2840 => Offset in virtual address space is 0xA10 @@ -138,7 +152,7 @@ private: static const uint32_t PDEC_BFREE_OFFSET = 0xA24; static const uint32_t PDEC_BPTR_OFFSET = 0xA25; static const uint32_t PDEC_SLEN_OFFSET = 0xA26; - static const uint32_t PDEC_MON = 0xA27; + static const uint32_t PDEC_MON_OFFSET = 0xA27; #if BOARD_TE0720 == 1 static const int CONFIG_MEMORY_MAP_SIZE = 0x400; @@ -330,6 +344,29 @@ private: */ uint8_t getOddParity(uint8_t number); + /** + * brief Returns the 32-bit wide communication link control word (CLCW) + */ + uint32_t getClcw(); + + /** + * @brief Returns the PDEC monitor register content + * + */ + uint32_t getPdecMon(); + + /** + * @brief Reads and prints the CLCW. Can be useful for debugging. + */ + void printClcw(); + + /** + * @brief Prints monitor register information to debug console. + */ + void printPdecMon(); + + std::string getMonStatusString(uint32_t status); + object_id_t tcDestinationId; AcceptsTelecommandsIF* tcDestination = nullptr; diff --git a/mission/devices/ACUHandler.cpp b/mission/devices/ACUHandler.cpp index 24bd52fe..955b1703 100644 --- a/mission/devices/ACUHandler.cpp +++ b/mission/devices/ACUHandler.cpp @@ -16,6 +16,11 @@ ReturnValue_t ACUHandler::buildNormalDeviceCommand( return buildCommandFromCommand(*id, NULL, 0); } +void ACUHandler::fillCommandAndReplyMap() { + GomspaceDeviceHandler::fillCommandAndReplyMap(); + this->insertInCommandMap(PRINT_CHANNEL_STATS); +} + void ACUHandler::letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) { parseHkTableReply(packet); @@ -266,3 +271,38 @@ ReturnValue_t ACUHandler::initializeLocalDataPool( return HasReturnvaluesIF::RETURN_OK; } + +ReturnValue_t ACUHandler::deviceSpecificCommand(DeviceCommandId_t cmd) { + switch(cmd) { + case PRINT_CHANNEL_STATS: { + printChannelStats(); + return RETURN_OK; + } + default: { + return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; + } + } +} + +void ACUHandler::printChannelStats() { + PoolReadGuard pg(&acuHkTableDataset); + sif::info << "ACU Info: Current [mA], Voltage [mV]" << std::endl; + sif::info << std::setw(8) << std::left << "Ch0" << std::dec << "| " << + static_cast(acuHkTableDataset.currentInChannel0.value) << + std::setw(15) << std::right << acuHkTableDataset.voltageInChannel0.value << std::endl; + sif::info << std::setw(8) << std::left << "Ch1" << std::dec << "| " << + static_cast(acuHkTableDataset.currentInChannel1.value) << + std::setw(15) << std::right << acuHkTableDataset.voltageInChannel1.value << std::endl; + sif::info << std::setw(8) << std::left << "Ch2" << std::dec << "| " << + static_cast(acuHkTableDataset.currentInChannel2.value) << + std::setw(15) << std::right << acuHkTableDataset.voltageInChannel2.value << std::endl; + sif::info << std::setw(8) << std::left << "Ch3" << std::dec << "| " << + static_cast(acuHkTableDataset.currentInChannel3.value) << + std::setw(15) << std::right << acuHkTableDataset.voltageInChannel3.value << std::endl; + sif::info << std::setw(8) << std::left << "Ch4" << std::dec << "| " << + static_cast(acuHkTableDataset.currentInChannel4.value) << + std::setw(15) << std::right << acuHkTableDataset.voltageInChannel4.value << std::endl; + sif::info << std::setw(8) << std::left << "Ch5" << std::dec << "| " << + static_cast(acuHkTableDataset.currentInChannel5.value) << + std::setw(15) << std::right << acuHkTableDataset.voltageInChannel5.value << std::endl; +} diff --git a/mission/devices/ACUHandler.h b/mission/devices/ACUHandler.h index 8ab32a24..2bb688e7 100644 --- a/mission/devices/ACUHandler.h +++ b/mission/devices/ACUHandler.h @@ -3,6 +3,7 @@ #include "GomspaceDeviceHandler.h" #include +#include "fsfw/datapool/PoolReadGuard.h" /** * @brief Handler for the ACU from Gomspace. Monitors and controls the battery charging via @@ -25,8 +26,14 @@ protected: */ virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) override; + virtual void fillCommandAndReplyMap() override; + + virtual ReturnValue_t deviceSpecificCommand(DeviceCommandId_t cmd) override; + private: + static const DeviceCommandId_t PRINT_CHANNEL_STATS = 51; + ACU::HkTableDataset acuHkTableDataset; /** @@ -34,6 +41,11 @@ private: * the values in the acuHkTableDataset. */ void parseHkTableReply(const uint8_t *packet); + + /** + * @brief Prints channel statistics (current and voltage) to console + */ + void printChannelStats(); }; #endif /* MISSION_DEVICES_ACUHANDLER_H_ */ diff --git a/mission/devices/GomspaceDeviceHandler.cpp b/mission/devices/GomspaceDeviceHandler.cpp index e5912969..95e35a5e 100644 --- a/mission/devices/GomspaceDeviceHandler.cpp +++ b/mission/devices/GomspaceDeviceHandler.cpp @@ -87,7 +87,7 @@ ReturnValue_t GomspaceDeviceHandler::buildCommandFromCommand( break; } default: - return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; + return deviceSpecificCommand(deviceCommand); } return HasReturnvaluesIF::RETURN_OK; } @@ -398,6 +398,10 @@ LocalPoolDataSetBase* GomspaceDeviceHandler::getDataSetHandle(sid_t sid) { } } +ReturnValue_t GomspaceDeviceHandler::deviceSpecificCommand(DeviceCommandId_t cmd) { + return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; +} + void GomspaceDeviceHandler::setModeNormal() { mode = MODE_NORMAL; } diff --git a/mission/devices/GomspaceDeviceHandler.h b/mission/devices/GomspaceDeviceHandler.h index 78257b83..29156fce 100644 --- a/mission/devices/GomspaceDeviceHandler.h +++ b/mission/devices/GomspaceDeviceHandler.h @@ -73,7 +73,7 @@ protected: virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) override; ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) override; - void fillCommandAndReplyMap() override; + virtual 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, @@ -105,6 +105,11 @@ protected: virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; + /** + * @brief Can be used by gomspace devices to implement device specific commands. + */ + virtual ReturnValue_t deviceSpecificCommand(DeviceCommandId_t cmd); + private: /** diff --git a/mission/devices/devicedefinitions/GomspaceDefinitions.h b/mission/devices/devicedefinitions/GomspaceDefinitions.h index bd509239..0fbbc5b0 100644 --- a/mission/devices/devicedefinitions/GomspaceDefinitions.h +++ b/mission/devices/devicedefinitions/GomspaceDefinitions.h @@ -25,7 +25,10 @@ static const uint8_t REBOOT_PORT = 4; static const uint8_t PARAM_PORT = 7; static const uint8_t P60_PORT_GNDWDT_RESET = 9; -/* Device commands are derived from the rparam.h of the gomspace lib */ +/** + * Device commands are derived from the rparam.h of the gomspace lib.. + * IDs above 50 are reserved for device specific commands. + */ static const DeviceCommandId_t PING = 1; //!< [EXPORT] : [COMMAND] static const DeviceCommandId_t NONE = 2; // Set when no command is pending static const DeviceCommandId_t REBOOT = 4; //!< [EXPORT] : [COMMAND] diff --git a/mission/tmtc/CCSDSHandler.cpp b/mission/tmtc/CCSDSHandler.cpp index e0239d9a..524fe4b8 100644 --- a/mission/tmtc/CCSDSHandler.cpp +++ b/mission/tmtc/CCSDSHandler.cpp @@ -80,15 +80,19 @@ ReturnValue_t CCSDSHandler::initialize() { EventManagerIF* manager = ObjectManager::instance()->get( objects::EVENT_MANAGER); - if (manager == nullptr) { + if (manager == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "CCSDSHandler::initialize: Invalid event manager" << std::endl; #endif - return RETURN_FAILED; + return ObjectManagerIF::CHILD_INIT_FAILED; } result = manager->registerListener(eventQueue->getId()); if (result != HasReturnvaluesIF::RETURN_OK) { - return result; +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "CCSDSHandler::initialize: Failed to register CCSDS handler as event " + "listener" << std::endl; +#endif + return ObjectManagerIF::CHILD_INIT_FAILED;; } result = manager->subscribeToEventRange(eventQueue->getId(), event::getEventId(PdecHandler::CARRIER_LOCK), diff --git a/mission/utility/CMakeLists.txt b/mission/utility/CMakeLists.txt index 4847dddd..50532596 100644 --- a/mission/utility/CMakeLists.txt +++ b/mission/utility/CMakeLists.txt @@ -1,5 +1,6 @@ target_sources(${TARGET_NAME} PUBLIC TmFunnel.cpp + Timestamp.cpp ) diff --git a/mission/utility/Timestamp.cpp b/mission/utility/Timestamp.cpp new file mode 100644 index 00000000..36ddf4d8 --- /dev/null +++ b/mission/utility/Timestamp.cpp @@ -0,0 +1,19 @@ +#include "Timestamp.h" +#include "fsfw/serviceinterface/ServiceInterfaceStream.h" + +Timestamp::Timestamp() { + ReturnValue_t result = Clock::getDateAndTime(&time); + if (result != RETURN_OK) { + sif::warning << "Timestamp::Timestamp: Failed to get time" << std::endl; + } +} + +Timestamp::~Timestamp() { +} + +std::string Timestamp::str() { + return std::to_string(time.year) + "-" + std::to_string(time.month) + "-" + + std::to_string(time.day) + "--" + std::to_string(time.hour) + "-" + + std::to_string(time.minute) + "-" + std::to_string(time.second) + "-"; +} + diff --git a/mission/utility/Timestamp.h b/mission/utility/Timestamp.h new file mode 100644 index 00000000..05dae31f --- /dev/null +++ b/mission/utility/Timestamp.h @@ -0,0 +1,27 @@ +#ifndef MISSION_UTILITY_TIMESTAMP_H_ +#define MISSION_UTILITY_TIMESTAMP_H_ + +#include +#include "fsfw/timemanager/Clock.h" +#include "fsfw/returnvalues/HasReturnvaluesIF.h" + +/** + * @brief This class generates timestamps for files. + * + * @author J. Meier + */ +class Timestamp : public HasReturnvaluesIF { +public: + Timestamp(); + virtual ~Timestamp(); + + /** + * @brief Returns the timestamp string + */ + std::string str(); + +private: + Clock::TimeOfDay_t time; +}; + +#endif /* MISSION_UTILITY_TIMESTAMP_H_ */ diff --git a/tmtc b/tmtc index 1c2f09ad..2ecc4de0 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 1c2f09adc8c775cf84cfab860da165a319a756af +Subproject commit 2ecc4de0223f3772627a002a6486c356ab6f5cd2