diff --git a/common/config/commonObjects.h b/common/config/commonObjects.h index 1743dcf7..2e7c8411 100644 --- a/common/config/commonObjects.h +++ b/common/config/commonObjects.h @@ -94,7 +94,8 @@ enum commonObjects: uint32_t { // 0x73 ('s') for assemblies and system/subsystem components ACS_BOARD_ASS = 0x73000001, - SUS_BOARD_ASS = 0x73000002 + SUS_BOARD_ASS = 0x73000002, + TCS_BOARD_ASS = 0x73000003 }; } diff --git a/mission/system/CMakeLists.txt b/mission/system/CMakeLists.txt index 6c284620..27637339 100644 --- a/mission/system/CMakeLists.txt +++ b/mission/system/CMakeLists.txt @@ -2,14 +2,14 @@ target_sources(${LIB_EIVE_MISSION} PRIVATE AcsBoardAssembly.cpp SusAssembly.cpp AcsSubsystem.cpp - TcsSubsystem.cpp EiveSystem.cpp ComSubsystem.cpp - TcsSubsystem.cpp DualLanePowerStateMachine.cpp PowerStateMachineBase.cpp DualLaneAssemblyBase.cpp + TcsBoardAssembly.cpp AcsBoardFdir.cpp SusFdir.cpp + RtdFdir.cpp ) \ No newline at end of file diff --git a/mission/system/DualLaneAssemblyBase.h b/mission/system/DualLaneAssemblyBase.h index f62c521d..e0996848 100644 --- a/mission/system/DualLaneAssemblyBase.h +++ b/mission/system/DualLaneAssemblyBase.h @@ -69,7 +69,7 @@ class DualLaneAssemblyBase : public AssemblyBase, public ConfirmsFailuresIF { virtual void startTransition(Mode_t mode, Submode_t submode) override; virtual void handleChildrenLostMode(ReturnValue_t result) override; virtual void handleModeTransitionFailed(ReturnValue_t result) override; - virtual void handleModeReached(); + virtual void handleModeReached() override; MessageQueueId_t getEventReceptionQueue() override; diff --git a/mission/system/RtdFdir.cpp b/mission/system/RtdFdir.cpp new file mode 100644 index 00000000..f4f9806e --- /dev/null +++ b/mission/system/RtdFdir.cpp @@ -0,0 +1,6 @@ +#include "RtdFdir.h" + +#include + +RtdFdir::RtdFdir(object_id_t sensorId) + : DeviceHandlerFailureIsolation(sensorId, objects::TCS_BOARD_ASS) {} diff --git a/mission/system/RtdFdir.h b/mission/system/RtdFdir.h new file mode 100644 index 00000000..1dedbb82 --- /dev/null +++ b/mission/system/RtdFdir.h @@ -0,0 +1,11 @@ +#ifndef MISSION_SYSTEM_RTDFDIR_H_ +#define MISSION_SYSTEM_RTDFDIR_H_ + +#include + +class RtdFdir : public DeviceHandlerFailureIsolation { + public: + RtdFdir(object_id_t sensorId); +}; + +#endif /* MISSION_SYSTEM_RTDFDIR_H_ */ diff --git a/mission/system/TcsBoardAssembly.cpp b/mission/system/TcsBoardAssembly.cpp new file mode 100644 index 00000000..71964a3c --- /dev/null +++ b/mission/system/TcsBoardAssembly.cpp @@ -0,0 +1,158 @@ +#include "TcsBoardAssembly.h" + +#include +#include + +TcsBoardAssembly::TcsBoardAssembly(object_id_t objectId, object_id_t parentId, + PowerSwitchIF* pwrSwitcher, power::Switch_t theSwitch, + TcsBoardHelper helper) + : AssemblyBase(objectId, parentId, 24), switcher(pwrSwitcher, theSwitch), helper(helper) { + eventQueue = QueueFactory::instance()->createMessageQueue(24); +} + +void TcsBoardAssembly::performChildOperation() { + auto state = switcher.getState(); + if (state != PowerSwitcher::WAIT_OFF and state != PowerSwitcher::WAIT_ON) { + AssemblyBase::performChildOperation(); + return; + } + switcher.doStateMachine(); + if (state == PowerSwitcher::WAIT_OFF and switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) { + // Indicator that a transition to off is finished + AssemblyBase::handleModeReached(); + } else if (state == PowerSwitcher::WAIT_ON and + switcher.getState() == PowerSwitcher::SWITCH_IS_ON) { + // Indicator that mode commanding can be performed now + AssemblyBase::performChildOperation(); + } +} + +ReturnValue_t TcsBoardAssembly::commandChildren(Mode_t mode, Submode_t submode) { + ReturnValue_t result = RETURN_OK; + // Initialize the mode table to ensure all devices are in a defined state + for (uint8_t idx = 0; idx < NUMBER_RTDS; idx++) { + modeTable[idx].setMode(MODE_OFF); + modeTable[idx].setSubmode(SUBMODE_NONE); + } + if (recoveryState != RecoveryState::RECOVERY_STARTED) { + if (mode == DeviceHandlerIF::MODE_NORMAL or mode == MODE_ON) { + result = handleNormalOrOnModeCmd(mode, submode); + } + } + HybridIterator tableIter(modeTable.begin(), modeTable.end()); + executeTable(tableIter); + return result; +} + +ReturnValue_t TcsBoardAssembly::checkChildrenStateOn(Mode_t wantedMode, Submode_t wantedSubmode) { + uint8_t devsInWrongMode = 0; + for (uint8_t idx = 0; idx < NUMBER_RTDS; idx++) { + if (childrenMap[idx].mode != wantedMode) { + devsInWrongMode++; + } + } + // TODO: Can't really do something other than power cycling if devices in wrong mode. + // Might attempt one power-cycle. In any case, trigger an event + return RETURN_OK; +} + +ReturnValue_t TcsBoardAssembly::isModeCombinationValid(Mode_t mode, Submode_t submode) { + if (mode == MODE_ON or mode == MODE_OFF or mode == DeviceHandlerIF::MODE_NORMAL) { + return RETURN_OK; + } + return HasModesIF::INVALID_MODE; +} + +ReturnValue_t TcsBoardAssembly::initialize() { + ReturnValue_t result = RETURN_OK; + for (const auto& obj : helper.rtdIds) { + result = registerChild(obj); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + return SubsystemBase::initialize(); +} + +void TcsBoardAssembly::startTransition(Mode_t mode, Submode_t submode) { + if (mode != MODE_OFF) { + switcher.turnOn(); + switcher.doStateMachine(); + if (switcher.getState() == PowerSwitcher::SWITCH_IS_ON) { + AssemblyBase::startTransition(mode, submode); + } else { + // Need to wait with mode commanding until power switcher is done + targetMode = mode; + targetSubmode = submode; + } + } else { + AssemblyBase::startTransition(mode, submode); + } +} + +ReturnValue_t TcsBoardAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode) { + ReturnValue_t result = RETURN_OK; + bool needsSecondStep = false; + Mode_t devMode = 0; + object_id_t objId = 0; + for (uint8_t idx = 0; idx < NUMBER_RTDS; idx++) { + devMode = childrenMap[idx].mode; + objId = helper.rtdIds[idx]; + if (mode == devMode) { + modeTable[idx].setMode(mode); + } else if (mode == DeviceHandlerIF::MODE_NORMAL) { + if (isUseable(objId, devMode)) { + if (devMode == MODE_ON) { + modeTable[idx].setMode(mode); + modeTable[idx].setSubmode(SUBMODE_NONE); + } else { + modeTable[idx].setMode(MODE_ON); + modeTable[idx].setSubmode(SUBMODE_NONE); + if (internalState != STATE_SECOND_STEP) { + needsSecondStep = true; + } + } + } + } else if (mode == MODE_ON) { + if (isUseable(objId, devMode)) { + modeTable[idx].setMode(MODE_ON); + modeTable[idx].setSubmode(SUBMODE_NONE); + } + } + } + if (needsSecondStep) { + result = NEED_SECOND_STEP; + } + return result; +} + +bool TcsBoardAssembly::isUseable(object_id_t object, Mode_t mode) { + if (healthHelper.healthTable->isFaulty(object)) { + return false; + } + + // Check if device is already in target mode + if (childrenMap[object].mode == mode) { + return true; + } + + if (healthHelper.healthTable->isCommandable(object)) { + return true; + } + return false; +} + +MessageQueueId_t TcsBoardAssembly::getEventReceptionQueue() { return eventQueue->getId(); } + +void TcsBoardAssembly::handleModeReached() { + if (targetMode == MODE_OFF) { + switcher.turnOff(); + switcher.doStateMachine(); + // Need to wait with call to AssemblyBase::handleModeReached until power switcher is done + if (switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) { + AssemblyBase::handleModeReached(); + } + } else { + AssemblyBase::handleModeReached(); + } +} diff --git a/mission/system/TcsSubsystem.h b/mission/system/TcsBoardAssembly.h similarity index 54% rename from mission/system/TcsSubsystem.h rename to mission/system/TcsBoardAssembly.h index f7e160bd..f3f32164 100644 --- a/mission/system/TcsSubsystem.h +++ b/mission/system/TcsBoardAssembly.h @@ -11,10 +11,10 @@ struct TcsBoardHelper { std::array rtdIds = {}; }; -class TcsSubsystem : public AssemblyBase { +class TcsBoardAssembly : public AssemblyBase, public ConfirmsFailuresIF { public: - TcsSubsystem(object_id_t objectId, object_id_t parentId, PowerSwitchIF* pwrSwitcher, - power::Switch_t switcher, TcsBoardHelper helper); + TcsBoardAssembly(object_id_t objectId, object_id_t parentId, PowerSwitchIF* pwrSwitcher, + power::Switch_t switcher, TcsBoardHelper helper); ReturnValue_t initialize() override; @@ -25,12 +25,26 @@ class TcsSubsystem : public AssemblyBase { PowerSwitcher switcher; TcsBoardHelper helper; FixedArrayList modeTable; + MessageQueueIF* eventQueue = nullptr; + ReturnValue_t handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode); + /** + * Check whether it makes sense to send mode commands to the device + * @param object + * @param mode + * @return + */ + bool isUseable(object_id_t object, Mode_t mode); + + // ConfirmFailureIF implementation + MessageQueueId_t getEventReceptionQueue() override; + + // AssemblyBase implementation ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) override; ReturnValue_t checkChildrenStateOn(Mode_t wantedMode, Submode_t wantedSubmode) override; ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) override; - ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, - uint32_t* msToReachTheMode) override; + void startTransition(Mode_t mode, Submode_t submode) override; + void handleModeReached() override; }; #endif /* MISSION_SYSTEM_TCSSUBSYSTEM_H_ */ diff --git a/mission/system/TcsSubsystem.cpp b/mission/system/TcsSubsystem.cpp deleted file mode 100644 index c3e5724f..00000000 --- a/mission/system/TcsSubsystem.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "TcsSubsystem.h" - -#include - -TcsSubsystem::TcsSubsystem(object_id_t objectId, object_id_t parentId, PowerSwitchIF* pwrSwitcher, - power::Switch_t theSwitch, TcsBoardHelper helper) - : AssemblyBase(objectId, parentId, 24), switcher(pwrSwitcher, theSwitch), helper(helper) {} - -void TcsSubsystem::performChildOperation() { - switcher.doStateMachine(); - if (not switcher.active()) { - AssemblyBase::performChildOperation(); - } -} - -ReturnValue_t TcsSubsystem::checkModeCommand(Mode_t mode, Submode_t submode, - uint32_t* msToReachTheMode) { - if (mode == MODE_ON or mode == MODE_OFF or mode == DeviceHandlerIF::MODE_NORMAL) { - return RETURN_OK; - } - return HasModesIF::INVALID_MODE; -} - -ReturnValue_t TcsSubsystem::initialize() { - ReturnValue_t result = RETURN_OK; - for (const auto& obj : helper.rtdIds) { - result = registerChild(obj); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - } - return SubsystemBase::initialize(); -}