-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathqepn.c
More file actions
323 lines (288 loc) · 14.6 KB
/
qepn.c
File metadata and controls
323 lines (288 loc) · 14.6 KB
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
/*****************************************************************************
* Product: QEP-nano implemenation
* Last Updated for Version: 4.1.03
* Date of the Last Update: Feb 15, 2010
*
* Q u a n t u m L e a P s
* ---------------------------
* innovating embedded systems
*
* Copyright (C) 2002-2010 Quantum Leaps, LLC. All rights reserved.
*
* This software may be distributed and modified under the terms of the GNU
* General Public License version 2 (GPL) as published by the Free Software
* Foundation and appearing in the file GPL.TXT included in the packaging of
* this file. Please note that GPL Section 2[b] requires that all works based
* on this software must also be made publicly available under the terms of
* the GPL ("Copyleft").
*
* Alternatively, this software may be distributed and modified under the
* terms of Quantum Leaps commercial licenses, which expressly supersede
* the GPL and are specifically designed for licensees interested in
* retaining the proprietary status of their code.
*
* Contact information:
* Quantum Leaps Web site: http://www.quantum-leaps.com
* e-mail: info@quantum-leaps.com
*****************************************************************************/
#include "qpn_port.h" /* QP-nano port */
#ifndef Q_NHSM
Q_DEFINE_THIS_MODULE(qepn)
#endif
/**
* \file
* \ingroup qepn qfn
* QEP-nano implementation.
*/
/** empty signal for internal use only */
#define QEP_EMPTY_SIG_ 0
/** maximum depth of state nesting (including the top level), must be >= 2 */
#define QEP_MAX_NEST_DEPTH_ 5
/*..........................................................................*/
/*lint -e970 -e971 */ /* ignore MISRA rules 13 and 14 in this function */
char const Q_ROM * Q_ROM_VAR QP_getVersion(void) {
static char const Q_ROM Q_ROM_VAR version[] = {
((QP_VERSION >> 12) & 0xF) + '0',
'.',
((QP_VERSION >> 8) & 0xF) + '0',
'.',
((QP_VERSION >> 4) & 0xF) + '0',
(QP_VERSION & 0xF) + '0',
'\0'
};
return version;
}
#ifndef Q_NFSM
/*..........................................................................*/
void QFsm_init(QFsm *me) {
(void)(*me->state)(me); /* execute the top-most initial transition */
Q_SIG(me) = (QSignal)Q_ENTRY_SIG;
(void)(*me->state)(me); /* enter the target */
}
/*..........................................................................*/
#ifndef QK_PREEMPTIVE
void QFsm_dispatch(QFsm *me) {
#else
void QFsm_dispatch(QFsm *me) Q_REENTRANT {
#endif
QStateHandler s = me->state;
if ((*s)(me) == Q_RET_TRAN) { /* transition taken? */
Q_SIG(me) = (QSignal)Q_EXIT_SIG;
(void)(*s)(me); /* exit the source */
Q_SIG(me) = (QSignal)Q_ENTRY_SIG;
(void)(*me->state)(me); /* enter the target */
}
}
#endif /* Q_NFSM */
#ifndef Q_NHSM
/*..........................................................................*/
QState QHsm_top(QHsm *me) {
(void)me; /* supress the "unused argument" compiler warning */
return Q_IGNORED(); /* the top state ignores all events */
}
/*..........................................................................*/
void QHsm_init(QHsm *me) {
//xil_printf("\n\rInside QHSM_init before anything");
QStateHandler t;
Q_ALLEGE((*me->state)(me) == Q_RET_TRAN);/* initial tran. must be taken */
//xil_printf("\n\rInside QFSM_init after Allege");
t = (QStateHandler)&QHsm_top; /* an HSM starts in the top state */
do { /* drill into the target hierarchy... */
//xil_printf("\n\rInside QFSM_init in do");
QStateHandler path[QEP_MAX_NEST_DEPTH_];
int8_t ip = (int8_t)0;
//xil_printf("\n\rInside QFSM_init after QSTATE HANDLER PATH");
path[0] = me->state;
Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_;
// xil_printf("\n\rInside QFSM_init after Q_SIG(me)");
(void)(*me->state)(me);
// xil_printf("\n\rInside QFSM_init after (void)(*me->state)(me)");
while (me->state != t) {
path[++ip] = me->state;
(void)(*me->state)(me);
}
//xil_printf("\n\rInside QFSM_init after while");
me->state = path[0];
/* entry path must not overflow */
Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
//xil_printf("\n\rInside QFSM_init after assert");
Q_SIG(me) = (QSignal)Q_ENTRY_SIG;
//xil_printf("\n\rInside QFSM_init Q_SIG assignemnt");
do { /* retrace the entry path in reverse (correct) order... */
(void)(*path[ip])(me); /* enter path[ip] */
} while ((--ip) >= (int8_t)0);
//xil_printf("\n\rInside QFSM_init after second do");
t = path[0];
Q_SIG(me) = (QSignal)Q_INIT_SIG;
// xil_printf("\n\rInside QFSM_init after second Q_SIG");
// xil_printf("\n\rQ_RET_TRAN =%d", Q_RET_TRAN);
// xil_printf("\n\r(*t)(me) =%d", (*t)(me));
} while ((*t)(me) == Q_RET_TRAN); /* initial transition handled? */
// xil_printf("\n\rInside QFSM_init after while");
me->state = t;
//xil_printf("\n\rInside QFSM_init at end");
}
/*..........................................................................*/
#ifndef QK_PREEMPTIVE
void QHsm_dispatch(QHsm *me) {
#else
void QHsm_dispatch(QHsm *me) Q_REENTRANT {
#endif
QStateHandler path[QEP_MAX_NEST_DEPTH_];
QStateHandler s;
QStateHandler t;
QState r;
t = me->state; /* save the current state */
do { /* process the event hierarchically... */
s = me->state;
r = (*s)(me); /* invoke state handler s */
} while (r == Q_RET_SUPER);
if (r == Q_RET_TRAN) { /* transition taken? */
int8_t ip = (int8_t)(-1); /* transition entry path index */
int8_t iq; /* helper transition entry path index */
path[0] = me->state; /* save the target of the transition */
path[1] = t;
while (t != s) { /* exit current state to transition source s... */
Q_SIG(me) = (QSignal)Q_EXIT_SIG; /* find superstate of t */
if ((*t)(me) == Q_RET_HANDLED) { /* exit action handled? */
Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_;
(void)(*t)(me); /* find superstate of t */
}
t = me->state; /* me->state holds the superstate */
}
t = path[0]; /* target of the transition */
if (s == t) { /* (a) check source==target (transition to self) */
Q_SIG(me) = (QSignal)Q_EXIT_SIG;
(void)(*s)(me); /* exit the source */
ip = (int8_t)0; /* enter the target */
}
else {
Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_;
(void)(*t)(me); /* find superstate of target */
t = me->state;
if (s == t) { /* (b) check source==target->super */
ip = (int8_t)0; /* enter the target */
}
else {
Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_;
(void)(*s)(me); /* find superstate of source */
/* (c) check source->super==target->super */
if (me->state == t) {
Q_SIG(me) = (QSignal)Q_EXIT_SIG;
(void)(*s)(me); /* exit the source */
ip = (int8_t)0; /* enter the target */
}
else {
/* (d) check source->super==target */
if (me->state == path[0]) {
Q_SIG(me) = (QSignal)Q_EXIT_SIG;
(void)(*s)(me); /* exit the source */
}
else { /* (e) check rest of source==target->super->super..
* and store the entry path along the way
*/
iq = (int8_t)0; /* indicate that LCA not found */
ip = (int8_t)1; /* enter target and its superstate */
path[1] = t; /* save the superstate of target */
t = me->state; /* save source->super */
Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_;
r = (*path[1])(me); /* find target->super->super */
while (r == Q_RET_SUPER) {
path[++ip] = me->state; /* store the entry path */
if (me->state == s) { /* is it the source? */
iq = (int8_t)1; /* indicate that LCA found */
/* entry path must not overflow */
Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
--ip; /* do not enter the source */
r = Q_RET_HANDLED; /* terminate the loop */
}
else { /* it is not the source, keep going up */
r = (*me->state)(me); /* superstate of t */
}
}
if (iq == (int8_t)0) { /* the LCA not found yet? */
/* entry path must not overflow */
Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
Q_SIG(me) = (QSignal)Q_EXIT_SIG;
(void)(*s)(me); /* exit the source */
/* (f) check the rest of source->super
* == target->super->super...
*/
iq = ip;
r = Q_RET_IGNORED; /* indicate LCA NOT found */
do {
s = path[iq];
if (t == s) { /* is this the LCA? */
r = Q_RET_HANDLED;/* indicate LCA found */
ip = (int8_t)(iq - 1);/*do not enter LCA*/
iq = (int8_t)(-1);/* terminate the loop */
}
else {
--iq; /* try lower superstate of target */
}
} while (iq >= (int8_t)0);
if (r != Q_RET_HANDLED) { /* LCA not found yet? */
/* (g) check each source->super->...
* for each target->super...
*/
r = Q_RET_IGNORED; /* keep looping */
do {
/* exit t unhandled? */
Q_SIG(me) = (QSignal)Q_EXIT_SIG;
if ((*t)(me) == Q_RET_HANDLED) {
Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_;
(void)(*t)(me); /* find super of t */
}
t = me->state; /* set to super of t */
iq = ip;
do {
s = path[iq];
if (t == s) { /* is this LCA? */
/* do not enter LCA */
ip = (int8_t)(iq - 1);
iq = (int8_t)(-1);/*break inner */
r = Q_RET_HANDLED;/*break outer */
}
else {
--iq;
}
} while (iq >= (int8_t)0);
} while (r != Q_RET_HANDLED);
}
}
}
}
}
}
/* retrace the entry path in reverse (desired) order... */
Q_SIG(me) = (QSignal)Q_ENTRY_SIG;
for (; ip >= (int8_t)0; --ip) {
(void)(*path[ip])(me); /* enter path[ip] */
}
t = path[0]; /* stick the target into register */
me->state = t; /* update the current state */
/* drill into the target hierarchy... */
Q_SIG(me) = (QSignal)Q_INIT_SIG;
while ((*t)(me) == Q_RET_TRAN) {
ip = (int8_t)0;
path[0] = me->state;
Q_SIG(me) = (QSignal)QEP_EMPTY_SIG_;
(void)(*me->state)(me); /* find the superstate */
while (me->state != t) {
path[++ip] = me->state;
(void)(*me->state)(me); /* find the superstate */
}
me->state = path[0];
/* entry path must not overflow */
Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
Q_SIG(me) = (QSignal)Q_ENTRY_SIG;
do { /* retrace the entry path in reverse (correct) order... */
(void)(*path[ip])(me); /* enter path[ip] */
} while ((--ip) >= (int8_t)0);
t = path[0];
Q_SIG(me) = (QSignal)Q_INIT_SIG;
}
}
me->state = t; /* set new state or restore the current state */
}
#endif /* Q_NHSM */