adc.c
Go to the documentation of this file.00001
00038 #include <compiler.h>
00039 #include <adc.h>
00040
00046
00047
00048
00049 #ifdef ADCA
00050
00058 static uint8_t adca_enable_count;
00059
00060 # ifdef CONFIG_ADC_CALLBACK_ENABLE
00061
00066 static adc_callback_t adca_callback;
00067
00075 ISR(ADCA_CH0_vect)
00076 {
00077 adca_callback(&ADCA, 0, adcch_get_result(&ADCA, 0));
00078 }
00079
00080 # if XMEGA_A
00081
00089 ISR(ADCA_CH1_vect)
00090 {
00091 adca_callback(&ADCA, 1, adcch_get_result(&ADCA, 1));
00092 }
00093
00101 ISR(ADCA_CH2_vect)
00102 {
00103 adca_callback(&ADCA, 2, adcch_get_result(&ADCA, 2));
00104 }
00105
00113 ISR(ADCA_CH3_vect)
00114 {
00115 adca_callback(&ADCA, 3, adcch_get_result(&ADCA, 3));
00116 }
00117
00118 # endif
00119 # endif
00120 #endif
00121
00122 #ifdef ADCB
00123
00131 static uint8_t adcb_enable_count;
00132
00133 # ifdef CONFIG_ADC_CALLBACK_ENABLE
00134
00139 static adc_callback_t adcb_callback;
00140
00148 ISR(ADCB_CH0_vect)
00149 {
00150 adcb_callback(&ADCB, 0, adcch_get_result(&ADCB, 0));
00151 }
00152
00153 # if XMEGA_A
00154
00162 ISR(ADCB_CH1_vect)
00163 {
00164 adcb_callback(&ADCB, 1, adcch_get_result(&ADCB, 1));
00165 }
00166
00174 ISR(ADCB_CH2_vect)
00175 {
00176 adcb_callback(&ADCB, 2, adcch_get_result(&ADCB, 2));
00177 }
00178
00186 ISR(ADCB_CH3_vect)
00187 {
00188 adcb_callback(&ADCB, 3, adcch_get_result(&ADCB, 3));
00189 }
00190
00191 # endif
00192 # endif
00193 #endif
00194
00196
00209 static void adc_enable_clock(ADC_t *adc)
00210 {
00211 #ifdef ADCA
00212 if ((uintptr_t)adc == (uintptr_t)(&ADCA)) {
00213 Assert(adca_enable_count < 0xff);
00214 if (!adca_enable_count++) {
00215 sysclk_enable_module(SYSCLK_PORT_A, SYSCLK_ADC);
00216 }
00217 } else
00218 #endif
00219
00220 #ifdef ADCB
00221 if ((uintptr_t)adc == (uintptr_t)(&ADCB)) {
00222 Assert(adcb_enable_count < 0xff);
00223 if (!adcb_enable_count++) {
00224 sysclk_enable_module(SYSCLK_PORT_B, SYSCLK_ADC);
00225 }
00226 } else
00227 #endif
00228
00229 {
00230 Assert(0);
00231 }
00232 }
00233
00244 static void adc_disable_clock(ADC_t *adc)
00245 {
00246 #ifdef ADCA
00247 if ((uintptr_t)adc == (uintptr_t)(&ADCA)) {
00248 Assert(adca_enable_count);
00249 if (!--adca_enable_count) {
00250 sysclk_disable_module(SYSCLK_PORT_A, SYSCLK_ADC);
00251 }
00252 } else
00253 #endif
00254
00255 #ifdef ADCB
00256 if ((uintptr_t)adc == (uintptr_t)(&ADCB)) {
00257 Assert(adcb_enable_count);
00258 if (!--adcb_enable_count) {
00259 sysclk_disable_module(SYSCLK_PORT_B, SYSCLK_ADC);
00260 }
00261 } else
00262 #endif
00263
00264 {
00265 Assert(0);
00266 }
00267 }
00268
00279 void adc_enable(ADC_t *adc)
00280 {
00281 irqflags_t flags = cpu_irq_save();
00282 adc_enable_clock(adc);
00283 adc->CTRLA |= ADC_ENABLE_bm;
00284 cpu_irq_restore(flags);
00285
00286 sleepmgr_lock_mode(SLEEPMGR_IDLE);
00287 }
00288
00296 void adc_disable(ADC_t *adc)
00297 {
00298 irqflags_t flags = cpu_irq_save();
00299 adc->CTRLA &= ~ADC_ENABLE_bm;
00300 adc_disable_clock(adc);
00301 cpu_irq_restore(flags);
00302
00303 sleepmgr_unlock_mode(SLEEPMGR_IDLE);
00304 }
00305
00314 bool adc_is_enabled(ADC_t *adc)
00315 {
00316
00317
00318
00319
00320
00321 #ifdef ADCA
00322 if ((uintptr_t)adc == (uintptr_t)&ADCA) {
00323 return adca_enable_count;
00324 } else
00325 #endif
00326
00327 #ifdef ADCB
00328 if ((uintptr_t)adc == (uintptr_t)&ADCB) {
00329 return adcb_enable_count;
00330 } else
00331 #endif
00332
00333 {
00334 Assert(0);
00335 return false;
00336 }
00337 }
00338
00349 void adc_write_configuration(ADC_t *adc, const struct adc_config *conf)
00350 {
00351 uint16_t cal;
00352 uint8_t enable;
00353 irqflags_t flags;
00354
00355 #ifdef ADCA
00356 if ((uintptr_t)adc == (uintptr_t)&ADCA) {
00357 cal = adc_get_calibration_data(ADC_CAL_ADCA);
00358 } else
00359 #endif
00360
00361 #ifdef ADCB
00362 if ((uintptr_t)adc == (uintptr_t)&ADCB) {
00363 cal = adc_get_calibration_data(ADC_CAL_ADCB);
00364 } else
00365 #endif
00366
00367 {
00368 Assert(0);
00369 return;
00370 }
00371
00372 flags = cpu_irq_save();
00373 adc_enable_clock(adc);
00374
00375 enable = adc->CTRLA & ADC_ENABLE_bm;
00376
00377 adc->CTRLA = ADC_FLUSH_bm;
00378 adc->CAL = cal;
00379 adc->CMP = conf->cmp;
00380 adc->REFCTRL = conf->refctrl;
00381 adc->PRESCALER = conf->prescaler;
00382 adc->EVCTRL = conf->evctrl;
00383 adc->CTRLB = conf->ctrlb;
00384
00385 #if XMEGA_A
00386 adc->CTRLA = enable | conf->ctrla;
00387 #elif XMEGA_D
00388 adc->CTRLA = enable;
00389 #endif
00390
00391 adc_disable_clock(adc);
00392
00393 cpu_irq_restore(flags);
00394 }
00395
00405 void adc_read_configuration(ADC_t *adc, struct adc_config *conf)
00406 {
00407 irqflags_t flags = cpu_irq_save();
00408
00409 adc_enable_clock(adc);
00410
00411 #if XMEGA_A
00412 conf->ctrla = adc->CTRLA & ADC_DMASEL_gm;
00413 #endif
00414
00415 conf->cmp = adc->CMP;
00416 conf->refctrl = adc->REFCTRL;
00417 conf->prescaler = adc->PRESCALER;
00418 conf->evctrl = adc->EVCTRL;
00419 conf->ctrlb = adc->CTRLB;
00420
00421 adc_disable_clock(adc);
00422
00423 cpu_irq_restore(flags);
00424 }
00425
00439 void adcch_write_configuration(ADC_t *adc, uint8_t ch,
00440 const struct adc_channel_config *ch_conf)
00441 {
00442 ADC_CH_t *adc_ch;
00443 irqflags_t flags;
00444
00445 Assert(ch < ADC_NR_OF_CHANNELS);
00446 adc_ch = &adc->CH0 + ch;
00447
00448 flags = cpu_irq_save();
00449
00450 #if defined(CONFIG_ADC_CALLBACK_ENABLE) && defined(_ASSERT_ENABLE_)
00451 if ((adc_ch->INTCTRL & ADC_CH_INTLVL_gm) != ADC_CH_INTLVL_OFF_gc) {
00452 #ifdef ADCA
00453 if ((uintptr_t)adc == (uintptr_t)&ADCA) {
00454 Assert(adca_callback);
00455 } else
00456 #endif
00457
00458 #ifdef ADCB
00459 if ((uintptr_t)adc == (uintptr_t)&ADCB) {
00460 Assert(adcb_callback);
00461 } else
00462 #endif
00463
00464 {
00465 Assert(0);
00466 return;
00467 }
00468 }
00469 #endif
00470
00471 adc_enable_clock(adc);
00472 adc_ch->CTRL = ch_conf->ctrl;
00473 adc_ch->INTCTRL = ch_conf->intctrl;
00474 adc_ch->MUXCTRL = ch_conf->muxctrl;
00475 adc_disable_clock(adc);
00476
00477 cpu_irq_restore(flags);
00478 }
00479
00490 void adcch_read_configuration(ADC_t *adc, uint8_t ch,
00491 struct adc_channel_config *ch_conf)
00492 {
00493 ADC_CH_t *adc_ch;
00494 irqflags_t flags;
00495
00496 Assert(ch < ADC_NR_OF_CHANNELS);
00497 adc_ch = &adc->CH0 + ch;
00498
00499 flags = cpu_irq_save();
00500
00501 adc_enable_clock(adc);
00502 ch_conf->ctrl = adc_ch->CTRL;
00503 ch_conf->intctrl = adc_ch->INTCTRL;
00504 ch_conf->muxctrl = adc_ch->MUXCTRL;
00505 adc_disable_clock(adc);
00506
00507 cpu_irq_restore(flags);
00508 }
00509
00510 #if defined(CONFIG_ADC_CALLBACK_ENABLE) || defined(__DOXYGEN__)
00511
00520 void adc_set_callback(ADC_t *adc, adc_callback_t callback)
00521 {
00522 irqflags_t flags;
00523
00524 Assert(callback);
00525
00526 flags = cpu_irq_save();
00527
00528 #ifdef ADCA
00529 if ((uintptr_t)adc == (uintptr_t)&ADCA) {
00530 adca_callback = callback;
00531 } else
00532 #endif
00533
00534 #ifdef ADCB
00535 if ((uintptr_t)adc == (uintptr_t)&ADCB) {
00536 adcb_callback = callback;
00537 } else
00538 #endif
00539
00540 {
00541 Assert(0);
00542 }
00543
00544 cpu_irq_restore(flags);
00545 }
00546
00547 #endif