diff --git a/lib/adc.c b/lib/adc.c index d2b1da7..8202ff6 100644 --- a/lib/adc.c +++ b/lib/adc.c @@ -1,5 +1,6 @@ #include #include +#include #include "calc.h" #include "adc.h" @@ -8,7 +9,7 @@ void adc_init(enum ADC_Prescaller presc) { ADCSRA |= presc; // 128 prescaler -> 125 kHz - ADMUX |= _BV(REFS0); // Voltage reference + ADMUX |= _BV(REFS0); // Voltage reference sbi(ADCSRA, ADEN); // Enable ADC } @@ -24,26 +25,53 @@ void adc_enable(void) sbi(ADCSRA, ADEN); } -static void adc_convert(uint8_t channel) +/** Start a new conversion */ +void adc_start_conversion(uint8_t channel) { set_low_nibble(ADMUX, channel); // Select channel to sample - sbi(ADMUX, ADLAR); // Align result to left + cbi(ADMUX, ADLAR); // Align result to right sbi(ADCSRA, ADSC); // Start conversion +} + +/** Check if ADC is done converting */ +bool adc_ready(void) +{ + return bit_is_low(ADCSRA, ADSC); +} + +/** Read the result of last conversion with 8bit precision */ +uint8_t adc_read_8bit() +{ + uint8_t low = ADCL; + uint8_t high = ADCH; + return low >> 2 | high << 6; +} - while (bit_is_high(ADCSRA, ADSC)); // Wait for it... +/** Read the result of last conversion with 10bit precision */ +uint16_t adc_read_10bit() +{ + uint8_t low = ADCL; + uint8_t high = ADCH; + return ((uint16_t) high << 8) | low; +} + +/** Start ADC conversion and wait for the result */ +static void adc_convert(uint8_t channel) +{ + adc_start_conversion(channel); + while (!adc_ready()); // Wait for it... } /** Sample analog pin with 8-bit precision */ -uint8_t adc_read_byte(uint8_t channel) +uint8_t adc_convert_8bit(uint8_t channel) { adc_convert(channel); - return ADCH; // The upper 8 bits of ADC result + return adc_read_8bit(); } - /** Sample analog pin with 10-bit precision */ -uint16_t adc_read_word(uint8_t channel) +uint16_t adc_convert_10bit(uint8_t channel) { adc_convert(channel); - return ADCW; // The whole ADC word (10 bits) + return adc_read_10bit(); } diff --git a/lib/adc.h b/lib/adc.h index f879b8a..af93226 100644 --- a/lib/adc.h +++ b/lib/adc.h @@ -25,8 +25,20 @@ void adc_disable(void); /** Enable (already initialized) ADC */ void adc_enable(void); -/** Sample analog pin with 8-bit precision */ -uint8_t adc_read_byte(uint8_t channel); +/** Start a new conversion */ +void adc_start_conversion(uint8_t channel); -/** Sample analog pin with 10-bit precision */ -uint16_t adc_read_word(uint8_t channel); +/** Check if ADC is done converting */ +bool adc_ready(void); + +/** Read the result of last conversion with 8bit precision */ +uint8_t adc_read_8bit(void); + +/** Read the result of last conversion with 10bit precision */ +uint16_t adc_read_10bit(void); + +/** Sample analog pin with 8-bit precision. Blocking! */ +uint8_t adc_convert_8bit(uint8_t channel); + +/** Sample analog pin with 10-bit precision. Blocking! */ +uint16_t adc_convert_10bit(uint8_t channel);