From 35d5a5a245e4fba7bcaa0dd59d6c02c1c321b1fd Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 18 Nov 2019 00:41:11 -0700 Subject: added SOS mode to the BLF LT1 Lantern build, because people wanted it --- spaghetti-monster/anduril/anduril.c | 48 ++++++++++++++++++++++++----- spaghetti-monster/anduril/cfg-blf-lantern.h | 3 ++ 2 files changed, 44 insertions(+), 7 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 48f4ac1..3ab97cb 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -90,6 +90,8 @@ // so don't enable them at the same time as any of the above strobes) //#define USE_POLICE_STROBE_MODE //#define USE_SOS_MODE +//#define USE_SOS_MODE_IN_FF_GROUP // put SOS in the "boring strobes" mode +//#define USE_SOS_MODE_IN_BLINKY_GROUP // put SOS in the blinkies mode group /***** specific settings for known driver types *****/ #include "tk.h" @@ -146,7 +148,7 @@ #define USE_STROBE_STATE #endif -#if defined(USE_POLICE_STROBE_MODE) || defined(USE_SOS_MODE) +#if defined(USE_POLICE_STROBE_MODE) || defined(USE_SOS_MODE_IN_FF_GROUP) #define USE_BORING_STROBE_STATE #endif @@ -282,6 +284,10 @@ uint8_t goodnight_state(Event event, uint16_t arg); uint8_t beacon_state(Event event, uint16_t arg); uint8_t beacon_config_state(Event event, uint16_t arg); #endif +#ifdef USE_SOS_MODE_IN_BLINKY_GROUP +// automatic SOS emergency signal +uint8_t sos_state(Event event, uint16_t arg); +#endif // soft lockout #define MOON_DURING_LOCKOUT_MODE // if enabled, 2nd lockout click goes to the other ramp's floor level @@ -1507,8 +1513,29 @@ inline void police_strobe_iter() { } } #endif +#endif // #ifdef USE_BORING_STROBE_STATE #ifdef USE_SOS_MODE +#ifdef USE_SOS_MODE_IN_BLINKY_GROUP +uint8_t sos_state(Event event, uint16_t arg) { + // 1 click: off + if (event == EV_1click) { + set_state(off_state, 0); + return MISCHIEF_MANAGED; + } + // 2 clicks: next mode + else if (event == EV_2clicks) { + #ifdef USE_THERMAL_REGULATION + set_state(tempcheck_state, 0); + #else + set_state(battcheck_state, 0); + #endif + return MISCHIEF_MANAGED; + } + return EVENT_NOT_HANDLED; +} +#endif + void sos_blink(uint8_t num, uint8_t dah) { #define DIT_LENGTH 200 for (; num > 0; num--) { @@ -1527,14 +1554,13 @@ void sos_blink(uint8_t num, uint8_t dah) { inline void sos_mode_iter() { // one iteration of main loop() - nice_delay_ms(1000); + //nice_delay_ms(1000); sos_blink(3, 0); // S sos_blink(3, 1); // O sos_blink(3, 0); // S - nice_delay_ms(1000); + nice_delay_ms(2000); } #endif // #ifdef USE_SOS_MODE -#endif // #ifdef USE_BORING_STROBE_STATE #ifdef USE_BATTCHECK @@ -1585,9 +1611,11 @@ uint8_t beacon_state(Event event, uint16_t arg) { } // TODO: use sleep ticks to measure time between pulses, // to save power - // 2 clicks: tempcheck mode + // 2 clicks: next mode else if (event == EV_2clicks) { - #ifdef USE_THERMAL_REGULATION + #ifdef USE_SOS_MODE_IN_BLINKY_GROUP + set_state(sos_state, 0); + #elif defined(USE_THERMAL_REGULATION) set_state(tempcheck_state, 0); #else set_state(battcheck_state, 0); @@ -2646,7 +2674,7 @@ void loop() { break; #endif - #ifdef USE_SOS_MODE + #ifdef USE_SOS_MODE_IN_FF_GROUP default: // SOS sos_mode_iter(); break; @@ -2667,6 +2695,12 @@ void loop() { } #endif + #ifdef USE_SOS_MODE_IN_BLINKY_GROUP + else if (state == sos_state) { + sos_mode_iter(); + } + #endif + #ifdef USE_THERMAL_REGULATION // TODO: blink out therm_ceil during thermal_config_state? else if (state == tempcheck_state) { diff --git a/spaghetti-monster/anduril/cfg-blf-lantern.h b/spaghetti-monster/anduril/cfg-blf-lantern.h index bf183eb..bdcd893 100644 --- a/spaghetti-monster/anduril/cfg-blf-lantern.h +++ b/spaghetti-monster/anduril/cfg-blf-lantern.h @@ -54,6 +54,9 @@ #define MUGGLE_FLOOR 15 // about 20 lm #define MUGGLE_CEILING 115 // about 350 lm +#define USE_SOS_MODE +#define USE_SOS_MODE_IN_BLINKY_GROUP + // the sensor (attiny85) is nowhere near the emitters // so thermal regulation can't work #ifdef USE_THERMAL_REGULATION -- cgit v1.2.3 From 36b0f74974140093e1b4b9cd6c358ba89f286f48 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 18 Nov 2019 23:59:49 -0700 Subject: fixed issue where button-press-during-sleep could occasionally cause a reboot (by turning off PCINT when the light is awake) --- spaghetti-monster/fsm-standby.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-standby.c b/spaghetti-monster/fsm-standby.c index 4124d92..e4ef92c 100644 --- a/spaghetti-monster/fsm-standby.c +++ b/spaghetti-monster/fsm-standby.c @@ -43,8 +43,6 @@ void sleep_until_eswitch_pressed() while (button_is_pressed()) {} empty_event_sequence(); // cancel pending input on suspend - PCINT_on(); // wake on e-switch event - #ifdef TICK_DURING_STANDBY // detect which type of event caused a wake-up irq_adc = 0; @@ -54,6 +52,9 @@ void sleep_until_eswitch_pressed() #else go_to_standby = 0; #endif + + PCINT_on(); // wake on e-switch event + // configure sleep mode set_sleep_mode(SLEEP_MODE_PWR_DOWN); @@ -89,7 +90,10 @@ void sleep_until_eswitch_pressed() #endif // go back to normal running mode - //PCINT_on(); // should be on already + // PCINT not needed any more, and can cause problems if on + // (occasional reboots on wakeup-by-button-press) + PCINT_off(); + // restore normal awake-mode interrupts ADC_on(); WDT_on(); } -- cgit v1.2.3 From ed6a02bc0ba93b9ef3139a545225b611fc4c99dc Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 19 Nov 2019 00:06:41 -0700 Subject: cleaned up WDT code a bit, reduced total size, fixed bug where ticks_since_last could have the wrong value sometimes, reduced power use in sleep mode very slightly by skipping button-handling code while asleep --- spaghetti-monster/fsm-pcint.c | 3 +-- spaghetti-monster/fsm-wdt.c | 51 ++++++++++++++++++++----------------------- 2 files changed, 25 insertions(+), 29 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-pcint.c b/spaghetti-monster/fsm-pcint.c index a4a496a..1ba1c15 100644 --- a/spaghetti-monster/fsm-pcint.c +++ b/spaghetti-monster/fsm-pcint.c @@ -97,8 +97,7 @@ void PCINT_inner(uint8_t pressed) { pushed = push_event(B_RELEASE); } - // check if sequence matches any defined sequences - // if so, send event to current state callback + // send event to the current state callback if (pushed) { button_last_state = pressed; emit_current_event(0); diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index beab1a2..0c49a75 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -90,6 +90,14 @@ void WDT_inner() { static uint8_t adc_trigger = 0; + // 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 = (ticks_since_last + 1) \ + | (ticks_since_last & 0x8000); + // copy back to the original + ticks_since_last_event = ticks_since_last; + // detect and emit button change events (even during standby) uint8_t was_pressed = button_last_state; uint8_t pressed = button_is_pressed(); @@ -97,38 +105,29 @@ void WDT_inner() { go_to_standby = 0; PCINT_inner(pressed); } + // cache again, in case the value changed + ticks_since_last = ticks_since_last_event; #ifdef TICK_DURING_STANDBY - static uint16_t sleep_counter = 0; // handle standby mode specially if (go_to_standby) { // emit a halfsleep tick, and process it - emit(EV_sleep_tick, sleep_counter); - // wrap around from 65535 to 32768, not 0 - sleep_counter = (sleep_counter + 1) | (sleep_counter & 0x8000); + emit(EV_sleep_tick, ticks_since_last); process_emissions(); - #if defined(USE_SLEEP_LVP) + #ifndef USE_SLEEP_LVP + return; // no sleep LVP needed if nothing drains power while off + #else // stop here, usually... but proceed often enough for sleep LVP to work - if (0 != (sleep_counter & 0x7f)) return; + if (0 != (ticks_since_last & 0x7f)) return; + adc_trigger = 255; // make sure a measurement will happen - #else - return; // no sleep LVP needed if nothing drains power while off + ADC_on(); // enable ADC voltage measurement functions temporarily #endif } - else { sleep_counter = 0; } + else { // button handling should only happen while awake #endif - // 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 - //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 @@ -148,9 +147,9 @@ void WDT_inner() { emit_current_event(ticks_since_last); } // has button been down long enough to become a "hold"? + // (first frame of a "hold" event) else { if (ticks_since_last >= HOLD_TIMEOUT) { - //ticks_since_last_event = 0; current_event |= B_HOLD; emit_current_event(0); } @@ -163,27 +162,25 @@ void WDT_inner() { // no timeout required when releasing a long-press // TODO? move this logic to PCINT() and simplify things here? if (current_event & B_HOLD) { - //emit_current_event(0); // should have been emitted by PCINT + //emit_current_event(0); // should have been emitted by PCINT_inner() empty_event_sequence(); } // end and clear event after 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(); } } + #ifdef TICK_DURING_STANDBY + } + #endif + #if defined(USE_LVP) || defined(USE_THERMAL_REGULATION) // start a new ADC measurement every 4 ticks adc_trigger ++; if (0 == (adc_trigger & 3)) { - #if defined(TICK_DURING_STANDBY) && defined(USE_SLEEP_LVP) - // we shouldn't be here unless it woke up for a LVP check... - // so enable ADC voltage measurement functions temporarily - if (go_to_standby) ADC_on(); - #endif ADC_start_measurement(); irq_adc_stable = 0; adcint_enable = 1; -- cgit v1.2.3 From 492fdf3281aa7bbcb5aa37b10420766b433e8d34 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 19 Nov 2019 00:21:15 -0700 Subject: fixed ADC cycles running 2X as fast as intended --- spaghetti-monster/fsm-adc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index c859539..ccf1ca2 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -108,12 +108,12 @@ static inline uint8_t calc_voltage_divider(uint16_t value) { } #endif -// Each full cycle runs 7.8X per second with just voltage enabled, -// or 3.9X per second with voltage and temperature. +// Each full cycle runs 15.6X per second with just voltage enabled, +// or 7.8X per second with voltage and temperature. #if defined(USE_LVP) && defined(USE_THERMAL_REGULATION) -#define ADC_CYCLES_PER_SECOND 4 -#else #define ADC_CYCLES_PER_SECOND 8 +#else +#define ADC_CYCLES_PER_SECOND 16 #endif #ifdef USE_THERMAL_REGULATION @@ -322,13 +322,13 @@ static inline void ADC_temperature_handler() { // if it's time to rotate the thermal history, do it history_step ++; #if (THERMAL_UPDATE_SPEED == 4) // new value every 4s - #define THERM_HISTORY_STEP_MAX 15 + #define THERM_HISTORY_STEP_MAX ((2*ADC_CYCLES_PER_SECOND)-1) #elif (THERMAL_UPDATE_SPEED == 2) // new value every 2s - #define THERM_HISTORY_STEP_MAX 7 + #define THERM_HISTORY_STEP_MAX (ADC_CYCLES_PER_SECOND-1) #elif (THERMAL_UPDATE_SPEED == 1) // new value every 1s - #define THERM_HISTORY_STEP_MAX 3 + #define THERM_HISTORY_STEP_MAX ((ADC_CYCLES_PER_SECOND/2)-1) #elif (THERMAL_UPDATE_SPEED == 0) // new value every 0.5s - #define THERM_HISTORY_STEP_MAX 1 + #define THERM_HISTORY_STEP_MAX ((ADC_CYCLES_PER_SECOND/4)-1) #endif if (0 == (history_step & THERM_HISTORY_STEP_MAX)) { // rotate measurements and add a new one -- cgit v1.2.3 From bac2e2572bf2d12aed8f0eecdd2b47bf4c29c001 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 19 Nov 2019 00:25:54 -0700 Subject: enabled prevent_reboot_loop() on all builds, to reduce the impact of any potential crashes (even though I just fixed the only known bug which could trigger an unintentional reboot) --- spaghetti-monster/fsm-main.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index c9ab69b..d352a36 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -79,22 +79,24 @@ inline void hw_setup() { #endif -#ifdef USE_REBOOT -void prevent_reboot_loop() { +//#ifdef USE_REBOOT +static inline void prevent_reboot_loop() { // prevent WDT from rebooting MCU again MCUSR &= ~(1<= 1 DDRB |= (1 << PWM1_PIN); @@ -69,7 +69,7 @@ inline void hw_setup() { PCMSK = (1 << SWITCH_PIN); // pin change interrupt uses this pin } #elif (ATTINY == 1634) -inline void hw_setup() { +static inline void hw_setup() { // this gets tricky with so many pins... // ... so punt it to the hwdef file hwdef_setup(); -- cgit v1.2.3 From 1354b727e203a2c93b12a349b58c04b1cc31228e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 19 Nov 2019 00:37:16 -0700 Subject: Mateminco MF01S can fit muggle mode again, barely --- spaghetti-monster/anduril/cfg-mateminco-mf01s.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h index 2af1305..22b497b 100644 --- a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h @@ -15,9 +15,9 @@ // doesn't quite fit -#ifdef USE_MUGGLE_MODE -#undef USE_MUGGLE_MODE -#endif +//#ifdef USE_MUGGLE_MODE +//#undef USE_MUGGLE_MODE +//#endif // don't blink during ramp, it's irrelevant and annoying on this light -- cgit v1.2.3 From edede40c7ae37c5e13bce7c31d3ffba9e9fefdf8 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 20 Nov 2019 15:29:51 -0700 Subject: fixed unintentional wakeup right after going to sleep (by enabling the PCINT slightly sooner, before setting its "handled" flag) --- spaghetti-monster/fsm-standby.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-standby.c b/spaghetti-monster/fsm-standby.c index e4ef92c..9398f52 100644 --- a/spaghetti-monster/fsm-standby.c +++ b/spaghetti-monster/fsm-standby.c @@ -43,6 +43,8 @@ void sleep_until_eswitch_pressed() while (button_is_pressed()) {} empty_event_sequence(); // cancel pending input on suspend + PCINT_on(); // wake on e-switch event + #ifdef TICK_DURING_STANDBY // detect which type of event caused a wake-up irq_adc = 0; @@ -53,8 +55,6 @@ void sleep_until_eswitch_pressed() go_to_standby = 0; #endif - PCINT_on(); // wake on e-switch event - // configure sleep mode set_sleep_mode(SLEEP_MODE_PWR_DOWN); -- cgit v1.2.3