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
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00085
00086
00087 #ifdef __GNUC__
00088
00089 #include <string.h>
00090 #include <avr/sleep.h>
00091 #include <sys/heap.h>
00092 #include <sys/atom.h>
00093 #include <sys/nutconfig.h>
00094
00095 #include <dev/irqreg.h>
00096 #include <dev/adc.h>
00097
00098 #ifndef ADC_INITIAL_CHANNEL
00099 #define ADC_INITIAL_CHANNEL ADC0
00100 #endif
00101
00102 #ifndef ADC_INITIAL_REF
00103 #define ADC_INITIAL_REF AVCC
00104 #endif
00105
00106 #ifndef ADC_INITIAL_MODE
00107 #define ADC_INITIAL_MODE SINGLE_CONVERSION
00108 #endif
00109
00110 #ifndef ADC_INITIAL_PRESCALE
00111 #define ADC_INITIAL_PRESCALE ADC_PRESCALE_DIV64
00112 #endif
00113
00114 #define ADC_BUF_SIZE 16 // this may only be a power of two
00115
00116 #if defined(__GNUC__) && defined(__AVR_ENHANCED__)
00117 uint8_t adc_sleep_mode = SLEEP_MODE_ADC;
00118
00119
00120 #if defined(SMCR)
00121 #define AVR_SLEEP_CTRL_REG SMCR
00122 #else
00123 #define AVR_SLEEP_CTRL_REG MCUCR
00124 #endif
00125 #endif
00126
00127
00128
00129
00130 adc_mode_t current_mode = ADC_OFF;
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 #define _adc_buf_head ADC_BUF_SIZE
00142 #define _adc_buf_tail (ADC_BUF_SIZE+1)
00143
00144 uint16_t *ADC_buffer = NULL;
00145
00146 inline int ADCBufRead(uint16_t * buf, uint16_t * read)
00147 {
00148 uint8_t tail, head;
00149 tail = buf[_adc_buf_tail];
00150 head = buf[_adc_buf_head];
00151 if (head != tail) {
00152 *read = buf[tail];
00153 buf[_adc_buf_tail] = (tail + 1) & (ADC_BUF_SIZE-1);
00154 return 0;
00155 }
00156 return 1;
00157 }
00158
00159 inline int ADCBufWrite(uint16_t * buf, uint16_t * write)
00160 {
00161 uint8_t tail, head;
00162 tail = buf[_adc_buf_tail];
00163 head = buf[_adc_buf_head];
00164 if ((head + 1) % ADC_BUF_SIZE != tail) {
00165 buf[head] = *write;
00166 buf[_adc_buf_head] = (head + 1) & (ADC_BUF_SIZE-1);
00167 return 0;
00168 }
00169 return 1;
00170 }
00171
00172 void ADCBufInit(uint16_t * buf)
00173 {
00174 buf[_adc_buf_head] = 0;
00175 buf[_adc_buf_tail] = 0;
00176 }
00177
00178 static void ADCInterrupt(void *arg)
00179 {
00180 uint16_t ADC_value;
00181
00182 ADC_value = inw(ADCW);
00183
00184 if (ADCBufWrite(ADC_buffer, &ADC_value) != 0) {
00185
00186 }
00187
00188 }
00189
00190 void ADCInit()
00191 {
00192 if (ADC_buffer) return;
00193
00194 ADCSetChannel(ADC_INITIAL_CHANNEL);
00195 ADCSetRef(ADC_INITIAL_REF);
00196 ADCSetMode(ADC_INITIAL_MODE);
00197 ADCSetPrescale(ADC_INITIAL_PRESCALE);
00198
00199 ADC_buffer = NutHeapAlloc(sizeof(uint16_t) * (ADC_BUF_SIZE + 2));
00200 ADCBufInit(ADC_buffer);
00201
00202 if (NutRegisterIrqHandler(&sig_ADC, ADCInterrupt, NULL)) {
00203
00204 return;
00205 }
00206
00207 sbi(ADCSR, ADEN);
00208
00209
00210 sbi(ADCSR, ADIE);
00211 }
00212
00213 void ADCSetRef(adc_ref_t reference)
00214 {
00215 ADCStopConversion();
00216
00217 #ifdef __AVR_ENHANCED__
00218 switch (reference) {
00219 case AVCC:
00220 cbi(ADMUX, REFS1);
00221 sbi(ADMUX, REFS0);
00222 break;
00223 case AREF:
00224 cbi(ADMUX, REFS1);
00225 cbi(ADMUX, REFS0);
00226 break;
00227 case INTERNAL_256:
00228 sbi(ADMUX, REFS1);
00229 sbi(ADMUX, REFS0);
00230 break;
00231 }
00232 #endif
00233
00234 }
00235
00236 void ADCSetMode(adc_mode_t mode)
00237 {
00238 ADCStopConversion();
00239
00240 switch (mode) {
00241 case FREE_RUNNING:
00242 sbi(ADCSR, ADFR);
00243 break;
00244 case SINGLE_CONVERSION:
00245 cbi(ADCSR, ADFR);
00246 break;
00247 case ADC_OFF:
00248 break;
00249 }
00250 current_mode = mode;
00251 }
00252
00253 uint8_t ADCSetPrescale(uint8_t prescalar)
00254 {
00255
00256 ADCStopConversion();
00257
00258 if (prescalar > 128) {
00259 prescalar = 128;
00260 }
00261
00262 switch (prescalar) {
00263 case ADC_PRESCALE_DIV2:
00264 cbi(ADCSR, ADPS2);
00265 cbi(ADCSR, ADPS1);
00266 cbi(ADCSR, ADPS0);
00267 break;
00268 case ADC_PRESCALE_DIV4:
00269 cbi(ADCSR, ADPS2);
00270 sbi(ADCSR, ADPS1);
00271 cbi(ADCSR, ADPS0);
00272 break;
00273 case ADC_PRESCALE_DIV8:
00274 cbi(ADCSR, ADPS2);
00275 sbi(ADCSR, ADPS1);
00276 sbi(ADCSR, ADPS0);
00277 break;
00278 case ADC_PRESCALE_DIV16:
00279 sbi(ADCSR, ADPS2);
00280 cbi(ADCSR, ADPS1);
00281 cbi(ADCSR, ADPS0);
00282 break;
00283 case ADC_PRESCALE_DIV32:
00284 sbi(ADCSR, ADPS2);
00285 cbi(ADCSR, ADPS1);
00286 sbi(ADCSR, ADPS0);
00287 break;
00288 case ADC_PRESCALE_DIV64:
00289 sbi(ADCSR, ADPS2);
00290 sbi(ADCSR, ADPS1);
00291 cbi(ADCSR, ADPS0);
00292 break;
00293 case ADC_PRESCALE_DIV128:
00294 sbi(ADCSR, ADPS2);
00295 sbi(ADCSR, ADPS1);
00296 sbi(ADCSR, ADPS0);
00297 break;
00298
00299 default:
00300 return 1;
00301 break;
00302 }
00303
00304 return 0;
00305 }
00306
00307 void ADCSetChannel(adc_channel_t adc_channel)
00308 {
00309 uint8_t current_admux;
00310
00311 current_admux = inb(ADMUX) & 0xF8;
00312
00313 outb(ADMUX, (current_admux | adc_channel));
00314 }
00315
00316 void ADCBufferFlush(void)
00317 {
00318 ADCBufInit(ADC_buffer);
00319 }
00320
00321 void ADCStartConversion()
00322 {
00323 sbi(ADCSR, ADSC);
00324 }
00325
00326 void ADCStartLowNoiseConversion()
00327 {
00328 ADCSetMode(SINGLE_CONVERSION);
00329
00330 #if defined(__GNUC__) && defined(__AVR_ENHANCED__)
00331 {
00332 uint8_t sleep_mode = AVR_SLEEP_CTRL_REG & _SLEEP_MODE_MASK;
00333 set_sleep_mode(adc_sleep_mode);
00334
00335
00336 AVR_SLEEP_CTRL_REG |= _BV(SE);
00337 __asm__ __volatile__ ("sleep" "\n\t" :: );
00338 AVR_SLEEP_CTRL_REG &= ~_BV(SE);
00339 set_sleep_mode(sleep_mode);
00340 }
00341 #else
00342 sbi(ADCSR, ADSC);
00343 #endif
00344 }
00345
00346 void ADCStopConversion()
00347 {
00348 if (current_mode != FREE_RUNNING) {
00349
00350 return;
00351 }
00352
00353
00354
00355 cbi(ADCSR, ADEN);
00356 cbi(ADCSR, ADSC);
00357 sbi(ADCSR, ADEN);
00358 }
00359
00360 uint8_t ADCRead(uint16_t * value)
00361 {
00362 return ADCBufRead(ADC_buffer, value);
00363 }
00364
00365 inline adc_mode_t ADCGetMode(void)
00366 {
00367 return (current_mode);
00368 }
00369 #endif
00370