Xmega Application Note


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 /* XMEGA_A */
00119 #  endif /* ADCA */
00120 #endif /* CONFIG_ADC_CALLBACK_ENABLE */
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 /* XMEGA_A */
00192 #  endif /* ADCB */
00193 #endif /* CONFIG_ADC_CALLBACK_ENABLE */
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         /* It is sufficient to return the state of the ADC enable counters
00317          * since all driver functions that change the counts are protected
00318          * against interrupts and only the enable/disable functions leave the
00319          * counts incremented/decremented upon return.
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 /* ADCA */
00457 
00458 #ifdef ADCB
00459                 if ((uintptr_t)adc == (uintptr_t)&ADCB) {
00460                         Assert(adcb_callback);
00461                 } else
00462 #endif /* ADCB */
00463 
00464                 {
00465                         Assert(0);
00466                         return;
00467                 }
00468         }
00469 #endif /* CONFIG_ADC_CALLBACK_ENABLE */
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 /* CONFIG_ADC_CALLBACK_ENABLE */
@DOC_TITLE@
Generated on Fri Oct 22 12:15:25 2010 for AVR1300 Using the Xmega ADC by doxygen 1.6.3