5 static uint16_t target;
6 static uint16_t pwm_val;
7 static int16_t err_sum;
8 static unsigned char state;
9 unsigned char mode_changed;
11 #define SENSE_MOHM 3000 /* 1 Ohm */
13 * Voltage in uV at ADC reading == 1 is 1100/gain/1024
14 * ADC module returns sum of 1 << PWMLED_ADC_SHIFT measurements
15 * Voltage in uV measured is current in mA * sense resistance in mOhm
17 #define MA_TO_ADC(ma) ((uint16_t) \
20 * (1 << (PWMLED_ADC_SHIFT)) \
24 static uint16_t adc_max = MA_TO_ADC(30);
26 static uint16_t targets[N_PWMLED_MODES] = {
36 // The above are constructed so that the following work:
37 #define ST_IS_ON(s) ((s) & 0x02)
38 #define ST_CAN_SET_MODE(s) ((s) & 0x01)
48 void pwmled_set_target(unsigned char mode)
50 target = targets[mode];
54 void pwmled_on_off(unsigned char mode)
56 if (!ST_CAN_SET_MODE(state))
71 static inline void pwmled_err()
79 set_error(ERR_PWMLED);
83 void pwmled_adc(uint16_t adcval)
91 // skip the first reading after mode change
92 if (state == ST_ON && mode_changed) {
97 if (adcval > adc_max) {
104 sum = ((int32_t)pwm_val << shift)
105 + err_sum + target - adcval;
110 pwm_val = sum >> shift;
111 sum -= pwm_val << shift;
114 if (pwm_val >= PWM_MAX
115 || (pwm_val > (2*PWM_MAX/3) && adcval < 0x08)) {