Loading projects/step-up/adc.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -202,7 +202,7 @@ ISR(ADC_vect) { // IRQ handler switch (current_adc) { switch (current_adc) { case 0: case 0: // pwmled_adc(current_adc, adc_sum); // pwmled_adc(current_adc, adc_sum); pwmled_adc(1, adc_sum); pwmled_adc(adc_sum); break; break; } } Loading projects/step-up/lights.h +2 −2 Original line number Original line Diff line number Diff line Loading @@ -44,8 +44,8 @@ void susp_tmr(); /* pwmled.c */ /* pwmled.c */ void init_pwmled(); void init_pwmled(); void pwmled_adc(unsigned char n, uint16_t adcval); void pwmled_adc(uint16_t adcval); void pwmled_set_mode(unsigned char n, unsigned char mode); void pwmled_set_mode(unsigned char mode); /* gpio.c */ /* gpio.c */ void init_gpio(); void init_gpio(); Loading projects/step-up/pwmled.c +46 −146 Original line number Original line Diff line number Diff line Loading @@ -2,18 +2,11 @@ #include "lights.h" #include "lights.h" typedef struct { static uint16_t target; uint16_t target, pwm; static uint16_t pwm_val; int16_t err_sum; static int16_t err_sum; unsigned char mode, state; static unsigned char state; union { unsigned char mode_changed; 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]; #define SENSE_MOHM 3000 /* 1 Ohm */ #define SENSE_MOHM 3000 /* 1 Ohm */ /* /* Loading @@ -21,29 +14,20 @@ pwmled_t pwmleds[N_PWMLEDS]; * ADC module returns sum of 1 << PWMLED_ADC_SHIFT measurements * ADC module returns sum of 1 << PWMLED_ADC_SHIFT measurements * Voltage in uV measured is current in mA * sense resistance in mOhm * 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) \ ((uint32_t)(ma) \ * (SENSE_MOHM) \ * (SENSE_MOHM) \ * (1 << (PWMLED_ADC_SHIFT)) \ * (1 << (PWMLED_ADC_SHIFT)) \ * 1024 \ * 1024 \ / (1100000/(gain)))) / 1100000)) static uint16_t adc_max[N_PWMLEDS] = { static uint16_t adc_max = MA_TO_ADC(30); MA_GAIN_TO_ADC( 30, 1), MA_GAIN_TO_ADC( 30, 1), }; static uint16_t adc_vals[N_PWMLEDS*N_PWMLED_MODES] = { static uint16_t targets[N_PWMLED_MODES] = { /* pwmled0 */ MA_TO_ADC( 2), MA_GAIN_TO_ADC( 2, 1), MA_TO_ADC( 8), MA_GAIN_TO_ADC( 5, 1), MA_TO_ADC(14), MA_GAIN_TO_ADC( 10, 1), MA_TO_ADC(20), 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), }; }; #define ST_DISABLED 0 #define ST_DISABLED 0 Loading @@ -56,159 +40,75 @@ static uint16_t adc_vals[N_PWMLEDS*N_PWMLED_MODES] = { void init_pwmled() void init_pwmled() { { unsigned char i, j; pwm_val = 0; err_sum = 0; for (i = 0; i < N_PWMLEDS; i++) { target = targets[0]; pwmled_t *led = pwmleds + i; state = ST_OFF; 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; } } 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(state)) if (!ST_CAN_SET_MODE(led->state)) return; return; if (led->mode) { // save the previous state if (mode) { led->mode_pwm[led->mode - 1] = led->pwm; target = targets[mode - 1]; led->err_sums[led->mode - 1] = led->err_sum; state = ST_ON; } mode_changed = 1; pwm_set(pwm_val); 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 { } else { led->state = ST_OFF; state = ST_OFF; pwm_off(); pwm_off(); } } } } #define PWMLED_PROBE_STEADY_COUNT 10 static inline void pwmled_err() static inline unsigned char pwmled_probed_ok(unsigned char n, uint16_t old_pwm) { { pwmled_t *led = pwmleds + n; state = ST_DISABLED; 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; } else { unsigned char i; led->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) { pwmleds[n].state = ST_DISABLED; pwm_off(); pwm_off(); log_byte(0xF1); log_byte(0xF1); log_byte(n); // log_word(jiffies); log_flush(); 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; int32_t sum; unsigned char shift; unsigned char shift; if (!ST_IS_ON(led->state)) if (!ST_IS_ON(state)) return; return; if (led->state == ST_ON && led->mode_changed) { // skip the first reading after mode change led->mode_changed--; if (state == ST_ON && mode_changed) { mode_changed--; return; 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) sum = ((int32_t)pwm_val << shift) + led->err_sum + led->target - adcval; + err_sum + target - adcval; if (sum < 0) if (sum < 0) sum = 0; sum = 0; led->pwm = sum >> shift; pwm_val = sum >> shift; sum -= led->pwm << shift; sum -= pwm_val << shift; led->err_sum = sum; err_sum = sum; if (led->pwm >= PWM_MAX if (pwm_val >= PWM_MAX || (led->pwm > (2*PWM_MAX/3) && adcval < 0x08)) { || (pwm_val > (2*PWM_MAX/3) && adcval < 0x08)) { pwmled_err(n); pwmled_err(); return; return; } } if (led->state == ST_PROBING) pwm_set(pwm_val); if (pwmled_probed_ok(n, old_pwm)) return; if (led->pwm == old_pwm) return; pwm_set(led->pwm); } } Loading
projects/step-up/adc.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -202,7 +202,7 @@ ISR(ADC_vect) { // IRQ handler switch (current_adc) { switch (current_adc) { case 0: case 0: // pwmled_adc(current_adc, adc_sum); // pwmled_adc(current_adc, adc_sum); pwmled_adc(1, adc_sum); pwmled_adc(adc_sum); break; break; } } Loading
projects/step-up/lights.h +2 −2 Original line number Original line Diff line number Diff line Loading @@ -44,8 +44,8 @@ void susp_tmr(); /* pwmled.c */ /* pwmled.c */ void init_pwmled(); void init_pwmled(); void pwmled_adc(unsigned char n, uint16_t adcval); void pwmled_adc(uint16_t adcval); void pwmled_set_mode(unsigned char n, unsigned char mode); void pwmled_set_mode(unsigned char mode); /* gpio.c */ /* gpio.c */ void init_gpio(); void init_gpio(); Loading
projects/step-up/pwmled.c +46 −146 Original line number Original line Diff line number Diff line Loading @@ -2,18 +2,11 @@ #include "lights.h" #include "lights.h" typedef struct { static uint16_t target; uint16_t target, pwm; static uint16_t pwm_val; int16_t err_sum; static int16_t err_sum; unsigned char mode, state; static unsigned char state; union { unsigned char mode_changed; 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]; #define SENSE_MOHM 3000 /* 1 Ohm */ #define SENSE_MOHM 3000 /* 1 Ohm */ /* /* Loading @@ -21,29 +14,20 @@ pwmled_t pwmleds[N_PWMLEDS]; * ADC module returns sum of 1 << PWMLED_ADC_SHIFT measurements * ADC module returns sum of 1 << PWMLED_ADC_SHIFT measurements * Voltage in uV measured is current in mA * sense resistance in mOhm * 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) \ ((uint32_t)(ma) \ * (SENSE_MOHM) \ * (SENSE_MOHM) \ * (1 << (PWMLED_ADC_SHIFT)) \ * (1 << (PWMLED_ADC_SHIFT)) \ * 1024 \ * 1024 \ / (1100000/(gain)))) / 1100000)) static uint16_t adc_max[N_PWMLEDS] = { static uint16_t adc_max = MA_TO_ADC(30); MA_GAIN_TO_ADC( 30, 1), MA_GAIN_TO_ADC( 30, 1), }; static uint16_t adc_vals[N_PWMLEDS*N_PWMLED_MODES] = { static uint16_t targets[N_PWMLED_MODES] = { /* pwmled0 */ MA_TO_ADC( 2), MA_GAIN_TO_ADC( 2, 1), MA_TO_ADC( 8), MA_GAIN_TO_ADC( 5, 1), MA_TO_ADC(14), MA_GAIN_TO_ADC( 10, 1), MA_TO_ADC(20), 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), }; }; #define ST_DISABLED 0 #define ST_DISABLED 0 Loading @@ -56,159 +40,75 @@ static uint16_t adc_vals[N_PWMLEDS*N_PWMLED_MODES] = { void init_pwmled() void init_pwmled() { { unsigned char i, j; pwm_val = 0; err_sum = 0; for (i = 0; i < N_PWMLEDS; i++) { target = targets[0]; pwmled_t *led = pwmleds + i; state = ST_OFF; 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; } } 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(state)) if (!ST_CAN_SET_MODE(led->state)) return; return; if (led->mode) { // save the previous state if (mode) { led->mode_pwm[led->mode - 1] = led->pwm; target = targets[mode - 1]; led->err_sums[led->mode - 1] = led->err_sum; state = ST_ON; } mode_changed = 1; pwm_set(pwm_val); 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 { } else { led->state = ST_OFF; state = ST_OFF; pwm_off(); pwm_off(); } } } } #define PWMLED_PROBE_STEADY_COUNT 10 static inline void pwmled_err() static inline unsigned char pwmled_probed_ok(unsigned char n, uint16_t old_pwm) { { pwmled_t *led = pwmleds + n; state = ST_DISABLED; 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; } else { unsigned char i; led->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) { pwmleds[n].state = ST_DISABLED; pwm_off(); pwm_off(); log_byte(0xF1); log_byte(0xF1); log_byte(n); // log_word(jiffies); log_flush(); 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; int32_t sum; unsigned char shift; unsigned char shift; if (!ST_IS_ON(led->state)) if (!ST_IS_ON(state)) return; return; if (led->state == ST_ON && led->mode_changed) { // skip the first reading after mode change led->mode_changed--; if (state == ST_ON && mode_changed) { mode_changed--; return; 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) sum = ((int32_t)pwm_val << shift) + led->err_sum + led->target - adcval; + err_sum + target - adcval; if (sum < 0) if (sum < 0) sum = 0; sum = 0; led->pwm = sum >> shift; pwm_val = sum >> shift; sum -= led->pwm << shift; sum -= pwm_val << shift; led->err_sum = sum; err_sum = sum; if (led->pwm >= PWM_MAX if (pwm_val >= PWM_MAX || (led->pwm > (2*PWM_MAX/3) && adcval < 0x08)) { || (pwm_val > (2*PWM_MAX/3) && adcval < 0x08)) { pwmled_err(n); pwmled_err(); return; return; } } if (led->state == ST_PROBING) pwm_set(pwm_val); if (pwmled_probed_ok(n, old_pwm)) return; if (led->pwm == old_pwm) return; pwm_set(led->pwm); } }