em_lesense.c

Go to the documentation of this file.
00001 /***************************************************************************/
00034 #include "em_lesense.h"
00035 #if defined(LESENSE_COUNT) && (LESENSE_COUNT > 0)
00036 #include "em_assert.h"
00037 #include "em_bitband.h"
00038 #include "em_cmu.h"
00039 
00041 #ifndef UINT32_MAX
00042 #define UINT32_MAX ((uint32_t)(0xFFFFFFFF))
00043 #endif
00044 
00046 /***************************************************************************/
00051 /***************************************************************************/
00057 /*******************************************************************************
00058  **************************   LOCAL FUNCTIONS   ********************************
00059  ******************************************************************************/
00060 
00061 
00062 /*******************************************************************************
00063  **************************   GLOBAL FUNCTIONS   *******************************
00064  ******************************************************************************/
00065 
00066 /***************************************************************************/
00097 void LESENSE_Init(LESENSE_Init_TypeDef const *init, bool const reqReset)
00098 {
00099   /* Sanity check of initialization values */
00100   EFM_ASSERT((uint32_t)init->timeCtrl.startDelay < 4U);
00101   EFM_ASSERT((uint32_t)init->perCtrl.dacPresc < 32U);
00102 
00103   /* Reset LESENSE registers if requested. */
00104   if (reqReset)
00105   {
00106     LESENSE_Reset();
00107   }
00108 
00109   /* Set sensor start delay for each channel. */
00110   LESENSE_StartDelaySet((uint32_t)init->timeCtrl.startDelay);
00111 
00112   /* LESENSE core control configuration.
00113    * Set PRS source, SCANCONF register usage strategy, interrupt and
00114    * DMA trigger level condition, DMA wakeup condition, bias mode,
00115    * enable/disable to sample both ACMPs simultaneously, enable/disable to store
00116    * SCANRES in CNT_RES after each scan, enable/disable to always write to the
00117    * result buffer, even if it is full, enable/disable LESENSE running in debug
00118    * mode. */
00119   LESENSE->CTRL = ((uint32_t)init->coreCtrl.prsSel <<
00120                    _LESENSE_CTRL_PRSSEL_SHIFT) |
00121                   (uint32_t)init->coreCtrl.scanConfSel |
00122                   (uint32_t)init->coreCtrl.bufTrigLevel |
00123                   (uint32_t)init->coreCtrl.wakeupOnDMA |
00124                   ((uint32_t)init->coreCtrl.invACMP0 <<
00125                    _LESENSE_CTRL_ACMP0INV_SHIFT) |
00126                   ((uint32_t)init->coreCtrl.invACMP1 <<
00127                    _LESENSE_CTRL_ACMP1INV_SHIFT) |
00128                   ((uint32_t)init->coreCtrl.dualSample <<
00129                    _LESENSE_CTRL_DUALSAMPLE_SHIFT) |
00130                   ((uint32_t)init->coreCtrl.storeScanRes <<
00131                    _LESENSE_CTRL_STRSCANRES_SHIFT) |
00132                   ((uint32_t)init->coreCtrl.bufOverWr <<
00133                    _LESENSE_CTRL_BUFOW_SHIFT) |
00134                   ((uint32_t)init->coreCtrl.debugRun <<
00135                    _LESENSE_CTRL_DEBUGRUN_SHIFT);
00136 
00137   /* Set scan mode in the CTRL register using the provided function, don't
00138    * start scanning immediately. */
00139   LESENSE_ScanModeSet((LESENSE_ScanMode_TypeDef)init->coreCtrl.scanStart, false);
00140 
00141   /* LESENSE peripheral control configuration.
00142    * Set DAC0 and DAC1 data source, conversion mode, output mode. Set DAC
00143    * prescaler and reference. Set ACMP0 and ACMP1 control mode. Set ACMP and DAC
00144    * duty cycle (warm up) mode. */
00145   LESENSE->PERCTRL = ((uint32_t)init->perCtrl.dacCh0Data <<
00146                       _LESENSE_PERCTRL_DACCH0DATA_SHIFT) |
00147                      ((uint32_t)init->perCtrl.dacCh0ConvMode <<
00148                       _LESENSE_PERCTRL_DACCH0CONV_SHIFT) |
00149                      ((uint32_t)init->perCtrl.dacCh0OutMode <<
00150                       _LESENSE_PERCTRL_DACCH0OUT_SHIFT) |
00151                      ((uint32_t)init->perCtrl.dacCh1Data <<
00152                       _LESENSE_PERCTRL_DACCH1DATA_SHIFT) |
00153                      ((uint32_t)init->perCtrl.dacCh1ConvMode <<
00154                       _LESENSE_PERCTRL_DACCH1CONV_SHIFT) |
00155                      ((uint32_t)init->perCtrl.dacCh1OutMode <<
00156                       _LESENSE_PERCTRL_DACCH1OUT_SHIFT) |
00157                      ((uint32_t)init->perCtrl.dacPresc <<
00158                       _LESENSE_PERCTRL_DACPRESC_SHIFT) |
00159                      (uint32_t)init->perCtrl.dacRef |
00160                      ((uint32_t)init->perCtrl.acmp0Mode <<
00161                       _LESENSE_PERCTRL_ACMP0MODE_SHIFT) |
00162                      ((uint32_t)init->perCtrl.acmp1Mode <<
00163                       _LESENSE_PERCTRL_ACMP1MODE_SHIFT) |
00164                      (uint32_t)init->perCtrl.warmupMode;
00165 
00166   /* LESENSE decoder general control configuration.
00167    * Set decoder input source, select PRS input for decoder bits.
00168    * Enable/disable the decoder to check the present state.
00169    * Enable/disable decoder to channel interrupt mapping.
00170    * Enable/disable decoder hysteresis on PRS output.
00171    * Enable/disable decoder hysteresis on count events.
00172    * Enable/disable decoder hysteresis on interrupt requests.
00173    * Enable/disable count mode on LESPRS0 and LESPRS1. */
00174   LESENSE->DECCTRL = (uint32_t)init->decCtrl.decInput |
00175                      ((uint32_t)init->decCtrl.prsChSel0 <<
00176                       _LESENSE_DECCTRL_PRSSEL0_SHIFT) |
00177                      ((uint32_t)init->decCtrl.prsChSel1 <<
00178                       _LESENSE_DECCTRL_PRSSEL1_SHIFT) |
00179                      ((uint32_t)init->decCtrl.prsChSel2 <<
00180                       _LESENSE_DECCTRL_PRSSEL2_SHIFT) |
00181                      ((uint32_t)init->decCtrl.prsChSel3 <<
00182                       _LESENSE_DECCTRL_PRSSEL3_SHIFT) |
00183                      ((uint32_t)init->decCtrl.chkState <<
00184                       _LESENSE_DECCTRL_ERRCHK_SHIFT) |
00185                      ((uint32_t)init->decCtrl.intMap <<
00186                       _LESENSE_DECCTRL_INTMAP_SHIFT) |
00187                      ((uint32_t)init->decCtrl.hystPRS0 <<
00188                       _LESENSE_DECCTRL_HYSTPRS0_SHIFT) |
00189                      ((uint32_t)init->decCtrl.hystPRS1 <<
00190                       _LESENSE_DECCTRL_HYSTPRS1_SHIFT) |
00191                      ((uint32_t)init->decCtrl.hystPRS2 <<
00192                       _LESENSE_DECCTRL_HYSTPRS2_SHIFT) |
00193                      ((uint32_t)init->decCtrl.hystIRQ <<
00194                       _LESENSE_DECCTRL_HYSTIRQ_SHIFT) |
00195                      ((uint32_t)init->decCtrl.prsCount <<
00196                       _LESENSE_DECCTRL_PRSCNT_SHIFT);
00197 
00198   /* Set initial LESENSE decoder state. */
00199   LESENSE_DecoderStateSet((uint32_t)init->decCtrl.initState);
00200 
00201   /* LESENSE bias control configuration. */
00202   LESENSE->BIASCTRL = (uint32_t)init->coreCtrl.biasMode;
00203 }
00204 
00205 
00206 /***************************************************************************/
00232 uint32_t LESENSE_ScanFreqSet(uint32_t refFreq, uint32_t const scanFreq)
00233 {
00234   uint32_t tmp;
00235   uint32_t pcPresc = 0UL;  /* Period counter prescaler. */
00236   uint32_t clkDiv  = 1UL;  /* Clock divisor value (2^pcPresc). */
00237   uint32_t pcTop   = 63UL; /* Period counter top value (max. 63). */
00238   uint32_t calcScanFreq;   /* Variable for testing the calculation algorithm. */
00239 
00240 
00241   /* If refFreq is set to 0, the currently configured reference clock is
00242    * assumed. */
00243   if (!refFreq)
00244   {
00245     refFreq = CMU_ClockFreqGet(cmuClock_LESENSE);
00246   }
00247 
00248   /* Max. value of pcPresc is 128, thus using reference frequency less than
00249    * 33554431Hz (33.554431MHz), the frequency calculation in the while loop
00250    * below will not overflow. */
00251   EFM_ASSERT(refFreq < ((uint32_t)UINT32_MAX / 128UL));
00252 
00253   /* Sanity check of scan frequency value. */
00254   EFM_ASSERT((scanFreq > 0U) && (scanFreq <= refFreq));
00255 
00256   /* Calculate the minimum necessary prescaler value in order to provide the
00257    * biggest possible resolution for setting scan frequency.
00258    * Maximum number of calculation cycles is 7 (value of lesenseClkDiv_128). */
00259   while ((refFreq / ((uint32_t)scanFreq * clkDiv) > (pcTop + 1UL)) &&
00260          (pcPresc < lesenseClkDiv_128))
00261   {
00262     ++pcPresc;
00263     clkDiv = (uint32_t)1UL << pcPresc;
00264   }
00265 
00266   /* Calculate pcTop value. */
00267   pcTop = ((uint32_t)refFreq / ((uint32_t)scanFreq * clkDiv)) - 1UL;
00268 
00269   /* Clear current PCPRESC and PCTOP settings. Be aware of the effect of
00270    * non-atomic Read-Modify-Write on LESENSE->TIMCRTL. */
00271   tmp = LESENSE->TIMCTRL & (~(_LESENSE_TIMCTRL_PCPRESC_MASK)&
00272                             ~(_LESENSE_TIMCTRL_PCTOP_MASK));
00273 
00274   /* Set new values in tmp while reserving other settings. */
00275   tmp |= ((uint32_t)pcPresc << _LESENSE_TIMCTRL_PCPRESC_SHIFT) |
00276          ((uint32_t)pcTop << _LESENSE_TIMCTRL_PCTOP_SHIFT);
00277 
00278   /* Set values in LESENSE_TIMCTRL register. */
00279   LESENSE->TIMCTRL = tmp;
00280 
00281   /* For testing the calculation algorithm. */
00282   calcScanFreq = ((uint32_t)refFreq / ((uint32_t)(1UL + pcTop) * clkDiv));
00283 
00284   return calcScanFreq;
00285 }
00286 
00287 
00288 /***************************************************************************/
00314 void LESENSE_ScanModeSet(LESENSE_ScanMode_TypeDef const scanMode,
00315                          bool const start)
00316 {
00317   uint32_t tmp; /* temporary storage of the CTRL register value */
00318 
00319 
00320   /* Save the CTRL register value to tmp.
00321    * Please be aware the effects of the non-atomic Read-Modify-Write cycle! */
00322   tmp = LESENSE->CTRL & ~(_LESENSE_CTRL_SCANMODE_MASK);
00323   /* Setting the requested scanMode to the CTRL register. Casting signed int
00324    * (enum) to unsigned long (uint32_t). */
00325   tmp |= (uint32_t)scanMode;
00326 
00327   /* Write the new value to the CTRL register. */
00328   LESENSE->CTRL = tmp;
00329 
00330   /* Start sensor scanning if requested. */
00331   if (start)
00332   {
00333     LESENSE_ScanStart();
00334   }
00335 }
00336 
00337 
00338 /***************************************************************************/
00356 void LESENSE_StartDelaySet(uint8_t const startDelay)
00357 {
00358   uint32_t tmp; /* temporary storage of the TIMCTRL register value */
00359 
00360 
00361   /* Sanity check of startDelay. */
00362   EFM_ASSERT(startDelay < 4U);
00363 
00364   /* Save the TIMCTRL register value to tmp.
00365    * Please be aware the effects of the non-atomic Read-Modify-Write cycle! */
00366   tmp = LESENSE->TIMCTRL & ~(_LESENSE_TIMCTRL_STARTDLY_MASK);
00367   /* Setting the requested startDelay to the TIMCTRL register. */
00368   tmp |= (uint32_t)startDelay << _LESENSE_TIMCTRL_STARTDLY_SHIFT;
00369 
00370   /* Write the new value to the TIMCTRL register. */
00371   LESENSE->TIMCTRL = tmp;
00372 }
00373 
00374 
00375 /***************************************************************************/
00399 void LESENSE_ClkDivSet(LESENSE_ChClk_TypeDef const clk,
00400                        LESENSE_ClkPresc_TypeDef const clkDiv)
00401 {
00402   uint32_t tmp;
00403 
00404 
00405   /* Select clock to prescale */
00406   switch (clk)
00407   {
00408   case lesenseClkHF:
00409   {
00410     /* Sanity check of clock divisor for HF clock. */
00411     EFM_ASSERT((uint32_t)clkDiv <= lesenseClkDiv_8);
00412 
00413     /* Clear current AUXPRESC settings. */
00414     tmp = LESENSE->TIMCTRL & ~(_LESENSE_TIMCTRL_AUXPRESC_MASK);
00415 
00416     /* Set new values in tmp while reserving other settings. */
00417     tmp |= ((uint32_t)clkDiv << _LESENSE_TIMCTRL_AUXPRESC_SHIFT);
00418 
00419     /* Set values in LESENSE_TIMCTRL register. */
00420     LESENSE->TIMCTRL = tmp;
00421   }
00422   break;
00423 
00424   case lesenseClkLF:
00425   {
00426     /* Clear current LFPRESC settings. */
00427     tmp = LESENSE->TIMCTRL & ~(_LESENSE_TIMCTRL_LFPRESC_MASK);
00428 
00429     /* Set new values in tmp while reserving other settings. */
00430     tmp |= ((uint32_t)clkDiv << _LESENSE_TIMCTRL_LFPRESC_SHIFT);
00431 
00432     /* Set values in LESENSE_TIMCTRL register. */
00433     LESENSE->TIMCTRL = tmp;
00434   }
00435   break;
00436 
00437   default:
00438   {
00439     EFM_ASSERT(0);
00440   }
00441   break;
00442   }
00443 }
00444 
00445 
00446 /***************************************************************************/
00467 void LESENSE_ChannelAllConfig(LESENSE_ChAll_TypeDef const *confChAll)
00468 {
00469   uint32_t i;
00470 
00471 
00472   /* Iterate through all the 16 channels */
00473   for (i = 0U; i < 16U; ++i)
00474   {
00475     /* Configure scan channels. */
00476     LESENSE_ChannelConfig(&confChAll->Ch[i], i);
00477   }
00478 }
00479 
00480 
00481 /***************************************************************************/
00503 void LESENSE_ChannelConfig(LESENSE_ChDesc_TypeDef const *confCh,
00504                            uint32_t const chIdx)
00505 {
00506   uint32_t tmp; /* Service variable. */
00507 
00508 
00509   /* Sanity check of configuration parameters */
00510   EFM_ASSERT(chIdx < 16U);
00511   EFM_ASSERT(confCh->exTime < 64U);
00512   EFM_ASSERT(confCh->sampleDelay < 128U);
00513   EFM_ASSERT(confCh->measDelay < 128U);
00514   /* Not a complete assert, as the max. value of acmpThres depends on other
00515    * configuration parameters, check the parameter description of acmpThres for
00516    * for more details! */
00517   EFM_ASSERT(confCh->acmpThres < 4096U);
00518   EFM_ASSERT(!(confCh->chPinExMode == lesenseChPinExDACOut &&
00519                (chIdx != 2U) && (chIdx != 3U) && (chIdx != 4U) && (chIdx != 5U)));
00520   EFM_ASSERT(!(confCh->chPinIdleMode == lesenseChPinIdleDACCh1 &&
00521                ((chIdx != 12U) && (chIdx != 13U) && (chIdx != 14U) && (chIdx != 15U))));
00522   EFM_ASSERT(!(confCh->chPinIdleMode == lesenseChPinIdleDACCh0 &&
00523                ((chIdx != 0U) && (chIdx != 1U) && (chIdx != 2U) && (chIdx != 3U))));
00524 
00525 
00526   /* Configure chIdx setup in LESENSE idle phase.
00527    * Read-modify-write in order to support reconfiguration during LESENSE
00528    * operation. */
00529   tmp               = (LESENSE->IDLECONF & ~((uint32_t)0x3UL << (chIdx * 2UL)));
00530   tmp              |= ((uint32_t)confCh->chPinIdleMode << (chIdx * 2UL));
00531   LESENSE->IDLECONF = tmp;
00532 
00533   /* Channel specific timing configuration on scan channel chIdx.
00534    * Set excitation time, sampling delay, measurement delay. */
00535   LESENSE_ChannelTimingSet(chIdx,
00536                            (uint32_t)confCh->exTime,
00537                            (uint32_t)confCh->sampleDelay,
00538                            (uint32_t)confCh->measDelay);
00539 
00540   /* Channel specific configuration of clocks, sample mode, excitation pin mode
00541    * alternate excitation usage and interrupt mode on scan channel chIdx in
00542    * LESENSE_CHchIdx_INTERACT. */
00543   LESENSE->CH[chIdx].INTERACT = ((uint32_t)confCh->exClk << 
00544                                  _LESENSE_CH_INTERACT_EXCLK_SHIFT) |
00545                                 ((uint32_t)confCh->sampleClk <<
00546                                  _LESENSE_CH_INTERACT_SAMPLECLK_SHIFT) |
00547                                 (uint32_t)confCh->sampleMode |
00548                                 (uint32_t)confCh->intMode |
00549                                 (uint32_t)confCh->chPinExMode |
00550                                 ((uint32_t)confCh->useAltEx <<
00551                                  _LESENSE_CH_INTERACT_ALTEX_SHIFT);
00552 
00553   /* Configure channel specific counter comparison mode, optional result
00554    * forwarding to decoder, optional counter value storing and optional result
00555    * inverting on scan channel chIdx in LESENSE_CHchIdx_EVAL. */
00556   LESENSE->CH[chIdx].EVAL = (uint32_t)confCh->compMode |
00557                             ((uint32_t)confCh->shiftRes <<
00558                              _LESENSE_CH_EVAL_DECODE_SHIFT) |
00559                             ((uint32_t)confCh->storeCntRes <<
00560                              _LESENSE_CH_EVAL_STRSAMPLE_SHIFT) |
00561                             ((uint32_t)confCh->invRes <<
00562                              _LESENSE_CH_EVAL_SCANRESINV_SHIFT);
00563 
00564   /* Configure analog comparator (ACMP) threshold and decision threshold for
00565    * counter separately with the function provided for that. */
00566   LESENSE_ChannelThresSet(chIdx,
00567                          (uint32_t)confCh->acmpThres,
00568                          (uint32_t)confCh->cntThres);
00569 
00570   /* Enable/disable interrupts on channel.
00571    * Note: BITBAND_Peripheral() function is used for setting/clearing single
00572    * bit peripheral register bitfields. Read the function description in
00573    * efm32_bitband.h for more details. */
00574   BITBAND_Peripheral(&(LESENSE->IEN),
00575                      (uint32_t)chIdx,
00576                      (uint32_t)confCh->enaInt);
00577 
00578   /* Enable/disable CHchIdx pin. */
00579   BITBAND_Peripheral(&(LESENSE->ROUTE),
00580                      (uint32_t)chIdx,
00581                      (uint32_t)confCh->enaPin);
00582 
00583   /* Enable/disable scan channel chIdx. */
00584   BITBAND_Peripheral(&(LESENSE->CHEN),
00585                      (uint32_t)chIdx,
00586                      (uint32_t)confCh->enaScanCh);
00587 }
00588 
00589 
00590 /***************************************************************************/
00607 void LESENSE_AltExConfig(LESENSE_ConfAltEx_TypeDef const *confAltEx)
00608 {
00609   uint32_t i;
00610   uint32_t tmp;
00611 
00612 
00613   /* Configure alternate excitation mapping.
00614    * Atomic read-modify-write using BITBAND_Peripheral function in order to
00615    * support reconfiguration during LESENSE operation. */
00616   BITBAND_Peripheral(&(LESENSE->CTRL),
00617                      _LESENSE_CTRL_ALTEXMAP_SHIFT,
00618                      (uint32_t)confAltEx->altExMap);
00619 
00620   switch (confAltEx->altExMap)
00621   {
00622   case lesenseAltExMapALTEX:
00623     /* Iterate through the 8 possible alternate excitation pin descriptors. */
00624     for (i = 0U; i < 8U; ++i)
00625     {
00626       /* Enable/disable alternate excitation pin i.
00627        * Atomic read-modify-write using BITBAND_Peripheral function in order to
00628        * support reconfiguration during LESENSE operation. */
00629       BITBAND_Peripheral(&(LESENSE->ROUTE),
00630                          (16UL + i),
00631                          (uint32_t)confAltEx->AltEx[i].enablePin);
00632  
00633       /* Setup the idle phase state of alternate excitation pin i.
00634        * Read-modify-write in order to support reconfiguration during LESENSE
00635        * operation. */
00636       tmp                = (LESENSE->ALTEXCONF & ~((uint32_t)0x3UL << (i * 2UL)));
00637       tmp               |= ((uint32_t)confAltEx->AltEx[i].idleConf << (i * 2UL));
00638       LESENSE->ALTEXCONF = tmp;
00639       
00640       /* Enable/disable always excite on channel i */
00641       BITBAND_Peripheral(&(LESENSE->ALTEXCONF),
00642                          (16UL + i),
00643                          (uint32_t)confAltEx->AltEx[i].alwaysEx);
00644     }
00645     break;
00646 
00647   case lesenseAltExMapACMP:
00648     /* Iterate through all the 16 alternate excitation channels */
00649     for (i = 0U; i < 16U; ++i)
00650     {
00651       /* Enable/disable alternate ACMP excitation channel pin i. */
00652       /* Atomic read-modify-write using BITBAND_Peripheral function in order to
00653        * support reconfiguration during LESENSE operation. */
00654       BITBAND_Peripheral(&(LESENSE->ROUTE),
00655                          i,
00656                          (uint32_t)confAltEx->AltEx[i].enablePin);
00657     }
00658     break;
00659   default:
00660     /* Illegal value. */
00661     EFM_ASSERT(0);
00662   }
00663 }
00664 
00665 
00666 /***************************************************************************/
00690 void LESENSE_ChannelEnable(uint8_t const chIdx,
00691                            bool const enaScanCh,
00692                            bool const enaPin)
00693 {
00694   /* Enable/disable the assigned pin of scan channel chIdx.
00695    * Note: BITBAND_Peripheral() function is used for setting/clearing single
00696    * bit peripheral register bitfields. Read the function description in
00697    * efm32_bitband.h for more details. */
00698   BITBAND_Peripheral(&(LESENSE->ROUTE),
00699                      (uint32_t)chIdx,
00700                      (uint32_t)enaPin);
00701 
00702   /* Enable/disable scan channel chIdx. */
00703   BITBAND_Peripheral(&(LESENSE->CHEN),
00704                      (uint32_t)chIdx,
00705                      (uint32_t)enaScanCh);
00706 }
00707 
00708 
00709 /***************************************************************************/
00731 void LESENSE_ChannelEnableMask(uint16_t chMask, uint16_t pinMask)
00732 {
00733   /* Enable/disable all channels at once according to the mask. */
00734   LESENSE->CHEN = chMask;
00735   /* Enable/disable all channel pins at once according to the mask. */
00736   LESENSE->ROUTE = pinMask;
00737 }
00738 
00739 
00740 /***************************************************************************/
00768 void LESENSE_ChannelTimingSet(uint8_t const chIdx,
00769                               uint8_t const exTime,
00770                               uint8_t const sampleDelay,
00771                               uint8_t const measDelay)
00772 {
00773   /* Sanity check of parameters. */
00774   EFM_ASSERT(exTime < 64U);
00775   EFM_ASSERT(sampleDelay < 128U);
00776   EFM_ASSERT(measDelay < 128U);
00777 
00778   /* Channel specific timing configuration on scan channel chIdx.
00779    * Setting excitation time, sampling delay, measurement delay. */
00780   LESENSE->CH[chIdx].TIMING = ((uint32_t)exTime <<
00781                                _LESENSE_CH_TIMING_EXTIME_SHIFT) |
00782                               ((uint32_t)sampleDelay <<
00783                                _LESENSE_CH_TIMING_SAMPLEDLY_SHIFT) |
00784                               ((uint32_t)measDelay <<
00785                                _LESENSE_CH_TIMING_MEASUREDLY_SHIFT);
00786 }
00787 
00788 
00789 /***************************************************************************/
00822 void LESENSE_ChannelThresSet(uint8_t const chIdx,
00823                              uint16_t const acmpThres,
00824                              uint16_t const cntThres)
00825 {
00826   uint32_t tmp; /* temporary storage */
00827 
00828 
00829   /* Sanity check for acmpThres only, cntThres is 16bit value. */
00830   EFM_ASSERT(acmpThres < 4096U);
00831   /* Sanity check for LESENSE channel id. */
00832   EFM_ASSERT(chIdx < 16);
00833 
00834   /* Save the INTERACT register value of channel chIdx to tmp.
00835    * Please be aware the effects of the non-atomic Read-Modify-Write cycle! */
00836   tmp = LESENSE->CH[chIdx].INTERACT & ~(_LESENSE_CH_INTERACT_ACMPTHRES_MASK);
00837   /* Set the ACMP threshold value to the INTERACT register of channel chIdx. */
00838   tmp |= (uint32_t)acmpThres << _LESENSE_CH_INTERACT_ACMPTHRES_SHIFT;
00839   /* Write the new value to the INTERACT register. */
00840   LESENSE->CH[chIdx].INTERACT = tmp;
00841 
00842   /* Save the EVAL register value of channel chIdx to tmp.
00843    * Please be aware the effects of the non-atomic Read-Modify-Write cycle! */
00844   tmp = LESENSE->CH[chIdx].EVAL & ~(_LESENSE_CH_EVAL_COMPTHRES_MASK);
00845   /* Set the counter threshold value to the INTERACT register of channel chIdx. */
00846   tmp |= (uint32_t)cntThres << _LESENSE_CH_EVAL_COMPTHRES_SHIFT;
00847   /* Write the new value to the EVAL register. */
00848   LESENSE->CH[chIdx].EVAL = tmp;
00849 }
00850 
00851 
00852 /***************************************************************************/
00868 void LESENSE_DecoderStateAllConfig(LESENSE_DecStAll_TypeDef const *confDecStAll)
00869 {
00870   uint32_t i;
00871 
00872 
00873   /* Iterate through all the 16 decoder states. */
00874   for (i = 0U; i < 16U; ++i)
00875   {
00876     /* Configure decoder state i. */
00877     LESENSE_DecoderStateConfig(&confDecStAll->St[i], i);
00878   }
00879 }
00880 
00881 
00882 /***************************************************************************/
00897 void LESENSE_DecoderStateConfig(LESENSE_DecStDesc_TypeDef const *confDecSt,
00898                                 uint32_t const decSt)
00899 {
00900   /* Sanity check of configuration parameters */
00901   EFM_ASSERT(decSt < 16U);
00902   EFM_ASSERT((uint32_t)confDecSt->confA.compMask < 16U);
00903   EFM_ASSERT((uint32_t)confDecSt->confA.compVal < 16U);
00904   EFM_ASSERT((uint32_t)confDecSt->confA.nextState < 16U);
00905   EFM_ASSERT((uint32_t)confDecSt->confB.compMask < 16U);
00906   EFM_ASSERT((uint32_t)confDecSt->confB.compVal < 16U);
00907   EFM_ASSERT((uint32_t)confDecSt->confB.nextState < 16U);
00908 
00909   /* Configure state descriptor A (LESENSE_STi_TCONFA) for decoder state i.
00910    * Setting sensor compare value, sensor mask, next state index,
00911    * transition action, interrupt flag option and state descriptor chaining
00912    * configurations. */
00913   LESENSE->ST[decSt].TCONFA = (uint32_t)confDecSt->confA.prsAct |
00914                               ((uint32_t)confDecSt->confA.compMask <<
00915                                _LESENSE_ST_TCONFA_MASK_SHIFT) |
00916                               ((uint32_t)confDecSt->confA.compVal <<
00917                                _LESENSE_ST_TCONFA_COMP_SHIFT) |
00918                               ((uint32_t)confDecSt->confA.nextState <<
00919                                _LESENSE_ST_TCONFA_NEXTSTATE_SHIFT) |
00920                               ((uint32_t)confDecSt->confA.setInt <<
00921                                _LESENSE_ST_TCONFA_SETIF_SHIFT) |
00922                               ((uint32_t)confDecSt->chainDesc <<
00923                                _LESENSE_ST_TCONFA_CHAIN_SHIFT);
00924 
00925   /* Configure state descriptor Bi (LESENSE_STi_TCONFB).
00926    * Setting sensor compare value, sensor mask, next state index, transition
00927    * action and interrupt flag option configurations. */
00928   LESENSE->ST[decSt].TCONFB = (uint32_t)confDecSt->confB.prsAct |
00929                               ((uint32_t)confDecSt->confB.compMask <<
00930                                _LESENSE_ST_TCONFB_MASK_SHIFT) |
00931                               ((uint32_t)confDecSt->confB.compVal <<
00932                                _LESENSE_ST_TCONFB_COMP_SHIFT) |
00933                               ((uint32_t)confDecSt->confB.nextState <<
00934                                _LESENSE_ST_TCONFB_NEXTSTATE_SHIFT) |
00935                               ((uint32_t)confDecSt->confB.setInt <<
00936                                _LESENSE_ST_TCONFB_SETIF_SHIFT);
00937 }
00938 
00939 
00940 /***************************************************************************/
00955 void LESENSE_DecoderStateSet(uint32_t decSt)
00956 {
00957   EFM_ASSERT(decSt < 16U);
00958 
00959   LESENSE->DECSTATE = decSt & _LESENSE_DECSTATE_DECSTATE_MASK;
00960 }
00961 
00962 
00963 /***************************************************************************/
00971 uint32_t LESENSE_DecoderStateGet(void)
00972 {
00973   return LESENSE->DECSTATE & _LESENSE_DECSTATE_DECSTATE_MASK;
00974 }
00975 
00976 
00977 /***************************************************************************/
00990 void LESENSE_ScanStart(void)
00991 {
00992   /* Wait for any pending previous write operation to the CMD register to
00993      complete before accessing the CMD register. */
00994   while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY);
00995 
00996   /* Start scanning of sensors */
00997   LESENSE->CMD = LESENSE_CMD_START;
00998 
00999   /* Wait for the write operation to the CMD register to complete before
01000      returning. */
01001   while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY);
01002 }
01003 
01004 
01005 /***************************************************************************/
01021 void LESENSE_ScanStop(void)
01022 {
01023   /* Wait for any pending previous write operation to the CMD register to
01024      complete before accessing the CMD register. */
01025   while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY);
01026 
01027   /* Stop scanning of sensors */
01028   LESENSE->CMD = LESENSE_CMD_STOP;
01029 
01030   /* Wait for the write operation to the CMD register to complete before
01031      returning. */
01032   while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY);
01033 }
01034 
01035 
01036 /***************************************************************************/
01049 void LESENSE_DecoderStart(void)
01050 {
01051   /* Wait for any pending previous write operation to the CMD register to
01052      complete before accessing the CMD register. */
01053   while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY);
01054 
01055   /* Start decoder */
01056   LESENSE->CMD = LESENSE_CMD_DECODE;
01057 
01058   /* Wait for the write operation to the CMD register to complete before
01059      returning. */
01060   while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY);
01061 }
01062 
01063 
01064 /***************************************************************************/
01077 void LESENSE_ResultBufferClear(void)
01078 {
01079   /* Wait for any pending previous write operation to the CMD register to
01080      complete before accessing the CMD register. */
01081   while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY);
01082 
01083   LESENSE->CMD = LESENSE_CMD_CLEARBUF;
01084 
01085   /* Wait for the write operation to the CMD register to complete before
01086      returning. */
01087   while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY);
01088 }
01089 
01090 
01091 /***************************************************************************/
01104 void LESENSE_Reset(void)
01105 {
01106   uint32_t i;
01107 
01108 
01109   /* Disable all LESENSE interrupts first */
01110   LESENSE->IEN = _LESENSE_IEN_RESETVALUE;
01111 
01112   /* Clear all pending LESENSE interrupts */
01113   LESENSE->IFC = _LESENSE_IFC_MASK;
01114 
01115   /* Stop the decoder */
01116   LESENSE->DECCTRL |= LESENSE_DECCTRL_DISABLE;
01117 
01118   /* Wait for any pending previous write operation to the CMD register to
01119      complete before accessing the CMD register. */
01120   while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY);
01121   /* Stop sensor scan and clear result buffer */
01122   LESENSE->CMD = (LESENSE_CMD_STOP | LESENSE_CMD_CLEARBUF);
01123 
01124   /* Reset LESENSE configuration registers */
01125   LESENSE->CTRL      = _LESENSE_CTRL_RESETVALUE;
01126   LESENSE->PERCTRL   = _LESENSE_PERCTRL_RESETVALUE;
01127   LESENSE->DECCTRL   = _LESENSE_DECCTRL_RESETVALUE;
01128   LESENSE->BIASCTRL  = _LESENSE_BIASCTRL_RESETVALUE;
01129   LESENSE->CHEN      = _LESENSE_CHEN_RESETVALUE;
01130   LESENSE->IDLECONF  = _LESENSE_IDLECONF_RESETVALUE;
01131   LESENSE->ALTEXCONF = _LESENSE_ALTEXCONF_RESETVALUE;
01132 
01133   /* Disable LESENSE to control GPIO pins */
01134   LESENSE->ROUTE = _LESENSE_ROUTE_RESETVALUE;
01135 
01136   /* Reset all channel configuration registers */
01137   for (i = 0U; i < 16U; ++i)
01138   {
01139     LESENSE->CH[i].TIMING   = _LESENSE_CH_TIMING_RESETVALUE;
01140     LESENSE->CH[i].INTERACT = _LESENSE_CH_INTERACT_RESETVALUE;
01141     LESENSE->CH[i].EVAL     = _LESENSE_CH_EVAL_RESETVALUE;
01142   }
01143 
01144   /* Reset all decoder state configuration registers */
01145   for (i = 0U; i < 16U; ++i)
01146   {
01147     LESENSE->ST[i].TCONFA = _LESENSE_ST_TCONFA_RESETVALUE;
01148     LESENSE->ST[i].TCONFB = _LESENSE_ST_TCONFB_RESETVALUE;
01149   }
01150   /* Wait for the write operation to the CMD register to complete before
01151      returning. */
01152   while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY);
01153 }
01154 
01155 
01159 #endif /* defined(LESENSE_COUNT) && (LESENSE_COUNT > 0) */