Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 #include <arch/arm.h>
00049 #include <dev/irqreg.h>
00050 
00051 #include <sys/event.h>
00052 #include <sys/atom.h>
00053 #include <sys/timer.h>
00054 #include <sys/thread.h>
00055 #include <sys/heap.h>
00056 
00057 #include <dev/irqreg.h>
00058 #include <dev/at91_adc.h>
00059 
00064 
00065 #ifndef AT91_ADC_INITIAL_MODE
00066 #define AT91_ADC_INITIAL_MODE SINGLE_CONVERSION
00067 #endif
00068 
00069 #ifndef AT91_ADC_INITIAL_PRESCALE
00070 #define AT91_ADC_INITIAL_PRESCALE 55
00071 #endif
00072 
00073 #define AT91_ADC_BUF_SIZE 16 // this may only be a power of two
00074 
00075 #define _adc_buf_head AT91_ADC_BUF_SIZE
00076 #define _adc_buf_tail AT91_ADC_BUF_SIZE+1
00077 
00078 uint16_t **ADC_Buffer = NULL;
00079 
00088 int ADCBufRead(uint16_t channel, uint16_t * read)
00089 {
00090     uint16_t tail, head;
00091     tail = ADC_Buffer[channel][_adc_buf_tail];
00092     head = ADC_Buffer[channel][_adc_buf_head];
00093     if (head != tail) {
00094         *read = ADC_Buffer[channel][tail];
00095         ADC_Buffer[channel][_adc_buf_tail] = (tail + 1) & (AT91_ADC_BUF_SIZE - 1);
00096         return 0;
00097     }
00098     return 1;
00099 }
00100 
00101 
00102 
00103 static inline int ADCBufWrite(uint16_t channel, uint16_t write)
00104 {
00105     uint16_t tail, head;
00106     tail = ADC_Buffer[channel][_adc_buf_tail];
00107     head = ADC_Buffer[channel][_adc_buf_head];
00108     if (((head + 1) & (AT91_ADC_BUF_SIZE - 1)) != tail) {
00109         ADC_Buffer[channel][head] = write;
00110         ADC_Buffer[channel][_adc_buf_head] = (head + 1) & (AT91_ADC_BUF_SIZE - 1);
00111         return 0;
00112     }
00113     return 1;
00114 }
00115 
00122 void ADCSetMode(TADCMode mode) 
00123 {
00124     uint32_t regval;
00125     
00126     regval = inr(ADC_MR);
00127     regval &= ~ADC_SLEEP;
00128     switch (mode) {
00129         case ADC_OFF:
00130             regval &= ~ADC_TRGEN;
00131             regval |= ADC_SLEEP;
00132             break;
00133         case SINGLE_CONVERSION:
00134             regval &= ~ADC_TRGEN;
00135             break;
00136         case FREE_RUNNING_T0:
00137             regval &= ~ADC_TRGSEL;
00138             regval |= ADC_TRGEN | ADC_TRGSEL_TIOA0;
00139             break;     
00140         case FREE_RUNNING_T1:
00141             regval &= ~ADC_TRGSEL;
00142             regval |= ADC_TRGEN | ADC_TRGSEL_TIOA1;
00143             break;
00144         case FREE_RUNNING_T2:
00145             regval &= ~ADC_TRGSEL;
00146             regval |= ADC_TRGEN | ADC_TRGSEL_TIOA2;
00147         break;
00148         case FREE_RUNNING_EXT:
00149             regval &= ~ADC_TRGSEL;
00150             regval |= ADC_TRGEN | ADC_TRGSEL_EXT;
00151             break;
00152     }
00153     outr(ADC_MR, regval);
00154 }
00155 
00162 void ADCEnableChannel(TADCChannel channel) 
00163 {
00164     uint32_t     adc_chsr;
00165     register int idx;
00166     register int max = channel;
00167 
00168     outr(ADC_CHER, _BV(channel));
00169     adc_chsr = inr(ADC_CHSR);
00170 
00171     
00172     for (idx = 0; idx < 8; idx ++) {
00173         if (adc_chsr & _BV(idx)) max = idx;
00174     }
00175 
00176     
00177     outr(ADC_IDR, 0x000000FF);
00178     
00179     outr(ADC_IER, _BV(max));
00180 }
00181 
00188 void ADCDisableChannel(TADCChannel channel) 
00189 {
00190     outr(ADC_CHDR, _BV(channel));
00191     outr(ADC_IDR,  _BV(channel));
00192 }
00193 
00200 void ADCSetPrescale(uint32_t prescale)
00201 {
00202     if (prescale > 128) prescale = 128;
00203 
00204     prescale = (prescale / 2) - 1;
00205     outr(ADC_MR, ((inr(ADC_MR) & ~(ADC_PRESCAL | ADC_STARTUP | ADC_SHTIM)) | 
00206                 (prescale << ADC_PRESCAL_LSB) | ADC_STARTUP | ADC_SHTIM));     
00207 }
00208 
00214 void ADCStartConversion(void)
00215 {
00216     outr(ADC_CR, ADC_START);
00217 }
00218 
00219 
00220 
00221 
00222 
00223 static void ADCInterrupt(void *arg)
00224 {
00225     register uint32_t adcsr = inr(ADC_SR) & inr(ADC_CHSR);
00226     uint16_t ADC_Value;        
00227     uint16_t channel;
00228 
00229     for (channel = 0; channel < ADC_MAX_CHANNEL; channel ++) {
00230         if (adcsr & _BV(channel)) {
00231             ADC_Value = inr(ADC_CDR(channel));
00232             if (ADCBufWrite(channel, ADC_Value) != 0) {
00233                 
00234             }
00235         }
00236     }
00237 }
00238 
00243 void ADCInit(void)
00244 {
00245     int channel;
00246     
00247     
00248     if (ADC_Buffer) return;
00249 
00250     
00251     outr(PMC_PCER, _BV(ADC_ID));              
00252     outr(ADC_CR, ADC_SWRST);                  
00253     outr(ADC_CR, 0x00);
00254     
00255     
00256     outr(ADC_CHDR, ADC_CH0 | ADC_CH1 | ADC_CH2 | ADC_CH3 | ADC_CH4 | ADC_CH5 | ADC_CH6 | ADC_CH7);
00257     ADCSetMode(AT91_ADC_INITIAL_MODE);
00258     ADCSetPrescale(AT91_ADC_INITIAL_PRESCALE);
00259 
00260     
00261     ADC_Buffer = NutHeapAlloc(sizeof(uint16_t *) * ADC_MAX_CHANNEL);
00262     for (channel = 0; channel < ADC_MAX_CHANNEL; channel ++) {
00263         ADC_Buffer[channel] = NutHeapAlloc(sizeof(uint16_t) * AT91_ADC_BUF_SIZE + 2);
00264         ADC_Buffer[channel][_adc_buf_head] = 0;
00265         ADC_Buffer[channel][_adc_buf_tail] = 0;        
00266     }
00267 
00268     if (NutRegisterIrqHandler(&sig_ADC, ADCInterrupt, NULL)) {
00269         
00270         return;
00271     }
00272     NutIrqEnable(&sig_ADC);
00273 }
00274