1
// Emisar 2-channel generic w/ tint ramping
2
// Copyright (C) 2021-2023 Selene ToyKeeper
3
// SPDX-License-Identifier: GPL-3.0-or-later
6
#include "chan-rgbaux.c"
11
void set_level_ch1(uint8_t level);
12
void set_level_ch2(uint8_t level);
13
void set_level_both(uint8_t level);
14
void set_level_blend(uint8_t level);
15
void set_level_auto(uint8_t level);
17
bool gradual_tick_ch1(uint8_t gt);
18
bool gradual_tick_ch2(uint8_t gt);
19
bool gradual_tick_both(uint8_t gt);
20
bool gradual_tick_blend(uint8_t gt);
21
bool gradual_tick_auto(uint8_t gt);
24
Channel channels[] = {
26
.set_level = set_level_ch1,
27
.gradual_tick = gradual_tick_ch1,
31
.set_level = set_level_ch2,
32
.gradual_tick = gradual_tick_ch2,
35
{ // both channels, tied together (max "200%" power)
36
.set_level = set_level_both,
37
.gradual_tick = gradual_tick_both,
40
{ // both channels, manual blend (max "100%" power)
41
.set_level = set_level_blend,
42
.gradual_tick = gradual_tick_blend,
45
{ // both channels, auto blend
46
.set_level = set_level_auto,
47
.gradual_tick = gradual_tick_auto,
54
// set new values for both channels,
55
// handling any possible combination
56
// and any before/after state
57
void set_pwms(uint16_t ch1_pwm, uint16_t ch2_pwm, uint16_t top) {
58
bool was_on = (CH1_PWM>0) | (CH2_PWM>0);
59
bool now_on = (ch1_pwm>0) | (ch2_pwm>0);
64
PWM_TOP = PWM_TOP_INIT;
66
CH1_ENABLE_PORT &= ~(1 << CH1_ENABLE_PIN); // disable opamp
67
CH2_ENABLE_PORT &= ~(1 << CH2_ENABLE_PIN); // disable opamp
72
CH1_ENABLE_PORT |= (1 << CH1_ENABLE_PIN); // enable opamp
74
CH1_ENABLE_PORT &= ~(1 << CH1_ENABLE_PIN); // disable opamp
77
CH2_ENABLE_PORT |= (1 << CH2_ENABLE_PIN); // enable opamp
79
CH2_ENABLE_PORT &= ~(1 << CH2_ENABLE_PIN); // disable opamp
84
// manual phase sync when changing level while already on
85
if (was_on && now_on) while(PWM_CNT > (top - 32)) {}
89
// reset phase when turning on or off
90
//if ((! was_on) | (! now_on)) PWM_CNT = 0;
91
if (! was_on) PWM_CNT = 0;
94
void set_level_zero() {
95
return set_pwms(0, 0, PWM_TOP_INIT);
98
void set_level_ch1(uint8_t level) {
99
uint16_t pwm = PWM_GET(pwm1_levels, level);
100
uint16_t top = PWM_GET(pwm_tops, level);
101
set_pwms(pwm, 0, top);
104
void set_level_ch2(uint8_t level) {
105
uint16_t pwm = PWM_GET(pwm1_levels, level);
106
uint16_t top = PWM_GET(pwm_tops, level);
107
set_pwms(0, pwm, top);
110
void set_level_both(uint8_t level) {
111
uint16_t pwm = PWM_GET(pwm1_levels, level);
112
uint16_t top = PWM_GET(pwm_tops, level);
113
set_pwms(pwm, pwm, top);
116
void set_level_blend(uint8_t level) {
117
PWM_DATATYPE ch1_pwm, ch2_pwm;
118
PWM_DATATYPE brightness = PWM_GET(pwm1_levels, level);
119
PWM_DATATYPE top = PWM_GET(pwm_tops, level);
120
uint8_t blend = cfg.channel_mode_args[channel_mode];
122
calc_2ch_blend(&ch1_pwm, &ch2_pwm, brightness, top, blend);
124
set_pwms(ch1_pwm, ch2_pwm, top);
127
void set_level_auto(uint8_t level) {
128
PWM_DATATYPE ch1_pwm, ch2_pwm;
129
PWM_DATATYPE brightness = PWM_GET(pwm1_levels, level);
130
PWM_DATATYPE top = PWM_GET(pwm_tops, level);
131
uint8_t blend = 255 * (uint16_t)level / RAMP_SIZE;
132
if (cfg.channel_mode_args[channel_mode] & 0b01000000)
135
calc_2ch_blend(&ch1_pwm, &ch2_pwm, brightness, top, blend);
137
set_pwms(ch1_pwm, ch2_pwm, top);
141
///// bump each channel toward a target value /////
142
bool gradual_adjust(uint16_t ch1_pwm, uint16_t ch2_pwm) {
143
GRADUAL_ADJUST_SIMPLE(ch1_pwm, CH1_PWM);
144
GRADUAL_ADJUST_SIMPLE(ch2_pwm, CH2_PWM);
146
// check for completion
147
if ((ch1_pwm == CH1_PWM)
148
&& (ch2_pwm == CH2_PWM)) {
151
return false; // not done yet
154
bool gradual_tick_ch1(uint8_t gt) {
155
uint16_t pwm = PWM_GET(pwm1_levels, gt);
156
return gradual_adjust(pwm, 0);
159
bool gradual_tick_ch2(uint8_t gt) {
160
uint16_t pwm = PWM_GET(pwm1_levels, gt);
161
return gradual_adjust(0, pwm);
164
bool gradual_tick_both(uint8_t gt) {
165
uint16_t pwm = PWM_GET(pwm1_levels, gt);
166
return gradual_adjust(pwm, pwm);
169
bool gradual_tick_blend(uint8_t gt) {
170
PWM_DATATYPE ch1_pwm, ch2_pwm;
171
PWM_DATATYPE brightness = PWM_GET(pwm1_levels, gt);
172
PWM_DATATYPE top = PWM_GET(pwm_tops, gt);
173
uint8_t blend = cfg.channel_mode_args[channel_mode];
175
calc_2ch_blend(&ch1_pwm, &ch2_pwm, brightness, top, blend);
177
return gradual_adjust(ch1_pwm, ch2_pwm);
180
bool gradual_tick_auto(uint8_t gt) {
181
PWM_DATATYPE ch1_pwm, ch2_pwm;
182
PWM_DATATYPE brightness = PWM_GET(pwm1_levels, gt);
183
PWM_DATATYPE top = PWM_GET(pwm_tops, gt);
184
uint8_t blend = 255 * (uint16_t)gt / RAMP_SIZE;
185
if (cfg.channel_mode_args[channel_mode] & 0b01000000)
188
calc_2ch_blend(&ch1_pwm, &ch2_pwm, brightness, top, blend);
190
return gradual_adjust(ch1_pwm, ch2_pwm);