diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f3c2488..a768e7e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,8 +16,16 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +## Fixed + +- Generic HK handling: Bug where HKs were generated a lot more often than required. This is the case + if a device handler `PERFORM_OPERATION` step is performed more than once per PST cycle. +- Syrlinks now goes to `_MODE_TO_ON` when finishing the `doStartUp` transition. + ## Changed +- Doubled GS PST interval instead of scheduling everything twice. +- Syrlinks now only has one `PERFORM_OPERATION` step, but still has two communication steps. - PCDU components only allow setting `NEEDS_RECOVERY`, `HEALTHY` and `EXTERNAL_CONTROL` health states now. TMP sensor components only allow `HEALTHY` , `EXTERNAL_CONTROL`, `FAULTY` and `PERMANENT_FAULTY`. diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index 3f29de5e..3b71c6cd 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -62,9 +62,9 @@ #include "mission/system/acs/acsModeTree.h" #include "mission/system/com/SyrlinksFdir.h" #include "mission/system/com/comModeTree.h" -#include "mission/system/power/GomspacePowerFdir.h" #include "mission/system/fdir/RtdFdir.h" #include "mission/system/objects/TcsBoardAssembly.h" +#include "mission/system/power/GomspacePowerFdir.h" #include "mission/system/tree/payloadModeTree.h" #include "mission/system/tree/tcsModeTree.h" #include "mission/tmtc/tmFilters.h" diff --git a/bsp_q7s/core/scheduling.cpp b/bsp_q7s/core/scheduling.cpp index 2d767687..e248938a 100644 --- a/bsp_q7s/core/scheduling.cpp +++ b/bsp_q7s/core/scheduling.cpp @@ -538,7 +538,7 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction FixedTimeslotTaskIF* gomSpacePstTask = factory.createFixedTimeslotTask("GS_PST_TASK", 65, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, - 0.5, missedDeadlineFunc, &RR_SCHEDULING); + 0.25, missedDeadlineFunc, &RR_SCHEDULING); result = pst::pstGompaceCan(gomSpacePstTask); if (result != returnvalue::OK) { if (result != FixedTimeslotTaskIF::SLOT_LIST_EMPTY) { diff --git a/mission/com/SyrlinksHandler.cpp b/mission/com/SyrlinksHandler.cpp index 297ffd88..1ee490a7 100644 --- a/mission/com/SyrlinksHandler.cpp +++ b/mission/com/SyrlinksHandler.cpp @@ -21,15 +21,15 @@ SyrlinksHandler::~SyrlinksHandler() = default; void SyrlinksHandler::doStartUp() { if (internalState == InternalState::OFF) { - transitionCommandPending = false; internalState = InternalState::ENABLE_TEMPERATURE_PROTECTION; commandExecuted = false; } if (internalState == InternalState::ENABLE_TEMPERATURE_PROTECTION) { if (commandExecuted) { // Go to normal mode immediately and disable transmitter on startup. - setMode(_MODE_TO_NORMAL); + setMode(_MODE_TO_ON); internalState = InternalState::IDLE; + transState = TransitionState::IDLE; commandExecuted = false; } } @@ -37,15 +37,16 @@ void SyrlinksHandler::doStartUp() { void SyrlinksHandler::doShutDown() { // In any case, always disable TX first. - if (internalState != InternalState::SET_TX_STANDBY) { - internalState = InternalState::SET_TX_STANDBY; - transitionCommandPending = false; + if (internalState != InternalState::TX_TRANSITION) { + internalState = InternalState::TX_TRANSITION; + transState = TransitionState::SET_TX_STANDBY; commandExecuted = false; } - if (internalState == InternalState::SET_TX_STANDBY) { + if (internalState == InternalState::TX_TRANSITION) { if (commandExecuted) { temperatureSet.setValidity(false, true); internalState = InternalState::OFF; + transState = TransitionState::IDLE; commandExecuted = false; setMode(_MODE_POWER_DOWN); } @@ -99,30 +100,43 @@ ReturnValue_t SyrlinksHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { } ReturnValue_t SyrlinksHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { + if (transState == TransitionState::CMD_PENDING or transState == TransitionState::DONE) { + return NOTHING_TO_SEND; + } switch (internalState) { case InternalState::ENABLE_TEMPERATURE_PROTECTION: { *id = syrlinks::WRITE_LCL_CONFIG; + transState = TransitionState::CMD_PENDING; return buildCommandFromCommand(*id, nullptr, 0); } - case InternalState::SET_TX_MODULATION: { - *id = syrlinks::SET_TX_MODE_MODULATION; - return buildCommandFromCommand(*id, nullptr, 0); - } - case InternalState::SELECT_MODULATION_BPSK: { - *id = syrlinks::SET_WAVEFORM_BPSK; - return buildCommandFromCommand(*id, nullptr, 0); - } - case InternalState::SELECT_MODULATION_0QPSK: { - *id = syrlinks::SET_WAVEFORM_0QPSK; - return buildCommandFromCommand(*id, nullptr, 0); - } - case InternalState::SET_TX_CW: { - *id = syrlinks::SET_TX_MODE_CW; - return buildCommandFromCommand(*id, nullptr, 0); - } - case InternalState::SET_TX_STANDBY: { - *id = syrlinks::SET_TX_MODE_STANDBY; - return buildCommandFromCommand(*id, nullptr, 0); + case InternalState::TX_TRANSITION: { + switch (transState) { + case TransitionState::SET_TX_MODULATION: { + *id = syrlinks::SET_TX_MODE_MODULATION; + return buildCommandFromCommand(*id, nullptr, 0); + } + case TransitionState::SELECT_MODULATION_BPSK: { + *id = syrlinks::SET_WAVEFORM_BPSK; + return buildCommandFromCommand(*id, nullptr, 0); + } + case TransitionState::SELECT_MODULATION_0QPSK: { + *id = syrlinks::SET_WAVEFORM_0QPSK; + return buildCommandFromCommand(*id, nullptr, 0); + } + case TransitionState::SET_TX_CW: { + *id = syrlinks::SET_TX_MODE_CW; + return buildCommandFromCommand(*id, nullptr, 0); + } + case TransitionState::SET_TX_STANDBY: { + *id = syrlinks::SET_TX_MODE_STANDBY; + return buildCommandFromCommand(*id, nullptr, 0); + } + default: { + return NOTHING_TO_SEND; + } + } + transState = TransitionState::CMD_PENDING; + break; } default: { break; @@ -622,8 +636,6 @@ void SyrlinksHandler::parseAgcHighByte(const uint8_t* packet) { agcValueHighByte = convertHexStringToUint8(reinterpret_cast(packet + offset)); } -void SyrlinksHandler::setNormalDatapoolEntriesInvalid() {} - uint32_t SyrlinksHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 2500; } ReturnValue_t SyrlinksHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, @@ -652,11 +664,11 @@ ReturnValue_t SyrlinksHandler::initializeLocalDataPool(localpool::DataPool& loca poolManager.subscribeForDiagPeriodicPacket( subdp::DiagnosticsHkPeriodicParams(rxDataset.getSid(), enableHkSets, 60.0)); poolManager.subscribeForRegularPeriodicPacket( - subdp::RegularHkPeriodicParams(temperatureSet.getSid(), enableHkSets, 20.0)); + subdp::RegularHkPeriodicParams(temperatureSet.getSid(), enableHkSets, 60.0)); return returnvalue::OK; } -void SyrlinksHandler::setModeNormal() { setMode(MODE_NORMAL); } +void SyrlinksHandler::setModeNormal() { setMode(_MODE_TO_NORMAL); } float SyrlinksHandler::calcTempVal(uint16_t raw) { return 0.126984 * raw - 67.87; } @@ -675,12 +687,31 @@ ReturnValue_t SyrlinksHandler::handleAckReply(const uint8_t* packet) { break; } case (syrlinks::SET_WAVEFORM_BPSK): - case (syrlinks::SET_WAVEFORM_0QPSK): - case (syrlinks::SET_TX_MODE_STANDBY): - case (syrlinks::SET_TX_MODE_MODULATION): + case (syrlinks::SET_WAVEFORM_0QPSK): { + if (result == returnvalue::OK and isTransitionalMode()) { + transState = TransitionState::SET_TX_MODULATION; + commandExecuted = true; + } + break; + } + case (syrlinks::SET_TX_MODE_STANDBY): { + if (result == returnvalue::OK and isTransitionalMode()) { + transState = TransitionState::DONE; + commandExecuted = true; + } + break; + } + case (syrlinks::SET_TX_MODE_MODULATION): { + if (result == returnvalue::OK and isTransitionalMode()) { + transState = TransitionState::DONE; + commandExecuted = true; + } + break; + } case (syrlinks::SET_TX_MODE_CW): { if (result == returnvalue::OK and isTransitionalMode()) { commandExecuted = true; + transState = TransitionState::DONE; } break; } @@ -704,7 +735,7 @@ ReturnValue_t SyrlinksHandler::handleAckReply(const uint8_t* packet) { ReturnValue_t SyrlinksHandler::isModeCombinationValid(Mode_t mode, Submode_t submode) { if (mode == HasModesIF::MODE_ON or mode == DeviceHandlerIF::MODE_NORMAL) { - if (submode >= com::Submode::NUM_SUBMODES) { + if (submode >= com::Submode::NUM_SUBMODES or submode < com::Submode::RX_ONLY) { return HasModesIF::INVALID_SUBMODE; } return returnvalue::OK; @@ -731,72 +762,54 @@ void SyrlinksHandler::setDebugMode(bool enable) { this->debugMode = enable; } void SyrlinksHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) { Mode_t tgtMode = getBaseMode(getMode()); - auto commandDone = [&]() { - setMode(tgtMode); - transitionCommandPending = false; + auto doneHandler = [&]() { internalState = InternalState::IDLE; + transState = TransitionState::IDLE; + DeviceHandlerBase::doTransition(modeFrom, subModeFrom); }; - auto txOnHandler = [&](InternalState selMod) { - if (internalState == InternalState::IDLE) { - transitionCommandPending = false; - commandExecuted = false; - internalState = selMod; - } - // Select modulation first (BPSK or 0QPSK). - if (internalState == selMod) { - if (commandExecuted) { - transitionCommandPending = false; - internalState = InternalState::SET_TX_MODULATION; - commandExecuted = false; - } - } - // Now go into modulation mode. - if (internalState == InternalState::SET_TX_MODULATION) { - if (commandExecuted) { - commandDone(); - return true; - } - } - return false; - }; + if (transState == TransitionState::DONE) { + return doneHandler(); + } auto txStandbyHandler = [&]() { - if (internalState == InternalState::IDLE) { - transitionCommandPending = false; - internalState = InternalState::SET_TX_STANDBY; - commandExecuted = false; - } - if (internalState == InternalState::SET_TX_STANDBY) { - if (commandExecuted) { - commandDone(); - return; - } - } + txDataset.setReportingEnabled(false); + poolManager.changeCollectionInterval(temperatureSet.getSid(), 60.0); + transState = TransitionState::SET_TX_STANDBY; + internalState = InternalState::TX_TRANSITION; }; + auto txOnHandler = [&](TransitionState tgtTransitionState) { + txDataset.setReportingEnabled(true); + poolManager.changeCollectionInterval(txDataset.getSid(), 10.0); + poolManager.changeCollectionInterval(temperatureSet.getSid(), 5.0); + transState = tgtTransitionState; + internalState = InternalState::TX_TRANSITION; + }; + if (tgtMode == HasModesIF::MODE_ON or tgtMode == DeviceHandlerIF::MODE_NORMAL) { + // If submode has not changed, no special transition handling necessary. + if (getSubmode() == subModeFrom) { + return doneHandler(); + } + // Transition is on-going, wait for it to finish. + if (transState != TransitionState::IDLE) { + return; + } + // Transition start logic. switch (getSubmode()) { case (com::Submode::RX_AND_TX_DEFAULT_DATARATE): { auto currentDatarate = com::getCurrentDatarate(); if (currentDatarate == com::Datarate::LOW_RATE_MODULATION_BPSK) { - if (txOnHandler(InternalState::SELECT_MODULATION_BPSK)) { - return; - } + txOnHandler(TransitionState::SELECT_MODULATION_BPSK); } else if (currentDatarate == com::Datarate::HIGH_RATE_MODULATION_0QPSK) { - if (txOnHandler(InternalState::SELECT_MODULATION_0QPSK)) { - return; - } + txOnHandler(TransitionState::SELECT_MODULATION_0QPSK); } break; } case (com::Submode::RX_AND_TX_LOW_DATARATE): { - if (txOnHandler(InternalState::SELECT_MODULATION_BPSK)) { - return; - } + txOnHandler(TransitionState::SELECT_MODULATION_BPSK); break; } case (com::Submode::RX_AND_TX_HIGH_DATARATE): { - if (txOnHandler(InternalState::SELECT_MODULATION_0QPSK)) { - return; - } + txOnHandler(TransitionState::SELECT_MODULATION_0QPSK); break; } case (com::Submode::RX_ONLY): { @@ -804,21 +817,17 @@ void SyrlinksHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) { return; } case (com::Submode::RX_AND_TX_CW): { - if (internalState == InternalState::IDLE) { - internalState = InternalState::SET_TX_STANDBY; - commandExecuted = false; - } - if (commandExecuted) { - commandDone(); - return; - } + txOnHandler(TransitionState::SET_TX_CW); break; } default: { - commandDone(); + sif::error << "SyrlinksHandler: Unexpected submode " << getSubmode() << std::endl; + DeviceHandlerBase::doTransition(modeFrom, subModeFrom); } } } else if (tgtMode == HasModesIF::MODE_OFF) { txStandbyHandler(); + } else { + return doneHandler(); } } diff --git a/mission/com/SyrlinksHandler.h b/mission/com/SyrlinksHandler.h index 97541ecb..2c9d620f 100644 --- a/mission/com/SyrlinksHandler.h +++ b/mission/com/SyrlinksHandler.h @@ -46,7 +46,6 @@ class SyrlinksHandler : public DeviceHandlerBase { size_t* foundLen) override; ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) override; ReturnValue_t getSwitches(const uint8_t** switches, uint8_t* numberOfSwitches) override; - void setNormalDatapoolEntriesInvalid() override; uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) override; @@ -112,22 +111,26 @@ class SyrlinksHandler : public DeviceHandlerBase { float tempPowerAmplifier = 0; float tempBasebandBoard = 0; bool commandExecuted = false; - bool transitionCommandPending = false; uint8_t commandBuffer[syrlinks::MAX_COMMAND_SIZE]; enum class InternalState { OFF, ENABLE_TEMPERATURE_PROTECTION, + TX_TRANSITION, + IDLE + } internalState = InternalState::OFF; + + enum class TransitionState { + IDLE, SELECT_MODULATION_BPSK, SELECT_MODULATION_0QPSK, SET_TX_MODULATION, SET_TX_CW, SET_TX_STANDBY, - IDLE - }; - - InternalState internalState = InternalState::OFF; + CMD_PENDING, + DONE + } transState = TransitionState::IDLE; /** * This object is used to store the id of the next command to execute. This controls the diff --git a/mission/pollingSeqTables.cpp b/mission/pollingSeqTables.cpp index 574cc9c1..0367ef27 100644 --- a/mission/pollingSeqTables.cpp +++ b/mission/pollingSeqTables.cpp @@ -26,8 +26,7 @@ ReturnValue_t pst::pstSyrlinks(FixedTimeslotTaskIF *thisSequence) { thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0.25, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0.25, DeviceHandlerIF::GET_READ); - thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0.4, - DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0.4, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0.75, DeviceHandlerIF::SEND_READ); @@ -114,40 +113,15 @@ ReturnValue_t pst::pstGompaceCan(FixedTimeslotTaskIF *thisSequence) { thisSequence->addSlot(objects::PDU2_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::ACU_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE); - thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.25, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.25, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.25, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::ACU_HANDLER, length * 0.25, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.5, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.5, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.5, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::ACU_HANDLER, length * 0.5, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.25, DeviceHandlerIF::GET_READ); - thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.25, DeviceHandlerIF::GET_READ); - thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.25, DeviceHandlerIF::GET_READ); - thisSequence->addSlot(objects::ACU_HANDLER, length * 0.25, DeviceHandlerIF::GET_READ); - - thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.5, DeviceHandlerIF::PERFORM_OPERATION); - thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.5, DeviceHandlerIF::PERFORM_OPERATION); - thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.5, DeviceHandlerIF::PERFORM_OPERATION); - thisSequence->addSlot(objects::ACU_HANDLER, length * 0.5, DeviceHandlerIF::PERFORM_OPERATION); - - thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.5, DeviceHandlerIF::SEND_WRITE); - thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.5, DeviceHandlerIF::SEND_WRITE); - thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.5, DeviceHandlerIF::SEND_WRITE); - thisSequence->addSlot(objects::ACU_HANDLER, length * 0.5, DeviceHandlerIF::SEND_WRITE); - - thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.5, DeviceHandlerIF::GET_WRITE); - thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.5, DeviceHandlerIF::GET_WRITE); - thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.5, DeviceHandlerIF::GET_WRITE); - thisSequence->addSlot(objects::ACU_HANDLER, length * 0.5, DeviceHandlerIF::GET_WRITE); - - thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.75, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.75, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.75, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::ACU_HANDLER, length * 0.75, DeviceHandlerIF::SEND_READ); - - thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.75, DeviceHandlerIF::GET_READ); - thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.75, DeviceHandlerIF::GET_READ); - thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.75, DeviceHandlerIF::GET_READ); - thisSequence->addSlot(objects::ACU_HANDLER, length * 0.75, DeviceHandlerIF::GET_READ); + thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.5, DeviceHandlerIF::GET_READ); + thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.5, DeviceHandlerIF::GET_READ); + thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.5, DeviceHandlerIF::GET_READ); + thisSequence->addSlot(objects::ACU_HANDLER, length * 0.5, DeviceHandlerIF::GET_READ); if (thisSequence->checkSequence() != returnvalue::OK) { sif::error << "GomSpace PST initialization failed" << std::endl; return returnvalue::FAILED;