5 static uint16_t pwm_vals[N_PWMLEDS*N_PWMLED_MODES];
6 static uint16_t pwm_max[N_PWMLEDS] = { 0x70, 0x70, 0x1F0 };
7 static uint16_t adc_max[N_PWMLEDS] = { 0x70, 0x70, 0xF0 };
8 static uint16_t adc_vals[N_PWMLEDS*N_PWMLED_MODES] = {
10 0x04, 0x14, 0x24, 0x38,
12 0x04, 0x14, 0x24, 0x38,
14 0x0c, 0x24, 0x48, 0x90,
17 // TODO: maybe convert this to bitmask to simplify pwmled_needs_adc() ?
18 static unsigned char pwmled_state[N_PWMLEDS];
24 static unsigned char pwmled_mode[N_PWMLEDS];
25 static unsigned char pwmled_mode_set[N_PWMLEDS];
27 static uint16_t pwm_probes[N_PWMLEDS];
29 static void start_probing(unsigned char n)
31 pwmled_state[n] = ST_PROBING;
40 for (i = 0; i < N_PWMLEDS*N_PWMLED_MODES; i++) {
43 pwmled_mode_set[i] = 0;
46 for (i = 0; i < N_PWMLEDS; i++) {
51 unsigned char pwmled_needs_adc(unsigned char n)
53 unsigned char st = pwmled_state[n];
54 if (st == ST_PROBING || st == ST_ON)
60 unsigned char pwmled_enabled(unsigned char n)
62 unsigned char st = pwmled_state[n];
63 if (st == ST_OFF || st == ST_ON)
69 void pwmled_set_mode(unsigned char n, unsigned char mode)
71 if (!pwmled_enabled(n))
82 pwmled_state[n] = ST_OFF;
86 if (mode <= N_PWMLED_MODES) {
89 pwmval = pwm_vals[n*N_PWMLED_MODES+mode];
94 pwmled_state[n] = ST_ON;
95 pwmled_mode[n] = mode;
96 pwmled_mode_set[n] = 1;
100 static void inline probing_adc(unsigned char n, uint16_t adcval)
102 unsigned char need_bigger = 0, i;
103 uint16_t *pwm_p = &pwm_vals[n*N_PWMLED_MODES];
104 uint16_t *adc_p = &adc_vals[n*N_PWMLED_MODES];
105 uint16_t pwm = pwm_probes[n];
113 if (adcval > adc_max[n] // Too high
114 || (pwm == 0 && adcval > 0) // non-zero voltage with zero PWM
117 pwmled_state[n] = ST_DISABLED;
124 for (i = 0; i < N_PWMLED_MODES; i++, pwm_p++, adc_p++) {
125 uint16_t adc = *adc_p;
133 if ((n == 1 && pwm > 0x35) || adcval != 0) {
141 if (!need_bigger) { // successfully probed
144 pwmled_state[n] = ST_OFF;
151 if (pwm >= pwm_max[n]) { // over the maximum!
153 pwmled_state[n] = ST_DISABLED;
167 static void inline on_adc(unsigned char n, uint16_t adcval)
169 unsigned char mode = pwmled_mode[n];
170 uint16_t adc_exp = adc_vals[n*N_PWMLED_MODES+mode];
171 uint16_t *pwm_p = &pwm_vals[n*N_PWMLED_MODES+mode];
172 uint16_t old_pwm = *pwm_p;
173 uint16_t new_pwm = old_pwm;
181 if (pwmled_mode_set[n]) { // ignore the first reading
182 pwmled_mode_set[n] = 0;
186 // FIXME: running average?
187 if (2*adcval > 5*adc_exp) { // >2.5x expected, lower significantly
188 new_pwm = 2*old_pwm/3;
189 } else if (3*adcval > 4*adc_exp) { // >1.33x expected, lower a bit
190 new_pwm = old_pwm - 1;
191 } else if (4*adcval < 3*adc_exp) { // 0.75x expected, raise a bit
192 new_pwm = old_pwm + 1;
195 // FIXME: better disconnect detection
196 if (new_pwm > pwm_max[n]) { // FIXME: disconnected?
197 new_pwm = pwm_max[n];
199 if (new_pwm < 2) { // short-circuit?
203 if (new_pwm != old_pwm) {
213 void pwmled_adc(unsigned char n, uint16_t adcval)
215 unsigned char i, probing;
216 switch (pwmled_state[n]) {
218 probing_adc(n, adcval);
222 for (i = 0; i < N_PWMLEDS; i++)
223 if (pwmled_state[i] == ST_PROBING)
227 for (i = 0; i < N_PWMLEDS; i++)
228 log_byte(pwmled_state[i]);
230 for (i = 0; i < N_PWMLEDS*N_PWMLED_MODES; i++)
231 log_word(pwm_vals[i]);
241 // WTF am I doing in this function then? Maybe recently switched off?