Table driven Finite State Machine library based on the Harel state machine, supporting actions on transitions, state entry and state exit. Comes with example illustrating use with interrupts and timers. 03/01/2010 - fixed potential memory leak in DebugTrace.

Dependencies:   mbed

Committer:
snatch59
Date:
Sun Jan 03 11:56:03 2010 +0000
Revision:
0:918566a376fb

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
snatch59 0:918566a376fb 1 /*
snatch59 0:918566a376fb 2 * FiniteStateMachine. Table driven Finite State Machine library
snatch59 0:918566a376fb 3 * based on theHarel state machine, supporting actions on transitions, state
snatch59 0:918566a376fb 4 * entry and state exit.
snatch59 0:918566a376fb 5 *
snatch59 0:918566a376fb 6 * Copyright (C) <2009> Petras Saduikis <petras@petras.co.uk>
snatch59 0:918566a376fb 7 *
snatch59 0:918566a376fb 8 * This file is part of FiniteStateMachine.
snatch59 0:918566a376fb 9 *
snatch59 0:918566a376fb 10 * FiniteStateMachine is free software: you can redistribute it and/or modify
snatch59 0:918566a376fb 11 * it under the terms of the GNU General Public License as published by
snatch59 0:918566a376fb 12 * the Free Software Foundation, either version 3 of the License, or
snatch59 0:918566a376fb 13 * (at your option) any later version.
snatch59 0:918566a376fb 14 *
snatch59 0:918566a376fb 15 * FiniteStateMachine is distributed in the hope that it will be useful,
snatch59 0:918566a376fb 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
snatch59 0:918566a376fb 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
snatch59 0:918566a376fb 18 * GNU General Public License for more details.
snatch59 0:918566a376fb 19 *
snatch59 0:918566a376fb 20 * You should have received a copy of the GNU General Public License
snatch59 0:918566a376fb 21 * along with DebugTrace. If not, see <http://www.gnu.org/licenses/>.
snatch59 0:918566a376fb 22 */
snatch59 0:918566a376fb 23
snatch59 0:918566a376fb 24 #ifndef SNATCH59_FSM_H
snatch59 0:918566a376fb 25 #define SNATCH59_FSM_H
snatch59 0:918566a376fb 26
snatch59 0:918566a376fb 27 #include <mbed.h>
snatch59 0:918566a376fb 28 #include "FSMDefs.h"
snatch59 0:918566a376fb 29
snatch59 0:918566a376fb 30 STATE_TEMPLATE_ class State;
snatch59 0:918566a376fb 31
snatch59 0:918566a376fb 32 TRANS_DEF_TEMPLATE_
snatch59 0:918566a376fb 33 struct TransitionDefinition
snatch59 0:918566a376fb 34 {
snatch59 0:918566a376fb 35 const char* ownerState;
snatch59 0:918566a376fb 36 int eventId;
snatch59 0:918566a376fb 37 StateBehaviour mode;
snatch59 0:918566a376fb 38 ActionPtrType action;
snatch59 0:918566a376fb 39 const char* newState;
snatch59 0:918566a376fb 40 };
snatch59 0:918566a376fb 41
snatch59 0:918566a376fb 42 TRANS_DEF_TEMPLATE_
snatch59 0:918566a376fb 43 class StateDefinition
snatch59 0:918566a376fb 44 {
snatch59 0:918566a376fb 45 public:
snatch59 0:918566a376fb 46 const char* stateName;
snatch59 0:918566a376fb 47 ActionPtrType stateEntryAction;
snatch59 0:918566a376fb 48 ActionPtrType stateExitAction;
snatch59 0:918566a376fb 49 };
snatch59 0:918566a376fb 50
snatch59 0:918566a376fb 51 #include "State.h"
snatch59 0:918566a376fb 52
snatch59 0:918566a376fb 53 FSM_TEMPLATE_
snatch59 0:918566a376fb 54 class FiniteStateMachine
snatch59 0:918566a376fb 55 {
snatch59 0:918566a376fb 56 public:
snatch59 0:918566a376fb 57 FiniteStateMachine();
snatch59 0:918566a376fb 58 ~FiniteStateMachine();
snatch59 0:918566a376fb 59
snatch59 0:918566a376fb 60 void initialize(StateObjectType* owner,
snatch59 0:918566a376fb 61 const STATE_DEFINITION_* states, const int total_states,
snatch59 0:918566a376fb 62 const TRANSITION_DEFINITION_* transitions, const int total_transitions,
snatch59 0:918566a376fb 63 const char* this_state);
snatch59 0:918566a376fb 64 void traverse(const int new_event);
snatch59 0:918566a376fb 65 void forceToState(const char* stat_name);
snatch59 0:918566a376fb 66 bool isState(const char* this_state) const;
snatch59 0:918566a376fb 67 const char* getCurrentStateName() const;
snatch59 0:918566a376fb 68
snatch59 0:918566a376fb 69 private:
snatch59 0:918566a376fb 70 void addStates(const STATE_DEFINITION_* states, const int total_states,
snatch59 0:918566a376fb 71 const TRANSITION_DEFINITION_* &transitions, const int total_transitions);
snatch59 0:918566a376fb 72 void executeTraversal(const int event);
snatch59 0:918566a376fb 73
snatch59 0:918566a376fb 74 // Data Members
snatch59 0:918566a376fb 75 STATE_* currentState;
snatch59 0:918566a376fb 76 int totalStates;
snatch59 0:918566a376fb 77 StateObjectType* itsStateObject;
snatch59 0:918566a376fb 78 STATE_* itsStates[maxStates];
snatch59 0:918566a376fb 79 };
snatch59 0:918566a376fb 80
snatch59 0:918566a376fb 81 FSM_TEMPLATE_
snatch59 0:918566a376fb 82 inline const char* FINITE_STATE_MACHINE_::getCurrentStateName() const
snatch59 0:918566a376fb 83 {
snatch59 0:918566a376fb 84 return (currentState->getName());
snatch59 0:918566a376fb 85 }
snatch59 0:918566a376fb 86
snatch59 0:918566a376fb 87 FSM_TEMPLATE_
snatch59 0:918566a376fb 88 inline bool FINITE_STATE_MACHINE_::isState(const char* this_state) const
snatch59 0:918566a376fb 89 {
snatch59 0:918566a376fb 90 if (0 == strcmp(currentState->getName(), this_state)) return true;
snatch59 0:918566a376fb 91
snatch59 0:918566a376fb 92 return false;
snatch59 0:918566a376fb 93 }
snatch59 0:918566a376fb 94
snatch59 0:918566a376fb 95 FSM_TEMPLATE_
snatch59 0:918566a376fb 96 FINITE_STATE_MACHINE_::FiniteStateMachine() : totalStates(0), currentState(NULL)
snatch59 0:918566a376fb 97 {
snatch59 0:918566a376fb 98 }
snatch59 0:918566a376fb 99
snatch59 0:918566a376fb 100 FSM_TEMPLATE_
snatch59 0:918566a376fb 101 FINITE_STATE_MACHINE_::~FiniteStateMachine()
snatch59 0:918566a376fb 102 {
snatch59 0:918566a376fb 103 if (itsStates != NULL)
snatch59 0:918566a376fb 104 {
snatch59 0:918566a376fb 105 // delete all its States
snatch59 0:918566a376fb 106 for (int i = 0; i < totalStates; i++)
snatch59 0:918566a376fb 107 {
snatch59 0:918566a376fb 108 delete itsStates[i];
snatch59 0:918566a376fb 109 }
snatch59 0:918566a376fb 110 }
snatch59 0:918566a376fb 111 }
snatch59 0:918566a376fb 112
snatch59 0:918566a376fb 113 FSM_TEMPLATE_
snatch59 0:918566a376fb 114 void FINITE_STATE_MACHINE_::initialize(StateObjectType* owner,
snatch59 0:918566a376fb 115 const STATE_DEFINITION_* states, const int total_states,
snatch59 0:918566a376fb 116 const TRANSITION_DEFINITION_* transitions, const int total_transitions,
snatch59 0:918566a376fb 117 const char* this_state)
snatch59 0:918566a376fb 118 {
snatch59 0:918566a376fb 119 itsStateObject = owner;
snatch59 0:918566a376fb 120
snatch59 0:918566a376fb 121 for (int k = 0; k < total_states; k++)
snatch59 0:918566a376fb 122 {
snatch59 0:918566a376fb 123 addStates(states, total_states, transitions, total_transitions);
snatch59 0:918566a376fb 124 }
snatch59 0:918566a376fb 125
snatch59 0:918566a376fb 126 forceToState(this_state);
snatch59 0:918566a376fb 127 }
snatch59 0:918566a376fb 128
snatch59 0:918566a376fb 129 FSM_TEMPLATE_
snatch59 0:918566a376fb 130 void FINITE_STATE_MACHINE_::traverse(const int new_event)
snatch59 0:918566a376fb 131 {
snatch59 0:918566a376fb 132 if (0 == totalStates)
snatch59 0:918566a376fb 133 {
snatch59 0:918566a376fb 134 return;
snatch59 0:918566a376fb 135 }
snatch59 0:918566a376fb 136
snatch59 0:918566a376fb 137 STATE_TRANSITION_* associated_transition = NULL;
snatch59 0:918566a376fb 138 STATE_* new_state = currentState->match(new_event, associated_transition);
snatch59 0:918566a376fb 139
snatch59 0:918566a376fb 140 if (new_state != NULL && associated_transition != NULL)
snatch59 0:918566a376fb 141 {
snatch59 0:918566a376fb 142 StateBehaviour behaviour = associated_transition->getStateBehaviour();
snatch59 0:918566a376fb 143
snatch59 0:918566a376fb 144 if (actions == behaviour)
snatch59 0:918566a376fb 145 {
snatch59 0:918566a376fb 146 currentState->doExitAction(itsStateObject);
snatch59 0:918566a376fb 147 }
snatch59 0:918566a376fb 148
snatch59 0:918566a376fb 149 currentState = new_state;
snatch59 0:918566a376fb 150
snatch59 0:918566a376fb 151 associated_transition->doAction(itsStateObject);
snatch59 0:918566a376fb 152
snatch59 0:918566a376fb 153 if (actions == behaviour)
snatch59 0:918566a376fb 154 {
snatch59 0:918566a376fb 155 new_state->doEntryAction(itsStateObject);
snatch59 0:918566a376fb 156 }
snatch59 0:918566a376fb 157 }
snatch59 0:918566a376fb 158 }
snatch59 0:918566a376fb 159
snatch59 0:918566a376fb 160 FSM_TEMPLATE_
snatch59 0:918566a376fb 161 void FINITE_STATE_MACHINE_::forceToState(const char* state_name)
snatch59 0:918566a376fb 162 {
snatch59 0:918566a376fb 163 for (int i = 0; i < totalStates; i++)
snatch59 0:918566a376fb 164 {
snatch59 0:918566a376fb 165 if (0 == strcmp(itsStates[i]->getName(), state_name))
snatch59 0:918566a376fb 166 {
snatch59 0:918566a376fb 167 currentState = itsStates[i];
snatch59 0:918566a376fb 168 break;
snatch59 0:918566a376fb 169 }
snatch59 0:918566a376fb 170 }
snatch59 0:918566a376fb 171 }
snatch59 0:918566a376fb 172
snatch59 0:918566a376fb 173 FSM_TEMPLATE_
snatch59 0:918566a376fb 174 void FINITE_STATE_MACHINE_::addStates(const STATE_DEFINITION_* states, const int total_states,
snatch59 0:918566a376fb 175 const TRANSITION_DEFINITION_* &transitions, const int total_transitions)
snatch59 0:918566a376fb 176 {
snatch59 0:918566a376fb 177 for (int i = 0; i < total_states; i++)
snatch59 0:918566a376fb 178 {
snatch59 0:918566a376fb 179
snatch59 0:918566a376fb 180 itsStates[i] = new STATE_(states[i].stateName,
snatch59 0:918566a376fb 181 states[i].stateEntryAction,
snatch59 0:918566a376fb 182 states[i].stateExitAction);
snatch59 0:918566a376fb 183 }
snatch59 0:918566a376fb 184 totalStates = total_states;
snatch59 0:918566a376fb 185
snatch59 0:918566a376fb 186 for (int i = 0; i < total_states; i++)
snatch59 0:918566a376fb 187 {
snatch59 0:918566a376fb 188 itsStates[i]->addTransitions(transitions, total_transitions, itsStates, total_states);
snatch59 0:918566a376fb 189 }
snatch59 0:918566a376fb 190 }
snatch59 0:918566a376fb 191
snatch59 0:918566a376fb 192 #endif