1
// Emisar generic 2-channel + DD FET w/ tint ramping
2
// Copyright (C) 2021-2023 Selene ToyKeeper
3
// SPDX-License-Identifier: GPL-3.0-or-later
7
#include "chan-rgbaux.c"
10
void set_level_zero();
12
void set_level_ch1(uint8_t level);
13
void set_level_ch2(uint8_t level);
14
void set_level_both(uint8_t level);
15
void set_level_blend(uint8_t level);
16
void set_level_auto(uint8_t level);
18
bool gradual_tick_ch1(uint8_t gt);
19
bool gradual_tick_ch2(uint8_t gt);
20
bool gradual_tick_both(uint8_t gt);
21
bool gradual_tick_blend(uint8_t gt);
22
bool gradual_tick_auto(uint8_t gt);
25
Channel channels[] = {
27
.set_level = set_level_ch1,
28
.gradual_tick = gradual_tick_ch1,
32
.set_level = set_level_ch2,
33
.gradual_tick = gradual_tick_ch2,
36
{ // both channels, tied together (max "200%" power)
37
.set_level = set_level_both,
38
.gradual_tick = gradual_tick_both,
41
{ // both channels, manual blend (max "100%" power)
42
.set_level = set_level_blend,
43
.gradual_tick = gradual_tick_blend,
46
{ // both channels, auto blend
47
.set_level = set_level_auto,
48
.gradual_tick = gradual_tick_auto,
55
// set new values for both channels,
56
// handling any possible combination
57
// and any before/after state
58
void set_pwms(uint8_t ch1_pwm, uint8_t ch2_pwm, uint8_t ch3_pwm, uint16_t top) {
59
bool was_on = (CH1_PWM>0) | (CH2_PWM>0) | (CH3_PWM>0);
60
bool now_on = (ch1_pwm>0) | (ch2_pwm>0) | (ch3_pwm>0);
63
CH1_PWM = 0; // linear
64
CH2_PWM = 0; // linear
65
CH3_PWM = 0; // DD FET
66
PWM_TOP = PWM_TOP_INIT;
68
CH1_ENABLE_PORT &= ~(1 << CH1_ENABLE_PIN); // disable opamp
69
CH2_ENABLE_PORT &= ~(1 << CH2_ENABLE_PIN); // disable opamp
74
CH1_ENABLE_PORT |= (1 << CH1_ENABLE_PIN); // enable opamp
76
CH1_ENABLE_PORT &= ~(1 << CH1_ENABLE_PIN); // disable opamp
79
CH2_ENABLE_PORT |= (1 << CH2_ENABLE_PIN); // enable opamp
81
CH2_ENABLE_PORT &= ~(1 << CH2_ENABLE_PIN); // disable opamp
87
// manual phase sync when changing level while already on
88
if (was_on && now_on) while(PWM_CNT > (top - 32)) {}
92
// reset phase when turning on or off
93
//if ((! was_on) | (! now_on)) PWM_CNT = 0;
94
if (! was_on) PWM_CNT = 0;
97
void set_level_zero() {
98
return set_pwms(0, 0, 0, PWM_TOP_INIT);
101
void set_level_ch1(uint8_t level) {
102
uint8_t pwm1 = PWM_GET8 (pwm1_levels, level);
103
uint8_t pwm3 = PWM_GET8 (pwm2_levels, level);
104
uint16_t top = PWM_GET16(pwm3_levels, level);
105
set_pwms(pwm1, 0, pwm3, top);
108
void set_level_ch2(uint8_t level) {
109
uint8_t pwm2 = PWM_GET8 (pwm4_levels, level);
110
uint16_t top = PWM_GET16(pwm5_levels, level);
111
set_pwms(0, pwm2, 0, top);
114
void set_level_both(uint8_t level) {
115
uint8_t pwm1 = PWM_GET8 (pwm1_levels, level);
116
uint8_t pwm3 = PWM_GET8 (pwm2_levels, level);
117
uint16_t top = PWM_GET16(pwm3_levels, level);
118
set_pwms(pwm1, pwm1, pwm3, top);
121
void set_level_blend(uint8_t level) {
123
uint8_t pwm3 = PWM_GET8 (pwm2_levels, level); // DD FET
124
//uint16_t brightness = PWM_GET8 (pwm1_levels, level) << 1;
125
uint16_t brightness = PWM_GET8 (pwm1_levels, level) + pwm3;
126
uint16_t top = PWM_GET16(pwm3_levels, level);
127
uint8_t blend = cfg.channel_mode_args[channel_mode];
129
calc_2ch_blend(&pwm1, &pwm2, brightness, top, blend);
131
set_pwms(pwm1, pwm2, pwm3, top);
134
void set_level_auto(uint8_t level) {
136
uint8_t brightness = PWM_GET8 (pwm4_levels, level);
137
uint16_t top = PWM_GET16(pwm5_levels, level);
138
uint8_t blend = 255 * (uint16_t)level / RAMP_SIZE;
139
if (cfg.channel_mode_args[channel_mode] & 0b01000000)
142
calc_2ch_blend(&pwm1, &pwm2, brightness, top, blend);
144
set_pwms(pwm1, pwm2, 0, top);
148
///// bump each channel toward a target value /////
149
bool gradual_adjust(uint8_t ch1_pwm, uint8_t ch2_pwm, uint8_t ch3_pwm) {
150
GRADUAL_ADJUST_STACKED(ch1_pwm, CH1_PWM, PWM_TOP_INIT);
151
GRADUAL_ADJUST_STACKED(ch2_pwm, CH2_PWM, PWM_TOP_INIT);
152
GRADUAL_ADJUST_SIMPLE (ch3_pwm, CH3_PWM);
154
// check for completion
155
if ((ch1_pwm == CH1_PWM)
156
&& (ch2_pwm == CH2_PWM)
157
&& (ch3_pwm == CH3_PWM)) {
160
return false; // not done yet
163
bool gradual_tick_ch1(uint8_t gt) {
164
uint8_t pwm1 = PWM_GET8(pwm1_levels, gt);
165
uint8_t pwm3 = PWM_GET8(pwm2_levels, gt);
166
return gradual_adjust(pwm1, 0, pwm3);
169
bool gradual_tick_ch2(uint8_t gt) {
170
uint8_t pwm2 = PWM_GET8(pwm4_levels, gt);
171
return gradual_adjust(0, pwm2, 0);
174
bool gradual_tick_both(uint8_t gt) {
175
uint8_t pwm1 = PWM_GET8(pwm1_levels, gt);
176
uint8_t pwm3 = PWM_GET8(pwm2_levels, gt);
177
return gradual_adjust(pwm1, pwm1, pwm3);
180
bool gradual_tick_blend(uint8_t level) {
182
uint8_t pwm3 = PWM_GET8 (pwm2_levels, level); // DD FET
183
//uint16_t brightness = PWM_GET8 (pwm1_levels, level) << 1;
184
uint16_t brightness = PWM_GET8 (pwm1_levels, level) + pwm3;
185
uint16_t top = PWM_GET16(pwm3_levels, level);
186
uint8_t blend = cfg.channel_mode_args[channel_mode];
188
calc_2ch_blend(&pwm1, &pwm2, brightness, top, blend);
190
return gradual_adjust(pwm1, pwm2, pwm3);
193
bool gradual_tick_auto(uint8_t level) {
195
uint8_t brightness = PWM_GET8 (pwm4_levels, level);
196
uint16_t top = PWM_GET16(pwm5_levels, level);
197
uint8_t blend = 255 * (uint16_t)level / RAMP_SIZE;
198
if (cfg.channel_mode_args[channel_mode] & 0b01000000)
201
calc_2ch_blend(&pwm1, &pwm2, brightness, top, blend);
203
return gradual_adjust(pwm1, pwm2, 0);