-
Notifications
You must be signed in to change notification settings - Fork 26
/
StateMachine.h
183 lines (143 loc) · 5.79 KB
/
StateMachine.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// https://github.com/endurodave/C_StateMachine
//
// The StateMachine module is a C language implementation of a finite state
// machine (FSM).
//
// All event data must be created dynamically using SM_XAlloc. Use a fixed
// block allocator or the heap as desired.
//
// The standard version (non-EX) supports state and event functions. The
// extended version (EX) supports the additional guard, entry and exit state
// machine features.
//
// Macros are used to assist in creating the state machine machinery.
#ifndef _STATE_MACHINE_H
#define _STATE_MACHINE_H
#include "DataTypes.h"
#include "Fault.h"
#ifdef __cplusplus
extern "C" {
#endif
// Define USE_SM_ALLOCATOR to use the fixed block allocator instead of heap
#define USE_SM_ALLOCATOR
#ifdef USE_SM_ALLOCATOR
#include "sm_allocator.h"
#define SM_XAlloc(size) SMALLOC_Alloc(size)
#define SM_XFree(ptr) SMALLOC_Free(ptr)
#else
#include <stdlib.h>
#define SM_XAlloc(size) malloc(size)
#define SM_XFree(ptr) free(ptr)
#endif
enum { EVENT_IGNORED = 0xFE, CANNOT_HAPPEN = 0xFF };
typedef void NoEventData;
// State machine constant data
typedef struct
{
const CHAR* name;
const BYTE maxStates;
const struct SM_StateStruct* stateMap;
const struct SM_StateStructEx* stateMapEx;
} SM_StateMachineConst;
// State machine instance data
typedef struct
{
const CHAR* name;
void* pInstance;
BYTE newState;
BYTE currentState;
BOOL eventGenerated;
void* pEventData;
} SM_StateMachine;
// Generic state function signatures
typedef void (*SM_StateFunc)(SM_StateMachine* self, void* pEventData);
typedef BOOL (*SM_GuardFunc)(SM_StateMachine* self, void* pEventData);
typedef void (*SM_EntryFunc)(SM_StateMachine* self, void* pEventData);
typedef void (*SM_ExitFunc)(SM_StateMachine* self);
typedef struct SM_StateStruct
{
SM_StateFunc pStateFunc;
} SM_StateStruct;
typedef struct SM_StateStructEx
{
SM_StateFunc pStateFunc;
SM_GuardFunc pGuardFunc;
SM_EntryFunc pEntryFunc;
SM_ExitFunc pExitFunc;
} SM_StateStructEx;
// Public functions
#define SM_Event(_smName_, _eventFunc_, _eventData_) \
_eventFunc_(&_smName_##Obj, _eventData_)
#define SM_Get(_smName_, _getFunc_) \
_getFunc_(&_smName_##Obj)
// Protected functions
#define SM_InternalEvent(_newState_, _eventData_) \
_SM_InternalEvent(self, _newState_, _eventData_)
#define SM_GetInstance(_instance_) \
(_instance_*)(self->pInstance);
// Private functions
void _SM_ExternalEvent(SM_StateMachine* self, const SM_StateMachineConst* selfConst, BYTE newState, void* pEventData);
void _SM_InternalEvent(SM_StateMachine* self, BYTE newState, void* pEventData);
void _SM_StateEngine(SM_StateMachine* self, const SM_StateMachineConst* selfConst);
void _SM_StateEngineEx(SM_StateMachine* self, const SM_StateMachineConst* selfConst);
#define SM_DECLARE(_smName_) \
extern SM_StateMachine _smName_##Obj;
#define SM_DEFINE(_smName_, _instance_) \
SM_StateMachine _smName_##Obj = { #_smName_, _instance_, \
0, 0, 0, 0 };
#define EVENT_DECLARE(_eventFunc_, _eventData_) \
void _eventFunc_(SM_StateMachine* self, _eventData_* pEventData);
#define EVENT_DEFINE(_eventFunc_, _eventData_) \
void _eventFunc_(SM_StateMachine* self, _eventData_* pEventData)
#define GET_DECLARE(_getFunc_, _getData_) \
_getData_ _getFunc_(SM_StateMachine* self);
#define GET_DEFINE(_getFunc_, _getData_) \
_getData_ _getFunc_(SM_StateMachine* self)
#define STATE_DECLARE(_stateFunc_, _eventData_) \
static void ST_##_stateFunc_(SM_StateMachine* self, _eventData_* pEventData);
#define STATE_DEFINE(_stateFunc_, _eventData_) \
static void ST_##_stateFunc_(SM_StateMachine* self, _eventData_* pEventData)
#define GUARD_DECLARE(_guardFunc_, _eventData_) \
static BOOL GD_##_guardFunc_(SM_StateMachine* self, _eventData_* pEventData);
#define GUARD_DEFINE(_guardFunc_, _eventData_) \
static BOOL GD_##_guardFunc_(SM_StateMachine* self, _eventData_* pEventData)
#define ENTRY_DECLARE(_entryFunc_, _eventData_) \
static void EN_##_entryFunc_(SM_StateMachine* self, _eventData_* pEventData);
#define ENTRY_DEFINE(_entryFunc_, _eventData_) \
static void EN_##_entryFunc_(SM_StateMachine* self, _eventData_* pEventData)
#define EXIT_DECLARE(_exitFunc_) \
static void EX_##_exitFunc_(SM_StateMachine* self);
#define EXIT_DEFINE(_exitFunc_) \
static void EX_##_exitFunc_(SM_StateMachine* self)
#define BEGIN_STATE_MAP(_smName_) \
static const SM_StateStruct _smName_##StateMap[] = {
#define STATE_MAP_ENTRY(_stateFunc_) \
{ (SM_StateFunc)_stateFunc_ },
#define END_STATE_MAP(_smName_) \
}; \
static const SM_StateMachineConst _smName_##Const = { #_smName_, \
(sizeof(_smName_##StateMap)/sizeof(_smName_##StateMap[0])), \
_smName_##StateMap, NULL };
#define BEGIN_STATE_MAP_EX(_smName_) \
static const SM_StateStructEx _smName_##StateMap[] = {
#define STATE_MAP_ENTRY_EX(_stateFunc_) \
{ (SM_StateFunc)_stateFunc_, NULL, NULL, NULL },
#define STATE_MAP_ENTRY_ALL_EX(_stateFunc_, _guardFunc_, _entryFunc_, _exitFunc_) \
{ (SM_StateFunc)_stateFunc_, (SM_GuardFunc)_guardFunc_, (SM_EntryFunc)_entryFunc_, (SM_ExitFunc)_exitFunc_ },
#define END_STATE_MAP_EX(_smName_) \
}; \
static const SM_StateMachineConst _smName_##Const = { #_smName_, \
(sizeof(_smName_##StateMap)/sizeof(_smName_##StateMap[0])), \
NULL, _smName_##StateMap };
#define BEGIN_TRANSITION_MAP \
static const BYTE TRANSITIONS[] = { \
#define TRANSITION_MAP_ENTRY(_entry_) \
_entry_,
#define END_TRANSITION_MAP(_smName_, _eventData_) \
}; \
_SM_ExternalEvent(self, &_smName_##Const, TRANSITIONS[self->currentState], _eventData_); \
C_ASSERT((sizeof(TRANSITIONS)/sizeof(BYTE)) == (sizeof(_smName_##StateMap)/sizeof(_smName_##StateMap[0])));
#ifdef __cplusplus
}
#endif
#endif // _STATE_MACHINE_H