Loading projects/step-up/adc.c +25 −70 Original line number Original line Diff line number Diff line #include <avr/io.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include "lights.h" #include "lights.h" #define AMBIENT_ADC N_PWMLEDS #define BATTERY_ADC (N_PWMLEDS + 0) #define BATTERY_ADC (N_PWMLEDS + 1) #define BUTTON_ADC (N_PWMLEDS + 1) #define ADC1_GAIN20 (N_PWMLEDS + 2) #define ZERO_ADC (N_PWMLEDS + 2) #define BUTTON_ADC (N_PWMLEDS + 3) #define ZERO_ADC (N_PWMLEDS + 4) #define NUM_ADCS ZERO_ADC //#define NUM_ADCS ZERO_ADC #define NUM_ADCS 1 struct { struct { unsigned char read_zero_log : 2; unsigned char read_zero_log : 2; Loading @@ -17,54 +17,36 @@ struct { unsigned char read_keep_log : 4; unsigned char read_keep_log : 4; } adc_params[NUM_ADCS] = { } adc_params[NUM_ADCS] = { { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 1 { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 1 #if 0 { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 2 { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 2 { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 3 { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 3 { 0, 1, AMBIENT_ADC_SHIFT }, // ambient { 0, 1, AMBIENT_ADC_SHIFT }, // ambient { 0, 1, 0 }, // battery { 0, 1, 0 }, // battery { 0, 1, 0 }, // gain20 { 0, 1, 0 }, // gain20 { 0, 1, 0 }, // buttons { 0, 1, 0 }, // buttons #endif }; }; volatile static unsigned char current_adc, current_slow_adc; 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, zero_count, drop_count, read_count, n_reads_log; #define ADC1_GAIN20_OFFSET_SHIFT 6 static uint16_t adc1_gain20_offset; static void setup_mux(unsigned char n) static void setup_mux(unsigned char n) { { /* ADC numbering: PWM LEDs first, then others, zero at the end */ /* ADC numbering: PWM LEDs first, then others, zero at the end */ switch (n) { switch (n) { case 0: // pwmled 1: 1.1V, ADC0,1 (PA0,1), gain 20 case 0: // pwmled 1: 1.1V, ADC3 (PB3), single-ended ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX1) | _BV(MUX0); break; case 1: // pwmled 2: 1.1V, ADC2,1 (PA2,1), gain 20 ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); break; case 2: // pwmled 3: 1.1V, ADC4 (PA5), single-ended ADMUX = _BV(REFS1) | _BV(MUX2); break; case AMBIENT_ADC: // ambient light: 1.1V, ADC5 (PA6), single-ended ADMUX = _BV(REFS1) | _BV(MUX2) | _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); ADMUX = _BV(REFS1) | _BV(MUX1) | _BV(MUX0); break; break; case ZERO_ADC: // zero: 1.1V, ADC1 (PA1), single-ended case ZERO_ADC: // zero: 1.1V, GND, single-ended ADMUX = _BV(REFS1) | _BV(MUX0); ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX0); break; break; } } } } static void start_next_adc() void start_next_adc() { { #if 0 if (current_adc == 0) { if (current_adc == 0) { if (current_slow_adc > N_PWMLEDS) { if (current_slow_adc > N_PWMLEDS) { // read one of the non-PWMLED ADCs // read one of the non-PWMLED ADCs Loading @@ -80,6 +62,10 @@ static void start_next_adc() // next PWMLED // next PWMLED current_adc--; current_adc--; } } #else // single ADC for testing only current_adc = 0; #endif #if 0 #if 0 log_byte(0x90 + current_adc); // debug ADC switching log_byte(0x90 + current_adc); // debug ADC switching Loading Loading @@ -153,27 +139,20 @@ void init_adc() // ADCSRB |= _BV(GSEL); // gain 8 or 32 // ADCSRB |= _BV(GSEL); // gain 8 or 32 // Disable digital input on all bits used by ADC // Disable digital input on all bits used by ADC DIDR0 = _BV(ADC0D) | _BV(ADC1D) | _BV(ADC2D) | _BV(ADC3D) DIDR0 = _BV(ADC3D) | _BV(ADC2D); | _BV(ADC4D) | _BV(ADC5D) | _BV(ADC6D); // 1.1V, ADC1,1, gain 20 // 1.1V, GND ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX0); ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX0); /* Do first conversion and drop the result */ /* Do first conversion and drop the result */ read_adc_sync(); read_adc_sync(); adc1_gain20_offset = 0; for (i = 0; i < (1 << ADC1_GAIN20_OFFSET_SHIFT); i++) { adc1_gain20_offset += read_adc_sync() - (adc1_gain20_offset >> ADC1_GAIN20_OFFSET_SHIFT); } ADCSRA |= _BV(ADIE); // enable IRQ ADCSRA |= _BV(ADIE); // enable IRQ start_next_adc(); start_next_adc(); } } #if 0 void susp_adc() void susp_adc() { { ADCSRA = 0; ADCSRA = 0; Loading @@ -186,6 +165,7 @@ static void adc1_gain20_adc(uint16_t adcsum) adc1_gain20_offset += adcsum adc1_gain20_offset += adcsum - (adc1_gain20_offset >> ADC1_GAIN20_OFFSET_SHIFT); - (adc1_gain20_offset >> ADC1_GAIN20_OFFSET_SHIFT); } } #endif ISR(ADC_vect) { // IRQ handler ISR(ADC_vect) { // IRQ handler uint16_t adcval = ADCW; uint16_t adcval = ADCW; Loading Loading @@ -219,38 +199,13 @@ ISR(ADC_vect) { // IRQ handler * Now we have performed read_count measurements and have them * Now we have performed read_count measurements and have them * in adc_sum. * in adc_sum. */ */ // For inputs with gain, subtract the measured gain stage offset if (current_adc < 2) { uint16_t offset = adc1_gain20_offset >> (ADC1_GAIN20_OFFSET_SHIFT - n_reads_log); if (adc_sum > offset) adc_sum -= offset; else adc_sum = 0; } switch (current_adc) { switch (current_adc) { case 0: case 0: case 1: // pwmled_adc(current_adc, adc_sum); case 2: log_word(0x9000+adc_sum); pwmled_adc(current_adc, adc_sum); return; break; 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 ADC1_GAIN20: adc1_gain20_adc(adcval); break; break; } } start_next_adc(); start_next_adc(); } } Loading
projects/step-up/adc.c +25 −70 Original line number Original line Diff line number Diff line #include <avr/io.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include "lights.h" #include "lights.h" #define AMBIENT_ADC N_PWMLEDS #define BATTERY_ADC (N_PWMLEDS + 0) #define BATTERY_ADC (N_PWMLEDS + 1) #define BUTTON_ADC (N_PWMLEDS + 1) #define ADC1_GAIN20 (N_PWMLEDS + 2) #define ZERO_ADC (N_PWMLEDS + 2) #define BUTTON_ADC (N_PWMLEDS + 3) #define ZERO_ADC (N_PWMLEDS + 4) #define NUM_ADCS ZERO_ADC //#define NUM_ADCS ZERO_ADC #define NUM_ADCS 1 struct { struct { unsigned char read_zero_log : 2; unsigned char read_zero_log : 2; Loading @@ -17,54 +17,36 @@ struct { unsigned char read_keep_log : 4; unsigned char read_keep_log : 4; } adc_params[NUM_ADCS] = { } adc_params[NUM_ADCS] = { { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 1 { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 1 #if 0 { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 2 { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 2 { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 3 { 0, 1, PWMLED_ADC_SHIFT }, // pwmled 3 { 0, 1, AMBIENT_ADC_SHIFT }, // ambient { 0, 1, AMBIENT_ADC_SHIFT }, // ambient { 0, 1, 0 }, // battery { 0, 1, 0 }, // battery { 0, 1, 0 }, // gain20 { 0, 1, 0 }, // gain20 { 0, 1, 0 }, // buttons { 0, 1, 0 }, // buttons #endif }; }; volatile static unsigned char current_adc, current_slow_adc; 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, zero_count, drop_count, read_count, n_reads_log; #define ADC1_GAIN20_OFFSET_SHIFT 6 static uint16_t adc1_gain20_offset; static void setup_mux(unsigned char n) static void setup_mux(unsigned char n) { { /* ADC numbering: PWM LEDs first, then others, zero at the end */ /* ADC numbering: PWM LEDs first, then others, zero at the end */ switch (n) { switch (n) { case 0: // pwmled 1: 1.1V, ADC0,1 (PA0,1), gain 20 case 0: // pwmled 1: 1.1V, ADC3 (PB3), single-ended ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX1) | _BV(MUX0); break; case 1: // pwmled 2: 1.1V, ADC2,1 (PA2,1), gain 20 ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); break; case 2: // pwmled 3: 1.1V, ADC4 (PA5), single-ended ADMUX = _BV(REFS1) | _BV(MUX2); break; case AMBIENT_ADC: // ambient light: 1.1V, ADC5 (PA6), single-ended ADMUX = _BV(REFS1) | _BV(MUX2) | _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); ADMUX = _BV(REFS1) | _BV(MUX1) | _BV(MUX0); break; break; case ZERO_ADC: // zero: 1.1V, ADC1 (PA1), single-ended case ZERO_ADC: // zero: 1.1V, GND, single-ended ADMUX = _BV(REFS1) | _BV(MUX0); ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX0); break; break; } } } } static void start_next_adc() void start_next_adc() { { #if 0 if (current_adc == 0) { if (current_adc == 0) { if (current_slow_adc > N_PWMLEDS) { if (current_slow_adc > N_PWMLEDS) { // read one of the non-PWMLED ADCs // read one of the non-PWMLED ADCs Loading @@ -80,6 +62,10 @@ static void start_next_adc() // next PWMLED // next PWMLED current_adc--; current_adc--; } } #else // single ADC for testing only current_adc = 0; #endif #if 0 #if 0 log_byte(0x90 + current_adc); // debug ADC switching log_byte(0x90 + current_adc); // debug ADC switching Loading Loading @@ -153,27 +139,20 @@ void init_adc() // ADCSRB |= _BV(GSEL); // gain 8 or 32 // ADCSRB |= _BV(GSEL); // gain 8 or 32 // Disable digital input on all bits used by ADC // Disable digital input on all bits used by ADC DIDR0 = _BV(ADC0D) | _BV(ADC1D) | _BV(ADC2D) | _BV(ADC3D) DIDR0 = _BV(ADC3D) | _BV(ADC2D); | _BV(ADC4D) | _BV(ADC5D) | _BV(ADC6D); // 1.1V, ADC1,1, gain 20 // 1.1V, GND ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX0); ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX0); /* Do first conversion and drop the result */ /* Do first conversion and drop the result */ read_adc_sync(); read_adc_sync(); adc1_gain20_offset = 0; for (i = 0; i < (1 << ADC1_GAIN20_OFFSET_SHIFT); i++) { adc1_gain20_offset += read_adc_sync() - (adc1_gain20_offset >> ADC1_GAIN20_OFFSET_SHIFT); } ADCSRA |= _BV(ADIE); // enable IRQ ADCSRA |= _BV(ADIE); // enable IRQ start_next_adc(); start_next_adc(); } } #if 0 void susp_adc() void susp_adc() { { ADCSRA = 0; ADCSRA = 0; Loading @@ -186,6 +165,7 @@ static void adc1_gain20_adc(uint16_t adcsum) adc1_gain20_offset += adcsum adc1_gain20_offset += adcsum - (adc1_gain20_offset >> ADC1_GAIN20_OFFSET_SHIFT); - (adc1_gain20_offset >> ADC1_GAIN20_OFFSET_SHIFT); } } #endif ISR(ADC_vect) { // IRQ handler ISR(ADC_vect) { // IRQ handler uint16_t adcval = ADCW; uint16_t adcval = ADCW; Loading Loading @@ -219,38 +199,13 @@ ISR(ADC_vect) { // IRQ handler * Now we have performed read_count measurements and have them * Now we have performed read_count measurements and have them * in adc_sum. * in adc_sum. */ */ // For inputs with gain, subtract the measured gain stage offset if (current_adc < 2) { uint16_t offset = adc1_gain20_offset >> (ADC1_GAIN20_OFFSET_SHIFT - n_reads_log); if (adc_sum > offset) adc_sum -= offset; else adc_sum = 0; } switch (current_adc) { switch (current_adc) { case 0: case 0: case 1: // pwmled_adc(current_adc, adc_sum); case 2: log_word(0x9000+adc_sum); pwmled_adc(current_adc, adc_sum); return; break; 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 ADC1_GAIN20: adc1_gain20_adc(adcval); break; break; } } start_next_adc(); start_next_adc(); } }