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 #include <arch/arm.h>
00045 #include <dev/irqreg.h>
00046
00047 #include <sys/event.h>
00048 #include <sys/atom.h>
00049 #include <sys/timer.h>
00050 #include <sys/thread.h>
00051 #include <sys/heap.h>
00052
00053 #include <dev/irqreg.h>
00054 #include <dev/at91_adc.h>
00055
00060
00061 #ifndef AT91_ADC_INITIAL_MODE
00062 #define AT91_ADC_INITIAL_MODE SINGLE_CONVERSION
00063 #endif
00064
00065 #ifndef AT91_ADC_INITIAL_PRESCALE
00066 #define AT91_ADC_INITIAL_PRESCALE 55
00067 #endif
00068
00069 #define AT91_ADC_BUF_SIZE 16 // this may only be a power of two
00070
00071 #define _adc_buf_head AT91_ADC_BUF_SIZE
00072 #define _adc_buf_tail AT91_ADC_BUF_SIZE+1
00073
00074 uint16_t **ADC_Buffer = NULL;
00075
00084 int ADCBufRead(uint16_t channel, uint16_t * read)
00085 {
00086 uint16_t tail, head;
00087 tail = ADC_Buffer[channel][_adc_buf_tail];
00088 head = ADC_Buffer[channel][_adc_buf_head];
00089 if (head != tail) {
00090 *read = ADC_Buffer[channel][tail];
00091 ADC_Buffer[channel][_adc_buf_tail] = (tail + 1) & (AT91_ADC_BUF_SIZE-1);
00092 return 0;
00093 }
00094 return 1;
00095 }
00096
00097
00098
00099 static inline int ADCBufWrite(uint16_t channel, uint16_t write)
00100 {
00101 uint16_t tail, head;
00102 tail = ADC_Buffer[channel][_adc_buf_tail];
00103 head = ADC_Buffer[channel][_adc_buf_head];
00104 if ((head + 1) % AT91_ADC_BUF_SIZE != tail) {
00105 ADC_Buffer[channel][head] = write;
00106 ADC_Buffer[channel][_adc_buf_head] = (head + 1) & (AT91_ADC_BUF_SIZE-1);
00107 return 0;
00108 }
00109 return 1;
00110 }
00111
00118 void ADCSetMode(TADCMode mode)
00119 {
00120 u_int regval;
00121
00122 regval = inr(ADC_MR);
00123 regval &= ~ADC_SLEEP;
00124 switch (mode) {
00125 case ADC_OFF:
00126 regval &= ~ADC_TRGEN;
00127 regval |= ADC_SLEEP;
00128 break;
00129 case SINGLE_CONVERSION:
00130 regval &= ~ADC_TRGEN;
00131 break;
00132 case FREE_RUNNING_T0:
00133 regval &= ~ADC_TRGSEL;
00134 regval |= ADC_TRGEN | ADC_TRGSEL_TIOA0;
00135 break;
00136 case FREE_RUNNING_T1:
00137 regval &= ~ADC_TRGSEL;
00138 regval |= ADC_TRGEN | ADC_TRGSEL_TIOA1;
00139 break;
00140 case FREE_RUNNING_T2:
00141 regval &= ~ADC_TRGSEL;
00142 regval |= ADC_TRGEN | ADC_TRGSEL_TIOA2;
00143 break;
00144 case FREE_RUNNING_EXT:
00145 regval &= ~ADC_TRGSEL;
00146 regval |= ADC_TRGEN | ADC_TRGSEL_EXT;
00147 break;
00148 }
00149 outr(ADC_MR, regval);
00150 }
00151
00158 void ADCEnableChannel(TADCChannel channel)
00159 {
00160 outr(ADC_CHER, _BV(channel));
00161 outr(ADC_IER, _BV(channel));
00162 }
00163
00170 void ADCDisableChannel(TADCChannel channel)
00171 {
00172 outr(ADC_CHER, _BV(channel));
00173 outr(ADC_IDR, _BV(channel));
00174 }
00175
00182 void ADCSetPrescale(u_int prescale)
00183 {
00184 if (prescale > 128) prescale = 128;
00185
00186 prescale = (prescale / 2) - 1;
00187 outr(ADC_MR, ((inr(ADC_MR) & ~(ADC_PRESCAL | ADC_STARTUP | ADC_SHTIM)) |
00188 (prescale << ADC_PRESCAL_LSB) | ADC_STARTUP | ADC_SHTIM));
00189 }
00190
00196 void ADCStartConversion(void)
00197 {
00198 outr(ADC_CR, ADC_START);
00199 }
00200
00201
00202
00203
00204
00205 static void ADCInterrupt(void *arg)
00206 {
00207 register u_int adcsr = inr(ADC_SR);
00208 uint16_t ADC_Value;
00209 uint16_t channel;
00210
00211 for (channel = 0; channel < ADC_MAX_CHANNEL; channel ++) {
00212 if (adcsr & _BV(channel)) {
00213 ADC_Value = inr(ADC_CDR(channel));
00214 if (ADCBufWrite(channel, ADC_Value) != 0) {
00215
00216 }
00217 }
00218 }
00219 }
00220
00225 void ADCInit(void)
00226 {
00227 int channel;
00228
00229
00230 if (ADC_Buffer) return;
00231
00232
00233 outr(PMC_PCER, _BV(ADC_ID));
00234 outr(ADC_CR, ADC_SWRST);
00235 outr(ADC_CR, 0x00);
00236
00237
00238 outr(ADC_CHDR, ADC_CH0 | ADC_CH1 | ADC_CH2 | ADC_CH3 | ADC_CH4 | ADC_CH5 | ADC_CH6 | ADC_CH7);
00239 ADCSetMode(AT91_ADC_INITIAL_MODE);
00240 ADCSetPrescale(AT91_ADC_INITIAL_PRESCALE);
00241
00242
00243 ADC_Buffer = NutHeapAlloc(sizeof(uint16_t *) * ADC_MAX_CHANNEL);
00244 for (channel = 0; channel < ADC_MAX_CHANNEL; channel ++) {
00245 ADC_Buffer[channel] = NutHeapAlloc(sizeof(uint16_t) * AT91_ADC_BUF_SIZE + 2);
00246 ADC_Buffer[channel][_adc_buf_head] = 0;
00247 ADC_Buffer[channel][_adc_buf_tail] = 0;
00248 }
00249
00250 if (NutRegisterIrqHandler(&sig_ADC, ADCInterrupt, NULL)) {
00251
00252 return;
00253 }
00254 NutIrqEnable(&sig_ADC);
00255 }
00256