diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ac65ee..b180a10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ set(SOURCE_FILES lib/nsdelay.h lib/spi.c lib/spi.h + lib/adc.c + lib/adc.h lib/usart.c lib/usart.h ) diff --git a/Makefile b/Makefile index 72cc337..b79c0ff 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,7 @@ OBJS = $(BINARY).o OBJS += lib/usart.o OBJS += lib/iopins.o OBJS += lib/spi.o +OBJS += lib/adc.o # Dirs with header files INCL_DIRS = . lib/ diff --git a/lib/adc.c b/lib/adc.c new file mode 100644 index 0000000..d2b1da7 --- /dev/null +++ b/lib/adc.c @@ -0,0 +1,49 @@ +#include +#include + +#include "calc.h" +#include "adc.h" + +/** Initialize the ADC */ +void adc_init(enum ADC_Prescaller presc) +{ + ADCSRA |= presc; // 128 prescaler -> 125 kHz + ADMUX |= _BV(REFS0); // Voltage reference + sbi(ADCSRA, ADEN); // Enable ADC +} + +/** Disable ADC */ +void adc_disable(void) +{ + cbi(ADCSRA, ADEN); +} + +/** Enable ADC */ +void adc_enable(void) +{ + sbi(ADCSRA, ADEN); +} + +static void adc_convert(uint8_t channel) +{ + set_low_nibble(ADMUX, channel); // Select channel to sample + sbi(ADMUX, ADLAR); // Align result to left + sbi(ADCSRA, ADSC); // Start conversion + + while (bit_is_high(ADCSRA, ADSC)); // Wait for it... +} + +/** Sample analog pin with 8-bit precision */ +uint8_t adc_read_byte(uint8_t channel) +{ + adc_convert(channel); + return ADCH; // The upper 8 bits of ADC result +} + + +/** Sample analog pin with 10-bit precision */ +uint16_t adc_read_word(uint8_t channel) +{ + adc_convert(channel); + return ADCW; // The whole ADC word (10 bits) +} diff --git a/lib/adc.h b/lib/adc.h new file mode 100644 index 0000000..f879b8a --- /dev/null +++ b/lib/adc.h @@ -0,0 +1,32 @@ +#pragma once + +// +// Utilities for build-in A/D converter +// + +#include + +enum ADC_Prescaller { + ADC_PRESC_2 = 1, + ADC_PRESC_4 = 2, + ADC_PRESC_8 = 3, + ADC_PRESC_16 = 4, + ADC_PRESC_32 = 5, + ADC_PRESC_64 = 6, + ADC_PRESC_128 = 7, +}; + +/** Initialize the ADC and enable it */ +void adc_init(enum ADC_Prescaller presc); + +/** Disable ADC (for power saving) */ +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); + +/** Sample analog pin with 10-bit precision */ +uint16_t adc_read_word(uint8_t channel);