From: Jan "Yenya" Kasprzak Date: Mon, 29 Apr 2013 15:58:46 +0000 (+0200) Subject: pwmled.c: only one pwmled X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?p=tinyboard.git;a=commitdiff_plain;h=e207868d62200cd821bc1a1893913fbafe1efc77 pwmled.c: only one pwmled --- diff --git a/projects/step-up/adc.c b/projects/step-up/adc.c index f06cbc5..6309c41 100644 --- a/projects/step-up/adc.c +++ b/projects/step-up/adc.c @@ -202,7 +202,7 @@ ISR(ADC_vect) { // IRQ handler switch (current_adc) { case 0: // pwmled_adc(current_adc, adc_sum); - pwmled_adc(1, adc_sum); + pwmled_adc(adc_sum); break; } diff --git a/projects/step-up/lights.h b/projects/step-up/lights.h index e47aa96..f63b6f9 100644 --- a/projects/step-up/lights.h +++ b/projects/step-up/lights.h @@ -44,8 +44,8 @@ void susp_tmr(); /* pwmled.c */ void init_pwmled(); -void pwmled_adc(unsigned char n, uint16_t adcval); -void pwmled_set_mode(unsigned char n, unsigned char mode); +void pwmled_adc(uint16_t adcval); +void pwmled_set_mode(unsigned char mode); /* gpio.c */ void init_gpio(); diff --git a/projects/step-up/pwmled.c b/projects/step-up/pwmled.c index 5299330..b066c59 100644 --- a/projects/step-up/pwmled.c +++ b/projects/step-up/pwmled.c @@ -2,18 +2,11 @@ #include "lights.h" -typedef struct { - uint16_t target, pwm; - int16_t err_sum; - unsigned char mode, state; - union { - unsigned char probe_steady, mode_changed; - }; - uint16_t mode_pwm[N_PWMLED_MODES]; - int16_t err_sums[N_PWMLED_MODES]; -} pwmled_t; - -pwmled_t pwmleds[N_PWMLEDS]; +static uint16_t target; +static uint16_t pwm_val; +static int16_t err_sum; +static unsigned char state; +unsigned char mode_changed; #define SENSE_MOHM 3000 /* 1 Ohm */ /* @@ -21,29 +14,20 @@ pwmled_t pwmleds[N_PWMLEDS]; * ADC module returns sum of 1 << PWMLED_ADC_SHIFT measurements * Voltage in uV measured is current in mA * sense resistance in mOhm */ -#define MA_GAIN_TO_ADC(ma, gain) ((uint16_t) \ +#define MA_TO_ADC(ma) ((uint16_t) \ ((uint32_t)(ma) \ * (SENSE_MOHM) \ * (1 << (PWMLED_ADC_SHIFT)) \ * 1024 \ - / (1100000/(gain)))) + / 1100000)) -static uint16_t adc_max[N_PWMLEDS] = { - MA_GAIN_TO_ADC( 30, 1), - MA_GAIN_TO_ADC( 30, 1), -}; +static uint16_t adc_max = MA_TO_ADC(30); -static uint16_t adc_vals[N_PWMLEDS*N_PWMLED_MODES] = { - /* pwmled0 */ - MA_GAIN_TO_ADC( 2, 1), - MA_GAIN_TO_ADC( 5, 1), - MA_GAIN_TO_ADC( 10, 1), - MA_GAIN_TO_ADC( 20, 1), - /* pwmled1 */ - MA_GAIN_TO_ADC( 2, 1), - MA_GAIN_TO_ADC( 8, 1), - MA_GAIN_TO_ADC( 14, 1), - MA_GAIN_TO_ADC( 20, 1), +static uint16_t targets[N_PWMLED_MODES] = { + MA_TO_ADC( 2), + MA_TO_ADC( 8), + MA_TO_ADC(14), + MA_TO_ADC(20), }; #define ST_DISABLED 0 @@ -56,159 +40,75 @@ static uint16_t adc_vals[N_PWMLEDS*N_PWMLED_MODES] = { void init_pwmled() { - unsigned char i, j; - - for (i = 0; i < N_PWMLEDS; i++) { - pwmled_t *led = pwmleds + i; - led->err_sum = 0; - led->target = adc_vals[i*N_PWMLED_MODES]; - led->pwm = 0; - led->mode = 1; - led->state = ST_PROBING; - led->probe_steady = 0; - - for (j = 0; j < N_PWMLED_MODES; j++) { - led->mode_pwm[j] = 0; - led->err_sums[j] = 0; - } - } - pwmleds[0].state = ST_DISABLED; + pwm_val = 0; + err_sum = 0; + target = targets[0]; + state = ST_OFF; } -void pwmled_set_mode(unsigned char n, unsigned char mode) +void pwmled_set_mode(unsigned char mode) { - pwmled_t *led = pwmleds + n; - - if (!ST_CAN_SET_MODE(led->state)) + if (!ST_CAN_SET_MODE(state)) return; - if (led->mode) { // save the previous state - led->mode_pwm[led->mode - 1] = led->pwm; - led->err_sums[led->mode - 1] = led->err_sum; - } - - led->mode = mode; - - if (mode > 0 && mode <= N_PWMLED_MODES) { - led->target = adc_vals[n*N_PWMLED_MODES + mode - 1]; - led->state = ST_ON; - led->pwm = led->mode_pwm[mode - 1]; - led->err_sum = led->err_sums[mode - 1]; - led->mode_changed = 1; - pwm_set(led->pwm); - } else { - led->state = ST_OFF; - pwm_off(); - } -} - -#define PWMLED_PROBE_STEADY_COUNT 10 - -static inline unsigned char pwmled_probed_ok(unsigned char n, uint16_t old_pwm) -{ - pwmled_t *led = pwmleds + n; - - if (led->pwm == old_pwm) { - if (led->probe_steady < PWMLED_PROBE_STEADY_COUNT) - led->probe_steady++; - } else { - led->probe_steady = 0; - } - - if (led->probe_steady < PWMLED_PROBE_STEADY_COUNT - && old_pwm <= led->pwm) - return 0; - - // probed OK - led->mode_pwm[led->mode - 1] = led->pwm; - led->err_sums[led->mode - 1] = 0; - - // next mode to probe? - if (led->mode < N_PWMLED_MODES) { - led->probe_steady = 0; - led->err_sum = 0; - - led->mode++; - led->target = adc_vals[n*N_PWMLED_MODES+led->mode-1]; - - return 0; + if (mode) { + target = targets[mode - 1]; + state = ST_ON; + mode_changed = 1; + pwm_set(pwm_val); } else { - unsigned char i; - - led->state = ST_OFF; + state = ST_OFF; pwm_off(); - - log_byte(0xF0); - log_byte(n); - // log_word(jiffies); - - for (i = 0; i < N_PWMLED_MODES; i++) - log_word(led->mode_pwm[i]); - - log_flush(); - - // pattern_reload(); - // pwmled_set_mode(n, 2); - - return 1; } } -static inline void pwmled_err(unsigned char n) +static inline void pwmled_err() { - pwmleds[n].state = ST_DISABLED; + state = ST_DISABLED; pwm_off(); log_byte(0xF1); - log_byte(n); - // log_word(jiffies); log_flush(); } -void pwmled_adc(unsigned char n, uint16_t adcval) +void pwmled_adc(uint16_t adcval) { - pwmled_t *led = pwmleds + n; - uint16_t old_pwm; int32_t sum; unsigned char shift; - if (!ST_IS_ON(led->state)) + if (!ST_IS_ON(state)) return; - if (led->state == ST_ON && led->mode_changed) { - led->mode_changed--; + // skip the first reading after mode change + if (state == ST_ON && mode_changed) { + mode_changed--; return; } - // FIXME: test for maximum adcval value (adc_max[n]) - old_pwm = led->pwm; + if (adcval > adc_max) { + pwmled_err(); + return; + } - shift = led->state == ST_PROBING ? 3 : 8; + shift = 5; - sum = ((int32_t)led->pwm << shift) - + led->err_sum + led->target - adcval; + sum = ((int32_t)pwm_val << shift) + + err_sum + target - adcval; if (sum < 0) sum = 0; - led->pwm = sum >> shift; - sum -= led->pwm << shift; - led->err_sum = sum; + pwm_val = sum >> shift; + sum -= pwm_val << shift; + err_sum = sum; - if (led->pwm >= PWM_MAX - || (led->pwm > (2*PWM_MAX/3) && adcval < 0x08)) { - pwmled_err(n); + if (pwm_val >= PWM_MAX + || (pwm_val > (2*PWM_MAX/3) && adcval < 0x08)) { + pwmled_err(); return; } - if (led->state == ST_PROBING) - if (pwmled_probed_ok(n, old_pwm)) - return; - - if (led->pwm == old_pwm) - return; - - pwm_set(led->pwm); + pwm_set(pwm_val); }