From 55541be4a505da3df7d1a2b8bf3b5295b0af58f7 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 13 Apr 2023 20:38:25 -0600 Subject: refactor progress checkpoint ... got Sofirn LT1S Pro and Emisar D4v2 working with the new channel mode system ... but there's a lot more left to do --- spaghetti-monster/fsm-ramping.c | 422 +++++++++++++++++++++++++--------------- 1 file changed, 266 insertions(+), 156 deletions(-) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 63692c8..5096dfd 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -2,46 +2,28 @@ * fsm-ramping.c: Ramping functions for SpaghettiMonster. * Handles 1- to 4-channel smooth ramping on a single LED. * - * Copyright (C) 2017 Selene ToyKeeper - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Copyright (C) 2017-2023 Selene ToyKeeper + * SPDX-License-Identifier: GPL-3.0-or-later */ -#ifndef FSM_RAMPING_C -#define FSM_RAMPING_C +#pragma once #ifdef USE_RAMPING -void set_level(uint8_t level) { - #ifdef USE_JUMP_START - // maybe "jump start" the engine, if it's prone to slow starts - // (pulse the output high for a moment to wake up the power regulator) - // (only do this when starting from off and going to a low level) - if ((! actual_level) - && level - && (level < jump_start_level)) { - set_level(jump_start_level); - delay_4ms(JUMP_START_TIME/4); - } - #endif // ifdef USE_JUMP_START +void set_channel_mode(uint8_t mode) { + uint8_t cur_level = actual_level; + // turn off old LEDs before changing channel + set_level(0); - actual_level = level; + // change the channel + channel_mode = mode; - #ifdef USE_SET_LEVEL_GRADUALLY - gradual_target = level; - #endif + // update the LEDs + set_level(cur_level); +} +#ifdef HAS_AUX_LEDS +inline void set_level_aux_leds(uint8_t level) { #ifdef USE_INDICATOR_LED_WHILE_RAMPING // use side-facing aux LEDs while main LEDs are on if (! go_to_standby) { @@ -52,9 +34,6 @@ void set_level(uint8_t level) { button_led_set((level > 0) + (level > DEFAULT_LEVEL)); #endif } - //if (level > MAX_1x7135) indicator_led(2); - //else if (level > 0) indicator_led(1); - //else if (! go_to_standby) indicator_led(0); #else // turn off front-facing aux LEDs while main LEDs are on #if defined(USE_INDICATOR_LED) || defined(USE_AUX_RGB_LEDS) if (! go_to_standby) { @@ -70,33 +49,173 @@ void set_level(uint8_t level) { } #endif #endif +} +#endif // ifdef HAS_AUX_LEDS - #ifdef OVERRIDE_SET_LEVEL - set_level_override(level); - #else - #if defined(PWM1_CNT) && defined(PWM1_PHASE_RESET_ON) || defined(PWM1_PHASE_SYNC) - static uint8_t prev_level = 0; - uint8_t api_level = level; +void set_level(uint8_t level) { + #ifdef USE_JUMP_START + // maybe "jump start" the engine, if it's prone to slow starts + // (pulse the output high for a moment to wake up the power regulator) + // (only do this when starting from off and going to a low level) + // TODO: allow different jump start behavior per channel mode + if ((! actual_level) + && level + && (level < jump_start_level)) { + set_level(jump_start_level); + delay_4ms(JUMP_START_TIME/4); + } + #endif + + #ifdef HAS_AUX_LEDS + set_level_aux_leds(level); + #endif + + // call the relevant hardware-specific set_level_*() + SetLevelFuncPtr set_level_func = channel_modes[channel_mode]; + set_level_func(level); + + actual_level = level; + + #ifdef USE_SET_LEVEL_GRADUALLY + gradual_target = level; + #endif + + #ifdef USE_DYNAMIC_UNDERCLOCKING + auto_clock_speed(); + #endif +} + +///// Common set_level_*() functions shared by multiple lights ///// +// (unique lights should use their own, +// but these common versions cover most of the common hardware designs) + +#ifdef USE_SET_LEVEL_1CH +// single set of LEDs with 1 power channel +void set_level_1ch(uint8_t level) { + if (level == 0) { + LOW_PWM_LVL = 0; + } else { + level --; // PWM array index = level - 1 + LOW_PWM_LVL = PWM_GET(low_pwm_levels, level); + } +} +#endif + +#ifdef USE_SET_LEVEL_2CH_STACKED +// single set of LEDs with 2 stacked power channels, DDFET+1 or DDFET+linear +void set_level_2ch_stacked(uint8_t level) { + if (level == 0) { + LOW_PWM_LVL = 0; + HIGH_PWM_LVL = 0; + } else { + level --; // PWM array index = level - 1 + LOW_PWM_LVL = PWM_GET(low_pwm_levels, level); + HIGH_PWM_LVL = PWM_GET(high_pwm_levels, level); + } +} +#endif + +#ifdef USE_SET_LEVEL_3CH_STACKED +// single set of LEDs with 3 stacked power channels, like DDFET+N+1 +void set_level_3ch_stacked(uint8_t level) { + if (level == 0) { + LOW_PWM_LVL = 0; + MED_PWM_LVL = 0; + HIGH_PWM_LVL = 0; + } else { + level --; // PWM array index = level - 1 + LOW_PWM_LVL = PWM_GET(low_pwm_levels, level); + MED_PWM_LVL = PWM_GET(med_pwm_levels, level); + HIGH_PWM_LVL = PWM_GET(high_pwm_levels, level); + } +} +#endif + +// TODO: upgrade some older lights to dynamic PWM +// TODO: 1ch w/ dynamic PWM +// TODO: 1ch w/ dynamic PWM and opamp enable pins? +// TODO: 2ch stacked w/ dynamic PWM +// TODO: 2ch stacked w/ dynamic PWM and opamp enable pins? + +#ifdef USE_SET_LEVEL_2CH_BLEND +// warm + cool blend w/ middle sag correction +void set_level_2ch_blend(uint8_t level) { + #ifndef TINT_RAMPING_CORRECTION + #define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint + #endif + + BLEND_PWM_DATATYPE vpwm; + + if (level == 0) { + vpwm = 0; + } else { + level --; // PWM array index = level - 1 + vpwm = PWM_GET(blend_pwm_levels, level); + } + + // calculate actual PWM levels based on a single-channel ramp + // and a global tint value + uint16_t brightness = vpwm; + uint16_t warm_PWM, cool_PWM; + const uint16_t top = PWM_TOP; + + // auto-tint modes + uint8_t mytint = channel_mode_args[channel_mode]; + + PWM_DATATYPE2 base_PWM = brightness; + #if defined(TINT_RAMPING_CORRECTION) && (TINT_RAMPING_CORRECTION > 0) + // middle tints sag, so correct for that effect + // by adding extra power which peaks at the middle tint + // (correction is only necessary when PWM is fast) + if (level > HALFSPEED_LEVEL) { + base_PWM = brightness + + ((((PWM_DATATYPE2)brightness) * TINT_RAMPING_CORRECTION / 64) + * triangle_wave(mytint) / 255); + } + // fade the triangle wave out when above 100% power, + // so it won't go over 200% + if (brightness > top) { + base_PWM -= 2 * ( + ((brightness - top) * TINT_RAMPING_CORRECTION / 64) + * triangle_wave(mytint) / 255 + ); + } + // guarantee no more than 200% power + if (base_PWM > (top << 1)) { base_PWM = top << 1; } #endif - //TCCR0A = PHASE; + cool_PWM = (((PWM_DATATYPE2)mytint * (PWM_DATATYPE2)base_PWM) + 127) / 255; + warm_PWM = base_PWM - cool_PWM; + // when running at > 100% power, spill extra over to other channel + if (cool_PWM > top) { + warm_PWM += (cool_PWM - top); + cool_PWM = top; + } else if (warm_PWM > top) { + cool_PWM += (warm_PWM - top); + warm_PWM = top; + } + + WARM_PWM_LVL = warm_PWM; + COOL_PWM_LVL = cool_PWM; +} +#endif // ifdef USE_TINT_RAMPING + +#ifdef USE_LEGACY_SET_LEVEL +// (this is mostly just here for reference, temporarily) +// single set of LEDs with 1 to 3 stacked power channels, +// like linear, FET+1, and FET+N+1 +// (default set_level_*() function for most lights) +void set_level_legacy(uint8_t level) { if (level == 0) { #if PWM_CHANNELS >= 1 - PWM1_LVL = 0; + PWM1_LVL = 0; #endif #if PWM_CHANNELS >= 2 - PWM2_LVL = 0; + PWM2_LVL = 0; #endif #if PWM_CHANNELS >= 3 - PWM3_LVL = 0; - #endif - #if PWM_CHANNELS >= 4 - PWM4_LVL = 0; - #endif - #ifdef USE_TINT_RAMPING - TINT1_LVL = 0; - TINT2_LVL = 0; + PWM3_LVL = 0; #endif #if defined(PWM1_CNT) && defined(PWM1_PHASE_RESET_OFF) PWM1_CNT = 0; @@ -121,7 +240,6 @@ void set_level(uint8_t level) { #endif } else { // enable the power channel, if relevant - #ifndef USE_TINT_RAMPING // update_tint handles this better #ifdef LED_ENABLE_PIN #ifdef LED_ON_DELAY uint8_t led_enable_port_save = LED_ENABLE_PORT; @@ -161,7 +279,6 @@ void set_level(uint8_t level) { delay_4ms(LED2_ON_DELAY/4); #endif #endif - #endif // ifndef USE_TINT_RAMPING // PWM array index = level - 1 level --; @@ -175,9 +292,6 @@ void set_level(uint8_t level) { #if PWM_CHANNELS >= 3 PWM3_LVL = PWM_GET(pwm3_levels, level); #endif - #if PWM_CHANNELS >= 4 - PWM4_LVL = PWM_GET(pwm4_levels, level); - #endif #ifdef USE_DYN_PWM uint16_t top = PWM_GET(pwm_tops, level); @@ -190,29 +304,15 @@ void set_level(uint8_t level) { // (but don't wait when turning on from zero, because // it'll reset the phase below anyway) // to be safe, allow at least 32 cycles to update TOP - while(prev_level && (PWM1_CNT > (top - 32))) {} + while(actual_level && (PWM1_CNT > (top - 32))) {} #endif // pulse frequency modulation, a.k.a. dynamic PWM PWM1_TOP = top; - - // repeat for other channels if necessary - #ifdef PMW2_TOP - #if defined(PWM2_CNT) && defined(PWM2_PHASE_SYNC) - while(prev_level && (PWM2_CNT > (top - 32))) {} - #endif - PWM2_TOP = top; - #endif - #ifdef PMW3_TOP - #if defined(PWM3_CNT) && defined(PWM3_PHASE_SYNC) - while(prev_level && (PWM3_CNT > (top - 32))) {} - #endif - PWM3_TOP = top; - #endif #endif // ifdef USE_DYN_PWM #if defined(PWM1_CNT) && defined(PWM1_PHASE_RESET_ON) // force reset phase when turning on from zero // (because otherwise the initial response is inconsistent) - if (! prev_level) { + if (! actual_level) { PWM1_CNT = 0; #if defined(PWM2_CNT) && defined(PWM2_PHASE_RESET_ON) PWM2_CNT = 0; @@ -223,114 +323,117 @@ void set_level(uint8_t level) { } #endif } - #ifdef USE_TINT_RAMPING - update_tint(); - #endif - - #if defined(PWM1_CNT) && defined(PWM1_PHASE_RESET_ON) || defined(PWM1_PHASE_SYNC) - prev_level = api_level; - #endif - #endif // ifdef OVERRIDE_SET_LEVEL #ifdef USE_DYNAMIC_UNDERCLOCKING auto_clock_speed(); #endif } +#endif + #ifdef USE_SET_LEVEL_GRADUALLY inline void set_level_gradually(uint8_t lvl) { gradual_target = lvl; } -#ifndef OVERRIDE_GRADUAL_TICK + // call this every frame or every few frames to change brightness very smoothly void gradual_tick() { - // go by only one ramp level at a time instead of directly to the target - uint8_t gt = gradual_target; - if (gt < actual_level) gt = actual_level - 1; - else if (gt > actual_level) gt = actual_level + 1; - - /* - #ifdef LED_ENABLE_PIN_LEVEL_MIN - // only enable during part of the ramp - if ((gt >= LED_ENABLE_PIN_LEVEL_MIN) - && (gt <= LED_ENABLE_PIN_LEVEL_MAX)) - LED_ENABLE_PORT |= (1 << LED_ENABLE_PIN); - else // disable during other parts of the ramp - LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN); - #endif - */ + // call the relevant hardware-specific function + GradualTickFuncPtr gradual_tick_func = gradual_tick_modes[channel_mode]; + gradual_tick_func(); +} - gt --; // convert 1-based number to 0-based +// reduce repetition with macros +// common code at the beginning of every gradual tick handler +#define GRADUAL_TICK_SETUP() \ + uint8_t gt = gradual_target; \ + if (gt < actual_level) gt = actual_level - 1; \ + else if (gt > actual_level) gt = actual_level + 1; \ + gt --; \ PWM_DATATYPE target; - #if PWM_CHANNELS >= 1 - target = PWM_GET(pwm1_levels, gt); - #if PWM_CHANNELS > 1 - if ((gt < actual_level) // special case for FET-only turbo - && (PWM1_LVL == 0) // (bypass adjustment period for first step) - && (target == PWM_TOP)) PWM1_LVL = PWM_TOP; - else - #endif - if (PWM1_LVL < target) PWM1_LVL ++; - else if (PWM1_LVL > target) PWM1_LVL --; - #endif - #if PWM_CHANNELS >= 2 - target = PWM_GET(pwm2_levels, gt); - #if PWM_CHANNELS > 2 - if ((gt < actual_level) // special case for FET-only turbo - && (PWM2_LVL == 0) // (bypass adjustment period for first step) - && (target == PWM_TOP)) PWM2_LVL = PWM_TOP; - else - #endif - if (PWM2_LVL < target) PWM2_LVL ++; - else if (PWM2_LVL > target) PWM2_LVL --; - #endif - #if PWM_CHANNELS >= 3 - target = PWM_GET(pwm3_levels, gt); - if (PWM3_LVL < target) PWM3_LVL ++; - else if (PWM3_LVL > target) PWM3_LVL --; - #endif - #if PWM_CHANNELS >= 4 - target = PWM_GET(pwm4_levels, gt); - if (PWM4_LVL < target) PWM4_LVL ++; - else if (PWM4_LVL > target) PWM4_LVL --; - #endif +// tick the top layer of the stack +#define GRADUAL_ADJUST_1CH(TABLE,PWM) \ + target = PWM_GET(TABLE, gt); \ + if (PWM < target) PWM ++; \ + else if (PWM > target) PWM --; + +// tick a base level of the stack +// (with support for special DD FET behavior +// like "low=0, high=255" --> "low=255, high=254") +#define GRADUAL_ADJUST(TABLE,PWM,TOP) \ + target = PWM_GET(TABLE, gt); \ + if ((gt < actual_level) \ + && (PWM == 0) \ + && (target == TOP)) PWM = TOP; \ + else \ + if (PWM < target) PWM ++; \ + else if (PWM > target) PWM --; + +// do this when output exactly matches a ramp level +#define GRADUAL_IS_ACTUAL() \ + uint8_t orig = gradual_target; \ + set_level(gt + 1); \ + gradual_target = orig; + +#ifdef USE_GRADUAL_TICK_1CH +void gradual_tick_1ch() { + GRADUAL_TICK_SETUP(); + + GRADUAL_ADJUST_1CH(low_pwm_levels, LOW_PWM_LVL); // did we go far enough to hit the next defined ramp level? // if so, update the main ramp level tracking var - if ((PWM1_LVL == PWM_GET(pwm1_levels, gt)) - #if PWM_CHANNELS >= 2 - && (PWM2_LVL == PWM_GET(pwm2_levels, gt)) - #endif - #if PWM_CHANNELS >= 3 - && (PWM3_LVL == PWM_GET(pwm3_levels, gt)) - #endif - #if PWM_CHANNELS >= 4 - && (PWM4_LVL == PWM_GET(pwm4_levels, gt)) - #endif + if ((LOW_PWM_LVL == PWM_GET(low_pwm_levels, gt))) + { + GRADUAL_IS_ACTUAL(); + } +} +#endif + +#ifdef USE_GRADUAL_TICK_2CH_STACKED +void gradual_tick_2ch_stacked() { + GRADUAL_TICK_SETUP(); + + GRADUAL_ADJUST(low_pwm_levels, LOW_PWM_LVL, PWM_TOP); + GRADUAL_ADJUST_1CH(high_pwm_levels, HIGH_PWM_LVL); + + // did we go far enough to hit the next defined ramp level? + // if so, update the main ramp level tracking var + if ( (LOW_PWM_LVL == PWM_GET(low_pwm_levels, gt)) + && (HIGH_PWM_LVL == PWM_GET(high_pwm_levels, gt)) + ) + { + GRADUAL_IS_ACTUAL(); + } +} +#endif + +#ifdef USE_GRADUAL_TICK_3CH_STACKED +void gradual_tick_3ch_stacked() { + GRADUAL_TICK_SETUP(); + + GRADUAL_ADJUST(low_pwm_levels, LOW_PWM_LVL, PWM_TOP); + GRADUAL_ADJUST(med_pwm_levels, MED_PWM_LVL, PWM_TOP); + GRADUAL_ADJUST_1CH(high_pwm_levels, HIGH_PWM_LVL); + + // did we go far enough to hit the next defined ramp level? + // if so, update the main ramp level tracking var + if ( (LOW_PWM_LVL == PWM_GET(low_pwm_levels, gt)) + && (MED_PWM_LVL == PWM_GET(med_pwm_levels, gt)) + && (HIGH_PWM_LVL == PWM_GET(high_pwm_levels, gt)) ) { - //actual_level = gt + 1; - uint8_t orig = gradual_target; - set_level(gt + 1); - gradual_target = orig; + GRADUAL_IS_ACTUAL(); } - // is handled in set_level() - //#ifdef USE_TINT_RAMPING - //update_tint(); - //#endif - // is handled in set_level() - //#ifdef USE_DYNAMIC_UNDERCLOCKING - //auto_clock_speed(); - //#endif } -#endif // ifdef OVERRIDE_GRADUAL_TICK +#endif #endif // ifdef USE_SET_LEVEL_GRADUALLY #if defined(USE_TINT_RAMPING) && (!defined(TINT_RAMP_TOGGLE_ONLY)) -void update_tint() { +void set_level_2ch_blend() { #ifndef TINT_RAMPING_CORRECTION #define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint #endif @@ -340,7 +443,7 @@ void update_tint() { //PWM_DATATYPE brightness = PWM_GET(pwm1_levels, level); uint16_t brightness = PWM1_LVL; uint16_t warm_PWM, cool_PWM; - #ifdef USE_DYN_PWM + #ifdef USE_STACKED_DYN_PWM uint16_t top = PWM1_TOP; //uint16_t top = PWM_GET(pwm_tops, actual_level-1); #else @@ -414,5 +517,12 @@ void update_tint() { #endif // ifdef USE_TINT_RAMPING -#endif // ifdef USE_RAMPING +// define the channel mode lists +// TODO: move to progmem +SetLevelFuncPtr channel_modes[NUM_CHANNEL_MODES] = { SET_LEVEL_MODES }; +#ifdef USE_SET_LEVEL_GRADUALLY +GradualTickFuncPtr gradual_tick_modes[NUM_CHANNEL_MODES] = { GRADUAL_TICK_MODES }; #endif + + +#endif // ifdef USE_RAMPING -- cgit v1.2.3 From 6142f73db27cef29246291fd09227cc7bc3d4b15 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 14 Apr 2023 20:51:40 -0600 Subject: LT1S: added thermal regulation ... and a bunch of gradual_tick functions ... and abstracted out some of the tint calculations ... and moved some UI settings into cfg.h --- spaghetti-monster/fsm-ramping.c | 33 --------------------------------- 1 file changed, 33 deletions(-) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 5096dfd..a55c74b 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -344,39 +344,6 @@ void gradual_tick() { } -// reduce repetition with macros -// common code at the beginning of every gradual tick handler -#define GRADUAL_TICK_SETUP() \ - uint8_t gt = gradual_target; \ - if (gt < actual_level) gt = actual_level - 1; \ - else if (gt > actual_level) gt = actual_level + 1; \ - gt --; \ - PWM_DATATYPE target; - -// tick the top layer of the stack -#define GRADUAL_ADJUST_1CH(TABLE,PWM) \ - target = PWM_GET(TABLE, gt); \ - if (PWM < target) PWM ++; \ - else if (PWM > target) PWM --; - -// tick a base level of the stack -// (with support for special DD FET behavior -// like "low=0, high=255" --> "low=255, high=254") -#define GRADUAL_ADJUST(TABLE,PWM,TOP) \ - target = PWM_GET(TABLE, gt); \ - if ((gt < actual_level) \ - && (PWM == 0) \ - && (target == TOP)) PWM = TOP; \ - else \ - if (PWM < target) PWM ++; \ - else if (PWM > target) PWM --; - -// do this when output exactly matches a ramp level -#define GRADUAL_IS_ACTUAL() \ - uint8_t orig = gradual_target; \ - set_level(gt + 1); \ - gradual_target = orig; - #ifdef USE_GRADUAL_TICK_1CH void gradual_tick_1ch() { GRADUAL_TICK_SETUP(); -- cgit v1.2.3 From fbcac59563c32f14de4861449c1b267c247b5b78 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 16 Apr 2023 18:21:29 -0600 Subject: reduced ROM by ~600 bytes by moving all eeprom config values to a "cfg" struct (this also made some parts of the code cleaner) --- spaghetti-monster/fsm-ramping.c | 126 ++++++++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 31 deletions(-) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index a55c74b..14b0db8 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -16,7 +16,7 @@ void set_channel_mode(uint8_t mode) { set_level(0); // change the channel - channel_mode = mode; + CH_MODE = mode; // update the LEDs set_level(cur_level); @@ -61,8 +61,8 @@ void set_level(uint8_t level) { // TODO: allow different jump start behavior per channel mode if ((! actual_level) && level - && (level < jump_start_level)) { - set_level(jump_start_level); + && (level < JUMP_START_LEVEL)) { + set_level(JUMP_START_LEVEL); delay_4ms(JUMP_START_TIME/4); } #endif @@ -72,7 +72,7 @@ void set_level(uint8_t level) { #endif // call the relevant hardware-specific set_level_*() - SetLevelFuncPtr set_level_func = channel_modes[channel_mode]; + SetLevelFuncPtr set_level_func = channel_modes[CH_MODE]; set_level_func(level); actual_level = level; @@ -138,54 +138,52 @@ void set_level_3ch_stacked(uint8_t level) { // TODO: 2ch stacked w/ dynamic PWM // TODO: 2ch stacked w/ dynamic PWM and opamp enable pins? -#ifdef USE_SET_LEVEL_2CH_BLEND -// warm + cool blend w/ middle sag correction -void set_level_2ch_blend(uint8_t level) { +#ifdef USE_CALC_2CH_BLEND +// calculate a "tint ramp" blend between 2 channels +// results are placed in *warm and *cool vars +// brightness : total amount of light units to distribute +// top : maximum allowed brightness per channel +// blend : ratio between warm and cool (0 = warm, 128 = 50%, 255 = cool) +void calc_2ch_blend( + PWM_DATATYPE *warm, + PWM_DATATYPE *cool, + PWM_DATATYPE brightness, + PWM_DATATYPE top, + uint8_t blend) { + #ifndef TINT_RAMPING_CORRECTION #define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint #endif - BLEND_PWM_DATATYPE vpwm; - - if (level == 0) { - vpwm = 0; - } else { - level --; // PWM array index = level - 1 - vpwm = PWM_GET(blend_pwm_levels, level); - } - // calculate actual PWM levels based on a single-channel ramp - // and a global tint value - uint16_t brightness = vpwm; - uint16_t warm_PWM, cool_PWM; - const uint16_t top = PWM_TOP; - - // auto-tint modes - uint8_t mytint = channel_mode_args[channel_mode]; - + // and a blend value + PWM_DATATYPE warm_PWM, cool_PWM; PWM_DATATYPE2 base_PWM = brightness; + #if defined(TINT_RAMPING_CORRECTION) && (TINT_RAMPING_CORRECTION > 0) + uint8_t level = actual_level - 1; + // middle tints sag, so correct for that effect // by adding extra power which peaks at the middle tint // (correction is only necessary when PWM is fast) if (level > HALFSPEED_LEVEL) { base_PWM = brightness + ((((PWM_DATATYPE2)brightness) * TINT_RAMPING_CORRECTION / 64) - * triangle_wave(mytint) / 255); + * triangle_wave(blend) / 255); } // fade the triangle wave out when above 100% power, // so it won't go over 200% if (brightness > top) { base_PWM -= 2 * ( ((brightness - top) * TINT_RAMPING_CORRECTION / 64) - * triangle_wave(mytint) / 255 + * triangle_wave(blend) / 255 ); } // guarantee no more than 200% power if (base_PWM > (top << 1)) { base_PWM = top << 1; } #endif - cool_PWM = (((PWM_DATATYPE2)mytint * (PWM_DATATYPE2)base_PWM) + 127) / 255; + cool_PWM = (((PWM_DATATYPE2)blend * (PWM_DATATYPE2)base_PWM) + 127) / 255; warm_PWM = base_PWM - cool_PWM; // when running at > 100% power, spill extra over to other channel if (cool_PWM > top) { @@ -196,10 +194,76 @@ void set_level_2ch_blend(uint8_t level) { warm_PWM = top; } - WARM_PWM_LVL = warm_PWM; - COOL_PWM_LVL = cool_PWM; + *warm = warm_PWM; + *cool = cool_PWM; } -#endif // ifdef USE_TINT_RAMPING +#endif // ifdef USE_CALC_2CH_BLEND + +#ifdef USE_HSV2RGB +RGB_t hsv2rgb(uint8_t h, uint8_t s, uint8_t v) { + RGB_t color; + + uint16_t region, fpart, high, low, rising, falling; + + if (s == 0) { // grey + color.r = color.g = color.b = v; + return color; + } + + // make hue 0-5 + region = ((uint16_t)h * 6) >> 8; + // find remainder part, make it from 0-255 + fpart = ((uint16_t)h * 6) - (region << 8); + + // calculate graph segments, doing integer multiplication + high = v; + low = (v * (255 - s)) >> 8; + falling = (v * (255 - ((s * fpart) >> 8))) >> 8; + rising = (v * (255 - ((s * (255 - fpart)) >> 8))) >> 8; + + // default floor + color.r = low; + color.g = low; + color.b = low; + + // assign graph shapes based on color cone region + switch (region) { + case 0: + color.r = high; + color.g = rising; + //color.b = low; + break; + case 1: + color.r = falling; + color.g = high; + //color.b = low; + break; + case 2: + //color.r = low; + color.g = high; + color.b = rising; + break; + case 3: + //color.r = low; + color.g = falling; + color.b = high; + break; + case 4: + color.r = rising; + //color.g = low; + color.b = high; + break; + default: + color.r = high; + //color.g = low; + color.b = falling; + break; + } + + return color; +} +#endif // ifdef USE_HSV2RGB + #ifdef USE_LEGACY_SET_LEVEL // (this is mostly just here for reference, temporarily) @@ -339,7 +403,7 @@ inline void set_level_gradually(uint8_t lvl) { // call this every frame or every few frames to change brightness very smoothly void gradual_tick() { // call the relevant hardware-specific function - GradualTickFuncPtr gradual_tick_func = gradual_tick_modes[channel_mode]; + GradualTickFuncPtr gradual_tick_func = gradual_tick_modes[CH_MODE]; gradual_tick_func(); } -- cgit v1.2.3 From 583854e37efde7f461e073e735a1736b02d28c70 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 17 Apr 2023 00:08:32 -0600 Subject: switched the rest of FSM + Anduril to use SPDX license headers instead of full GPL headers (or all too often, nothing at all) There are a few "FIXME" entries where I'm not sure about the correct copyright. --- spaghetti-monster/fsm-ramping.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 14b0db8..280e4b3 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -1,10 +1,6 @@ -/* - * fsm-ramping.c: Ramping functions for SpaghettiMonster. - * Handles 1- to 4-channel smooth ramping on a single LED. - * - * Copyright (C) 2017-2023 Selene ToyKeeper - * SPDX-License-Identifier: GPL-3.0-or-later - */ +// fsm-ramping.c: Ramping functions for SpaghettiMonster. +// Copyright (C) 2017-2023 Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later #pragma once @@ -557,3 +553,4 @@ GradualTickFuncPtr gradual_tick_modes[NUM_CHANNEL_MODES] = { GRADUAL_TICK_MODES #endif // ifdef USE_RAMPING + -- cgit v1.2.3 From 5f6bb2bda2dd4eccbdfba94e5d35cedc8c0c42dc Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 25 Apr 2023 01:07:15 -0600 Subject: updated D4Sv2-tintramp -> Emisar 2-channel build target ... ... and reworked how gradual_tick() works ... and updated LT1S Pro to use new method --- spaghetti-monster/fsm-ramping.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 280e4b3..393c425 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -398,9 +398,20 @@ inline void set_level_gradually(uint8_t lvl) { // call this every frame or every few frames to change brightness very smoothly void gradual_tick() { + uint8_t gt = gradual_target; + if (gt < actual_level) gt = actual_level - 1; + else if (gt > actual_level) gt = actual_level + 1; + gt --; + // call the relevant hardware-specific function GradualTickFuncPtr gradual_tick_func = gradual_tick_modes[CH_MODE]; - gradual_tick_func(); + bool done = gradual_tick_func(gt); + + if (done) { + uint8_t orig = gradual_target; + set_level(gt + 1); + gradual_target = orig; + } } -- cgit v1.2.3 From 00dbf2b76cdbad2dbf2fd3b960bcb09d77f932d1 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 2 May 2023 23:44:22 -0600 Subject: post-off voltage display: use low brightness when torch was at moon level before, and skip the voltage display after UI actions which didn't change the mode (like "Off -> 7C" to change aux LED settings) --- spaghetti-monster/fsm-ramping.c | 1 + 1 file changed, 1 insertion(+) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 393c425..d4e2068 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -71,6 +71,7 @@ void set_level(uint8_t level) { SetLevelFuncPtr set_level_func = channel_modes[CH_MODE]; set_level_func(level); + if (actual_level != level) prev_level = actual_level; actual_level = level; #ifdef USE_SET_LEVEL_GRADUALLY -- cgit v1.2.3 From 95a9eb6b3078915a2686c7ec55320273ef429838 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 10 Jul 2023 11:56:04 -0600 Subject: refactored how channel modes are defined, and converted emisar-2ch build --- spaghetti-monster/fsm-ramping.c | 345 +--------------------------------------- 1 file changed, 5 insertions(+), 340 deletions(-) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index d4e2068..6419bfd 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -6,18 +6,6 @@ #ifdef USE_RAMPING -void set_channel_mode(uint8_t mode) { - uint8_t cur_level = actual_level; - // turn off old LEDs before changing channel - set_level(0); - - // change the channel - CH_MODE = mode; - - // update the LEDs - set_level(cur_level); -} - #ifdef HAS_AUX_LEDS inline void set_level_aux_leds(uint8_t level) { #ifdef USE_INDICATOR_LED_WHILE_RAMPING @@ -55,6 +43,9 @@ void set_level(uint8_t level) { // (pulse the output high for a moment to wake up the power regulator) // (only do this when starting from off and going to a low level) // TODO: allow different jump start behavior per channel mode + // FIXME: don't jump-start during factory reset + // (it seems to cause some eeprom issues on KR4 + // when doing a click with a loose tailcap) if ((! actual_level) && level && (level < JUMP_START_LEVEL)) { @@ -68,7 +59,7 @@ void set_level(uint8_t level) { #endif // call the relevant hardware-specific set_level_*() - SetLevelFuncPtr set_level_func = channel_modes[CH_MODE]; + SetLevelFuncPtr set_level_func = channels[CH_MODE].set_level; set_level_func(level); if (actual_level != level) prev_level = actual_level; @@ -83,185 +74,6 @@ void set_level(uint8_t level) { #endif } -///// Common set_level_*() functions shared by multiple lights ///// -// (unique lights should use their own, -// but these common versions cover most of the common hardware designs) - -#ifdef USE_SET_LEVEL_1CH -// single set of LEDs with 1 power channel -void set_level_1ch(uint8_t level) { - if (level == 0) { - LOW_PWM_LVL = 0; - } else { - level --; // PWM array index = level - 1 - LOW_PWM_LVL = PWM_GET(low_pwm_levels, level); - } -} -#endif - -#ifdef USE_SET_LEVEL_2CH_STACKED -// single set of LEDs with 2 stacked power channels, DDFET+1 or DDFET+linear -void set_level_2ch_stacked(uint8_t level) { - if (level == 0) { - LOW_PWM_LVL = 0; - HIGH_PWM_LVL = 0; - } else { - level --; // PWM array index = level - 1 - LOW_PWM_LVL = PWM_GET(low_pwm_levels, level); - HIGH_PWM_LVL = PWM_GET(high_pwm_levels, level); - } -} -#endif - -#ifdef USE_SET_LEVEL_3CH_STACKED -// single set of LEDs with 3 stacked power channels, like DDFET+N+1 -void set_level_3ch_stacked(uint8_t level) { - if (level == 0) { - LOW_PWM_LVL = 0; - MED_PWM_LVL = 0; - HIGH_PWM_LVL = 0; - } else { - level --; // PWM array index = level - 1 - LOW_PWM_LVL = PWM_GET(low_pwm_levels, level); - MED_PWM_LVL = PWM_GET(med_pwm_levels, level); - HIGH_PWM_LVL = PWM_GET(high_pwm_levels, level); - } -} -#endif - -// TODO: upgrade some older lights to dynamic PWM -// TODO: 1ch w/ dynamic PWM -// TODO: 1ch w/ dynamic PWM and opamp enable pins? -// TODO: 2ch stacked w/ dynamic PWM -// TODO: 2ch stacked w/ dynamic PWM and opamp enable pins? - -#ifdef USE_CALC_2CH_BLEND -// calculate a "tint ramp" blend between 2 channels -// results are placed in *warm and *cool vars -// brightness : total amount of light units to distribute -// top : maximum allowed brightness per channel -// blend : ratio between warm and cool (0 = warm, 128 = 50%, 255 = cool) -void calc_2ch_blend( - PWM_DATATYPE *warm, - PWM_DATATYPE *cool, - PWM_DATATYPE brightness, - PWM_DATATYPE top, - uint8_t blend) { - - #ifndef TINT_RAMPING_CORRECTION - #define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint - #endif - - // calculate actual PWM levels based on a single-channel ramp - // and a blend value - PWM_DATATYPE warm_PWM, cool_PWM; - PWM_DATATYPE2 base_PWM = brightness; - - #if defined(TINT_RAMPING_CORRECTION) && (TINT_RAMPING_CORRECTION > 0) - uint8_t level = actual_level - 1; - - // middle tints sag, so correct for that effect - // by adding extra power which peaks at the middle tint - // (correction is only necessary when PWM is fast) - if (level > HALFSPEED_LEVEL) { - base_PWM = brightness - + ((((PWM_DATATYPE2)brightness) * TINT_RAMPING_CORRECTION / 64) - * triangle_wave(blend) / 255); - } - // fade the triangle wave out when above 100% power, - // so it won't go over 200% - if (brightness > top) { - base_PWM -= 2 * ( - ((brightness - top) * TINT_RAMPING_CORRECTION / 64) - * triangle_wave(blend) / 255 - ); - } - // guarantee no more than 200% power - if (base_PWM > (top << 1)) { base_PWM = top << 1; } - #endif - - cool_PWM = (((PWM_DATATYPE2)blend * (PWM_DATATYPE2)base_PWM) + 127) / 255; - warm_PWM = base_PWM - cool_PWM; - // when running at > 100% power, spill extra over to other channel - if (cool_PWM > top) { - warm_PWM += (cool_PWM - top); - cool_PWM = top; - } else if (warm_PWM > top) { - cool_PWM += (warm_PWM - top); - warm_PWM = top; - } - - *warm = warm_PWM; - *cool = cool_PWM; -} -#endif // ifdef USE_CALC_2CH_BLEND - -#ifdef USE_HSV2RGB -RGB_t hsv2rgb(uint8_t h, uint8_t s, uint8_t v) { - RGB_t color; - - uint16_t region, fpart, high, low, rising, falling; - - if (s == 0) { // grey - color.r = color.g = color.b = v; - return color; - } - - // make hue 0-5 - region = ((uint16_t)h * 6) >> 8; - // find remainder part, make it from 0-255 - fpart = ((uint16_t)h * 6) - (region << 8); - - // calculate graph segments, doing integer multiplication - high = v; - low = (v * (255 - s)) >> 8; - falling = (v * (255 - ((s * fpart) >> 8))) >> 8; - rising = (v * (255 - ((s * (255 - fpart)) >> 8))) >> 8; - - // default floor - color.r = low; - color.g = low; - color.b = low; - - // assign graph shapes based on color cone region - switch (region) { - case 0: - color.r = high; - color.g = rising; - //color.b = low; - break; - case 1: - color.r = falling; - color.g = high; - //color.b = low; - break; - case 2: - //color.r = low; - color.g = high; - color.b = rising; - break; - case 3: - //color.r = low; - color.g = falling; - color.b = high; - break; - case 4: - color.r = rising; - //color.g = low; - color.b = high; - break; - default: - color.r = high; - //color.g = low; - color.b = falling; - break; - } - - return color; -} -#endif // ifdef USE_HSV2RGB - - #ifdef USE_LEGACY_SET_LEVEL // (this is mostly just here for reference, temporarily) // single set of LEDs with 1 to 3 stacked power channels, @@ -405,7 +217,7 @@ void gradual_tick() { gt --; // call the relevant hardware-specific function - GradualTickFuncPtr gradual_tick_func = gradual_tick_modes[CH_MODE]; + GradualTickFuncPtr gradual_tick_func = channels[CH_MODE].gradual_tick; bool done = gradual_tick_func(gt); if (done) { @@ -414,155 +226,8 @@ void gradual_tick() { gradual_target = orig; } } - - -#ifdef USE_GRADUAL_TICK_1CH -void gradual_tick_1ch() { - GRADUAL_TICK_SETUP(); - - GRADUAL_ADJUST_1CH(low_pwm_levels, LOW_PWM_LVL); - - // did we go far enough to hit the next defined ramp level? - // if so, update the main ramp level tracking var - if ((LOW_PWM_LVL == PWM_GET(low_pwm_levels, gt))) - { - GRADUAL_IS_ACTUAL(); - } -} -#endif - -#ifdef USE_GRADUAL_TICK_2CH_STACKED -void gradual_tick_2ch_stacked() { - GRADUAL_TICK_SETUP(); - - GRADUAL_ADJUST(low_pwm_levels, LOW_PWM_LVL, PWM_TOP); - GRADUAL_ADJUST_1CH(high_pwm_levels, HIGH_PWM_LVL); - - // did we go far enough to hit the next defined ramp level? - // if so, update the main ramp level tracking var - if ( (LOW_PWM_LVL == PWM_GET(low_pwm_levels, gt)) - && (HIGH_PWM_LVL == PWM_GET(high_pwm_levels, gt)) - ) - { - GRADUAL_IS_ACTUAL(); - } -} -#endif - -#ifdef USE_GRADUAL_TICK_3CH_STACKED -void gradual_tick_3ch_stacked() { - GRADUAL_TICK_SETUP(); - - GRADUAL_ADJUST(low_pwm_levels, LOW_PWM_LVL, PWM_TOP); - GRADUAL_ADJUST(med_pwm_levels, MED_PWM_LVL, PWM_TOP); - GRADUAL_ADJUST_1CH(high_pwm_levels, HIGH_PWM_LVL); - - // did we go far enough to hit the next defined ramp level? - // if so, update the main ramp level tracking var - if ( (LOW_PWM_LVL == PWM_GET(low_pwm_levels, gt)) - && (MED_PWM_LVL == PWM_GET(med_pwm_levels, gt)) - && (HIGH_PWM_LVL == PWM_GET(high_pwm_levels, gt)) - ) - { - GRADUAL_IS_ACTUAL(); - } -} -#endif #endif // ifdef USE_SET_LEVEL_GRADUALLY -#if defined(USE_TINT_RAMPING) && (!defined(TINT_RAMP_TOGGLE_ONLY)) -void set_level_2ch_blend() { - #ifndef TINT_RAMPING_CORRECTION - #define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint - #endif - - // calculate actual PWM levels based on a single-channel ramp - // and a global tint value - //PWM_DATATYPE brightness = PWM_GET(pwm1_levels, level); - uint16_t brightness = PWM1_LVL; - uint16_t warm_PWM, cool_PWM; - #ifdef USE_STACKED_DYN_PWM - uint16_t top = PWM1_TOP; - //uint16_t top = PWM_GET(pwm_tops, actual_level-1); - #else - const uint16_t top = PWM_TOP; - #endif - - // auto-tint modes - uint8_t mytint; - uint8_t level = actual_level - 1; - #if 1 - // perceptual by ramp level - if (tint == 0) { mytint = 255 * (uint16_t)level / RAMP_SIZE; } - else if (tint == 255) { mytint = 255 - (255 * (uint16_t)level / RAMP_SIZE); } - #else - // linear with power level - //if (tint == 0) { mytint = brightness; } - //else if (tint == 255) { mytint = 255 - brightness; } - #endif - // stretch 1-254 to fit 0-255 range (hits every value except 98 and 198) - else { mytint = (tint * 100 / 99) - 1; } - - PWM_DATATYPE2 base_PWM = brightness; - #if defined(TINT_RAMPING_CORRECTION) && (TINT_RAMPING_CORRECTION > 0) - // middle tints sag, so correct for that effect - // by adding extra power which peaks at the middle tint - // (correction is only necessary when PWM is fast) - if (level > HALFSPEED_LEVEL) { - base_PWM = brightness - + ((((PWM_DATATYPE2)brightness) * TINT_RAMPING_CORRECTION / 64) * triangle_wave(mytint) / 255); - } - // fade the triangle wave out when above 100% power, - // so it won't go over 200% - if (brightness > top) { - base_PWM -= 2 * ( - ((brightness - top) * TINT_RAMPING_CORRECTION / 64) - * triangle_wave(mytint) / 255 - ); - } - // guarantee no more than 200% power - if (base_PWM > (top << 1)) { base_PWM = top << 1; } - #endif - - cool_PWM = (((PWM_DATATYPE2)mytint * (PWM_DATATYPE2)base_PWM) + 127) / 255; - warm_PWM = base_PWM - cool_PWM; - // when running at > 100% power, spill extra over to other channel - if (cool_PWM > top) { - warm_PWM += (cool_PWM - top); - cool_PWM = top; - } else if (warm_PWM > top) { - cool_PWM += (warm_PWM - top); - warm_PWM = top; - } - - TINT1_LVL = warm_PWM; - TINT2_LVL = cool_PWM; - - // disable the power channel, if relevant - #ifdef LED_ENABLE_PIN - if (warm_PWM) - LED_ENABLE_PORT |= (1 << LED_ENABLE_PIN); - else - LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN); - #endif - #ifdef LED2_ENABLE_PIN - if (cool_PWM) - LED2_ENABLE_PORT |= (1 << LED2_ENABLE_PIN); - else - LED2_ENABLE_PORT &= ~(1 << LED2_ENABLE_PIN); - #endif -} -#endif // ifdef USE_TINT_RAMPING - - -// define the channel mode lists -// TODO: move to progmem -SetLevelFuncPtr channel_modes[NUM_CHANNEL_MODES] = { SET_LEVEL_MODES }; -#ifdef USE_SET_LEVEL_GRADUALLY -GradualTickFuncPtr gradual_tick_modes[NUM_CHANNEL_MODES] = { GRADUAL_TICK_MODES }; -#endif - - #endif // ifdef USE_RAMPING -- cgit v1.2.3 From 04a48e44b25d1c42dc26f837586a7503bb74b749 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 24 Aug 2023 17:08:01 -0600 Subject: added channel mode per strobe mode, and made FSM channel mode more flexible, and fixed issue in tactical mode where strobes wouldn't stop on button release --- spaghetti-monster/fsm-ramping.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 6419bfd..a970f0e 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -59,7 +59,7 @@ void set_level(uint8_t level) { #endif // call the relevant hardware-specific set_level_*() - SetLevelFuncPtr set_level_func = channels[CH_MODE].set_level; + SetLevelFuncPtr set_level_func = channels[channel_mode].set_level; set_level_func(level); if (actual_level != level) prev_level = actual_level; @@ -217,7 +217,7 @@ void gradual_tick() { gt --; // call the relevant hardware-specific function - GradualTickFuncPtr gradual_tick_func = channels[CH_MODE].gradual_tick; + GradualTickFuncPtr gradual_tick_func = channels[channel_mode].gradual_tick; bool done = gradual_tick_func(gt); if (done) { -- cgit v1.2.3 From 9e5f2dacebf880f61671974ddd8f604cf1782f37 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 25 Aug 2023 17:27:43 -0600 Subject: started splitting set_level(0) into its own set_level_zero(), and made USE_AUX_RGB_LEDS_WHILE_ON work more like the old indicator LEDs, where it gets set automatically with set_level() Using set_level_zero() reduces space used by channel modes, and simplifies code for each mode's set_level_*() functions. I measured about 220 bytes less in the emisar-d4k-3ch build this way, while also reducing the chance of bugs. --- spaghetti-monster/fsm-ramping.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index a970f0e..89f540b 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -36,6 +36,25 @@ inline void set_level_aux_leds(uint8_t level) { } #endif // ifdef HAS_AUX_LEDS +#ifdef USE_AUX_RGB_LEDS_WHILE_ON +// TODO: maybe move this stuff into FSM +#include "anduril/aux-leds.h" // for rgb_led_voltage_readout() +inline void set_level_aux_rgb_leds(uint8_t level) { + if (! go_to_standby) { + if (level > 0) { + rgb_led_voltage_readout(level > USE_AUX_RGB_LEDS_WHILE_ON); + } else { + rgb_led_set(0); + } + // some drivers can be wired with RGB or single color to button + // ... so support both even though only one is connected + #ifdef USE_BUTTON_LED + button_led_set((level > 0) + (level > DEFAULT_LEVEL)); + #endif + } +} +#endif // ifdef USE_AUX_RGB_LEDS_WHILE_ON + void set_level(uint8_t level) { #ifdef USE_JUMP_START @@ -58,9 +77,17 @@ void set_level(uint8_t level) { set_level_aux_leds(level); #endif - // call the relevant hardware-specific set_level_*() - SetLevelFuncPtr set_level_func = channels[channel_mode].set_level; - set_level_func(level); + #ifdef USE_AUX_RGB_LEDS_WHILE_ON + set_level_aux_rgb_leds(level); + #endif + + if (0 == level) { + set_level_zero(); + } else { + // call the relevant hardware-specific set_level_*() + SetLevelFuncPtr set_level_func = channels[channel_mode].set_level; + set_level_func(level - 1); + } if (actual_level != level) prev_level = actual_level; actual_level = level; -- cgit v1.2.3 From 78f2a7dd69cd21922fc43508b317c5a81f8ea7cb Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 3 Oct 2023 16:24:09 -0600 Subject: raised default temperature limit to 50C on attiny1616 and newer MCUs, slightly simplified gradual_tick() --- spaghetti-monster/fsm-ramping.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 89f540b..adc8acb 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -241,15 +241,14 @@ void gradual_tick() { uint8_t gt = gradual_target; if (gt < actual_level) gt = actual_level - 1; else if (gt > actual_level) gt = actual_level + 1; - gt --; // call the relevant hardware-specific function GradualTickFuncPtr gradual_tick_func = channels[channel_mode].gradual_tick; - bool done = gradual_tick_func(gt); + bool done = gradual_tick_func(gt - 1); if (done) { uint8_t orig = gradual_target; - set_level(gt + 1); + set_level(gt); gradual_target = orig; } } -- cgit v1.2.3