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.
FSM.h@0:918566a376fb, 2010-01-03 (annotated)
- Committer:
- snatch59
- Date:
- Sun Jan 03 11:56:03 2010 +0000
- Revision:
- 0:918566a376fb
Who changed what in which revision?
User | Revision | Line number | New 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 |