aboutsummaryrefslogtreecommitdiff
path: root/spaghetti-monster
diff options
context:
space:
mode:
Diffstat (limited to 'spaghetti-monster')
-rw-r--r--spaghetti-monster/anduril/anduril.c48
-rw-r--r--spaghetti-monster/anduril/cfg-blf-lantern.h3
-rw-r--r--spaghetti-monster/anduril/cfg-blf-q8.h6
-rw-r--r--spaghetti-monster/anduril/cfg-mateminco-mf01s.h6
-rw-r--r--spaghetti-monster/fsm-adc.c18
-rw-r--r--spaghetti-monster/fsm-main.c16
-rw-r--r--spaghetti-monster/fsm-pcint.c3
-rw-r--r--spaghetti-monster/fsm-standby.c6
-rw-r--r--spaghetti-monster/fsm-wdt.c51
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;