00001
00034 #include "em_pcnt.h"
00035 #if defined(PCNT_COUNT) && (PCNT_COUNT > 0)
00036
00037 #include "em_cmu.h"
00038 #include "em_assert.h"
00039 #include "em_bitband.h"
00040
00041
00046
00052
00053
00054
00055
00060 #if (PCNT_COUNT == 1)
00061 #define PCNT_REF_VALID(ref) ((ref) == PCNT0)
00062 #elif (PCNT_COUNT == 2)
00063 #define PCNT_REF_VALID(ref) (((ref) == PCNT0) || ((ref) == PCNT1))
00064 #elif (PCNT_COUNT == 3)
00065 #define PCNT_REF_VALID(ref) (((ref) == PCNT0) || ((ref) == PCNT1) || \
00066 ((ref) == PCNT2))
00067 #else
00068 #error Undefined number of pulse counters (PCNT).
00069 #endif
00070
00074
00075
00076
00077
00080
00090 __STATIC_INLINE unsigned int PCNT_Map(PCNT_TypeDef *pcnt)
00091 {
00092 return(((uint32_t)pcnt - PCNT0_BASE) / 0x400);
00093 }
00094
00095
00096
00107 __STATIC_INLINE void PCNT_Sync(PCNT_TypeDef *pcnt, uint32_t mask)
00108 {
00109
00110
00111 if (pcnt->FREEZE & PCNT_FREEZE_REGFREEZE)
00112 {
00113 return;
00114 }
00115
00116
00117
00118 while (pcnt->SYNCBUSY & mask)
00119 ;
00120 }
00121
00124
00125
00126
00127
00128
00142 void PCNT_CounterReset(PCNT_TypeDef *pcnt)
00143 {
00144 EFM_ASSERT(PCNT_REF_VALID(pcnt));
00145
00146
00147 BITBAND_Peripheral(&(pcnt->CTRL), _PCNT_CTRL_RSTEN_SHIFT, 1);
00148
00149
00150 BITBAND_Peripheral(&(pcnt->CTRL), _PCNT_CTRL_RSTEN_SHIFT, 0);
00151 }
00152
00153
00154
00178 void PCNT_CounterTopSet(PCNT_TypeDef *pcnt, uint32_t count, uint32_t top)
00179 {
00180 uint32_t ctrl;
00181
00182 EFM_ASSERT(PCNT_REF_VALID(pcnt));
00183
00184 #ifdef PCNT0
00185 if (PCNT0 == pcnt)
00186 {
00187 EFM_ASSERT((1<<PCNT0_CNT_SIZE) > count);
00188 EFM_ASSERT((1<<PCNT0_CNT_SIZE) > top);
00189 }
00190 #endif
00191
00192 #ifdef PCNT1
00193 if (PCNT1 == pcnt)
00194 {
00195 EFM_ASSERT((1<<PCNT1_CNT_SIZE) > count);
00196 EFM_ASSERT((1<<PCNT1_CNT_SIZE) > top);
00197 }
00198 #endif
00199
00200 #ifdef PCNT2
00201 if (PCNT2 == pcnt)
00202 {
00203 EFM_ASSERT((1<<PCNT2_CNT_SIZE) > count);
00204 EFM_ASSERT((1<<PCNT2_CNT_SIZE) > top);
00205 }
00206 #endif
00207
00208
00209 ctrl = pcnt->CTRL;
00210
00211
00212 if ((ctrl & _PCNT_CTRL_MODE_MASK) != PCNT_CTRL_MODE_DISABLE)
00213 {
00214 PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL);
00215 pcnt->CTRL = (ctrl & ~_PCNT_CTRL_MODE_MASK) | PCNT_CTRL_MODE_DISABLE;
00216 }
00217
00218
00219 PCNT_Sync(pcnt, PCNT_SYNCBUSY_TOPB);
00220 pcnt->TOPB = count;
00221
00222
00223 PCNT_Sync(pcnt, PCNT_SYNCBUSY_TOPB | PCNT_SYNCBUSY_CMD);
00224
00225
00226 pcnt->CMD = PCNT_CMD_LTOPBIM;
00227 PCNT_Sync(pcnt, PCNT_SYNCBUSY_CMD);
00228
00229
00230 pcnt->CMD = PCNT_CMD_LCNTIM;
00231
00232
00233
00234
00235 if (top != count)
00236 {
00237
00238 PCNT_Sync(pcnt, PCNT_SYNCBUSY_CMD);
00239
00240
00241
00242 pcnt->TOPB = top;
00243
00244
00245 PCNT_Sync(pcnt, PCNT_SYNCBUSY_TOPB | PCNT_SYNCBUSY_CMD);
00246 pcnt->CMD = PCNT_CMD_LTOPBIM;
00247 }
00248
00249
00250 if ((ctrl & _PCNT_CTRL_MODE_MASK) != PCNT_CTRL_MODE_DISABLE)
00251 {
00252 PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL | PCNT_SYNCBUSY_CMD);
00253 pcnt->CTRL = ctrl;
00254 }
00255 }
00256
00257
00258
00280 void PCNT_Enable(PCNT_TypeDef *pcnt, PCNT_Mode_TypeDef mode)
00281 {
00282 uint32_t tmp;
00283
00284 EFM_ASSERT(PCNT_REF_VALID(pcnt));
00285
00286
00287 tmp = pcnt->CTRL & ~_PCNT_CTRL_MODE_MASK;
00288 tmp |= (uint32_t)mode << _PCNT_CTRL_MODE_SHIFT;
00289
00290
00291 PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL);
00292 pcnt->CTRL = tmp;
00293 }
00294
00295 #if defined( _PCNT_INPUT_MASK )
00296
00312 void PCNT_PRSInputEnable(PCNT_TypeDef *pcnt,
00313 PCNT_PRSInput_TypeDef prsInput,
00314 bool enable)
00315 {
00316 EFM_ASSERT(PCNT_REF_VALID(pcnt));
00317
00318
00319 switch (prsInput)
00320 {
00321
00322 case pcntPRSInputS0:
00323 {
00324 BITBAND_Peripheral(&(pcnt->INPUT), _PCNT_INPUT_S0PRSEN_SHIFT, (uint32_t)enable);
00325 }
00326 break;
00327
00328
00329 case pcntPRSInputS1:
00330 {
00331 BITBAND_Peripheral(&(pcnt->INPUT), _PCNT_INPUT_S1PRSEN_SHIFT, (uint32_t)enable);
00332 }
00333 break;
00334
00335
00336 default:
00337 {
00338 EFM_ASSERT(0);
00339 }
00340 break;
00341 }
00342 }
00343 #endif
00344
00345
00346
00373 void PCNT_FreezeEnable(PCNT_TypeDef *pcnt, bool enable)
00374 {
00375 EFM_ASSERT(PCNT_REF_VALID(pcnt));
00376
00377 if (enable)
00378 {
00379
00380
00381
00382
00383
00384
00385
00386 while (pcnt->SYNCBUSY)
00387 ;
00388
00389 pcnt->FREEZE = PCNT_FREEZE_REGFREEZE;
00390 }
00391 else
00392 {
00393 pcnt->FREEZE = 0;
00394 }
00395 }
00396
00397
00398
00437 void PCNT_Init(PCNT_TypeDef *pcnt, const PCNT_Init_TypeDef *init)
00438 {
00439 unsigned int inst;
00440 uint32_t tmp;
00441
00442 EFM_ASSERT(PCNT_REF_VALID(pcnt));
00443
00444 #ifdef PCNT0
00445 if (PCNT0 == pcnt)
00446 {
00447 EFM_ASSERT((1<<PCNT0_CNT_SIZE) > init->counter);
00448 EFM_ASSERT((1<<PCNT0_CNT_SIZE) > init->top);
00449 }
00450 #endif
00451
00452 #ifdef PCNT1
00453 if (PCNT1 == pcnt)
00454 {
00455 EFM_ASSERT((1<<PCNT1_CNT_SIZE) > init->counter);
00456 EFM_ASSERT((1<<PCNT1_CNT_SIZE) > init->top);
00457 }
00458 #endif
00459
00460 #ifdef PCNT2
00461 if (PCNT2 == pcnt)
00462 {
00463 EFM_ASSERT((1<<PCNT2_CNT_SIZE) > init->counter);
00464 EFM_ASSERT((1<<PCNT2_CNT_SIZE) > init->top);
00465 }
00466 #endif
00467
00468
00469 inst = PCNT_Map(pcnt);
00470
00471 #if defined( _PCNT_INPUT_MASK )
00472
00473
00474
00475 tmp = pcnt->INPUT & ~(_PCNT_INPUT_S0PRSSEL_MASK | _PCNT_INPUT_S1PRSSEL_MASK);
00476 tmp |= ((uint32_t)init->s0PRS << _PCNT_INPUT_S0PRSSEL_SHIFT) |
00477 ((uint32_t)init->s1PRS << _PCNT_INPUT_S1PRSSEL_SHIFT);
00478 pcnt->INPUT = tmp;
00479 #endif
00480
00481
00482 tmp = 0;
00483 if (init->negEdge)
00484 {
00485 tmp |= PCNT_CTRL_EDGE_NEG;
00486 }
00487
00488 if (init->countDown)
00489 {
00490 tmp |= PCNT_CTRL_CNTDIR_DOWN;
00491 }
00492
00493 if (init->filter)
00494 {
00495 tmp |= PCNT_CTRL_FILT;
00496 }
00497
00498 #if defined( PCNT_CTRL_HYST )
00499 if (init->hyst)
00500 {
00501 tmp |= PCNT_CTRL_HYST;
00502 }
00503 #endif
00504
00505 #if defined( PCNT_CTRL_S1CDIR )
00506 if (init->s1CntDir)
00507 {
00508 tmp |= PCNT_CTRL_S1CDIR;
00509 }
00510 #endif
00511
00512
00513 #if defined( _PCNT_CTRL_CNTEV_SHIFT )
00514 tmp |= init->cntEvent << _PCNT_CTRL_CNTEV_SHIFT;
00515 #endif
00516
00517 #if defined( _PCNT_CTRL_AUXCNTEV_SHIFT )
00518 {
00519
00520
00521
00522
00523
00524 uint32_t auxCntEventField = 0;
00525 switch (init->auxCntEvent)
00526 {
00527 case pcntCntEventBoth:
00528 auxCntEventField = pcntCntEventNone;
00529 break;
00530 case pcntCntEventNone:
00531 auxCntEventField = pcntCntEventBoth;
00532 break;
00533 case pcntCntEventUp:
00534 case pcntCntEventDown:
00535 auxCntEventField = init->auxCntEvent;
00536 break;
00537 default:
00538
00539 EFM_ASSERT(0);
00540 }
00541 tmp |= auxCntEventField << _PCNT_CTRL_AUXCNTEV_SHIFT;
00542 }
00543 #endif
00544
00545
00546
00547 BITBAND_Peripheral(&(pcnt->CTRL), _PCNT_CTRL_RSTEN_SHIFT, 1);
00548
00549
00550 CMU_PCNTClockExternalSet(inst, false);
00551
00552
00553 switch (init->mode)
00554 {
00555 case pcntModeExtSingle:
00556 case pcntModeExtQuad:
00557 tmp |= init->mode << _PCNT_CTRL_MODE_SHIFT;
00558
00559
00560
00561
00562
00563 PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL);
00564
00565
00566
00567 pcnt->CTRL = PCNT_CTRL_RSTEN;
00568
00569
00570 PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL);
00571
00572
00573 CMU_PCNTClockExternalSet(inst, true);
00574
00575
00576
00577
00578
00579 pcnt->TOPB = init->top;
00580
00581
00582 pcnt->CMD = PCNT_CMD_LTOPBIM;
00583
00584
00585
00586
00587
00588 pcnt->CTRL = tmp;
00589
00590
00591
00592
00593
00594 break;
00595
00596
00597
00598 default:
00599
00600 if ((pcnt->CTRL & _PCNT_CTRL_MODE_MASK) != PCNT_CTRL_MODE_DISABLE)
00601 {
00602
00603
00604
00605 pcnt->CTRL = tmp | PCNT_CTRL_MODE_DISABLE | PCNT_CTRL_RSTEN;
00606
00607
00608
00609 PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL);
00610 }
00611
00612
00613 BITBAND_Peripheral(&(pcnt->CTRL), _PCNT_CTRL_RSTEN_SHIFT, 0);
00614
00615
00616 PCNT_CounterTopSet(pcnt, init->counter, init->top);
00617
00618
00619 if (init->mode == pcntModeOvsSingle)
00620 {
00621 PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL);
00622 pcnt->CTRL = tmp | (init->mode << _PCNT_CTRL_MODE_SHIFT);
00623 }
00624 break;
00625 }
00626 }
00627
00628
00629
00645 void PCNT_Reset(PCNT_TypeDef *pcnt)
00646 {
00647 unsigned int inst;
00648
00649 EFM_ASSERT(PCNT_REF_VALID(pcnt));
00650
00651
00652 inst = PCNT_Map(pcnt);
00653
00654 pcnt->IEN = _PCNT_IEN_RESETVALUE;
00655
00656
00657
00658
00659
00660
00661 BITBAND_Peripheral(&(pcnt->CTRL), _PCNT_CTRL_RSTEN_SHIFT, 1);
00662
00663
00664 CMU_PCNTClockExternalSet(inst, false);
00665
00666 PCNT_TopBufferSet(pcnt, _PCNT_TOPB_RESETVALUE);
00667
00668
00669 pcnt->CTRL = _PCNT_CTRL_RESETVALUE | PCNT_CTRL_RSTEN;
00670
00671
00672 PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL);
00673 BITBAND_Peripheral(&(pcnt->CTRL), _PCNT_CTRL_RSTEN_SHIFT, 0);
00674
00675
00676 pcnt->IFC = _PCNT_IFC_MASK;
00677
00678
00679 }
00680
00681
00682
00698 void PCNT_TopBufferSet(PCNT_TypeDef *pcnt, uint32_t val)
00699 {
00700 EFM_ASSERT(PCNT_REF_VALID(pcnt));
00701
00702
00703 PCNT_Sync(pcnt, PCNT_SYNCBUSY_TOPB);
00704 pcnt->TOPB = val;
00705 }
00706
00707
00708
00724 void PCNT_TopSet(PCNT_TypeDef *pcnt, uint32_t val)
00725 {
00726 EFM_ASSERT(PCNT_REF_VALID(pcnt));
00727
00728 #ifdef PCNT0
00729 if (PCNT0 == pcnt)
00730 {
00731 EFM_ASSERT((1<<PCNT0_CNT_SIZE) > val);
00732 }
00733 #endif
00734
00735 #ifdef PCNT1
00736 if (PCNT1 == pcnt)
00737 {
00738 EFM_ASSERT((1<<PCNT1_CNT_SIZE) > val);
00739 }
00740 #endif
00741
00742 #ifdef PCNT2
00743 if (PCNT2 == pcnt)
00744 {
00745 EFM_ASSERT((1<<PCNT2_CNT_SIZE) > val);
00746 }
00747 #endif
00748
00749
00750
00751
00752 PCNT_Sync(pcnt, PCNT_SYNCBUSY_TOPB);
00753 pcnt->TOPB = val;
00754
00755
00756 PCNT_Sync(pcnt, PCNT_SYNCBUSY_TOPB | PCNT_SYNCBUSY_CMD);
00757 pcnt->CMD = PCNT_CMD_LTOPBIM;
00758 }
00759
00760
00763 #endif