86
///// Common set_level_*() functions shared by multiple lights /////
87
// (unique lights should use their own,
88
// but these common versions cover most of the common hardware designs)
90
#ifdef USE_SET_LEVEL_1CH
91
// single set of LEDs with 1 power channel
92
void set_level_1ch(uint8_t level) {
96
level --; // PWM array index = level - 1
97
LOW_PWM_LVL = PWM_GET(low_pwm_levels, level);
102
#ifdef USE_SET_LEVEL_2CH_STACKED
103
// single set of LEDs with 2 stacked power channels, DDFET+1 or DDFET+linear
104
void set_level_2ch_stacked(uint8_t level) {
109
level --; // PWM array index = level - 1
110
LOW_PWM_LVL = PWM_GET(low_pwm_levels, level);
111
HIGH_PWM_LVL = PWM_GET(high_pwm_levels, level);
116
#ifdef USE_SET_LEVEL_3CH_STACKED
117
// single set of LEDs with 3 stacked power channels, like DDFET+N+1
118
void set_level_3ch_stacked(uint8_t level) {
124
level --; // PWM array index = level - 1
125
LOW_PWM_LVL = PWM_GET(low_pwm_levels, level);
126
MED_PWM_LVL = PWM_GET(med_pwm_levels, level);
127
HIGH_PWM_LVL = PWM_GET(high_pwm_levels, level);
132
// TODO: upgrade some older lights to dynamic PWM
133
// TODO: 1ch w/ dynamic PWM
134
// TODO: 1ch w/ dynamic PWM and opamp enable pins?
135
// TODO: 2ch stacked w/ dynamic PWM
136
// TODO: 2ch stacked w/ dynamic PWM and opamp enable pins?
138
#ifdef USE_CALC_2CH_BLEND
139
// calculate a "tint ramp" blend between 2 channels
140
// results are placed in *warm and *cool vars
141
// brightness : total amount of light units to distribute
142
// top : maximum allowed brightness per channel
143
// blend : ratio between warm and cool (0 = warm, 128 = 50%, 255 = cool)
147
PWM_DATATYPE brightness,
151
#ifndef TINT_RAMPING_CORRECTION
152
#define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint
155
// calculate actual PWM levels based on a single-channel ramp
157
PWM_DATATYPE warm_PWM, cool_PWM;
158
PWM_DATATYPE2 base_PWM = brightness;
160
#if defined(TINT_RAMPING_CORRECTION) && (TINT_RAMPING_CORRECTION > 0)
161
uint8_t level = actual_level - 1;
163
// middle tints sag, so correct for that effect
164
// by adding extra power which peaks at the middle tint
165
// (correction is only necessary when PWM is fast)
166
if (level > HALFSPEED_LEVEL) {
167
base_PWM = brightness
168
+ ((((PWM_DATATYPE2)brightness) * TINT_RAMPING_CORRECTION / 64)
169
* triangle_wave(blend) / 255);
171
// fade the triangle wave out when above 100% power,
172
// so it won't go over 200%
173
if (brightness > top) {
175
((brightness - top) * TINT_RAMPING_CORRECTION / 64)
176
* triangle_wave(blend) / 255
179
// guarantee no more than 200% power
180
if (base_PWM > (top << 1)) { base_PWM = top << 1; }
183
cool_PWM = (((PWM_DATATYPE2)blend * (PWM_DATATYPE2)base_PWM) + 127) / 255;
184
warm_PWM = base_PWM - cool_PWM;
185
// when running at > 100% power, spill extra over to other channel
186
if (cool_PWM > top) {
187
warm_PWM += (cool_PWM - top);
189
} else if (warm_PWM > top) {
190
cool_PWM += (warm_PWM - top);
197
#endif // ifdef USE_CALC_2CH_BLEND
200
RGB_t hsv2rgb(uint8_t h, uint8_t s, uint8_t v) {
203
uint16_t region, fpart, high, low, rising, falling;
205
if (s == 0) { // grey
206
color.r = color.g = color.b = v;
211
region = ((uint16_t)h * 6) >> 8;
212
// find remainder part, make it from 0-255
213
fpart = ((uint16_t)h * 6) - (region << 8);
215
// calculate graph segments, doing integer multiplication
217
low = (v * (255 - s)) >> 8;
218
falling = (v * (255 - ((s * fpart) >> 8))) >> 8;
219
rising = (v * (255 - ((s * (255 - fpart)) >> 8))) >> 8;
226
// assign graph shapes based on color cone region
262
#endif // ifdef USE_HSV2RGB
265
77
#ifdef USE_LEGACY_SET_LEVEL
266
78
// (this is mostly just here for reference, temporarily)
267
79
// single set of LEDs with 1 to 3 stacked power channels,
414
226
gradual_target = orig;
419
#ifdef USE_GRADUAL_TICK_1CH
420
void gradual_tick_1ch() {
421
GRADUAL_TICK_SETUP();
423
GRADUAL_ADJUST_1CH(low_pwm_levels, LOW_PWM_LVL);
425
// did we go far enough to hit the next defined ramp level?
426
// if so, update the main ramp level tracking var
427
if ((LOW_PWM_LVL == PWM_GET(low_pwm_levels, gt)))
434
#ifdef USE_GRADUAL_TICK_2CH_STACKED
435
void gradual_tick_2ch_stacked() {
436
GRADUAL_TICK_SETUP();
438
GRADUAL_ADJUST(low_pwm_levels, LOW_PWM_LVL, PWM_TOP);
439
GRADUAL_ADJUST_1CH(high_pwm_levels, HIGH_PWM_LVL);
441
// did we go far enough to hit the next defined ramp level?
442
// if so, update the main ramp level tracking var
443
if ( (LOW_PWM_LVL == PWM_GET(low_pwm_levels, gt))
444
&& (HIGH_PWM_LVL == PWM_GET(high_pwm_levels, gt))
452
#ifdef USE_GRADUAL_TICK_3CH_STACKED
453
void gradual_tick_3ch_stacked() {
454
GRADUAL_TICK_SETUP();
456
GRADUAL_ADJUST(low_pwm_levels, LOW_PWM_LVL, PWM_TOP);
457
GRADUAL_ADJUST(med_pwm_levels, MED_PWM_LVL, PWM_TOP);
458
GRADUAL_ADJUST_1CH(high_pwm_levels, HIGH_PWM_LVL);
460
// did we go far enough to hit the next defined ramp level?
461
// if so, update the main ramp level tracking var
462
if ( (LOW_PWM_LVL == PWM_GET(low_pwm_levels, gt))
463
&& (MED_PWM_LVL == PWM_GET(med_pwm_levels, gt))
464
&& (HIGH_PWM_LVL == PWM_GET(high_pwm_levels, gt))
471
229
#endif // ifdef USE_SET_LEVEL_GRADUALLY
474
#if defined(USE_TINT_RAMPING) && (!defined(TINT_RAMP_TOGGLE_ONLY))
475
void set_level_2ch_blend() {
476
#ifndef TINT_RAMPING_CORRECTION
477
#define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint
480
// calculate actual PWM levels based on a single-channel ramp
481
// and a global tint value
482
//PWM_DATATYPE brightness = PWM_GET(pwm1_levels, level);
483
uint16_t brightness = PWM1_LVL;
484
uint16_t warm_PWM, cool_PWM;
485
#ifdef USE_STACKED_DYN_PWM
486
uint16_t top = PWM1_TOP;
487
//uint16_t top = PWM_GET(pwm_tops, actual_level-1);
489
const uint16_t top = PWM_TOP;
494
uint8_t level = actual_level - 1;
496
// perceptual by ramp level
497
if (tint == 0) { mytint = 255 * (uint16_t)level / RAMP_SIZE; }
498
else if (tint == 255) { mytint = 255 - (255 * (uint16_t)level / RAMP_SIZE); }
500
// linear with power level
501
//if (tint == 0) { mytint = brightness; }
502
//else if (tint == 255) { mytint = 255 - brightness; }
504
// stretch 1-254 to fit 0-255 range (hits every value except 98 and 198)
505
else { mytint = (tint * 100 / 99) - 1; }
507
PWM_DATATYPE2 base_PWM = brightness;
508
#if defined(TINT_RAMPING_CORRECTION) && (TINT_RAMPING_CORRECTION > 0)
509
// middle tints sag, so correct for that effect
510
// by adding extra power which peaks at the middle tint
511
// (correction is only necessary when PWM is fast)
512
if (level > HALFSPEED_LEVEL) {
513
base_PWM = brightness
514
+ ((((PWM_DATATYPE2)brightness) * TINT_RAMPING_CORRECTION / 64) * triangle_wave(mytint) / 255);
516
// fade the triangle wave out when above 100% power,
517
// so it won't go over 200%
518
if (brightness > top) {
520
((brightness - top) * TINT_RAMPING_CORRECTION / 64)
521
* triangle_wave(mytint) / 255
524
// guarantee no more than 200% power
525
if (base_PWM > (top << 1)) { base_PWM = top << 1; }
528
cool_PWM = (((PWM_DATATYPE2)mytint * (PWM_DATATYPE2)base_PWM) + 127) / 255;
529
warm_PWM = base_PWM - cool_PWM;
530
// when running at > 100% power, spill extra over to other channel
531
if (cool_PWM > top) {
532
warm_PWM += (cool_PWM - top);
534
} else if (warm_PWM > top) {
535
cool_PWM += (warm_PWM - top);
539
TINT1_LVL = warm_PWM;
540
TINT2_LVL = cool_PWM;
542
// disable the power channel, if relevant
543
#ifdef LED_ENABLE_PIN
545
LED_ENABLE_PORT |= (1 << LED_ENABLE_PIN);
547
LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN);
549
#ifdef LED2_ENABLE_PIN
551
LED2_ENABLE_PORT |= (1 << LED2_ENABLE_PIN);
553
LED2_ENABLE_PORT &= ~(1 << LED2_ENABLE_PIN);
556
#endif // ifdef USE_TINT_RAMPING
559
// define the channel mode lists
560
// TODO: move to progmem
561
SetLevelFuncPtr channel_modes[NUM_CHANNEL_MODES] = { SET_LEVEL_MODES };
562
#ifdef USE_SET_LEVEL_GRADUALLY
563
GradualTickFuncPtr gradual_tick_modes[NUM_CHANNEL_MODES] = { GRADUAL_TICK_MODES };
567
232
#endif // ifdef USE_RAMPING