20
20
#ifndef FSM_EVENTS_C
21
21
#define FSM_EVENTS_C
23
// TODO: maybe compare events by number instead of pointer?
24
// (number = index in event types array)
25
// (comparison would use full event content, but send off index to callbacks)
26
// (saves space by using uint8_t instead of a pointer)
27
// (also eliminates the need to duplicate single-entry events like for voltage or timer tick)
29
// return 1 if (a == b), 0 otherwise
30
uint8_t compare_event_sequences(uint8_t *a, const uint8_t *b) {
31
for(uint8_t i=0; (i<EV_MAX_LEN) && (a[i] == pgm_read_byte(b+i)); i++) {
32
// end of zero-terminated sequence
33
if (a[i] == 0) return 1;
35
// if we ever fall out, that means something was different
36
// (or the sequence is too long)
40
23
void empty_event_sequence() {
41
for(uint8_t i=0; i<EV_MAX_LEN; i++) current_event[i] = 0;
24
current_event = EV_none;
42
25
// when the user completes an input sequence, interrupt any running timers
43
26
// to cancel any delays currently in progress
44
27
// This eliminates a whole bunch of extra code:
50
33
uint8_t push_event(uint8_t ev_type) {
51
34
ticks_since_last_event = 0; // something happened
53
//uint8_t prev_event = 0; // never push the same event twice in a row
54
for(i=0; current_event[i] && (i<EV_MAX_LEN); i++) {
55
// this doesn't actually seem to be necessary any more...
56
//prev_event = current_event[i];
36
// only click events are sent to this function
37
current_event |= B_CLICK;
39
// handle button presses
40
if (ev_type == B_PRESS) {
42
current_event |= B_PRESS;
43
// increase click counter
44
if ((current_event & B_COUNT) < (B_COUNT-1)) {
47
return 1; // event pushed, even if max clicks already reached
48
// (will just repeat the max over and over)
58
//if ((i < EV_MAX_LEN) && (prev_event != ev_type)) {
59
//if (prev_event != ev_type) {
61
current_event[i] = ev_type;
50
// handle button releases
51
else if (ev_type == B_RELEASE) {
52
// clear the press flag
53
current_event &= (~B_PRESS);
54
// if a "hold" event just ended, set the timeout flag
55
// to indicate that the event is done and can be cleared
56
if (current_event & B_HOLD) { current_event |= B_TIMEOUT; }
62
57
return 1; // event pushed
64
// TODO: ... something?
66
return 0; // no event pushed
69
// find and return last action in the current event sequence
71
uint8_t last_event(uint8_t offset) {
73
for(i=0; current_event[i] && (i<EV_MAX_LEN); i++);
74
if (i == EV_MAX_LEN) return current_event[EV_MAX_LEN-offset];
75
else if (i >= offset) return current_event[i-offset];
80
inline uint8_t last_event_num() {
82
for(i=0; current_event[i] && (i<EV_MAX_LEN); i++);
87
void append_emission(EventPtr event, uint16_t arg) {
60
return 0; // unexpected event type
65
void append_emission(Event event, uint16_t arg) {
91
(i<EMISSION_QUEUE_LEN) && (emissions[i].event != NULL);
69
(i<EMISSION_QUEUE_LEN) && (emissions[i].event != EV_none);
94
72
if (i < EMISSION_QUEUE_LEN) {
105
83
emissions[i].event = emissions[i+1].event;
106
84
emissions[i].arg = emissions[i+1].arg;
108
emissions[i].event = NULL;
86
emissions[i].event = EV_none;
109
87
emissions[i].arg = 0;
112
90
void process_emissions() {
113
while (emissions[0].event != NULL) {
91
while (emissions[0].event != EV_none) {
114
92
emit_now(emissions[0].event, emissions[0].arg);
115
93
delete_first_emission();
204
182
// Call stacked callbacks for the given event until one handles it.
205
uint8_t emit_now(EventPtr event, uint16_t arg) {
183
uint8_t emit_now(Event event, uint16_t arg) {
206
184
for(int8_t i=state_stack_len-1; i>=0; i--) {
207
185
uint8_t err = state_stack[i](event, arg);
208
186
if (! err) return 0;
210
188
return 1; // event not handled
213
void emit(EventPtr event, uint16_t arg) {
191
void emit(Event event, uint16_t arg) {
214
192
// add this event to the queue for later,
215
193
// so we won't use too much time during an interrupt
216
194
append_emission(event, arg);
219
// Search the pre-defined event list for one matching what the user just did,
220
// and emit it if one was found.
221
197
void emit_current_event(uint16_t arg) {
223
for (uint8_t i=0; i<(sizeof(event_sequences)/sizeof(EventPtr)); i++) {
224
if (events_match(current_event, event_sequences[i])) {
226
//err = emit(event_sequences[i], arg);
228
emit(event_sequences[i], arg);
198
ticks_since_last_event = arg;
199
emit(current_event, arg);