8
// "auto tint" channel mode
9
void set_level_auto_3ch_blend(uint8_t level) {
10
BLEND_PWM_DATATYPE vpwm;
8
// single set of LEDs with 1 power channel and dynamic PWM
9
void set_level_1ch_dyn(uint8_t level) {
12
PWM_CNT = 0; // reset phase
15
14
level --; // PWM array index = level - 1
16
vpwm = PWM_GET(blend_pwm_levels, level);
15
RED_PWM_LVL = PWM_GET(pwm1_levels, level);
16
// pulse frequency modulation, a.k.a. dynamic PWM
17
PWM_TOP = PWM_GET(pwm_tops, level);
18
// force reset phase when turning on from zero
19
// (because otherwise the initial response is inconsistent)
20
if (! actual_level) PWM_CNT = 0;
25
// warm + cool blend w/ middle sag correction and dynamic PWM
26
void set_level_2ch_dyn_blend(uint8_t level) {
27
#ifndef TINT_RAMPING_CORRECTION
28
#define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint
34
PWM_CNT = 0; // reset phase
38
level --; // PWM array index = level - 1
39
PWM_DATATYPE brightness = PWM_GET(pwm1_levels, level);
40
uint16_t top = PWM_GET(pwm_tops, level);
42
// calculate actual PWM levels based on a single-channel ramp
43
// and a global tint value
44
uint16_t warm_PWM, cool_PWM;
45
uint8_t mytint = channel_mode_args[channel_mode];
47
PWM_DATATYPE2 base_PWM = brightness;
48
#if defined(TINT_RAMPING_CORRECTION) && (TINT_RAMPING_CORRECTION > 0)
49
// middle tints sag, so correct for that effect
50
// by adding extra power which peaks at the middle tint
51
// (correction is only necessary when PWM is fast)
52
if (level > HALFSPEED_LEVEL) {
54
+ ((((PWM_DATATYPE2)brightness) * TINT_RAMPING_CORRECTION / 64)
55
* triangle_wave(mytint) / 255);
57
// fade the triangle wave out when above 100% power,
58
// so it won't go over 200%
59
if (brightness > top) {
61
((brightness - top) * TINT_RAMPING_CORRECTION / 64)
62
* triangle_wave(mytint) / 255
65
// guarantee no more than 200% power
66
if (base_PWM > (top << 1)) { base_PWM = top << 1; }
69
cool_PWM = (((PWM_DATATYPE2)mytint * (PWM_DATATYPE2)base_PWM) + 127) / 255;
70
warm_PWM = base_PWM - cool_PWM;
71
// when running at > 100% power, spill extra over to other channel
73
warm_PWM += (cool_PWM - top);
75
} else if (warm_PWM > top) {
76
cool_PWM += (warm_PWM - top);
80
WARM_PWM_LVL = warm_PWM;
81
COOL_PWM_LVL = cool_PWM;
83
if (! actual_level) PWM_CNT = 0; // reset phase
87
// "auto tint" channel mode with dynamic PWM
88
void set_level_auto_3ch_dyn_blend(uint8_t level) {
93
PWM_CNT = 0; // reset phase
97
level --; // PWM array index = level - 1
98
PWM_DATATYPE vpwm = PWM_GET(pwm1_levels, level);
99
// pulse frequency modulation, a.k.a. dynamic PWM
100
uint16_t top = PWM_GET(pwm_tops, level);
19
102
// tint goes from 0 (red) to 127 (warm white) to 255 (cool white)
21
104
mytint = 255 * (uint16_t)level / RAMP_SIZE;
23
BLEND_PWM_DATATYPE a, b, c;
106
PWM_DATATYPE a, b, c;
25
108
// red is high at 0, low at 255
26
109
a = (((PWM_DATATYPE2)(255 - mytint)
42
127
void set_level_red_white_blend(uint8_t level) {
43
128
// set the warm+cool white LEDs first
44
129
channel_mode = CM_WHITE;
45
set_level_2ch_blend(level);
130
set_level_2ch_dyn_blend(level);
46
131
channel_mode = CM_WHITE_RED;
48
BLEND_PWM_DATATYPE vpwm;
50
133
// set the red LED as a ratio of the white output level
54
level --; // PWM array index = level - 1
55
vpwm = PWM_GET(blend_pwm_levels, level);
136
PWM_CNT = 0; // reset phase
140
level --; // PWM array index = level - 1
141
PWM_DATATYPE vpwm = PWM_GET(pwm1_levels, level);
59
144
// 255 = red at 100% of white channel PWM
60
145
uint8_t ratio = channel_mode_args[channel_mode];