adc_at91.c

Go to the documentation of this file.
00001 
00048 #include "adc_at91.h"
00049 
00050 #include <cpu/irq.h>
00051 
00052 #include "cfg/cfg_adc.h"
00053 #include "cfg/cfg_kern.h"
00054 #include <cfg/macros.h>
00055 #include <cfg/compiler.h>
00056 
00057 // Define log settings for cfg/log.h.
00058 #define LOG_LEVEL         ADC_LOG_LEVEL
00059 #define LOG_FORMAT        ADC_LOG_FORMAT
00060 #include <cfg/log.h>
00061 
00062 #include <drv/adc.h>
00063 
00064 #include <io/arm.h>
00065 
00066 #if CONFIG_KERN
00067     #include <cfg/module.h>
00068     #include <kern/proc.h>
00069     #include <kern/signal.h>
00070 
00071 
00072     #if !CONFIG_KERN_SIGNALS
00073         #error Signals must be active to use ADC with kernel
00074     #endif
00075 
00076     /* Signal adc convertion end */
00077     #define SIG_ADC_COMPLETE SIG_USER0
00078 
00079     /* ADC waiting process */
00080     static struct Process *adc_process;
00081 
00086     static void ISR_FUNC adc_conversion_end_irq(void)
00087     {
00088         sig_signal(adc_process, SIG_ADC_COMPLETE);
00089 
00090         /* Inform hw that we have served the IRQ */
00091         AIC_EOICR = 0;
00092     }
00093 
00094     static void adc_enable_irq(void)
00095     {
00096 
00097         // Disable all interrupt
00098         ADC_IDR = 0xFFFFFFFF;
00099 
00100         //Register interrupt vector
00101         AIC_SVR(ADC_ID) = adc_conversion_end_irq;
00102         AIC_SMR(ADC_ID) = AIC_SRCTYPE_INT_EDGE_TRIGGERED;
00103         AIC_IECR = BV(ADC_ID);
00104 
00105         //Enable data ready irq
00106         ADC_IER = BV(ADC_DRDY);
00107     }
00108 
00109 #endif /* CONFIG_KERN */
00110 
00111 
00116 INLINE void adc_hw_select_ch(uint8_t ch)
00117 {
00118     //Disable all channels
00119     ADC_CHDR = ADC_CH_MASK;
00120     //Enable select channel
00121     ADC_CHER = BV(ch);
00122 }
00123 
00124 
00130 INLINE uint16_t adc_hw_read(void)
00131 {
00132     ASSERT(!(ADC_SR & ADC_EOC_MASK));
00133 
00134     #if CONFIG_KERN
00135         adc_process = proc_current();
00136     #endif
00137 
00138     // Start convertion
00139     ADC_CR = BV(ADC_START);
00140 
00141     #if CONFIG_KERN
00142         // Ensure IRQs enabled.
00143         IRQ_ASSERT_ENABLED();
00144         sig_wait(SIG_ADC_COMPLETE);
00145     #else
00146         //Wait in polling until is done
00147         while (!(ADC_SR & BV(ADC_DRDY)));
00148     #endif
00149 
00150     //Return the last converted data
00151     return(ADC_LCDR);
00152 }
00153 
00157 INLINE void adc_hw_init(void)
00158 {
00159     //Init ADC pins.
00160     ADC_INIT_PINS();
00161 
00162     /*
00163      * Set adc mode register:
00164      * - Disable hardware trigger and enable software trigger.
00165      * - Select normal mode.
00166      * - Set ADC_BITS bit convertion resolution.
00167      *
00168      * \{
00169      */
00170     ADC_MR = 0;
00171     #if ADC_BITS == 10
00172         ADC_MR &= ~BV(ADC_LOWRES);
00173     #elif ADC_BITS == 8
00174         ADC_MR |= BV(ADC_LOWRES);
00175     #else
00176         #error No select bit resolution is supported to this CPU
00177     #endif
00178     /* \} */
00179 
00180     LOG_INFO("prescaler[%ld], stup[%ld], shtim[%ld]\n",ADC_COMPUTED_PRESCALER, ADC_COMPUTED_STARTUPTIME,  ADC_COMPUTED_SHTIME);
00181 
00182 
00183     //Apply computed prescaler value
00184     ADC_MR &= ~ADC_PRESCALER_MASK;
00185     ADC_MR |= ((ADC_COMPUTED_PRESCALER << ADC_PRESCALER_SHIFT) & ADC_PRESCALER_MASK);
00186     LOG_INFO("prescaler[%ld]\n", (ADC_COMPUTED_PRESCALER << ADC_PRESCALER_SHIFT) & ADC_PRESCALER_MASK);
00187 
00188     //Apply computed start up time
00189     ADC_MR &= ~ADC_STARTUP_MASK;
00190     ADC_MR |= ((ADC_COMPUTED_STARTUPTIME << ADC_STARTUP_SHIFT) & ADC_STARTUP_MASK);
00191     LOG_INFO("sttime[%ld]\n", (ADC_COMPUTED_STARTUPTIME << ADC_STARTUP_SHIFT) & ADC_STARTUP_MASK);
00192 
00193     //Apply computed sample and hold time
00194     ADC_MR &= ~ADC_SHTIME_MASK;
00195     ADC_MR |= ((ADC_COMPUTED_SHTIME << ADC_SHTIME_SHIFT) & ADC_SHTIME_MASK);
00196     LOG_INFO("shtime[%ld]\n", (ADC_COMPUTED_SHTIME << ADC_SHTIME_SHIFT) & ADC_SHTIME_MASK);
00197 
00198     #if CONFIG_KERN
00199         //Register and enable irq for adc.
00200         adc_enable_irq();
00201     #endif
00202 
00203 }