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