From 3fbd6973fcaa805e4ac1cae4d56a8c84985caf89 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 13 Nov 2019 18:33:23 -0700 Subject: fixed some compile issues related to delay_4ms() --- spaghetti-monster/darkhorse/darkhorse.c | 1 - spaghetti-monster/fsm-events.c | 2 ++ spaghetti-monster/meteor/meteor.c | 1 - tk-delay.h | 2 ++ 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/spaghetti-monster/darkhorse/darkhorse.c b/spaghetti-monster/darkhorse/darkhorse.c index e613f55..4058c2f 100644 --- a/spaghetti-monster/darkhorse/darkhorse.c +++ b/spaghetti-monster/darkhorse/darkhorse.c @@ -21,7 +21,6 @@ #define USE_LVP #define USE_THERMAL_REGULATION #define DEFAULT_THERM_CEIL 45 -#define USE_DELAY_4MS #define USE_RAMPING #define RAMP_LENGTH 150 #define USE_BATTCHECK diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index f35607d..3e9a12d 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -20,6 +20,8 @@ #ifndef FSM_EVENTS_C #define FSM_EVENTS_C +#include + void empty_event_sequence() { current_event = EV_none; diff --git a/spaghetti-monster/meteor/meteor.c b/spaghetti-monster/meteor/meteor.c index 5e925e2..7d854a1 100644 --- a/spaghetti-monster/meteor/meteor.c +++ b/spaghetti-monster/meteor/meteor.c @@ -22,7 +22,6 @@ #define USE_LVP #define USE_THERMAL_REGULATION #define DEFAULT_THERM_CEIL 45 -#define USE_DELAY_4MS #define USE_RAMPING #define RAMP_LENGTH 150 #define USE_BATTCHECK diff --git a/tk-delay.h b/tk-delay.h index 7b00ac0..29cf463 100644 --- a/tk-delay.h +++ b/tk-delay.h @@ -48,12 +48,14 @@ void _delay_zero() { } #endif #ifdef USE_DELAY_4MS +#ifndef delay_4ms #define delay_4ms _delay_4ms void _delay_4ms(uint8_t n) // because it saves a bit of ROM space to do it this way { while(n-- > 0) _delay_loop_2(BOGOMIPS*4); } #endif +#endif #ifdef USE_DELAY_S #define delay_s _delay_s void _delay_s() // because it saves a bit of ROM space to do it this way -- cgit v1.2.3 From 8b59e880614455bd7bc7d8595de847dd6fe9b5b2 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 14 Nov 2019 01:52:50 -0700 Subject: refactored how interrupts work... set a flag and return immediately, then handle the actual logic later during a less-critical code path Enables smarter responses to standby wakeups. Seems to fix missed button presses during standby, and most of the too-fast sleep ticks. Also eliminated waits from button state measurement, so it can happen easier during standby. (also eliminates the chance of an infinite loop on extra-noisy hardware) Also might improve timing-sensitive interrupts like attiny85 PWM channel 4, or a PWM-DSM hybrid technique I'd like to try. BUT this change also appears to break the thermal sensor, so that needs to be fixed. --- spaghetti-monster/fsm-adc.c | 45 ++++++++++++++++++++++++++++++++--------- spaghetti-monster/fsm-adc.h | 8 +++++++- spaghetti-monster/fsm-events.c | 3 +++ spaghetti-monster/fsm-main.c | 21 +++++++++++++++++++ spaghetti-monster/fsm-main.h | 2 ++ spaghetti-monster/fsm-pcint.c | 21 +++++++------------ spaghetti-monster/fsm-pcint.h | 1 + spaghetti-monster/fsm-standby.c | 19 +++++++++++++---- spaghetti-monster/fsm-wdt.c | 22 +++++++++++++------- spaghetti-monster/fsm-wdt.h | 4 ++-- 10 files changed, 108 insertions(+), 38 deletions(-) diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 6832e32..1fc5472 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -113,15 +113,44 @@ static inline uint8_t calc_voltage_divider(uint16_t value) { #else #define ADC_CYCLES_PER_SECOND 8 #endif -// TODO: is this better done in main() or WDT()? + +// save the measurement result, set a flag to show something happened, +// and count how many times we've triggered since last counter reset ISR(ADC_vect) { - // For some reason, the ADC interrupt is getting called a *lot* - // more often than it should be, like it's auto-triggering after each - // measurement, but I don't know why, or how to turn that off... - // So, skip every call except when explicitly requested. + #if 0 // the fancy method is probably not even needed + // count up but wrap around from 255 to 128; not 255 to 0 + // TODO: find a way to do this faster if possible + uint8_t val = irq_adc; // cache volatile value + irq_adc = (val + 1) | (val & 0b10000000); + #else + irq_adc ++; + #endif + adc_value = ADC; // save this for later use +} + +void ADC_inner() { + // ignore the first measurement; the docs say it's junk + if (irq_adc < 2) { + ADC_start_measurement(); // start a second measurement + return; + } + + // the ADC triggers repeatedly when it's on, but we only want one value + // (so ignore everything after the first value, until it's manually reset) if (! adcint_enable) return; + + // if we're actually runnning, reset the status flags / counters + irq_adc = 0; adcint_enable = 0; + #ifdef TICK_DURING_STANDBY + // in sleep mode, turn off after just one measurement + // (having the ADC on raises standby power by about 250 uA) + // (and the usual standby level is only ~20 uA) + if (go_to_standby) ADC_off(); + #endif + + // what is being measured? 0/1 = battery voltage, 2/3 = temperature static uint8_t adc_step = 0; // LVP declarations @@ -155,7 +184,7 @@ ISR(ADC_vect) { #define ADC_STEPS 2 #endif - uint16_t measurement = ADC; // latest 10-bit ADC reading + uint16_t measurement = adc_value; // latest 10-bit ADC reading #ifdef USE_PSEUDO_RAND // real-world entropy makes this a true random, not pseudo @@ -376,10 +405,6 @@ ISR(ADC_vect) { #endif #endif - #ifdef TICK_DURING_STANDBY - // if we were asleep, go back to sleep - if (go_to_standby) ADC_off(); - #endif } #ifdef USE_BATTCHECK diff --git a/spaghetti-monster/fsm-adc.h b/spaghetti-monster/fsm-adc.h index 274fb4d..acb3da6 100644 --- a/spaghetti-monster/fsm-adc.h +++ b/spaghetti-monster/fsm-adc.h @@ -38,9 +38,15 @@ #define VOLTAGE_FUDGE_FACTOR 5 #endif #endif + +volatile uint8_t irq_adc = 0; // ADC interrupt happened? +uint16_t adc_value; // last ADC measurement +uint8_t adcint_enable = 0; // is the current ADC result needed? +void ADC_inner(); // do the actual ADC-related calculations + volatile uint8_t voltage = 0; -volatile uint8_t adcint_enable; // kludge, because adc auto-retrigger won't turn off void low_voltage(); + #ifdef USE_BATTCHECK void battcheck(); #ifdef BATTCHECK_VpT diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index 3e9a12d..e125e84 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -145,6 +145,9 @@ uint8_t nice_delay_ms(uint16_t ms) { _delay_loop_2(BOGOMIPS*98/100); #endif // ifdef USE_DYNAMIC_UNDERCLOCKING + // run pending system processes while we wait + handle_deferred_interrupts(); + if ((nice_delay_interrupt) || (old_state != current_state)) { return 0; // state changed; abort } diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index e537a9e..a898f41 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -160,6 +160,9 @@ int main() { standby_mode(); } + // catch up on interrupts + handle_deferred_interrupts(); + // give the recipe some time slices loop(); @@ -168,4 +171,22 @@ int main() { } } + +void handle_deferred_interrupts() { + /* + if (irq_pcint) { // button pressed or released + // nothing to do here + // (PCINT only matters during standby) + } + */ + if (irq_adc) { // ADC done measuring + ADC_inner(); + // irq_adc = 0; // takes care of itself + } + if (irq_wdt) { // the clock ticked + WDT_inner(); + // irq_wdt = 0; // takes care of itself + } +} + #endif diff --git a/spaghetti-monster/fsm-main.h b/spaghetti-monster/fsm-main.h index cc469d7..55ae2ff 100644 --- a/spaghetti-monster/fsm-main.h +++ b/spaghetti-monster/fsm-main.h @@ -21,5 +21,7 @@ #define FSM_MAIN_H int main(); +// needs to run frequently to execute the logic for WDT and ADC and stuff +void handle_deferred_interrupts(); #endif diff --git a/spaghetti-monster/fsm-pcint.c b/spaghetti-monster/fsm-pcint.c index 4928980..a4a496a 100644 --- a/spaghetti-monster/fsm-pcint.c +++ b/spaghetti-monster/fsm-pcint.c @@ -24,19 +24,9 @@ #include uint8_t button_is_pressed() { - // remember the past 32 measurements - static uint32_t readings = 0; - // take at least one new measurement, - // and wait for measurements to settle to all zeroes or all ones - do { - // shift past readings and add current value - readings = (readings << 1) | ((SWITCH_PORT & (1<> 2; + + #ifdef USE_VOLTAGE_DIVIDER + voltage = calc_voltage_divider(total); + #else + voltage = (uint16_t)(1.1*1024*10)/total + VOLTAGE_FUDGE_FACTOR; + #endif + } + #else // no USE_LVP_AVG + #ifdef USE_VOLTAGE_DIVIDER + voltage = calc_voltage_divider(measurement); + #else + // calculate actual voltage: volts * 10 + // ADC = 1.1 * 1024 / volts + // volts = 1.1 * 1024 / ADC + //voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; + voltage = ((uint16_t)(2*1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR) >> 1; + #endif #endif + // if low, callback EV_voltage_low / EV_voltage_critical + // (but only if it has been more than N ticks since last call) + if (lvp_timer) { + lvp_timer --; + } else { // it has been long enough since the last warning + if (voltage < VOLTAGE_LOW) { + if (lvp_lowpass < LVP_LOWPASS_STRENGTH) { + lvp_lowpass ++; + } else { + // try to send out a warning + //uint8_t err = emit(EV_voltage_low, 0); + //uint8_t err = emit_now(EV_voltage_low, 0); + emit(EV_voltage_low, 0); + //if (!err) { + // on successful warning, reset counters + lvp_timer = LVP_TIMER_START; + lvp_lowpass = 0; + //} + } + } else { + // voltage not low? reset count + lvp_lowpass = 0; + } + } +} +#endif + +#ifdef USE_THERMAL_REGULATION +static inline void ADC_temperature_handler() { // thermal declarations - #ifdef USE_THERMAL_REGULATION #ifndef THERMAL_UPDATE_SPEED #define THERMAL_UPDATE_SPEED 2 #endif #define NUM_THERMAL_VALUES_HISTORY 8 - #define ADC_STEPS 4 static uint8_t history_step = 0; // don't update history as often static int16_t temperature_history[NUM_THERMAL_VALUES_HISTORY]; static uint8_t temperature_timer = 0; @@ -180,232 +292,132 @@ void ADC_inner() { #define TEMPERATURE_TIMER_START ((THERMAL_WARNING_SECONDS-2)*ADC_CYCLES_PER_SECOND) // N seconds between thermal regulation events #define OVERHEAT_LOWPASS_STRENGTH (ADC_CYCLES_PER_SECOND*2) // lowpass for 2 seconds #define UNDERHEAT_LOWPASS_STRENGTH (ADC_CYCLES_PER_SECOND*2) // lowpass for 2 seconds - #else - #define ADC_STEPS 2 - #endif uint16_t measurement = adc_value; // latest 10-bit ADC reading - #ifdef USE_PSEUDO_RAND - // real-world entropy makes this a true random, not pseudo - pseudo_rand_seed += measurement; - #endif - - #if defined(TICK_DURING_STANDBY) && defined(USE_SLEEP_LVP) - // only measure battery voltage while asleep - if (go_to_standby) adc_step = 1; - else - #endif - - adc_step = (adc_step + 1) & (ADC_STEPS-1); - - #ifdef USE_LVP - // voltage - if (adc_step == 1) { - #ifdef USE_LVP_AVG - // prime on first execution - if (voltage == 0) { - for(uint8_t i=0; i> 2; - - #ifdef USE_VOLTAGE_DIVIDER - voltage = calc_voltage_divider(total); - #else - voltage = (uint16_t)(1.1*1024*10)/total + VOLTAGE_FUDGE_FACTOR; - #endif - } - #else // no USE_LVP_AVG - #ifdef USE_VOLTAGE_DIVIDER - voltage = calc_voltage_divider(measurement); - #else - // calculate actual voltage: volts * 10 - // ADC = 1.1 * 1024 / volts - // volts = 1.1 * 1024 / ADC - //voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; - voltage = ((uint16_t)(2*1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR) >> 1; - #endif - #endif - // if low, callback EV_voltage_low / EV_voltage_critical - // (but only if it has been more than N ticks since last call) - if (lvp_timer) { - lvp_timer --; - } else { // it has been long enough since the last warning - if (voltage < VOLTAGE_LOW) { - if (lvp_lowpass < LVP_LOWPASS_STRENGTH) { - lvp_lowpass ++; - } else { - // try to send out a warning - //uint8_t err = emit(EV_voltage_low, 0); - //uint8_t err = emit_now(EV_voltage_low, 0); - emit(EV_voltage_low, 0); - //if (!err) { - // on successful warning, reset counters - lvp_timer = LVP_TIMER_START; - lvp_lowpass = 0; - //} - } - } else { - // voltage not low? reset count - lvp_lowpass = 0; - } + // Convert ADC units to Celsius (ish) + int16_t temp = measurement - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; + + // prime on first execution + if (reset_thermal_history) { + reset_thermal_history = 0; + temperature = temp; + for(uint8_t i=0; i temperature) { + temperature ++; + } else if (temp < temperature) { + temperature --; } } - #endif // ifdef USE_LVP + // guess what the temperature will be in a few seconds + int16_t pt; + { + int16_t diff; + int16_t t = temperature; - #ifdef USE_THERMAL_REGULATION - // temperature - else if (adc_step == 3) { - // Convert ADC units to Celsius (ish) - int16_t temp = measurement - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; - - // prime on first execution - if (reset_thermal_history) { - reset_thermal_history = 0; - temperature = temp; - for(uint8_t i=0; i temperature) { - temperature ++; - } else if (temp < temperature) { - temperature --; + // algorithm tweaking; not really intended to be modified + // how far ahead should we predict? + #ifndef THERM_PREDICTION_STRENGTH + #define THERM_PREDICTION_STRENGTH 4 + #endif + // how proportional should the adjustments be? (not used yet) + #ifndef THERM_RESPONSE_MAGNITUDE + #define THERM_RESPONSE_MAGNITUDE 128 + #endif + // acceptable temperature window size in C + #define THERM_WINDOW_SIZE 5 + // highest temperature allowed + #define THERM_CEIL ((int16_t)therm_ceil) + // bottom of target temperature window + #define THERM_FLOOR (THERM_CEIL - THERM_WINDOW_SIZE) + + // 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 + #elif (THERMAL_UPDATE_SPEED == 2) // new value every 2s + #define THERM_HISTORY_STEP_MAX 7 + #elif (THERMAL_UPDATE_SPEED == 1) // new value every 1s + #define THERM_HISTORY_STEP_MAX 3 + #elif (THERMAL_UPDATE_SPEED == 0) // new value every 0.5s + #define THERM_HISTORY_STEP_MAX 1 + #endif + if (0 == (history_step & THERM_HISTORY_STEP_MAX)) { + // rotate measurements and add a new one + for (uint8_t i=0; i 0) diff --; - } - // projected_temperature = current temp extended forward by amplified rate of change - //projected_temperature = temperature_history[NUM_THERMAL_VALUES_HISTORY-1] + (diff< 0) diff --; } + // projected_temperature = current temp extended forward by amplified rate of change + //projected_temperature = temperature_history[NUM_THERMAL_VALUES_HISTORY-1] + (diff< THERM_FLOOR) { - underheat_lowpass = 0; // we're probably not too cold - } - if (pt < THERM_CEIL) { - overheat_lowpass = 0; // we're probably not too hot - } + // cancel counters if appropriate + if (pt > THERM_FLOOR) { + underheat_lowpass = 0; // we're probably not too cold + } + if (pt < THERM_CEIL) { + overheat_lowpass = 0; // we're probably not too hot + } - if (temperature_timer) { - temperature_timer --; - } else { // it has been long enough since the last warning - - // Too hot? - if (pt > THERM_CEIL) { - if (overheat_lowpass < OVERHEAT_LOWPASS_STRENGTH) { - overheat_lowpass ++; - } else { - // reset counters - overheat_lowpass = 0; - temperature_timer = TEMPERATURE_TIMER_START; - // how far above the ceiling? - //int16_t howmuch = (pt - THERM_CEIL) * THERM_RESPONSE_MAGNITUDE / 128; - int16_t howmuch = pt - THERM_CEIL; - // try to send out a warning - emit(EV_temperature_high, howmuch); - } + if (temperature_timer) { + temperature_timer --; + } else { // it has been long enough since the last warning + + // Too hot? + if (pt > THERM_CEIL) { + if (overheat_lowpass < OVERHEAT_LOWPASS_STRENGTH) { + overheat_lowpass ++; + } else { + // reset counters + overheat_lowpass = 0; + temperature_timer = TEMPERATURE_TIMER_START; + // how far above the ceiling? + //int16_t howmuch = (pt - THERM_CEIL) * THERM_RESPONSE_MAGNITUDE / 128; + int16_t howmuch = pt - THERM_CEIL; + // try to send out a warning + emit(EV_temperature_high, howmuch); } + } - // Too cold? - else if (pt < THERM_FLOOR) { - if (underheat_lowpass < UNDERHEAT_LOWPASS_STRENGTH) { - underheat_lowpass ++; - } else { - // reset counters - underheat_lowpass = 0; - temperature_timer = TEMPERATURE_TIMER_START; - // how far below the floor? - //int16_t howmuch = (THERM_FLOOR - pt) * THERM_RESPONSE_MAGNITUDE / 128; - int16_t howmuch = THERM_FLOOR - pt; - // try to send out a warning (unless voltage is low) - // (LVP and underheat warnings fight each other) - if (voltage > VOLTAGE_LOW) - emit(EV_temperature_low, howmuch); - } + // Too cold? + else if (pt < THERM_FLOOR) { + if (underheat_lowpass < UNDERHEAT_LOWPASS_STRENGTH) { + underheat_lowpass ++; + } else { + // reset counters + underheat_lowpass = 0; + temperature_timer = TEMPERATURE_TIMER_START; + // how far below the floor? + //int16_t howmuch = (THERM_FLOOR - pt) * THERM_RESPONSE_MAGNITUDE / 128; + int16_t howmuch = THERM_FLOOR - pt; + // try to send out a warning (unless voltage is low) + // (LVP and underheat warnings fight each other) + if (voltage > VOLTAGE_LOW) + emit(EV_temperature_low, howmuch); } } } - #endif // ifdef USE_THERMAL_REGULATION - - - // set the correct type of measurement for next time - #ifdef USE_THERMAL_REGULATION - #ifdef USE_LVP - if (adc_step < 2) set_admux_voltage(); - else set_admux_therm(); - #else - set_admux_therm(); - #endif - #else - #ifdef USE_LVP - set_admux_voltage(); - #endif - #endif - } +#endif + #ifdef USE_BATTCHECK #ifdef BATTCHECK_4bars diff --git a/spaghetti-monster/fsm-adc.h b/spaghetti-monster/fsm-adc.h index acb3da6..5f4d0c8 100644 --- a/spaghetti-monster/fsm-adc.h +++ b/spaghetti-monster/fsm-adc.h @@ -44,6 +44,7 @@ uint16_t adc_value; // last ADC measurement uint8_t adcint_enable = 0; // is the current ADC result needed? void ADC_inner(); // do the actual ADC-related calculations +static inline void ADC_voltage_handler(); volatile uint8_t voltage = 0; void low_voltage(); @@ -56,7 +57,7 @@ void battcheck(); #define USE_BLINK_DIGIT #endif #endif -#endif +#endif // ifdef USE_LVP #ifdef USE_THERMAL_REGULATION @@ -85,7 +86,8 @@ int8_t therm_cal_offset = 0; //void low_temperature(); //void high_temperature(); volatile uint8_t reset_thermal_history = 1; -#endif +static inline void ADC_temperature_handler(); +#endif // ifdef USE_THERMAL_REGULATION inline void ADC_on(); -- cgit v1.2.3 From ae082e6331d75c2cbe339290fbce4e79c2aa2ede Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 14 Nov 2019 18:00:54 -0700 Subject: fixed ADC code; measures and behaves correctly now, and is easier to read... ... but factory reset's auto-calibrate still doesn't get the right values for some reason (manual calibration works, but not auto) --- spaghetti-monster/fsm-adc.c | 76 ++++++++++++++++++++++----------------------- spaghetti-monster/fsm-adc.h | 4 ++- spaghetti-monster/fsm-wdt.c | 2 +- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index ddf4c65..d447189 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -30,6 +30,7 @@ inline void set_admux_therm() { #else #error Unrecognized MCU type #endif + adc_channel = 1; } inline void set_admux_voltage() { @@ -52,6 +53,7 @@ inline void set_admux_voltage() { #else #error Unrecognized MCU type #endif + adc_channel = 0; } inline void ADC_start_measurement() { @@ -115,38 +117,37 @@ static inline uint8_t calc_voltage_divider(uint16_t value) { #endif #ifdef USE_THERMAL_REGULATION -#define ADC_STEPS 4 -#else #define ADC_STEPS 2 +#else +#define ADC_STEPS 1 #endif -// save the measurement result, set a flag to show something happened, -// and count how many times we've triggered since last counter reset +// happens every time the ADC sampler finishes a measurement ISR(ADC_vect) { - #if 0 // the fancy method is probably not even needed - // count up but wrap around from 255 to 128; not 255 to 0 - // TODO: find a way to do this faster if possible - uint8_t val = irq_adc; // cache volatile value - irq_adc = (val + 1) | (val & 0b10000000); - #else - irq_adc ++; + #ifdef USE_PSEUDO_RAND + // real-world entropy makes this a true random, not pseudo + pseudo_rand_seed += ADCL; #endif - adc_value = ADC; // save this for later use + + if (irq_adc_stable) { // skip first result; it's junk + adc_values[adc_channel] = ADC; // save this for later use + irq_adc = 1; // a value was saved, so trigger deferred logic + } + irq_adc_stable = 1; + + // start another measurement + // (is explicit because it otherwise doesn't seem to happen during standby mode) + ADC_start_measurement(); } void ADC_inner() { - // ignore the first measurement; the docs say it's junk - if (irq_adc < 2) { - ADC_start_measurement(); // start a second measurement - return; - } + irq_adc = 0; // event handled // the ADC triggers repeatedly when it's on, but we only want one value // (so ignore everything after the first value, until it's manually reset) if (! adcint_enable) return; - // if we're actually runnning, reset the status flags / counters - irq_adc = 0; + // disable after one iteration adcint_enable = 0; #ifdef TICK_DURING_STANDBY @@ -156,41 +157,37 @@ void ADC_inner() { if (go_to_standby) ADC_off(); #endif - // what is being measured? 0/1 = battery voltage, 2/3 = temperature + // what is being measured? 0 = battery voltage, 1 = temperature static uint8_t adc_step = 0; - #ifdef USE_PSEUDO_RAND - // real-world entropy makes this a true random, not pseudo - pseudo_rand_seed += adc_value; - #endif - - #if defined(TICK_DURING_STANDBY) && defined(USE_SLEEP_LVP) - // only measure battery voltage while asleep - if (go_to_standby) adc_step = 1; - else - #endif - - adc_step = (adc_step + 1) & (ADC_STEPS-1); - #ifdef USE_LVP - if (adc_step == 1) { // voltage + if (0 == adc_step) { // voltage ADC_voltage_handler(); } #endif #ifdef USE_THERMAL_REGULATION - else if (adc_step == 3) { // temperature + else if (1 == adc_step) { // temperature ADC_temperature_handler(); } #endif + #if defined(TICK_DURING_STANDBY) && defined(USE_SLEEP_LVP) + // only measure battery voltage while asleep + if (go_to_standby) adc_step = 0; + else + #endif + + adc_step = (adc_step + 1) & (ADC_STEPS-1); + // set the correct type of measurement for next time #ifdef USE_THERMAL_REGULATION #ifdef USE_LVP - if (adc_step < 2) set_admux_voltage(); + if (0 == adc_step) set_admux_voltage(); else set_admux_therm(); #else - set_admux_therm(); + //set_admux_therm(); + #error "USE_THERMAL_REGULATION set without USE_LVP" #endif #else #ifdef USE_LVP @@ -198,6 +195,7 @@ void ADC_inner() { #endif #endif + irq_adc_stable = 0; // first result is unstable } @@ -213,7 +211,7 @@ static inline void ADC_voltage_handler() { #define LVP_TIMER_START (VOLTAGE_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) // N seconds between LVP warnings #define LVP_LOWPASS_STRENGTH ADC_CYCLES_PER_SECOND // lowpass for one second - uint16_t measurement = adc_value; // latest 10-bit ADC reading + uint16_t measurement = adc_values[0]; // latest 10-bit ADC reading #ifdef USE_LVP_AVG // prime on first execution @@ -293,7 +291,7 @@ static inline void ADC_temperature_handler() { #define OVERHEAT_LOWPASS_STRENGTH (ADC_CYCLES_PER_SECOND*2) // lowpass for 2 seconds #define UNDERHEAT_LOWPASS_STRENGTH (ADC_CYCLES_PER_SECOND*2) // lowpass for 2 seconds - uint16_t measurement = adc_value; // latest 10-bit ADC reading + uint16_t measurement = adc_values[1]; // latest 10-bit ADC reading // Convert ADC units to Celsius (ish) int16_t temp = measurement - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; diff --git a/spaghetti-monster/fsm-adc.h b/spaghetti-monster/fsm-adc.h index 5f4d0c8..6e39750 100644 --- a/spaghetti-monster/fsm-adc.h +++ b/spaghetti-monster/fsm-adc.h @@ -40,7 +40,9 @@ #endif volatile uint8_t irq_adc = 0; // ADC interrupt happened? -uint16_t adc_value; // last ADC measurement +volatile uint8_t irq_adc_stable = 0; // have we passed the 1st junk value yet? +uint8_t adc_channel = 0; // 0=voltage, 1=temperature +uint16_t adc_values[2]; // last ADC measurements (0=voltage, 1=temperature) uint8_t adcint_enable = 0; // is the current ADC result needed? void ADC_inner(); // do the actual ADC-related calculations diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index 3cb7d86..beab1a2 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -185,7 +185,7 @@ void WDT_inner() { if (go_to_standby) ADC_on(); #endif ADC_start_measurement(); - irq_adc = 0; + irq_adc_stable = 0; adcint_enable = 1; } #endif -- cgit v1.2.3 From 81ed77d88c999f9c2368718047d0969fef44e534 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 14 Nov 2019 18:28:52 -0700 Subject: fixed factory reset (wasn't running interrupt logic since it's deferred now) (also fixed issue where nice_delay_ms() was aborted during setup()) (and adjusted the timing to make factory reset similar to the speed it was before this change) --- spaghetti-monster/anduril/anduril.c | 10 +++++----- spaghetti-monster/fsm-events.c | 12 ++++++------ spaghetti-monster/fsm-main.c | 1 - 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 48f4ac1..19d61b7 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -2356,7 +2356,7 @@ void rgb_led_update(uint8_t mode, uint8_t arg) { void factory_reset() { // display a warning for a few seconds before doing the actual reset, // so the user has time to abort if they want - #define SPLODEY_TIME 3000 + #define SPLODEY_TIME 2500 #define SPLODEY_STEPS 64 #define SPLODEY_TIME_PER_STEP (SPLODEY_TIME/SPLODEY_STEPS) uint8_t bright; @@ -2364,9 +2364,9 @@ void factory_reset() { // wind up to an explosion for (bright=0; bright>1); - delay_4ms(SPLODEY_TIME_PER_STEP/2/4); + nice_delay_ms(SPLODEY_TIME_PER_STEP/2); if (! button_is_pressed()) { reset = 0; break; @@ -2387,14 +2387,14 @@ void factory_reset() { bright = MAX_LEVEL; for (; bright > 0; bright--) { set_level(bright); - delay_4ms(SPLODEY_TIME_PER_STEP/6/4); + nice_delay_ms(SPLODEY_TIME_PER_STEP/8); } } // explosion cancelled, fade away else { for (; bright > 0; bright--) { set_level(bright); - delay_4ms(SPLODEY_TIME_PER_STEP/3/4); + nice_delay_ms(SPLODEY_TIME_PER_STEP/3); } } } diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index e125e84..a1b013a 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -110,7 +110,7 @@ uint8_t nice_delay_ms(uint16_t ms) { /* // delay_zero() implementation if (ms == 0) { CLKPR = 1<> 2; + #ifdef USE_VOLTAGE_LOWPASS + static uint16_t prev_measurement = 0; - #ifdef USE_VOLTAGE_DIVIDER - voltage = calc_voltage_divider(total); - #else - voltage = (uint16_t)(1.1*1024*10)/total + VOLTAGE_FUDGE_FACTOR; - #endif - } - #else // no USE_LVP_AVG - #ifdef USE_VOLTAGE_DIVIDER - voltage = calc_voltage_divider(measurement); - #else - // calculate actual voltage: volts * 10 - // ADC = 1.1 * 1024 / volts - // volts = 1.1 * 1024 / ADC - //voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; - voltage = ((uint16_t)(2*1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR) >> 1; - #endif + // prime on first execution, or while asleep + if (go_to_standby || (! prev_measurement)) prev_measurement = measurement; + + // only allow raw value to go up or down by 1 per iteration + if (measurement > prev_measurement) measurement = prev_measurement + 1; + else if (measurement < prev_measurement) measurement = prev_measurement - 1; + + // remember for later + prev_measurement = measurement; + #endif // no USE_VOLTAGE_LOWPASS + + #ifdef USE_VOLTAGE_DIVIDER + voltage = calc_voltage_divider(measurement); + #else + // calculate actual voltage: volts * 10 + // ADC = 1.1 * 1024 / volts + // volts = 1.1 * 1024 / ADC + //voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; + voltage = ((uint16_t)(2*1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR) >> 1; #endif + // if low, callback EV_voltage_low / EV_voltage_critical // (but only if it has been more than N ticks since last call) if (lvp_timer) { -- cgit v1.2.3 From 69788279c4bac4508d363634e680abf999e6d631 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 14 Nov 2019 19:28:32 -0700 Subject: oops, put voltage lowpass on the wrong D4S --- spaghetti-monster/anduril/cfg-emisar-d4s.h | 3 --- spaghetti-monster/anduril/cfg-emisar-d4sv2.h | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/spaghetti-monster/anduril/cfg-emisar-d4s.h b/spaghetti-monster/anduril/cfg-emisar-d4s.h index a9ac5f0..6fe95a6 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4s.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4s.h @@ -47,6 +47,3 @@ #define THERMAL_UPDATE_SPEED 2 #define THERM_PREDICTION_STRENGTH 4 -// attiny1634 has enough space to smooth out voltage readings -#define USE_VOLTAGE_LOWPASS - diff --git a/spaghetti-monster/anduril/cfg-emisar-d4sv2.h b/spaghetti-monster/anduril/cfg-emisar-d4sv2.h index acc9101..c47e774 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4sv2.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4sv2.h @@ -61,3 +61,7 @@ // seems relevant on attiny1634 #define THERM_CAL_OFFSET 5 + +// attiny1634 has enough space to smooth out voltage readings +#define USE_VOLTAGE_LOWPASS + -- cgit v1.2.3 From c8a74e625ea00efc3fd9923e9204e3f32eda4091 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 14 Nov 2019 19:35:33 -0700 Subject: turned off muggle mode on Q8 and MF01S, to make builds small enough again --- spaghetti-monster/anduril/cfg-blf-q8.h | 5 +++++ spaghetti-monster/anduril/cfg-mateminco-mf01s.h | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/spaghetti-monster/anduril/cfg-blf-q8.h b/spaghetti-monster/anduril/cfg-blf-q8.h index 970fedb..166b10e 100644 --- a/spaghetti-monster/anduril/cfg-blf-q8.h +++ b/spaghetti-monster/anduril/cfg-blf-q8.h @@ -13,6 +13,11 @@ // lockout: blinking (3) #define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 2) +// doesn't quite fit +#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 // ... mixed with this: diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h index 0585b38..2af1305 100644 --- a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h @@ -14,6 +14,12 @@ #define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 1) +// doesn't quite fit +#ifdef USE_MUGGLE_MODE +#undef USE_MUGGLE_MODE +#endif + + // don't blink during ramp, it's irrelevant and annoying on this light #define BLINK_AT_RAMP_CEILING #undef BLINK_AT_RAMP_MIDDLE -- cgit v1.2.3 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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(-) 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 From 481ba09b19630d2742fdc34a81484524838439f3 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 22 Nov 2019 15:55:51 -0700 Subject: added -fwhole-program gcc flag, suggested by Agro. Signficantly reduces ROM size! :) --- bin/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/build.sh b/bin/build.sh index fbb24ea..3992c38 100755 --- a/bin/build.sh +++ b/bin/build.sh @@ -14,7 +14,7 @@ export PROGRAM=$1 ; shift export MCU=attiny$ATTINY export CC=avr-gcc export OBJCOPY=avr-objcopy -export CFLAGS="-Wall -g -Os -mmcu=$MCU -c -std=gnu99 -fgnu89-inline -DATTINY=$ATTINY -I.. -I../.. -I../../.. -fshort-enums" +export CFLAGS="-Wall -g -Os -mmcu=$MCU -c -std=gnu99 -fgnu89-inline -fwhole-program -DATTINY=$ATTINY -I.. -I../.. -I../../.. -fshort-enums" export OFLAGS="-Wall -g -Os -mmcu=$MCU" export LDFLAGS="-fgnu89-inline" export OBJCOPYFLAGS='--set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0 --no-change-warnings -O ihex' -- cgit v1.2.3