From 49f4475b2e45b2110b46cd6d44cc967f637c07fc Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 8 Sep 2021 17:14:53 -0600 Subject: got D4Sv2 tint ramping to work, with dynamic PWM (PFM) and (maybe) thermal regulation (untested) (also broke BLF LT1 in the process; need to fix that now) Rewrote how tint ramping works, so it provides a virtual "PWM1_LVL" for other code to use, and it translates that internally into actual hardware controls. This should, in theory, allow smooth thermal regulation (gradual_tick) to work on tint-ramp lights. --- spaghetti-monster/fsm-ramping.c | 108 +++++++++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 40 deletions(-) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 54ca45c..c3a5147 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -89,6 +89,10 @@ void set_level(uint8_t level) { #if PWM_CHANNELS >= 4 PWM4_LVL = 0; #endif + #ifdef USE_TINT_RAMPING + TINT1_LVL = 0; + TINT2_LVL = 0; + #endif // disable the power channel, if relevant #ifdef LED_ENABLE_PIN LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN); @@ -117,44 +121,6 @@ void set_level(uint8_t level) { // PWM array index = level - 1 level --; - #ifdef USE_TINT_RAMPING - #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 - uint8_t brightness = PWM_GET(pwm1_levels, level); - uint8_t warm_PWM, cool_PWM; - - // auto-tint modes - uint8_t mytint; - #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; } - - // middle tints sag, so correct for that effect - uint16_t base_PWM = brightness; - // correction is only necessary when PWM is fast - if (level > HALFSPEED_LEVEL) { - base_PWM = brightness - + ((((uint16_t)brightness) * TINT_RAMPING_CORRECTION / 64) * triangle_wave(mytint) / 255); - } - - cool_PWM = (((uint16_t)mytint * (uint16_t)base_PWM) + 127) / 255; - warm_PWM = base_PWM - cool_PWM; - - PWM1_LVL = warm_PWM; - PWM2_LVL = cool_PWM; - #else // ifdef USE_TINT_RAMPING - #if PWM_CHANNELS >= 1 PWM1_LVL = PWM_GET(pwm1_levels, level); #endif @@ -168,8 +134,6 @@ void set_level(uint8_t level) { PWM4_LVL = PWM_GET(pwm4_levels, level); #endif - #endif // ifdef USE_TINT_RAMPING - #ifdef USE_DYN_PWM uint16_t top = PWM_GET(pwm_tops, level); #ifdef PWM1_CNT @@ -214,6 +178,10 @@ void set_level(uint8_t level) { } #endif } + #ifdef USE_TINT_RAMPING + update_tint(); + #endif + #ifdef PWM1_CNT prev_level = api_level; #endif @@ -289,6 +257,9 @@ void gradual_tick() { { actual_level = gt + 1; } + #ifdef USE_TINT_RAMPING + update_tint(); + #endif #ifdef USE_DYNAMIC_UNDERCLOCKING auto_clock_speed(); #endif @@ -296,5 +267,62 @@ void gradual_tick() { #endif // ifdef OVERRIDE_GRADUAL_TICK #endif // ifdef USE_SET_LEVEL_GRADUALLY + +#ifdef USE_TINT_RAMPING +void update_tint() { + #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); + PWM_DATATYPE brightness = PWM1_LVL; + PWM_DATATYPE warm_PWM, cool_PWM; + + // 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; } + + // middle tints sag, so correct for that effect + PWM_DATATYPE2 base_PWM = brightness; + // correction is only necessary when PWM is fast + #if defined(TINT_RAMPING_CORRECTION) && (TINT_RAMPING_CORRECTION > 0) + if (level > HALFSPEED_LEVEL) { + base_PWM = brightness + + ((((PWM_DATATYPE2)brightness) * TINT_RAMPING_CORRECTION / 64) * triangle_wave(mytint) / 255); + } + #endif + + cool_PWM = (((PWM_DATATYPE2)mytint * (PWM_DATATYPE2)base_PWM) + 127) / 255; + warm_PWM = base_PWM - cool_PWM; + + 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); + #endif + #ifdef LED2_ENABLE_PIN + if (! cool_PWM) + LED2_ENABLE_PORT &= ~(1 << LED2_ENABLE_PIN); + #endif +} +#endif // ifdef USE_TINT_RAMPING + + #endif // ifdef USE_RAMPING #endif -- cgit v1.2.3 From 5405c977d887e4077e76c4ba035b4676509fec12 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 10 Sep 2021 00:40:47 -0600 Subject: added D4Sv2-tintramp-FET build, which uses a FET on one set of LEDs for turbo modes (it's weird, but Hank wants it) also reworked gradual tint adjustment a bit, so some complex parts go in set_level() instead (probably needs more testing) --- spaghetti-monster/fsm-ramping.c | 19 ++++++++++++------- 1 file changed, 12 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 c3a5147..50907ec 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -204,6 +204,7 @@ void gradual_tick() { 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) @@ -212,6 +213,7 @@ void gradual_tick() { else // disable during other parts of the ramp LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN); #endif + */ gt --; // convert 1-based number to 0-based @@ -255,14 +257,17 @@ void gradual_tick() { #endif ) { - actual_level = gt + 1; + //actual_level = gt + 1; + set_level(gt + 1); } - #ifdef USE_TINT_RAMPING - update_tint(); - #endif - #ifdef USE_DYNAMIC_UNDERCLOCKING - auto_clock_speed(); - #endif + // 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 // ifdef USE_SET_LEVEL_GRADUALLY -- cgit v1.2.3 From b8b6214b7e9c3f2bb86f7379995fb64c73736d11 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 10 Sep 2021 00:48:01 -0600 Subject: fixed ancient bug which caused a weird up-spike in thermal regulation during initial turbo drop, on 3-channel drivers like FW3A and ROT66 (as shown here: http://toykeeper.net/torches/fw3a/therm-2019-05-22.1.png ) What happened was... the FET would start to drop, but gradual adjustments noticed that the Nx7135 channel needed to go from 0 to 255, so it would then slowly ramp that up, and then afterward, the FET drop could finally continue... because the code didn't jump straight from 0 to 255 like it was supposed to. Simple, easy fix: Make channel 2 go up immediately just like channel 1 does. This makes the thermal response several seconds faster than it was before, so it doesn't get as hot, and is less likely to overshoot and bounce later. --- spaghetti-monster/fsm-ramping.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 50907ec..88fb490 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -221,14 +221,23 @@ void gradual_tick() { #if PWM_CHANNELS >= 1 target = PWM_GET(pwm1_levels, gt); - 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 if (PWM1_LVL < target) PWM1_LVL ++; + #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 -- cgit v1.2.3 From 75cecc4525522b3a4c6339b5aa303bb568769974 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 10 Sep 2021 01:22:35 -0600 Subject: fixed K9.3 builds (oops, new update_tint() needed to be compiled out for K9.3) --- spaghetti-monster/fsm-ramping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 88fb490..e8fcde7 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -282,7 +282,7 @@ void gradual_tick() { #endif // ifdef USE_SET_LEVEL_GRADUALLY -#ifdef USE_TINT_RAMPING +#if defined(USE_TINT_RAMPING) && (!defined(TINT_RAMP_TOGGLE_ONLY)) void update_tint() { #ifndef TINT_RAMPING_CORRECTION #define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint -- cgit v1.2.3