diff --git a/include/etl/fsm.h b/include/etl/fsm.h index bb5fdc9a..63beaf07 100644 --- a/include/etl/fsm.h +++ b/include/etl/fsm.h @@ -213,7 +213,7 @@ namespace etl template struct check_ids : etl::true_type { }; - + template struct check_ids : etl::integral_constant::value> diff --git a/include/etl/generators/fsm_generator.h b/include/etl/generators/fsm_generator.h index 9166c78c..143b2708 100644 --- a/include/etl/generators/fsm_generator.h +++ b/include/etl/generators/fsm_generator.h @@ -72,6 +72,7 @@ cog.outl("//******************************************************************** #include "message_router.h" #include "integral_limits.h" #include "largest.h" +#include "tuple.h" #include @@ -226,8 +227,78 @@ namespace etl template ETL_CONSTANT fsm_state_id_t ifsm_state_helper::Self_Transition; + + // Compile-time: TState::ID must equal its index in the type list (0..N-1) + template struct check_ids : etl::true_type + { + }; + + template + struct check_ids + : etl::integral_constant::value> + { + }; } + class ifsm_state; + + //*************************************************************************** + /// A class to store FSM states. + //*************************************************************************** + template + class fsm_state_pack + { + public: + + friend class etl::fsm; + + ETL_STATIC_ASSERT((private_fsm::check_ids<0, TStates...>::value), "State IDs must be 0..N-1 and in order"); + ETL_STATIC_ASSERT(sizeof...(TStates) > 0, "At least one state is required"); + ETL_STATIC_ASSERT(sizeof...(TStates) < private_fsm::ifsm_state_helper<>::No_State_Change, "State IDs mst be less than ifsm_state::No_State_Change"); + + //********************************* + // The number of states. + //********************************* + static constexpr size_t size() + { + return sizeof...(TStates); + } + + //********************************* + /// Gets a reference to the state. + //********************************* + template + TState& get() + { + return etl::get(storage); + } + + //********************************* + /// Gets a const reference to the state. + //********************************* + template + const TState& get() const + { + return etl::get(storage); + } + + private: + + //********************************* + /// Gets a pointer to the state list. + //********************************* + etl::ifsm_state** get_state_list() + { + return &states[0]; + } + + /// A tuple to store the states. + etl::tuple storage{}; + + /// Pointers to the states. + etl::ifsm_state* states[sizeof...(TStates)]{ &etl::get(storage)... }; + }; + //*************************************************************************** /// Interface class for FSM states. //*************************************************************************** @@ -359,8 +430,8 @@ namespace etl ifsm_state* p_default_child; // Disabled. - ifsm_state(const ifsm_state&); - ifsm_state& operator =(const ifsm_state&); + ifsm_state(const ifsm_state&) ETL_DELETE; + ifsm_state& operator =(const ifsm_state&) ETL_DELETE; }; //*************************************************************************** @@ -386,6 +457,7 @@ namespace etl //******************************************* /// Set the states for the FSM + /// From a pointer to etl::ifsm_state and size. //******************************************* template void set_states(etl::ifsm_state** p_states, TSize size) @@ -404,6 +476,22 @@ namespace etl } } + //******************************************* + /// Set the states for the FSM + /// From an etl::fsm_state_pack. + //******************************************* + template + void set_states(etl::fsm_state_pack& state_pack) + { + state_list = state_pack.get_state_list(); + number_of_states = etl::fsm_state_id_t(state_pack.size()); + + for (etl::fsm_state_id_t i = 0; i < number_of_states; ++i) + { + state_list[i]->set_fsm_context(*this); + } + } + //******************************************* /// Starts the FSM. /// Can only be called once. diff --git a/support/Release notes.txt b/support/Release notes.txt index 093f4449..078f2baf 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -2,6 +2,7 @@ 20.42.2 Updates: +Added 'emplace' constructor to etl::optional Added etl::crc8_opensafety Added etl::crc16_opensafety_a and etl::crc16_opensafety_b Added etl::crc64_iso @@ -9,12 +10,18 @@ Added etl::type_lists_are_convertible Made etl::closure constexpr for C++14 Made invocation of delegate consrexpr for C++14 #1132 Request: Make type_def Methods Noexcept +#1054 Using #pragma once +#1159 etl::fsm helper to check states id sequence at compile time Fixes: Fix gamma tests (removed integral tests) #1126 to_arithmetic does not compile on C++98 #1150 Bug in the void etl::unlink(first, last) for bidirectional links. #1151 test failure in i386 in 20.42.1: test_replace_strings in test_string_utilities.c fails +#1152 Patch: use "python3 -m cogapp" instead of "cog" in generate.bat +#1153 ROM size increase after algorithm_exception introduction +#1156 Name conflict between template parameter and status register macro on MSP430 devices +#1158 Bug: Inverted logic in ! __has_include() check causes compilation failure on compilers without header Pull Requests: #955 Implements deferred callback timer with optional priority