-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathstateHandler.h
153 lines (97 loc) · 3.34 KB
/
stateHandler.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
#ifndef STATEHANDLER_H
#define STATEHANDLER_H
#include <IHWLayer.h>
////////////////// EXAMPLE //////////////////////
/*
enum stateNames {START,SHIFT};
STATEFUNCS
STATE(START)
ON_ENTER
ALWAYS
ON_EVENT
EVENTCHECK(BTN_DOWN,ShiftButton)
CHANGE_STATE(SHIFT);
END_EVENTCHECK
ON_EXIT
END_STATE
STATE(SHIFT)
ON_ENTER
ALWAYS
ON_EVENT
EVENTCHECK(BTN_UP,ShiftButton)
CHANGE_STATE(START);
END_EVENTCHECK
ON_EXIT
END_STATE
END_STATEFUNCS
*/
////// Marcos for implicitly defining run() which
////// processes the current state
////////////////////////////////////////////////
#define STATEFUNCS uint8_t states::activeState = 0;\
bool states::newState = true;\
bool states::eventProcessed = true;\
hardwareEvent states::lastEvent;\
void states::run() {
#define ANYSTATE
#define ANYSTATE_ENTER if(newState) {
#define ANYSTATE_EVENT } if (!eventProcessed) {
#define END_ANYSTATE } switch (activeState) {
#define STATE(N) case N:
#define ON_ENTER if (newState) { // code that is executed everytime this state is run for the first time
#define ALWAYS newState = false;} // code that is executed everytime this state is active
#define ON_EVENT if (!eventProcessed) { // code that is executed when there is a new event
#define ON_EXIT eventProcessed = true;}if (newState) { // code that is executed when this state is run for the last time
#define END_STATE }break;
#define END_STATEFUNCS default: break; }}
#define CHANGE_STATE(N) activeState = N; newState = true; // switch to different state in next run
#define RERUN_STATE newState = true; eventProcessed = true; return; // re-renter the current state in next run.
// In ANYSTATE, this will NOT enter the real state!
////// Macros for analysing the last read event
////////////////////////////////////////////////
#define DONT_CARE_NUMBER lastEvent.number
#define THIS_NUMBER lastEvent.number
// check for type and number
#define EVENTCHECK(...) EVENTCHECK_(__VA_ARGS__)
#define EVENTCHECK_(TY,NU) if((lastEvent.type == IHWLayer::TY) && (lastEvent.number == NU) ) {
#define END_EVENTCHECK }
// check for type and if number is inside array
// if match has been found it will be written to VAR
#define EVENTCHECK_ARRAY(TY,AR,VAR) if ((lastEvent.type == IHWLayer::TY)) {\
for (uint8_t VAR = 0; VAR<sizeof(AR); VAR++) {\
if (lastEvent.number == AR[VAR]) {
#define END_EVENTCHECK_ARRAY }}}
////// HOOKS
////////////////////////////////////////////////
// where to run current state
#define RUN_ACTIVE_STATE states::run();
// add a new event to be processed during next run of state
#define ADD_EVENT(E) states::queueEvent(E);
// for use as event receiver of hardware layer
#define STATEHANDLER states::queueEvent
// use active state outside of this object
#define ACTIVESTATE states::getActiveState()
// re-trigger ON_ENTER on active state
#define RETRIGGER_ACTIVE_STATE states::rerunState();
class states {
public:
static void queueEvent(hardwareEvent event) {
if (eventProcessed) {
lastEvent = event;
eventProcessed = false;
}
}
static void run();
static uint8_t getActiveState() {
return activeState;
}
static void rerunState() {
newState = true;
}
private:
static uint8_t activeState;
static bool newState;
static bool eventProcessed;
static hardwareEvent lastEvent;
};
#endif