From b85a22301e05f7580a834146b0016dea5f46d55d Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 15 Sep 2020 02:57:59 -0600 Subject: added hybrid memory option (a.k.a. manual memory timer) Hybrid memory is a combination of automatic and manual, depending on how long the light was off. If it was a short time, automatic mem is used. For a longer time, it resets to the manual memory level. Also tweaked some of the larger build targets again to make sure they fit in ROM. --- spaghetti-monster/anduril/anduril.c | 6 ++++ spaghetti-monster/anduril/cfg-ff-rot66.h | 3 ++ spaghetti-monster/anduril/cfg-ff-rot66g2.h | 1 + .../anduril/cfg-mateminco-mf01-mini.h | 1 + spaghetti-monster/anduril/config-default.h | 12 ++++++-- spaghetti-monster/anduril/load-save-config-fsm.h | 3 ++ spaghetti-monster/anduril/load-save-config.c | 6 ++++ spaghetti-monster/anduril/off-mode.c | 32 ++++++++++++++++------ spaghetti-monster/anduril/ramp-mode-fsm.h | 5 ++++ spaghetti-monster/anduril/ramp-mode.c | 27 +++++++++++++++++- spaghetti-monster/anduril/ramp-mode.h | 7 +++++ 11 files changed, 91 insertions(+), 12 deletions(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 05d0e04..b497eb9 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -218,6 +218,12 @@ void setup() { load_config(); + #if defined(USE_MANUAL_MEMORY) && defined(USE_MANUAL_MEMORY_TIMER) + // without this, initial boot-up brightness is wrong + // when manual mem is enabled with a non-zero timer + if (manual_memory) memorized_level = manual_memory; + #endif + #ifdef USE_TINT_RAMPING // add tint ramping underneath every other state push_state(tint_ramping_state, 0); diff --git a/spaghetti-monster/anduril/cfg-ff-rot66.h b/spaghetti-monster/anduril/cfg-ff-rot66.h index 9922681..bfffd95 100644 --- a/spaghetti-monster/anduril/cfg-ff-rot66.h +++ b/spaghetti-monster/anduril/cfg-ff-rot66.h @@ -2,6 +2,9 @@ #define MODEL_NUMBER "0411" #include "hwdef-FF_ROT66.h" +// ROM is too big... remove something +#undef USE_VOLTAGE_CORRECTION + // the button lights up #define USE_INDICATOR_LED // the button is visible while main LEDs are on diff --git a/spaghetti-monster/anduril/cfg-ff-rot66g2.h b/spaghetti-monster/anduril/cfg-ff-rot66g2.h index 8a97c87..aefc23a 100644 --- a/spaghetti-monster/anduril/cfg-ff-rot66g2.h +++ b/spaghetti-monster/anduril/cfg-ff-rot66g2.h @@ -5,6 +5,7 @@ // ROM is too big... remove something #undef USE_VOLTAGE_CORRECTION +#undef USE_MANUAL_MEMORY_TIMER // if the "low" mode was disabled, turn it back on #ifdef INDICATOR_LED_SKIP_LOW diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h b/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h index 9b39af1..1a0fefe 100644 --- a/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h @@ -4,6 +4,7 @@ // ROM is too big... remove something #undef USE_VOLTAGE_CORRECTION +#undef USE_MANUAL_MEMORY_TIMER // the button lights up #define USE_INDICATOR_LED diff --git a/spaghetti-monster/anduril/config-default.h b/spaghetti-monster/anduril/config-default.h index ac30b3a..1c2083e 100644 --- a/spaghetti-monster/anduril/config-default.h +++ b/spaghetti-monster/anduril/config-default.h @@ -72,10 +72,16 @@ // adds a runtime option to switch between automatic memory (default) // and manual memory (only available if compiled in) // (manual memory makes 1-click-from-off start at the same level each time) -// (the level can be set explicitly with 5 clicks from on, -// or the user can go back to automatic with click-click-click-click-hold) -// TODO: remap to a shorter button sequence? +// (the level can be set explicitly with 10 clicks from on, +// or the user can go back to automatic with 10H) #define USE_MANUAL_MEMORY +// if enabled, user can use "hybrid memory" +// The light will use automatic or manual memory level, depending on how long +// the light was off. Short off = automatic, long off = manual. +// This also remaps 10C/10H: +// - 10C toggles manual mem on/off at current level. +// - 10H configures the timer value. +#define USE_MANUAL_MEMORY_TIMER // enable sunset timer (ramp-down and automatic shutoff) // timer is available in regular ramp mode and candle mode diff --git a/spaghetti-monster/anduril/load-save-config-fsm.h b/spaghetti-monster/anduril/load-save-config-fsm.h index c7c4c8d..885fb72 100644 --- a/spaghetti-monster/anduril/load-save-config-fsm.h +++ b/spaghetti-monster/anduril/load-save-config-fsm.h @@ -33,6 +33,9 @@ typedef enum { #endif #ifdef USE_MANUAL_MEMORY manual_memory_e, + #ifdef USE_MANUAL_MEMORY_TIMER + manual_memory_timer_e, + #endif #endif #ifdef USE_TINT_RAMPING tint_e, diff --git a/spaghetti-monster/anduril/load-save-config.c b/spaghetti-monster/anduril/load-save-config.c index 8360ee4..2880c6d 100644 --- a/spaghetti-monster/anduril/load-save-config.c +++ b/spaghetti-monster/anduril/load-save-config.c @@ -35,6 +35,9 @@ void load_config() { #endif #ifdef USE_MANUAL_MEMORY manual_memory = eeprom[manual_memory_e]; + #ifdef USE_MANUAL_MEMORY_TIMER + manual_memory_timer = eeprom[manual_memory_timer_e]; + #endif #endif #ifdef USE_TINT_RAMPING tint = eeprom[tint_e]; @@ -92,6 +95,9 @@ void save_config() { #endif #ifdef USE_MANUAL_MEMORY eeprom[manual_memory_e] = manual_memory; + #ifdef USE_MANUAL_MEMORY_TIMER + eeprom[manual_memory_timer_e] = manual_memory_timer; + #endif #endif #ifdef USE_TINT_RAMPING eeprom[tint_e] = tint; diff --git a/spaghetti-monster/anduril/off-mode.c b/spaghetti-monster/anduril/off-mode.c index ab6156a..5ebaa1d 100644 --- a/spaghetti-monster/anduril/off-mode.c +++ b/spaghetti-monster/anduril/off-mode.c @@ -27,6 +27,12 @@ #endif uint8_t off_state(Event event, uint16_t arg) { + #ifdef USE_MANUAL_MEMORY_TIMER + // keep track of how long the light was off, + // so we can do different things on waking, depending on how long asleep + static uint16_t off_time = 0; + #endif + // turn emitter off when entering state if (event == EV_enter_state) { set_level(0); @@ -58,6 +64,9 @@ uint8_t off_state(Event event, uint16_t arg) { #if defined(TICK_DURING_STANDBY) // blink the indicator LED, maybe else if (event == EV_sleep_tick) { + #ifdef USE_MANUAL_MEMORY_TIMER + off_time = arg; + #endif #ifdef USE_INDICATOR_LED if ((indicator_led_mode & 0b00000011) == 0b00000011) { indicator_blink(arg); @@ -118,9 +127,14 @@ uint8_t off_state(Event event, uint16_t arg) { // 1 click (before timeout): go to memorized level, but allow abort for double click else if (event == EV_click1_release) { #ifdef USE_MANUAL_MEMORY - if (manual_memory) - set_level(nearest_level(manual_memory)); - else + // for full manual memory, set manual_memory_timer to 0 + if (manual_memory + #ifdef USE_MANUAL_MEMORY_TIMER + && (off_time >= (manual_memory_timer * SLEEP_TICKS_PER_MINUTE)) + #endif + ) { + set_level(nearest_level(manual_memory)); + } else #endif set_level(nearest_level(memorized_level)); return MISCHIEF_MANAGED; @@ -128,12 +142,14 @@ uint8_t off_state(Event event, uint16_t arg) { #endif // if (B_TIMING_ON != B_TIMEOUT_T) // 1 click: regular mode else if (event == EV_1click) { - #ifdef USE_MANUAL_MEMORY - if (manual_memory) - set_state(steady_state, manual_memory); - else - #endif + #if (B_TIMING_ON != B_TIMEOUT_T) + // brightness was already set; reuse previous value + set_state(steady_state, actual_level); + #else + // FIXME: B_TIMEOUT_T breaks manual_memory and manual_memory_timer + // (need to duplicate manual mem logic here, probably) set_state(steady_state, memorized_level); + #endif return MISCHIEF_MANAGED; } // click, hold: momentary at ceiling or turbo diff --git a/spaghetti-monster/anduril/ramp-mode-fsm.h b/spaghetti-monster/anduril/ramp-mode-fsm.h index 9d8a1f4..997e80d 100644 --- a/spaghetti-monster/anduril/ramp-mode-fsm.h +++ b/spaghetti-monster/anduril/ramp-mode-fsm.h @@ -36,5 +36,10 @@ #define DEFAULT_LEVEL MAX_1x7135 #endif +// requires the ability to measure time while "off" +#ifdef USE_MANUAL_MEMORY_TIMER +#define TICK_DURING_STANDBY +#endif + #endif diff --git a/spaghetti-monster/anduril/ramp-mode.c b/spaghetti-monster/anduril/ramp-mode.c index 90c7368..6d177cc 100644 --- a/spaghetti-monster/anduril/ramp-mode.c +++ b/spaghetti-monster/anduril/ramp-mode.c @@ -368,20 +368,32 @@ uint8_t steady_state(Event event, uint16_t arg) { #ifdef USE_MANUAL_MEMORY else if (event == EV_10clicks) { + #ifdef USE_MANUAL_MEMORY_TIMER + // first time turns on manual memory, + // second time (at same level) goes back to automatic + if (manual_memory == actual_level) manual_memory = 0; + else + #endif manual_memory = actual_level; save_config(); blink_once(); return MISCHIEF_MANAGED; } else if (event == EV_click10_hold) { + #ifdef USE_MANUAL_MEMORY_TIMER + // let user configure timer for manual / hybrid memory + push_state(manual_memory_timer_config_state, 0); + #else // manual mem, but no timer + // turn off manual memory; go back to automatic if (0 == arg) { manual_memory = 0; save_config(); blink_once(); } + #endif return MISCHIEF_MANAGED; } - #endif + #endif // ifdef USE_MANUAL_MEMORY return EVENT_NOT_HANDLED; } @@ -420,6 +432,19 @@ uint8_t simple_ui_config_state(Event event, uint16_t arg) { #endif #endif // #ifdef USE_RAMP_CONFIG +#ifdef USE_MANUAL_MEMORY_TIMER +void manual_memory_timer_config_save() { + uint8_t val; + // skip to keep old value, or click to use hybrid mem with N-1 minute timer + val = config_state_values[0]; + if (val) manual_memory_timer = val - 1; +} + +uint8_t manual_memory_timer_config_state(Event event, uint16_t arg) { + return config_state_base(event, arg, 1, manual_memory_timer_config_save); +} +#endif + // find the ramp level closest to the target, // using only the levels which are allowed in the current state uint8_t nearest_level(int16_t target) { diff --git a/spaghetti-monster/anduril/ramp-mode.h b/spaghetti-monster/anduril/ramp-mode.h index cd350bf..58d65a9 100644 --- a/spaghetti-monster/anduril/ramp-mode.h +++ b/spaghetti-monster/anduril/ramp-mode.h @@ -124,6 +124,10 @@ uint8_t simple_ui_config_state(Event event, uint16_t arg); #endif #endif +#if defined(USE_MANUAL_MEMORY) && defined(USE_MANUAL_MEMORY_TIMER) +uint8_t manual_memory_timer_config_state(Event event, uint16_t arg); +#endif + // calculate the nearest ramp level which would be valid at the moment // (is a no-op for smooth ramp, but limits discrete ramp to only the // correct levels for the user's config) @@ -145,6 +149,9 @@ void set_level_and_therm_target(uint8_t level); uint8_t memorized_level = DEFAULT_LEVEL; #ifdef USE_MANUAL_MEMORY uint8_t manual_memory = 0; +#ifdef USE_MANUAL_MEMORY_TIMER +uint8_t manual_memory_timer = 0; +#endif #endif #ifdef USE_SIMPLE_UI // whether to enable the simplified interface or not -- cgit v1.2.3