diff --git a/.vscode/settings.json b/.vscode/settings.json index ae73470616491339b1b4dd30234db922365b8e12..ad3a4cc6e27d76d6fbb77d88dcc67532033ebcfe 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -186,11 +186,6 @@ "cmake.configureSettings": { "CMAKE_C_COMPILER_LAUNCHER": "ccache", "CMAKE_CXX_COMPILER_LAUNCHER": "ccache" -<<<<<<< HEAD }, "compilerexplorer.compilationDirectory": "${workspaceFolder}/build" } -======= - } -} ->>>>>>> 170759b0 ([vscode] Add cspell words to workspace dictionary) diff --git a/src/boards/Groundstation/Automated/SMController/SMController.cpp b/src/boards/Groundstation/Automated/SMController/SMController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c4966d5d649bff3a2170247ee3e30779fb73ecdc --- /dev/null +++ b/src/boards/Groundstation/Automated/SMController/SMController.cpp @@ -0,0 +1,639 @@ +/* Copyright (c) 2024 Skyward Experimental Rocketry + * Author: Federico Lolli + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "SMController.h" + +#include <common/Events.h> +#include <drivers/timer/TimestampTimer.h> + +#include "SMControllerData.h" + +using namespace Boardcore; +using namespace Common; +using namespace miosix; + +namespace Antennas +{ + +SMController::SMController() : HSM(&SMController::state_config) +{ + EventBroker::getInstance().subscribe(this, TOPIC_ARP); + EventBroker::getInstance().subscribe(this, TOPIC_TMTC); +} + +// Super state +Boardcore::State SMController::state_config(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::CONFIG); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_top); + } + case EV_INIT: + { + return transition(&SMController::state_init); + } + case TMTC_ARP_RESET_BOARD: + { + reboot(); + return HANDLED; + } + default: + { + return UNHANDLED; + } + } +} + +// Super state +Boardcore::State SMController::state_feedback(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::FEEDBACK); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_top); + } + case EV_INIT: + { + return transition(&SMController::state_armed); + } + case TMTC_ARP_DISARM: + { + return transition(&SMController::state_init_done); + } + default: + { + return UNHANDLED; + } + } +} + +// Super state +Boardcore::State SMController::state_no_feedback(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::NO_FEEDBACK); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_top); + } + case EV_INIT: + { + return transition(&SMController::state_armed_nf); + } + case TMTC_ARP_DISARM: + { + return transition(&SMController::state_insert_info); + } + default: + { + return UNHANDLED; + } + } +} + +Boardcore::State SMController::state_init(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::INIT); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_config); + } + case EV_INIT: + { + return HANDLED; + } + case ARP_INIT_OK: + { + return transition(&SMController::state_init_done); + } + case ARP_INIT_ERROR: + { + return transition(&SMController::state_init_error); + } + default: + { + return UNHANDLED; + } + } +} + +Boardcore::State SMController::state_init_error(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::INIT_ERROR); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_config); + } + case EV_INIT: + { + return HANDLED; + } + case TMTC_ARP_FORCE_NO_FEEDBACK: + { + return transition(&SMController::state_insert_info); + } + case TMTC_ARP_FORCE_INIT: + { + return transition(&SMController::state_init_done); + } + default: + { + return UNHANDLED; + } + } +} + +Boardcore::State SMController::state_init_done(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::INIT_DONE); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_config); + } + case EV_INIT: + { + return HANDLED; + } + case TMTC_ARP_FORCE_NO_FEEDBACK: + { + return transition(&SMController::state_insert_info); + } + case TMTC_ARP_ARM: + { + return transition(&SMController::state_feedback); + } + default: + { + return UNHANDLED; + } + } +} + +Boardcore::State SMController::state_insert_info(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::INSERT_INFO); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_config); + } + case EV_INIT: + { + return HANDLED; + } + case TMTC_ARP_ARM: + { + return transition(&SMController::state_no_feedback); + } + default: + { + return UNHANDLED; + } + } +} + +Boardcore::State SMController::state_armed(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::ARMED); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_feedback); + } + case EV_INIT: + { + return HANDLED; + } + case TMTC_ARP_ENTER_TEST_MODE: + { + return transition(&SMController::state_test); + } + case TMTC_ARP_CALIBRATE: + { + return transition(&SMController::state_calibrate); + } + default: + { + return UNHANDLED; + } + } +} + +Boardcore::State SMController::state_test(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::TEST); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_feedback); + } + case EV_INIT: + { + return HANDLED; + } + case TMTC_ARP_EXIT_TEST_MODE: + { + return transition(&SMController::state_armed); + } + default: + { + return UNHANDLED; + } + } +} + +Boardcore::State SMController::state_calibrate(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::CALIBRATE); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_feedback); + } + case EV_INIT: + { + return HANDLED; + } + case ARP_CAL_DONE: + { + return transition(&SMController::state_fix_antennas); + } + case TMTC_ARP_RESET_ALGORITHM: + { + return transition(&SMController::state_armed); + } + default: + { + return UNHANDLED; + } + } +} + +Boardcore::State SMController::state_fix_antennas(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::FIX_ANTENNAS); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_feedback); + } + case EV_INIT: + { + return HANDLED; + } + case ARP_FIX_ANTENNAS: + { + return transition(&SMController::state_fix_rocket); + } + case TMTC_ARP_RESET_ALGORITHM: + { + return transition(&SMController::state_armed); + } + default: + { + return UNHANDLED; + } + } +} + +Boardcore::State SMController::state_fix_rocket(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::FIX_ROCKET); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_feedback); + } + case EV_INIT: + { + return HANDLED; + } + case ARP_FIX_ROCKET: + { + return transition(&SMController::state_active); + } + case TMTC_ARP_RESET_ALGORITHM: + { + return transition(&SMController::state_armed); + } + default: + { + return UNHANDLED; + } + } +} + +Boardcore::State SMController::state_active(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::ACTIVE); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_feedback); + } + case EV_INIT: + { + return HANDLED; + } + case TMTC_ARP_RESET_ALGORITHM: + { + return transition(&SMController::state_armed); + } + default: + { + return UNHANDLED; + } + } +} + +Boardcore::State SMController::state_armed_nf(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::ARMED_NF); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_no_feedback); + } + case EV_INIT: + { + return HANDLED; + } + case TMTC_ARP_ENTER_TEST_MODE: + { + return transition(&SMController::state_test_nf); + } + case TMTC_ARP_CALIBRATE: + { + return transition(&SMController::state_fix_rocket_nf); + } + default: + { + return UNHANDLED; + } + } +} + +Boardcore::State SMController::state_test_nf(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::TEST_NF); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_no_feedback); + } + case EV_INIT: + { + return HANDLED; + } + case TMTC_ARP_EXIT_TEST_MODE: + { + return transition(&SMController::state_armed_nf); + } + default: + { + return UNHANDLED; + } + } +} + +Boardcore::State SMController::state_fix_rocket_nf( + const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::FIX_ROCKET_NF); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_no_feedback); + } + case EV_INIT: + { + return HANDLED; + } + case ARP_FIX_ROCKET: + { + return transition(&SMController::state_active_nf); + } + case TMTC_ARP_RESET_ALGORITHM: + { + return transition(&SMController::state_armed_nf); + } + default: + { + return UNHANDLED; + } + } +} + +Boardcore::State SMController::state_active_nf(const Boardcore::Event& event) +{ + switch (event) + { + case EV_ENTRY: + { + logStatus(SMControllerState::ACTIVE_NF); + return HANDLED; + } + case EV_EXIT: + { + return HANDLED; + } + case EV_EMPTY: + { + return tranSuper(&SMController::state_no_feedback); + } + case EV_INIT: + { + return HANDLED; + } + case TMTC_ARP_RESET_ALGORITHM: + { + return transition(&SMController::state_armed_nf); + } + default: + { + return UNHANDLED; + } + } +} + +void SMController::logStatus(SMControllerState state) +{ + { + PauseKernelLock lock; + status.timestamp = TimestampTimer::getTimestamp(); + status.state = state; + } + + Logger::getInstance().log(status); +} + +} // namespace Antennas diff --git a/src/boards/Groundstation/Automated/SMController/SMController.h b/src/boards/Groundstation/Automated/SMController/SMController.h new file mode 100644 index 0000000000000000000000000000000000000000..f48e7957b86f5e62ff8cdc22b0f528344e4a3394 --- /dev/null +++ b/src/boards/Groundstation/Automated/SMController/SMController.h @@ -0,0 +1,73 @@ +/* Copyright (c) 2024 Skyward Experimental Rocketry + * Author: Federico Lolli + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include <events/EventBroker.h> +#include <events/HSM.h> + +#include <utils/ModuleManager/ModuleManager.hpp> + +#include "SMControllerData.h" + +namespace Antennas +{ + +class SMController : public Boardcore::Module, + public Boardcore::HSM<SMController> +{ +public: + SMController(); + + // FSM States + Boardcore::State state_config(const Boardcore::Event& event); + Boardcore::State state_feedback(const Boardcore::Event& event); + Boardcore::State state_no_feedback(const Boardcore::Event& event); + Boardcore::State state_init(const Boardcore::Event& event); + Boardcore::State state_init_error(const Boardcore::Event& event); + Boardcore::State state_init_done(const Boardcore::Event& event); + Boardcore::State state_insert_info(const Boardcore::Event& event); + Boardcore::State state_armed(const Boardcore::Event& event); + Boardcore::State state_test(const Boardcore::Event& event); + Boardcore::State state_calibrate(const Boardcore::Event& event); + Boardcore::State state_fix_antennas(const Boardcore::Event& event); + Boardcore::State state_fix_rocket(const Boardcore::Event& event); + Boardcore::State state_active(const Boardcore::Event& event); + Boardcore::State state_armed_nf(const Boardcore::Event& event); + Boardcore::State state_test_nf(const Boardcore::Event& event); + Boardcore::State state_fix_rocket_nf(const Boardcore::Event& event); + Boardcore::State state_active_nf(const Boardcore::Event& event); + +private: + /** + * @brief Logs the current state of the FSM + * @param state The current FSM state + */ + void logStatus(SMControllerState state); + + SMControllerStatus status; + + Boardcore::PrintLogger logger = + Boardcore::Logging::getLogger("SMController"); +}; + +} // namespace Antennas diff --git a/src/boards/Groundstation/Automated/SMController/SMControllerData.h b/src/boards/Groundstation/Automated/SMController/SMControllerData.h new file mode 100644 index 0000000000000000000000000000000000000000..98b3fa259acdf35868893b9d6d784dca04d32a3c --- /dev/null +++ b/src/boards/Groundstation/Automated/SMController/SMControllerData.h @@ -0,0 +1,79 @@ +/* Copyright (c) 2024 Skyward Experimental Rocketry + * Author: Federico Lolli + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include <stdint.h> + +#include <iostream> +#include <string> + +namespace Antennas +{ + +enum class SMControllerState : uint8_t +{ + INIT = 0, + INIT_ERROR, + INIT_DONE, + INSERT_INFO, + ARMED, + ARMED_NF, + TEST, + TEST_NF, + CALIBRATE, + FIX_ANTENNAS, + FIX_ROCKET, + FIX_ROCKET_NF, + ACTIVE, + ACTIVE_NF, + /** + * @brief macro state for configuration (init, init_error, + * init_done, state_insert_info) + */ + CONFIG, + /** + * @brief macro state for feedback (armed, test, calibrate, + * fix_antennas, fix_rocket, active) + */ + FEEDBACK, + /** + * @brief macro state for no feedback (armed_nf, test_nf, + * fix_rocket_nf, active_nf) + */ + NO_FEEDBACK +}; + +struct SMControllerStatus +{ + uint64_t timestamp; + SMControllerState state; + + static std::string header() { return "timestamp,state\n"; } + + void print(std::ostream& os) const + { + os << timestamp << "," << (int)state << "\n"; + } +}; + +} // namespace Antennas