8 unsigned char mode, state, probe_steady;
9 uint16_t mode_pwm[N_PWMLED_MODES];
10 int16_t err_sums[N_PWMLED_MODES];
13 pwmled_t pwmleds[N_PWMLEDS];
15 #define PWMLED2_TESTING_WITH_350MA_LED
17 #define SENSE_MOHM 33 /* 0.033 Ohm */
18 #define MA_MOHM_GAIN_TO_ADC(ma, mohm, gain) (\
19 ((unsigned long)(ma))*(mohm) /* voltage at sensing resistor in uV */ \
20 /(1100000UL/gain/1024UL) /* voltage of ADC reading == 1 */ \
23 static uint16_t adc_max[N_PWMLEDS] = {
24 MA_MOHM_GAIN_TO_ADC( 400, SENSE_MOHM, 20),
25 MA_MOHM_GAIN_TO_ADC( 30, SENSE_MOHM, 20),
26 #ifdef PWMLED2_TESTING_WITH_350MA_LED
27 MA_MOHM_GAIN_TO_ADC( 400, SENSE_MOHM, 1)
29 MA_MOHM_GAIN_TO_ADC(2500, SENSE_MOHM, 1)
33 static uint16_t adc_vals[N_PWMLEDS*N_PWMLED_MODES] = {
35 MA_MOHM_GAIN_TO_ADC( 20, SENSE_MOHM, 20),
36 MA_MOHM_GAIN_TO_ADC( 50, SENSE_MOHM, 20),
37 MA_MOHM_GAIN_TO_ADC( 100, SENSE_MOHM, 20),
38 MA_MOHM_GAIN_TO_ADC( 350, SENSE_MOHM, 20),
42 MA_MOHM_GAIN_TO_ADC( 5, SENSE_MOHM, 20),
43 MA_MOHM_GAIN_TO_ADC( 12, SENSE_MOHM, 20),
44 MA_MOHM_GAIN_TO_ADC( 16, SENSE_MOHM, 20),
45 MA_MOHM_GAIN_TO_ADC( 20, SENSE_MOHM, 20),
50 #ifdef PWMLED2_TESTING_WITH_350MA_LED
51 MA_MOHM_GAIN_TO_ADC( 100, SENSE_MOHM, 1),
52 MA_MOHM_GAIN_TO_ADC( 140, SENSE_MOHM, 1),
53 MA_MOHM_GAIN_TO_ADC( 250, SENSE_MOHM, 1),
54 MA_MOHM_GAIN_TO_ADC( 350, SENSE_MOHM, 1),
56 MA_MOHM_GAIN_TO_ADC( 150, SENSE_MOHM, 1),
57 MA_MOHM_GAIN_TO_ADC( 350, SENSE_MOHM, 1),
58 MA_MOHM_GAIN_TO_ADC( 700, SENSE_MOHM, 1),
59 MA_MOHM_GAIN_TO_ADC(2400, SENSE_MOHM, 1),
68 // The above are constructed so that the following work:
69 #define ST_IS_ON(s) ((s) & 0x02)
70 #define ST_CAN_SET_MODE(s) ((s) & 0x01)
76 for (i = 0; i < N_PWMLEDS; i++) {
77 pwmled_t *led = pwmleds + i;
79 led->target = adc_vals[i*N_PWMLED_MODES];
82 led->state = ST_PROBING;
83 led->probe_steady = 0;
85 for (j = 0; j < N_PWMLED_MODES; j++) {
92 void pwmled_set_mode(unsigned char n, unsigned char mode)
94 pwmled_t *led = pwmleds + n;
96 if (!ST_CAN_SET_MODE(led->state))
99 if (led->mode) { // save the previous state
100 led->mode_pwm[led->mode - 1] = led->pwm;
101 led->err_sums[led->mode - 1] = led->err_sum;
106 if (mode > 0 && mode <= N_PWMLED_MODES) {
107 led->target = adc_vals[n*N_PWMLED_MODES + mode - 1];
109 led->pwm = led->mode_pwm[mode - 1];
110 led->err_sum = led->err_sums[mode - 1];
111 pwm_set(n, led->pwm);
118 #define PWMLED_PROBE_STEADY_COUNT 10
120 static inline unsigned char pwmled_probed_ok(unsigned char n, uint16_t old_pwm)
122 pwmled_t *led = pwmleds + n;
124 if (led->pwm == old_pwm) {
125 if (led->probe_steady < PWMLED_PROBE_STEADY_COUNT)
128 led->probe_steady = 0;
131 if (led->probe_steady < PWMLED_PROBE_STEADY_COUNT
132 && old_pwm <= led->pwm)
136 led->mode_pwm[led->mode - 1] = led->pwm;
137 led->err_sums[led->mode - 1] = 0;
139 // next mode to probe?
140 if (led->mode < N_PWMLED_MODES) {
141 led->probe_steady = 0;
145 led->target = adc_vals[n*N_PWMLED_MODES+led->mode-1];
158 for (i = 0; i < N_PWMLED_MODES; i++)
159 log_word(led->mode_pwm[i]);
169 static inline void pwmled_err(unsigned char n)
171 pwmleds[n].state = ST_DISABLED;
181 void pwmled_adc(unsigned char n, uint16_t adcval)
183 pwmled_t *led = pwmleds + n;
188 if (!ST_IS_ON(led->state))
191 // FIXME: test for maximum adcval value (adc_max[n])
195 shift = led->state == ST_PROBING ? 3 : 5;
197 sum = ((int32_t)led->pwm << shift)
198 + led->err_sum + led->target - adcval;
203 led->pwm = sum >> shift;
204 sum -= led->pwm << shift;
207 if (led->pwm > (PWM_MAX << PWM_STEP_SHIFT)-5) {
212 if (led->state == ST_PROBING)
213 if (pwmled_probed_ok(n, old_pwm))
216 if (led->pwm == old_pwm)
219 pwm_set(n, led->pwm);