]> www.fi.muni.cz Git - bike-lights.git/blob - pwmled.c
log reset count immediately
[bike-lights.git] / pwmled.c
1 #include <avr/io.h>
2
3 #include "lights.h"
4
5 static unsigned char pwm_vals[N_PWMLEDS*N_PWMLED_MODES];
6 static unsigned char adc_vals[N_PWMLEDS*N_PWMLED_MODES] = {
7         /* pwmled0 */
8         0x04, 0x14, 0x24, 0x38,
9         /* pwmled1 */
10         0x04, 0x14, 0x24, 0x38,
11         /* pwmled2 */
12         0x04, 0x14, 0x24, 0x38,
13 };
14
15 static unsigned char pwmled_state[N_PWMLEDS];
16 #define ST_DISABLED 0
17 #define ST_PROBING  1
18 #define ST_OFF      2
19 #define ST_ON       3
20
21 static unsigned char pwmled_mode[N_PWMLEDS];
22
23 static unsigned char pwm_probes[N_PWMLEDS];
24
25 static void start_probing(unsigned char n)
26 {
27         pwmled_state[n] = ST_PROBING;
28         pwm_set(n, 0);
29         pwm_on(n);
30         pwm_probes[n] = 0;
31 }
32
33 void pwmled_init()
34 {
35         unsigned char i;
36
37         for (i = 0; i < N_PWMLEDS*N_PWMLED_MODES; i++)
38                 pwm_vals[i] = 0;
39
40         for (i = 0; i < N_PWMLEDS; i++) {
41                 start_probing(i);
42         }
43 }
44
45 unsigned char pwmled_is_on(unsigned char n)
46 {
47         unsigned char st = pwmled_state[n];
48         if (st == ST_PROBING || st == ST_ON)
49                 return 1;
50         else
51                 return 0;
52 }
53
54 static void inline probing_adc(unsigned char n, uint16_t adcval)
55 {
56         unsigned char need_bigger = 0, i;
57         unsigned char *pwm_p = &pwm_vals[n*N_PWMLED_MODES];
58         unsigned char *adc_p = &adc_vals[n*N_PWMLED_MODES];
59         unsigned char pwm = pwm_probes[n];
60
61 #if 0
62         log_byte(0xF4);
63         log_byte(n);
64         log_word(adcval);
65 #endif
66
67 #if 0
68         if (pwm == 0 && adcval > 0) { // non-zero voltage with zero PWM?
69                 pwmled_state[n] = ST_DISABLED;
70                 log_byte(n);
71                 log_byte(0xF0);
72                 log_word(adcval);
73                 return;
74         }
75 #endif
76
77         for (i = 0; i < N_PWMLED_MODES; i++, pwm_p++, adc_p++) {
78                 uint16_t adc = *adc_p;
79                 if (adc >= adcval) {
80                         *pwm_p = pwm;
81                         need_bigger = 1;
82                 }
83         }
84
85 #if 0
86         if ((n == 1 && pwm > 0x35) || adcval != 0) {
87                 log_byte(n);
88                 log_byte(0xF3);
89                 log_byte(pwm);
90                 log_word(adcval);
91         }
92 #endif
93
94         if (!need_bigger) { // successfully probed
95                 pwm_off(n);
96                 // pwm_set(n, 0);
97                 pwmled_state[n] = ST_OFF;
98                 log_byte(0xF1);
99                 log_byte(n);
100
101                 return;
102         }
103
104         if (pwm >= 0x70) { // over the maximum!
105                 pwm_off(n);
106                 pwmled_state[n] = ST_DISABLED;
107                 log_byte(0xF2);
108                 log_byte(n);
109                 // pwm_set(n, 0);
110                 return;
111         }
112
113         // try to increase
114         pwm++;
115         pwm_probes[n] = pwm;
116         pwm_set(n, pwm);
117 }
118
119 // Feedback loop
120 static void inline on_adc(unsigned char n, uint16_t adcval)
121 {
122 #if 0
123         uint16_t new_pwm = led_modes[led_mode].pwmval;
124         uint16_t old_pwm = new_pwm;
125         uint16_t adc_exp = led_modes[led_mode].expected;
126
127         log_word(((adcval & 0xFF) << 8) | old_pwm);
128
129         if (2*adcval > 5*adc_exp) { // >2.5x expected, lower significantly
130                 new_pwm = 2*old_pwm/3;
131         } else if (3*adcval > 4*adc_exp) { // >1.33x expected, lower a bit
132                 new_pwm = old_pwm - 1;
133         } else if (4*adcval < 3*adc_exp) { // 0.75x expected, raise a bit
134                 new_pwm = old_pwm + 1;
135         }
136
137         if (new_pwm > 0x60) { // odpojeno?
138                 new_pwm = 0x60;
139         }
140         if (new_pwm < 2) { // zkrat?
141                 new_pwm = 2;
142         }
143
144 set_pwm:
145         if (new_pwm != old_pwm) {
146                 led_modes[led_mode].pwmval = new_pwm;
147                 OCR1D = new_pwm;
148         }
149         // ADCSRA |= _BV(ADSC);
150 #endif
151 }
152
153 void pwmled_adc(unsigned char n, uint16_t adcval)
154 {
155         unsigned char i, probing;
156         switch (pwmled_state[n]) {
157         case ST_PROBING:
158                 probing_adc(n, adcval);
159
160                 probing = 0;
161                 for (i = 0; i < N_PWMLEDS; i++)
162                         if (pwmled_state[i] == ST_PROBING)
163                                 probing = 1;
164
165                 if (!probing) {
166                         for (i = 0; i < N_PWMLEDS; i++)
167                                 log_byte(pwmled_state[i]);
168                                 
169                         for (i = 0; i < N_PWMLEDS*N_PWMLED_MODES; i++)
170                                 log_byte(pwm_vals[i]);
171                         log_flush();
172                 }
173                 
174                 return;
175         case ST_ON:
176                 on_adc(n, adcval);
177                 return;
178         // WTF am I doing in this function then?
179         }
180 }