]> www.fi.muni.cz Git - bike-lights.git/commitdiff
adc: measure gain stage offset _slowly_
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Fri, 30 Nov 2012 01:12:05 +0000 (02:12 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Fri, 30 Nov 2012 01:12:05 +0000 (02:12 +0100)
use running sum of 1<<6 measurements, and do only one measurement
per loop in order to not disturb other measurements. Also, do not log
timer overruns for ADC, as we do most of the processing in ADC IRQs now.

firmware/adc.c

index ba30e5ca632c01e8064323d460ce3324fa7dc23a..fa0782c4248c6ee67917901cc1340dedfefea087 100644 (file)
@@ -12,7 +12,8 @@ volatile static unsigned char current_adc;
 static uint16_t adc_sum;
 static unsigned char sum_shift;
 static unsigned char adc_vals;
-static uint16_t adc1_gain20_offset_x16;
+#define ADC1_GAIN20_OFFSET_SHIFT       6
+static uint16_t adc1_gain20_offset;
 
 static void inline setup_mux(unsigned char n)
 {
@@ -28,7 +29,7 @@ static void inline setup_mux(unsigned char n)
                break;
        case 2: // pwmled 3: 1.1V, ADC4 (PA5), single-ended
                ADMUX = _BV(REFS1) | _BV(MUX2);
-               sum_shift = 2; // 4 measurements
+               sum_shift = 3; // 8 measurements
                break;
        case 3: // ambient light: 1.1V, ADC5 (PA6), single-ended
                ADMUX = _BV(REFS1) | _BV(MUX2) | _BV(MUX0);
@@ -40,7 +41,7 @@ static void inline setup_mux(unsigned char n)
                break;
        case 5: // gain stage offset: 1.1V, ADC1,1, gain 20
                ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX0);
-               sum_shift = 3; // 8 measurements
+               sum_shift = 0; // 1 measurement
                break;
        }
 
@@ -85,14 +86,15 @@ void init_adc()
                ;
        ADCSRA |= _BV(ADIF); // clear the IRQ flag
 
-       adc1_gain20_offset_x16 = 0;
+       adc1_gain20_offset = 0;
 
-       for (i = 0; i < 16; i++) {
+       for (i = 0; i < (1 << ADC1_GAIN20_OFFSET_SHIFT); i++) {
                ADCSRA |= _BV(ADSC);
 
                while ((ADCSRA & _BV(ADIF)) == 0)
                        ;
-               adc1_gain20_offset_x16 += ADCW;
+               adc1_gain20_offset += ADCW
+                       - (adc1_gain20_offset >> ADC1_GAIN20_OFFSET_SHIFT);
 
                ADCSRA |= _BV(ADIF); // clear the IRQ flag
        }
@@ -128,18 +130,19 @@ ISR(ADC_vect) { // IRQ handler
 
        if (current_adc == ADC1_GAIN20) {
                // running average
-               adc1_gain20_offset_x16 += adcval
-                       - (adc1_gain20_offset_x16 >> 4);
+               adc1_gain20_offset += adcval
+                       - (adc1_gain20_offset >> ADC1_GAIN20_OFFSET_SHIFT);
        } else if (current_adc == 0 || current_adc == 1) {
-               uint16_t offset = adc1_gain20_offset_x16 >> 4;
-               if (adcval >= offset)
-                       adcval -= offset;
+               uint16_t offset = adc1_gain20_offset
+                       >> (ADC1_GAIN20_OFFSET_SHIFT - sum_shift);
+               if (adc_sum > offset)
+                       adc_sum -= offset;
                else
-                       adcval = 0;
+                       adc_sum = 0;
        }
 
        if (current_adc < N_PWMLEDS)
-               pwmled_adc(current_adc, adcval);
+               pwmled_adc(current_adc, adc_sum);
        if (current_adc == AMBIENT_ADC)
                ambient_adc(adcval);
        if (current_adc == BATTERY_ADC)
@@ -152,7 +155,9 @@ void timer_start_adcs()
 {
        if (current_adc == NUM_ADCS) // Don't start if in progress
                start_next_adc();
+#if 0
        else
                log_byte(0x99);
+#endif
 }