~toykeeper/flashlight-firmware/fsm

« back to all changes in this revision

Viewing changes to ToyKeeper/hwdef-emisar-2ch.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 2-channel generic w/ tint ramping
 
2
// Copyright (C) 2021-2023 Selene ToyKeeper
 
3
// SPDX-License-Identifier: GPL-3.0-or-later
 
4
#pragma once
 
5
 
 
6
#include "chan-rgbaux.c"
 
7
 
 
8
 
 
9
void set_level_zero();
 
10
 
 
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);
 
16
 
 
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);
 
22
 
 
23
 
 
24
Channel channels[] = {
 
25
    { // channel 1 only
 
26
        .set_level    = set_level_ch1,
 
27
        .gradual_tick = gradual_tick_ch1,
 
28
        .has_args     = 0
 
29
    },
 
30
    { // channel 2 only
 
31
        .set_level    = set_level_ch2,
 
32
        .gradual_tick = gradual_tick_ch2,
 
33
        .has_args     = 0
 
34
    },
 
35
    { // both channels, tied together (max "200%" power)
 
36
        .set_level    = set_level_both,
 
37
        .gradual_tick = gradual_tick_both,
 
38
        .has_args     = 0
 
39
    },
 
40
    { // both channels, manual blend (max "100%" power)
 
41
        .set_level    = set_level_blend,
 
42
        .gradual_tick = gradual_tick_blend,
 
43
        .has_args     = 1
 
44
    },
 
45
    { // both channels, auto blend
 
46
        .set_level    = set_level_auto,
 
47
        .gradual_tick = gradual_tick_auto,
 
48
        .has_args     = 1
 
49
    },
 
50
    RGB_AUX_CHANNELS
 
51
};
 
52
 
 
53
 
 
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);
 
60
 
 
61
    if (! now_on) {
 
62
        CH1_PWM = 0;
 
63
        CH2_PWM = 0;
 
64
        PWM_TOP = PWM_TOP_INIT;
 
65
        PWM_CNT = 0;
 
66
        CH1_ENABLE_PORT &= ~(1 << CH1_ENABLE_PIN);  // disable opamp
 
67
        CH2_ENABLE_PORT &= ~(1 << CH2_ENABLE_PIN);  // disable opamp
 
68
        return;
 
69
    }
 
70
 
 
71
    if (ch1_pwm)
 
72
        CH1_ENABLE_PORT |= (1 << CH1_ENABLE_PIN);  // enable opamp
 
73
    else
 
74
        CH1_ENABLE_PORT &= ~(1 << CH1_ENABLE_PIN);  // disable opamp
 
75
 
 
76
    if (ch2_pwm)
 
77
        CH2_ENABLE_PORT |= (1 << CH2_ENABLE_PIN);  // enable opamp
 
78
    else
 
79
        CH2_ENABLE_PORT &= ~(1 << CH2_ENABLE_PIN);  // disable opamp
 
80
 
 
81
    CH1_PWM = ch1_pwm;
 
82
    CH2_PWM = ch2_pwm;
 
83
 
 
84
    // manual phase sync when changing level while already on
 
85
    if (was_on && now_on) while(PWM_CNT > (top - 32)) {}
 
86
 
 
87
    PWM_TOP = top;
 
88
 
 
89
    // reset phase when turning on or off
 
90
    //if ((! was_on) | (! now_on)) PWM_CNT = 0;
 
91
    if (! was_on) PWM_CNT = 0;
 
92
}
 
93
 
 
94
void set_level_zero() {
 
95
    return set_pwms(0, 0, PWM_TOP_INIT);
 
96
}
 
97
 
 
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);
 
102
}
 
103
 
 
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);
 
108
}
 
109
 
 
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);
 
114
}
 
115
 
 
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];
 
121
 
 
122
    calc_2ch_blend(&ch1_pwm, &ch2_pwm, brightness, top, blend);
 
123
 
 
124
    set_pwms(ch1_pwm, ch2_pwm, top);
 
125
}
 
126
 
 
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)
 
133
        blend = 255 - blend;
 
134
 
 
135
    calc_2ch_blend(&ch1_pwm, &ch2_pwm, brightness, top, blend);
 
136
 
 
137
    set_pwms(ch1_pwm, ch2_pwm, top);
 
138
}
 
139
 
 
140
 
 
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);
 
145
 
 
146
    // check for completion
 
147
    if ((ch1_pwm == CH1_PWM)
 
148
     && (ch2_pwm == CH2_PWM)) {
 
149
        return true;  // done
 
150
    }
 
151
    return false;  // not done yet
 
152
}
 
153
 
 
154
bool gradual_tick_ch1(uint8_t gt) {
 
155
    uint16_t pwm = PWM_GET(pwm1_levels, gt);
 
156
    return gradual_adjust(pwm, 0);
 
157
}
 
158
 
 
159
bool gradual_tick_ch2(uint8_t gt) {
 
160
    uint16_t pwm = PWM_GET(pwm1_levels, gt);
 
161
    return gradual_adjust(0, pwm);
 
162
}
 
163
 
 
164
bool gradual_tick_both(uint8_t gt) {
 
165
    uint16_t pwm = PWM_GET(pwm1_levels, gt);
 
166
    return gradual_adjust(pwm, pwm);
 
167
}
 
168
 
 
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];
 
174
 
 
175
    calc_2ch_blend(&ch1_pwm, &ch2_pwm, brightness, top, blend);
 
176
 
 
177
    return gradual_adjust(ch1_pwm, ch2_pwm);
 
178
}
 
179
 
 
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)
 
186
        blend = 255 - blend;
 
187
 
 
188
    calc_2ch_blend(&ch1_pwm, &ch2_pwm, brightness, top, blend);
 
189
 
 
190
    return gradual_adjust(ch1_pwm, ch2_pwm);
 
191
}
 
192
 
 
193