adc_at91.c

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