adc_avr.c

Go to the documentation of this file.
00001 
00044 #include "adc_avr.h"
00045 
00046 #include "cfg/cfg_adc.h"
00047 #include "cfg/cfg_proc.h"
00048 #include "cfg/cfg_signal.h"
00049 #include <cfg/macros.h>
00050 #include <cfg/compiler.h>
00051 
00052 #include <cpu/irq.h> // IRQ_ASSERT_ENABLED()
00053 
00054 #include <drv/adc.h>
00055 
00056 #include <avr/io.h>
00057 #include <avr/interrupt.h>
00058 
00065 #define ADC_AVR_AREF   0
00066 #define ADC_AVR_AVCC   1
00067 #define ADC_AVR_INT256 2
00068 /* \} */
00069 
00070 #if CONFIG_KERN
00071     #include <cfg/module.h>
00072     #include <kern/proc.h>
00073     #include <kern/signal.h>
00074 
00075 
00076     #if !CONFIG_KERN_SIGNALS
00077         #error Signals must be active to use the ADC with kernel
00078     #endif
00079 
00080     /* Signal adc convertion end */
00081     #define SIG_ADC_COMPLETE SIG_SINGLE
00082 
00083     /* ADC waiting process */
00084     static struct Process *adc_process;
00085 
00090     ISR(ADC_vect)
00091     {
00092         sig_signal(adc_process, SIG_ADC_COMPLETE);
00093     }
00094 #endif /* CONFIG_KERN */
00095 
00100 void adc_hw_select_ch(uint8_t ch)
00101 {
00102     /* Set to 0 all mux registers */
00103     ADMUX &= ~(BV(MUX4) | BV(MUX3) | BV(MUX2) | BV(MUX1) | BV(MUX0));
00104 
00105     /* Select channel, only first 8 channel modes are supported for now */
00106     ADMUX |= (ch & 0x07);
00107 }
00108 
00109 
00115 uint16_t adc_hw_read(void)
00116 {
00117     // Ensure another convertion is not running.
00118     ASSERT(!(ADCSRA & BV(ADSC)));
00119 
00120     // Start convertion
00121     ADCSRA |= BV(ADSC);
00122 
00123     #if CONFIG_KERN
00124         // Ensure IRQs enabled.
00125         IRQ_ASSERT_ENABLED();
00126         adc_process = proc_current();
00127         sig_wait(SIG_ADC_COMPLETE);
00128     #else
00129         //Wait in polling until is done
00130         while (ADCSRA & BV(ADSC)) ;
00131     #endif
00132 
00133     return(ADC);
00134 }
00135 
00139 void adc_hw_init(void)
00140 {
00141     /*
00142      * Select channel 0 as default,
00143      * result right adjusted.
00144      */
00145     ADMUX = 0;
00146 
00147     #if CONFIG_ADC_AVR_REF == ADC_AVR_AREF
00148         /* External voltage at AREF as analog ref source */
00149         /* None */
00150     #elif CONFIG_ADC_AVR_REF == ADC_AVR_AVCC
00151         /* AVCC as analog ref source */
00152         ADMUX |= BV(REFS0);
00153     #elif CONFIG_ADC_AVR_REF == ADC_AVR_INT256
00154         /* Internal 2.56V as ref source */
00155         ADMUX |= BV(REFS1) | BV(REFS0);
00156     #else
00157         #error Unsupported ADC ref value.
00158     #endif
00159 
00160     #if defined(ADCSRB)
00161     /* Disable Auto trigger source: ADC in Free running mode. */
00162     ADCSRB = 0;
00163     #endif
00164 
00165     /* Enable ADC, disable autotrigger mode. */
00166     ADCSRA = BV(ADEN);
00167 
00168     #if CONFIG_KERN
00169         MOD_CHECK(proc);
00170         ADCSRA |= BV(ADIE);
00171     #endif
00172 
00173     /* Set convertion frequency */
00174     #if CONFIG_ADC_AVR_DIVISOR == 2
00175         ADCSRA |= BV(ADPS0);
00176     #elif CONFIG_ADC_AVR_DIVISOR == 4
00177         ADCSRA |= BV(ADPS1);
00178     #elif CONFIG_ADC_AVR_DIVISOR == 8
00179         ADCSRA |= BV(ADPS1) | BV(ADPS0);
00180     #elif CONFIG_ADC_AVR_DIVISOR == 16
00181         ADCSRA |= BV(ADPS2);
00182     #elif CONFIG_ADC_AVR_DIVISOR == 32
00183         ADCSRA |= BV(ADPS2) | BV(ADPS0);
00184     #elif CONFIG_ADC_AVR_DIVISOR == 64
00185         ADCSRA |= BV(ADPS2) | BV(ADPS1);
00186     #elif CONFIG_ADC_AVR_DIVISOR == 128
00187         ADCSRA |= BV(ADPS2) | BV(ADPS1) | BV(ADPS0);
00188     #else
00189         #error Unsupported ADC prescaler value.
00190     #endif
00191 
00192     /* Start a convertion to init ADC hw */
00193     adc_hw_read();
00194 }