A C++ template library for embedded applications
Designed and maintained by
Aster Consulting Ltd
Join the ETL community

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.

This FSM is much 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 <<template>>

____________________________________________________________________________________________________
etl::istate_chart

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.

____________________________________________________________________________________________________
etl::state_chart

A templated class. Inherits from etl::istate_chart.

Template parameters


TObject  The object type that supplies actions, guards, on entry and on exit functionality

____________________________________________________________________________________________________

Constructors


state_chart(TObject& object,
            const transition* transition_table_begin,
            const transition* transition_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 scope as the state chart. i.e. It must exist while the state chart exists.

state_id
The initial state id.
____________________________________________________________________________________________________

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 scope 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 scope 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

____________________________________________________________________________________________________

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)

Triggers the state chart with the event.

____________________________________________________________________________________________________

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)

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)

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.

____________________________________________________________________________________________________

const state* find_state(state_id_t state_id)

Returns a const pointer to the entry in the state table matching the supplied state  id.
If the entry does not exist then the array's end() is returned.

____________________________________________________________________________________________________

Member Types


transition

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)

current_state_id
The state id that the state chart must be in for the event to be processed.

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.

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, 5> 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