-
Notifications
You must be signed in to change notification settings - Fork 0
/
tinyfsm.c
157 lines (133 loc) · 4.35 KB
/
tinyfsm.c
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
/**
* @file tinyfsm.c
* @brief Tiny Finite State Machine (FSM) framework.
*
* @authored by Edwin Koch
* @date 10. June 2024
*
* @license MIT License
* See the LICENSE file in the project root for more information.
*/
#include "tinyfsm.h"
// No-op lock function for single-threaded use
static unsigned int _singleThreadedLock(fsmMutex_t mutexObject) {
return 0; // Success
}
// No-op unlock function for single-threaded use
static unsigned int _singleThreadedUnlock(fsmMutex_t mutexObject) {
return 0; // Success
}
void fsmInit(
fsm_t* fsmObject,
fsmStateRoutine_t entryState,
fsmAction_t entryAction,
fsmAction_t fsmEndingAction,
fsmMutex_t mutexObject,
fsmMutexOps_t mutexOps)
{
fsmObject->entryState = entryState;
fsmObject->previousState = entryState;
fsmObject->currentState = entryState;
fsmObject->nextState = entryState;
fsmObject->entryAction = entryAction;
fsmObject->fsmEndingAction = fsmEndingAction;
fsmObject->action = entryAction;
fsmObject->state = STATE_START;
fsmObject->mutexObject = mutexObject;
fsmObject->mutexOps = mutexOps;
fsmObject->initialized = 1;
}
void fsmInitSingleThreaded(
fsm_t* fsmObject,
fsmStateRoutine_t entryState,
fsmAction_t entryAction,
fsmAction_t fsmEndingAction)
{
static fsmMutexOps_t singleThreadedOps = {
.lock = _singleThreadedLock,
.unlock = _singleThreadedUnlock
};
fsmObject->entryState = entryState;
fsmObject->previousState = entryState;
fsmObject->currentState = entryState;
fsmObject->nextState = entryState;
fsmObject->entryAction = entryAction;
fsmObject->fsmEndingAction = fsmEndingAction;
fsmObject->action = entryAction;
fsmObject->state = STATE_START;
fsmObject->mutexObject = 0;
fsmObject->mutexOps = singleThreadedOps;
fsmObject->initialized = 1;
}
fsmStatus_t fsmRun(fsm_t* fsmObject)
{
// cease execution if not initialized
if (fsmObject->initialized != 1) return FSM_NOT_INITIALIZED;
// mutex lock
if (fsmObject->mutexOps.lock(fsmObject->mutexObject) != 0) return FSM_MUTEX_LOCKED;
switch (fsmObject->state) {
case STATE_START:
fsmObject->entryAction();
fsmObject->state = STATE_NO_CHANGE;
break;
case STATE_NO_CHANGE:
fsmObject->mutexOps.unlock(fsmObject->mutexObject);
fsmObject->currentState();
// wait until mutex is unlocked and then lock it
while(fsmObject->mutexOps.lock(fsmObject->mutexObject) != 0);
break;
case STATE_TRANSITION:
// Change state
fsmObject->previousState = fsmObject->currentState;
fsmObject->currentState = fsmObject->nextState;
fsmObject->action();
fsmObject->state = STATE_NO_CHANGE;
break;
case STATE_END_FSM:
// End the finite state machine
fsmObject->previousState = fsmObject->entryState;
fsmObject->currentState = fsmObject->entryState;
fsmObject->nextState = fsmObject->entryState;
fsmObject->fsmEndingAction();
fsmObject->state = STATE_NO_CHANGE;
// mutex unlock
fsmObject->mutexOps.unlock(fsmObject->mutexObject);
return FSM_ENDED;
default:
// Invalid state
fsmObject->mutexOps.unlock(fsmObject->mutexObject);
return FSM_FAULT_UNKNOWN_STATE_RETURN;
}
// mutex unlock
fsmObject->mutexOps.unlock(fsmObject->mutexObject);
return FSM_RUNNING;
}
void fsmTransitionState(
fsm_t* fsmObject,
fsmStateRoutine_t nextState,
fsmAction_t action)
{
// cease execution if not initialized
if (fsmObject->initialized != 1) return;
// mutex lock
if (fsmObject->mutexOps.lock(fsmObject->mutexObject) != 0) return;
fsmObject->state = STATE_TRANSITION;
fsmObject->action = action;
fsmObject->nextState = nextState;
// mutex unlock
fsmObject->mutexOps.unlock(fsmObject->mutexObject);
}
void fsmEndFSM(fsm_t* fsmObject)
{
// cease execution if not initialized
if (fsmObject->initialized != 1) return;
// mutex lock
if (fsmObject->mutexOps.lock(fsmObject->mutexObject) != 0) return;
fsmObject->state = STATE_END_FSM;
// mutex unlock
fsmObject->mutexOps.unlock(fsmObject->mutexObject);
}
void fsmNoAction()
{
// No action function
}