diff --git a/CMakeLists.txt b/CMakeLists.txt index 20a5c67e..03d51ac2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,24 +159,42 @@ find_package(Catch2 3) #global compiler options need to be set before adding executables if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - add_compile_options( - "-Wall" - "-Wextra" - "-Wimplicit-fallthrough=1" - "-Wno-unused-parameter" - "-Wno-psabi" - ) - # Remove unused sections. - add_compile_options( - "-ffunction-sections" - "-fdata-sections" - ) + add_compile_options( + "-Wall" + "-Wextra" + "-Wimplicit-fallthrough=1" + "-Wno-unused-parameter" + "-Wno-psabi" + "-Wduplicated-cond" # check for duplicate conditions + "-Wduplicated-branches" # check for duplicate branches + "-Wlogical-op" # Search for bitwise operations instead of logical + "-Wnull-dereference" # Search for NULL dereference + "-Wundef" # Warn if undefind marcos are used + "-Wformat=2" # Format string problem detection + "-Wformat-overflow=2" # Formatting issues in printf + "-Wformat-truncation=2" # Formatting issues in printf + "-Wformat-security" # Search for dangerous printf operations + "-Wstrict-overflow=3" # Warn if integer overflows might happen + "-Warray-bounds=2" # Some array bounds violations will be found + "-Wshift-overflow=2" # Search for bit left shift overflows (createPeriodicTask( + PeriodicTaskIF* acsTask = factory->createPeriodicTask( "ACS_CTRL", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc); - result = acsCtrl->addComponent(objects::GPS_CONTROLLER); + result = acsTask->addComponent(objects::GPS_CONTROLLER); if (result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("ACS_CTRL", objects::GPS_CONTROLLER); } + result = acsTask->addComponent(objects::ACS_BOARD_ASS); + if (result != HasReturnvaluesIF::RETURN_OK) { + initmission::printAddObjectError("ACS_ASS", objects::GPS_CONTROLLER); + } #endif /* OBSW_ADD_ACS_HANDLERS */ #if BOARD_TE0720 == 0 @@ -209,7 +213,7 @@ void initmission::initTasks() { #endif #if OBSW_ADD_ACS_HANDLERS == 1 - acsCtrl->startTask(); + acsTask->startTask(); #endif sif::info << "Tasks started.." << std::endl; diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index be6d1b11..6542aa85 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -1,5 +1,6 @@ #include "ObjectFactory.h" +#include #include #include #include @@ -83,6 +84,7 @@ #include "mission/devices/devicedefinitions/SusDefinitions.h" #include "mission/devices/devicedefinitions/SyrlinksDefinitions.h" #include "mission/devices/devicedefinitions/payloadPcduDefinitions.h" +#include "mission/system/AcsBoardAssembly.h" #include "mission/tmtc/CCSDSHandler.h" #include "mission/tmtc/VirtualChannel.h" #include "mission/utility/TmFunnel.h" @@ -124,18 +126,19 @@ void ObjectFactory::produce(void* args) { UartComIF* uartComIF = nullptr; SpiComIF* spiComIF = nullptr; I2cComIF* i2cComIF = nullptr; + PowerSwitchIF* pwrSwitcher = nullptr; createCommunicationInterfaces(&gpioComIF, &uartComIF, &spiComIF, &i2cComIF); createTmpComponents(); #if BOARD_TE0720 == 0 new CoreController(objects::CORE_CONTROLLER); gpioCallbacks::disableAllDecoder(); - createPcduComponents(gpioComIF); + createPcduComponents(gpioComIF, &pwrSwitcher); createRadSensorComponent(gpioComIF); createSunSensorComponents(gpioComIF, spiComIF); #if OBSW_ADD_ACS_BOARD == 1 - createAcsBoardComponents(gpioComIF, uartComIF); + createAcsBoardComponents(gpioComIF, uartComIF, pwrSwitcher); #endif createHeaterComponents(); @@ -260,7 +263,7 @@ void ObjectFactory::createCommunicationInterfaces(LinuxLibgpioIF** gpioComIF, Ua #endif } -void ObjectFactory::createPcduComponents(LinuxLibgpioIF* gpioComIF) { +void ObjectFactory::createPcduComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF** pwrSwitcher) { CspCookie* p60DockCspCookie = new CspCookie(P60Dock::MAX_REPLY_LENGTH, addresses::P60DOCK); CspCookie* pdu1CspCookie = new CspCookie(PDU::MAX_REPLY_LENGTH, addresses::PDU1); CspCookie* pdu2CspCookie = new CspCookie(PDU::MAX_REPLY_LENGTH, addresses::PDU2); @@ -275,7 +278,7 @@ void ObjectFactory::createPcduComponents(LinuxLibgpioIF* gpioComIF) { new PDU2Handler(objects::PDU2_HANDLER, objects::CSP_COM_IF, pdu2CspCookie); pdu2handler->assignChannelHookFunction(&pcdu::switchCallback, gpioComIF); ACUHandler* acuhandler = new ACUHandler(objects::ACU_HANDLER, objects::CSP_COM_IF, acuCspCookie); - new PCDUHandler(objects::PCDU_HANDLER, 50); + auto pcduHandler = new PCDUHandler(objects::PCDU_HANDLER, 50); /** * Setting PCDU devices to mode normal immediately after start up because PCDU is always @@ -285,6 +288,9 @@ void ObjectFactory::createPcduComponents(LinuxLibgpioIF* gpioComIF) { pdu1handler->setModeNormal(); pdu2handler->setModeNormal(); acuhandler->setModeNormal(); + if (pwrSwitcher != nullptr) { + *pwrSwitcher = pcduHandler; + } } void ObjectFactory::createRadSensorComponent(LinuxLibgpioIF* gpioComIF) { @@ -453,6 +459,7 @@ void ObjectFactory::createSunSensorComponents(LinuxLibgpioIF* gpioComIF, SpiComI susHandler9->setToGoToNormalMode(true); susHandler10->setToGoToNormalMode(true); susHandler11->setToGoToNormalMode(true); +#endif #if OBSW_DEBUG_SUS == 1 susHandler0->enablePeriodicPrintout(true, 3); susHandler1->enablePeriodicPrintout(true, 3); @@ -467,12 +474,11 @@ void ObjectFactory::createSunSensorComponents(LinuxLibgpioIF* gpioComIF, SpiComI susHandler10->enablePeriodicPrintout(true, 3); susHandler11->enablePeriodicPrintout(true, 3); #endif -#endif - #endif /* OBSW_ADD_SUN_SENSORS == 1 */ } -void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComIF* uartComIF) { +void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComIF* uartComIF, + PowerSwitchIF* pwrSwitcher) { using namespace gpio; GpioCookie* gpioCookieAcsBoard = new GpioCookie(); @@ -579,40 +585,40 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComI MGMLIS3MDL::MAX_BUFFER_SIZE, spi::DEFAULT_LIS3_MODE, spi::DEFAULT_LIS3_SPEED); auto mgmLis3Handler = new MgmLIS3MDLHandler(objects::MGM_0_LIS3_HANDLER, objects::SPI_COM_IF, spiCookie, spi::LIS3_TRANSITION_DELAY); + static_cast(mgmLis3Handler); #if OBSW_TEST_ACS == 1 mgmLis3Handler->setStartUpImmediately(); mgmLis3Handler->setToGoToNormalMode(true); +#endif #if OBSW_DEBUG_ACS == 1 mgmLis3Handler->enablePeriodicPrintouts(true, 10); #endif -#endif - spiCookie = new SpiCookie(addresses::MGM_1_RM3100, gpioIds::MGM_1_RM3100_CS, spiDev, RM3100::MAX_BUFFER_SIZE, spi::DEFAULT_RM3100_MODE, spi::DEFAULT_RM3100_SPEED); auto mgmRm3100Handler = new MgmRM3100Handler(objects::MGM_1_RM3100_HANDLER, objects::SPI_COM_IF, spiCookie, spi::RM3100_TRANSITION_DELAY); + static_cast(mgmRm3100Handler); #if OBSW_TEST_ACS == 1 mgmRm3100Handler->setStartUpImmediately(); mgmRm3100Handler->setToGoToNormalMode(true); +#endif #if OBSW_DEBUG_ACS == 1 mgmRm3100Handler->enablePeriodicPrintouts(true, 10); #endif -#endif - spiCookie = new SpiCookie(addresses::MGM_2_LIS3, gpioIds::MGM_2_LIS3_CS, spiDev, MGMLIS3MDL::MAX_BUFFER_SIZE, spi::DEFAULT_LIS3_MODE, spi::DEFAULT_LIS3_SPEED); - auto mgmLis3Handler2 = new MgmLIS3MDLHandler(objects::MGM_2_LIS3_HANDLER, objects::SPI_COM_IF, - spiCookie, spi::LIS3_TRANSITION_DELAY); + mgmLis3Handler = new MgmLIS3MDLHandler(objects::MGM_2_LIS3_HANDLER, objects::SPI_COM_IF, + spiCookie, spi::LIS3_TRANSITION_DELAY); + static_cast(mgmLis3Handler); #if OBSW_TEST_ACS == 1 - mgmLis3Handler2->setStartUpImmediately(); - mgmLis3Handler2->setToGoToNormalMode(true); + mgmLis3Handler->setStartUpImmediately(); + mgmLis3Handler->setToGoToNormalMode(true); +#endif #if OBSW_DEBUG_ACS == 1 - mgmLis3Handler2->enablePeriodicPrintouts(true, 10); + mgmLis3Handler->enablePeriodicPrintouts(true, 10); #endif -#endif - spiCookie = new SpiCookie(addresses::MGM_3_RM3100, gpioIds::MGM_3_RM3100_CS, spiDev, RM3100::MAX_BUFFER_SIZE, spi::DEFAULT_RM3100_MODE, spi::DEFAULT_RM3100_SPEED); @@ -621,11 +627,10 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComI #if OBSW_TEST_ACS == 1 mgmRm3100Handler->setStartUpImmediately(); mgmRm3100Handler->setToGoToNormalMode(true); +#endif #if OBSW_DEBUG_ACS == 1 mgmRm3100Handler->enablePeriodicPrintouts(true, 10); #endif -#endif - // Commented until ACS board V2 in in clean room again // Gyro 0 Side A spiCookie = new SpiCookie(addresses::GYRO_0_ADIS, gpioIds::GYRO_0_ADIS_CS, spiDev, @@ -633,12 +638,13 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComI spi::DEFAULT_ADIS16507_SPEED); auto adisHandler = new GyroADIS1650XHandler(objects::GYRO_0_ADIS_HANDLER, objects::SPI_COM_IF, spiCookie, ADIS1650X::Type::ADIS16505); + static_cast(adisHandler); #if OBSW_TEST_ACS == 1 adisHandler->setStartUpImmediately(); adisHandler->setToGoToNormalModeImmediately(); +#endif #if OBSW_DEBUG_ACS == 1 adisHandler->enablePeriodicPrintouts(true, 10); -#endif #endif // Gyro 1 Side A @@ -647,12 +653,13 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComI spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED); auto gyroL3gHandler = new GyroHandlerL3GD20H(objects::GYRO_1_L3G_HANDLER, objects::SPI_COM_IF, spiCookie, spi::L3G_TRANSITION_DELAY); + static_cast(gyroL3gHandler); #if OBSW_TEST_ACS == 1 gyroL3gHandler->setStartUpImmediately(); gyroL3gHandler->setToGoToNormalMode(true); +#endif #if OBSW_DEBUG_ACS == 1 gyroL3gHandler->enablePeriodicPrintouts(true, 10); -#endif #endif // Gyro 2 Side B spiCookie = new SpiCookie(addresses::GYRO_2_ADIS, gpioIds::GYRO_2_ADIS_CS, spiDev, @@ -673,9 +680,9 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComI #if OBSW_TEST_ACS == 1 gyroL3gHandler->setStartUpImmediately(); gyroL3gHandler->setToGoToNormalMode(true); +#endif #if OBSW_DEBUG_ACS == 1 gyroL3gHandler->enablePeriodicPrintouts(true, 10); -#endif #endif bool debugGps = false; @@ -691,6 +698,24 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComI auto gpsHandler0 = new GPSHyperionLinuxController(objects::GPS_CONTROLLER, objects::NO_OBJECT, debugGps); gpsHandler0->setResetPinTriggerFunction(gps::triggerGpioResetPin, &resetArgsGnss0); + + AcsBoardHelper acsBoardHelper = AcsBoardHelper( + objects::MGM_0_LIS3_HANDLER, objects::MGM_1_RM3100_HANDLER, objects::MGM_2_LIS3_HANDLER, + objects::MGM_3_RM3100_HANDLER, objects::GYRO_0_ADIS_HANDLER, objects::GYRO_1_L3G_HANDLER, + objects::GYRO_2_ADIS_HANDLER, objects::GYRO_3_L3G_HANDLER, objects::GPS_CONTROLLER); + auto acsAss = new AcsBoardAssembly(objects::ACS_BOARD_ASS, objects::NO_OBJECT, pwrSwitcher, + acsBoardHelper, gpioComIF); + static_cast(acsAss); + +#if OBSW_TEST_ACS_BOARD_ASS == 1 + CommandMessage msg; + ModeMessage::setModeMessage(&msg, ModeMessage::CMD_MODE_COMMAND, DeviceHandlerIF::MODE_NORMAL, + duallane::A_SIDE); + ReturnValue_t result = MessageQueueSenderIF::sendMessage(acsAss->getCommandQueue(), &msg); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "Sending mode command failed" << std::endl; + } +#endif #endif /* OBSW_ADD_ACS_HANDLERS == 1 */ } @@ -1214,11 +1239,11 @@ void ObjectFactory::createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF* static_cast(plPcduHandler); #if OBSW_TEST_PL_PCDU == 1 plPcduHandler->setStartUpImmediately(); +#endif #if OBSW_DEBUG_PL_PCDU == 1 plPcduHandler->setToGoToNormalModeImmediately(true); plPcduHandler->enablePeriodicPrintout(true, 5); #endif -#endif } void ObjectFactory::createTestComponents(LinuxLibgpioIF* gpioComIF) { diff --git a/bsp_q7s/core/ObjectFactory.h b/bsp_q7s/core/ObjectFactory.h index ecc92f01..d680a7c9 100644 --- a/bsp_q7s/core/ObjectFactory.h +++ b/bsp_q7s/core/ObjectFactory.h @@ -5,6 +5,7 @@ class LinuxLibgpioIF; class UartComIF; class SpiComIF; class I2cComIF; +class PowerSwitchIF; namespace ObjectFactory { @@ -13,13 +14,13 @@ void produce(void* args); void createCommunicationInterfaces(LinuxLibgpioIF** gpioComIF, UartComIF** uartComIF, SpiComIF** spiComIF, I2cComIF** i2cComIF); - +void createPcduComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF** pwrSwitcher); void createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF* spiComIF); void createTmpComponents(); -void createPcduComponents(LinuxLibgpioIF* gpioComIF); void createRadSensorComponent(LinuxLibgpioIF* gpioComIF); void createSunSensorComponents(LinuxLibgpioIF* gpioComIF, SpiComIF* spiComIF); -void createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComIF* uartComIF); +void createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComIF* uartComIF, + PowerSwitchIF* pwrSwitcher); void createHeaterComponents(); void createSolarArrayDeploymentComponents(); void createSyrlinksComponents(); diff --git a/bsp_q7s/core/obsw.cpp b/bsp_q7s/core/obsw.cpp index 04163a82..4b0639f7 100644 --- a/bsp_q7s/core/obsw.cpp +++ b/bsp_q7s/core/obsw.cpp @@ -6,13 +6,15 @@ #include "InitMission.h" #include "OBSWConfig.h" #include "OBSWVersion.h" -#include "fsfw/FSFWVersion.h" #include "fsfw/tasks/TaskFactory.h" +#include "fsfw/version.h" #include "watchdogConf.h" static int OBSW_ALREADY_RUNNING = -2; int obsw::obsw() { + fsfw::Version version; + fsfw::getVersion(version); std::cout << "-- EIVE OBSW --" << std::endl; #if BOARD_TE0720 == 0 std::cout << "-- Compiled for Linux (Xiphos Q7S) --" << std::endl; @@ -20,7 +22,8 @@ int obsw::obsw() { std::cout << "-- Compiled for Linux (TE0720) --" << std::endl; #endif std::cout << "-- OBSW v" << SW_VERSION << "." << SW_SUBVERSION << "." << SW_REVISION << ", FSFW v" - << FSFW_VERSION << "." << FSFW_SUBVERSION << "." << FSFW_REVISION << "--" << std::endl; + << version.major << "." << version.minor << "." << version.revision << "--" + << std::endl; std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl; #if Q7S_CHECK_FOR_ALREADY_RUNNING_IMG == 1 diff --git a/bsp_q7s/devices/PlocSupervisorHandler.h b/bsp_q7s/devices/PlocSupervisorHandler.h index 986e5bbb..b85b8ace 100644 --- a/bsp_q7s/devices/PlocSupervisorHandler.h +++ b/bsp_q7s/devices/PlocSupervisorHandler.h @@ -5,6 +5,7 @@ #include #include +#include "OBSWConfig.h" #include "devicedefinitions/PlocSupervisorDefinitions.h" /** diff --git a/bsp_q7s/memory/SdCardManager.cpp b/bsp_q7s/memory/SdCardManager.cpp index 769a7dd7..b336b84c 100644 --- a/bsp_q7s/memory/SdCardManager.cpp +++ b/bsp_q7s/memory/SdCardManager.cpp @@ -1,6 +1,7 @@ #include "SdCardManager.h" #include +#include #include #include @@ -8,6 +9,7 @@ #include #include +#include "OBSWConfig.h" #include "common/config/commonObjects.h" #include "fsfw/ipc/MutexFactory.h" #include "fsfw/serviceinterface/ServiceInterface.h" @@ -404,16 +406,13 @@ SdCardManager::OpStatus SdCardManager::checkCurrentOp(Operations& currentOp) { bool bytesRead = false; #if OBSW_ENABLE_TIMERS == 1 - Timer timer; - timer.setTimer(100); - uint32_t remainingTimeMs = 0; + Countdown timer(100); #endif while (true) { ReturnValue_t result = cmdExecutor.check(bytesRead); // This timer can prevent deadlocks due to missconfigurations #if OBSW_ENABLE_TIMERS == 1 - timer.getTimer(&remainingTimeMs); - if (remainingTimeMs == 0) { + if (timer.hasTimedOut()) { sif::error << "SdCardManager::checkCurrentOp: Timeout!" << std::endl; return OpStatus::FAIL; } diff --git a/common/config/OBSWVersion.h b/common/config/OBSWVersion.h index 39cb356a..f719a274 100644 --- a/common/config/OBSWVersion.h +++ b/common/config/OBSWVersion.h @@ -4,7 +4,7 @@ const char* const SW_NAME = "eive"; #define SW_VERSION 1 -#define SW_SUBVERSION 8 +#define SW_SUBVERSION 9 #define SW_REVISION 0 #endif /* COMMON_CONFIG_OBSWVERSION_H_ */ diff --git a/common/config/commonConfig.h.in b/common/config/commonConfig.h.in index c18d4bff..6d74884f 100644 --- a/common/config/commonConfig.h.in +++ b/common/config/commonConfig.h.in @@ -12,7 +12,7 @@ // because UDP packets are not allowed in the VPN // This will cause the OBSW to initialize the TMTC bridge responsible for exchanging data with the // CCSDS IP Cores. -#define OBSW_USE_TCP_BRIDGE 1 +#define OBSW_USE_TMTC_TCP_BRIDGE 1 namespace common { extern const uint16_t PUS_PACKET_ID; diff --git a/common/config/commonObjects.h b/common/config/commonObjects.h index 6cc90be9..30b05333 100644 --- a/common/config/commonObjects.h +++ b/common/config/commonObjects.h @@ -91,6 +91,9 @@ enum commonObjects: uint32_t { STR_HELPER = 0x44330002, AXI_PTME_CONFIG = 44330003, PTME_CONFIG = 44330004, + + // 0x73 ('s') for assemblies and system/subsystem components + ACS_BOARD_ASS = 0x73000001 }; } diff --git a/common/config/devices/powerSwitcherList.h b/common/config/devices/powerSwitcherList.h index a9a75ce4..f99e0930 100644 --- a/common/config/devices/powerSwitcherList.h +++ b/common/config/devices/powerSwitcherList.h @@ -3,6 +3,7 @@ #include "OBSWConfig.h" +#include #include namespace pcduSwitches { @@ -33,32 +34,36 @@ enum Switches: uint8_t { static const uint8_t ON = 1; static const uint8_t OFF = 0; -/* Output states after reboot of the PDUs */ +// Output states after reboot of the PDUs + +const std::array INIT_SWITCH_STATES = { + // PDU 1 +// Because the TE0720 is not connected to the PCDU, this switch is always on #if BOARD_TE0720 == 1 -/* Because the TE0720 is not connected to the PCDU, this switch is always on */ -static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = ON; + ON, #else -static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = OFF; + OFF, #endif -static const uint8_t INIT_STATE_SYRLINKS = OFF; -static const uint8_t INIT_STATE_STAR_TRACKER = OFF; -static const uint8_t INIT_STATE_MGT = OFF; -static const uint8_t INIT_STATE_SUS_NOMINAL = OFF; -static const uint8_t INIT_STATE_SOLAR_CELL_EXP = OFF; -static const uint8_t INIT_STATE_PLOC = OFF; -static const uint8_t INIT_STATE_ACS_BOARD_SIDE_A = OFF; - -static const uint8_t INIT_STATE_Q7S = ON; -static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH1 = OFF; -static const uint8_t INIT_STATE_RW = OFF; -static const uint8_t INIT_STATE_SUS_REDUNDANT = OFF; -static const uint8_t INIT_STATE_DEPLOYMENT_MECHANISM = OFF; -static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH6 = OFF; -static const uint8_t INIT_STATE_ACS_BOARD_SIDE_B = OFF; -static const uint8_t INIT_STATE_PAYLOAD_CAMERA = OFF; -static const uint8_t INIT_STATE_TCS_BOARD_3V3 = OFF; + OFF, + OFF, + OFF, + OFF, + OFF, + OFF, + OFF, + OFF, + // PDU 2 + ON, + OFF, + OFF, + OFF, + OFF, + OFF, + OFF, + OFF, + OFF +}; } - #endif /* FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ */ diff --git a/common/config/lwgps_opts.h b/common/config/lwgps_opts.h index 20632d6f..2be39f1d 100644 --- a/common/config/lwgps_opts.h +++ b/common/config/lwgps_opts.h @@ -41,4 +41,8 @@ * copy & replace here settings you want to change values */ +#ifndef __DOXYGEN__ +#define __DOXYGEN__ 0 +#endif + #endif /* LWGPS_HDR_OPTS_H */ diff --git a/fsfw b/fsfw index 7571987a..3b497dbb 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 7571987a1d90528d067e2ab86d1b589bc0e89b42 +Subproject commit 3b497dbb8dae77f1cf28f50f7ba770c4256acd2d diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv index 8d4d39e3..6bb34d7d 100644 --- a/generators/bsp_q7s_events.csv +++ b/generators/bsp_q7s_events.csv @@ -77,6 +77,9 @@ 8901;0x22c5;CLOCK_SET_FAILURE;LOW;;fsfw/src/fsfw/pus/Service9TimeManagement.h 9700;0x25e4;TEST;INFO;;fsfw/src/fsfw/pus/Service17Test.h 10600;0x2968;CHANGE_OF_SETUP_PARAMETER;LOW;;fsfw/hal/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h +10800;0x2a30;SWITCH_CMD_SENT;INFO;Indicates that a FSFW object requested setting a switch P1: 1 if on was requested, 0 for off | P2: Switch Index;mission/devices/devicedefinitions/powerDefinitions.h +10801;0x2a31;SWITCH_HAS_CHANGED;INFO;Indicated that a swithc state has changed P1: New switch state, 1 for on, 0 for off | P2: Switch Index;mission/devices/devicedefinitions/powerDefinitions.h +10802;0x2a32;SWITCHING_Q7S_DENIED;MEDIUM;;mission/devices/devicedefinitions/powerDefinitions.h 10900;0x2a94;GPIO_PULL_HIGH_FAILED;LOW;;mission/devices/HeaterHandler.h 10901;0x2a95;GPIO_PULL_LOW_FAILED;LOW;;mission/devices/HeaterHandler.h 10902;0x2a96;SWITCH_ALREADY_ON;LOW;;mission/devices/HeaterHandler.h @@ -106,9 +109,8 @@ 11502;0x2cee;SUPV_ACK_FAILURE;LOW;PLOC supervisor received acknowledgment failure report;bsp_q7s/devices/PlocSupervisorHandler.h 11503;0x2cef;SUPV_EXE_FAILURE;LOW;PLOC received execution failure report;bsp_q7s/devices/PlocSupervisorHandler.h 11504;0x2cf0;SUPV_CRC_FAILURE_EVENT;LOW;PLOC supervisor reply has invalid crc;bsp_q7s/devices/PlocSupervisorHandler.h -11600;0x2d50;ALLOC_FAILURE;MEDIUM;;bsp_q7s/core/CoreController.h -11601;0x2d51;REBOOT_SW;MEDIUM; Software reboot occured. Can also be a systemd reboot. P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h -11603;0x2d53;REBOOT_HW;MEDIUM;;bsp_q7s/core/CoreController.h +11600;0x2d50;SANITIZATION_FAILED;LOW;;bsp_q7s/memory/SdCardManager.h +11601;0x2d51;MOUNTED_SD_CARD;INFO;;bsp_q7s/memory/SdCardManager.h 11700;0x2db4;UPDATE_FILE_NOT_EXISTS;LOW;;bsp_q7s/devices/PlocUpdater.h 11701;0x2db5;ACTION_COMMANDING_FAILED;LOW;Failed to send command to supervisor handler P1: Return value of CommandActionHelper::commandAction P2: Action ID of command to send;bsp_q7s/devices/PlocUpdater.h 11702;0x2db6;UPDATE_AVAILABLE_FAILED;LOW;Supervisor handler replied action message indicating a command execution failure of the update available command;bsp_q7s/devices/PlocUpdater.h @@ -139,6 +141,7 @@ 12014;0x2eee;STR_HELPER_FILE_NOT_EXISTS;LOW;Specified file does not exist P1: Internal state of str helper;linux/devices/startracker/StrHelper.h 12015;0x2eef;STR_HELPER_SENDING_PACKET_FAILED;LOW;;linux/devices/startracker/StrHelper.h 12016;0x2ef0;STR_HELPER_REQUESTING_MSG_FAILED;LOW;;linux/devices/startracker/StrHelper.h +12100;0x2f44;TRANSITION_BACK_TO_OFF;MEDIUM;Could not transition properly and went back to ALL OFF;mission/devices/PayloadPcduHandler.h 12101;0x2f45;NEG_V_OUT_OF_BOUNDS;MEDIUM;P1: 0 -> too low, 1 -> too high P2: Float value;mission/devices/PayloadPcduHandler.h 12102;0x2f46;U_DRO_OUT_OF_BOUNDS;MEDIUM;P1: 0 -> too low, 1 -> too high P2: Float value;mission/devices/PayloadPcduHandler.h 12103;0x2f47;I_DRO_OUT_OF_BOUNDS;MEDIUM;P1: 0 -> too low, 1 -> too high P2: Float value;mission/devices/PayloadPcduHandler.h @@ -150,3 +153,10 @@ 12109;0x2f4d;I_MPA_OUT_OF_BOUNDS;MEDIUM;P1: 0 -> too low, 1 -> too high P2: Float value;mission/devices/PayloadPcduHandler.h 12110;0x2f4e;U_HPA_OUT_OF_BOUNDS;MEDIUM;P1: 0 -> too low, 1 -> too high P2: Float value;mission/devices/PayloadPcduHandler.h 12111;0x2f4f;I_HPA_OUT_OF_BOUNDS;MEDIUM;P1: 0 -> too low, 1 -> too high P2: Float value;mission/devices/PayloadPcduHandler.h +12200;0x2fa8;TRANSITION_OTHER_SIDE_FAILED;HIGH;;mission/system/AcsBoardAssembly.h +12201;0x2fa9;NOT_ENOUGH_DEVICES_DUAL_MODE;HIGH;;mission/system/AcsBoardAssembly.h +12202;0x2faa;POWER_STATE_MACHINE_TIMEOUT;MEDIUM;;mission/system/AcsBoardAssembly.h +13600;0x3520;ALLOC_FAILURE;MEDIUM;;bsp_q7s/core/CoreController.h +13601;0x3521;REBOOT_SW;MEDIUM; Software reboot occured. Can also be a systemd reboot. P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h +13602;0x3522;REBOOT_MECHANISM_TRIGGERED;MEDIUM;The reboot mechanism was triggered. P1: First 16 bits: Last Chip, Last 16 bits: Last Copy, P2: Each byte is the respective reboot count for the slots;bsp_q7s/core/CoreController.h +13603;0x3523;REBOOT_HW;MEDIUM;;bsp_q7s/core/CoreController.h diff --git a/generators/bsp_q7s_objects.csv b/generators/bsp_q7s_objects.csv index a0c0a6dc..da127d35 100644 --- a/generators/bsp_q7s_objects.csv +++ b/generators/bsp_q7s_objects.csv @@ -107,6 +107,7 @@ 0x5400CAFE;DUMMY_INTERFACE 0x54123456;LIBGPIOD_TEST 0x54694269;TEST_TASK +0x73000001;ACS_BOARD_ASS 0x73000100;TM_FUNNEL 0x73500000;CCSDS_IP_CORE_BRIDGE 0xFFFFFFFF;NO_OBJECT diff --git a/generators/events/event_parser.py b/generators/events/event_parser.py index 7b6b86c8..9398ba98 100644 --- a/generators/events/event_parser.py +++ b/generators/events/event_parser.py @@ -82,7 +82,10 @@ def parse_events( handle_csv_export( file_name=CSV_FILENAME, event_list=event_list, file_separator=FILE_SEPARATOR ) - copy_file(filename=CSV_FILENAME, destination=CSV_COPY_DEST, delete_existing_file=True) + LOGGER.info(f"Copying CSV file to {CSV_COPY_DEST}") + copy_file( + filename=CSV_FILENAME, destination=CSV_COPY_DEST, delete_existing_file=True + ) if generate_cpp: handle_cpp_export( @@ -93,7 +96,7 @@ def parse_events( header_file_name=CPP_H_FILENAME, ) if COPY_CPP_FILE: - LOGGER.info(f"EventParser: Copying file to {CPP_COPY_DESTINATION}") + LOGGER.info(f"EventParser: Copying CPP translation file to {CPP_COPY_DESTINATION}") copy_file(CPP_FILENAME, CPP_COPY_DESTINATION) copy_file(CPP_H_FILENAME, CPP_COPY_DESTINATION) diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index 30188315..9cbd0bef 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 152 translations. + * @brief Auto-generated event translation file. Contains 162 translations. * @details - * Generated on: 2022-03-04 14:55:20 + * Generated on: 2022-03-07 17:09:35 */ #include "translateEvents.h" @@ -84,6 +84,9 @@ const char *CLOCK_SET_STRING = "CLOCK_SET"; const char *CLOCK_SET_FAILURE_STRING = "CLOCK_SET_FAILURE"; const char *TEST_STRING = "TEST"; const char *CHANGE_OF_SETUP_PARAMETER_STRING = "CHANGE_OF_SETUP_PARAMETER"; +const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT"; +const char *SWITCH_HAS_CHANGED_STRING = "SWITCH_HAS_CHANGED"; +const char *SWITCHING_Q7S_DENIED_STRING = "SWITCHING_Q7S_DENIED"; const char *GPIO_PULL_HIGH_FAILED_STRING = "GPIO_PULL_HIGH_FAILED"; const char *GPIO_PULL_LOW_FAILED_STRING = "GPIO_PULL_LOW_FAILED"; const char *SWITCH_ALREADY_ON_STRING = "SWITCH_ALREADY_ON"; @@ -113,9 +116,8 @@ const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_ const char *SUPV_ACK_FAILURE_STRING = "SUPV_ACK_FAILURE"; const char *SUPV_EXE_FAILURE_STRING = "SUPV_EXE_FAILURE"; const char *SUPV_CRC_FAILURE_EVENT_STRING = "SUPV_CRC_FAILURE_EVENT"; -const char *ALLOC_FAILURE_STRING = "ALLOC_FAILURE"; -const char *REBOOT_SW_STRING = "REBOOT_SW"; -const char *REBOOT_HW_STRING = "REBOOT_HW"; +const char *SANITIZATION_FAILED_STRING = "SANITIZATION_FAILED"; +const char *MOUNTED_SD_CARD_STRING = "MOUNTED_SD_CARD"; const char *UPDATE_FILE_NOT_EXISTS_STRING = "UPDATE_FILE_NOT_EXISTS"; const char *ACTION_COMMANDING_FAILED_STRING = "ACTION_COMMANDING_FAILED"; const char *UPDATE_AVAILABLE_FAILED_STRING = "UPDATE_AVAILABLE_FAILED"; @@ -146,6 +148,7 @@ 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 *TRANSITION_BACK_TO_OFF_STRING = "TRANSITION_BACK_TO_OFF"; const char *NEG_V_OUT_OF_BOUNDS_STRING = "NEG_V_OUT_OF_BOUNDS"; const char *U_DRO_OUT_OF_BOUNDS_STRING = "U_DRO_OUT_OF_BOUNDS"; const char *I_DRO_OUT_OF_BOUNDS_STRING = "I_DRO_OUT_OF_BOUNDS"; @@ -157,6 +160,13 @@ const char *U_MPA_OUT_OF_BOUNDS_STRING = "U_MPA_OUT_OF_BOUNDS"; const char *I_MPA_OUT_OF_BOUNDS_STRING = "I_MPA_OUT_OF_BOUNDS"; const char *U_HPA_OUT_OF_BOUNDS_STRING = "U_HPA_OUT_OF_BOUNDS"; const char *I_HPA_OUT_OF_BOUNDS_STRING = "I_HPA_OUT_OF_BOUNDS"; +const char *TRANSITION_OTHER_SIDE_FAILED_STRING = "TRANSITION_OTHER_SIDE_FAILED"; +const char *NOT_ENOUGH_DEVICES_DUAL_MODE_STRING = "NOT_ENOUGH_DEVICES_DUAL_MODE"; +const char *POWER_STATE_MACHINE_TIMEOUT_STRING = "POWER_STATE_MACHINE_TIMEOUT"; +const char *ALLOC_FAILURE_STRING = "ALLOC_FAILURE"; +const char *REBOOT_SW_STRING = "REBOOT_SW"; +const char *REBOOT_MECHANISM_TRIGGERED_STRING = "REBOOT_MECHANISM_TRIGGERED"; +const char *REBOOT_HW_STRING = "REBOOT_HW"; const char *translateEvents(Event event) { switch ((event & 0xFFFF)) { @@ -318,6 +328,12 @@ const char *translateEvents(Event event) { return TEST_STRING; case (10600): return CHANGE_OF_SETUP_PARAMETER_STRING; + case (10800): + return SWITCH_CMD_SENT_STRING; + case (10801): + return SWITCH_HAS_CHANGED_STRING; + case (10802): + return SWITCHING_Q7S_DENIED_STRING; case (10900): return GPIO_PULL_HIGH_FAILED_STRING; case (10901): @@ -377,11 +393,9 @@ const char *translateEvents(Event event) { case (11504): return SUPV_CRC_FAILURE_EVENT_STRING; case (11600): - return ALLOC_FAILURE_STRING; + return SANITIZATION_FAILED_STRING; case (11601): - return REBOOT_SW_STRING; - case (11603): - return REBOOT_HW_STRING; + return MOUNTED_SD_CARD_STRING; case (11700): return UPDATE_FILE_NOT_EXISTS_STRING; case (11701): @@ -442,6 +456,8 @@ const char *translateEvents(Event event) { return STR_HELPER_SENDING_PACKET_FAILED_STRING; case (12016): return STR_HELPER_REQUESTING_MSG_FAILED_STRING; + case (12100): + return TRANSITION_BACK_TO_OFF_STRING; case (12101): return NEG_V_OUT_OF_BOUNDS_STRING; case (12102): @@ -464,6 +480,20 @@ const char *translateEvents(Event event) { return U_HPA_OUT_OF_BOUNDS_STRING; case (12111): return I_HPA_OUT_OF_BOUNDS_STRING; + case (12200): + return TRANSITION_OTHER_SIDE_FAILED_STRING; + case (12201): + return NOT_ENOUGH_DEVICES_DUAL_MODE_STRING; + case (12202): + return POWER_STATE_MACHINE_TIMEOUT_STRING; + case (13600): + return ALLOC_FAILURE_STRING; + case (13601): + return REBOOT_SW_STRING; + case (13602): + return REBOOT_MECHANISM_TRIGGERED_STRING; + case (13603): + return REBOOT_HW_STRING; default: return "UNKNOWN_EVENT"; } diff --git a/generators/fsfwgen b/generators/fsfwgen index 348877b5..c5ef1783 160000 --- a/generators/fsfwgen +++ b/generators/fsfwgen @@ -1 +1 @@ -Subproject commit 348877b5d93ad17db4b03d08b134a2e1c87af2df +Subproject commit c5ef1783a3b082c0e88561bd91bc3ee0f459fafc diff --git a/generators/objects/objects.py b/generators/objects/objects.py index 3ea80e8e..fa174bc1 100644 --- a/generators/objects/objects.py +++ b/generators/objects/objects.py @@ -118,5 +118,5 @@ def handle_file_export(list_items): copy_file( filename=CSV_OBJECT_FILENAME, destination=CSV_COPY_DEST, - delete_existing_file=True + delete_existing_file=True, ) diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index bf38d322..b29ed5db 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: 2022-03-04 14:55:17 + * Contains 113 translations. + * Generated on: 2022-03-07 17:15:28 */ #include "translateObjects.h" @@ -115,6 +115,7 @@ const char *DUMMY_HANDLER_STRING = "DUMMY_HANDLER"; const char *DUMMY_INTERFACE_STRING = "DUMMY_INTERFACE"; const char *LIBGPIOD_TEST_STRING = "LIBGPIOD_TEST"; const char *TEST_TASK_STRING = "TEST_TASK"; +const char *ACS_BOARD_ASS_STRING = "ACS_BOARD_ASS"; const char *TM_FUNNEL_STRING = "TM_FUNNEL"; const char *CCSDS_IP_CORE_BRIDGE_STRING = "CCSDS_IP_CORE_BRIDGE"; const char *NO_OBJECT_STRING = "NO_OBJECT"; @@ -339,6 +340,8 @@ const char *translateObject(object_id_t object) { return LIBGPIOD_TEST_STRING; case 0x54694269: return TEST_TASK_STRING; + case 0x73000001: + return ACS_BOARD_ASS_STRING; case 0x73000100: return TM_FUNNEL_STRING; case 0x73500000: diff --git a/generators/returnvalues/returnvalues_parser.py b/generators/returnvalues/returnvalues_parser.py index 48d929ea..53c84564 100644 --- a/generators/returnvalues/returnvalues_parser.py +++ b/generators/returnvalues/returnvalues_parser.py @@ -87,7 +87,7 @@ def parse_returnvalues(): copy_file( filename=CSV_RETVAL_FILENAME, destination=CSV_COPY_DEST, - delete_existing_file=True + delete_existing_file=True, ) if EXPORT_TO_SQL: LOGGER.info("ReturnvalueParser: Exporting to SQL") diff --git a/linux/boardtest/UartTestClass.cpp b/linux/boardtest/UartTestClass.cpp index 1f8c2563..9c51ed8a 100644 --- a/linux/boardtest/UartTestClass.cpp +++ b/linux/boardtest/UartTestClass.cpp @@ -14,6 +14,10 @@ #define GPS_REPLY_WIRETAPPING 0 +#ifndef RPI_TEST_GPS_HANDLER +#define RPI_TEST_GPS_HANDLER 0 +#endif + UartTestClass::UartTestClass(object_id_t objectId) : TestTask(objectId) { mode = TestModes::SCEX; } ReturnValue_t UartTestClass::initialize() { diff --git a/linux/devices/GPSHyperionLinuxController.cpp b/linux/devices/GPSHyperionLinuxController.cpp index d5b2741e..3260818c 100644 --- a/linux/devices/GPSHyperionLinuxController.cpp +++ b/linux/devices/GPSHyperionLinuxController.cpp @@ -1,5 +1,6 @@ #include "GPSHyperionLinuxController.h" +#include "OBSWConfig.h" #include "fsfw/datapool/PoolReadGuard.h" #include "fsfw/timemanager/Clock.h" @@ -30,10 +31,12 @@ ReturnValue_t GPSHyperionLinuxController::checkModeCommand(Mode_t mode, Submode_ uint32_t *msToReachTheMode) { if (not modeCommanded) { if (mode == MODE_ON or mode == MODE_OFF) { - // 10 minutes time to reach fix - *msToReachTheMode = 600000; + // 5h time to reach fix + *msToReachTheMode = MAX_SECONDS_TO_REACH_FIX; maxTimeToReachFix.resetTimer(); modeCommanded = true; + } else if (mode == MODE_NORMAL) { + return HasModesIF::INVALID_MODE; } } return HasReturnvaluesIF::RETURN_OK; diff --git a/linux/devices/GPSHyperionLinuxController.h b/linux/devices/GPSHyperionLinuxController.h index b8ab028d..f0e4e6e0 100644 --- a/linux/devices/GPSHyperionLinuxController.h +++ b/linux/devices/GPSHyperionLinuxController.h @@ -21,7 +21,7 @@ */ class GPSHyperionLinuxController : public ExtendedControllerBase { public: - static constexpr uint32_t MAX_SECONDS_TO_REACH_FIX = 600; + static constexpr uint32_t MAX_SECONDS_TO_REACH_FIX = 60 * 60 * 5; GPSHyperionLinuxController(object_id_t objectId, object_id_t parentId, bool debugHyperionGps = false); virtual ~GPSHyperionLinuxController(); diff --git a/linux/fsfwconfig/OBSWConfig.h.in b/linux/fsfwconfig/OBSWConfig.h.in index f741364a..36802829 100644 --- a/linux/fsfwconfig/OBSWConfig.h.in +++ b/linux/fsfwconfig/OBSWConfig.h.in @@ -41,6 +41,7 @@ debugging. */ #define OBSW_TC_FROM_PDEC 0 #define OBSW_ENABLE_TIMERS 1 +#define OBSW_INITIALIZE_SWITCHES 1 #define OBSW_ADD_MGT 1 #define OBSW_ADD_BPX_BATTERY_HANDLER 1 #define OBSW_ADD_STAR_TRACKER 0 @@ -48,7 +49,7 @@ debugging. */ #define OBSW_ADD_PLOC_MPSOC 0 #define OBSW_ADD_SUN_SENSORS 0 #define OBSW_ADD_ACS_BOARD 1 -#define OBSW_ADD_ACS_HANDLERS 0 +#define OBSW_ADD_ACS_HANDLERS 1 #define OBSW_ADD_RW 0 #define OBSW_ADD_RTD_DEVICES 0 #define OBSW_ADD_TMP_DEVICES 0 @@ -84,6 +85,7 @@ debugging. */ #define OBSW_ADD_UART_TEST_CODE 0 #define OBSW_TEST_ACS 0 +#define OBSW_TEST_ACS_BOARD_ASS 0 #define OBSW_DEBUG_ACS 0 #define OBSW_TEST_SUS 0 #define OBSW_DEBUG_SUS 0 diff --git a/linux/fsfwconfig/events/subsystemIdRanges.h b/linux/fsfwconfig/events/subsystemIdRanges.h index 33ef1a09..768797b5 100644 --- a/linux/fsfwconfig/events/subsystemIdRanges.h +++ b/linux/fsfwconfig/events/subsystemIdRanges.h @@ -13,7 +13,7 @@ namespace SUBSYSTEM_ID { enum : uint8_t { SUBSYSTEM_ID_START = COMMON_SUBSYSTEM_ID_END, - CORE = 116, + CORE = 136, }; } diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index 30188315..9cbd0bef 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 152 translations. + * @brief Auto-generated event translation file. Contains 162 translations. * @details - * Generated on: 2022-03-04 14:55:20 + * Generated on: 2022-03-07 17:09:35 */ #include "translateEvents.h" @@ -84,6 +84,9 @@ const char *CLOCK_SET_STRING = "CLOCK_SET"; const char *CLOCK_SET_FAILURE_STRING = "CLOCK_SET_FAILURE"; const char *TEST_STRING = "TEST"; const char *CHANGE_OF_SETUP_PARAMETER_STRING = "CHANGE_OF_SETUP_PARAMETER"; +const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT"; +const char *SWITCH_HAS_CHANGED_STRING = "SWITCH_HAS_CHANGED"; +const char *SWITCHING_Q7S_DENIED_STRING = "SWITCHING_Q7S_DENIED"; const char *GPIO_PULL_HIGH_FAILED_STRING = "GPIO_PULL_HIGH_FAILED"; const char *GPIO_PULL_LOW_FAILED_STRING = "GPIO_PULL_LOW_FAILED"; const char *SWITCH_ALREADY_ON_STRING = "SWITCH_ALREADY_ON"; @@ -113,9 +116,8 @@ const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_ const char *SUPV_ACK_FAILURE_STRING = "SUPV_ACK_FAILURE"; const char *SUPV_EXE_FAILURE_STRING = "SUPV_EXE_FAILURE"; const char *SUPV_CRC_FAILURE_EVENT_STRING = "SUPV_CRC_FAILURE_EVENT"; -const char *ALLOC_FAILURE_STRING = "ALLOC_FAILURE"; -const char *REBOOT_SW_STRING = "REBOOT_SW"; -const char *REBOOT_HW_STRING = "REBOOT_HW"; +const char *SANITIZATION_FAILED_STRING = "SANITIZATION_FAILED"; +const char *MOUNTED_SD_CARD_STRING = "MOUNTED_SD_CARD"; const char *UPDATE_FILE_NOT_EXISTS_STRING = "UPDATE_FILE_NOT_EXISTS"; const char *ACTION_COMMANDING_FAILED_STRING = "ACTION_COMMANDING_FAILED"; const char *UPDATE_AVAILABLE_FAILED_STRING = "UPDATE_AVAILABLE_FAILED"; @@ -146,6 +148,7 @@ 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 *TRANSITION_BACK_TO_OFF_STRING = "TRANSITION_BACK_TO_OFF"; const char *NEG_V_OUT_OF_BOUNDS_STRING = "NEG_V_OUT_OF_BOUNDS"; const char *U_DRO_OUT_OF_BOUNDS_STRING = "U_DRO_OUT_OF_BOUNDS"; const char *I_DRO_OUT_OF_BOUNDS_STRING = "I_DRO_OUT_OF_BOUNDS"; @@ -157,6 +160,13 @@ const char *U_MPA_OUT_OF_BOUNDS_STRING = "U_MPA_OUT_OF_BOUNDS"; const char *I_MPA_OUT_OF_BOUNDS_STRING = "I_MPA_OUT_OF_BOUNDS"; const char *U_HPA_OUT_OF_BOUNDS_STRING = "U_HPA_OUT_OF_BOUNDS"; const char *I_HPA_OUT_OF_BOUNDS_STRING = "I_HPA_OUT_OF_BOUNDS"; +const char *TRANSITION_OTHER_SIDE_FAILED_STRING = "TRANSITION_OTHER_SIDE_FAILED"; +const char *NOT_ENOUGH_DEVICES_DUAL_MODE_STRING = "NOT_ENOUGH_DEVICES_DUAL_MODE"; +const char *POWER_STATE_MACHINE_TIMEOUT_STRING = "POWER_STATE_MACHINE_TIMEOUT"; +const char *ALLOC_FAILURE_STRING = "ALLOC_FAILURE"; +const char *REBOOT_SW_STRING = "REBOOT_SW"; +const char *REBOOT_MECHANISM_TRIGGERED_STRING = "REBOOT_MECHANISM_TRIGGERED"; +const char *REBOOT_HW_STRING = "REBOOT_HW"; const char *translateEvents(Event event) { switch ((event & 0xFFFF)) { @@ -318,6 +328,12 @@ const char *translateEvents(Event event) { return TEST_STRING; case (10600): return CHANGE_OF_SETUP_PARAMETER_STRING; + case (10800): + return SWITCH_CMD_SENT_STRING; + case (10801): + return SWITCH_HAS_CHANGED_STRING; + case (10802): + return SWITCHING_Q7S_DENIED_STRING; case (10900): return GPIO_PULL_HIGH_FAILED_STRING; case (10901): @@ -377,11 +393,9 @@ const char *translateEvents(Event event) { case (11504): return SUPV_CRC_FAILURE_EVENT_STRING; case (11600): - return ALLOC_FAILURE_STRING; + return SANITIZATION_FAILED_STRING; case (11601): - return REBOOT_SW_STRING; - case (11603): - return REBOOT_HW_STRING; + return MOUNTED_SD_CARD_STRING; case (11700): return UPDATE_FILE_NOT_EXISTS_STRING; case (11701): @@ -442,6 +456,8 @@ const char *translateEvents(Event event) { return STR_HELPER_SENDING_PACKET_FAILED_STRING; case (12016): return STR_HELPER_REQUESTING_MSG_FAILED_STRING; + case (12100): + return TRANSITION_BACK_TO_OFF_STRING; case (12101): return NEG_V_OUT_OF_BOUNDS_STRING; case (12102): @@ -464,6 +480,20 @@ const char *translateEvents(Event event) { return U_HPA_OUT_OF_BOUNDS_STRING; case (12111): return I_HPA_OUT_OF_BOUNDS_STRING; + case (12200): + return TRANSITION_OTHER_SIDE_FAILED_STRING; + case (12201): + return NOT_ENOUGH_DEVICES_DUAL_MODE_STRING; + case (12202): + return POWER_STATE_MACHINE_TIMEOUT_STRING; + case (13600): + return ALLOC_FAILURE_STRING; + case (13601): + return REBOOT_SW_STRING; + case (13602): + return REBOOT_MECHANISM_TRIGGERED_STRING; + case (13603): + return REBOOT_HW_STRING; default: return "UNKNOWN_EVENT"; } diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index bf38d322..b29ed5db 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: 2022-03-04 14:55:17 + * Contains 113 translations. + * Generated on: 2022-03-07 17:15:28 */ #include "translateObjects.h" @@ -115,6 +115,7 @@ const char *DUMMY_HANDLER_STRING = "DUMMY_HANDLER"; const char *DUMMY_INTERFACE_STRING = "DUMMY_INTERFACE"; const char *LIBGPIOD_TEST_STRING = "LIBGPIOD_TEST"; const char *TEST_TASK_STRING = "TEST_TASK"; +const char *ACS_BOARD_ASS_STRING = "ACS_BOARD_ASS"; const char *TM_FUNNEL_STRING = "TM_FUNNEL"; const char *CCSDS_IP_CORE_BRIDGE_STRING = "CCSDS_IP_CORE_BRIDGE"; const char *NO_OBJECT_STRING = "NO_OBJECT"; @@ -339,6 +340,8 @@ const char *translateObject(object_id_t object) { return LIBGPIOD_TEST_STRING; case 0x54694269: return TEST_TASK_STRING; + case 0x73000001: + return ACS_BOARD_ASS_STRING; case 0x73000100: return TM_FUNNEL_STRING; case 0x73500000: diff --git a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp index cc93a933..62ea6296 100644 --- a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp +++ b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp @@ -5,8 +5,13 @@ #include #include -#include "OBSWConfig.h" -#include "objects/systemObjectList.h" +#ifndef RPI_TEST_ADIS16507 +#define RPI_TEST_ADIS16507 0 +#endif + +#ifndef RPI_TEST_GPS_HANDLER +#define RPI_TEST_GPS_HANDLER 0 +#endif ReturnValue_t pst::pstGpio(FixedTimeslotTaskIF *thisSequence) { // Length of a communication cycle @@ -359,7 +364,7 @@ ReturnValue_t pst::pstSpi(FixedTimeslotTaskIF *thisSequence) { #endif #if OBSW_ADD_ACS_BOARD == 1 && OBSW_ADD_ACS_HANDLERS == 1 - bool enableAside = false; + bool enableAside = true; bool enableBside = true; if (enableAside) { // A side diff --git a/mission/controller/ThermalController.cpp b/mission/controller/ThermalController.cpp index 2b6f704f..d79bb26a 100644 --- a/mission/controller/ThermalController.cpp +++ b/mission/controller/ThermalController.cpp @@ -45,4 +45,4 @@ ReturnValue_t ThermalController::checkModeCommand(Mode_t mode, Submode_t submode return INVALID_MODE; } return RETURN_OK; -} \ No newline at end of file +} diff --git a/mission/core/GenericFactory.cpp b/mission/core/GenericFactory.cpp index 651ba993..9eb27f22 100644 --- a/mission/core/GenericFactory.cpp +++ b/mission/core/GenericFactory.cpp @@ -24,7 +24,7 @@ #include "objects/systemObjectList.h" #if OBSW_ADD_TCPIP_BRIDGE == 1 -#if OBSW_USE_TCP_BRIDGE == 0 +#if OBSW_USE_TMTC_TCP_BRIDGE == 0 // UDP server includes #include "fsfw/osal/common/UdpTcPollingTask.h" #include "fsfw/osal/common/UdpTmTcBridge.h" @@ -90,7 +90,7 @@ void ObjectFactory::produceGenericObjects() { pus::PUS_SERVICE_200); #if OBSW_ADD_TCPIP_BRIDGE == 1 -#if OBSW_USE_TCP_BRIDGE == 0 +#if OBSW_USE_TMTC_TCP_BRIDGE == 0 auto tmtcBridge = new UdpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); new UdpTcPollingTask(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE); sif::info << "Created UDP server for TMTC commanding with listener port " diff --git a/mission/devices/ACUHandler.cpp b/mission/devices/ACUHandler.cpp index 60e26302..b7a54088 100644 --- a/mission/devices/ACUHandler.cpp +++ b/mission/devices/ACUHandler.cpp @@ -23,7 +23,7 @@ void ACUHandler::letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *pack parseHkTableReply(packet); handleDeviceTM(&acuHkTableDataset, id, true); -#if OBSW_ENHANCED_PRINTOUT == 1 && OBSW_DEBUG_ACU == 1 +#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_ACU == 1 acuHkTableDataset.read(); float temperatureC_1 = acuHkTableDataset.temperature1.value * 0.1; float temperatureC_2 = acuHkTableDataset.temperature2.value * 0.1; diff --git a/mission/devices/GomspaceDeviceHandler.cpp b/mission/devices/GomspaceDeviceHandler.cpp index 4cec651e..6decef16 100644 --- a/mission/devices/GomspaceDeviceHandler.cpp +++ b/mission/devices/GomspaceDeviceHandler.cpp @@ -1,5 +1,7 @@ -#include -#include +#include "GomspaceDeviceHandler.h" + +#include "devicedefinitions/GomSpacePackets.h" +#include "devicedefinitions/powerDefinitions.h" GomspaceDeviceHandler::GomspaceDeviceHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie, uint16_t maxConfigTableAddress, @@ -189,6 +191,11 @@ ReturnValue_t GomspaceDeviceHandler::generateSetParamCommand(const uint8_t* comm size_t commandDataLen) { ReturnValue_t result = setParamCacher.deSerialize(&commandData, &commandDataLen, SerializeIF::Endianness::BIG); + // This breaks layering but I really don't want to accept this command.. + if (setParamCacher.getAddress() == PDU2::CONFIG_ADDRESS_OUT_EN_Q7S) { + triggerEvent(power::SWITCHING_Q7S_DENIED, 0, 0); + return HasReturnvaluesIF::RETURN_FAILED; + } if (result != HasReturnvaluesIF::RETURN_OK) { sif::error << "GomspaceDeviceHandler: Failed to deserialize set parameter " "message" diff --git a/mission/devices/PCDUHandler.cpp b/mission/devices/PCDUHandler.cpp index 49312601..e54222b1 100644 --- a/mission/devices/PCDUHandler.cpp +++ b/mission/devices/PCDUHandler.cpp @@ -27,7 +27,6 @@ ReturnValue_t PCDUHandler::performOperation(uint8_t counter) { readCommandQueue(); return RETURN_OK; } - return RETURN_OK; } @@ -79,25 +78,9 @@ ReturnValue_t PCDUHandler::initialize() { void PCDUHandler::initializeSwitchStates() { using namespace pcduSwitches; - switchStates[Switches::PDU2_CH0_Q7S] = pcduSwitches::INIT_STATE_Q7S; - switchStates[Switches::PDU2_CH6_PL_PCDU_BATT_1_14V8] = pcduSwitches::INIT_STATE_PAYLOAD_PCDU_CH1; - switchStates[Switches::PDU2_CH2_RW_5V] = pcduSwitches::INIT_STATE_RW; - switchStates[Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V] = - pcduSwitches::INIT_STATE_TCS_BOARD_8V_HEATER_IN; - switchStates[Switches::PDU2_CH4_SUS_REDUNDANT_3V3] = pcduSwitches::INIT_STATE_SUS_REDUNDANT; - switchStates[Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V] = - pcduSwitches::INIT_STATE_DEPLOYMENT_MECHANISM; - switchStates[Switches::PDU2_CH6_PL_PCDU_BATT_1_14V8] = pcduSwitches::INIT_STATE_PAYLOAD_PCDU_CH6; - switchStates[Switches::PDU2_CH7_ACS_BOARD_SIDE_B_3V3] = pcduSwitches::INIT_STATE_ACS_BOARD_SIDE_B; - switchStates[Switches::PDU2_CH8_PAYLOAD_CAMERA] = pcduSwitches::INIT_STATE_PAYLOAD_CAMERA; - switchStates[Switches::PDU1_CH0_TCS_BOARD_3V3] = pcduSwitches::INIT_STATE_TCS_BOARD_3V3; - switchStates[Switches::PDU1_CH1_SYRLINKS_12V] = pcduSwitches::INIT_STATE_SYRLINKS; - switchStates[Switches::PDU1_CH2_STAR_TRACKER_5V] = pcduSwitches::INIT_STATE_STAR_TRACKER; - switchStates[Switches::PDU1_CH3_MGT_5V] = pcduSwitches::INIT_STATE_MGT; - switchStates[Switches::PDU1_CH4_SUS_NOMINAL_3V3] = pcduSwitches::INIT_STATE_SUS_NOMINAL; - switchStates[Switches::PDU1_CH5_SOLAR_CELL_EXP_5V] = pcduSwitches::INIT_STATE_SOLAR_CELL_EXP; - switchStates[Switches::PDU1_CH6_PLOC_12V] = pcduSwitches::INIT_STATE_PLOC; - switchStates[Switches::PDU1_CH7_ACS_A_SIDE_3V3] = pcduSwitches::INIT_STATE_ACS_BOARD_SIDE_A; + for (uint8_t idx = 0; idx < Switches::NUMBER_OF_SWITCHES; idx++) { + switchStates[idx] = INIT_SWITCH_STATES[idx]; + } } void PCDUHandler::readCommandQueue() { @@ -117,7 +100,7 @@ void PCDUHandler::readCommandQueue() { MessageQueueId_t PCDUHandler::getCommandQueue() const { return commandQueue->getId(); } -void PCDUHandler::handleChangedDataset(sid_t sid, store_address_t storeId) { +void PCDUHandler::handleChangedDataset(sid_t sid, store_address_t storeId, bool* clearMessage) { if (sid == sid_t(objects::PDU2_HANDLER, PDU2::HK_TABLE_DATA_SET_ID)) { updateHkTableDataset(storeId, &pdu2HkTableDataset, &timeStampPdu2HkDataset); updatePdu2SwitchStates(); @@ -159,25 +142,31 @@ void PCDUHandler::updateHkTableDataset(store_address_t storeId, LocalPoolDataSet void PCDUHandler::updatePdu2SwitchStates() { using namespace pcduSwitches; + GOMSPACE::Pdu pdu = GOMSPACE::Pdu::PDU2; PoolReadGuard rg(&pdu2HkTableDataset); if (rg.getReadResult() == RETURN_OK) { MutexGuard mg(pwrMutex); - switchStates[Switches::PDU2_CH0_Q7S] = pdu2HkTableDataset.outEnabledQ7S.value; - switchStates[Switches::PDU2_CH1_PL_PCDU_BATT_0_14V8] = - pdu2HkTableDataset.outEnabledPlPCDUCh1.value; - switchStates[Switches::PDU2_CH2_RW_5V] = pdu2HkTableDataset.outEnabledReactionWheels.value; - switchStates[Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V] = - pdu2HkTableDataset.outEnabledTCSBoardHeaterIn.value; - switchStates[Switches::PDU2_CH4_SUS_REDUNDANT_3V3] = - pdu2HkTableDataset.outEnabledSUSRedundant.value; - switchStates[Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V] = - pdu2HkTableDataset.outEnabledDeplMechanism.value; - switchStates[Switches::PDU2_CH6_PL_PCDU_BATT_1_14V8] = - pdu2HkTableDataset.outEnabledPlPCDUCh6.value; - switchStates[Switches::PDU2_CH7_ACS_BOARD_SIDE_B_3V3] = - pdu2HkTableDataset.outEnabledAcsBoardSideB.value; - switchStates[Switches::PDU2_CH8_PAYLOAD_CAMERA] = - pdu2HkTableDataset.outEnabledPayloadCamera.value; + checkAndUpdateSwitch(pdu, Switches::PDU2_CH0_Q7S, pdu2HkTableDataset.outEnabledQ7S.value); + + checkAndUpdateSwitch(pdu, Switches::PDU2_CH1_PL_PCDU_BATT_0_14V8, + pdu2HkTableDataset.outEnabledPlPCDUCh1.value); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH2_RW_5V, + pdu2HkTableDataset.outEnabledReactionWheels.value); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V, + pdu2HkTableDataset.outEnabledTCSBoardHeaterIn.value); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH4_SUS_REDUNDANT_3V3, + pdu2HkTableDataset.outEnabledSUSRedundant.value); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V, + pdu2HkTableDataset.outEnabledDeplMechanism.value); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH6_PL_PCDU_BATT_1_14V8, + pdu2HkTableDataset.outEnabledPlPCDUCh6.value); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH7_ACS_BOARD_SIDE_B_3V3, + pdu2HkTableDataset.outEnabledAcsBoardSideB.value); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH8_PAYLOAD_CAMERA, + pdu2HkTableDataset.outEnabledPayloadCamera.value); + if (firstSwitchInfoPdu2) { + firstSwitchInfoPdu2 = false; + } } else { sif::debug << "PCDUHandler::updatePdu2SwitchStates: Failed to read PDU2 Hk Dataset" << std::endl; @@ -187,25 +176,31 @@ void PCDUHandler::updatePdu2SwitchStates() { void PCDUHandler::updatePdu1SwitchStates() { using namespace pcduSwitches; PoolReadGuard rg(&pdu1HkTableDataset); + GOMSPACE::Pdu pdu = GOMSPACE::Pdu::PDU1; if (rg.getReadResult() == RETURN_OK) { MutexGuard mg(pwrMutex); - switchStates[Switches::PDU1_CH0_TCS_BOARD_3V3] = pdu1HkTableDataset.outEnabledTCSBoard3V3.value; - switchStates[Switches::PDU1_CH1_SYRLINKS_12V] = pdu1HkTableDataset.outEnabledSyrlinks.value; - switchStates[Switches::PDU1_CH2_STAR_TRACKER_5V] = - pdu1HkTableDataset.outEnabledStarTracker.value; - switchStates[Switches::PDU1_CH3_MGT_5V] = pdu1HkTableDataset.outEnabledMGT.value; - switchStates[Switches::PDU1_CH4_SUS_NOMINAL_3V3] = - pdu1HkTableDataset.outEnabledSUSNominal.value; - switchStates[Switches::PDU1_CH5_SOLAR_CELL_EXP_5V] = - pdu1HkTableDataset.outEnabledSolarCellExp.value; - switchStates[Switches::PDU1_CH6_PLOC_12V] = pdu1HkTableDataset.outEnabledPLOC.value; - switchStates[Switches::PDU1_CH7_ACS_A_SIDE_3V3] = - pdu1HkTableDataset.outEnabledAcsBoardSideA.value; - switchStates[Switches::PDU1_CH8_UNOCCUPIED] = pdu1HkTableDataset.outEnabledChannel8.value; + checkAndUpdateSwitch(pdu, Switches::PDU1_CH0_TCS_BOARD_3V3, + pdu1HkTableDataset.outEnabledTCSBoard3V3.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH1_SYRLINKS_12V, + pdu1HkTableDataset.outEnabledSyrlinks.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH2_STAR_TRACKER_5V, + pdu1HkTableDataset.outEnabledStarTracker.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH3_MGT_5V, pdu1HkTableDataset.outEnabledMGT.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH4_SUS_NOMINAL_3V3, + pdu1HkTableDataset.outEnabledSUSNominal.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH5_SOLAR_CELL_EXP_5V, + pdu1HkTableDataset.outEnabledSolarCellExp.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH6_PLOC_12V, pdu1HkTableDataset.outEnabledPLOC.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH7_ACS_A_SIDE_3V3, + pdu1HkTableDataset.outEnabledAcsBoardSideA.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH8_UNOCCUPIED, + pdu1HkTableDataset.outEnabledChannel8.value); + if (firstSwitchInfoPdu1) { + firstSwitchInfoPdu1 = false; + } } else { sif::debug << "PCDUHandler::updatePdu1SwitchStates: Failed to read dataset" << std::endl; } - pdu1HkTableDataset.commit(); } LocalDataPoolManager* PCDUHandler::getHkManagerHandle() { return &poolManager; } @@ -264,11 +259,12 @@ void PCDUHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) const pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } - // That does not really make sense but let's keep it here for completeness reasons.. + // This is a dangerous command. Reject/Igore it for now case pcduSwitches::PDU2_CH0_Q7S: { - memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_Q7S; - pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); - break; + return; + // memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_Q7S; + // pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + // break; } case pcduSwitches::PDU2_CH1_PL_PCDU_BATT_0_14V8: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_PAYLOAD_PCDU_CH1; @@ -347,6 +343,9 @@ void PCDUHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) const if (result != RETURN_OK) { sif::debug << "PCDUHandler::sendSwitchCommand: Failed to send message to PDU Handler" << std::endl; + } else { + // Can't use trigger event because of const function constraint, but this hack seems to work + this->forwardEvent(power::SWITCH_CMD_SENT, parameterValue, switchNr); } } @@ -375,6 +374,7 @@ object_id_t PCDUHandler::getObjectId() const { return SystemObject::getObjectId( ReturnValue_t PCDUHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { + using namespace pcduSwitches; localDataPoolMap.emplace(P60System::PDU2_CURRENT_OUT_Q7S, new PoolEntry({0})); localDataPoolMap.emplace(P60System::PDU2_CURRENT_OUT_PAYLOAD_PCDU_CH1, new PoolEntry({0})); @@ -413,28 +413,34 @@ ReturnValue_t PCDUHandler::initializeLocalDataPool(localpool::DataPool& localDat localDataPoolMap.emplace(P60System::PDU2_CONV_EN_3, new PoolEntry({0})); localDataPoolMap.emplace(P60System::PDU2_OUT_EN_Q7S, - new PoolEntry({pcduSwitches::INIT_STATE_Q7S})); - localDataPoolMap.emplace(P60System::PDU2_OUT_EN_PAYLOAD_PCDU_CH1, - new PoolEntry({pcduSwitches::INIT_STATE_PAYLOAD_PCDU_CH1})); + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH0_Q7S]})); + localDataPoolMap.emplace( + P60System::PDU2_OUT_EN_PAYLOAD_PCDU_CH1, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH1_PL_PCDU_BATT_0_14V8]})); localDataPoolMap.emplace(P60System::PDU2_OUT_EN_RW, - new PoolEntry({pcduSwitches::INIT_STATE_RW})); + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH2_RW_5V]})); #if BOARD_TE0720 == 1 localDataPoolMap.emplace(P60System::PDU2_OUT_EN_TCS_BOARD_HEATER_IN, new PoolEntry({1})); #else localDataPoolMap.emplace( P60System::PDU2_OUT_EN_TCS_BOARD_HEATER_IN, - new PoolEntry({pcduSwitches::INIT_STATE_TCS_BOARD_8V_HEATER_IN})); + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V]})); #endif - localDataPoolMap.emplace(P60System::PDU2_OUT_EN_SUS_REDUNDANT, - new PoolEntry({pcduSwitches::INIT_STATE_SUS_REDUNDANT})); - localDataPoolMap.emplace(P60System::PDU2_OUT_EN_DEPLOYMENT_MECHANISM, - new PoolEntry({pcduSwitches::INIT_STATE_DEPLOYMENT_MECHANISM})); - localDataPoolMap.emplace(P60System::PDU2_OUT_EN_PAYLOAD_PCDU_CH6, - new PoolEntry({pcduSwitches::INIT_STATE_PAYLOAD_PCDU_CH6})); - localDataPoolMap.emplace(P60System::PDU2_OUT_EN_ACS_BOARD_SIDE_B, - new PoolEntry({pcduSwitches::INIT_STATE_ACS_BOARD_SIDE_B})); - localDataPoolMap.emplace(P60System::PDU2_OUT_EN_PAYLOAD_CAMERA, - new PoolEntry({pcduSwitches::INIT_STATE_PAYLOAD_CAMERA})); + localDataPoolMap.emplace( + P60System::PDU2_OUT_EN_SUS_REDUNDANT, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH4_SUS_REDUNDANT_3V3]})); + localDataPoolMap.emplace( + P60System::PDU2_OUT_EN_DEPLOYMENT_MECHANISM, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V]})); + localDataPoolMap.emplace( + P60System::PDU2_OUT_EN_PAYLOAD_PCDU_CH6, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH6_PL_PCDU_BATT_1_14V8]})); + localDataPoolMap.emplace( + P60System::PDU2_OUT_EN_ACS_BOARD_SIDE_B, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH7_ACS_BOARD_SIDE_B_3V3]})); + localDataPoolMap.emplace( + P60System::PDU2_OUT_EN_PAYLOAD_CAMERA, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH8_PAYLOAD_CAMERA]})); localDataPoolMap.emplace(P60System::PDU2_BOOTCAUSE, new PoolEntry({0})); localDataPoolMap.emplace(P60System::PDU2_BOOTCNT, new PoolEntry({0})); @@ -496,16 +502,32 @@ ReturnValue_t PCDUHandler::initializeLocalDataPool(localpool::DataPool& localDat new PoolEntry({0})); localDataPoolMap.emplace(P60System::PDU1_CURRENT_OUT_CHANNEL8, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_TCS_BOARD_3V3, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_SYRLINKS, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_STAR_TRACKER, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_MGT, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_SUS_NOMINAL, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_SOLAR_CELL_EXP, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_PLOC, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_ACS_BOARD_SIDE_A, - new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_CHANNEL8, new PoolEntry({0})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_TCS_BOARD_3V3, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH0_TCS_BOARD_3V3]})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_SYRLINKS, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH1_SYRLINKS_12V]})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_STAR_TRACKER, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH2_STAR_TRACKER_5V]})); + localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_MGT, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH3_MGT_5V]})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_SUS_NOMINAL, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH4_SUS_NOMINAL_3V3]})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_SOLAR_CELL_EXP, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH5_SOLAR_CELL_EXP_5V]})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_PLOC, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH6_PLOC_12V]})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_ACS_BOARD_SIDE_A, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH7_ACS_A_SIDE_3V3]})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_CHANNEL8, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH8_UNOCCUPIED]})); localDataPoolMap.emplace(P60System::PDU1_VCC, new PoolEntry({0})); localDataPoolMap.emplace(P60System::PDU1_VBAT, new PoolEntry({0})); @@ -595,3 +617,27 @@ LocalPoolDataSetBase* PCDUHandler::getDataSetHandle(sid_t sid) { return nullptr; } } + +void PCDUHandler::checkAndUpdateSwitch(GOMSPACE::Pdu pdu, pcduSwitches::Switches switchIdx, + uint8_t setValue) { + using namespace pcduSwitches; + if (switchStates[switchIdx] != setValue) { +#if OBSW_INITIALIZE_SWITCHES == 1 + // This code initializes the switches to the default init switch states on every reboot. + // This is not done by the PCDU unless it is power-cycled. + if (((pdu == GOMSPACE::Pdu::PDU1) and firstSwitchInfoPdu1) or + ((pdu == GOMSPACE::Pdu::PDU2) and firstSwitchInfoPdu2)) { + ReturnValue_t state = PowerSwitchIF::SWITCH_OFF; + if (INIT_SWITCH_STATES[switchIdx] == ON) { + state = PowerSwitchIF::SWITCH_ON; + } + sendSwitchCommand(switchIdx, state); + } else { + triggerEvent(power::SWITCH_HAS_CHANGED, setValue, switchIdx); + } +#else + triggerEvent(power::SWITCH_HAS_CHANGED, setValue, switchIdx); +#endif + } + switchStates[switchIdx] = setValue; +} diff --git a/mission/devices/PCDUHandler.h b/mission/devices/PCDUHandler.h index 126f486a..3d014205 100644 --- a/mission/devices/PCDUHandler.h +++ b/mission/devices/PCDUHandler.h @@ -8,13 +8,16 @@ #include #include #include -#include + +#include "devicedefinitions/GomspaceDefinitions.h" +#include "devicedefinitions/powerDefinitions.h" /** * @brief The PCDUHandler provides a compact interface to handle all devices related to the - * control of power. This is necessary because the fsfw manages all power - * related functionalities via one power object. This includes for example the switch on and off of - * devices. + * control of power. + * @details + * This is necessary because the FSFW manages all power related functionalities via one + * power object. This includes for example switching on and off of devices. */ class PCDUHandler : public PowerSwitchIF, public HasLocalDataPoolIF, @@ -27,7 +30,8 @@ class PCDUHandler : public PowerSwitchIF, virtual ReturnValue_t initialize() override; virtual ReturnValue_t performOperation(uint8_t counter) override; virtual void handleChangedDataset(sid_t sid, - store_address_t storeId = storeId::INVALID_STORE_ADDRESS); + store_address_t storeId = storeId::INVALID_STORE_ADDRESS, + bool* clearMessage = nullptr) override; virtual void sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) const override; virtual void sendFuseOnCommand(uint8_t fuseNr) const override; @@ -80,6 +84,8 @@ class PCDUHandler : public PowerSwitchIF, MessageQueueIF* commandQueue = nullptr; size_t cmdQueueSize; + bool firstSwitchInfoPdu1 = true; + bool firstSwitchInfoPdu2 = true; PeriodicTaskIF* executingTask = nullptr; @@ -113,6 +119,7 @@ class PCDUHandler : public PowerSwitchIF, */ void updateHkTableDataset(store_address_t storeId, LocalPoolDataSetBase* dataset, CCSDSTime::CDS_short* datasetTimeStamp); + void checkAndUpdateSwitch(GOMSPACE::Pdu pdu, pcduSwitches::Switches switchIdx, uint8_t setValue); }; #endif /* MISSION_DEVICES_PCDUHANDLER_H_ */ diff --git a/mission/devices/devicedefinitions/powerDefinitions.h b/mission/devices/devicedefinitions/powerDefinitions.h new file mode 100644 index 00000000..746bda34 --- /dev/null +++ b/mission/devices/devicedefinitions/powerDefinitions.h @@ -0,0 +1,20 @@ +#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_POWERDEFINITIONS_H_ +#define MISSION_DEVICES_DEVICEDEFINITIONS_POWERDEFINITIONS_H_ + +#include +#include + +namespace power { + +static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_HANDLER; +//! [EXPORT] : [COMMENT] Indicates that a FSFW object requested setting a switch +//! P1: 1 if on was requested, 0 for off | P2: Switch Index +static constexpr Event SWITCH_CMD_SENT = event::makeEvent(SUBSYSTEM_ID, 0, severity::INFO); +//! [EXPORT] : [COMMENT] Indicated that a swithc state has changed +//! P1: New switch state, 1 for on, 0 for off | P2: Switch Index +static constexpr Event SWITCH_HAS_CHANGED = event::makeEvent(SUBSYSTEM_ID, 1, severity::INFO); +static constexpr Event SWITCHING_Q7S_DENIED = event::makeEvent(SUBSYSTEM_ID, 2, severity::MEDIUM); + +} // namespace power + +#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_POWERDEFINITIONS_H_ */ diff --git a/mission/system/AcsBoardAssembly.cpp b/mission/system/AcsBoardAssembly.cpp index 7cecf66b..286bb106 100644 --- a/mission/system/AcsBoardAssembly.cpp +++ b/mission/system/AcsBoardAssembly.cpp @@ -6,7 +6,10 @@ AcsBoardAssembly::AcsBoardAssembly(object_id_t objectId, object_id_t parentId, PowerSwitchIF* switcher, AcsBoardHelper helper, GpioIF* gpioIF) - : AssemblyBase(objectId, parentId), pwrSwitcher(switcher), helper(helper), gpioIF(gpioIF) { + : AssemblyBase(objectId, parentId), + pwrStateMachine(SWITCH_A, SWITCH_B, switcher), + helper(helper), + gpioIF(gpioIF) { if (switcher == nullptr) { sif::error << "AcsBoardAssembly::AcsBoardAssembly: Invalid Power Switcher " "IF passed" @@ -27,14 +30,43 @@ AcsBoardAssembly::AcsBoardAssembly(object_id_t objectId, object_id_t parentId, initModeTableEntry(helper.gpsId, entry); } +void AcsBoardAssembly::performChildOperation() { + using namespace duallane; + if (pwrStateMachine.active()) { + pwrStateMachineWrapper(); + // This state is the indicator that the power state machine is done + } + if (not pwrStateMachine.active()) { + AssemblyBase::performChildOperation(); + } +} + +void AcsBoardAssembly::startTransition(Mode_t mode, Submode_t submode) { + using namespace duallane; + pwrStateMachine.reset(); + // If anything other than MODE_OFF is commanded, perform power state machine first + if (mode != MODE_OFF) { + // Cache the target modes, required by power state machine + pwrStateMachine.start(mode, submode); + // Cache these for later after the power state machine has finished + targetMode = mode; + targetSubmode = submode; + // Perform power state machine first, then start mode transition. The power state machine will + // start the transition after it has finished + pwrStateMachineWrapper(); + } else { + // Command the devices to off first before switching off the power. The handleModeReached + // custom implementation will take care of starting the power state machine. + AssemblyBase::startTransition(mode, submode); + } +} + ReturnValue_t AcsBoardAssembly::commandChildren(Mode_t mode, Submode_t submode) { + using namespace duallane; ReturnValue_t result = RETURN_OK; refreshHelperModes(); - powerStateMachine(mode, submode); if (mode == DeviceHandlerIF::MODE_NORMAL or mode == MODE_ON) { - if (state == States::MODE_COMMANDING) { - handleNormalOrOnModeCmd(mode, submode); - } + result = handleNormalOrOnModeCmd(mode, submode); } else { modeTable[ModeTableIdx::GYRO_0_A].setMode(MODE_OFF); modeTable[ModeTableIdx::GYRO_0_A].setSubmode(SUBMODE_NONE); @@ -55,36 +87,39 @@ ReturnValue_t AcsBoardAssembly::commandChildren(Mode_t mode, Submode_t submode) modeTable[ModeTableIdx::GPS].setMode(MODE_OFF); modeTable[ModeTableIdx::GPS].setSubmode(SUBMODE_NONE); } - HybridIterator tableIter(modeTable.begin(), modeTable.end()); executeTable(tableIter); return result; } ReturnValue_t AcsBoardAssembly::checkChildrenStateOn(Mode_t wantedMode, Submode_t wantedSubmode) { + using namespace duallane; refreshHelperModes(); - if (submode == A_SIDE) { + // if (state == PwrStates::SWITCHING_POWER) { + // // Wrong mode + // sif::error << "Wrong mode, currently switching power" << std::endl; + // return RETURN_OK; + // } + if (wantedSubmode == A_SIDE) { if ((helper.gyro0SideAMode != wantedMode and helper.gyro1SideAMode != wantedMode) or (helper.mgm0SideAMode != wantedMode and helper.mgm1SideAMode != wantedMode) or - helper.gpsMode != wantedMode) { - submode = B_SIDE; + helper.gpsMode != MODE_ON) { return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE; } return RETURN_OK; - } else if (submode == B_SIDE) { + } else if (wantedSubmode == B_SIDE) { if ((helper.gyro2SideBMode != wantedMode and helper.gyro3SideBMode != wantedMode) or (helper.mgm2SideBMode != wantedMode and helper.mgm3SideBMode != wantedMode) or - helper.gpsMode != wantedMode) { - submode = DUAL_MODE; + helper.gpsMode != MODE_ON) { return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE; } return RETURN_OK; - } else if (submode == DUAL_MODE) { + } else if (wantedSubmode == DUAL_MODE) { if ((helper.gyro0SideAMode != wantedMode and helper.gyro1SideAMode != wantedMode and helper.gyro2AdisIdSideB != wantedMode and helper.gyro3SideBMode != wantedMode) or (helper.mgm0SideAMode != wantedMode and helper.mgm1SideAMode != wantedMode and helper.mgm2SideBMode != wantedMode and helper.mgm3SideBMode != wantedMode) or - helper.gpsMode != wantedMode) { + helper.gpsMode != MODE_ON) { // Trigger event, but don't start any other transitions. This is the last fallback mode. if (dualModeErrorSwitch) { triggerEvent(NOT_ENOUGH_DEVICES_DUAL_MODE, 0, 0); @@ -98,35 +133,41 @@ ReturnValue_t AcsBoardAssembly::checkChildrenStateOn(Mode_t wantedMode, Submode_ } ReturnValue_t AcsBoardAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode) { + using namespace duallane; ReturnValue_t result = RETURN_OK; auto cmdSeq = [&](object_id_t objectId, Mode_t devMode, ModeTableIdx tableIdx) { if (mode == DeviceHandlerIF::MODE_NORMAL) { if (isUseable(objectId, devMode)) { - if (mode != MODE_OFF) { - modeTable[tableIdx].setMode(devMode); + if (devMode == MODE_ON) { + modeTable[tableIdx].setMode(mode); modeTable[tableIdx].setSubmode(SUBMODE_NONE); + } else { - result = NEED_SECOND_STEP; modeTable[tableIdx].setMode(MODE_ON); modeTable[tableIdx].setSubmode(SUBMODE_NONE); } } - } else if (devMode == MODE_ON) { + } else if (mode == MODE_ON) { if (isUseable(objectId, devMode)) { modeTable[tableIdx].setMode(MODE_ON); modeTable[tableIdx].setSubmode(SUBMODE_NONE); } } }; - switch (this->submode) { + if (this->mode == MODE_OFF and mode == DeviceHandlerIF::MODE_NORMAL) { + if (internalState != STATE_SECOND_STEP) { + result = NEED_SECOND_STEP; + } + } + switch (submode) { case (A_SIDE): { cmdSeq(helper.gyro0AdisIdSideA, helper.gyro0SideAMode, ModeTableIdx::GYRO_0_A); cmdSeq(helper.gyro1L3gIdSideA, helper.gyro1SideAMode, ModeTableIdx::GYRO_1_A); cmdSeq(helper.mgm0Lis3IdSideA, helper.mgm0SideAMode, ModeTableIdx::MGM_0_A); cmdSeq(helper.mgm1Rm3100IdSideA, helper.mgm1SideAMode, ModeTableIdx::MGM_1_A); - cmdSeq(helper.gpsId, helper.gpsMode, ModeTableIdx::GPS); - ReturnValue_t result = gpioIF->pullLow(gpioIds::GNSS_SELECT); - if (result != HasReturnvaluesIF::RETURN_OK) { + modeTable[ModeTableIdx::GPS].setMode(MODE_ON); + modeTable[ModeTableIdx::GPS].setSubmode(SUBMODE_NONE); + if (gpioIF->pullLow(gpioIds::GNSS_SELECT) != HasReturnvaluesIF::RETURN_OK) { #if OBSW_VERBOSE_LEVEL >= 1 sif::error << "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull GNSS select low" << std::endl; @@ -148,8 +189,7 @@ ReturnValue_t AcsBoardAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t s cmdSeq(helper.mgm2Lis3IdSideB, helper.mgm2SideBMode, ModeTableIdx::MGM_2_B); cmdSeq(helper.mgm3Rm3100IdSideB, helper.mgm3SideBMode, ModeTableIdx::MGM_3_B); cmdSeq(helper.gpsId, helper.gpsMode, ModeTableIdx::GPS); - gpioIF->pullHigh(gpioIds::GNSS_SELECT); - if (result != HasReturnvaluesIF::RETURN_OK) { + if (gpioIF->pullHigh(gpioIds::GNSS_SELECT) != HasReturnvaluesIF::RETURN_OK) { #if OBSW_VERBOSE_LEVEL >= 1 sif::error << "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull GNSS select high" << std::endl; @@ -175,12 +215,13 @@ ReturnValue_t AcsBoardAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t s cmdSeq(helper.gyro3L3gIdSideB, helper.gyro3SideBMode, ModeTableIdx::GYRO_3_B); cmdSeq(helper.mgm2Lis3IdSideB, helper.mgm2SideBMode, ModeTableIdx::MGM_2_B); cmdSeq(helper.mgm3Rm3100IdSideB, helper.mgm3SideBMode, ModeTableIdx::MGM_3_B); + ReturnValue_t status = RETURN_OK; if (defaultSubmode == Submodes::A_SIDE) { - result = gpioIF->pullLow(gpioIds::GNSS_SELECT); + status = gpioIF->pullLow(gpioIds::GNSS_SELECT); } else { - result = gpioIF->pullHigh(gpioIds::GNSS_SELECT); + status = gpioIF->pullHigh(gpioIds::GNSS_SELECT); } - if (result != HasReturnvaluesIF::RETURN_OK) { + if (status != HasReturnvaluesIF::RETURN_OK) { #if OBSW_VERBOSE_LEVEL >= 1 sif::error << "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull GNSS select to" "default side for dual mode" @@ -196,90 +237,165 @@ ReturnValue_t AcsBoardAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t s return result; } -void AcsBoardAssembly::powerStateMachine(Mode_t mode, Submode_t submode) { - ReturnValue_t switchStateA = RETURN_OK; - ReturnValue_t switchStateB = RETURN_OK; - if (state == States::IDLE or state == States::SWITCHING_POWER) { - switchStateA = pwrSwitcher->getSwitchState(SWITCH_A); - switchStateB = pwrSwitcher->getSwitchState(SWITCH_B); +ReturnValue_t AcsBoardAssembly::isModeCombinationValid(Mode_t mode, Submode_t submode) { + using namespace duallane; + if (submode != A_SIDE and submode != B_SIDE and submode != DUAL_MODE) { + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + +bool AcsBoardAssembly::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; +} + +void AcsBoardAssembly::handleModeReached() { + using namespace duallane; + if (targetMode == MODE_OFF) { + pwrStateMachine.start(targetMode, targetSubmode); + // Now we can switch off the power. After that, the AssemblyBase::handleModeReached function + // will be called + pwrStateMachineWrapper(); } else { + finishModeOp(); + } +} + +void AcsBoardAssembly::handleChildrenLostMode(ReturnValue_t result) { + using namespace duallane; + // Some ACS board components are required for Safe-Mode. It would be good if the software + // transitions from A side to B side and from B side to dual mode autonomously + // to ensure that that enough sensors are available without an operators intervention. + // Therefore, the lost mode handler was overwritten to start these transitions + Submode_t nextSubmode = Submodes::A_SIDE; + if (submode == Submodes::A_SIDE) { + nextSubmode = Submodes::B_SIDE; + } + if (not tryingOtherSide) { + triggerEvent(CANT_KEEP_MODE, mode, submode); + startTransition(mode, nextSubmode); + tryingOtherSide = true; + } else { + // Not sure when this would happen. This flag is reset if the mode was reached. If it + // was not reached, the transition failure handler should be called. + sif::error << "AcsBoardAssembly::handleChildrenLostMode: Wrong handler called" << std::endl; + triggerEvent(TRANSITION_OTHER_SIDE_FAILED, mode, targetSubmode); + startTransition(mode, Submodes::DUAL_MODE); + } +} + +void AcsBoardAssembly::handleModeTransitionFailed(ReturnValue_t result) { + using namespace duallane; + Submode_t nextSubmode = Submodes::A_SIDE; + if (submode == Submodes::A_SIDE) { + nextSubmode = Submodes::B_SIDE; + } + // Check whether the transition was started because the mode could not be kept (not commanded). + // If this is not the case, start transition to other side. If it is the case, start + // transition to dual mode. + if (not tryingOtherSide) { + triggerEvent(CANT_KEEP_MODE, mode, submode); + startTransition(mode, nextSubmode); + tryingOtherSide = true; + } else { + triggerEvent(TRANSITION_OTHER_SIDE_FAILED, mode, targetSubmode); + startTransition(mode, Submodes::DUAL_MODE); + } +} + +void AcsBoardAssembly::setPreferredSide(duallane::Submodes submode) { + using namespace duallane; + if (submode != Submodes::A_SIDE and submode != Submodes::B_SIDE) { return; } - if (mode == MODE_OFF) { - if (switchStateA == PowerSwitchIF::SWITCH_OFF and switchStateB == PowerSwitchIF::SWITCH_OFF) { - state = States::MODE_COMMANDING; - return; - } + this->defaultSubmode = submode; +} + +void AcsBoardAssembly::selectGpsInDualMode(duallane::Submodes side) { + using namespace duallane; + if (submode != Submodes::DUAL_MODE) { + return; + } + ReturnValue_t result = RETURN_OK; + if (side == Submodes::A_SIDE) { + result = gpioIF->pullLow(gpioIds::GNSS_SELECT); } else { - switch (this->submode) { - case (A_SIDE): { - if (switchStateA == PowerSwitchIF::SWITCH_ON and - switchStateB == PowerSwitchIF::SWITCH_OFF) { - state = States::MODE_COMMANDING; - return; - } - break; - } - case (B_SIDE): { - if (switchStateA == PowerSwitchIF::SWITCH_OFF and - switchStateB == PowerSwitchIF::SWITCH_ON) { - state = States::MODE_COMMANDING; - return; - } - break; - } - case (DUAL_MODE): { - if (switchStateA == PowerSwitchIF::SWITCH_ON and switchStateB == PowerSwitchIF::SWITCH_ON) { - state = States::MODE_COMMANDING; - return; - } - } - } + result = gpioIF->pullHigh(gpioIds::GNSS_SELECT); } - if (state == States::IDLE) { - if (mode == MODE_OFF) { - if (switchStateA != PowerSwitchIF::SWITCH_OFF) { - pwrSwitcher->sendSwitchCommand(SWITCH_A, false); - } - if (switchStateB != PowerSwitchIF::SWITCH_OFF) { - pwrSwitcher->sendSwitchCommand(SWITCH_B, false); - } + if (result != HasReturnvaluesIF::RETURN_OK) { +#if OBSW_VERBOSE_LEVEL >= 1 + sif::error << "AcsBoardAssembly::switchGpsInDualMode: Switching GPS failed" << std::endl; +#endif + } +} + +void AcsBoardAssembly::refreshHelperModes() { + try { + helper.gyro0SideAMode = childrenMap.at(helper.gyro0AdisIdSideA).mode; + helper.gyro1SideAMode = childrenMap.at(helper.gyro1L3gIdSideA).mode; + helper.gyro2SideBMode = childrenMap.at(helper.gyro2AdisIdSideB).mode; + helper.gyro3SideBMode = childrenMap.at(helper.gyro2AdisIdSideB).mode; + helper.mgm0SideAMode = childrenMap.at(helper.mgm0Lis3IdSideA).mode; + helper.mgm1SideAMode = childrenMap.at(helper.mgm1Rm3100IdSideA).mode; + helper.mgm2SideBMode = childrenMap.at(helper.mgm2Lis3IdSideB).mode; + helper.mgm3SideBMode = childrenMap.at(helper.mgm3Rm3100IdSideB).mode; + helper.gpsMode = childrenMap.at(helper.gpsId).mode; + } catch (const std::out_of_range& e) { + sif::error << "AcsBoardAssembly::refreshHelperModes: Invalid map: " << e.what() << std::endl; + } +} + +void AcsBoardAssembly::initModeTableEntry(object_id_t id, ModeListEntry& entry) { + entry.setObject(id); + entry.setMode(MODE_OFF); + entry.setSubmode(SUBMODE_NONE); + entry.setInheritSubmode(false); + modeTable.insert(entry); +} + +void AcsBoardAssembly::finishModeOp() { + using namespace duallane; + AssemblyBase::handleModeReached(); + pwrStateMachine.reset(); + powerRetryCounter = 0; + tryingOtherSide = false; + dualModeErrorSwitch = true; +} + +ReturnValue_t AcsBoardAssembly::pwrStateMachineWrapper() { + using namespace duallane; + OpCodes opCode = pwrStateMachine.powerStateMachine(); + if (opCode == OpCodes::NONE) { + return RETURN_OK; + } else if (opCode == OpCodes::FINISH_OP) { + finishModeOp(); + } else if (opCode == OpCodes::START_TRANSITION) { + AssemblyBase::startTransition(targetMode, targetSubmode); + } else if (opCode == OpCodes::TIMEOUT_OCCURED) { + if (powerRetryCounter == 0) { + powerRetryCounter++; + pwrStateMachine.reset(); } else { - switch (submode) { - case (A_SIDE): { - if (switchStateA != PowerSwitchIF::SWITCH_ON) { - pwrSwitcher->sendSwitchCommand(SWITCH_A, true); - } - if (switchStateB != PowerSwitchIF::SWITCH_OFF) { - pwrSwitcher->sendSwitchCommand(SWITCH_B, false); - } - break; - } - case (B_SIDE): { - if (switchStateA != PowerSwitchIF::SWITCH_OFF) { - pwrSwitcher->sendSwitchCommand(SWITCH_A, false); - } - if (switchStateB != PowerSwitchIF::SWITCH_ON) { - pwrSwitcher->sendSwitchCommand(SWITCH_B, true); - } - break; - } - case (DUAL_MODE): { - if (switchStateA != PowerSwitchIF::SWITCH_ON) { - pwrSwitcher->sendSwitchCommand(SWITCH_A, true); - } - if (switchStateB != PowerSwitchIF::SWITCH_ON) { - pwrSwitcher->sendSwitchCommand(SWITCH_B, true); - } - break; - } - } +#if OBSW_VERBOSE_LEVEL >= 1 + sif::warning << "Timeout occured in power state machine" << std::endl; +#endif + triggerEvent(POWER_STATE_MACHINE_TIMEOUT, 0, 0); + return RETURN_FAILED; } - state = States::SWITCHING_POWER; - } - if (state == States::SWITCHING_POWER) { - // TODO: Could check for a timeout (temporal or cycles) here and resend command } + return RETURN_OK; } ReturnValue_t AcsBoardAssembly::initialize() { @@ -315,118 +431,9 @@ ReturnValue_t AcsBoardAssembly::initialize() { if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - return result; -} - -ReturnValue_t AcsBoardAssembly::isModeCombinationValid(Mode_t mode, Submode_t submode) { - if (submode != A_SIDE and submode != B_SIDE and submode != DUAL_MODE) { - return HasReturnvaluesIF::RETURN_FAILED; - } - return HasReturnvaluesIF::RETURN_OK; -} - -bool AcsBoardAssembly::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; -} - -void AcsBoardAssembly::handleModeReached() { - AssemblyBase::handleModeReached(); - state = States::IDLE; - tryingOtherSide = false; - dualModeErrorSwitch = true; -} - -void AcsBoardAssembly::handleChildrenLostMode(ReturnValue_t result) { - // Some ACS board components are required for Safe-Mode. It would be good if the software - // transitions from A side to B side and from B side to dual mode autonomously - // to ensure that that enough sensors are available without an operators intervention. - // Therefore, the lost mode handler was overwritten to start these transitions - Submode_t nextSubmode = Submodes::A_SIDE; - if (submode == Submodes::A_SIDE) { - nextSubmode = Submodes::B_SIDE; - } - if (not tryingOtherSide) { - triggerEvent(CANT_KEEP_MODE, mode, submode); - startTransition(mode, nextSubmode); - tryingOtherSide = true; - } else { - // Not sure when this would happen. This flag is reset if the mode was reached. If it - // was not reached, the transition failure handler should be called. - sif::error << "AcsBoardAssembly::handleChildrenLostMode: Wrong handler called" << std::endl; - triggerEvent(TRANSITION_OTHER_SIDE_FAILED, mode, targetSubmode); - startTransition(mode, Submodes::DUAL_MODE); - } -} - -void AcsBoardAssembly::handleModeTransitionFailed(ReturnValue_t result) { - Submode_t nextSubmode = Submodes::A_SIDE; - if (submode == Submodes::A_SIDE) { - nextSubmode = Submodes::B_SIDE; - } - // Check whether the transition was started because the mode could not be kept (not commanded). - // If this is not the case, start transition to other side. If it is the case, start - // transition to dual mode. - if (not tryingOtherSide) { - triggerEvent(CANT_KEEP_MODE, mode, submode); - startTransition(mode, nextSubmode); - tryingOtherSide = true; - } else { - triggerEvent(TRANSITION_OTHER_SIDE_FAILED, mode, targetSubmode); - startTransition(mode, Submodes::DUAL_MODE); - } -} - -void AcsBoardAssembly::setPreferredSide(Submodes submode) { - if (submode != Submodes::A_SIDE and submode != Submodes::B_SIDE) { - return; - } - this->defaultSubmode = submode; -} - -void AcsBoardAssembly::selectGpsInDualMode(Submodes side) { - if (submode != Submodes::DUAL_MODE) { - return; - } - ReturnValue_t result = RETURN_OK; - if (side == Submodes::A_SIDE) { - result = gpioIF->pullLow(gpioIds::GNSS_SELECT); - } else { - result = gpioIF->pullHigh(gpioIds::GNSS_SELECT); - } + result = registerChild(helper.gpsId); if (result != HasReturnvaluesIF::RETURN_OK) { -#if OBSW_VERBOSE_LEVEL >= 1 - sif::error << "AcsBoardAssembly::switchGpsInDualMode: Switching GPS failed" << std::endl; -#endif + return result; } -} - -void AcsBoardAssembly::refreshHelperModes() { - helper.gyro0SideAMode = childrenMap[helper.gyro0AdisIdSideA].mode; - helper.gyro1SideAMode = childrenMap[helper.gyro1L3gIdSideA].mode; - helper.gyro2SideBMode = childrenMap[helper.gyro2AdisIdSideB].mode; - helper.gyro3SideBMode = childrenMap[helper.gyro2AdisIdSideB].mode; - helper.mgm0SideAMode = childrenMap[helper.mgm0Lis3IdSideA].mode; - helper.mgm1SideAMode = childrenMap[helper.mgm1Rm3100IdSideA].mode; - helper.mgm2SideBMode = childrenMap[helper.mgm2Lis3IdSideB].mode; - helper.mgm3SideBMode = childrenMap[helper.mgm3Rm3100IdSideB].mode; -} - -void AcsBoardAssembly::initModeTableEntry(object_id_t id, ModeListEntry& entry) { - entry.setObject(id); - entry.setMode(MODE_OFF); - entry.setSubmode(SUBMODE_NONE); - entry.setInheritSubmode(false); - modeTable.insert(entry); + return AssemblyBase::initialize(); } diff --git a/mission/system/AcsBoardAssembly.h b/mission/system/AcsBoardAssembly.h index 37da581e..7f2a85fa 100644 --- a/mission/system/AcsBoardAssembly.h +++ b/mission/system/AcsBoardAssembly.h @@ -6,6 +6,8 @@ #include #include +#include "DualLanePowerStateMachine.h" + struct AcsBoardHelper { AcsBoardHelper(object_id_t mgm0Id, object_id_t mgm1Id, object_id_t mgm2Id, object_id_t mgm3Id, object_id_t gyro0Id, object_id_t gyro1Id, object_id_t gyro2Id, object_id_t gyro3Id, @@ -17,7 +19,8 @@ struct AcsBoardHelper { gyro0AdisIdSideA(gyro0Id), gyro1L3gIdSideA(gyro1Id), gyro2AdisIdSideB(gyro2Id), - gyro3L3gIdSideB(gyro3Id) {} + gyro3L3gIdSideB(gyro3Id), + gpsId(gpsId) {} object_id_t mgm0Lis3IdSideA = objects::NO_OBJECT; object_id_t mgm1Rm3100IdSideA = objects::NO_OBJECT; @@ -57,6 +60,17 @@ enum ModeTableIdx : uint8_t { class PowerSwitchIF; class GpioIF; +/** + * @brief Assembly class which manages redundant ACS board sides + * @details + * This class takes care of ensuring that enough devices on the ACS board are available at all + * times. It does so by doing autonomous transitions to the redundant side or activating both sides + * if not enough devices are available. + * + * This class also takes care of switching on the A side and/or B side power lanes. Normally, + * doing this task would be performed by the device handlers, but this is not possible for the + * ACS board where multiple sensors share the same power supply. + */ class AcsBoardAssembly : public AssemblyBase { public: static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::ACS_BOARD_ASS; @@ -64,21 +78,22 @@ class AcsBoardAssembly : public AssemblyBase { event::makeEvent(SUBSYSTEM_ID, 0, severity::HIGH); static constexpr Event NOT_ENOUGH_DEVICES_DUAL_MODE = event::makeEvent(SUBSYSTEM_ID, 1, severity::HIGH); - static constexpr uint8_t NUMBER_DEVICES_MODE_TABLE = 9; + static constexpr Event POWER_STATE_MACHINE_TIMEOUT = + event::makeEvent(SUBSYSTEM_ID, 2, severity::MEDIUM); - enum Submodes : Submode_t { A_SIDE = 0, B_SIDE = 1, DUAL_MODE = 2 }; + static constexpr uint8_t NUMBER_DEVICES_MODE_TABLE = 9; AcsBoardAssembly(object_id_t objectId, object_id_t parentId, PowerSwitchIF* pwrSwitcher, AcsBoardHelper helper, GpioIF* gpioIF); - void setPreferredSide(Submodes submode); + void setPreferredSide(duallane::Submodes submode); /** * In dual mode, the A side or the B side GPS device can be used, but not both. * This function can be used to switch the used GPS device. * @param side */ - void selectGpsInDualMode(Submodes side); + void selectGpsInDualMode(duallane::Submodes side); private: static constexpr pcduSwitches::Switches SWITCH_A = @@ -86,13 +101,14 @@ class AcsBoardAssembly : public AssemblyBase { static constexpr pcduSwitches::Switches SWITCH_B = pcduSwitches::Switches::PDU2_CH7_ACS_BOARD_SIDE_B_3V3; - enum class States { IDLE, SWITCHING_POWER, MODE_COMMANDING } state = States::IDLE; - - PowerSwitchIF* pwrSwitcher = nullptr; + // This helper object complete encapsulates power switching + DualLanePowerStateMachine pwrStateMachine; bool tryingOtherSide = false; AcsBoardHelper helper; GpioIF* gpioIF = nullptr; - Submodes defaultSubmode = Submodes::A_SIDE; + uint8_t powerRetryCounter = 0; + // duallane::PwrStates state = duallane::PwrStates::IDLE; + duallane::Submodes defaultSubmode = duallane::Submodes::A_SIDE; bool dualModeErrorSwitch = true; FixedArrayList modeTable; @@ -102,6 +118,8 @@ class AcsBoardAssembly : public AssemblyBase { 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; + void performChildOperation() override; + void startTransition(Mode_t mode, Submode_t submode) override; void handleModeReached() override; void handleModeTransitionFailed(ReturnValue_t result) override; void handleChildrenLostMode(ReturnValue_t result) override; @@ -114,9 +132,16 @@ class AcsBoardAssembly : public AssemblyBase { */ bool isUseable(object_id_t object, Mode_t mode); ReturnValue_t handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode); - void powerStateMachine(Mode_t mode, Submode_t submode); void initModeTableEntry(object_id_t id, ModeListEntry& entry); void refreshHelperModes(); + void finishModeOp(); + /** + * Thin wrapper function which is required because the helper class + * can not access protected member functions. + * @param mode + * @param submode + */ + ReturnValue_t pwrStateMachineWrapper(); }; #endif /* MISSION_SYSTEM_ACSBOARDASSEMBLY_H_ */ diff --git a/mission/system/CMakeLists.txt b/mission/system/CMakeLists.txt index 6296de1e..fb8d7096 100644 --- a/mission/system/CMakeLists.txt +++ b/mission/system/CMakeLists.txt @@ -6,4 +6,5 @@ target_sources(${LIB_EIVE_MISSION} PRIVATE EiveSystem.cpp ComSubsystem.cpp TcsSubsystem.cpp + DualLanePowerStateMachine.cpp ) \ No newline at end of file diff --git a/mission/system/DualLanePowerStateMachine.cpp b/mission/system/DualLanePowerStateMachine.cpp new file mode 100644 index 00000000..16465358 --- /dev/null +++ b/mission/system/DualLanePowerStateMachine.cpp @@ -0,0 +1,134 @@ +#include "DualLanePowerStateMachine.h" + +#include +#include + +DualLanePowerStateMachine::DualLanePowerStateMachine(pcduSwitches::Switches switchA, + pcduSwitches::Switches switchB, + PowerSwitchIF* pwrSwitcher, + dur_millis_t checkTimeout) + : SWITCH_A(switchA), SWITCH_B(switchB), pwrSwitcher(pwrSwitcher), checkTimeout(checkTimeout) {} + +void DualLanePowerStateMachine::setCheckTimeout(dur_millis_t timeout) { + checkTimeout.setTimeout(timeout); +} + +void DualLanePowerStateMachine::start(Mode_t mode, Submode_t submode) { + checkTimeout.resetTimer(); + targetMode = mode; + targetSubmode = submode; + state = duallane::PwrStates::SWITCHING_POWER; +} + +duallane::PwrStates DualLanePowerStateMachine::getState() const { return state; } + +bool DualLanePowerStateMachine::active() { + if (state == duallane::PwrStates::IDLE or state == duallane::PwrStates::MODE_COMMANDING) { + return false; + } + return true; +} + +duallane::OpCodes DualLanePowerStateMachine::powerStateMachine() { + using namespace duallane; + ReturnValue_t switchStateA = RETURN_OK; + ReturnValue_t switchStateB = RETURN_OK; + if (state == PwrStates::IDLE or state == PwrStates::MODE_COMMANDING) { + return duallane::OpCodes::NONE; + } + if (state == PwrStates::SWITCHING_POWER or state == PwrStates::CHECKING_POWER) { + switchStateA = pwrSwitcher->getSwitchState(SWITCH_A); + switchStateB = pwrSwitcher->getSwitchState(SWITCH_B); + } else { + return OpCodes::NONE; + } + if (targetMode == HasModesIF::MODE_OFF) { + if (switchStateA == PowerSwitchIF::SWITCH_OFF and switchStateB == PowerSwitchIF::SWITCH_OFF) { + state = PwrStates::IDLE; + return OpCodes::FINISH_OP; + } + } else { + switch (targetSubmode) { + case (A_SIDE): { + if (switchStateA == PowerSwitchIF::SWITCH_ON and + switchStateB == PowerSwitchIF::SWITCH_OFF) { + state = PwrStates::MODE_COMMANDING; + return OpCodes::START_TRANSITION; + } + break; + } + case (B_SIDE): { + if (switchStateA == PowerSwitchIF::SWITCH_OFF and + switchStateB == PowerSwitchIF::SWITCH_ON) { + state = PwrStates::MODE_COMMANDING; + return OpCodes::START_TRANSITION; + } + break; + } + case (DUAL_MODE): { + if (switchStateA == PowerSwitchIF::SWITCH_ON and switchStateB == PowerSwitchIF::SWITCH_ON) { + state = PwrStates::MODE_COMMANDING; + return OpCodes::START_TRANSITION; + } + } + } + } + if (state == PwrStates::SWITCHING_POWER) { + if (targetMode == HasModesIF::MODE_OFF) { + if (switchStateA != PowerSwitchIF::SWITCH_OFF) { + pwrSwitcher->sendSwitchCommand(SWITCH_A, PowerSwitchIF::SWITCH_OFF); + } + if (switchStateB != PowerSwitchIF::SWITCH_OFF) { + pwrSwitcher->sendSwitchCommand(SWITCH_B, PowerSwitchIF::SWITCH_OFF); + } + checkTimeout.resetTimer(); + } else { + switch (targetSubmode) { + case (A_SIDE): { + if (switchStateA != PowerSwitchIF::SWITCH_ON) { + pwrSwitcher->sendSwitchCommand(SWITCH_A, PowerSwitchIF::SWITCH_ON); + } + if (switchStateB != PowerSwitchIF::SWITCH_OFF) { + pwrSwitcher->sendSwitchCommand(SWITCH_B, PowerSwitchIF::SWITCH_OFF); + } + checkTimeout.resetTimer(); + break; + } + case (B_SIDE): { + if (switchStateA != PowerSwitchIF::SWITCH_OFF) { + pwrSwitcher->sendSwitchCommand(SWITCH_A, PowerSwitchIF::SWITCH_OFF); + } + if (switchStateB != PowerSwitchIF::SWITCH_ON) { + pwrSwitcher->sendSwitchCommand(SWITCH_B, PowerSwitchIF::SWITCH_OFF); + } + checkTimeout.resetTimer(); + break; + } + case (DUAL_MODE): { + if (switchStateA != PowerSwitchIF::SWITCH_ON) { + pwrSwitcher->sendSwitchCommand(SWITCH_A, PowerSwitchIF::SWITCH_ON); + } + if (switchStateB != PowerSwitchIF::SWITCH_ON) { + pwrSwitcher->sendSwitchCommand(SWITCH_B, PowerSwitchIF::SWITCH_ON); + } + checkTimeout.resetTimer(); + break; + } + } + } + state = PwrStates::CHECKING_POWER; + } + if (state == PwrStates::CHECKING_POWER) { + if (checkTimeout.hasTimedOut()) { + return OpCodes::TIMEOUT_OCCURED; + } + } + return OpCodes::NONE; +} + +void DualLanePowerStateMachine::reset() { + state = duallane::PwrStates::IDLE; + targetMode = HasModesIF::MODE_OFF; + targetSubmode = 0; + checkTimeout.resetTimer(); +} diff --git a/mission/system/DualLanePowerStateMachine.h b/mission/system/DualLanePowerStateMachine.h new file mode 100644 index 00000000..bb4b3946 --- /dev/null +++ b/mission/system/DualLanePowerStateMachine.h @@ -0,0 +1,33 @@ +#ifndef MISSION_SYSTEM_DUALLANEPOWERSTATEMACHINE_H_ +#define MISSION_SYSTEM_DUALLANEPOWERSTATEMACHINE_H_ + +#include +#include + +#include "definitions.h" + +class AssemblyBase; +class PowerSwitchIF; + +class DualLanePowerStateMachine : public HasReturnvaluesIF { + public: + DualLanePowerStateMachine(pcduSwitches::Switches switchA, pcduSwitches::Switches switchB, + PowerSwitchIF* pwrSwitcher, dur_millis_t checkTimeout = 5000); + void setCheckTimeout(dur_millis_t timeout); + void reset(); + void start(Mode_t mode, Submode_t submode); + bool active(); + duallane::PwrStates getState() const; + duallane::OpCodes powerStateMachine(); + const pcduSwitches::Switches SWITCH_A; + const pcduSwitches::Switches SWITCH_B; + + private: + duallane::PwrStates state = duallane::PwrStates::IDLE; + PowerSwitchIF* pwrSwitcher = nullptr; + Mode_t targetMode = HasModesIF::MODE_OFF; + Submode_t targetSubmode = 0; + Countdown checkTimeout; +}; + +#endif /* MISSION_SYSTEM_DUALLANEPOWERSTATEMACHINE_H_ */ diff --git a/mission/system/definitions.h b/mission/system/definitions.h new file mode 100644 index 00000000..361f9f65 --- /dev/null +++ b/mission/system/definitions.h @@ -0,0 +1,14 @@ +#ifndef MISSION_SYSTEM_DEFINITIONS_H_ +#define MISSION_SYSTEM_DEFINITIONS_H_ + +#include + +namespace duallane { + +enum class PwrStates { IDLE, SWITCHING_POWER, CHECKING_POWER, MODE_COMMANDING }; +enum class OpCodes { NONE, FINISH_OP, START_TRANSITION, TIMEOUT_OCCURED }; +enum Submodes : Submode_t { A_SIDE = 0, B_SIDE = 1, DUAL_MODE = 2 }; + +} // namespace duallane + +#endif /* MISSION_SYSTEM_DEFINITIONS_H_ */ diff --git a/thirdparty/arcsec_star_tracker b/thirdparty/arcsec_star_tracker index b1594df9..93e93965 160000 --- a/thirdparty/arcsec_star_tracker +++ b/thirdparty/arcsec_star_tracker @@ -1 +1 @@ -Subproject commit b1594df9303056456604726592635d8a1c987e75 +Subproject commit 93e93965e2c6405170b62c523dea1990db02d2ad diff --git a/tmtc b/tmtc index e1d43b8d..abe9c8bc 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit e1d43b8de9e2b09493245fdf6c050b8b819eab41 +Subproject commit abe9c8bc000e834b99a2c367ed10f927eeb666b0