/* * statemachine.hpp * * Created on: Sep 14, 2023 * Author: Dario */ #ifndef INCLUDE_TACOS_STATEMACHINE_HPP_ #define INCLUDE_TACOS_STATEMACHINE_HPP_ #include #ifndef STA_TACOS_NUM_STATES # error "Number of states wasn't defined in config.hpp" #else #ifndef STA_TACOS_INITIAL_STATE # define STA_TACOS_INITIAL_STATE 0 #endif #define STA_TACOS_STATEMACHINE_QUEUE_LENGTH 4 // State transition happened because of #define STA_TACOS_STATE_CHANGE_NORMAL_FLAG ( 0x1U ) #define STA_TACOS_STATE_CHANGE_FORCED_FLAG ( 0x1U << 1) #define STA_TACOS_STATE_CHANGE_TIMEOUT ( 0x1U << 2) #define STA_TACOS_STATE_CHANGE_STARTUP_FLAG ( 0x1U << 3) #define STA_TACOS_STATE_CHANGE_ALL_FLAG ( 0x15U ) #include #include #include #include #include #include #include #include namespace sta { namespace tacos { enum EventFlags { NORMAL = 0x1U, FORCED = 0x1U << 1, TIMEOUT = 0x1U << 2, STARTUP = 0x1U << 3, ALL = NORMAL | FORCED | TIMEOUT | STARTUP }; struct StateTransition { uint16_t from; uint16_t to; EventFlags event; uint32_t lockout; }; class Statemachine : public TacosThread { public: /** * @brief The global event signaling a state change. */ static RtosEvent stateChangeEvent; /** * @brief Getter function for the singleton instance. */ static Statemachine* instance() { static CGuard g; if (!_instance) { // Create the manager singleton instance. Statemachine::_instance = new Statemachine(); } return _instance; } /** * @brief Returns the statemachine's current state. */ uint16_t getCurrentState() const; /** * @brief Request a state transition from a state to another. * * @param from The state which we want to leave. This is used to filter out obsolete transitions. * @param to The state to transition to. * @param lockout The minimum number of milliseconds we expect to stay in this state. This is used to block premature transitions. */ void requestStateTransition(uint32_t from, uint32_t to, uint32_t lockout = 0); /** * @brief Request a state transition after a given time has passed. * * @param from The state which we want to leave. This is used to filter out obsolete transitions. * @param to The state to transition to. * @param millis the number of milliseconds to wait before triggering the transition. * @param lockout The minimum number of milliseconds we expect to stay in this state. This is used to block premature transitions. */ void requestTimedStateTransition(uint32_t from, uint32_t to, uint32_t millis, uint32_t lockout = 0); void init() override; void func() override; private: static Statemachine * _instance; class CGuard { public: ~CGuard() { if( NULL != Statemachine::_instance ) { delete Statemachine::_instance; Statemachine::_instance = NULL; } } }; Statemachine(); Statemachine(const Statemachine&); ~Statemachine() {} private: /** * @brief Starts the lockoutTimer for the desired duration. */ void setLockoutTimer(uint32_t millis); private: uint16_t currentState_; RtosTimer lockoutTimer_; RtosTimer failsafeTimer_; RtosQueue queue_; }; } // namespace tacos } // namespace sta #endif // STA_TACOS_NUM_STATES #endif /* INCLUDE_TACOS_STATEMACHINE_HPP_ */