/* * statemachine.hpp * * Created on: Sep 14, 2023 * Author: Dario */ #ifndef INCLUDE_TACOS_STATEMACHINE_HPP_ #define INCLUDE_TACOS_STATEMACHINE_HPP_ #include #if !defined(STA_TACOS_NUM_STATES) && !defined(DOXYGEN) # error "Number of states wasn't defined in config.hpp" #else #if !defined(STA_TACOS_INITIAL_STATE) && !defined(DOXYGEN) # define STA_TACOS_INITIAL_STATE 0 #endif /** * @defgroup tacos_statemachine Statemachine Task * @ingroup tacos * @brief Statemachine task for TACOS. */ /** * @brief The maximum number of state transitions that can be queued. * * @ingroup tacos_statemachine */ #define STA_TACOS_STATEMACHINE_QUEUE_LENGTH 4 /** * @ingroup tacos_statemachine * @{ */ // State transition happened because of /** * @brief State change due to requested Transition. */ #define STA_TACOS_STATE_CHANGE_NORMAL_FLAG ( 0x1U ) /** * @brief State change due to forced Transition. */ #define STA_TACOS_STATE_CHANGE_FORCED_FLAG ( 0x1U << 1) /** * @brief State change due to timeout. */ #define STA_TACOS_STATE_CHANGE_TIMEOUT ( 0x1U << 2) /** * @brief State change due to startup. */ #define STA_TACOS_STATE_CHANGE_STARTUP_FLAG ( 0x1U << 3) /** * @brief State change due to any reason. */ #define STA_TACOS_STATE_CHANGE_ALL_FLAG ( 0x15U ) /** @} */ #include #include #include #include #include #include #include #include namespace sta { namespace tacos { /** * @brief Event flags for state transitions. * * @ingroup tacos_statemachine */ enum EventFlags { NORMAL = 0x1U, FORCED = 0x1U << 1, TIMEOUT = 0x1U << 2, STARTUP = 0x1U << 3, ALL = NORMAL | FORCED | TIMEOUT | STARTUP }; /** * @brief State transition structure. * * @ingroup tacos_statemachine */ struct StateTransition { /// Origin of transition uint16_t from; /// Destination of transition uint16_t to; /// Event that triggered the transition EventFlags event; /// Lockout time after transition uint32_t lockout; }; /** * @brief Statemachine implementation for Tacos. * * @ingroup tacos_statemachine */ 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. * * @param millis The duration of the timer in milliseconds. */ 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_ */