2
* fsm-ramping.c: Ramping functions for SpaghettiMonster.
3
* Handles 1- to 4-channel smooth ramping on a single LED.
5
* Copyright (C) 2017 Selene Scriven
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.
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.
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/>.
26
void set_level(uint8_t level) {
29
#ifdef USE_SET_LEVEL_GRADUALLY
30
gradual_target = level;
33
#ifdef USE_INDICATOR_LED_WHILE_RAMPING
34
#ifdef USE_INDICATOR_LED
36
indicator_led((level > 0) + (level > MAX_1x7135));
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);
42
#if defined(USE_INDICATOR_LED) || defined(USE_AUX_RGB_LEDS)
43
if (! go_to_standby) {
44
#ifdef USE_INDICATOR_LED
47
#ifdef USE_AUX_RGB_LEDS
50
button_led_set((level > 0) + (level > MAX_1x7135));
71
// disable the power channel, if relevant
73
LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN);
75
#ifdef LED_ENABLE2_PIN
76
LED_ENABLE2_PORT &= ~(1 << LED_ENABLE2_PIN);
81
// enable the power channel, if relevant
83
LED_ENABLE_PORT |= (1 << LED_ENABLE_PIN);
85
#ifdef LED_ENABLE2_PIN
86
LED_ENABLE2_PORT |= (1 << LED_ENABLE2_PIN);
89
#ifdef USE_TINT_RAMPING
90
#ifndef TINT_RAMPING_CORRECTION
91
#define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint
93
// calculate actual PWM levels based on a single-channel ramp
94
// and a global tint value
95
uint8_t brightness = PWM_GET(pwm1_levels, level);
96
uint8_t warm_PWM, cool_PWM;
101
// perceptual by ramp level
102
if (tint == 0) { mytint = 255 * (uint16_t)level / RAMP_SIZE; }
103
else if (tint == 255) { mytint = 255 - (255 * (uint16_t)level / RAMP_SIZE); }
105
// linear with power level
106
//if (tint == 0) { mytint = brightness; }
107
//else if (tint == 255) { mytint = 255 - brightness; }
109
// stretch 1-254 to fit 0-255 range (hits every value except 98 and 198)
110
else { mytint = (tint * 100 / 99) - 1; }
112
// middle tints sag, so correct for that effect
113
uint16_t base_PWM = brightness;
114
// correction is only necessary when PWM is fast
115
if (level > HALFSPEED_LEVEL) {
116
base_PWM = brightness
117
+ ((((uint16_t)brightness) * TINT_RAMPING_CORRECTION / 64) * triangle_wave(mytint) / 255);
120
cool_PWM = (((uint16_t)mytint * (uint16_t)base_PWM) + 127) / 255;
121
warm_PWM = base_PWM - cool_PWM;
127
#if PWM_CHANNELS >= 1
128
PWM1_LVL = PWM_GET(pwm1_levels, level);
130
#if PWM_CHANNELS >= 2
131
PWM2_LVL = PWM_GET(pwm2_levels, level);
133
#if PWM_CHANNELS >= 3
134
PWM3_LVL = PWM_GET(pwm3_levels, level);
136
#if PWM_CHANNELS >= 4
137
PWM4_LVL = PWM_GET(pwm4_levels, level);
140
#endif // ifdef USE_TINT_RAMPING
142
#ifdef USE_DYNAMIC_UNDERCLOCKING
147
#ifdef USE_SET_LEVEL_GRADUALLY
148
inline void set_level_gradually(uint8_t lvl) {
149
gradual_target = lvl;
152
// call this every frame or every few frames to change brightness very smoothly
153
void gradual_tick() {
154
// go by only one ramp level at a time instead of directly to the target
155
uint8_t gt = gradual_target;
156
if (gt < actual_level) gt = actual_level - 1;
157
else if (gt > actual_level) gt = actual_level + 1;
159
gt --; // convert 1-based number to 0-based
163
#if PWM_CHANNELS >= 1
164
target = PWM_GET(pwm1_levels, gt);
165
if ((gt < actual_level) // special case for FET-only turbo
166
&& (PWM1_LVL == 0) // (bypass adjustment period for first step)
167
&& (target == PWM_TOP)) PWM1_LVL = PWM_TOP;
168
else if (PWM1_LVL < target) PWM1_LVL ++;
169
else if (PWM1_LVL > target) PWM1_LVL --;
171
#if PWM_CHANNELS >= 2
172
target = PWM_GET(pwm2_levels, gt);
173
if (PWM2_LVL < target) PWM2_LVL ++;
174
else if (PWM2_LVL > target) PWM2_LVL --;
176
#if PWM_CHANNELS >= 3
177
target = PWM_GET(pwm3_levels, gt);
178
if (PWM3_LVL < target) PWM3_LVL ++;
179
else if (PWM3_LVL > target) PWM3_LVL --;
181
#if PWM_CHANNELS >= 4
182
target = PWM_GET(pwm4_levels, gt);
183
if (PWM4_LVL < target) PWM4_LVL ++;
184
else if (PWM4_LVL > target) PWM4_LVL --;
187
// did we go far enough to hit the next defined ramp level?
188
// if so, update the main ramp level tracking var
189
if ((PWM1_LVL == PWM_GET(pwm1_levels, gt))
190
#if PWM_CHANNELS >= 2
191
&& (PWM2_LVL == PWM_GET(pwm2_levels, gt))
193
#if PWM_CHANNELS >= 3
194
&& (PWM3_LVL == PWM_GET(pwm3_levels, gt))
196
#if PWM_CHANNELS >= 4
197
&& (PWM4_LVL == PWM_GET(pwm4_levels, gt))
201
actual_level = gt + 1;
206
#endif // ifdef USE_RAMPING