From e96562e36df96ca755d527e479e597ae4e4e09e1 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 18 Aug 2017 18:12:17 -0600 Subject: Some early ideas for Round Table. Nothing close to compile-able yet. --- RoundTable/round-table.c | 367 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 367 insertions(+) create mode 100644 RoundTable/round-table.c (limited to 'RoundTable/round-table.c') diff --git a/RoundTable/round-table.c b/RoundTable/round-table.c new file mode 100644 index 0000000..6cd1b10 --- /dev/null +++ b/RoundTable/round-table.c @@ -0,0 +1,367 @@ +#include "tk-attiny.h" + +// +typedef uint8_t (*EventCallbackPtr)(EventPtr event, uint16_t arg); +typedef uint8_t EventCallback(EventPtr event, uint16_t arg); +// FIXME: Why does a state need a number? Why not just a function pointer? +// (I don't think it actually needs a number...) +typedef struct State { + uint8_t num; + EventCallback event_callback; +} State; +typedef struct State* StatePtr; + +volatile StatePtr current_state; +#define EV_MAX_LEN 16 +volatile uint8_t current_event[EV_MAX_LEN]; + +volatile int16_t voltage; +#ifdef USE_THERMAL_REGULATION +volatile int16_t temperature; +#endif + +#define A_ENTER_STATE 1 +#define A_LEAVE_STATE 2 +#define A_TICK 3 +#define A_PRESS 4 +#define A_HOLD_START 5 +#define A_HOLD_TICK 6 +#define A_RELEASE 7 +#define A_RELEASE_TIMEOUT 8 +// TODO: add events for over/under-heat conditions (with parameter for severity) +#define A_OVERHEATING 9 +#define A_UNDERHEATING 10 +// TODO: add events for low voltage conditions +#define A_VOLTAGE_LOW 11 +#define A_VOLTAGE_CRITICAL 12 + +// TODO: maybe compare events by number instead of pointer? +// (number = index in event types array) +// (comparison would use full event content, but send off index to callbacks) +// (saves space by using uint8_t instead of a pointer) +// (also eliminates the need to duplicate single-entry events like for voltage or timer tick) + +// Event types +typedef PROGMEM const uint8_t Event; +typedef Event* EventPtr; +Event EV_enter_state[] = { + A_ENTER_STATE, + 0 } ; +Event EV_leave_state[] = { + A_LEAVE_STATE, + 0 } ; +Event EV_tick[] = { + A_TICK, + 0 } ; +Event EV_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_press_release[] = { + A_PRESS, + A_RELEASE, + 0 }; +#define EV_1click EV_press_release_timeout +Event EV_press_release_timeout[] = { + A_PRESS, + A_RELEASE, + A_RELEASE_TIMEOUT, + 0 }; +#define EV_hold EV_press_hold +// FIXME: Should holds use "start+tick" or just "tick" with a tick number? +// Or "start+tick" with a tick number? +Event EV_press_hold[] = { + A_PRESS, + A_HOLD_TIMEOUT, + 0 }; +Event EV_press_hold_release[] = { + A_PRESS, + A_HOLD_TIMEOUT, + A_RELEASE, + 0 }; +Event EV_press_release_press[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + 0 }; +Event EV_press_release_press_release[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + 0 }; +#define EV_2clicks EV_press_release_press_release_timeout +Event EV_press_release_press_release_timeout[] = { + A_PRESS, + A_RELEASE, + A_PRESS, + A_RELEASE, + A_RELEASE_TIMEOUT, + 0 }; +// ... and so on + +// A list of event types for easy iteration +EventPtr event_sequences[] = { + EV_press, + EV_press_release, + EV_press_release_timeout, + EV_press_release_press, + EV_press_release_press_release, + EV_press_release_press_release_timeout, + // ... +}; + +// TODO: move this to a separate UI-specific file +/* +State states[] = { + +}; +*/ + +// TODO? add events to a queue when inside an interrupt +// instead of calling the event functions directly? +// (then empty the queue in main loop?) + +// TODO? new delay() functions which handle queue consumption? +// TODO? new interruptible delay() functions? + +//static uint8_t ticks_since_last_event = 0; // TODO: 16 bits? + +void WDT_tick() { + timer ++; + + //static uint8_t hold_ticks = 0; // TODO: 16 bits? + + // callback on each timer tick + emit(EV_tick, timer); + + // if time since last event exceeds timeout, + // append timeout to current event sequence, then + // send event to current state callback + // //hold_event(ticks) + // //emit(EV_press_hold, hold_ticks); + // emit_current(hold_ticks); + // or + // //release_timeout() + // //emit(EV_press_release_timeout, 0); + // emit_current(0); + + // add 4-step voltage / temperature thing? + // with averaged values, + // once every N ticks? +} + +void button_change_interrupt() { + // TODO: debounce a little + + //ticks_since_last_event = 0; // something happened + + // TODO: add event to current sequence + + // check if sequence matches any defined sequences + // if so, send event to current state callback + emit_current(0); +} + +uint8_t emit_current(uint16_t arg) { + uint8_t err = 1; + for (uint8_t i=0; i