diff options
| -rw-r--r-- | spaghetti-monster/anduril/anduril.c | 48 | ||||
| -rw-r--r-- | spaghetti-monster/anduril/cfg-blf-lantern.h | 3 | ||||
| -rw-r--r-- | spaghetti-monster/anduril/cfg-blf-q8.h | 6 | ||||
| -rw-r--r-- | spaghetti-monster/anduril/cfg-mateminco-mf01s.h | 6 | ||||
| -rw-r--r-- | spaghetti-monster/fsm-adc.c | 18 | ||||
| -rw-r--r-- | spaghetti-monster/fsm-main.c | 16 | ||||
| -rw-r--r-- | spaghetti-monster/fsm-pcint.c | 3 | ||||
| -rw-r--r-- | spaghetti-monster/fsm-standby.c | 6 | ||||
| -rw-r--r-- | spaghetti-monster/fsm-wdt.c | 51 |
9 files changed, 98 insertions, 59 deletions
diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index e006292..a86af16 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 // cut clock speed at very low modes for better efficiency // (defined here so config files can override it) @@ -149,7 +151,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 @@ -285,6 +287,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 @@ -1527,8 +1533,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--) { @@ -1547,14 +1574,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 @@ -1605,9 +1631,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); @@ -2697,7 +2725,7 @@ void loop() { break; #endif - #ifdef USE_SOS_MODE + #ifdef USE_SOS_MODE_IN_FF_GROUP default: // SOS sos_mode_iter(); break; @@ -2718,6 +2746,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 diff --git a/spaghetti-monster/anduril/cfg-blf-q8.h b/spaghetti-monster/anduril/cfg-blf-q8.h index 166b10e..31c22ff 100644 --- a/spaghetti-monster/anduril/cfg-blf-q8.h +++ b/spaghetti-monster/anduril/cfg-blf-q8.h @@ -14,9 +14,9 @@ #define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 2) // doesn't quite fit -#ifdef USE_MUGGLE_MODE -#undef USE_MUGGLE_MODE -#endif +//#ifdef USE_MUGGLE_MODE +//#undef USE_MUGGLE_MODE +//#endif // copied from Emisar D4 ramp // ../../bin/level_calc.py 1 65 7135 1 0.8 150 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 diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 30f8460..9e52ab6 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -21,7 +21,7 @@ #define FSM_ADC_C -inline void set_admux_therm() { +static inline void set_admux_therm() { #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 1634) ADMUX = ADMUX_THERM; #elif (ATTINY == 841) @@ -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 diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index c9ab69b..4ad1e16 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -37,7 +37,7 @@ ISR(TIMER1_COMPA_vect) { #endif #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) -inline void hw_setup() { +static inline void hw_setup() { // configure PWM channels #if PWM_CHANNELS >= 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(); @@ -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<<WDRF); // reset status flag wdt_disable(); } -#endif +//#endif int main() { // Don't allow interrupts while booting cli(); - #ifdef USE_REBOOT + //#ifdef USE_REBOOT + // prevents cycling after a crash, + // whether intentional (like factory reset) or not (bugs) prevent_reboot_loop(); - #endif + //#endif hw_setup(); 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-standby.c b/spaghetti-monster/fsm-standby.c index 4124d92..9398f52 100644 --- a/spaghetti-monster/fsm-standby.c +++ b/spaghetti-monster/fsm-standby.c @@ -54,6 +54,7 @@ void sleep_until_eswitch_pressed() #else go_to_standby = 0; #endif + // 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(); } 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; |
