adc_avr.c

Go to the documentation of this file.
00001 
00015 #include "adc_avr.h"
00016 
00017 #include <drv/adc.h>
00018 #include <appconfig.h>
00019 
00020 #include <cfg/macros.h>
00021 #include <cfg/compiler.h>
00022 
00023 #include <avr/io.h>
00024 #include <avr/interrupt.h>
00025 
00026 #define ADC_AVR_AREF   0
00027 #define ADC_AVR_AVCC   1
00028 #define ADC_AVR_INT256 2
00029 
00030 #if CONFIG_KERNEL
00031     #include <cfg/module.h>
00032     #include <config_kern.h>
00033     #include <kern/proc.h>
00034     #include <kern/signal.h>
00035 
00036 
00037     #if !CONFIG_KERN_SIGNALS
00038         #error Signals must be active to use ADC with kernel
00039     #endif
00040 
00041     /* Signal adc convertion end */
00042     #define SIG_ADC_COMPLETE SIG_SINGLE
00043 
00044     /* ADC waiting process */
00045     static struct Process *adc_process;
00046 
00051     ISR(ADC_vect)
00052     {
00053         sig_signal(adc_process, SIG_ADC_COMPLETE);
00054     }
00055 #endif /* CONFIG_KERNEL */
00056 
00061 INLINE void adc_hw_select_ch(uint8_t ch)
00062 {
00063     /* Set to 0 all mux registers */
00064     ADMUX &= ~(BV(MUX3) | BV(MUX3) | BV(MUX2) | BV(MUX1) | BV(MUX0));
00065 
00066     /* Select channel, only first 8 channel modes are supported for now */
00067     ADMUX |= (ch & 0x07);
00068 }
00069 
00070 
00076 INLINE uint16_t adc_hw_read(void)
00077 {
00078     // Ensure another convertion is not running.
00079     ASSERT(!(ADCSRA & BV(ADSC)));
00080 
00081     // Start convertion
00082     ADCSRA |= BV(ADSC);
00083 
00084     #if CONFIG_KERNEL
00085         // Ensure IRQs enabled.
00086         ASSERT(IRQ_ENABLED());
00087         adc_process = proc_current();
00088         sig_wait(SIG_ADC_COMPLETE);
00089     #else
00090         //Wait in polling until is done
00091         while (ADCSRA & BV(ADSC)) ;
00092     #endif
00093 
00094     return(ADC);
00095 }
00096 
00100 INLINE void adc_hw_init(void)
00101 {
00102     /*
00103      * Select channel 0 as default,
00104      * result right adjusted.
00105      */
00106     ADMUX = 0;
00107 
00108     #if CONFIG_ADC_AVR_REF == ADC_AVR_AREF
00109         /* External voltage at AREF as analog ref source */
00110         /* None */
00111     #elif CONFIG_ADC_AVR_REF == ADC_AVR_AVCC
00112         /* AVCC as analog ref source */
00113         ADMUX |= BV(REFS0);
00114     #elif CONFIG_ADC_AVR_REF == ADC_AVR_INT256
00115         /* Internal 2.56V as ref source */
00116         ADMUX |= BV(REFS1) | BV(REFS0);
00117     #else
00118         #error Unsupported ADC ref value.
00119     #endif
00120 
00121     /* Disable Auto trigger source: ADC in Free running mode. */
00122     ADCSRB = 0;
00123     
00124     /* Enable ADC, disable autotrigger mode. */
00125     ADCSRA = BV(ADEN);
00126 
00127     #if CONFIG_KERNEL
00128         MOD_CHECK(proc);
00129         ADCSRA |= BV(ADIE);
00130     #endif
00131 
00132     /* Set convertion frequency */
00133     #if CONFIG_ADC_AVR_DIVISOR == 2
00134         ADCSRA |= BV(ADPS0);
00135     #elif CONFIG_ADC_AVR_DIVISOR == 4
00136         ADCSRA |= BV(ADPS1);
00137     #elif CONFIG_ADC_AVR_DIVISOR == 8
00138         ADCSRA |= BV(ADPS1) | BV(ADPS0);
00139     #elif CONFIG_ADC_AVR_DIVISOR == 16
00140         ADCSRA |= BV(ADPS2);
00141     #elif CONFIG_ADC_AVR_DIVISOR == 32
00142         ADCSRA |= BV(ADPS2) | BV(ADPS0);
00143     #elif CONFIG_ADC_AVR_DIVISOR == 64
00144         ADCSRA |= BV(ADPS2) | BV(ADPS1);
00145     #elif CONFIG_ADC_AVR_DIVISOR == 128
00146         ADCSRA |= BV(ADPS2) | BV(ADPS1) | BV(ADPS0);
00147     #else
00148         #error Unsupported ADC prescaler value.
00149     #endif
00150 
00151     /* Start a convertion to init ADC hw */
00152     adc_hw_read();
00153 }