diff options
Diffstat (limited to 'spaghetti-monster/fsm-events.h')
| -rw-r--r-- | spaghetti-monster/fsm-events.h | 485 |
1 files changed, 485 insertions, 0 deletions
diff --git a/spaghetti-monster/fsm-events.h b/spaghetti-monster/fsm-events.h new file mode 100644 index 0000000..2721303 --- /dev/null +++ b/spaghetti-monster/fsm-events.h @@ -0,0 +1,485 @@ +/* + * fsm-events.h: Event-handling functions for SpaghettiMonster. + * + * Copyright (C) 2017 Selene ToyKeeper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FSM_EVENTS_H +#define FSM_EVENTS_H + +#include <avr/pgmspace.h> + +// typedefs +typedef PROGMEM const uint8_t Event; +typedef Event * EventPtr; +typedef struct Emission { + EventPtr event; + uint16_t arg; +} Emission; + +#define EVENT_HANDLED 0 +#define EVENT_NOT_HANDLED 1 +#define MISCHIEF_MANAGED EVENT_HANDLED +#define MISCHIEF_NOT_MANAGED EVENT_NOT_HANDLED + +#ifndef MAX_CLICKS +#define MAX_CLICKS 4 +#endif + +#define EV_MAX_LEN ((MAX_CLICKS*2)+3) +uint8_t current_event[EV_MAX_LEN]; +// at 0.016 ms per tick, 255 ticks = 4.08 s +// TODO: 16 bits? +static volatile uint16_t ticks_since_last_event = 0; + +// timeout durations in ticks (each tick 1/60th s) +#ifndef HOLD_TIMEOUT +#define HOLD_TIMEOUT 24 +#endif +#ifndef RELEASE_TIMEOUT +#define RELEASE_TIMEOUT 24 +#endif + +#define A_ENTER_STATE 1 +#define A_LEAVE_STATE 2 +#define A_REENTER_STATE 3 +#define A_TICK 4 +#define A_PRESS 5 +#define A_HOLD 6 +#define A_RELEASE 7 +#define A_RELEASE_TIMEOUT 8 +#define A_OVERHEATING 9 +#define A_UNDERHEATING 10 +#define A_VOLTAGE_LOW 11 +//#define A_VOLTAGE_CRITICAL 12 +#define A_DEBUG 255 // test event for debugging + +// Event types +Event EV_debug[] = { + A_DEBUG, + 0 } ; +Event EV_enter_state[] = { + A_ENTER_STATE, + 0 } ; +Event EV_leave_state[] = { + A_LEAVE_STATE, + 0 } ; +Event EV_reenter_state[] = { + A_REENTER_STATE, + 0 } ; +Event EV_tick[] = { + A_TICK, + 0 } ; +#ifdef USE_LVP +Event EV_voltage_low[] = { + A_VOLTAGE_LOW, + 0 } ; +#endif +#ifdef USE_THERMAL_REGULATION +Event EV_temperature_high[] = { + A_OVERHEATING, + 0 } ; +Event EV_temperature_low[] = { + A_UNDERHEATING, + 0 } ; +#endif +Event EV_click1_press[] = { + A_PRESS, + 0 }; +// shouldn't normally happen, but UI might reset event while button is down +// so a release with no recorded prior hold could be possible +Event EV_release[] = { + A_RELEASE, + 0 }; +Event EV_click1_release[] = { + A_PRESS, + A_RELEASE, + 0 }; +#define EV_1click EV_click1_complete +Event EV_click1_complete[] = { + A_PRESS, + A_RELEASE, + A_RELEASE_TIMEOUT, + 0 }; +#define EV_hold EV_click1_hold +// FIXME: Should holds use "start+tick" or just "tick" with a tick number? +// Or "start+tick" with a tick number? +Event EV_click1_hold[] = { + A_PRESS, + A_HOLD, + 0 }; +Event EV_click1_hold_release[] = { + A_PRESS, + A_HOLD, + A_RELEASE, + 0 }; +#if MAX_CLICKS >= 2 +Event EV_click2_press[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + 0 }; +Event EV_click2_hold[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_HOLD, + 0 }; +Event EV_click2_hold_release[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_HOLD, + A_RELEASE, + 0 }; +Event EV_click2_release[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + 0 }; +#define EV_2clicks EV_click2_complete +Event EV_click2_complete[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_RELEASE_TIMEOUT, + 0 }; +#endif // MAX_CLICKS >= 2 +#if MAX_CLICKS >= 3 +Event EV_click3_press[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + 0 }; +Event EV_click3_hold[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_HOLD, + 0 }; +Event EV_click3_hold_release[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_HOLD, + A_RELEASE, + 0 }; +Event EV_click3_release[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + 0 }; +#define EV_3clicks EV_click3_complete +Event EV_click3_complete[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_RELEASE_TIMEOUT, + 0 }; +#endif // MAX_CLICKS >= 3 +#if MAX_CLICKS >= 4 +#define EV_4clicks EV_click4_complete +Event EV_click4_complete[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_RELEASE_TIMEOUT, + 0 }; +#endif +#if MAX_CLICKS >= 5 +#define EV_5clicks EV_click5_complete +Event EV_click5_complete[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_RELEASE_TIMEOUT, + 0 }; +#endif +#if MAX_CLICKS >= 6 +#define EV_6clicks EV_click6_complete +Event EV_click6_complete[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_RELEASE_TIMEOUT, + 0 }; +#endif +#if MAX_CLICKS >= 7 +#define EV_7clicks EV_click7_complete +Event EV_click7_complete[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_RELEASE_TIMEOUT, + 0 }; +#endif +#if MAX_CLICKS >= 8 +#define EV_8clicks EV_click8_complete +Event EV_click8_complete[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_RELEASE_TIMEOUT, + 0 }; +#endif +#if MAX_CLICKS >= 9 +#define EV_9clicks EV_click9_complete +Event EV_click9_complete[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_RELEASE_TIMEOUT, + 0 }; +#endif +#if MAX_CLICKS >= 10 +#define EV_10clicks EV_click10_complete +Event EV_click10_complete[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_RELEASE_TIMEOUT, + 0 }; +#endif +#if MAX_CLICKS >= 11 +#define EV_11clicks EV_click11_complete +Event EV_click11_complete[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_RELEASE_TIMEOUT, + 0 }; +#endif +#if MAX_CLICKS >= 12 +#define EV_12clicks EV_click12_complete +Event EV_click12_complete[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_RELEASE_TIMEOUT, + 0 }; +#endif +// ... and so on + +// A list of button event types for easy iteration +EventPtr event_sequences[] = { + EV_click1_press, + EV_release, + EV_click1_release, + EV_click1_complete, + EV_click1_hold, + EV_click1_hold_release, + #if MAX_CLICKS >= 2 + EV_click2_press, + EV_click2_hold, + EV_click2_hold_release, + EV_click2_release, + EV_click2_complete, + #endif + #if MAX_CLICKS >= 3 + EV_click3_press, + EV_click3_hold, + EV_click3_hold_release, + EV_click3_release, + EV_click3_complete, + #endif + #if MAX_CLICKS >= 4 + EV_click4_complete, + #endif + #if MAX_CLICKS >= 5 + EV_click5_complete, + #endif + #if MAX_CLICKS >= 6 + EV_click6_complete, + #endif + #if MAX_CLICKS >= 7 + EV_click7_complete, + #endif + #if MAX_CLICKS >= 8 + EV_click8_complete, + #endif + #if MAX_CLICKS >= 9 + EV_click9_complete, + #endif + #if MAX_CLICKS >= 10 + EV_click10_complete, + #endif + #if MAX_CLICKS >= 11 + EV_click11_complete, + #endif + #if MAX_CLICKS >= 12 + EV_click12_complete, + #endif + // ... +}; + +#define events_match(a,b) compare_event_sequences(a,b) +// return 1 if (a == b), 0 otherwise +uint8_t compare_event_sequences(uint8_t *a, const uint8_t *b); +void empty_event_sequence(); +uint8_t push_event(uint8_t ev_type); +// uint8_t last_event(uint8_t offset); +inline uint8_t last_event_num(); + + +#define EMISSION_QUEUE_LEN 16 +// no comment about "volatile emissions" +volatile Emission emissions[EMISSION_QUEUE_LEN]; + +void append_emission(EventPtr event, uint16_t arg); +void delete_first_emission(); +void process_emissions(); +//#define emit_now emit +uint8_t emit_now(EventPtr event, uint16_t arg); +void emit(EventPtr event, uint16_t arg); +void emit_current_event(uint16_t arg); + +uint8_t nice_delay_ms(uint16_t ms); +//uint8_t nice_delay_4ms(uint8_t ms); +//uint8_t nice_delay_s(); +inline void interrupt_nice_delays(); + +#endif |
