From badf37072988156a4cee753b922306195ee45916 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 24 Aug 2017 02:09:33 -0600 Subject: Added a ramping UI example. Added ramping support in general. --- spaghetti-monster/fsm-ramping.c | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 spaghetti-monster/fsm-ramping.c (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c new file mode 100644 index 0000000..ab7bd3c --- /dev/null +++ b/spaghetti-monster/fsm-ramping.c @@ -0,0 +1,62 @@ +/* + * 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 . + */ + +#ifndef FSM_RAMPING_C +#define FSM_RAMPING_C + +#ifdef USE_RAMPING + +void set_level(uint8_t level) { + actual_level = level; + //TCCR0A = PHASE; + if (level == 0) { + #if PWM_CHANNELS >= 1 + PWM1_LVL = 0; + #endif + #if PWM_CHANNELS >= 2 + PWM2_LVL = 0; + #endif + #if PWM_CHANNELS >= 3 + PWM3_LVL = 0; + #endif + #if PWM_CHANNELS >= 4 + PWM4_LVL = 0; + #endif + } else { + level --; + #if PWM_CHANNELS >= 1 + PWM1_LVL = pgm_read_byte(pwm1_levels + level); + #endif + #if PWM_CHANNELS >= 2 + PWM2_LVL = pgm_read_byte(pwm2_levels + level); + #endif + #if PWM_CHANNELS >= 3 + PWM3_LVL = pgm_read_byte(pwm3_levels + level); + #endif + #if PWM_CHANNELS >= 4 + PWM4_LVL = pgm_read_byte(pwm4_levels + level); + #endif + } +} + +// TODO: set_lvl_smooth? + +#endif // ifdef USE_RAMPING +#endif -- cgit v1.2.3 From 7315575b2e7506417c2f2e81846e378d09949b5e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 9 Sep 2017 22:58:26 -0600 Subject: Made thermal regulation adjust smoothly (1 PWM step at a time) to make adjustments less noticeable. Added set_level_gradually() and gradual_tick() to ramping lib. Not terribly happy with it yet, but it at least works in practice. Added extra thermal regulation checks because I was running into stupid behavior in edge cases. Increased lowest thermal stepdown level to MAX_LEVEL/3 because it was going down way too low before. (is still pretty low, but not quite as bad) --- spaghetti-monster/fsm-ramping.c | 146 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index ab7bd3c..50b4102 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -25,6 +25,9 @@ void set_level(uint8_t level) { actual_level = level; + #ifdef USE_SET_LEVEL_GRADUALLY + gradual_target = level; + #endif //TCCR0A = PHASE; if (level == 0) { #if PWM_CHANNELS >= 1 @@ -56,6 +59,149 @@ void set_level(uint8_t level) { } } +#ifdef USE_SET_LEVEL_GRADUALLY +inline void set_level_gradually(uint8_t lvl) { + gradual_target = lvl; +} + +// FIXME: This sucks +// FIXME: I think this can behave badly in some circumstances: +// - large smooth adjustment in progress +// - from something like (255,10) to (200, 0) +// - ... and a new target gets set while actual_level is ... not quite right +// - ... and it then ends up massively overshooting or even turning off +// (still haven't figured out the exact circumstances to cause it) +// (at the very least, actual_level can suddenly jump when multiple PWM levels are being adjusted) +// (so it's bad to rely on actual_level in the middle of a smooth adjustment) +void gradual_tick() { + int8_t changed = 0; + uint8_t target; + uint8_t gt = gradual_target - 1; + // FIXME: rewrite this completely, probably + // (perhaps go by only one ramp level at a time instead of directly to the target?) + #if PWM_CHANNELS >= 1 + target = pgm_read_byte(pwm1_levels + gt); + if (PWM1_LVL < target) { PWM1_LVL ++; changed = 1; } + else if (PWM1_LVL > target) { PWM1_LVL --; changed = -1; } + #endif + #if PWM_CHANNELS >= 2 + target = pgm_read_byte(pwm2_levels + gt); + if (PWM2_LVL < target) { PWM2_LVL ++; changed = 1; } + else if (PWM2_LVL > target) { PWM2_LVL --; changed = -1; } + #endif + #if PWM_CHANNELS >= 3 + target = pgm_read_byte(pwm3_levels + gt); + if (PWM3_LVL < target) { PWM3_LVL ++; changed = 1; } + else if (PWM3_LVL > target) { PWM3_LVL --; changed = -1; } + #endif + #if PWM_CHANNELS >= 4 + target = pgm_read_byte(pwm4_levels + gt); + if (PWM4_LVL < target) { PWM4_LVL ++; changed = 1; } + else if (PWM4_LVL > target) { PWM4_LVL --; changed = -1; } + #endif + // figure out what actual level is + /* + if (changed < 0) { + #if PWM_CHANNELS >= 4 + if (PWM4_LVL < pgm_read_byte(pwm4_levels + actual_level - 1)) + actual_level --; + else + #endif + #if PWM_CHANNELS >= 3 + if (PWM3_LVL < pgm_read_byte(pwm3_levels + actual_level - 1)) + actual_level --; + else + #endif + #if PWM_CHANNELS >= 2 + if (PWM2_LVL < pgm_read_byte(pwm2_levels + actual_level - 1)) + actual_level --; + else + #endif + if (PWM1_LVL < pgm_read_byte(pwm1_levels + actual_level - 1)) + actual_level --; + } + else if (changed > 0) { + #if PWM_CHANNELS >= 4 + if (PWM4_LVL > pgm_read_byte(pwm4_levels + actual_level - 1)) + actual_level ++; + else + #endif + #if PWM_CHANNELS >= 3 + if (PWM3_LVL > pgm_read_byte(pwm3_levels + actual_level - 1)) + actual_level ++; + else + #endif + #if PWM_CHANNELS >= 2 + if (PWM2_LVL > pgm_read_byte(pwm2_levels + actual_level - 1)) + actual_level ++; + else + #endif + if (PWM1_LVL > pgm_read_byte(pwm1_levels + actual_level - 1)) + actual_level ++; + } + else { + actual_level = gradual_target; + } + */ + /* + if (changed) { + #if PWM_CHANNELS >= 4 + if (PWM4_LVL != pgm_read_byte(pwm4_levels + actual_level - 1)) + actual_level += changed; + else + #endif + #if PWM_CHANNELS >= 3 + if (PWM3_LVL != pgm_read_byte(pwm3_levels + actual_level - 1)) + actual_level += changed; + else + #endif + #if PWM_CHANNELS >= 2 + if (PWM2_LVL != pgm_read_byte(pwm2_levels + actual_level - 1)) + actual_level += changed; + else + #endif + if (PWM1_LVL != pgm_read_byte(pwm1_levels + actual_level - 1)) + actual_level += changed; + } else { + actual_level = gradual_target; + } + */ + //if (! changed) { actual_level = gradual_target; } + if (changed) { + #if PWM_CHANNELS >= 4 + if (PWM4_LVL > 0) { + for (actual_level = 0; + (actual_level < MAX_LEVEL) && + (PWM4_LVL <= pgm_read_byte(pwm4_levels + actual_level - 1)); + actual_level ++) {} + } else + #endif + #if PWM_CHANNELS >= 3 + if (PWM3_LVL > 0) { + for (actual_level = 0; + (actual_level < MAX_LEVEL) && + (PWM3_LVL <= pgm_read_byte(pwm3_levels + actual_level - 1)); + actual_level ++) {} + } else + #endif + #if PWM_CHANNELS >= 2 + if (PWM2_LVL > 0) { + for (actual_level = 0; + (actual_level < MAX_LEVEL) && + (PWM2_LVL <= pgm_read_byte(pwm2_levels + actual_level - 1)); + actual_level ++) {} + } else + #endif + for (actual_level = 0; + (actual_level < MAX_LEVEL) && + (PWM1_LVL <= pgm_read_byte(pwm1_levels + actual_level - 1)); + actual_level ++) {} + } else { + actual_level = gradual_target; + } +} +#endif + // TODO: set_lvl_smooth? #endif // ifdef USE_RAMPING -- cgit v1.2.3 From b34403f8ad26017a5bf311c1b168d4083282f473 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 9 Sep 2017 23:51:59 -0600 Subject: Rewrote gradual_tick(). Is smaller, better, and safer now. Decreased gradual adjustment speed again to make thermal regulation less stair-stepped. --- spaghetti-monster/fsm-ramping.c | 144 ++++++++-------------------------------- 1 file changed, 28 insertions(+), 116 deletions(-) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 50b4102..092c242 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -64,145 +64,57 @@ inline void set_level_gradually(uint8_t lvl) { gradual_target = lvl; } -// FIXME: This sucks -// FIXME: I think this can behave badly in some circumstances: -// - large smooth adjustment in progress -// - from something like (255,10) to (200, 0) -// - ... and a new target gets set while actual_level is ... not quite right -// - ... and it then ends up massively overshooting or even turning off -// (still haven't figured out the exact circumstances to cause it) -// (at the very least, actual_level can suddenly jump when multiple PWM levels are being adjusted) -// (so it's bad to rely on actual_level in the middle of a smooth adjustment) +// call this every frame or every few frames to change brightness very smoothly void gradual_tick() { - int8_t changed = 0; - uint8_t target; + // go by only one ramp level at a time instead of directly to the target uint8_t gt = gradual_target - 1; - // FIXME: rewrite this completely, probably - // (perhaps go by only one ramp level at a time instead of directly to the target?) + if (gt < actual_level) gt = actual_level - 1; + else if (gt > actual_level) gt = actual_level + 1; + + uint8_t target; + #if PWM_CHANNELS >= 1 target = pgm_read_byte(pwm1_levels + gt); - if (PWM1_LVL < target) { PWM1_LVL ++; changed = 1; } - else if (PWM1_LVL > target) { PWM1_LVL --; changed = -1; } + if ((gt < actual_level) // special case for FET-only turbo + && (PWM1_LVL == 0) // (bypass adjustment period for first step) + && (target == 255)) PWM1_LVL = 255; + else if (PWM1_LVL < target) PWM1_LVL ++; + else if (PWM1_LVL > target) PWM1_LVL --; #endif #if PWM_CHANNELS >= 2 target = pgm_read_byte(pwm2_levels + gt); - if (PWM2_LVL < target) { PWM2_LVL ++; changed = 1; } - else if (PWM2_LVL > target) { PWM2_LVL --; changed = -1; } + if (PWM2_LVL < target) PWM2_LVL ++; + else if (PWM2_LVL > target) PWM2_LVL --; #endif #if PWM_CHANNELS >= 3 target = pgm_read_byte(pwm3_levels + gt); - if (PWM3_LVL < target) { PWM3_LVL ++; changed = 1; } - else if (PWM3_LVL > target) { PWM3_LVL --; changed = -1; } + if (PWM3_LVL < target) PWM3_LVL ++; + else if (PWM3_LVL > target) PWM3_LVL --; #endif #if PWM_CHANNELS >= 4 target = pgm_read_byte(pwm4_levels + gt); - if (PWM4_LVL < target) { PWM4_LVL ++; changed = 1; } - else if (PWM4_LVL > target) { PWM4_LVL --; changed = -1; } + if (PWM4_LVL < target) PWM4_LVL ++; + else if (PWM4_LVL > target) PWM4_LVL --; #endif - // figure out what actual level is - /* - if (changed < 0) { - #if PWM_CHANNELS >= 4 - if (PWM4_LVL < pgm_read_byte(pwm4_levels + actual_level - 1)) - actual_level --; - else - #endif - #if PWM_CHANNELS >= 3 - if (PWM3_LVL < pgm_read_byte(pwm3_levels + actual_level - 1)) - actual_level --; - else - #endif - #if PWM_CHANNELS >= 2 - if (PWM2_LVL < pgm_read_byte(pwm2_levels + actual_level - 1)) - actual_level --; - else - #endif - if (PWM1_LVL < pgm_read_byte(pwm1_levels + actual_level - 1)) - actual_level --; - } - else if (changed > 0) { - #if PWM_CHANNELS >= 4 - if (PWM4_LVL > pgm_read_byte(pwm4_levels + actual_level - 1)) - actual_level ++; - else - #endif - #if PWM_CHANNELS >= 3 - if (PWM3_LVL > pgm_read_byte(pwm3_levels + actual_level - 1)) - actual_level ++; - else - #endif + + // did we go far enough to hit the next defined ramp level? + // if so, update the main ramp level tracking var + if ((PWM1_LVL == pgm_read_byte(pwm1_levels + gt)) #if PWM_CHANNELS >= 2 - if (PWM2_LVL > pgm_read_byte(pwm2_levels + actual_level - 1)) - actual_level ++; - else - #endif - if (PWM1_LVL > pgm_read_byte(pwm1_levels + actual_level - 1)) - actual_level ++; - } - else { - actual_level = gradual_target; - } - */ - /* - if (changed) { - #if PWM_CHANNELS >= 4 - if (PWM4_LVL != pgm_read_byte(pwm4_levels + actual_level - 1)) - actual_level += changed; - else + && (PWM2_LVL == pgm_read_byte(pwm2_levels + gt)) #endif #if PWM_CHANNELS >= 3 - if (PWM3_LVL != pgm_read_byte(pwm3_levels + actual_level - 1)) - actual_level += changed; - else - #endif - #if PWM_CHANNELS >= 2 - if (PWM2_LVL != pgm_read_byte(pwm2_levels + actual_level - 1)) - actual_level += changed; - else + && (PWM3_LVL == pgm_read_byte(pwm3_levels + gt)) #endif - if (PWM1_LVL != pgm_read_byte(pwm1_levels + actual_level - 1)) - actual_level += changed; - } else { - actual_level = gradual_target; - } - */ - //if (! changed) { actual_level = gradual_target; } - if (changed) { #if PWM_CHANNELS >= 4 - if (PWM4_LVL > 0) { - for (actual_level = 0; - (actual_level < MAX_LEVEL) && - (PWM4_LVL <= pgm_read_byte(pwm4_levels + actual_level - 1)); - actual_level ++) {} - } else - #endif - #if PWM_CHANNELS >= 3 - if (PWM3_LVL > 0) { - for (actual_level = 0; - (actual_level < MAX_LEVEL) && - (PWM3_LVL <= pgm_read_byte(pwm3_levels + actual_level - 1)); - actual_level ++) {} - } else + && (PWM4_LVL == pgm_read_byte(pwm4_levels + gt)) #endif - #if PWM_CHANNELS >= 2 - if (PWM2_LVL > 0) { - for (actual_level = 0; - (actual_level < MAX_LEVEL) && - (PWM2_LVL <= pgm_read_byte(pwm2_levels + actual_level - 1)); - actual_level ++) {} - } else - #endif - for (actual_level = 0; - (actual_level < MAX_LEVEL) && - (PWM1_LVL <= pgm_read_byte(pwm1_levels + actual_level - 1)); - actual_level ++) {} - } else { - actual_level = gradual_target; + ) + { + actual_level = gt; } } #endif -// TODO: set_lvl_smooth? - #endif // ifdef USE_RAMPING #endif -- cgit v1.2.3 From e5864361c5e05aa5356d06cba6a19441ea0dc996 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 10 Sep 2017 16:38:40 -0600 Subject: Fixed a bug in gradual_tick(), I think. It was off by one, and caused actual_level to be off by one, which caused other parts of the code to do weird things... - end-of-ramp blink would happen repeatedly. - ramping up went slower (or not at all, with gradual_tick on each tick) - would sometimes trigger underheating code at moon level, and then glide up to the minimum regulation floor --- spaghetti-monster/fsm-ramping.c | 6 ++++-- 1 file changed, 4 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 092c242..cc5f486 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -67,10 +67,12 @@ inline void set_level_gradually(uint8_t lvl) { // 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 - 1; + uint8_t gt = gradual_target; if (gt < actual_level) gt = actual_level - 1; else if (gt > actual_level) gt = actual_level + 1; + gt --; // convert 1-based number to 0-based + uint8_t target; #if PWM_CHANNELS >= 1 @@ -111,7 +113,7 @@ void gradual_tick() { #endif ) { - actual_level = gt; + actual_level = gt + 1; } } #endif -- cgit v1.2.3 From 45e3a7758046536754f073c42ac27dc737e69fab Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 26 Sep 2017 16:47:44 -0600 Subject: Added dynamic underclocking to FSM, instead of doing it manually in Anduril. --- spaghetti-monster/fsm-ramping.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index cc5f486..11e56a5 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -57,6 +57,9 @@ void set_level(uint8_t level) { PWM4_LVL = pgm_read_byte(pwm4_levels + level); #endif } + #ifdef USE_DYNAMIC_UNDERCLOCKING + auto_clock_speed(); + #endif } #ifdef USE_SET_LEVEL_GRADUALLY -- cgit v1.2.3 From a154ddbda5477a9b5a66333b8777fd6d1ee99d39 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 21 Oct 2017 06:51:27 -0600 Subject: Moved indicator_led() from Anduril into FSM. Made it auto-set indicator level based on ramp level. Made Anduril configure voltage fudge and indicator LED functions based on driver type. Removed "ticks_spent_awake" thing since it's redundant. EV_tick arg does the same thing in fewer bytes. Rearranged some clauses in off_state to put events in a more coherent order. --- spaghetti-monster/fsm-ramping.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'spaghetti-monster/fsm-ramping.c') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 11e56a5..ec132ae 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -28,6 +28,13 @@ void set_level(uint8_t level) { #ifdef USE_SET_LEVEL_GRADUALLY gradual_target = level; #endif + #ifdef USE_INDICATOR_LED + if (! go_to_standby) + indicator_led((level > 0) + (level > MAX_1x7135)); + //if (level > MAX_1x7135) indicator_led(2); + //else if (level > 0) indicator_led(1); + //else if (! go_to_standby) indicator_led(0); + #endif //TCCR0A = PHASE; if (level == 0) { #if PWM_CHANNELS >= 1 -- cgit v1.2.3