From 6b41b5df92128c8810cbe14fd56258d90c3bb2b2 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 11 Nov 2018 06:09:07 -0700 Subject: Several fixes... - Made momentary+lockout modes smaller and work better. - Fixed buggy timing on hold events; made ticks_since_last_event reset when it should. - Reduced ROM size by caching volatile ticks_since_last_event sometimes. - Swapped what the top Event bit means, because it makes event handlers easier to write. - Made the maximum click event keep triggering if user keeps pressing, instead of dropping everything after the limit. --- spaghetti-monster/anduril/anduril.c | 54 +++++++++++++------------------------ spaghetti-monster/fsm-events.c | 13 ++++++--- spaghetti-monster/fsm-events.h | 6 ++--- spaghetti-monster/fsm-wdt.c | 23 ++++++++++------ 4 files changed, 46 insertions(+), 50 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index de4f996..4c3ccd7 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -1166,25 +1166,21 @@ uint8_t goodnight_state(Event event, uint16_t arg) { uint8_t lockout_state(Event event, uint16_t arg) { #ifdef MOON_DURING_LOCKOUT_MODE // momentary(ish) moon mode during lockout - // not all presses will be counted; - // it depends on what is in the master event_sequences table - if (arg == 0) { // Only turn on/off when button state changes - if (! (event & B_SYSTEM)) { // event is a button click type - if (event & B_PRESS) { // button is being held - #ifdef LOCKOUT_MOON_LOWEST - // Use lowest moon configured - uint8_t lvl = ramp_smooth_floor; - if (ramp_discrete_floor < lvl) lvl = ramp_discrete_floor; - set_level(lvl); - #else - // Use moon from current ramp - set_level(nearest_level(1)); - #endif - } - else { // button not being held - set_level(0); - } - } + // button is being held + if ((event & (B_CLICK | B_PRESS)) == (B_CLICK | B_PRESS)) { + #ifdef LOCKOUT_MOON_LOWEST + // Use lowest moon configured + uint8_t lvl = ramp_smooth_floor; + if (ramp_discrete_floor < lvl) lvl = ramp_discrete_floor; + set_level(lvl); + #else + // Use moon from current ramp + set_level(nearest_level(1)); + #endif + } + // button was released + else if ((event & (B_CLICK | B_PRESS)) == (B_CLICK)) { + set_level(0); } #endif @@ -1281,29 +1277,17 @@ uint8_t momentary_state(Event event, uint16_t arg) { // TODO: momentary strobe here? (for light painting) // light up when the button is pressed; go dark otherwise - #if 0 - if ((event ^ B_SYSTEM) & B_PRESS) { + // button is being held + if ((event & (B_CLICK | B_PRESS)) == (B_CLICK | B_PRESS)) { set_level(memorized_level); return MISCHIEF_MANAGED; } - else if (((event ^ B_SYSTEM) & B_PRESS) == 0) { + // button was released + else if ((event & (B_CLICK | B_PRESS)) == (B_CLICK)) { set_level(0); - empty_event_sequence(); //go_to_standby = 1; // sleep while light is off return MISCHIEF_MANAGED; } - #else - if (! (event & B_SYSTEM)) { // is a button-related event - if (event & B_PRESS) { // button is pressed - set_level(memorized_level); - } else { // button was released - set_level(0); - empty_event_sequence(); - //go_to_standby = 1; // sleep while light is off - } - return MISCHIEF_MANAGED; - } - #endif // Sleep, dammit! (but wait a few seconds first) // (because standby mode uses such little power that it can interfere diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index 091d4cf..b36c9f4 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -21,7 +21,7 @@ #define FSM_EVENTS_C void empty_event_sequence() { - current_event = 0; + current_event = EV_none; // when the user completes an input sequence, interrupt any running timers // to cancel any delays currently in progress // This eliminates a whole bunch of extra code: @@ -34,7 +34,7 @@ uint8_t push_event(uint8_t ev_type) { ticks_since_last_event = 0; // something happened // only click events are sent to this function - //current_event |= B_CLICK; + current_event |= B_CLICK; // handle button presses if (ev_type == B_PRESS) { @@ -43,9 +43,9 @@ uint8_t push_event(uint8_t ev_type) { // increase click counter if ((current_event & B_COUNT) < (B_COUNT-1)) { current_event ++; - return 1; // event pushed } - return 0; // maximum number of clicks reached + return 1; // event pushed, even if max clicks already reached + // (will just repeat the max over and over) } // handle button releases else if (ev_type == B_RELEASE) { @@ -194,4 +194,9 @@ void emit(Event event, uint16_t arg) { append_emission(event, arg); } +void emit_current_event(uint16_t arg) { + ticks_since_last_event = arg; + emit(current_event, arg); +} + #endif diff --git a/spaghetti-monster/fsm-events.h b/spaghetti-monster/fsm-events.h index d838800..45c95ee 100644 --- a/spaghetti-monster/fsm-events.h +++ b/spaghetti-monster/fsm-events.h @@ -63,8 +63,8 @@ static volatile uint16_t ticks_since_last_event = 0; */ // event masks / bits -#define B_SYSTEM 0b10000000 -#define B_CLICK 0b00000000 +#define B_SYSTEM 0b00000000 +#define B_CLICK 0b10000000 #define B_TIMEOUT 0b01000000 #define B_HOLD 0b00100000 #define B_PRESS 0b00010000 @@ -219,7 +219,7 @@ void process_emissions(); //#define emit_now emit uint8_t emit_now(Event event, uint16_t arg); void emit(Event event, uint16_t arg); -#define emit_current_event(arg) emit(current_event, arg) +void emit_current_event(uint16_t arg); uint8_t nice_delay_ms(uint16_t ms); //uint8_t nice_delay_4ms(uint8_t ms); diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index cfff1fa..3606c67 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -76,32 +76,38 @@ ISR(WDT_vect) { uint8_t pressed = button_is_pressed(); if (was_pressed != pressed) PCINT_inner(pressed); - //if (ticks_since_last_event < 0xff) ticks_since_last_event ++; + // cache this here to reduce ROM size, because it's volatile + uint16_t ticks_since_last = ticks_since_last_event; + // increment, but loop from max back to half - ticks_since_last_event = (ticks_since_last_event + 1) \ - | (ticks_since_last_event & 0x8000); + //if (ticks_since_last < 0xff) ticks_since_last ++; + ticks_since_last = (ticks_since_last + 1) \ + | (ticks_since_last & 0x8000); + // copy back to the original + ticks_since_last_event = ticks_since_last; // if time since last event exceeds timeout, // append timeout to current event sequence, then // send event to current state callback // callback on each timer tick - if ((current_event & B_FLAGS) == (B_HOLD | B_PRESS)) { + if ((current_event & B_FLAGS) == (B_CLICK | B_HOLD | B_PRESS)) { emit(EV_tick, 0); // override tick counter while holding button } else { - emit(EV_tick, ticks_since_last_event); + emit(EV_tick, ticks_since_last); } // user held button long enough to count as a long click? if (current_event & B_PRESS) { // during a "hold", send a hold event each tick, with a timer if (current_event & B_HOLD) { - emit_current_event(ticks_since_last_event); + emit_current_event(ticks_since_last); } // has button been down long enough to become a "hold"? else { - if (ticks_since_last_event >= HOLD_TIMEOUT) { + if (ticks_since_last >= HOLD_TIMEOUT) { + //ticks_since_last_event = 0; current_event |= B_HOLD; emit_current_event(0); } @@ -118,8 +124,9 @@ ISR(WDT_vect) { empty_event_sequence(); } // end and clear event after release timeout - else if (ticks_since_last_event >= RELEASE_TIMEOUT) { + else if (ticks_since_last >= RELEASE_TIMEOUT) { current_event |= B_TIMEOUT; + //ticks_since_last_event = 0; emit_current_event(0); empty_event_sequence(); } -- cgit v1.2.3