A C++ template library for embedded applications
MIT licensed
Designed and
maintained by
John Wellbelove
Support the development
of the ETL

State Chart

A finite state machine driven by the reception of events. The incoming event will call the optional action based on a
transition table. Optional on_entry and on_exit handlers can be declared in a state table.
An optional parameter may be sent to event handlers.

This FSM is simpler, both in implementation and use, than the message based FSM class defined elsewhere in the ETL.
See etl::fsm.

Defines the following classes:-
etl::istate_chart
etl::state_chart<TObject>
etl::state_chart<TObject, TParameter>

TParameter defines how a data parameter will be passed to event handlers.
This may be by value, pointer, reference or const reference.
For C++11 or above, you may pass an rvalue reference.
____________________________________________________________________________________________________

istate_chart<TParameter>

20.23.0
The base for all state charts.

Types
event_id_t
The type for event ids.

state_id_t
The type for state ids.

Member Functions
event_it_t get_state_id() const
Returns the id of the state.
____________________________________________________________________________________________________
virtual void process_event(event_id_t event_id, TParameter data) = 0
etl::state_chart will override this.
Processes the event message.
If a data parameter has been configured for etl::state_chart, then one will be default constructed.
____________________________________________________________________________________________________
virtual void start(bool on_entry_initial = true)
Starts the state chart.
____________________________________________________________________________________________________

istate_chart<void>

20.23.0
The base for all state charts.

Types
event_id_t
The type for event ids.

state_id_t
The type for state ids.

Member Functions
event_it_t get_state_id() const
Returns the id of the state.
____________________________________________________________________________________________________
virtual void process_event(event_id_t event_id) = 0
etl::state_chart will override this.
Processes the event message.
If a data parameter has been configured for etl::state_chart, then one will be default constructed.
____________________________________________________________________________________________________
virtual void start(bool on_entry_initial = true)
Starts the state chart.
____________________________________________________________________________________________________

state_chart

For run-time defined transition and state tables.
A templated class. Inherits from etl::istate_chart<TParameter> or etl::istate_chart<void>.

Template parameters
TObject     The object type that supplies actions, guards, on entry and on exit functionality.
TParameter  The type that will be passed as a parameter (optional).
____________________________________________________________________________________________________
Types

TParameter parameter_t
____________________________________________________________________________________________________
Constructor

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)

object
The instance of the that supplies actions, guards, on entry and on exit functionality.

transition_table_begin
transition_table_end
The table of transitions, defining the relationship between events and state changes; defines option actions and
guards.
Note: The transition table must have the same lifetime as the state chart. i.e. It must exist while the state chart exists.

state_table_begin
state_table_end
Sets the optional state table defining any 'on entry' and 'on exit' for states.
Not all states have to have entries in the table. States with no  'on entry' and 'on_exit' functionality may be omitted.
Note: The state table must have the same lifetime as the state chart. i.e. It must exist while the state chart exists.

state_id
The initial state id.
Note: The constructors do not call the 'on entry' function for the initial state
____________________________________________________________________________________________________

state_chart_ct

void parameter

state_chart_ctp

non-void parameter

For compile-time defined transition and state tables.
A templated class. Inherits from etl::istate_chart<TParameter> or etl::istate_chart<void>.

Template parameters
TObject                The object type that supplies actions, guards, on entry and on exit functionality.
TParameter             The type that will be passed as a parameter (state_chart_ctp).
TObject_Ref            A reference to the TObject instance.
Transition_Table_Begin A pointer to the start of the transition table.
Transition_Table_Size  The number of elements in the transition table.
State_Table_Begin      A pointer to the start of the state table.
State_Table_Size       The number of elements in the transition table.
Initial_State          The initial state.
____________________________________________________________________________________________________
Types
TParameter parameter_t
____________________________________________________________________________________________________
Constructor

state_chart()
____________________________________________________________________________________________________
Member Functions

void start(bool on_entry_initial = true)
Starts the state chart.
if on_entry_initial is true and the initial state has an on_entry method, then this will be called.
The function does nothing after the first call.
____________________________________________________________________________________________________
void process_event(event_id_t event_id) For void parameter.
Triggers the state chart with the event.
____________________________________________________________________________________________________
void process_event(event_id_t event_id, parameter_t data) For non-void parameter.
Triggers the state chart with the event.
Passes the parameter to the event handler.
____________________________________________________________________________________________________
TObject& get_object()
const TObject& get_object() const
Gets the implementation object instance.
____________________________________________________________________________________________________
void set_transition_table(const transition* transition_table_begin,
                          const transition* transition_table_end)
Not defined for state_chart_ct or state_chart_ctp.
The table of transitions, defining the relationship between events and state changes; defines option actions and
guards.
Note: The transition table must have the same scope as the state chart. i.e. It must exist while the state chart exists.
____________________________________________________________________________________________________
void set_state_table(const state* state_table_begin,
                     const state* state_table_end)
Not defined for state_chart_ct or state_chart_ctp.
Sets the optional state table defining any on_entry and on_exit for states.
Not all states have to have entries in the table. States with no  on_entry and on_exit functionality may be omitted.
Note: The state table must have the same scope as the state chart. i.e. It must exist while the state chart exists.
____________________________________________________________________________________________________
Member Types

transition
____________________________________________________________________________________________________
For etl::state_chart<TImplementation>
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)() = nullptr,
           bool (TObject::* const guard)()  = nullptr)

transition(const event_id_t event_id,
           const state_id_t next_state_id,
           void (TObject::* const action)() = nullptr,
           bool (TObject::* const guard)()  = nullptr)
____________________________________________________________________________________________________
For etl::state_chart<TImplementation, TParameter>
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)(data_parameter_type) = nullptr,
           bool (TObject::* const guard)()  = nullptr)

transition(const event_id_t event_id,
           const state_id_t next_state_id,
           void (TObject::* const action)(data_parameter_type) = nullptr,
           bool (TObject::* const guard)()  = nullptr)

current_state_id
The state id that the state chart must be in for the event to be processed.
If the second constructor form is used then the 'current state' is considered to be don't care.

event_id
The event id for this transition.

next_state_id
The state id that the state chart will be in after the event.

action
An optional pointer to the action that will be called when the transition occurs.

guard
An optional pointer to the guard for this transition. The transition will only occur if the guard returns true.
If the guard returns false then the scan of the transition table continues from the next position.
____________________________________________________________________________________________________
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
The ID of the state.

on_entry
An optional pointer to the function that will be called when a state is entered.

on_exit
An optional pointer to the function that will be called when a state is entered.
___________________________________________________________________________________________________
Example

class MotorControl : public etl::state_chart<MotorControl>
{
  void OnStart();
  void OnStop();
  void OnSetSpeed();
  bool StartGuard();

  static const etl::array<MotorControl::transition, 5> transitionTable;
};

const etl::array<MotorControl::transition, 5> MotorControl::transitionTable =
{
  MotorControl::transition(IDLE,
                           START,
                           RUNNING,
                           &MotorControl::OnStart,
                           &MotorControl::StartGuard),

  MotorControl::transition(RUNNING,
                           STOP,                                                   
                           WINDING_DOWN,
                           &MotorControl::OnStop),

  MotorControl::transition(WINDING_DOWN,
                           STOPPED,
                           IDLE),

  MotorControl::transition(RUNNING,
                           EMERGENCY_STOP,
                           IDLE,
                           &MotorControl::OnStop),

  MotorControl::transition(RUNNING,
                           SET_SPEED,
                           RUNNING,
                           &MotorControl::OnSetSpeed)
};
____________________________________________________________________________________________________
state

state(const state_id_t state_id,
      void (TObject::* const on_entry)() = nullptr,
      void (TObject::* const on_exit)()  = nullptr)

state_id
The id for this state.

on_entry
An optional pointer to the function that will be called when the state chart enters the state.

on_exit
An optional pointer to the function that will be called when the state chart exits the state.

____________________________________________________________________________________________________
Example

class MotorControl : public etl::state_chart<MotorControl>
{
  void OnExitIdle();
  void OnEnterStopped();
  void OnEnterRunning);
  void OnExitRunning();

  static const etl::array<MotorControl::state, 3> stateTable;
};

const etl::array<MotorControl::state, 3> MotorControl::stateTable =
{
  MotorControl::state(IDLE,    nullptr,                       &MotorControl::OnExitIdle),
  MotorControl::state(STOPPED, &MotorControl::OnEnterStopped, nullptr),
  MotorControl::state(RUNNING, &MotorControl::OnEnterRunning, &MotorControl::OnExitRunning)
};
____________________________________________________________________________________________________
Notes
____________________________________________________________________________________________________
Order of execution
When an event is processed, the execution occurs in the following order.
(Assuming all functions have been declared in the transition and state tables)

A call to the guard function.
A call to the action function.
A call to the current state's exit function (if the transition changes the state).
A call to the next state's entry function (if the transition changes the state).
____________________________________________________________________________________________________
Usage
The state chart may either used with inheritance or composition.

class Implementation : public etl::state_chart<Implementation>

class Implementation
{
   etl::state_chart<Implementation> stateChart;
};

Use inheritance when the implementation is a state machine.
Use composition if the implementation contains a state machine.
state_chart.h