~toykeeper/flashlight-firmware/fsm

« back to all changes in this revision

Viewing changes to ToyKeeper/hwdef-emisar-2ch-fet.c

  • Committer: Selene ToyKeeper
  • Date: 2023-11-04 15:09:10 UTC
  • mfrom: (483.1.175 anduril2)
  • Revision ID: bzr@toykeeper.net-20231104150910-ddd3afw4nhfvof2l
merged anduril2 branch -> fsm, with *years* of changes
(this also means this code is now Anduril 2 instead of Anduril 1)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
4
 
 
5
#pragma once
 
6
 
 
7
#include "chan-rgbaux.c"
 
8
 
 
9
 
 
10
void set_level_zero();
 
11
 
 
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);
 
17
 
 
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);
 
23
 
 
24
 
 
25
Channel channels[] = {
 
26
    { // channel 1 only
 
27
        .set_level    = set_level_ch1,
 
28
        .gradual_tick = gradual_tick_ch1,
 
29
        .has_args     = 0
 
30
    },
 
31
    { // channel 2 only
 
32
        .set_level    = set_level_ch2,
 
33
        .gradual_tick = gradual_tick_ch2,
 
34
        .has_args     = 0
 
35
    },
 
36
    { // both channels, tied together (max "200%" power)
 
37
        .set_level    = set_level_both,
 
38
        .gradual_tick = gradual_tick_both,
 
39
        .has_args     = 0
 
40
    },
 
41
    { // both channels, manual blend (max "100%" power)
 
42
        .set_level    = set_level_blend,
 
43
        .gradual_tick = gradual_tick_blend,
 
44
        .has_args     = 1
 
45
    },
 
46
    { // both channels, auto blend
 
47
        .set_level    = set_level_auto,
 
48
        .gradual_tick = gradual_tick_auto,
 
49
        .has_args     = 1
 
50
    },
 
51
    RGB_AUX_CHANNELS
 
52
};
 
53
 
 
54
 
 
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);
 
61
 
 
62
    if (! now_on) {
 
63
        CH1_PWM = 0;  // linear
 
64
        CH2_PWM = 0;  // linear
 
65
        CH3_PWM = 0;  // DD FET
 
66
        PWM_TOP = PWM_TOP_INIT;
 
67
        PWM_CNT = 0;
 
68
        CH1_ENABLE_PORT &= ~(1 << CH1_ENABLE_PIN);  // disable opamp
 
69
        CH2_ENABLE_PORT &= ~(1 << CH2_ENABLE_PIN);  // disable opamp
 
70
        return;
 
71
    }
 
72
 
 
73
    if (ch1_pwm)
 
74
        CH1_ENABLE_PORT |= (1 << CH1_ENABLE_PIN);  // enable opamp
 
75
    else
 
76
        CH1_ENABLE_PORT &= ~(1 << CH1_ENABLE_PIN);  // disable opamp
 
77
 
 
78
    if (ch2_pwm)
 
79
        CH2_ENABLE_PORT |= (1 << CH2_ENABLE_PIN);  // enable opamp
 
80
    else
 
81
        CH2_ENABLE_PORT &= ~(1 << CH2_ENABLE_PIN);  // disable opamp
 
82
 
 
83
    CH1_PWM = ch1_pwm;
 
84
    CH2_PWM = ch2_pwm;
 
85
    CH3_PWM = ch3_pwm;
 
86
 
 
87
    // manual phase sync when changing level while already on
 
88
    if (was_on && now_on) while(PWM_CNT > (top - 32)) {}
 
89
 
 
90
    PWM_TOP = top;
 
91
 
 
92
    // reset phase when turning on or off
 
93
    //if ((! was_on) | (! now_on)) PWM_CNT = 0;
 
94
    if (! was_on) PWM_CNT = 0;
 
95
}
 
96
 
 
97
void set_level_zero() {
 
98
    return set_pwms(0, 0, 0, PWM_TOP_INIT);
 
99
}
 
100
 
 
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);
 
106
}
 
107
 
 
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);
 
112
}
 
113
 
 
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);
 
119
}
 
120
 
 
121
void set_level_blend(uint8_t level) {
 
122
    uint16_t pwm1, pwm2;
 
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];
 
128
 
 
129
    calc_2ch_blend(&pwm1, &pwm2, brightness, top, blend);
 
130
 
 
131
    set_pwms(pwm1, pwm2, pwm3, top);
 
132
}
 
133
 
 
134
void set_level_auto(uint8_t level) {
 
135
    uint16_t pwm1, pwm2;
 
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)
 
140
        blend = 255 - blend;
 
141
 
 
142
    calc_2ch_blend(&pwm1, &pwm2, brightness, top, blend);
 
143
 
 
144
    set_pwms(pwm1, pwm2, 0, top);
 
145
}
 
146
 
 
147
 
 
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);
 
153
 
 
154
    // check for completion
 
155
    if ((ch1_pwm == CH1_PWM)
 
156
     && (ch2_pwm == CH2_PWM)
 
157
     && (ch3_pwm == CH3_PWM)) {
 
158
        return true;  // done
 
159
    }
 
160
    return false;  // not done yet
 
161
}
 
162
 
 
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);
 
167
}
 
168
 
 
169
bool gradual_tick_ch2(uint8_t gt) {
 
170
    uint8_t pwm2 = PWM_GET8(pwm4_levels, gt);
 
171
    return gradual_adjust(0, pwm2, 0);
 
172
}
 
173
 
 
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);
 
178
}
 
179
 
 
180
bool gradual_tick_blend(uint8_t level) {
 
181
    uint16_t pwm1, pwm2;
 
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];
 
187
 
 
188
    calc_2ch_blend(&pwm1, &pwm2, brightness, top, blend);
 
189
 
 
190
    return gradual_adjust(pwm1, pwm2, pwm3);
 
191
}
 
192
 
 
193
bool gradual_tick_auto(uint8_t level) {
 
194
    uint16_t pwm1, pwm2;
 
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)
 
199
        blend = 255 - blend;
 
200
 
 
201
    calc_2ch_blend(&pwm1, &pwm2, brightness, top, blend);
 
202
 
 
203
    return gradual_adjust(pwm1, pwm2, 0);
 
204
}
 
205
 
 
206