~gabe/flashlight-firmware/anduril2

« back to all changes in this revision

Viewing changes to ToyKeeper/spaghetti-monster/fsm-events.c

merged recent fsm branch updates

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#ifndef FSM_EVENTS_C
21
21
#define FSM_EVENTS_C
22
22
 
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)
28
 
 
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;
34
 
    }
35
 
    // if we ever fall out, that means something was different
36
 
    // (or the sequence is too long)
37
 
    return 0;
38
 
}
39
 
 
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:
49
32
 
50
33
uint8_t push_event(uint8_t ev_type) {
51
34
    ticks_since_last_event = 0;  // something happened
52
 
    uint8_t i;
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];
 
35
 
 
36
    // only click events are sent to this function
 
37
    current_event |= B_CLICK;
 
38
 
 
39
    // handle button presses
 
40
    if (ev_type == B_PRESS) {
 
41
        // set press flag
 
42
        current_event |= B_PRESS;
 
43
        // increase click counter
 
44
        if ((current_event & B_COUNT) < (B_COUNT-1)) {
 
45
            current_event ++;
 
46
        }
 
47
        return 1;  // event pushed, even if max clicks already reached
 
48
                   // (will just repeat the max over and over)
57
49
    }
58
 
    //if ((i < EV_MAX_LEN)  &&  (prev_event != ev_type)) {
59
 
    //if (prev_event != ev_type) {
60
 
    if (i < EV_MAX_LEN) {
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
63
 
    } else {
64
 
        // TODO: ... something?
65
58
    }
66
 
    return 0;  // no event pushed
67
 
}
68
 
 
69
 
// find and return last action in the current event sequence
70
 
/*
71
 
uint8_t last_event(uint8_t offset) {
72
 
    uint8_t i;
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];
76
 
    return 0;
77
 
}
78
 
*/
79
 
 
80
 
inline uint8_t last_event_num() {
81
 
    uint8_t i;
82
 
    for(i=0; current_event[i] && (i<EV_MAX_LEN); i++);
83
 
    return i;
84
 
}
85
 
 
86
 
 
87
 
void append_emission(EventPtr event, uint16_t arg) {
 
59
 
 
60
    return 0;  // unexpected event type
 
61
 
 
62
}
 
63
 
 
64
 
 
65
void append_emission(Event event, uint16_t arg) {
88
66
    uint8_t i;
89
67
    // find last entry
90
68
    for(i=0;
91
 
        (i<EMISSION_QUEUE_LEN) && (emissions[i].event != NULL);
 
69
        (i<EMISSION_QUEUE_LEN) && (emissions[i].event != EV_none);
92
70
        i++) { }
93
71
    // add new entry
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;
107
85
    }
108
 
    emissions[i].event = NULL;
 
86
    emissions[i].event = EV_none;
109
87
    emissions[i].arg = 0;
110
88
}
111
89
 
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();
116
94
    }
202
180
*/
203
181
 
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
211
189
}
212
190
 
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);
217
195
}
218
196
 
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) {
222
 
    //uint8_t err = 1;
223
 
    for (uint8_t i=0; i<(sizeof(event_sequences)/sizeof(EventPtr)); i++) {
224
 
        if (events_match(current_event, event_sequences[i])) {
225
 
            //DEBUG_FLASH;
226
 
            //err = emit(event_sequences[i], arg);
227
 
            //return err;
228
 
            emit(event_sequences[i], arg);
229
 
            return;
230
 
        }
231
 
    }
232
 
    //return err;
 
198
    ticks_since_last_event = arg;
 
199
    emit(current_event, arg);
233
200
}
234
201
 
235
202
#endif