From: Jan "Yenya" Kasprzak Date: Wed, 1 May 2013 13:25:26 +0000 (+0200) Subject: Merge branch 'master' of ssh://anxur.fi.muni.cz/~kas/html/git/tinyboard X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?p=tinyboard.git;a=commitdiff_plain;h=37d45fd92b03b610195d7d6227140672ccc17b2b;hp=3079ccda1c6d82058c801bf8192c616230a2ef93 Merge branch 'master' of ssh://anxur.fi.muni.cz/~kas/html/git/tinyboard --- diff --git a/projects/step-up/Makefile b/projects/step-up/Makefile index a0c7739..5c5af30 100644 --- a/projects/step-up/Makefile +++ b/projects/step-up/Makefile @@ -1,6 +1,6 @@ PROGRAM=lights -SRC=main.c logging.c pwm.c adc.c pwmled.c +SRC=main.c logging.c pwm.c adc.c pwmled.c pattern.c OBJ=$(SRC:.c=.o) diff --git a/projects/step-up/adc.c b/projects/step-up/adc.c index daf7bfe..fc4c7ca 100644 --- a/projects/step-up/adc.c +++ b/projects/step-up/adc.c @@ -5,32 +5,13 @@ #include "lights.h" -#define BATTERY_ADC (N_PWMLEDS + 0) -#define BUTTON_ADC (N_PWMLEDS + 1) -#define ZERO_ADC (N_PWMLEDS + 2) +#define ZERO_ADC 1 //#define NUM_ADCS ZERO_ADC #define NUM_ADCS 1 -struct { - unsigned char read_zero_log : 2; - unsigned char read_drop_log : 2; - unsigned char read_keep_log : 4; -} adc_params[NUM_ADCS] = { - { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 1 -#if 0 - { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 2 - { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 3 - { 0, 1, AMBIENT_ADC_SHIFT }, // ambient - { 0, 1, 0 }, // battery - { 0, 1, 0 }, // gain20 - { 0, 1, 0 }, // buttons -#endif -}; - volatile static unsigned char current_adc, current_slow_adc; -static uint16_t adc_sum, zero_count, drop_count, read_count, n_reads_log; - +static uint16_t adc_sum, read_zero, drop_count, read_count, n_reads_log; static void setup_mux(unsigned char n) { @@ -73,23 +54,14 @@ void start_next_adc() #endif adc_sum = 0; - // we use the last iteration of zero_count to set up the MUX - // to its final destination, hence the "1 +" below: - if (adc_params[current_adc].read_zero_log) - zero_count = 1 + (1 << (adc_params[current_adc].read_zero_log-1)); - else - zero_count = 1; + read_zero = 0; + drop_count = 1; - if (adc_params[current_adc].read_drop_log) - drop_count = 1 << (adc_params[current_adc].read_drop_log - 1); - else - drop_count = 0; - - read_count = 1 << adc_params[current_adc].read_keep_log; - n_reads_log = adc_params[current_adc].read_keep_log; + read_count = 1 << PWMLED_ADC_SHIFT; + n_reads_log = PWMLED_ADC_SHIFT; // set up mux, start one-shot conversion - if (zero_count > 1) + if (read_zero) setup_mux(ZERO_ADC); else setup_mux(current_adc); @@ -97,6 +69,7 @@ void start_next_adc() ADCSRA |= _BV(ADSC); } +#if 0 void timer_start_slow_adcs() { if (current_slow_adc > N_PWMLEDS) { // Don't start if in progress @@ -106,6 +79,7 @@ void timer_start_slow_adcs() // TODO: kick the watchdog here } } +#endif /* * Single synchronous ADC conversion. @@ -129,7 +103,6 @@ static uint16_t read_adc_sync() void init_adc() { - unsigned char i; current_slow_adc = NUM_ADCS; current_adc = 0; @@ -171,19 +144,26 @@ static void adc1_gain20_adc(uint16_t adcsum) } #endif +static void inline adc_based_timer() +{ + static uint16_t pattern_counter; + + if (++pattern_counter > 250) { + pattern_counter = 0; + patterns_next_tick(); + } +} + ISR(ADC_vect) { // IRQ handler uint16_t adcval = ADCW; - if (zero_count) { - if (zero_count > 1) { - ADCSRA |= _BV(ADSC); - zero_count--; - return; - } else { - setup_mux(current_adc); - zero_count = 0; - /* fall through */ - } + adc_based_timer(); + + if (read_zero) { + setup_mux(current_adc); + read_zero = 0; + ADCSRA |= _BV(ADSC); // drop this one, start the next + return; } if (drop_count) { @@ -193,7 +173,7 @@ ISR(ADC_vect) { // IRQ handler } if (read_count) { - ADCSRA |= _BV(ADSC); + ADCSRA |= _BV(ADSC); // immediately start the next conversion adc_sum += adcval; read_count--; return; @@ -206,7 +186,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..d409d9d 100644 --- a/projects/step-up/lights.h +++ b/projects/step-up/lights.h @@ -3,8 +3,6 @@ #define TESTING_FW 1 -#define N_LEDS 7 -#define N_PWMLEDS 2 #define N_PWMLED_MODES 4 #define N_BUTTONS 2 @@ -44,8 +42,9 @@ 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_target(unsigned char mode); +void pwmled_on_off(unsigned char on); /* gpio.c */ void init_gpio(); diff --git a/projects/step-up/pattern.c b/projects/step-up/pattern.c index 55b64cc..693df1d 100644 --- a/projects/step-up/pattern.c +++ b/projects/step-up/pattern.c @@ -3,29 +3,10 @@ #include "lights.h" +#define N_LEDS 1 static unsigned char led_counters[N_LEDS]; static pattern_t *led_patterns[N_LEDS]; -static pattern_t boot_pattern[] = { - { 1, 0x6 }, - { 0, 0x6 }, - { 1, 0x3 }, - { 0, 0x3 }, - { 1, 0x2 }, - { 0, 0x2 }, - { 1, 0x1 }, - { 0, 0x1 }, - { 1, 0x1 }, - { 0, 0x1 }, - { 1, 0x1 }, - { 0, 0x1 }, - { 1, 0x1 }, - { 0, 0x1 }, - { 1, 0x10 }, - { 0, 0x10 }, - PATTERN_END -}; - static pattern_t pattern_num[] = { { 0, 0x5 }, { 1, 0x1 }, /* 10 */ @@ -81,12 +62,20 @@ pattern_t off_pattern[] = { PATTERN_END }; +pattern_t on1_pattern[] = { + { 1, 1 }, + { 0, 2 }, + { 1, 1 }, + { 0, 8 }, + { 1, 1 }, + { 0, 8 }, + PATTERN_END +}; + static void led_set_mode(unsigned char n, unsigned char mode) { - if (n < N_PWMLEDS) { - pwmled_set_mode(n, mode); - } else if (n < N_LEDS) { - gpio_set(n - N_PWMLEDS, mode); + if (n == 0) { + pwmled_on_off(mode); } } @@ -107,8 +96,6 @@ void init_pattern() for (i = 0; i < N_LEDS; i++) led_set_pattern(i, NULL); - - led_set_pattern(N_PWMLEDS+1, boot_pattern); } pattern_t *number_pattern(unsigned char num, unsigned char inv) @@ -129,13 +116,21 @@ pattern_t *number_pattern(unsigned char num, unsigned char inv) static pattern_t *pattern_select(unsigned char n) { + static unsigned char count; + static unsigned char mode; switch(n) { - case 0: return pwmled0_pattern_select(); - case 1: return pwmled1_pattern_select(); - case 2: return pwmled2_pattern_select(); - case 3: return status_led_pattern_select(); - case 4: return illumination_led_pattern_select(); - case 6: return laser_pattern_select(); + case 0: + if (++count > 2) { + count = 0; + if (mode == 0) { + mode = 3; + } else { + mode = 0; + } + + pwmled_set_target(mode); + } + return number_pattern(mode ? 2 : 3, 0); default: return NULL; } } @@ -154,14 +149,10 @@ static void inline pattern_finished(unsigned char n) led_patterns[n] = NULL; - if (n < N_PWMLEDS) { - for (i = 0; i < N_PWMLEDS; i++) - if (led_patterns[i]) - return; - - /* all pwmleds finished; restart them */ - for (i = 0; i < N_PWMLEDS; i++) - led_set_pattern(i, pattern_select(i)); + if (n == 0) { + led_set_pattern(0, pattern_select(0)); + } +#if 0 } else if (n == 3) { if (!led_patterns[4]) led_set_pattern(4, pattern_select(4)); @@ -171,6 +162,7 @@ static void inline pattern_finished(unsigned char n) } else { led_set_pattern(n, pattern_select(n)); } +#endif } void patterns_next_tick() diff --git a/projects/step-up/pwmled.c b/projects/step-up/pwmled.c index 5299330..24fbe87 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,80 @@ 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_target(unsigned char mode) { - pwmled_t *led = pwmleds + n; - - if (!ST_CAN_SET_MODE(led->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(); - } + target = targets[mode]; + mode_changed = 1; } -#define PWMLED_PROBE_STEADY_COUNT 10 - -static inline unsigned char pwmled_probed_ok(unsigned char n, uint16_t old_pwm) +void pwmled_on_off(unsigned char mode) { - 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]; + if (!ST_CAN_SET_MODE(state)) + return; - return 0; + if (mode) { + 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); }