diff --git a/arduino/create_arduino_library.py b/arduino/create_arduino_library.py index f7c7c7e9..4d68c83d 100644 --- a/arduino/create_arduino_library.py +++ b/arduino/create_arduino_library.py @@ -17,31 +17,31 @@ print('') # Get the current path of the script arduino_dir = os.path.dirname(__file__) -print('arduino_dir = ', arduino_dir) +print('arduino_dir = ', arduino_dir) # Get the root folder of the ETL etl_dir = os.path.dirname(arduino_dir) -print('etl_dir = ', etl_dir) +print('etl_dir = ', etl_dir) # Get the ETL repository folder include_dir = os.path.join(etl_dir, 'include') -print('include_dir = ', include_dir) +print('include_dir = ', include_dir) # Get the ETL arduino_examples folder arduino_examples_dir = os.path.join(arduino_dir, 'examples') -print('examples_dir = ', arduino_examples_dir) +print('examples_dir = ', arduino_examples_dir) # Get the root folder of both repositories common_dir = os.path.dirname(etl_dir) -print('common_dir = ', common_dir) +print('common_dir = ', common_dir) # Get the ETL Arduino repository folder etl_arduino_dir = os.path.join(common_dir, 'etl-arduino') -print('etl_arduino_dir = ', etl_arduino_dir) +print('etl_arduino_dir = ', etl_arduino_dir) # Get the ETL Arduino src repository folder etl_arduino_src_dir = os.path.join(etl_arduino_dir, 'src') -print('etl_arduino_src_dir = ', etl_arduino_src_dir) +print('etl_arduino_src_dir = ', etl_arduino_src_dir) # Get the ETL Arduino examples repository folder etl_arduino_examples_dir = os.path.join(etl_arduino_dir, 'examples') @@ -51,7 +51,7 @@ print('') # Copy the library properties filename = 'library.properties' -source = os.path.join(etl_dir, filename) +source = os.path.join(arduino_dir, filename) destination = os.path.join(etl_arduino_dir, filename) print('Copy the library properties') print(' From :', source) @@ -60,6 +60,17 @@ shutil.copyfile(source, destination) print('') +# Copy the library json +filename = 'library.json' +source = os.path.join(arduino_dir, filename) +destination = os.path.join(etl_arduino_dir, filename) +print('Copy the library json') +print(' From :', source) +print(' To :', destination) +shutil.copyfile(source, destination) + +print('') + # Copy the Arduino ETL header filename = 'Embedded_Template_Library.h' source = os.path.join(arduino_dir, filename) diff --git a/arduino/library.json b/arduino/library.json new file mode 100644 index 00000000..3904cd23 --- /dev/null +++ b/arduino/library.json @@ -0,0 +1,21 @@ +{ + "name": "Embedded Template Library - Arduino", + "version": "20.23.0", + "authors": { + "name": "John Wellbelove", + "email": "john.wellbelove@etlcpp.com" + }, + "homepage": "https://www.etlcpp.com/", + "license": "MIT", + "description": "ETL. A C++ template library tailored for embedded systems. Directories formated for Arduino", + "keywords": "c-plus-plus, cpp, algorithms, containers, templates", + "repository": { + "type": "git", + "url": "https://github.com/ETLCPP/etl.git" + }, + "build": { + "includeDir": "include" + }, + "platforms": "*", + "frameworks": "*" +} diff --git a/arduino/library.properties b/arduino/library.properties new file mode 100644 index 00000000..6d425bc8 --- /dev/null +++ b/arduino/library.properties @@ -0,0 +1,10 @@ +name=Embedded Template Library - Arduino +version=20.23.0 +author= John Wellbelove +maintainer=John Wellbelove +license=MIT +sentence=ETL. A C++ template library tailored for embedded systems. +paragraph= +category=Other +url=https://www.etlcpp.com/ +architectures=* diff --git a/include/etl/bit.h b/include/etl/bit.h index b8e57f06..e22de9eb 100644 --- a/include/etl/bit.h +++ b/include/etl/bit.h @@ -195,8 +195,6 @@ namespace etl typename etl::enable_if::value, T>::type rotl(T value, int n) ETL_NOEXCEPT { - ETL_CONSTANT size_t N = etl::integral_limits::bits; - if (n < 0) { return etl::rotate_right(value, -n); @@ -215,8 +213,6 @@ namespace etl typename etl::enable_if::value, T>::type rotr(T value, int n) ETL_NOEXCEPT { - ETL_CONSTANT size_t N = etl::integral_limits::bits; - if (n < 0) { return etl::rotate_left(value, -n); diff --git a/include/etl/callback_timer_atomic.h b/include/etl/callback_timer_atomic.h index 9df96bb6..6e04a032 100644 --- a/include/etl/callback_timer_atomic.h +++ b/include/etl/callback_timer_atomic.h @@ -168,8 +168,6 @@ namespace etl // We have something to do? bool has_active = !active_list.empty(); - timer_data* ptimer = &active_list.front(); - if (has_active) { while (has_active && (count >= active_list.front().delta)) diff --git a/include/etl/callback_timer_locked.h b/include/etl/callback_timer_locked.h index c3b2abda..3cae867e 100644 --- a/include/etl/callback_timer_locked.h +++ b/include/etl/callback_timer_locked.h @@ -164,9 +164,7 @@ namespace etl if (try_lock()) { // We have something to do? - bool has_active = !active_list.empty(); - - timer_data* ptimer = &active_list.front(); + bool has_active = !active_list.empty(); if (has_active) { @@ -177,7 +175,6 @@ namespace etl count -= timer.delta; active_list.remove(timer.id, true); - ptimer = &active_list.front(); if (timer.repeating) { diff --git a/include/etl/endianness.h b/include/etl/endianness.h index fabaf259..b53ca51d 100644 --- a/include/etl/endianness.h +++ b/include/etl/endianness.h @@ -75,7 +75,11 @@ SOFTWARE. #endif // If true, then the endianness of the platform can be constexpr. -#define ETL_ENDIANNESS_IS_CONSTEXPR (ETL_CPP11_SUPPORTED && defined(ETL_ENDIAN_NATIVE)) +#if (ETL_CPP11_SUPPORTED && defined(ETL_ENDIAN_NATIVE)) + #define ETL_ENDIANNESS_IS_CONSTEXPR 1 +#else + #define ETL_ENDIANNESS_IS_CONSTEXPR 0 +#endif namespace etl { diff --git a/include/etl/numeric.h b/include/etl/numeric.h index f274635c..8bc135cf 100644 --- a/include/etl/numeric.h +++ b/include/etl/numeric.h @@ -177,9 +177,8 @@ namespace etl ETL_CONSTEXPR T midpoint(T a, T b, typename etl::enable_if<(!etl::is_pointer::value && !etl::is_integral::value && !etl::is_floating_point::value && - etl::is_same::iterator_category, ETL_OR_STD::forward_iterator_tag>::value || - etl::is_same::iterator_category, ETL_OR_STD::bidirectional_iterator_tag>::value) - , int>::type = 0) + (etl::is_same::iterator_category, ETL_OR_STD::forward_iterator_tag>::value || + etl::is_same::iterator_category, ETL_OR_STD::bidirectional_iterator_tag>::value)), int>::type = 0) { etl::advance(a, etl::distance(a, b) / 2U); return a; diff --git a/include/etl/state_chart.h b/include/etl/state_chart.h index 7533ae0f..7907a545 100644 --- a/include/etl/state_chart.h +++ b/include/etl/state_chart.h @@ -40,17 +40,298 @@ SOFTWARE. namespace etl { //*************************************************************************** - /// Simple Finite State Machine Interface + /// Simple Finite State Machine Types //*************************************************************************** + + namespace state_chart_traits + { + typedef uint_least8_t state_id_t; + typedef uint_least8_t event_id_t; + + //************************************************************************* + /// Transition definition + //************************************************************************* + template + struct transition + { + ETL_CONSTEXPR transition(const state_id_t current_state_id_, + event_id_t event_id_, + const state_id_t next_state_id_, + void (TObject::* const action_)(TParameter) = ETL_NULLPTR, + bool (TObject::* const guard_)() = ETL_NULLPTR) + : current_state_id(current_state_id_) + , event_id(event_id_) + , next_state_id(next_state_id_) + , action(action_) + , guard(guard_) + , from_any_state(false) + { + } + + ETL_CONSTEXPR transition(event_id_t event_id_, + const state_id_t next_state_id_, + void (TObject::* const action_)(TParameter) = ETL_NULLPTR, + bool (TObject::* const guard_)() = ETL_NULLPTR) + : current_state_id(0) + , event_id(event_id_) + , next_state_id(next_state_id_) + , action(action_) + , guard(guard_) + , from_any_state(true) + { + } + + const state_id_t current_state_id; + const event_id_t event_id; + const state_id_t next_state_id; + void (TObject::* const action)(TParameter); + bool (TObject::* const guard)(); + const bool from_any_state; + }; + + //************************************************************************* + /// Transition definition + /// Specialisation for void parameter + //************************************************************************* + template + struct transition + { + ETL_CONSTEXPR transition(const state_id_t current_state_id_, + event_id_t event_id_, + const state_id_t next_state_id_, + void (TObject::* const action_)() = ETL_NULLPTR, + bool (TObject::* const guard_)() = ETL_NULLPTR) + : current_state_id(current_state_id_) + , event_id(event_id_) + , next_state_id(next_state_id_) + , action(action_) + , guard(guard_) + , from_any_state(false) + { + } + + ETL_CONSTEXPR transition(event_id_t event_id_, + const state_id_t next_state_id_, + void (TObject::* const action_)() = ETL_NULLPTR, + bool (TObject::* const guard_)() = ETL_NULLPTR) + : current_state_id(0) + , event_id(event_id_) + , next_state_id(next_state_id_) + , action(action_) + , guard(guard_) + , from_any_state(true) + { + } + + const state_id_t current_state_id; + const event_id_t event_id; + const state_id_t next_state_id; + void (TObject::* const action)(); + bool (TObject::* const guard)(); + const bool from_any_state; + }; + + //************************************************************************* + /// State definition + //************************************************************************* + template + struct state + { + ETL_CONSTEXPR state(const state_id_t state_id_, + void (TObject::* const on_entry_)() = ETL_NULLPTR, + void (TObject::* const on_exit_)() = ETL_NULLPTR) + : state_id(state_id_) + , on_entry(on_entry_) + , on_exit(on_exit_) + { + } + + state_id_t state_id; + void (TObject::* const on_entry)(); + void (TObject::* const on_exit)(); + }; + } + + //*************************************************************************** + /// For non-void parameter types + //*************************************************************************** + template class istate_chart { public: - typedef int state_id_t; - typedef int event_id_t; + typedef TParameter parameter_t; + typedef state_chart_traits::state_id_t state_id_t; + typedef state_chart_traits::event_id_t event_id_t; - virtual void start(const bool on_entry_initial = true) = 0; - virtual void process_event(const event_id_t event_id) = 0; + virtual void process_event(event_id_t, parameter_t) = 0; + virtual ~istate_chart() {} + }; + + //*************************************************************************** + /// For void parameter types + //*************************************************************************** + template <> + class istate_chart + { + public: + + typedef void parameter_t; + typedef state_chart_traits::state_id_t state_id_t; + typedef state_chart_traits::event_id_t event_id_t; + + virtual void process_event(event_id_t) = 0; + virtual ~istate_chart() {} + }; + + //*************************************************************************** + /// Simple Finite State Machine + /// Compile time tables. + /// Event has no parameter. + //*************************************************************************** + template * Transition_Table_Begin, + size_t Transition_Table_Size, + const etl::state_chart_traits::state* State_Table_Begin, + size_t State_Table_Size, + etl::state_chart_traits::state_id_t Initial_State> + class state_chart_ct : public istate_chart + { + public: + + typedef void parameter_t; + typedef state_chart_traits::state_id_t state_id_t; + typedef state_chart_traits::event_id_t event_id_t; + typedef state_chart_traits::transition transition; + typedef state_chart_traits::state state; + + //************************************************************************* + /// Constructor. + //************************************************************************* + ETL_CONSTEXPR state_chart_ct() + : current_state_id(Initial_State) + , started(false) + { + } + + //************************************************************************* + /// Gets a const reference to the implementation object. + /// \return Const reference to the implementation object. + //************************************************************************* + TObject& get_object() + { + return TObject_Ref; + } + + //************************************************************************* + /// Gets a const reference to the implementation object. + /// \return Const reference to the implementation object. + //************************************************************************* + const TObject& get_object() const + { + return TObject_Ref; + } + + //************************************************************************* + /// Gets the current state id. + /// \return The current state id. + //************************************************************************* + const state* find_state(state_id_t state_id) + { + return etl::find_if(State_Table_Begin, State_Table_Begin + State_Table_Size, is_state(state_id)); + } + + //************************************************************************* + /// Start the state chart. + //************************************************************************* + void start(const bool on_entry_initial = true) + { + if (!started) + { + if (on_entry_initial) + { + // See if we have a state item for the initial state. + const state* s = find_state(current_state_id); + + // If the initial state has an 'on_entry' then call it. + if ((s != (State_Table_Begin + State_Table_Size)) && (s->on_entry != ETL_NULLPTR)) + { + (TObject_Ref.*(s->on_entry))(); + } + } + + started = true; + } + } + + //************************************************************************* + /// Processes the specified event. + /// The state machine will action the first item in the transition table + /// that satisfies the conditions for executing the action. + /// \param event_id The id of the event to process. + //************************************************************************* + virtual void process_event(event_id_t event_id) ETL_OVERRIDE + { + if (started) + { + const transition* t = Transition_Table_Begin; + + // Keep looping until we execute a transition or reach the end of the table. + while (t != (Transition_Table_Begin + Transition_Table_Size)) + { + // Scan the transition table from the latest position. + t = etl::find_if(t, (Transition_Table_Begin + Transition_Table_Size), is_transition(event_id, current_state_id)); + + // Found an entry? + if (t != (Transition_Table_Begin + Transition_Table_Size)) + { + // Shall we execute the transition? + if ((t->guard == ETL_NULLPTR) || ((TObject_Ref.*t->guard)())) + { + // Shall we execute the action? + if (t->action != ETL_NULLPTR) + { + (TObject_Ref.*t->action)(); + } + + // Changing state? + if (current_state_id != t->next_state_id) + { + const state* s; + + // See if we have a state item for the current state. + s = find_state(current_state_id); + + // If the current state has an 'on_exit' then call it. + if ((s != (State_Table_Begin + State_Table_Size)) && (s->on_exit != ETL_NULLPTR)) + { + (TObject_Ref.*(s->on_exit))(); + } + + current_state_id = t->next_state_id; + + // See if we have a state item for the new state. + s = find_state(current_state_id); + + // If the new state has an 'on_entry' then call it. + if ((s != (State_Table_Begin + State_Table_Size)) && (s->on_entry != ETL_NULLPTR)) + { + (TObject_Ref.*(s->on_entry))(); + } + } + + t = (Transition_Table_Begin + Transition_Table_Size); + } + else + { + // Start the search from the next item in the table. + ++t; + } + } + } + } + } //************************************************************************* /// Gets the current state id. @@ -61,108 +342,273 @@ namespace etl return current_state_id; } - virtual ~istate_chart() - { - } + private: - protected: - - istate_chart(state_id_t current_state_id_) - : current_state_id(current_state_id_) + //************************************************************************* + struct is_transition { - } + is_transition(event_id_t event_id_, state_id_t state_id_) + : event_id(event_id_) + , state_id(state_id_) + { + } + + bool operator()(const transition& t) const + { + return (t.event_id == event_id) && (t.from_any_state || (t.current_state_id == state_id)); + } + + const event_id_t event_id; + const state_id_t state_id; + }; + + //************************************************************************* + struct is_state + { + is_state(state_id_t state_id_) + : state_id(state_id_) + { + } + + bool operator()(const state& s) const + { + return (s.state_id == state_id); + } + + const state_id_t state_id; + }; + + // Disabled + state_chart_ct(const state_chart_ct&) ETL_DELETE; + state_chart_ct& operator =(const state_chart_ct&) ETL_DELETE; state_id_t current_state_id; ///< The current state id. + bool started; ///< Set if the state chart has been started. }; //*************************************************************************** /// Simple Finite State Machine - /// Data parameter for events. + /// Compile time tables. + /// Event has parameter. //*************************************************************************** - template - class state_chart : public istate_chart + template * Transition_Table_Begin, + size_t Transition_Table_Size, + const etl::state_chart_traits::state* State_Table_Begin, + size_t State_Table_Size, + etl::state_chart_traits::state_id_t Initial_State> + class state_chart_ctp : public istate_chart { public: typedef TParameter parameter_t; - - //************************************************************************* - /// Transition definition - //************************************************************************* - struct transition - { - ETL_CONSTEXPR transition(const state_id_t current_state_id_, - const event_id_t event_id_, - const state_id_t next_state_id_, - void (TObject::* const action_)(parameter_t) = ETL_NULLPTR, - bool (TObject::* const guard_)() = ETL_NULLPTR) - : from_any_state(false), - current_state_id(current_state_id_), - event_id(event_id_), - next_state_id(next_state_id_), - action(action_), - guard(guard_) - { - } - - ETL_CONSTEXPR transition(const event_id_t event_id_, - const state_id_t next_state_id_, - void (TObject::* const action_)(parameter_t) = ETL_NULLPTR, - bool (TObject::* const guard_)() = ETL_NULLPTR) - : from_any_state(true), - current_state_id(0), - event_id(event_id_), - next_state_id(next_state_id_), - action(action_), - guard(guard_) - { - } - - const bool from_any_state; - const state_id_t current_state_id; - const event_id_t event_id; - const state_id_t next_state_id; - void (TObject::* const action)(parameter_t); - bool (TObject::* const guard)(); - }; - - //************************************************************************* - /// State definition - //************************************************************************* - struct state - { - ETL_CONSTEXPR state(const state_id_t state_id_, - void (TObject::* const on_entry_)() = ETL_NULLPTR, - void (TObject::* const on_exit_)() = ETL_NULLPTR) - : state_id(state_id_), - on_entry(on_entry_), - on_exit(on_exit_) - { - } - - state_id_t state_id; - void (TObject::* const on_entry)(); - void (TObject::* const on_exit)(); - }; + typedef state_chart_traits::state_id_t state_id_t; + typedef state_chart_traits::event_id_t event_id_t; + typedef state_chart_traits::transition transition; + typedef state_chart_traits::state state; //************************************************************************* /// Constructor. - /// \param object_ A reference to the implementation object. - /// \param transition_table_begin_ The start of the table of transitions. - /// \param transition_table_end_ The end of the table of transitions. - /// \param state_id_ The initial state id. //************************************************************************* - ETL_CONSTEXPR state_chart(TObject& object_, - const transition* transition_table_begin_, - const transition* transition_table_end_, - const state_id_t state_id_) - : istate_chart(state_id_), - object(object_), - transition_table(transition_table_begin_, transition_table_end_), - started(false) + ETL_CONSTEXPR state_chart_ctp() + : current_state_id(Initial_State) + , started(false) { } + //************************************************************************* + /// Gets a const reference to the implementation object. + /// \return Const reference to the implementation object. + //************************************************************************* + TObject& get_object() + { + return TObject_Ref; + } + + //************************************************************************* + /// Gets a const reference to the implementation object. + /// \return Const reference to the implementation object. + //************************************************************************* + const TObject& get_object() const + { + return TObject_Ref; + } + + //************************************************************************* + /// Gets the current state id. + /// \return The current state id. + //************************************************************************* + const state* find_state(state_id_t state_id) + { + return etl::find_if(State_Table_Begin, State_Table_Begin + State_Table_Size, is_state(state_id)); + } + + //************************************************************************* + /// Start the state chart. + //************************************************************************* + void start(const bool on_entry_initial = true) + { + if (!started) + { + if (on_entry_initial) + { + // See if we have a state item for the initial state. + const state* s = find_state(current_state_id); + + // If the initial state has an 'on_entry' then call it. + if ((s != (State_Table_Begin + State_Table_Size)) && (s->on_entry != ETL_NULLPTR)) + { + (TObject_Ref.*(s->on_entry))(); + } + } + + started = true; + } + } + + //************************************************************************* + /// Processes the specified event. + /// The state machine will action the first item in the transition table + /// that satisfies the conditions for executing the action. + /// \param event_id The id of the event to process. + //************************************************************************* + virtual void process_event(event_id_t event_id, parameter_t data) ETL_OVERRIDE + { + if (started) + { + const transition* t = Transition_Table_Begin; + + // Keep looping until we execute a transition or reach the end of the table. + while (t != (Transition_Table_Begin + Transition_Table_Size)) + { + // Scan the transition table from the latest position. + t = etl::find_if(t, (Transition_Table_Begin + Transition_Table_Size), is_transition(event_id, current_state_id)); + + // Found an entry? + if (t != (Transition_Table_Begin + Transition_Table_Size)) + { + // Shall we execute the transition? + if ((t->guard == ETL_NULLPTR) || ((TObject_Ref.*t->guard)())) + { + // Shall we execute the action? + if (t->action != ETL_NULLPTR) + { +#if ETL_CPP11_SUPPORTED + (TObject_Ref.*t->action)(etl::forward(data)); +#else + (TObject_Ref.*t->action)(data); +#endif + } + + // Changing state? + if (current_state_id != t->next_state_id) + { + const state* s; + + // See if we have a state item for the current state. + s = find_state(current_state_id); + + // If the current state has an 'on_exit' then call it. + if ((s != (State_Table_Begin + State_Table_Size)) && (s->on_exit != ETL_NULLPTR)) + { + (TObject_Ref.*(s->on_exit))(); + } + + current_state_id = t->next_state_id; + + // See if we have a state item for the new state. + s = find_state(current_state_id); + + // If the new state has an 'on_entry' then call it. + if ((s != (State_Table_Begin + State_Table_Size)) && (s->on_entry != ETL_NULLPTR)) + { + (TObject_Ref.*(s->on_entry))(); + } + } + + t = (Transition_Table_Begin + Transition_Table_Size); + } + else + { + // Start the search from the next item in the table. + ++t; + } + } + } + } + } + + //************************************************************************* + /// Gets the current state id. + /// \return The current state id. + //************************************************************************* + state_id_t get_state_id() const + { + return current_state_id; + } + + private: + + //************************************************************************* + struct is_transition + { + is_transition(event_id_t event_id_, state_id_t state_id_) + : event_id(event_id_) + , state_id(state_id_) + { + } + + bool operator()(const transition& t) const + { + return (t.event_id == event_id) && (t.from_any_state || (t.current_state_id == state_id)); + } + + const event_id_t event_id; + const state_id_t state_id; + }; + + //************************************************************************* + struct is_state + { + is_state(state_id_t state_id_) + : state_id(state_id_) + { + } + + bool operator()(const state& s) const + { + return (s.state_id == state_id); + } + + const state_id_t state_id; + }; + + // Disabled + state_chart_ctp(const state_chart_ctp&) ETL_DELETE; + state_chart_ctp& operator =(const state_chart_ctp&) ETL_DELETE; + + state_id_t current_state_id; ///< The current state id. + bool started; ///< Set if the state chart has been started. + }; + + //*************************************************************************** + /// Simple Finite State Machine + /// Runtime tables. + /// Event has a parameter. + //*************************************************************************** + template + class state_chart : public istate_chart + { + public: + + typedef TParameter parameter_t; + typedef state_chart_traits::state_id_t state_id_t; + typedef state_chart_traits::event_id_t event_id_t; + typedef state_chart_traits::transition transition; + typedef state_chart_traits::state state; + //************************************************************************* /// Constructor. /// \param object_ A reference to the implementation object. @@ -172,17 +618,19 @@ namespace etl /// \param state_table_end_ The end of the state table. /// \param state_id_ The initial state id. //************************************************************************* - ETL_CONSTEXPR state_chart(TObject& object_, + ETL_CONSTEXPR state_chart(TObject& object_, const transition* transition_table_begin_, const transition* transition_table_end_, - const state* state_table_begin_, - const state* state_table_end_, - const state_id_t state_id_) - : istate_chart(state_id_), - object(object_), - transition_table(transition_table_begin_, transition_table_end_), - state_table(state_table_begin_, state_table_end_), - started(false) + const state* state_table_begin_, + const state* state_table_end_, + const state_id_t state_id_) + : object(object_) + , transition_table_begin(transition_table_begin_) + , state_table_begin(state_table_begin_) + , transition_table_size(transition_table_end_ - transition_table_begin_) + , state_table_size(state_table_end_ - state_table_begin_) + , current_state_id(state_id_) + , started(false) { } @@ -192,9 +640,10 @@ namespace etl /// \param state_table_end_ The end of the state table. //************************************************************************* void set_transition_table(const transition* transition_table_begin_, - const transition* transition_table_end_) + const transition* transition_table_end_) { - transition_table.assign(transition_table_begin_, transition_table_end_); + transition_table_begin = transition_table_begin_; + transition_table_size = transition_table_end_ - transition_table_begin_; } //************************************************************************* @@ -203,9 +652,10 @@ namespace etl /// \param state_table_end_ The end of the state table. //************************************************************************* void set_state_table(const state* state_table_begin_, - const state* state_table_end_) + const state* state_table_end_) { - state_table.assign(state_table_begin_, state_table_end_); + state_table_begin = state_table_begin_; + state_table_size = state_table_end_ - state_table_begin_; } //************************************************************************* @@ -232,22 +682,20 @@ namespace etl //************************************************************************* const state* find_state(state_id_t state_id) { - if (state_table.empty()) + if (state_table_begin == ETL_NULLPTR) { - return state_table.end(); + return state_table_end(); } else { - return etl::find_if(state_table.begin(), - state_table.end(), - is_state(state_id)); + return etl::find_if(state_table_begin, state_table_end(), is_state(state_id)); } } //************************************************************************* - /// + /// Start the state chart. //************************************************************************* - virtual void start(const bool on_entry_initial = true) ETL_OVERRIDE + void start(const bool on_entry_initial = true) { if (!started) { @@ -257,7 +705,7 @@ namespace etl const state* s = find_state(current_state_id); // If the initial state has an 'on_entry' then call it. - if ((s != state_table.end()) && (s->on_entry != ETL_NULLPTR)) + if ((s != state_table_end()) && (s->on_entry != ETL_NULLPTR)) { (object.*(s->on_entry))(); } @@ -273,34 +721,20 @@ namespace etl /// that satisfies the conditions for executing the action. /// \param event_id The id of the event to process. //************************************************************************* - virtual void process_event(const event_id_t event_id) ETL_OVERRIDE - { - process_event(event_id, typename etl::types::type()); - } - - //************************************************************************* - /// Processes the specified event. - /// The state machine will action the first item in the transition table - /// that satisfies the conditions for executing the action. - /// \param event_id The id of the event to process. - /// \param data The data to pass to the action. - //************************************************************************* - void process_event(const event_id_t event_id, parameter_t data) + void process_event(event_id_t event_id, parameter_t data) { if (started) { - const transition* t = transition_table.begin(); + const transition* t = transition_table_begin; // Keep looping until we execute a transition or reach the end of the table. - while (t != transition_table.end()) + while (t != transition_table_end()) { // Scan the transition table from the latest position. - t = etl::find_if(t, - transition_table.end(), - is_transition(event_id, current_state_id)); + t = etl::find_if(t, transition_table_end(), is_transition(event_id, current_state_id)); // Found an entry? - if (t != transition_table.end()) + if (t != transition_table_end()) { // Shall we execute the transition? if ((t->guard == ETL_NULLPTR) || ((object.*t->guard)())) @@ -324,7 +758,7 @@ namespace etl s = find_state(current_state_id); // If the current state has an 'on_exit' then call it. - if ((s != state_table.end()) && (s->on_exit != ETL_NULLPTR)) + if ((s != state_table_end()) && (s->on_exit != ETL_NULLPTR)) { (object.*(s->on_exit))(); } @@ -335,13 +769,13 @@ namespace etl s = find_state(current_state_id); // If the new state has an 'on_entry' then call it. - if ((s != state_table.end()) && (s->on_entry != ETL_NULLPTR)) + if ((s != state_table_end()) && (s->on_entry != ETL_NULLPTR)) { (object.*(s->on_entry))(); } } - t = transition_table.end(); + t = transition_table_end(); } else { @@ -353,14 +787,35 @@ namespace etl } } + //************************************************************************* + /// Gets the current state id. + /// \return The current state id. + //************************************************************************* + state_id_t get_state_id() const + { + return current_state_id; + } + private: + //************************************************************************* + const transition* const transition_table_end() const + { + return transition_table_begin + transition_table_size; + } + + //************************************************************************* + const state* const state_table_end() const + { + return state_table_begin + state_table_size; + } + //************************************************************************* struct is_transition { is_transition(event_id_t event_id_, state_id_t state_id_) - : event_id(event_id_), - state_id(state_id_) + : event_id(event_id_) + , state_id(state_id_) { } @@ -393,96 +848,30 @@ namespace etl state_chart(const state_chart&) ETL_DELETE; state_chart& operator =(const state_chart&) ETL_DELETE; - TObject& object; ///< The object that supplies guard and action member functions. - const etl::array_view transition_table; ///< The table of transitions. - etl::array_view state_table; ///< The table of states. - bool started; ///< Set if the state chart has been started. + TObject& object; ///< The object that supplies guard and action member functions. + const transition* transition_table_begin; ///< The start of the table of transitions. + const state* state_table_begin; ///< The start of the table of states. + uint_least8_t transition_table_size; ///< The size of the table of transitions. + uint_least8_t state_table_size; ///< The size of the table of states. + state_id_t current_state_id; ///< The current state id. + bool started; ///< Set if the state chart has been started. }; //*************************************************************************** /// Simple Finite State Machine + /// Runtime tables. + /// Event has no parameter. //*************************************************************************** template - class state_chart : public istate_chart + class state_chart : public istate_chart { public: - //************************************************************************* - /// Transition definition - //************************************************************************* - struct transition - { - ETL_CONSTEXPR transition(const state_id_t current_state_id_, - const event_id_t event_id_, - const state_id_t next_state_id_, - void (TObject::* const action_)() = ETL_NULLPTR, - bool (TObject::* const guard_)() = ETL_NULLPTR) - : from_any_state(false), - current_state_id(current_state_id_), - event_id(event_id_), - next_state_id(next_state_id_), - action(action_), - guard(guard_) - { - } - - ETL_CONSTEXPR transition(const event_id_t event_id_, - const state_id_t next_state_id_, - void (TObject::* const action_)() = ETL_NULLPTR, - bool (TObject::* const guard_)() = ETL_NULLPTR) - : from_any_state(true), - current_state_id(0), - event_id(event_id_), - next_state_id(next_state_id_), - action(action_), - guard(guard_) - { - } - - const bool from_any_state; - const state_id_t current_state_id; - const event_id_t event_id; - const state_id_t next_state_id; - void (TObject::* const action)(); - bool (TObject::* const guard)(); - }; - - //************************************************************************* - /// State definition - //************************************************************************* - struct state - { - ETL_CONSTEXPR state(const state_id_t state_id_, - void (TObject::* const on_entry_)() = ETL_NULLPTR, - void (TObject::* const on_exit_)() = ETL_NULLPTR) - : state_id(state_id_), - on_entry(on_entry_), - on_exit(on_exit_) - { - } - - state_id_t state_id; - void (TObject::* const on_entry)(); - void (TObject::* const on_exit)(); - }; - - //************************************************************************* - /// Constructor. - /// \param object_ A reference to the implementation object. - /// \param transition_table_begin_ The start of the table of transitions. - /// \param transition_table_end_ The end of the table of transitions. - /// \param state_id_ The initial state id. - //************************************************************************* - ETL_CONSTEXPR state_chart(TObject& object_, - const transition* transition_table_begin_, - const transition* transition_table_end_, - const state_id_t state_id_) - : istate_chart(state_id_), - object(object_), - transition_table(transition_table_begin_, transition_table_end_), - started(false) - { - } + typedef void parameter_t; + typedef state_chart_traits::state_id_t state_id_t; + typedef state_chart_traits::event_id_t event_id_t; + typedef state_chart_traits::transition transition; + typedef state_chart_traits::state state; //************************************************************************* /// Constructor. @@ -493,17 +882,19 @@ namespace etl /// \param state_table_end_ The end of the state table. /// \param state_id_ The initial state id. //************************************************************************* - ETL_CONSTEXPR state_chart(TObject& object_, + ETL_CONSTEXPR state_chart(TObject& object_, const transition* transition_table_begin_, const transition* transition_table_end_, - const state* state_table_begin_, - const state* state_table_end_, - const state_id_t state_id_) - : istate_chart(state_id_), - object(object_), - transition_table(transition_table_begin_, transition_table_end_), - state_table(state_table_begin_, state_table_end_), - started(false) + const state* state_table_begin_, + const state* state_table_end_, + const state_id_t state_id_) + : object(object_) + , transition_table_begin(transition_table_begin_) + , state_table_begin(state_table_begin_) + , transition_table_size(transition_table_end_ - transition_table_begin_) + , state_table_size(state_table_end_ - state_table_begin_) + , current_state_id(state_id_) + , started(false) { } @@ -515,7 +906,8 @@ namespace etl void set_transition_table(const transition* transition_table_begin_, const transition* transition_table_end_) { - transition_table.assign(transition_table_begin_, transition_table_end_); + transition_table_begin = transition_table_begin_; + transition_table_size = transition_table_end_ - transition_table_begin_; } //************************************************************************* @@ -526,7 +918,8 @@ namespace etl void set_state_table(const state* state_table_begin_, const state* state_table_end_) { - state_table.assign(state_table_begin_, state_table_end_); + state_table_begin = state_table_begin_; + state_table_size = state_table_end_ - state_table_begin_; } //************************************************************************* @@ -553,22 +946,20 @@ namespace etl //************************************************************************* const state* find_state(state_id_t state_id) { - if (state_table.empty()) + if (state_table_begin == ETL_NULLPTR) { - return state_table.end(); + return state_table_end(); } else { - return etl::find_if(state_table.begin(), - state_table.end(), - is_state(state_id)); + return etl::find_if(state_table_begin, state_table_end(), is_state(state_id)); } } //************************************************************************* - /// + /// Start the state chart. //************************************************************************* - virtual void start(const bool on_entry_initial = true) ETL_OVERRIDE + void start(const bool on_entry_initial = true) { if (!started) { @@ -578,7 +969,7 @@ namespace etl const state* s = find_state(current_state_id); // If the initial state has an 'on_entry' then call it. - if ((s != state_table.end()) && (s->on_entry != ETL_NULLPTR)) + if ((s != state_table_end()) && (s->on_entry != ETL_NULLPTR)) { (object.*(s->on_entry))(); } @@ -594,22 +985,20 @@ namespace etl /// that satisfies the conditions for executing the action. /// \param event_id The id of the event to process. //************************************************************************* - virtual void process_event(const event_id_t event_id) ETL_OVERRIDE + void process_event(event_id_t event_id) { if (started) { - const transition* t = transition_table.begin(); + const transition* t = transition_table_begin; // Keep looping until we execute a transition or reach the end of the table. - while (t != transition_table.end()) + while (t != transition_table_end()) { // Scan the transition table from the latest position. - t = etl::find_if(t, - transition_table.end(), - is_transition(event_id, current_state_id)); + t = etl::find_if(t, transition_table_end(), is_transition(event_id, current_state_id)); // Found an entry? - if (t != transition_table.end()) + if (t != transition_table_end()) { // Shall we execute the transition? if ((t->guard == ETL_NULLPTR) || ((object.*t->guard)())) @@ -629,7 +1018,7 @@ namespace etl s = find_state(current_state_id); // If the current state has an 'on_exit' then call it. - if ((s != state_table.end()) && (s->on_exit != ETL_NULLPTR)) + if ((s != state_table_end()) && (s->on_exit != ETL_NULLPTR)) { (object.*(s->on_exit))(); } @@ -640,13 +1029,13 @@ namespace etl s = find_state(current_state_id); // If the new state has an 'on_entry' then call it. - if ((s != state_table.end()) && (s->on_entry != ETL_NULLPTR)) + if ((s != state_table_end()) && (s->on_entry != ETL_NULLPTR)) { (object.*(s->on_entry))(); } } - t = transition_table.end(); + t = transition_table_end(); } else { @@ -658,14 +1047,35 @@ namespace etl } } + //************************************************************************* + /// Gets the current state id. + /// \return The current state id. + //************************************************************************* + state_id_t get_state_id() const + { + return current_state_id; + } + private: + //************************************************************************* + const transition* const transition_table_end() const + { + return transition_table_begin + transition_table_size; + } + + //************************************************************************* + const state* const state_table_end() const + { + return state_table_begin + state_table_size; + } + //************************************************************************* struct is_transition { is_transition(event_id_t event_id_, state_id_t state_id_) - : event_id(event_id_), - state_id(state_id_) + : event_id(event_id_) + , state_id(state_id_) { } @@ -698,10 +1108,13 @@ namespace etl state_chart(const state_chart&) ETL_DELETE; state_chart& operator =(const state_chart&) ETL_DELETE; - TObject& object; ///< The object that supplies guard and action member functions. - const etl::array_view transition_table; ///< The table of transitions. - etl::array_view state_table; ///< The table of states. - bool started; ///< Set if the state chart has been started. + TObject& object; ///< The object that supplies guard and action member functions. + const transition* transition_table_begin; ///< The start of the table of transitions. + const state* state_table_begin; ///< The start of the table of states. + uint_least8_t transition_table_size; ///< The size of the table of transitions. + uint_least8_t state_table_size; ///< The size of the table of states. + state_id_t current_state_id; ///< The current state id. + bool started; ///< Set if the state chart has been started. }; } diff --git a/library.properties b/library.properties index 18a2bd75..924c3798 100644 --- a/library.properties +++ b/library.properties @@ -1,4 +1,4 @@ -name=Embedded Template Library ETL +name=Embedded Template Library version=20.23.0 author= John Wellbelove maintainer=John Wellbelove diff --git a/support/Release notes.txt b/support/Release notes.txt index 0f5b211d..01f08ede 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,15 +1,21 @@ =============================================================================== 20.23.0 +Recoded state_chart to reduce its resource requirements. +Added compile time state chart variants. Added etl::unaligned_type for fundamental types. Added reverse engineered functionality from C++20 . +Added all permutations of leading/trailing bit tests. +Changed inline functions to templates in binary.h. Added etl::midpoint and etl::lerp Recoded etl::endian & etl::endianness to allow constexpr in certain configurations. +Updates and fixes to etl::bitset. Added to_ulong, to_ullong, to_string member functions. Moved void_t definition. Renamed 8bit check macro. Updated tests to support C++20 STL. Modified C++ language level detection. Added all permutations of leading/trailing bit tests. etl::iterator is more SFINAE compatible. +Updated C++ standard detection. =============================================================================== 20.22.0 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f8a755c8..ca5cc316 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -224,6 +224,8 @@ set(TEST_SOURCE_FILES test_state_chart.cpp test_state_chart_with_data_parameter.cpp test_state_chart_with_rvalue_data_parameter.cpp + test_state_chart_compile_time.cpp + test_state_chart_compile_time_with_data_parameter.cpp test_string_char.cpp test_string_char_external_buffer.cpp test_string_stream.cpp @@ -255,7 +257,7 @@ set(TEST_SOURCE_FILES test_type_lookup.cpp test_type_select.cpp test_type_traits.cpp -# test_unaligned_type.cpp + test_unaligned_type.cpp test_unordered_map.cpp test_unordered_multimap.cpp test_unordered_multiset.cpp diff --git a/test/etl_profile.h b/test/etl_profile.h index 59c42a15..230a65db 100644 --- a/test/etl_profile.h +++ b/test/etl_profile.h @@ -73,12 +73,6 @@ SOFTWARE. #define ETL_POLYMORPHIC_VECTOR #define ETL_POLYMORPHIC_INDIRECT_VECTOR -#if defined(ETL_CPP20_ENABLED) - #define ETL_CPP20_SUPPORTED 1 -#else - #define ETL_CPP20_SUPPORTED 0 -#endif - //#define ETL_POLYMORPHIC_CONTAINERS //#define ETL_MESSAGES_ARE_VIRTUAL diff --git a/test/test_state_chart.cpp b/test/test_state_chart.cpp index 821b921f..80a9c21a 100644 --- a/test/test_state_chart.cpp +++ b/test/test_state_chart.cpp @@ -51,7 +51,7 @@ namespace ABORT }; - ETL_DECLARE_ENUM_TYPE(EventId, etl::istate_chart::event_id_t) + ETL_DECLARE_ENUM_TYPE(EventId, etl::state_chart_traits::event_id_t) ETL_ENUM_TYPE(START, "Start") ETL_ENUM_TYPE(STOP, "Stop") ETL_ENUM_TYPE(EMERGENCY_STOP, "Emergency Stop") @@ -73,7 +73,7 @@ namespace NUMBER_OF_STATES }; - ETL_DECLARE_ENUM_TYPE(StateId, etl::istate_chart::state_id_t) + ETL_DECLARE_ENUM_TYPE(StateId, etl::state_chart_traits::state_id_t) ETL_ENUM_TYPE(IDLE, "Idle") ETL_ENUM_TYPE(RUNNING, "Running") ETL_ENUM_TYPE(WINDING_DOWN, "Winding Down") @@ -88,9 +88,8 @@ namespace public: MotorControl() - : state_chart(*this, transitionTable.begin(), transitionTable.end(), StateId::IDLE) + : etl::state_chart(*this, transitionTable.begin(), transitionTable.end(), stateTable.begin(), stateTable.end(), StateId::IDLE) { - this->set_state_table(stateTable.begin(), stateTable.end()); ClearStatistics(); } @@ -398,6 +397,143 @@ namespace CHECK_EQUAL(1, motorControl.null); } + //************************************************************************* + //TEST(test_state_chart_with_delegate) + //{ + // motorControl.ClearStatistics(); + + // auto process_event = motorControl.get_process_event_delegate(); + + // // Start the state chart + // motorControl.guard = true; + // motorControl.start(); + + // // Send unhandled events. + // process_event(EventId::STOP); + // process_event(EventId::STOPPED); + + // CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id())); + + // CHECK_EQUAL(false, motorControl.isLampOn); + // CHECK_EQUAL(0, motorControl.setSpeedCount); + // CHECK_EQUAL(0, motorControl.speed); + // CHECK_EQUAL(0, motorControl.startCount); + // CHECK_EQUAL(0, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(0, motorControl.windingDown); + + // // Send Start event. + // motorControl.guard = false; + // process_event(EventId::START); + + // // Still in Idle state. + + // CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id())); + + // CHECK_EQUAL(false, motorControl.isLampOn); + // CHECK_EQUAL(0, motorControl.setSpeedCount); + // CHECK_EQUAL(0, motorControl.speed); + // CHECK_EQUAL(0, motorControl.startCount); + // CHECK_EQUAL(0, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(0, motorControl.windingDown); + // CHECK_EQUAL(1, motorControl.null); + + // // Send Start event. + // motorControl.guard = true; + // process_event(EventId::START); + + // // Now in Running state. + + // CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state_id())); + + // CHECK_EQUAL(true, motorControl.isLampOn); + // CHECK_EQUAL(0, motorControl.setSpeedCount); + // CHECK_EQUAL(0, motorControl.speed); + // CHECK_EQUAL(1, motorControl.startCount); + // CHECK_EQUAL(0, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(0, motorControl.windingDown); + // CHECK_EQUAL(1, motorControl.null); + + // // Send unhandled events. + // process_event(EventId::START); + // process_event(EventId::STOPPED); + + // CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state_id())); + + // CHECK_EQUAL(true, motorControl.isLampOn); + // CHECK_EQUAL(0, motorControl.setSpeedCount); + // CHECK_EQUAL(0, motorControl.speed); + // CHECK_EQUAL(1, motorControl.startCount); + // CHECK_EQUAL(0, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(0, motorControl.windingDown); + // CHECK_EQUAL(1, motorControl.null); + + // // Send SetSpeed event. + // process_event(EventId::SET_SPEED); + + // // Still in Running state. + + // CHECK_EQUAL(StateId::RUNNING, int(motorControl.get_state_id())); + + // CHECK_EQUAL(true, motorControl.isLampOn); + // CHECK_EQUAL(1, motorControl.setSpeedCount); + // CHECK_EQUAL(100, motorControl.speed); + // CHECK_EQUAL(1, motorControl.startCount); + // CHECK_EQUAL(0, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(0, motorControl.windingDown); + // CHECK_EQUAL(1, motorControl.null); + + // // Send Stop event. + // process_event(EventId::STOP); + + // // Now in WindingDown state. + + // CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControl.get_state_id())); + + // CHECK_EQUAL(true, motorControl.isLampOn); + // CHECK_EQUAL(1, motorControl.setSpeedCount); + // CHECK_EQUAL(100, motorControl.speed); + // CHECK_EQUAL(1, motorControl.startCount); + // CHECK_EQUAL(1, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(1, motorControl.windingDown); + // CHECK_EQUAL(1, motorControl.null); + + // // Send unhandled events. + // process_event(EventId::START); + // process_event(EventId::STOP); + + // CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControl.get_state_id())); + + // CHECK_EQUAL(true, motorControl.isLampOn); + // CHECK_EQUAL(1, motorControl.setSpeedCount); + // CHECK_EQUAL(100, motorControl.speed); + // CHECK_EQUAL(1, motorControl.startCount); + // CHECK_EQUAL(1, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(1, motorControl.windingDown); + // CHECK_EQUAL(1, motorControl.null); + + // // Send Stopped event. + // process_event(EventId::STOPPED); + + // // Now in Idle state. + // CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id())); + + // CHECK_EQUAL(false, motorControl.isLampOn); + // CHECK_EQUAL(1, motorControl.setSpeedCount); + // CHECK_EQUAL(100, motorControl.speed); + // CHECK_EQUAL(1, motorControl.startCount); + // CHECK_EQUAL(1, motorControl.stopCount); + // CHECK_EQUAL(1, motorControl.stoppedCount); + // CHECK_EQUAL(0, motorControl.windingDown); + // CHECK_EQUAL(1, motorControl.null); + //} + //************************************************************************* TEST(test_fsm_emergency_stop) { @@ -447,6 +583,7 @@ namespace // Now in Running state. + // Send abort event. motorControl.process_event(EventId::ABORT); CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id())); diff --git a/test/test_state_chart_compile_time.cpp b/test/test_state_chart_compile_time.cpp new file mode 100644 index 00000000..10010efd --- /dev/null +++ b/test/test_state_chart_compile_time.cpp @@ -0,0 +1,612 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2018 jwellbelove + +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 "unit_test_framework.h" + +#include "etl/state_chart.h" +#include "etl/enum_type.h" +#include "etl/queue.h" +#include "etl/array.h" + +#include +#include + +namespace +{ + //*************************************************************************** + // Events + struct EventId + { + enum enum_type + { + START, + STOP, + EMERGENCY_STOP, + STOPPED, + SET_SPEED, + ABORT + }; + + ETL_DECLARE_ENUM_TYPE(EventId, etl::state_chart_traits::event_id_t) + ETL_ENUM_TYPE(START, "Start") + ETL_ENUM_TYPE(STOP, "Stop") + ETL_ENUM_TYPE(EMERGENCY_STOP, "Emergency Stop") + ETL_ENUM_TYPE(STOPPED, "Stopped") + ETL_ENUM_TYPE(SET_SPEED, "Set Speed") + ETL_ENUM_TYPE(ABORT, "Abort") + ETL_END_ENUM_TYPE + }; + + //*************************************************************************** + // States + struct StateId + { + enum enum_type + { + IDLE, + RUNNING, + WINDING_DOWN, + NUMBER_OF_STATES + }; + + ETL_DECLARE_ENUM_TYPE(StateId, etl::state_chart_traits::state_id_t) + ETL_ENUM_TYPE(IDLE, "Idle") + ETL_ENUM_TYPE(RUNNING, "Running") + ETL_ENUM_TYPE(WINDING_DOWN, "Winding Down") + ETL_END_ENUM_TYPE + }; + + //*********************************** + // The motor control FSM. + //*********************************** + class MotorControl + { + public: + + MotorControl() + { + ClearStatistics(); + } + + //*********************************** + void ClearStatistics() + { + startCount = 0; + stopCount = 0; + setSpeedCount = 0; + stoppedCount = 0; + isLampOn = false; + speed = 0; + windingDown = 0; + entered_idle = false; + null = 0; + } + + //*********************************** + void OnStart() + { + ++startCount; + } + + //*********************************** + void OnStop() + { + ++stopCount; + } + + //*********************************** + void OnStopped() + { + ++stoppedCount; + } + + //*********************************** + void OnSetSpeed() + { + ++setSpeedCount; + SetSpeedValue(100); + } + + //*********************************** + void OnEnterIdle() + { + TurnRunningLampOff(); + entered_idle = true; + } + + //*********************************** + void OnEnterRunning() + { + TurnRunningLampOn(); + } + + //*********************************** + void OnEnterWindingDown() + { + ++windingDown; + } + + //*********************************** + void OnExitWindingDown() + { + --windingDown; + } + + //*********************************** + void SetSpeedValue(int speed_) + { + speed = speed_; + } + + //*********************************** + bool Guard() + { + return guard; + } + + //*********************************** + bool NotGuard() + { + return !guard; + } + + //*********************************** + void TurnRunningLampOn() + { + isLampOn = true; + } + + //*********************************** + void TurnRunningLampOff() + { + isLampOn = false; + } + + //*********************************** + void Null() + { + ++null; + } + + int startCount; + int stopCount; + int setSpeedCount; + int stoppedCount; + bool isLampOn; + int speed; + int windingDown; + bool entered_idle; + int null; + + bool guard; + }; + + //*************************************************************************** + using transition = etl::state_chart_traits::transition; + + constexpr transition transitionTable[7] = + { + transition(StateId::IDLE, EventId::START, StateId::RUNNING, &MotorControl::OnStart, &MotorControl::Guard), + transition(StateId::IDLE, EventId::START, StateId::IDLE, &MotorControl::Null, &MotorControl::NotGuard), + transition(StateId::RUNNING, EventId::STOP, StateId::WINDING_DOWN, &MotorControl::OnStop), + transition(StateId::RUNNING, EventId::EMERGENCY_STOP, StateId::IDLE, &MotorControl::OnStop), + transition(StateId::RUNNING, EventId::SET_SPEED, StateId::RUNNING, &MotorControl::OnSetSpeed), + transition(StateId::WINDING_DOWN, EventId::STOPPED, StateId::IDLE, &MotorControl::OnStopped), + transition( EventId::ABORT, StateId::IDLE) + }; + + //*************************************************************************** + using state = etl::state_chart_traits::state; + + constexpr state stateTable[3] = + { + state(StateId::IDLE, &MotorControl::OnEnterIdle, nullptr), + state(StateId::RUNNING, &MotorControl::OnEnterRunning, nullptr), + state(StateId::WINDING_DOWN, &MotorControl::OnEnterWindingDown, &MotorControl::OnExitWindingDown) + }; + + MotorControl motorControl; + + etl::state_chart_ct motorControlStateChart; + + SUITE(test_state_chart_compile_time) + { + //************************************************************************* + TEST(test_state_chart) + { + motorControl.ClearStatistics(); + + // In Idle state. + CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(false, motorControl.isLampOn); + CHECK_EQUAL(0, motorControl.setSpeedCount); + CHECK_EQUAL(0, motorControl.speed); + CHECK_EQUAL(0, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + CHECK_EQUAL(false, motorControl.entered_idle); + + // Send Start event (state chart not started). + motorControl.guard = true; + motorControlStateChart.process_event(EventId::START); + + CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(false, motorControl.isLampOn); + CHECK_EQUAL(0, motorControl.setSpeedCount); + CHECK_EQUAL(0, motorControl.speed); + CHECK_EQUAL(0, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + CHECK_EQUAL(false, motorControl.entered_idle); + + // Start the state chart + motorControl.guard = true; + motorControlStateChart.start(); + + CHECK_EQUAL(true, motorControl.entered_idle); + + // Send unhandled events. + motorControlStateChart.process_event(EventId::STOP); + motorControlStateChart.process_event(EventId::STOPPED); + + CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(false, motorControl.isLampOn); + CHECK_EQUAL(0, motorControl.setSpeedCount); + CHECK_EQUAL(0, motorControl.speed); + CHECK_EQUAL(0, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + + // Send Start event. + motorControl.guard = false; + motorControlStateChart.process_event(EventId::START); + + // Still in Idle state. + + CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(false, motorControl.isLampOn); + CHECK_EQUAL(0, motorControl.setSpeedCount); + CHECK_EQUAL(0, motorControl.speed); + CHECK_EQUAL(0, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + CHECK_EQUAL(1, motorControl.null); + + // Send Start event. + motorControl.guard = true; + motorControlStateChart.process_event(EventId::START); + + // Now in Running state. + + CHECK_EQUAL(StateId::RUNNING, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(true, motorControl.isLampOn); + CHECK_EQUAL(0, motorControl.setSpeedCount); + CHECK_EQUAL(0, motorControl.speed); + CHECK_EQUAL(1, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + CHECK_EQUAL(1, motorControl.null); + + // Send unhandled events. + motorControlStateChart.process_event(EventId::START); + motorControlStateChart.process_event(EventId::STOPPED); + + CHECK_EQUAL(StateId::RUNNING, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(true, motorControl.isLampOn); + CHECK_EQUAL(0, motorControl.setSpeedCount); + CHECK_EQUAL(0, motorControl.speed); + CHECK_EQUAL(1, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + CHECK_EQUAL(1, motorControl.null); + + // Send SetSpeed event. + motorControlStateChart.process_event(EventId::SET_SPEED); + + // Still in Running state. + + CHECK_EQUAL(StateId::RUNNING, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(true, motorControl.isLampOn); + CHECK_EQUAL(1, motorControl.setSpeedCount); + CHECK_EQUAL(100, motorControl.speed); + CHECK_EQUAL(1, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + CHECK_EQUAL(1, motorControl.null); + + // Send Stop event. + motorControlStateChart.process_event(EventId::STOP); + + // Now in WindingDown state. + + CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(true, motorControl.isLampOn); + CHECK_EQUAL(1, motorControl.setSpeedCount); + CHECK_EQUAL(100, motorControl.speed); + CHECK_EQUAL(1, motorControl.startCount); + CHECK_EQUAL(1, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(1, motorControl.windingDown); + CHECK_EQUAL(1, motorControl.null); + + // Send unhandled events. + motorControlStateChart.process_event(EventId::START); + motorControlStateChart.process_event(EventId::STOP); + + CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(true, motorControl.isLampOn); + CHECK_EQUAL(1, motorControl.setSpeedCount); + CHECK_EQUAL(100, motorControl.speed); + CHECK_EQUAL(1, motorControl.startCount); + CHECK_EQUAL(1, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(1, motorControl.windingDown); + CHECK_EQUAL(1, motorControl.null); + + // Send Stopped event. + motorControlStateChart.process_event(EventId::STOPPED); + + // Now in Idle state. + CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(false, motorControl.isLampOn); + CHECK_EQUAL(1, motorControl.setSpeedCount); + CHECK_EQUAL(100, motorControl.speed); + CHECK_EQUAL(1, motorControl.startCount); + CHECK_EQUAL(1, motorControl.stopCount); + CHECK_EQUAL(1, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + CHECK_EQUAL(1, motorControl.null); + } + + //************************************************************************* + //TEST(test_state_chart_with_delegate) + //{ + // motorControl.ClearStatistics(); + + // auto process_event = motorControlStateChart.get_process_event_delegate(); + + // // Start the state chart + // motorControl.guard = true; + // motorControlStateChart.start(); + + // // Send unhandled events. + // process_event(EventId::STOP); + // process_event(EventId::STOPPED); + + // CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + // CHECK_EQUAL(false, motorControl.isLampOn); + // CHECK_EQUAL(0, motorControl.setSpeedCount); + // CHECK_EQUAL(0, motorControl.speed); + // CHECK_EQUAL(0, motorControl.startCount); + // CHECK_EQUAL(0, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(0, motorControl.windingDown); + + // // Send Start event. + // motorControl.guard = false; + // process_event(EventId::START); + + // // Still in Idle state. + + // CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + // CHECK_EQUAL(false, motorControl.isLampOn); + // CHECK_EQUAL(0, motorControl.setSpeedCount); + // CHECK_EQUAL(0, motorControl.speed); + // CHECK_EQUAL(0, motorControl.startCount); + // CHECK_EQUAL(0, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(0, motorControl.windingDown); + // CHECK_EQUAL(1, motorControl.null); + + // // Send Start event. + // motorControl.guard = true; + // process_event(EventId::START); + + // // Now in Running state. + + // CHECK_EQUAL(StateId::RUNNING, int(motorControlStateChart.get_state_id())); + + // CHECK_EQUAL(true, motorControl.isLampOn); + // CHECK_EQUAL(0, motorControl.setSpeedCount); + // CHECK_EQUAL(0, motorControl.speed); + // CHECK_EQUAL(1, motorControl.startCount); + // CHECK_EQUAL(0, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(0, motorControl.windingDown); + // CHECK_EQUAL(1, motorControl.null); + + // // Send unhandled events. + // process_event(EventId::START); + // process_event(EventId::STOPPED); + + // CHECK_EQUAL(StateId::RUNNING, int(motorControlStateChart.get_state_id())); + + // CHECK_EQUAL(true, motorControl.isLampOn); + // CHECK_EQUAL(0, motorControl.setSpeedCount); + // CHECK_EQUAL(0, motorControl.speed); + // CHECK_EQUAL(1, motorControl.startCount); + // CHECK_EQUAL(0, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(0, motorControl.windingDown); + // CHECK_EQUAL(1, motorControl.null); + + // // Send SetSpeed event. + // process_event(EventId::SET_SPEED); + + // // Still in Running state. + + // CHECK_EQUAL(StateId::RUNNING, int(motorControlStateChart.get_state_id())); + + // CHECK_EQUAL(true, motorControl.isLampOn); + // CHECK_EQUAL(1, motorControl.setSpeedCount); + // CHECK_EQUAL(100, motorControl.speed); + // CHECK_EQUAL(1, motorControl.startCount); + // CHECK_EQUAL(0, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(0, motorControl.windingDown); + // CHECK_EQUAL(1, motorControl.null); + + // // Send Stop event. + // process_event(EventId::STOP); + + // // Now in WindingDown state. + + // CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControlStateChart.get_state_id())); + + // CHECK_EQUAL(true, motorControl.isLampOn); + // CHECK_EQUAL(1, motorControl.setSpeedCount); + // CHECK_EQUAL(100, motorControl.speed); + // CHECK_EQUAL(1, motorControl.startCount); + // CHECK_EQUAL(1, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(1, motorControl.windingDown); + // CHECK_EQUAL(1, motorControl.null); + + // // Send unhandled events. + // process_event(EventId::START); + // process_event(EventId::STOP); + + // CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControlStateChart.get_state_id())); + + // CHECK_EQUAL(true, motorControl.isLampOn); + // CHECK_EQUAL(1, motorControl.setSpeedCount); + // CHECK_EQUAL(100, motorControl.speed); + // CHECK_EQUAL(1, motorControl.startCount); + // CHECK_EQUAL(1, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(1, motorControl.windingDown); + // CHECK_EQUAL(1, motorControl.null); + + // // Send Stopped event. + // process_event(EventId::STOPPED); + + // // Now in Idle state. + // CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + // CHECK_EQUAL(false, motorControl.isLampOn); + // CHECK_EQUAL(1, motorControl.setSpeedCount); + // CHECK_EQUAL(100, motorControl.speed); + // CHECK_EQUAL(1, motorControl.startCount); + // CHECK_EQUAL(1, motorControl.stopCount); + // CHECK_EQUAL(1, motorControl.stoppedCount); + // CHECK_EQUAL(0, motorControl.windingDown); + // CHECK_EQUAL(1, motorControl.null); + //} + + ////************************************************************************* + //TEST(test_fsm_emergency_stop) + //{ + // motorControl.ClearStatistics(); + + // // Now in Idle state. + + // // Send Start event. + // motorControlStateChart.process_event(EventId::START); + + // // Now in Running state. + + // CHECK_EQUAL(StateId::RUNNING, int(motorControlStateChart.get_state_id())); + + // CHECK_EQUAL(true, motorControl.isLampOn); + // CHECK_EQUAL(0, motorControl.setSpeedCount); + // CHECK_EQUAL(0, motorControl.speed); + // CHECK_EQUAL(1, motorControl.startCount); + // CHECK_EQUAL(0, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(0, motorControl.windingDown); + + // // Send emergency Stop event. + // motorControlStateChart.process_event(EventId::EMERGENCY_STOP); + + // // Now in Idle state. + // CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + // CHECK_EQUAL(false, motorControl.isLampOn); + // CHECK_EQUAL(0, motorControl.setSpeedCount); + // CHECK_EQUAL(0, motorControl.speed); + // CHECK_EQUAL(1, motorControl.startCount); + // CHECK_EQUAL(1, motorControl.stopCount); + // CHECK_EQUAL(0, motorControl.stoppedCount); + // CHECK_EQUAL(0, motorControl.windingDown); + //} + + //************************************************************************* + TEST(test_fsm_abort) + { + motorControl.ClearStatistics(); + + // Now in Idle state. + + // Send Start event. + motorControlStateChart.process_event(EventId::START); + + // Now in Running state. + + // Send abort event. + motorControlStateChart.process_event(EventId::ABORT); + CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + // Send Start event. + motorControlStateChart.process_event(EventId::START); + + // Now in Running state. + + // Send Stop event. + motorControlStateChart.process_event(EventId::STOP); + + // Now in WindingDown state. + motorControlStateChart.process_event(EventId::ABORT); + CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + } + }; +} diff --git a/test/test_state_chart_compile_time_with_data_parameter.cpp b/test/test_state_chart_compile_time_with_data_parameter.cpp new file mode 100644 index 00000000..b993d615 --- /dev/null +++ b/test/test_state_chart_compile_time_with_data_parameter.cpp @@ -0,0 +1,508 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2018 jwellbelove + +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 "unit_test_framework.h" + +#include "etl/state_chart.h" +#include "etl/enum_type.h" +#include "etl/queue.h" +#include "etl/array.h" + +#include + +namespace +{ + //*************************************************************************** + // Events + struct EventId + { + enum enum_type + { + START, + STOP, + EMERGENCY_STOP, + STOPPED, + SET_SPEED, + ABORT + }; + + ETL_DECLARE_ENUM_TYPE(EventId, etl::state_chart_traits::event_id_t) + ETL_ENUM_TYPE(START, "Start") + ETL_ENUM_TYPE(STOP, "Stop") + ETL_ENUM_TYPE(EMERGENCY_STOP, "Emergency Stop") + ETL_ENUM_TYPE(STOPPED, "Stopped") + ETL_ENUM_TYPE(SET_SPEED, "Set Speed") + ETL_ENUM_TYPE(ABORT, "Abort") + ETL_END_ENUM_TYPE + }; + + //*************************************************************************** + // States + struct StateId + { + enum enum_type + { + IDLE, + RUNNING, + WINDING_DOWN, + NUMBER_OF_STATES + }; + + ETL_DECLARE_ENUM_TYPE(StateId, etl::state_chart_traits::state_id_t) + ETL_ENUM_TYPE(IDLE, "Idle") + ETL_ENUM_TYPE(RUNNING, "Running") + ETL_ENUM_TYPE(WINDING_DOWN, "Winding Down") + ETL_END_ENUM_TYPE + }; + + //*********************************** + // The motor control FSM. + //*********************************** + class MotorControl + { + public: + + MotorControl() + { + ClearStatistics(); + } + + //*********************************** + void ClearStatistics() + { + startCount = 0; + stopCount = 0; + setSpeedCount = 0; + stoppedCount = 0; + isLampOn = false; + speed = 0; + windingDown = 0; + entered_idle = false; + null = 0; + data = 0; + } + + //*********************************** + void OnStart(int d) + { + data = d; + ++startCount; + } + + //*********************************** + void OnStop(int d) + { + data = d; + ++stopCount; + } + + //*********************************** + void OnStopped(int d) + { + data = d; + ++stoppedCount; + } + + //*********************************** + void OnSetSpeed(int d) + { + data = d; + ++setSpeedCount; + SetSpeedValue(100); + } + + //*********************************** + void OnEnterIdle() + { + TurnRunningLampOff(); + entered_idle = true; + } + + //*********************************** + void OnEnterRunning() + { + TurnRunningLampOn(); + } + + //*********************************** + void OnEnterWindingDown() + { + ++windingDown; + } + + //*********************************** + void OnExitWindingDown() + { + --windingDown; + } + + //*********************************** + void SetSpeedValue(int speed_) + { + speed = speed_; + } + + //*********************************** + bool Guard() + { + return guard; + } + + //*********************************** + bool NotGuard() + { + return !guard; + } + + //*********************************** + void TurnRunningLampOn() + { + isLampOn = true; + } + + //*********************************** + void TurnRunningLampOff() + { + isLampOn = false; + } + + //*********************************** + void Null(int d) + { + data = d; + ++null; + } + + int startCount; + int stopCount; + int setSpeedCount; + int stoppedCount; + bool isLampOn; + int speed; + int windingDown; + bool entered_idle; + int null; + int data; + + bool guard; + }; + + //*************************************************************************** + using transition = etl::state_chart_traits::transition; + + constexpr transition transitionTable[7] = + { + transition(StateId::IDLE, EventId::START, StateId::RUNNING, &MotorControl::OnStart, &MotorControl::Guard), + transition(StateId::IDLE, EventId::START, StateId::IDLE, &MotorControl::Null, &MotorControl::NotGuard), + transition(StateId::RUNNING, EventId::STOP, StateId::WINDING_DOWN, &MotorControl::OnStop), + transition(StateId::RUNNING, EventId::EMERGENCY_STOP, StateId::IDLE, &MotorControl::OnStop), + transition(StateId::RUNNING, EventId::SET_SPEED, StateId::RUNNING, &MotorControl::OnSetSpeed), + transition(StateId::WINDING_DOWN, EventId::STOPPED, StateId::IDLE, &MotorControl::OnStopped), + transition(EventId::ABORT, StateId::IDLE) + }; + + //*************************************************************************** + using state = etl::state_chart_traits::state; + + constexpr state stateTable[3] = + { + state(StateId::IDLE, &MotorControl::OnEnterIdle, nullptr), + state(StateId::RUNNING, &MotorControl::OnEnterRunning, nullptr), + state(StateId::WINDING_DOWN, &MotorControl::OnEnterWindingDown, &MotorControl::OnExitWindingDown) + }; + + MotorControl motorControl; + + etl::state_chart_ctp motorControlStateChart; + + SUITE(test_state_chart_compile_time_with_data_parameter) + { + //************************************************************************* + TEST(test_state_chart) + { + motorControl.ClearStatistics(); + + // In Idle state. + CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(false, motorControl.isLampOn); + CHECK_EQUAL(0, motorControl.setSpeedCount); + CHECK_EQUAL(0, motorControl.speed); + CHECK_EQUAL(0, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + CHECK_EQUAL(false, motorControl.entered_idle); + + // Send Start event (state chart not started). + motorControl.guard = true; + motorControlStateChart.process_event(EventId::START, 1); + + CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(0, motorControl.data); + CHECK_EQUAL(false, motorControl.isLampOn); + CHECK_EQUAL(0, motorControl.setSpeedCount); + CHECK_EQUAL(0, motorControl.speed); + CHECK_EQUAL(0, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + CHECK_EQUAL(false, motorControl.entered_idle); + + // Start the state chart + motorControl.guard = true; + motorControlStateChart.start(); + + CHECK_EQUAL(true, motorControl.entered_idle); + + // Send unhandled events. + motorControlStateChart.process_event(EventId::STOP, 2); + motorControlStateChart.process_event(EventId::STOPPED, 3); + + CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(0, motorControl.data); + CHECK_EQUAL(false, motorControl.isLampOn); + CHECK_EQUAL(0, motorControl.setSpeedCount); + CHECK_EQUAL(0, motorControl.speed); + CHECK_EQUAL(0, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + + // Send Start event. + motorControl.guard = false; + motorControlStateChart.process_event(EventId::START, 4); + + // Still in Idle state. + + CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(4, motorControl.data); + CHECK_EQUAL(false, motorControl.isLampOn); + CHECK_EQUAL(0, motorControl.setSpeedCount); + CHECK_EQUAL(0, motorControl.speed); + CHECK_EQUAL(0, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + CHECK_EQUAL(1, motorControl.null); + + // Send Start event. + motorControl.guard = true; + motorControlStateChart.process_event(EventId::START, 5); + + // Now in Running state. + + CHECK_EQUAL(StateId::RUNNING, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(5, motorControl.data); + CHECK_EQUAL(true, motorControl.isLampOn); + CHECK_EQUAL(0, motorControl.setSpeedCount); + CHECK_EQUAL(0, motorControl.speed); + CHECK_EQUAL(1, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + CHECK_EQUAL(1, motorControl.null); + + // Send unhandled events. + motorControlStateChart.process_event(EventId::START, 6); + motorControlStateChart.process_event(EventId::STOPPED, 7); + + CHECK_EQUAL(StateId::RUNNING, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(5, motorControl.data); + CHECK_EQUAL(true, motorControl.isLampOn); + CHECK_EQUAL(0, motorControl.setSpeedCount); + CHECK_EQUAL(0, motorControl.speed); + CHECK_EQUAL(1, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + CHECK_EQUAL(1, motorControl.null); + + // Send SetSpeed event. + motorControlStateChart.process_event(EventId::SET_SPEED, 8); + + // Still in Running state. + + CHECK_EQUAL(StateId::RUNNING, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(8, motorControl.data); + CHECK_EQUAL(true, motorControl.isLampOn); + CHECK_EQUAL(1, motorControl.setSpeedCount); + CHECK_EQUAL(100, motorControl.speed); + CHECK_EQUAL(1, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + CHECK_EQUAL(1, motorControl.null); + + // Send Stop event. + motorControlStateChart.process_event(EventId::STOP, 9); + + // Now in WindingDown state. + + CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(9, motorControl.data); + CHECK_EQUAL(true, motorControl.isLampOn); + CHECK_EQUAL(1, motorControl.setSpeedCount); + CHECK_EQUAL(100, motorControl.speed); + CHECK_EQUAL(1, motorControl.startCount); + CHECK_EQUAL(1, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(1, motorControl.windingDown); + CHECK_EQUAL(1, motorControl.null); + + // Send unhandled events. + motorControlStateChart.process_event(EventId::START, 10); + motorControlStateChart.process_event(EventId::STOP, 11); + + CHECK_EQUAL(StateId::WINDING_DOWN, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(9, motorControl.data); + CHECK_EQUAL(true, motorControl.isLampOn); + CHECK_EQUAL(1, motorControl.setSpeedCount); + CHECK_EQUAL(100, motorControl.speed); + CHECK_EQUAL(1, motorControl.startCount); + CHECK_EQUAL(1, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(1, motorControl.windingDown); + CHECK_EQUAL(1, motorControl.null); + + // Send Stopped event. + motorControlStateChart.process_event(EventId::STOPPED, 12); + + // Now in Idle state. + CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(12, motorControl.data); + CHECK_EQUAL(false, motorControl.isLampOn); + CHECK_EQUAL(1, motorControl.setSpeedCount); + CHECK_EQUAL(100, motorControl.speed); + CHECK_EQUAL(1, motorControl.startCount); + CHECK_EQUAL(1, motorControl.stopCount); + CHECK_EQUAL(1, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + CHECK_EQUAL(1, motorControl.null); + } + + //************************************************************************* + TEST(test_fsm_emergency_stop) + { + motorControl.ClearStatistics(); + + // Now in Idle state. + + // Send Start event. + motorControlStateChart.process_event(EventId::START, 1); + + // Now in Running state. + + CHECK_EQUAL(StateId::RUNNING, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(1, motorControl.data); + CHECK_EQUAL(true, motorControl.isLampOn); + CHECK_EQUAL(0, motorControl.setSpeedCount); + CHECK_EQUAL(0, motorControl.speed); + CHECK_EQUAL(1, motorControl.startCount); + CHECK_EQUAL(0, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + + // Send emergency Stop event. + motorControlStateChart.process_event(EventId::EMERGENCY_STOP, 2); + + // Now in Idle state. + CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + + CHECK_EQUAL(2, motorControl.data); + CHECK_EQUAL(false, motorControl.isLampOn); + CHECK_EQUAL(0, motorControl.setSpeedCount); + CHECK_EQUAL(0, motorControl.speed); + CHECK_EQUAL(1, motorControl.startCount); + CHECK_EQUAL(1, motorControl.stopCount); + CHECK_EQUAL(0, motorControl.stoppedCount); + CHECK_EQUAL(0, motorControl.windingDown); + } + + //************************************************************************* + TEST(test_fsm_abort) + { + motorControl.ClearStatistics(); + + // Now in Idle state. + + // Send Start event. + motorControlStateChart.process_event(EventId::START, 1); + + int state = int(motorControlStateChart.get_state_id()); + int check = StateId::RUNNING; + + // Now in Running state. + + // Send abort event. + motorControlStateChart.process_event(EventId::ABORT, 2); + + state = int(motorControlStateChart.get_state_id()); + check = StateId::IDLE; + + CHECK_EQUAL(check, state); + //CHECK_EQUAL(StateId::IDLE, state); + //CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id())); + + // Send Start event. + motorControlStateChart.process_event(EventId::START, 3); + + // Now in Running state. + + state = int(motorControlStateChart.get_state_id()); + check = StateId::RUNNING; + + // Send Stop event. + motorControlStateChart.process_event(EventId::STOP, 4); + + state = int(motorControlStateChart.get_state_id()); + check = StateId::WINDING_DOWN; + + // Now in WindingDown state. + motorControlStateChart.process_event(EventId::ABORT, 5); + CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); + } + }; +} diff --git a/test/test_state_chart_with_data_parameter.cpp b/test/test_state_chart_with_data_parameter.cpp index 59857dac..9d8963ca 100644 --- a/test/test_state_chart_with_data_parameter.cpp +++ b/test/test_state_chart_with_data_parameter.cpp @@ -51,7 +51,7 @@ namespace ABORT }; - ETL_DECLARE_ENUM_TYPE(EventId, etl::istate_chart::event_id_t) + ETL_DECLARE_ENUM_TYPE(EventId, etl::state_chart_traits::event_id_t) ETL_ENUM_TYPE(START, "Start") ETL_ENUM_TYPE(STOP, "Stop") ETL_ENUM_TYPE(EMERGENCY_STOP, "Emergency Stop") @@ -73,7 +73,7 @@ namespace NUMBER_OF_STATES }; - ETL_DECLARE_ENUM_TYPE(StateId, etl::istate_chart::state_id_t) + ETL_DECLARE_ENUM_TYPE(StateId, etl::state_chart_traits::state_id_t) ETL_ENUM_TYPE(IDLE, "Idle") ETL_ENUM_TYPE(RUNNING, "Running") ETL_ENUM_TYPE(WINDING_DOWN, "Winding Down") @@ -88,9 +88,8 @@ namespace public: MotorControl() - : state_chart(*this, transitionTable.begin(), transitionTable.end(), StateId::IDLE) + : etl::state_chart(*this, transitionTable.begin(), transitionTable.end(), stateTable.begin(), stateTable.end(), StateId::IDLE) { - this->set_state_table(stateTable.begin(), stateTable.end()); ClearStatistics(); } @@ -239,7 +238,7 @@ namespace MotorControl motorControl; - SUITE(test_state_chart_class) + SUITE(test_state_chart_with_data_parameter) { //************************************************************************* TEST(test_state_chart) @@ -463,19 +462,35 @@ namespace // Send Start event. motorControl.process_event(EventId::START, 1); + int state = int(motorControl.get_state_id()); + int check = StateId::RUNNING; + // Now in Running state. + // Send abort event. motorControl.process_event(EventId::ABORT, 2); - CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id())); + + state = int(motorControl.get_state_id()); + check = StateId::IDLE; + + CHECK_EQUAL(check, state); + //CHECK_EQUAL(StateId::IDLE, state); + //CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id())); // Send Start event. motorControl.process_event(EventId::START, 3); // Now in Running state. + state = int(motorControl.get_state_id()); + check = StateId::RUNNING; + // Send Stop event. motorControl.process_event(EventId::STOP, 4); + state = int(motorControl.get_state_id()); + check = StateId::WINDING_DOWN; + // Now in WindingDown state. motorControl.process_event(EventId::ABORT, 5); CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id())); diff --git a/test/test_state_chart_with_rvalue_data_parameter.cpp b/test/test_state_chart_with_rvalue_data_parameter.cpp index f6c43b6d..4b73e3a8 100644 --- a/test/test_state_chart_with_rvalue_data_parameter.cpp +++ b/test/test_state_chart_with_rvalue_data_parameter.cpp @@ -51,7 +51,7 @@ namespace ABORT }; - ETL_DECLARE_ENUM_TYPE(EventId, etl::istate_chart::event_id_t) + ETL_DECLARE_ENUM_TYPE(EventId, etl::state_chart_traits::event_id_t) ETL_ENUM_TYPE(START, "Start") ETL_ENUM_TYPE(STOP, "Stop") ETL_ENUM_TYPE(EMERGENCY_STOP, "Emergency Stop") @@ -73,7 +73,7 @@ namespace NUMBER_OF_STATES }; - ETL_DECLARE_ENUM_TYPE(StateId, etl::istate_chart::state_id_t) + ETL_DECLARE_ENUM_TYPE(StateId, etl::state_chart_traits::state_id_t) ETL_ENUM_TYPE(IDLE, "Idle") ETL_ENUM_TYPE(RUNNING, "Running") ETL_ENUM_TYPE(WINDING_DOWN, "Winding Down") @@ -119,9 +119,8 @@ namespace public: MotorControl() - : state_chart(*this, transitionTable.begin(), transitionTable.end(), StateId::IDLE) + : state_chart(*this, transitionTable.begin(), transitionTable.end(), stateTable.begin(), stateTable.end(), StateId::IDLE) { - this->set_state_table(stateTable.begin(), stateTable.end()); ClearStatistics(); } @@ -273,7 +272,7 @@ namespace SUITE(test_state_chart_class) { //************************************************************************* - TEST(test_state_chart) + TEST(test_state_chart_with_rvalue_data_parameter) { motorControl.ClearStatistics(); @@ -496,6 +495,7 @@ namespace // Now in Running state. + // Send abort event. motorControl.process_event(EventId::ABORT, Data(2)); CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id())); diff --git a/test/test_unaligned_type.cpp b/test/test_unaligned_type.cpp index 413a4a62..2c0e4213 100644 --- a/test/test_unaligned_type.cpp +++ b/test/test_unaligned_type.cpp @@ -150,7 +150,7 @@ namespace CHECK_EQUAL(sizeof(signed char), etl::host_schar_t::Size); CHECK_EQUAL(sizeof(unsigned char), etl::host_uchar_t::Size); CHECK_EQUAL(sizeof(short), etl::host_short_t::Size); - CHECK_EQUAL(sizeof(unsigned short), etl::host_uint_t::Size); + CHECK_EQUAL(sizeof(unsigned short), etl::host_ushort_t::Size); CHECK_EQUAL(sizeof(int), etl::host_int_t::Size); CHECK_EQUAL(sizeof(unsigned int), etl::host_uint_t::Size); CHECK_EQUAL(sizeof(long), etl::host_long_t::Size); @@ -181,12 +181,12 @@ namespace CHECK(etl::le_char_t(0x01) == char(0x01)); CHECK(etl::le_schar_t(0x01) == etl::le_schar_t(0x01)); - CHECK(signed char(0x01) == etl::le_schar_t(0x01)); - CHECK(etl::le_schar_t(0x01) == signed char(0x01)); + CHECK((signed char)(0x01) == etl::le_schar_t(0x01)); + CHECK(etl::le_schar_t(0x01) == (signed char)(0x01)); CHECK(etl::le_uchar_t(0x01U) == etl::le_uchar_t(0x01U)); - CHECK(unsigned char(0x01U) == etl::le_uchar_t(0x01U)); - CHECK(etl::le_uchar_t(0x01U) == unsigned char(0x01U)); + CHECK((unsigned char)(0x01U) == etl::le_uchar_t(0x01U)); + CHECK(etl::le_uchar_t(0x01U) == (unsigned char)(0x01U)); // short CHECK(etl::le_short_t(0x0123) == etl::le_short_t(0x0123)); @@ -194,8 +194,8 @@ namespace CHECK(etl::le_short_t(0x0123) == short(0x0123)); CHECK(etl::le_ushort_t(0x0123) == etl::le_ushort_t(0x0123)); - CHECK(unsigned short(0x0123) == etl::le_ushort_t(0x0123)); - CHECK(etl::le_ushort_t(0x0123) == unsigned short(0x0123)); + CHECK((unsigned short)(0x0123) == etl::le_ushort_t(0x0123)); + CHECK(etl::le_ushort_t(0x0123) == (unsigned short)(0x0123)); // int CHECK(etl::le_int_t(0x012345678) == etl::le_int_t(0x012345678)); @@ -203,8 +203,8 @@ namespace CHECK(etl::le_int_t(0x012345678) == int(0x012345678)); CHECK(etl::le_uint_t(0x012345678U) == etl::le_uint_t(0x012345678U)); - CHECK(unsigned int(0x012345678U) == etl::le_uint_t(0x012345678U)); - CHECK(etl::le_uint_t(0x012345678U) == unsigned int(0x012345678U)); + CHECK((unsigned int)(0x012345678U) == etl::le_uint_t(0x012345678U)); + CHECK(etl::le_uint_t(0x012345678U) == (unsigned int)(0x012345678U)); if (sizeof(long) == 4U) { @@ -214,20 +214,20 @@ namespace CHECK(etl::le_long_t(0x012345678) == long(0x012345678)); CHECK(etl::le_ulong_t(0x012345678U) == etl::le_ulong_t(0x012345678U)); - CHECK(unsigned long(0x012345678U) == etl::le_ulong_t(0x012345678U)); - CHECK(etl::le_ulong_t(0x012345678U) == unsigned long(0x012345678U)); + CHECK((unsigned long)(0x012345678U) == etl::le_ulong_t(0x012345678U)); + CHECK(etl::le_ulong_t(0x012345678U) == (unsigned long)(0x012345678U)); } if (sizeof(long long) == 8U) { // long long CHECK(etl::le_long_long_t(0x0123456789ABCDEF) == etl::le_long_long_t(0x0123456789ABCDEF)); - CHECK(long long(0x0123456789ABCDEF) == etl::le_long_long_t(0x0123456789ABCDEF)); - CHECK(etl::le_long_long_t(0x0123456789ABCDEF) == long long(0x0123456789ABCDEF)); + CHECK((long long)(0x0123456789ABCDEF) == etl::le_long_long_t(0x0123456789ABCDEF)); + CHECK(etl::le_long_long_t(0x0123456789ABCDEF) == (long long)(0x0123456789ABCDEF)); CHECK(etl::le_ulong_long_t(0x0123456789ABCDEFU) == etl::le_ulong_long_t(0x0123456789ABCDEFU)); - CHECK(unsigned long long(0x0123456789ABCDEFU) == etl::le_ulong_long_t(0x0123456789ABCDEFU)); - CHECK(etl::le_ulong_long_t(0x0123456789ABCDEFU) == unsigned long long(0x0123456789ABCDEFU)); + CHECK((unsigned long long)(0x0123456789ABCDEFU) == etl::le_ulong_long_t(0x0123456789ABCDEFU)); + CHECK(etl::le_ulong_long_t(0x0123456789ABCDEFU) == (unsigned long long)(0x0123456789ABCDEFU)); } } @@ -240,12 +240,12 @@ namespace CHECK(etl::le_char_t(0x01) != char(0x02)); CHECK(etl::le_schar_t(0x01) != etl::le_schar_t(0x02)); - CHECK(signed char(0x01) != etl::le_schar_t(0x02)); - CHECK(etl::le_schar_t(0x01) != signed char(0x02)); + CHECK((signed char)(0x01) != etl::le_schar_t(0x02)); + CHECK(etl::le_schar_t(0x01) != (signed char)(0x02)); CHECK(etl::le_uchar_t(0x01U) != etl::le_uchar_t(0x02U)); - CHECK(unsigned char(0x01U) != etl::le_uchar_t(0x02U)); - CHECK(etl::le_uchar_t(0x01U) != unsigned char(0x02U)); + CHECK((unsigned char)(0x01U) != etl::le_uchar_t(0x02U)); + CHECK(etl::le_uchar_t(0x01U) != (unsigned char)(0x02U)); // short CHECK(etl::le_short_t(0x0123) != etl::le_short_t(0x0223)); @@ -253,8 +253,8 @@ namespace CHECK(etl::le_short_t(0x0123) != short(0x0223)); CHECK(etl::le_ushort_t(0x0123) != etl::le_ushort_t(0x0223)); - CHECK(unsigned short(0x0123) != etl::le_ushort_t(0x0223)); - CHECK(etl::le_ushort_t(0x0123) != unsigned short(0x0223)); + CHECK((unsigned short)(0x0123) != etl::le_ushort_t(0x0223)); + CHECK(etl::le_ushort_t(0x0123) != (unsigned short)(0x0223)); // int CHECK(etl::le_int_t(0x012345678) != etl::le_int_t(0x022345678)); @@ -262,8 +262,8 @@ namespace CHECK(etl::le_int_t(0x012345678) != int(0x022345678)); CHECK(etl::le_uint_t(0x012345678U) != etl::le_uint_t(0x022345678U)); - CHECK(unsigned int(0x012345678U) != etl::le_uint_t(0x022345678U)); - CHECK(etl::le_uint_t(0x012345678U) != unsigned int(0x022345678U)); + CHECK((unsigned int)(0x012345678U) != etl::le_uint_t(0x022345678U)); + CHECK(etl::le_uint_t(0x012345678U) != (unsigned int)(0x022345678U)); if (sizeof(long) == 4U) { @@ -273,20 +273,20 @@ namespace CHECK(etl::le_long_t(0x012345678) != long(0x022345678)); CHECK(etl::le_ulong_t(0x012345678U) != etl::le_ulong_t(0x022345678U)); - CHECK(unsigned long(0x012345678U) != etl::le_ulong_t(0x022345678U)); - CHECK(etl::le_ulong_t(0x012345678U) != unsigned long(0x022345678U)); + CHECK((unsigned long)(0x012345678U) != etl::le_ulong_t(0x022345678U)); + CHECK(etl::le_ulong_t(0x012345678U) != (unsigned long)(0x022345678U)); } if (sizeof(long long) == 8U) { // long long CHECK(etl::le_long_long_t(0x0123456789ABCDEF) != etl::le_long_long_t(0x0223456789ABCDEF)); - CHECK(long long(0x0123456789ABCDEF) != etl::le_long_long_t(0x0223456789ABCDEF)); - CHECK(etl::le_long_long_t(0x0123456789ABCDEF) != long long(0x0223456789ABCDEF)); + CHECK((long long)(0x0123456789ABCDEF) != etl::le_long_long_t(0x0223456789ABCDEF)); + CHECK(etl::le_long_long_t(0x0123456789ABCDEF) != (long long)(0x0223456789ABCDEF)); CHECK(etl::le_ulong_long_t(0x0123456789ABCDEFU) != etl::le_ulong_long_t(0x0223456789ABCDEFU)); - CHECK(unsigned long long(0x0123456789ABCDEFU) != etl::le_ulong_long_t(0x0223456789ABCDEFU)); - CHECK(etl::le_ulong_long_t(0x0123456789ABCDEFU) != unsigned long long(0x0223456789ABCDEFU)); + CHECK((unsigned long long)(0x0123456789ABCDEFU) != etl::le_ulong_long_t(0x0223456789ABCDEFU)); + CHECK(etl::le_ulong_long_t(0x0123456789ABCDEFU) != (unsigned long long)(0x0223456789ABCDEFU)); } } @@ -299,12 +299,12 @@ namespace CHECK(etl::be_char_t(0x01) == char(0x01)); CHECK(etl::be_schar_t(0x01) == etl::be_schar_t(0x01)); - CHECK(signed char(0x01) == etl::be_schar_t(0x01)); - CHECK(etl::be_schar_t(0x01) == signed char(0x01)); + CHECK((signed char)(0x01) == etl::be_schar_t(0x01)); + CHECK(etl::be_schar_t(0x01) == (signed char)(0x01)); CHECK(etl::be_uchar_t(0x01U) == etl::be_uchar_t(0x01U)); - CHECK(unsigned char(0x01U) == etl::be_uchar_t(0x01U)); - CHECK(etl::be_uchar_t(0x01U) == unsigned char(0x01U)); + CHECK((unsigned char)(0x01U) == etl::be_uchar_t(0x01U)); + CHECK(etl::be_uchar_t(0x01U) == (unsigned char)(0x01U)); // short CHECK(etl::be_short_t(0x0123) == etl::be_short_t(0x0123)); @@ -312,8 +312,8 @@ namespace CHECK(etl::be_short_t(0x0123) == short(0x0123)); CHECK(etl::be_ushort_t(0x0123) == etl::be_ushort_t(0x0123)); - CHECK(unsigned short(0x0123) == etl::be_ushort_t(0x0123)); - CHECK(etl::be_ushort_t(0x0123) == unsigned short(0x0123)); + CHECK((unsigned short)(0x0123) == etl::be_ushort_t(0x0123)); + CHECK(etl::be_ushort_t(0x0123) == (unsigned short)(0x0123)); // int CHECK(etl::be_int_t(0x012345678) == etl::be_int_t(0x012345678)); @@ -321,8 +321,8 @@ namespace CHECK(etl::be_int_t(0x012345678) == int(0x012345678)); CHECK(etl::be_uint_t(0x012345678U) == etl::be_uint_t(0x012345678U)); - CHECK(unsigned int(0x012345678U) == etl::be_uint_t(0x012345678U)); - CHECK(etl::be_uint_t(0x012345678U) == unsigned int(0x012345678U)); + CHECK((unsigned int)(0x012345678U) == etl::be_uint_t(0x012345678U)); + CHECK(etl::be_uint_t(0x012345678U) == (unsigned int)(0x012345678U)); if (sizeof(long) == 4U) { @@ -332,20 +332,20 @@ namespace CHECK(etl::be_long_t(0x012345678) == long(0x012345678)); CHECK(etl::be_ulong_t(0x012345678U) == etl::be_ulong_t(0x012345678U)); - CHECK(unsigned long(0x012345678U) == etl::be_ulong_t(0x012345678U)); - CHECK(etl::be_ulong_t(0x012345678U) == unsigned long(0x012345678U)); + CHECK((unsigned long)(0x012345678U) == etl::be_ulong_t(0x012345678U)); + CHECK(etl::be_ulong_t(0x012345678U) == (unsigned long)(0x012345678U)); } if (sizeof(long long) == 8U) { // long long CHECK(etl::be_long_long_t(0x0123456789ABCDEF) == etl::be_long_long_t(0x0123456789ABCDEF)); - CHECK(long long(0x0123456789ABCDEF) == etl::be_long_long_t(0x0123456789ABCDEF)); - CHECK(etl::be_long_long_t(0x0123456789ABCDEF) == long long(0x0123456789ABCDEF)); + CHECK((long long)(0x0123456789ABCDEF) == etl::be_long_long_t(0x0123456789ABCDEF)); + CHECK(etl::be_long_long_t(0x0123456789ABCDEF) == (long long)(0x0123456789ABCDEF)); CHECK(etl::be_ulong_long_t(0x0123456789ABCDEFU) == etl::be_ulong_long_t(0x0123456789ABCDEFU)); - CHECK(unsigned long long(0x0123456789ABCDEFU) == etl::be_ulong_long_t(0x0123456789ABCDEFU)); - CHECK(etl::be_ulong_long_t(0x0123456789ABCDEFU) == unsigned long long(0x0123456789ABCDEFU)); + CHECK((unsigned long long)(0x0123456789ABCDEFU) == etl::be_ulong_long_t(0x0123456789ABCDEFU)); + CHECK(etl::be_ulong_long_t(0x0123456789ABCDEFU) == (unsigned long long)(0x0123456789ABCDEFU)); } } @@ -358,12 +358,12 @@ namespace CHECK(etl::be_char_t(0x01) != char(0x02)); CHECK(etl::be_schar_t(0x01) != etl::be_schar_t(0x02)); - CHECK(signed char(0x01) != etl::be_schar_t(0x02)); - CHECK(etl::be_schar_t(0x01) != signed char(0x02)); + CHECK((signed char)(0x01) != etl::be_schar_t(0x02)); + CHECK(etl::be_schar_t(0x01) != (signed char)(0x02)); CHECK(etl::be_uchar_t(0x01U) != etl::be_uchar_t(0x02U)); - CHECK(unsigned char(0x01U) != etl::be_uchar_t(0x02U)); - CHECK(etl::be_uchar_t(0x01U) != unsigned char(0x02U)); + CHECK((unsigned char)(0x01U) != etl::be_uchar_t(0x02U)); + CHECK(etl::be_uchar_t(0x01U) != (unsigned char)(0x02U)); // short CHECK(etl::be_short_t(0x0123) != etl::be_short_t(0x0223)); @@ -371,8 +371,8 @@ namespace CHECK(etl::be_short_t(0x0123) != short(0x0223)); CHECK(etl::be_ushort_t(0x0123) != etl::be_ushort_t(0x0223)); - CHECK(unsigned short(0x0123) != etl::be_ushort_t(0x0223)); - CHECK(etl::be_ushort_t(0x0123) != unsigned short(0x0223)); + CHECK((unsigned short)(0x0123) != etl::be_ushort_t(0x0223)); + CHECK(etl::be_ushort_t(0x0123) != (unsigned short)(0x0223)); // int CHECK(etl::be_int_t(0x012345678) != etl::be_int_t(0x022345678)); @@ -380,8 +380,8 @@ namespace CHECK(etl::be_int_t(0x012345678) != int(0x022345678)); CHECK(etl::be_uint_t(0x012345678U) != etl::be_uint_t(0x022345678U)); - CHECK(unsigned int(0x012345678U) != etl::be_uint_t(0x022345678U)); - CHECK(etl::be_uint_t(0x012345678U) != unsigned int(0x022345678U)); + CHECK((unsigned int)(0x012345678U) != etl::be_uint_t(0x022345678U)); + CHECK(etl::be_uint_t(0x012345678U) != (unsigned int)(0x022345678U)); if (sizeof(long) == 4U) { @@ -391,20 +391,20 @@ namespace CHECK(etl::be_long_t(0x012345678) != long(0x022345678)); CHECK(etl::be_ulong_t(0x012345678U) != etl::be_ulong_t(0x022345678U)); - CHECK(unsigned long(0x012345678U) != etl::be_ulong_t(0x022345678U)); - CHECK(etl::be_ulong_t(0x012345678U) != unsigned long(0x022345678U)); + CHECK((unsigned long)(0x012345678U) != etl::be_ulong_t(0x022345678U)); + CHECK(etl::be_ulong_t(0x012345678U) != (unsigned long)(0x022345678U)); } if (sizeof(long long) == 8U) { // long long CHECK(etl::be_long_long_t(0x0123456789ABCDEF) != etl::be_long_long_t(0x0223456789ABCDEF)); - CHECK(long long(0x0123456789ABCDEF) != etl::be_long_long_t(0x0223456789ABCDEF)); - CHECK(etl::be_long_long_t(0x0123456789ABCDEF) != long long(0x0223456789ABCDEF)); + CHECK((long long)(0x0123456789ABCDEF) != etl::be_long_long_t(0x0223456789ABCDEF)); + CHECK(etl::be_long_long_t(0x0123456789ABCDEF) != (long long)(0x0223456789ABCDEF)); CHECK(etl::be_ulong_long_t(0x0123456789ABCDEFU) != etl::be_ulong_long_t(0x0223456789ABCDEFU)); - CHECK(unsigned long long(0x0123456789ABCDEFU) != etl::be_ulong_long_t(0x0223456789ABCDEFU)); - CHECK(etl::be_ulong_long_t(0x0123456789ABCDEFU) != unsigned long long(0x0223456789ABCDEFU)); + CHECK((unsigned long long)(0x0123456789ABCDEFU) != etl::be_ulong_long_t(0x0223456789ABCDEFU)); + CHECK(etl::be_ulong_long_t(0x0123456789ABCDEFU) != (unsigned long long)(0x0223456789ABCDEFU)); } } diff --git a/test/vs2019/etl.vcxproj b/test/vs2019/etl.vcxproj index 08689ef4..2386fa9c 100644 --- a/test/vs2019/etl.vcxproj +++ b/test/vs2019/etl.vcxproj @@ -881,7 +881,7 @@ Level3 Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_CPP20_ENABLED;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) ../../../unittest-cpp/;../../include;../../test @@ -903,7 +903,7 @@ Level3 Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_CPP20_ENABLED;ETL_NO_STL;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_NO_STL;%(PreprocessorDefinitions) ../../../unittest-cpp/;../../include;../../test @@ -1184,7 +1184,7 @@ Level3 Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;__clang__;ETL_CPP20_ENABLED;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;__clang__;%(PreprocessorDefinitions) ../../../unittest-cpp/;../../include;../../test @@ -9457,6 +9457,8 @@ + + @@ -9522,6 +9524,7 @@ + diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters index d2667243..b554bc9f 100644 --- a/test/vs2019/etl.vcxproj.filters +++ b/test/vs2019/etl.vcxproj.filters @@ -1,10 +1,6 @@  - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms @@ -115,6 +111,76 @@ {562466b5-677d-4448-9e9e-f70805cd71ad} + + {66b8d39a-b610-4d5e-925a-4995f2ac74b2} + + + {a1af709b-90d3-4506-b742-3231d0fff1f5} + + + {43578ed8-b61d-4210-b5d4-bb4a26351934} + + + {c75cedd3-8b6c-4662-b965-aecbe7fd5d1c} + + + {da470864-7708-4e89-a24c-93a9ca2c4856} + + + {0873470d-a6d9-445c-bbc0-33252978ecff} + + + {b42bb316-6e55-4336-a72a-fc5f28d82ea5} + + + {a300635d-25da-4af6-b7e7-1e27ec9df921} + + + {dc898ba2-50f4-4c3d-abee-039670df8582} + + + {e260d680-649f-41b5-844d-c736a252dcb5} + + + {21e56de9-b458-4395-9949-3abfb1f5723b} + + + {d115746e-4d33-41b4-b88f-9fb2ca225286} + + + {a1417994-24a2-40ae-a934-ea318299f91c} + + + {126a3068-3048-4210-8cdf-41ec9e2e1436} + + + {a8738fb5-ff9c-40c2-b3c0-4843ca55097c} + + + {89fc701f-b9ea-4ff3-beac-199c003c4b3e} + + + {d266eb8f-3f48-4625-98d8-47b6cd9f13a5} + + + {66f5995b-c1a1-4bc7-b09a-b0148613d77a} + + + {3820f2db-3b02-48c1-ac8c-c3ee4507ee45} + + + {2682377b-6037-4163-9097-3e3e9824e215} + + + {d37e1c04-f45f-4513-99cc-debbbcf7dead} + + + {236aa242-d71f-48bd-9169-cfa7cbff9f10} + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + @@ -222,15 +288,6 @@ ETL\Utilities - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - ETL\Maths @@ -246,9 +303,6 @@ ETL\Containers - - ETL\Maths - ETL\Containers @@ -273,18 +327,6 @@ ETL\Containers - - ETL\Maths - - - ETL\Maths - - - Tests - - - ETL\Maths - ETL\Containers @@ -429,9 +471,6 @@ ETL\Profiles - - Tests - ETL\Profiles @@ -502,100 +541,100 @@ ETL\Utilities - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files - Header Files + UnitTest++\Header Files ETL\Maths @@ -648,15 +687,9 @@ ETL\Maths - - Tests - ETL\Frameworks - - ETL\Maths - ETL\Containers @@ -753,9 +786,6 @@ ETL\Utilities - - Tests - ETL\Utilities\Mutex @@ -868,7 +898,7 @@ ETL\Utilities - Header Files + UnitTest++\Header Files ETL\Frameworks @@ -909,9 +939,6 @@ ETL\Frameworks - - Tests - Tests\Sanity Checks\C++03 @@ -924,150 +951,12 @@ Tests\Sanity Checks\C++17 - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - ETL\Private ETL\Private - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - ETL\Maths @@ -1132,7 +1021,7 @@ ETL\Patterns - Header Files + UnitTest++\Header Files ETL\Utilities @@ -1179,308 +1068,188 @@ ETL\Utilities + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\CRC + + + ETL\Maths\Hash + + + ETL\Maths\Hash + + + ETL\Maths\Hash + + + ETL\Maths\Hash + + + ETL\Maths\Hash + + + ETL\Maths\Hash + + + ETL\Maths\Hash + + + ETL\Maths\Hash + + + Tests\Test Support + + + Tests\Test Support + + + Tests\Test Support + + + Tests\Test Support + + + Tests\Test Support + - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - Source Files - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - UnitTest++ @@ -1544,396 +1313,12 @@ UnitTest++\Win32 - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - Source Files Source Files - - Tests - - - Tests - Tests\Sanity Checks @@ -2723,138 +2108,6 @@ Tests\Sanity Checks - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - Source Files\Sanity Checks @@ -2936,54 +2189,12 @@ Source Files\Sanity Checks - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - Source Files - - Source Files - - - Source Files - - - Source Files - Source Files\Sanity Checks - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Tests - Source Files\Sanity Checks @@ -3029,77 +2240,938 @@ Source Files\Sanity Checks - - Source Files - - - Tests - Tests\Sanity Checks Tests\Sanity Checks - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - Tests\Sanity Checks Tests\Sanity Checks - - Tests - Tests\Sanity Checks Tests\Sanity Checks - - Tests - Tests\Sanity Checks - - Tests - - - Tests - - - Tests - - - Tests - - - Tests - Tests\Sanity Checks Tests\Sanity Checks + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Strings + + + Tests\Messaging + + + Tests\Messaging + + + Tests\Messaging + + + Tests\Messaging + + + Tests\Messaging + + + Tests\Messaging + + + Tests\Messaging + + + Tests\Messaging + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\Hashes + + + Tests\Hashes + + + Tests\Hashes + + + Tests\Hashes + + + Tests\Hashes + + + Tests\Hashes + + + Tests\Hashes + + + Tests\Hashes + + + Tests\Hashes + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Queues + + + Tests\Queues + + + Tests\Queues + + + Tests\Queues + + + Tests\Queues + + + Tests\Queues + + + Tests\Queues + + + Tests\Queues + + + Tests\Queues + + + Tests\Queues + + + Tests\Queues + + + Tests\Queues + + + Tests\Queues + + + Tests\Queues + + + Tests\Callbacks & Delegates + + + Tests\Callbacks & Delegates + + + Tests\Callbacks & Delegates + + + Tests\Callbacks & Delegates + + + Tests\Callbacks & Delegates + + + Tests\Callbacks & Delegates + + + Tests\Callbacks & Delegates + + + Tests\Timers + + + Tests\Timers + + + Tests\Timers + + + Tests\Strings + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Queues + + + Tests\State Machines + + + Tests\State Machines + + + Tests\State Machines + + + Tests\State Machines + + + Tests\State Machines + + + Tests\State Machines + + + Tests\State Machines + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Algorithms + + + Tests\Binary + + + Tests\Binary + + + Tests\Binary + + + Tests\Binary + + + Tests\Binary + + + Tests\Hashes + + + Tests\Containers + + + Tests\Containers + + + Tests\Containers + + + Tests\Test Support + + + Tests\Test Support + + + Tests\Strings + + + Tests\Containers + + + Tests\Algorithms + + + Tests\Types + + + Tests\Types + + + Tests\Types + + + Tests\Types + + + Tests\Types + + + Tests\Types + + + Tests\Types + + + Tests\Types + - Tests + Tests\Types + + + Tests\Types + + + Tests\Types + + + Tests\Types + + + Tests\Algorithms + + + Tests\Types + + + Tests\Types + + + Tests\Patterns + + + Tests\Patterns + + + Tests\Queues + + + Tests\Atomic + + + Tests\Atomic + + + Tests\Atomic + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\CRC + + + Tests\Maths + + + Tests\Maths + + + Tests\Maths + + + Tests\Maths + + + Tests\Maths + + + Tests\Maths + + + Tests\Maths + + + Tests\Maths + + + Tests\Maths + + + Tests\Maths + + + Tests\Maths + + + Tests\Maths + + + Tests\Maths + + + Tests\Algorithms + + + Tests\Memory & Iterators + + + Tests\Memory & Iterators + + + Tests\Memory & Iterators + + + Tests\Memory & Iterators + + + Tests\Memory & Iterators + + + Tests\Memory & Iterators + + + Tests\Maths + + + Tests\Maths + + + Tests\Containers + + + Tests\Errors + + + Tests\Errors + + + Tests\Patterns + + + Tests\Tasks + + + Tests\Misc + + + Tests\Misc + + + Tests\Misc + + + Tests\Misc + + + Tests\Misc + + + Tests\Misc + + + Tests\Misc + + + Tests\Misc + + + Tests\Misc + + + Tests\Misc @@ -3193,6 +3265,9 @@ Resource Files + + ETL\Arduino +