diff --git a/docs/anduril-manual.md b/docs/anduril-manual.md index 68c577ca..989247a7 100644 --- a/docs/anduril-manual.md +++ b/docs/anduril-manual.md @@ -817,7 +817,9 @@ Aux LED modes typically include: - Off - Low - High - - Blinking + - Blinking (fancy animation) + - Low blinking + - High blinking To configure the aux LEDs, go to the mode you want to configure and then click the button 7 times. This should change the aux LEDs to the next @@ -843,6 +845,7 @@ On most lights, the colors follow this sequence: - Disco (fast random colors) - Rainbow (cycles through all colors in order) - Voltage (uses color to display battery charge) + - Off (only light up the button LED if present) In voltage mode, the colors follow the same sequence, in the same order as a rainbow... with red indicating a low battery and purple indicating diff --git a/ui/anduril/aux-leds.c b/ui/anduril/aux-leds.c index 73566665..b052ff9d 100644 --- a/ui/anduril/aux-leds.c +++ b/ui/anduril/aux-leds.c @@ -21,35 +21,36 @@ void indicator_led_update(uint8_t mode, uint8_t tick) { //#ifdef USE_INDICATOR_LOW_BAT_WARNING #ifndef DUAL_VOLTAGE_FLOOR // this isn't set up for dual-voltage lights like the Sofirn SP10 Pro // fast blink a warning when battery is low but not critical + // use only low because high would drain the battery even quicker else if (voltage < VOLTAGE_RED) { - indicator_led(mode & (((tick & 0b0010)>>1) - 3)); + indicator_led(!(tick & 2)); } #endif //#endif - // normal steady output, 0/1/2 = off / low / high - else if ((mode & 0b00001111) < 3) { - indicator_led(mode); - } - // beacon-like blinky mode else { - #ifdef USE_OLD_BLINKING_INDICATOR - - // basic blink, 1/8th duty cycle - if (! (tick & 7)) { - indicator_led(2); - } - else { - indicator_led(0); - } - - #else + // Keep only relevant bits + mode &= INDICATOR_LED_CFG_MASK; // fancy blink, set off/low/high levels here: - static const uint8_t seq[] = {0, 1, 2, 1, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0}; - indicator_led(seq[tick & 15]); + static const uint8_t fancy_seq[] = {0, 1, 2, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0}; + + uint8_t level = mode; + switch (mode) { + case 3: + // fancy blink + level = fancy_seq[tick & 15]; + break; + #ifdef USE_EXTENDED_INDICATOR_PATTERNS + case 4: + case 5: + // low or high blink, 1/8th duty cycle + level = (tick & 7) ? 0 : mode - 3; + break; + #endif + } - #endif // ifdef USE_OLD_BLINKING_INDICATOR + indicator_led(level); } } #endif @@ -127,7 +128,11 @@ void rgb_led_update(uint8_t mode, uint16_t arg) { // use high mode if regular aux level is high or prev level was high pattern = 1 + ((2 == pattern) | (prev_level >= POST_OFF_VOLTAGE_BRIGHTNESS)); // voltage mode - color = RGB_LED_NUM_COLORS - 1; + color = RGB_LED_NUM_COLORS - 1 + #ifdef USE_BUTTON_LED + -1 + #endif + ; } #endif @@ -148,6 +153,11 @@ void rgb_led_update(uint8_t mode, uint16_t arg) { } actual_color = pgm_read_byte(colors + rainbow); } + #ifdef USE_BUTTON_LED + else if (color == RGB_LED_NUM_COLORS - 1) { // off + actual_color = 0; + } + #endif else { // voltage // show actual voltage while asleep... if (go_to_standby) { @@ -160,14 +170,22 @@ void rgb_led_update(uint8_t mode, uint16_t arg) { } } - // pick a brightness from the animation sequence - if (pattern == 3) { - // uses an odd length to avoid lining up with rainbow loop - static const uint8_t animation[] = {2, 1, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - frame = (frame + 1) % sizeof(animation); - pattern = animation[frame]; + // uses an odd length to avoid lining up with rainbow loop + static const uint8_t animation[] = {2, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + + switch (pattern) { + case 3: + frame = (frame + 1) % sizeof(animation); + pattern = animation[frame]; + break; + case 4: + case 5: + // low or high blink, 1/8th duty cycle + pattern = (arg & 7) ? 0 : pattern - 3; + break; } + uint8_t result; #ifdef USE_BUTTON_LED uint8_t button_led_result; diff --git a/ui/anduril/aux-leds.h b/ui/anduril/aux-leds.h index fa97e6b9..67450c3e 100644 --- a/ui/anduril/aux-leds.h +++ b/ui/anduril/aux-leds.h @@ -33,8 +33,12 @@ const PROGMEM uint8_t rgb_led_colors[] = { }; // intentionally 1 higher than total modes, to make "voltage" easier to reach // (at Hank's request) -#define RGB_LED_NUM_COLORS 11 -#define RGB_LED_NUM_PATTERNS 4 +const uint8_t RGB_LED_NUM_COLORS = 11 + #ifdef USE_BUTTON_LED + +1 + #endif + ; +#define RGB_LED_NUM_PATTERNS 6 #ifndef RGB_LED_OFF_DEFAULT #define RGB_LED_OFF_DEFAULT 0x19 // low, voltage //#define RGB_LED_OFF_DEFAULT 0x18 // low, rainbow @@ -48,18 +52,34 @@ const PROGMEM uint8_t rgb_led_colors[] = { #endif #endif -//#define USE_OLD_BLINKING_INDICATOR -//#define USE_FANCIER_BLINKING_INDICATOR +#ifdef USE_EXTENDED_INDICATOR_PATTERNS + #define INDICATOR_LED_NUM_PATTERNS 6 + #define INDICATOR_LED_CFG_MASK 0x0F + #define INDICATOR_LED_CFG_OFFSET 4 +#else + #define INDICATOR_LED_NUM_PATTERNS 4 + #define INDICATOR_LED_CFG_MASK 0x03 + #define INDICATOR_LED_CFG_OFFSET 2 +#endif + #ifdef USE_INDICATOR_LED - // bits 2-3 control lockout mode - // bits 0-1 control "off" mode - // modes are: 0=off, 1=low, 2=high, 3=blinking (if TICK_DURING_STANDBY enabled) + #ifndef TICK_DURING_STANDBY + #error "USE_INDICATOR_LED requires TICK_DURING_STANDBY" + #endif + // low nibble: off state + // high nibble: lockout state + // modes are: + // 0=off + // 1=low + // 2=high + // 3=fancy blinking + // 4=low blinking + // 5=high blinking #ifndef INDICATOR_LED_DEFAULT_MODE #ifdef USE_INDICATOR_LED_WHILE_RAMPING - #define INDICATOR_LED_DEFAULT_MODE ((2<<2) + 1) + #define INDICATOR_LED_DEFAULT_MODE ((2<> 2, 0); + // indicator_led_update(cfg.indicator_led_mode >> INDICATOR_LED_CFG_OFFSET, 0); #elif defined(USE_AUX_RGB_LEDS) rgb_led_update(cfg.rgb_led_lockout_mode, 0); #endif @@ -54,7 +54,7 @@ uint8_t lockout_state(Event event, uint16_t arg) { go_to_standby = 1; #ifdef USE_INDICATOR_LED // redundant, sleep tick does the same thing - //indicator_led_update(cfg.indicator_led_mode >> 2, arg); + //indicator_led_update(cfg.indicator_led_mode >> INDICATOR_LED_CFG_OFFSET, arg); #elif defined(USE_AUX_RGB_LEDS) rgb_led_update(cfg.rgb_led_lockout_mode, arg); #endif @@ -73,7 +73,7 @@ uint8_t lockout_state(Event event, uint16_t arg) { } #endif // ifdef USE_MANUAL_MEMORY_TIMER #if defined(USE_INDICATOR_LED) - indicator_led_update(cfg.indicator_led_mode >> 2, arg); + indicator_led_update(cfg.indicator_led_mode >> INDICATOR_LED_CFG_OFFSET, arg); #elif defined(USE_AUX_RGB_LEDS) rgb_led_update(cfg.rgb_led_lockout_mode, arg); #endif @@ -139,21 +139,14 @@ uint8_t lockout_state(Event event, uint16_t arg) { #if defined(USE_INDICATOR_LED) // 7 clicks: rotate through indicator LED modes (lockout mode) else if (event == EV_7clicks) { - #if defined(USE_INDICATOR_LED) - uint8_t mode = cfg.indicator_led_mode >> 2; - #ifdef TICK_DURING_STANDBY - mode = (mode + 1) & 3; - #else - mode = (mode + 1) % 3; - #endif - #ifdef INDICATOR_LED_SKIP_LOW - if (mode == 1) { mode ++; } - #endif - cfg.indicator_led_mode = (mode << 2) + (cfg.indicator_led_mode & 0x03); - // redundant, sleep tick does the same thing - //indicator_led_update(cfg.indicator_led_mode >> 2, arg); - #elif defined(USE_AUX_RGB_LEDS) + uint8_t mode = (cfg.indicator_led_mode >> INDICATOR_LED_CFG_OFFSET) + 1; + mode = mode % INDICATOR_LED_NUM_PATTERNS; + #ifdef INDICATOR_LED_SKIP_LOW + if (mode == 1) { mode ++; } #endif + cfg.indicator_led_mode = + (mode << INDICATOR_LED_CFG_OFFSET) + + (cfg.indicator_led_mode & INDICATOR_LED_CFG_MASK); save_config(); return EVENT_HANDLED; } diff --git a/ui/anduril/off-mode.c b/ui/anduril/off-mode.c index 36d771cf..ea8cab1a 100644 --- a/ui/anduril/off-mode.c +++ b/ui/anduril/off-mode.c @@ -31,7 +31,7 @@ uint8_t off_state(Event event, uint16_t arg) { #endif #ifdef USE_INDICATOR_LED // redundant, sleep tick does the same thing - //indicator_led_update(cfg.indicator_led_mode & 0x03, 0); + //indicator_led_update(cfg.indicator_led_mode, 0); #elif defined(USE_AUX_RGB_LEDS) // redundant, sleep tick does the same thing //rgb_led_update(cfg.rgb_led_off_mode, 0); @@ -55,7 +55,7 @@ uint8_t off_state(Event event, uint16_t arg) { go_to_standby = 1; #ifdef USE_INDICATOR_LED // redundant, sleep tick does the same thing - //indicator_led_update(cfg.indicator_led_mode & 0x03, arg); + //indicator_led_update(cfg.indicator_led_mode, arg); #elif defined(USE_AUX_RGB_LEDS) // redundant, sleep tick does the same thing //rgb_led_update(cfg.rgb_led_off_mode, arg); @@ -76,7 +76,7 @@ uint8_t off_state(Event event, uint16_t arg) { } #endif // ifdef USE_MANUAL_MEMORY_TIMER #ifdef USE_INDICATOR_LED - indicator_led_update(cfg.indicator_led_mode & 0x03, arg); + indicator_led_update(cfg.indicator_led_mode, arg); #elif defined(USE_AUX_RGB_LEDS) rgb_led_update(cfg.rgb_led_off_mode, arg); #endif @@ -280,18 +280,12 @@ uint8_t off_state(Event event, uint16_t arg) { #ifdef USE_INDICATOR_LED // 7 clicks: change indicator LED mode else if (event == EV_7clicks) { - uint8_t mode = (cfg.indicator_led_mode & 3) + 1; - #ifdef TICK_DURING_STANDBY - mode = mode & 3; - #else - mode = mode % 3; - #endif + uint8_t mode = (cfg.indicator_led_mode & INDICATOR_LED_CFG_MASK) + 1; + mode = mode % INDICATOR_LED_NUM_PATTERNS; #ifdef INDICATOR_LED_SKIP_LOW if (mode == 1) { mode ++; } #endif - cfg.indicator_led_mode = (cfg.indicator_led_mode & 0b11111100) | mode; - // redundant, sleep tick does the same thing - //indicator_led_update(cfg.indicator_led_mode & 0x03, arg); + cfg.indicator_led_mode = (cfg.indicator_led_mode & ~INDICATOR_LED_CFG_MASK) | mode; save_config(); return EVENT_HANDLED; }