Guest User

fsm-ramping.c

a guest
Aug 15th, 2021
15
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * fsm-ramping.c: Ramping functions for SpaghettiMonster.
  3.  * Handles 1- to 4-channel smooth ramping on a single LED.
  4.  *
  5.  * Copyright (C) 2017 Selene Scriven
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation, either version 3 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19.  */
  20.  
  21. #ifndef FSM_RAMPING_C
  22. #define FSM_RAMPING_C
  23.  
  24. #ifdef USE_RAMPING
  25.  
  26. void set_level(uint8_t level) {
  27.     actual_level = level;
  28.  
  29.     #ifdef USE_SET_LEVEL_GRADUALLY
  30.     gradual_target = level;
  31.     #endif
  32.  
  33.     #ifdef USE_INDICATOR_LED_WHILE_RAMPING
  34.         #ifdef USE_INDICATOR_LED
  35.         if (! go_to_standby)
  36.             indicator_led((level > 0) + (level > DEFAULT_LEVEL));
  37.         #endif
  38.         //if (level > MAX_1x7135) indicator_led(2);
  39.         //else if (level > 0) indicator_led(1);
  40.         //else if (! go_to_standby) indicator_led(0);
  41.     #else
  42.         #if defined(USE_INDICATOR_LED) || defined(USE_AUX_RGB_LEDS)
  43.         if (! go_to_standby) {
  44.             #ifdef USE_INDICATOR_LED
  45.                 indicator_led(0);
  46.             #endif
  47.             #ifdef USE_AUX_RGB_LEDS
  48.                 rgb_led_set(0);
  49.                 #ifdef USE_BUTTON_LED
  50.                     button_led_set((level > 0) + (level > DEFAULT_LEVEL));
  51.                 #endif
  52.             #endif
  53.         }
  54.         #endif
  55.     #endif
  56.  
  57.     #ifdef OVERRIDE_SET_LEVEL
  58.         set_level_override(level);
  59.     #else
  60.  
  61.     //TCCR0A = PHASE;
  62.     if (level == 0) {
  63.         #if PWM_CHANNELS >= 1
  64.         PWM1_LVL = 0;
  65.         #endif
  66.         #if PWM_CHANNELS >= 2
  67.         PWM2_LVL = 0;
  68.         #endif
  69.         #if PWM_CHANNELS >= 3
  70.         PWM3_LVL = 0;
  71.         #endif
  72.         #if PWM_CHANNELS >= 4
  73.         PWM4_LVL = 0;
  74.         #endif
  75.         // disable the power channel, if relevant
  76.         #ifdef LED_ENABLE_PIN
  77.         LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN);
  78.         #endif
  79.         #ifdef LED2_ENABLE_PIN
  80.         LED2_ENABLE_PORT &= ~(1 << LED2_ENABLE_PIN);
  81.         #endif
  82.     } else {
  83.         // enable the power channel, if relevant
  84.         #ifdef LED_ENABLE_PIN
  85.             #ifndef LED_ENABLE_PIN_LEVEL_MIN
  86.             LED_ENABLE_PORT |= (1 << LED_ENABLE_PIN);
  87.             #else
  88.             // only enable during part of the ramp
  89.             if ((level >= LED_ENABLE_PIN_LEVEL_MIN)
  90.                     && (level <= LED_ENABLE_PIN_LEVEL_MAX))
  91.                 LED_ENABLE_PORT |= (1 << LED_ENABLE_PIN);
  92.             else  // disable during other parts of the ramp
  93.                 LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN);
  94.             #endif
  95.         #endif
  96.         #ifdef LED2_ENABLE_PIN
  97.             #ifndef LED_ENABLE_PIN_LEVEL_MIN
  98.             LED_ENABLE_PORT |= (1 << LED_ENABLE_PIN);
  99.             LED2_ENABLE_PORT |= (1 << LED2_ENABLE_PIN);
  100.             #else
  101.             // only enable during part of the ramp
  102.             if ((level >= LED2_ENABLE_PIN_LEVEL_MIN)
  103.                     && (level <= LED2_ENABLE_PIN_LEVEL_MAX))
  104.                 LED2_ENABLE_PORT |= (1 << LED2_ENABLE_PIN);
  105.             else  // disable during other parts of the ramp
  106.                 LED2_ENABLE_PORT &= ~(1 << LED2_ENABLE_PIN);
  107.             #endif
  108.         #endif
  109.  
  110.         level --;
  111.  
  112.         #ifdef USE_TINT_RAMPING
  113.         #ifndef TINT_RAMPING_CORRECTION
  114.         #define TINT_RAMPING_CORRECTION 26  // 140% brightness at middle tint
  115.         #endif
  116.         // calculate actual PWM levels based on a single-channel ramp
  117.         // and a global tint value
  118.         uint8_t brightness = PWM_GET(pwm1_levels, level);
  119.         uint8_t warm_PWM, cool_PWM;
  120.  
  121.         // auto-tint modes
  122.         uint8_t mytint;
  123.         #if 1
  124.         // perceptual by ramp level
  125.         if (tint == 0) { mytint = 255 * (uint16_t)level / RAMP_SIZE; }
  126.         else if (tint == 255) { mytint = 255 - (255 * (uint16_t)level / RAMP_SIZE); }
  127.         #else
  128.         // linear with power level
  129.         //if (tint == 0) { mytint = brightness; }
  130.         //else if (tint == 255) { mytint = 255 - brightness; }
  131.         #endif
  132.         // stretch 1-254 to fit 0-255 range (hits every value except 98 and 198)
  133.         else { mytint = (tint * 100 / 99) - 1; }
  134.  
  135.         // middle tints sag, so correct for that effect
  136.         uint16_t base_PWM = brightness;
  137.         // correction is only necessary when PWM is fast
  138.         if (level > HALFSPEED_LEVEL) {
  139.             base_PWM = brightness
  140.                      + ((((uint16_t)brightness) * TINT_RAMPING_CORRECTION / 64) * triangle_wave(mytint) / 255);
  141.         }
  142.  
  143.         cool_PWM = (((uint16_t)mytint * (uint16_t)base_PWM) + 127) / 255;
  144.         warm_PWM = base_PWM - cool_PWM;
  145.  
  146.         PWM1_LVL = warm_PWM;
  147.         PWM2_LVL = cool_PWM;
  148.         #else  // ifdef USE_TINT_RAMPING
  149.  
  150.         #if PWM_CHANNELS >= 1
  151.         PWM1_LVL = PWM_GET(pwm1_levels, level);
  152.         #endif
  153.         #if PWM_CHANNELS >= 2
  154.         PWM2_LVL = PWM_GET(pwm2_levels, level);
  155.         #endif
  156.         #if PWM_CHANNELS >= 3
  157.         PWM3_LVL = PWM_GET(pwm3_levels, level);
  158.         #endif
  159.         #if PWM_CHANNELS >= 4
  160.         PWM4_LVL = PWM_GET(pwm4_levels, level);
  161.         #endif
  162.  
  163.         #endif  // ifdef USE_TINT_RAMPING
  164.     }
  165.     #endif  // ifdef OVERRIDE_SET_LEVEL
  166.     #ifdef USE_DYNAMIC_UNDERCLOCKING
  167.     auto_clock_speed();
  168.     #endif
  169. }
  170.  
  171. #ifdef USE_SET_LEVEL_GRADUALLY
  172. inline void set_level_gradually(uint8_t lvl) {
  173.     gradual_target = lvl;
  174. }
  175.  
  176. #ifndef OVERRIDE_GRADUAL_TICK
  177. // call this every frame or every few frames to change brightness very smoothly
  178. void gradual_tick() {
  179.     // go by only one ramp level at a time instead of directly to the target
  180.     uint8_t gt = gradual_target;
  181.     if (gt < actual_level) gt = actual_level - 1;
  182.     else if (gt > actual_level) gt = actual_level + 1;
  183.  
  184.     #ifdef LED_ENABLE_PIN_LEVEL_MIN
  185.     // only enable during part of the ramp
  186.     if ((gt >= LED_ENABLE_PIN_LEVEL_MIN)
  187.             && (gt <= LED_ENABLE_PIN_LEVEL_MAX))
  188.         LED_ENABLE_PORT |= (1 << LED_ENABLE_PIN);
  189.     else  // disable during other parts of the ramp
  190.         LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN);
  191.     #endif
  192.    
  193.     #ifdef LED2_ENABLE_PIN_LEVEL_MIN
  194.     // only enable during part of the ramp
  195.     if ((gt >= LED2_ENABLE_PIN_LEVEL_MIN)
  196.             && (gt <= LED2_ENABLE_PIN_LEVEL_MAX))
  197.         LED2_ENABLE_PORT |= (1 << LED2_ENABLE_PIN);
  198.     else  // disable during other parts of the ramp
  199.         LED2_ENABLE_PORT &= ~(1 << LED2_ENABLE_PIN);
  200.     #endif
  201.    
  202.  
  203.     gt --;  // convert 1-based number to 0-based
  204.  
  205.     PWM_DATATYPE target;
  206.  
  207.     #if PWM_CHANNELS >= 1
  208.     target = PWM_GET(pwm1_levels, gt);
  209.     if ((gt < actual_level)     // special case for FET-only turbo
  210.             && (PWM1_LVL == 0)  // (bypass adjustment period for first step)
  211.             && (target == PWM_TOP)) PWM1_LVL = PWM_TOP;
  212.     else if (PWM1_LVL < target) PWM1_LVL ++;
  213.     else if (PWM1_LVL > target) PWM1_LVL --;
  214.     #endif
  215.     #if PWM_CHANNELS >= 2
  216.     target = PWM_GET(pwm2_levels, gt);
  217.     if (PWM2_LVL < target) PWM2_LVL ++;
  218.     else if (PWM2_LVL > target) PWM2_LVL --;
  219.     #endif
  220.     #if PWM_CHANNELS >= 3
  221.     target = PWM_GET(pwm3_levels, gt);
  222.     if (PWM3_LVL < target) PWM3_LVL ++;
  223.     else if (PWM3_LVL > target) PWM3_LVL --;
  224.     #endif
  225.     #if PWM_CHANNELS >= 4
  226.     target = PWM_GET(pwm4_levels, gt);
  227.     if (PWM4_LVL < target) PWM4_LVL ++;
  228.     else if (PWM4_LVL > target) PWM4_LVL --;
  229.     #endif
  230.  
  231.     // did we go far enough to hit the next defined ramp level?
  232.     // if so, update the main ramp level tracking var
  233.     if ((PWM1_LVL == PWM_GET(pwm1_levels, gt))
  234.         #if PWM_CHANNELS >= 2
  235.             && (PWM2_LVL == PWM_GET(pwm2_levels, gt))
  236.         #endif
  237.         #if PWM_CHANNELS >= 3
  238.             && (PWM3_LVL == PWM_GET(pwm3_levels, gt))
  239.         #endif
  240.         #if PWM_CHANNELS >= 4
  241.             && (PWM4_LVL == PWM_GET(pwm4_levels, gt))
  242.         #endif
  243.         )
  244.     {
  245.         actual_level = gt + 1;
  246.     }
  247.     #ifdef USE_DYNAMIC_UNDERCLOCKING
  248.     auto_clock_speed();
  249.     #endif
  250. }
  251. #endif  // ifdef OVERRIDE_GRADUAL_TICK
  252. #endif  // ifdef USE_SET_LEVEL_GRADUALLY
  253.  
  254. #endif  // ifdef USE_RAMPING
  255. #endif
RAW Paste Data