5 static uint16_t pwm_vals[N_PWMLEDS*N_PWMLED_MODES];
6 static uint16_t pwm_max[N_PWMLEDS] = {
8 PWM_MAX - (PWM_MAX >> 4), // step-up
12 #define PWMLED2_TESTING_WITH_350MA_LED
14 #define SENSE_MOHM 33 /* 0.033 Ohm */
15 #define MA_MOHM_GAIN_TO_ADC(ma, mohm, gain) (\
16 ((unsigned long)(ma))*(mohm) /* voltage at sensing resistor in uV */ \
17 /(1100000UL/gain/1024UL) /* voltage of ADC reading == 1 */ \
19 static uint16_t adc_max[N_PWMLEDS] = {
20 MA_MOHM_GAIN_TO_ADC( 400, SENSE_MOHM, 20),
21 MA_MOHM_GAIN_TO_ADC( 30, SENSE_MOHM, 20),
22 #ifdef PWMLED2_TESTING_WITH_350MA_LED
23 MA_MOHM_GAIN_TO_ADC( 400, SENSE_MOHM, 1)
25 MA_MOHM_GAIN_TO_ADC(2500, SENSE_MOHM, 1)
28 static uint16_t adc_vals[N_PWMLEDS*N_PWMLED_MODES] = {
30 MA_MOHM_GAIN_TO_ADC( 20, SENSE_MOHM, 20),
31 MA_MOHM_GAIN_TO_ADC( 50, SENSE_MOHM, 20),
32 MA_MOHM_GAIN_TO_ADC( 100, SENSE_MOHM, 20),
33 MA_MOHM_GAIN_TO_ADC( 350, SENSE_MOHM, 20),
35 MA_MOHM_GAIN_TO_ADC( 5, SENSE_MOHM, 20),
36 MA_MOHM_GAIN_TO_ADC( 12, SENSE_MOHM, 20),
37 MA_MOHM_GAIN_TO_ADC( 16, SENSE_MOHM, 20),
38 MA_MOHM_GAIN_TO_ADC( 20, SENSE_MOHM, 20),
40 #ifdef PWMLED2_TESTING_WITH_350MA_LED
41 MA_MOHM_GAIN_TO_ADC( 100, SENSE_MOHM, 1),
42 MA_MOHM_GAIN_TO_ADC( 140, SENSE_MOHM, 1),
43 MA_MOHM_GAIN_TO_ADC( 250, SENSE_MOHM, 1),
44 MA_MOHM_GAIN_TO_ADC( 350, SENSE_MOHM, 1),
46 MA_MOHM_GAIN_TO_ADC( 150, SENSE_MOHM, 1),
47 MA_MOHM_GAIN_TO_ADC( 350, SENSE_MOHM, 1),
48 MA_MOHM_GAIN_TO_ADC( 700, SENSE_MOHM, 1),
49 MA_MOHM_GAIN_TO_ADC(2400, SENSE_MOHM, 1),
53 // TODO: maybe convert this to bitmask to simplify pwmled_needs_adc() ?
54 static unsigned char pwmled_state[N_PWMLEDS];
60 static unsigned char pwmled_mode[N_PWMLEDS];
61 static unsigned char pwmled_mode_set[N_PWMLEDS];
63 static uint16_t pwm_probes[N_PWMLEDS];
65 static void start_probing(unsigned char n)
67 pwmled_state[n] = ST_PROBING;
76 for (i = 0; i < N_PWMLEDS*N_PWMLED_MODES; i++) {
79 pwmled_mode_set[i] = 0;
82 for (i = 0; i < N_PWMLEDS; i++) {
87 unsigned char pwmled_needs_adc(unsigned char n)
89 unsigned char st = pwmled_state[n];
90 if (st == ST_PROBING || st == ST_ON)
96 unsigned char pwmled_enabled(unsigned char n)
98 unsigned char st = pwmled_state[n];
99 if (st == ST_OFF || st == ST_ON)
105 void pwmled_set_mode(unsigned char n, unsigned char mode)
107 if (!pwmled_enabled(n))
118 pwmled_state[n] = ST_OFF;
122 if (mode <= N_PWMLED_MODES) {
125 pwmval = pwm_vals[n*N_PWMLED_MODES+mode];
130 pwmled_state[n] = ST_ON;
131 pwmled_mode[n] = mode;
132 pwmled_mode_set[n] = 1;
136 static void inline probing_adc(unsigned char n, uint16_t adcval)
138 unsigned char need_bigger = 0, i;
139 uint16_t *pwm_p = &pwm_vals[n*N_PWMLED_MODES];
140 uint16_t *adc_p = &adc_vals[n*N_PWMLED_MODES];
141 uint16_t pwm = pwm_probes[n];
149 if (adcval > adc_max[n] // Too high
150 || (pwm == 0 && adcval > 0) // non-zero voltage with zero PWM
153 pwmled_state[n] = ST_DISABLED;
160 for (i = 0; i < N_PWMLED_MODES; i++, pwm_p++, adc_p++) {
161 uint16_t adc = *adc_p;
169 if ((n == 1 && pwm > 0x35) || adcval != 0) {
177 if (!need_bigger) { // successfully probed
180 pwmled_state[n] = ST_OFF;
187 if (pwm >= pwm_max[n]) { // over the maximum!
189 pwmled_state[n] = ST_DISABLED;
203 static void inline on_adc(unsigned char n, uint16_t adcval)
205 unsigned char mode = pwmled_mode[n];
206 uint16_t adc_exp = adc_vals[n*N_PWMLED_MODES+mode];
207 uint16_t *pwm_p = &pwm_vals[n*N_PWMLED_MODES+mode];
208 uint16_t old_pwm = *pwm_p;
209 uint16_t new_pwm = old_pwm;
217 if (pwmled_mode_set[n]) { // ignore the first reading
218 pwmled_mode_set[n] = 0;
222 // FIXME: running average?
223 if (2*adcval > 5*adc_exp) { // >2.5x expected, lower significantly
224 new_pwm = 2*old_pwm/3;
225 } else if (3*adcval > 4*adc_exp) { // >1.33x expected, lower a bit
226 new_pwm = old_pwm - 1;
227 } else if (4*adcval < 3*adc_exp) { // 0.75x expected, raise a bit
228 new_pwm = old_pwm + 1;
231 // FIXME: better disconnect detection
232 if (new_pwm > pwm_max[n]) { // FIXME: disconnected?
233 new_pwm = pwm_max[n];
235 if (new_pwm < 2) { // short-circuit?
239 if (new_pwm != old_pwm) {
249 void pwmled_adc(unsigned char n, uint16_t adcval)
251 unsigned char i, probing;
252 switch (pwmled_state[n]) {
254 probing_adc(n, adcval);
258 for (i = 0; i < N_PWMLEDS; i++)
259 if (pwmled_state[i] == ST_PROBING)
263 for (i = 0; i < N_PWMLEDS; i++)
264 log_byte(pwmled_state[i]);
266 for (i = 0; i < N_PWMLEDS*N_PWMLED_MODES; i++)
267 log_word(pwm_vals[i]);
277 // WTF am I doing in this function then? Maybe recently switched off?