X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?p=bike-lights.git;a=blobdiff_plain;f=firmware%2Fadc.c;h=9ed80f2d216b069412a2a12a53444c048d8a57eb;hp=02af6b380724ae6f92ccca9407d1e1951a75c53f;hb=15758319e9901ada7e67a7c0c3288e53d803f059;hpb=4c6ff89995f620aadb6cd8ef9403adac8ef48478 diff --git a/firmware/adc.c b/firmware/adc.c index 02af6b3..9ed80f2 100644 --- a/firmware/adc.c +++ b/firmware/adc.c @@ -3,11 +3,14 @@ #include "lights.h" -#define AMBIENT_ADC N_PWMLEDS -#define BATTERY_ADC (N_PWMLEDS + 1) -#define ADC1_GAIN20 (N_PWMLEDS + 2) -#define BUTTON_ADC (N_PWMLEDS + 3) -#define ZERO_ADC (N_PWMLEDS + 4) +// pwmleds are measured continuously (when active) +#define AMBIENT_ADC N_PWMLEDS // measured every jiffy (16 Hz) +#define BUTTON_ADC (N_PWMLEDS + 1) // measured every jiffy (16 Hz) +#define FIRST_16HZ_ADC BUTTON_ADC +#define BATTERY_ADC (N_PWMLEDS + 2) // once per second +#define ADC1_GAIN20 (N_PWMLEDS + 3) // once per second +#define FIRST_1S_ADC ADC1_GAIN20 +#define ZERO_ADC (N_PWMLEDS + 4) // must be last #define NUM_ADCS ZERO_ADC @@ -19,13 +22,15 @@ struct { { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 1 { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 2 { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 3 - { 0, 1, 3 }, // ambient + { 0, 1, AMBIENT_ADC_SHIFT }, // ambient + { 0, 1, 0 }, // buttons { 0, 1, 0 }, // battery { 0, 1, 0 }, // gain20 - { 0, 1, 0 }, // buttons }; -volatile static unsigned char current_adc; +volatile unsigned char adc_is_on; + +volatile static unsigned char current_adc, slow_adcs_wanted; static uint16_t adc_sum, zero_count, drop_count, read_count, n_reads_log; #define ADC1_GAIN20_OFFSET_SHIFT 6 static uint16_t adc1_gain20_offset; @@ -47,16 +52,16 @@ static void setup_mux(unsigned char n) case AMBIENT_ADC: // ambient light: 1.1V, ADC5 (PA6), single-ended ADMUX = _BV(REFS1) | _BV(MUX2) | _BV(MUX0); break; + case BUTTON_ADC: // buttons: 1.1V, ADC3, single-ended + PORTA |= _BV(PA3); // +5V to the voltage splitter + ADMUX = _BV(REFS1) | _BV(MUX1) | _BV(MUX0); + break; case BATTERY_ADC: // batt voltage: 1.1V, ADC6 (PA7), single-ended ADMUX = _BV(REFS1) | _BV(MUX2) | _BV(MUX1); break; case ADC1_GAIN20: // gain stage offset: 1.1V, ADC1,1, gain 20 ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX0); break; - case BUTTON_ADC: // buttons: 1.1V, ADC3, single-ended - PORTA |= _BV(PA3); // +5V to the voltage splitter - ADMUX = _BV(REFS1) | _BV(MUX1) | _BV(MUX0); - break; case ZERO_ADC: // zero: 1.1V, ADC1 (PA1), single-ended ADMUX = _BV(REFS1) | _BV(MUX0); break; @@ -65,11 +70,30 @@ static void setup_mux(unsigned char n) static void start_next_adc() { - if (current_adc > 0) + if (slow_adcs_wanted) { + current_adc = slow_adcs_wanted; + slow_adcs_wanted = 0; + goto found; + } + + if (current_adc > N_PWMLEDS) { current_adc--; - else - // TODO: kick the watchdog here. - current_adc = NUM_ADCS-1; + goto found; + } + + if (!TIMER1_IS_ON()) { + adc_is_on = 0; + return; + } + + do { + if (!current_adc) + current_adc = N_PWMLEDS; + --current_adc; + } while (!PWM_IS_ON(current_adc)); + +found: + adc_is_on = 1; adc_sum = 0; // we use the last iteration of zero_count to set up the MUX @@ -96,6 +120,19 @@ static void start_next_adc() ADCSRA |= _BV(ADSC); } +void timer_start_slow_adcs() +{ + if ((jiffies & 0x000F) == 0) { + slow_adcs_wanted = FIRST_1S_ADC; + } else { + slow_adcs_wanted = FIRST_16HZ_ADC; + } + + if (!adc_is_on) { + start_next_adc(); + } +} + /* * Single synchronous ADC conversion. * Has to be called with IRQs disabled (or with the ADC IRQ disabled). @@ -119,7 +156,9 @@ static uint16_t read_adc_sync() void init_adc() { unsigned char i; - current_adc = NUM_ADCS; + current_adc = 0; + adc_is_on = 1; + slow_adcs_wanted = FIRST_1S_ADC; ADCSRA = _BV(ADEN) // enable | _BV(ADPS1) | _BV(ADPS0) // CLK/8 = 125 kHz @@ -215,12 +254,12 @@ ISR(ADC_vect) { // IRQ handler case AMBIENT_ADC: ambient_adc(adc_sum); break; - case BATTERY_ADC: - battery_adc(adc_sum); - break; case BUTTON_ADC: button_adc(adc_sum); break; + case BATTERY_ADC: + battery_adc(adc_sum); + break; case ADC1_GAIN20: adc1_gain20_adc(adcval); break;