EFM32 Zero Gecko Software Documentation  efm32zg-doc-4.2.1
em_lesense.c
Go to the documentation of this file.
1 /***************************************************************************/
33 #include "em_lesense.h"
34 #if defined(LESENSE_COUNT) && (LESENSE_COUNT > 0)
35 #include "em_assert.h"
36 #include "em_bus.h"
37 #include "em_cmu.h"
38 
40 #if !defined(UINT32_MAX)
41 #define UINT32_MAX ((uint32_t)(0xFFFFFFFF))
42 #endif
43 
45 /***************************************************************************/
50 /***************************************************************************/
56 /*******************************************************************************
57  ************************** LOCAL FUNCTIONS ********************************
58  ******************************************************************************/
59 
60 
61 /*******************************************************************************
62  ************************** GLOBAL FUNCTIONS *******************************
63  ******************************************************************************/
64 
65 /***************************************************************************/
96 void LESENSE_Init(LESENSE_Init_TypeDef const *init, bool const reqReset)
97 {
98  /* Sanity check of initialization values */
99  EFM_ASSERT((uint32_t)init->timeCtrl.startDelay < 4U);
100  EFM_ASSERT((uint32_t)init->perCtrl.dacPresc < 32U);
101 
102  /* Reset LESENSE registers if requested. */
103  if (reqReset)
104  {
105  LESENSE_Reset();
106  }
107 
108  /* Set sensor start delay for each channel. */
109  LESENSE_StartDelaySet((uint32_t)init->timeCtrl.startDelay);
110 
111  /* LESENSE core control configuration.
112  * Set PRS source, SCANCONF register usage strategy, interrupt and
113  * DMA trigger level condition, DMA wakeup condition, bias mode,
114  * enable/disable to sample both ACMPs simultaneously, enable/disable to store
115  * SCANRES in CNT_RES after each scan, enable/disable to always write to the
116  * result buffer, even if it is full, enable/disable LESENSE running in debug
117  * mode. */
118  LESENSE->CTRL =
119  ((uint32_t)init->coreCtrl.prsSel << _LESENSE_CTRL_PRSSEL_SHIFT)
120  | (uint32_t)init->coreCtrl.scanConfSel
121  | (uint32_t)init->coreCtrl.bufTrigLevel
122  | (uint32_t)init->coreCtrl.wakeupOnDMA
123  | ((uint32_t)init->coreCtrl.invACMP0 << _LESENSE_CTRL_ACMP0INV_SHIFT)
124  | ((uint32_t)init->coreCtrl.invACMP1 << _LESENSE_CTRL_ACMP1INV_SHIFT)
125  | ((uint32_t)init->coreCtrl.dualSample << _LESENSE_CTRL_DUALSAMPLE_SHIFT)
126  | ((uint32_t)init->coreCtrl.storeScanRes << _LESENSE_CTRL_STRSCANRES_SHIFT)
127  | ((uint32_t)init->coreCtrl.bufOverWr << _LESENSE_CTRL_BUFOW_SHIFT)
128  | ((uint32_t)init->coreCtrl.debugRun << _LESENSE_CTRL_DEBUGRUN_SHIFT);
129 
130  /* Set scan mode in the CTRL register using the provided function, don't
131  * start scanning immediately. */
132  LESENSE_ScanModeSet((LESENSE_ScanMode_TypeDef)init->coreCtrl.scanStart, false);
133 
134  /* LESENSE peripheral control configuration.
135  * Set DAC0 and DAC1 data source, conversion mode, output mode. Set DAC
136  * prescaler and reference. Set ACMP0 and ACMP1 control mode. Set ACMP and DAC
137  * duty cycle (warm up) mode. */
138  LESENSE->PERCTRL =
139  ((uint32_t)init->perCtrl.dacCh0Data << _LESENSE_PERCTRL_DACCH0DATA_SHIFT)
140  | ((uint32_t)init->perCtrl.dacCh0ConvMode << _LESENSE_PERCTRL_DACCH0CONV_SHIFT)
141  | ((uint32_t)init->perCtrl.dacCh0OutMode << _LESENSE_PERCTRL_DACCH0OUT_SHIFT)
142  | ((uint32_t)init->perCtrl.dacCh1Data << _LESENSE_PERCTRL_DACCH1DATA_SHIFT)
143  | ((uint32_t)init->perCtrl.dacCh1ConvMode << _LESENSE_PERCTRL_DACCH1CONV_SHIFT)
144  | ((uint32_t)init->perCtrl.dacCh1OutMode << _LESENSE_PERCTRL_DACCH1OUT_SHIFT)
145  | ((uint32_t)init->perCtrl.dacPresc << _LESENSE_PERCTRL_DACPRESC_SHIFT)
146  | (uint32_t)init->perCtrl.dacRef
147  | ((uint32_t)init->perCtrl.acmp0Mode << _LESENSE_PERCTRL_ACMP0MODE_SHIFT)
148  | ((uint32_t)init->perCtrl.acmp1Mode << _LESENSE_PERCTRL_ACMP1MODE_SHIFT)
149  | (uint32_t)init->perCtrl.warmupMode;
150 
151  /* LESENSE decoder general control configuration.
152  * Set decoder input source, select PRS input for decoder bits.
153  * Enable/disable the decoder to check the present state.
154  * Enable/disable decoder to channel interrupt mapping.
155  * Enable/disable decoder hysteresis on PRS output.
156  * Enable/disable decoder hysteresis on count events.
157  * Enable/disable decoder hysteresis on interrupt requests.
158  * Enable/disable count mode on LESPRS0 and LESPRS1. */
159  LESENSE->DECCTRL =
160  (uint32_t)init->decCtrl.decInput
161  | ((uint32_t)init->decCtrl.prsChSel0 << _LESENSE_DECCTRL_PRSSEL0_SHIFT)
162  | ((uint32_t)init->decCtrl.prsChSel1 << _LESENSE_DECCTRL_PRSSEL1_SHIFT)
163  | ((uint32_t)init->decCtrl.prsChSel2 << _LESENSE_DECCTRL_PRSSEL2_SHIFT)
164  | ((uint32_t)init->decCtrl.prsChSel3 << _LESENSE_DECCTRL_PRSSEL3_SHIFT)
165  | ((uint32_t)init->decCtrl.chkState << _LESENSE_DECCTRL_ERRCHK_SHIFT)
166  | ((uint32_t)init->decCtrl.intMap << _LESENSE_DECCTRL_INTMAP_SHIFT)
167  | ((uint32_t)init->decCtrl.hystPRS0 << _LESENSE_DECCTRL_HYSTPRS0_SHIFT)
168  | ((uint32_t)init->decCtrl.hystPRS1 << _LESENSE_DECCTRL_HYSTPRS1_SHIFT)
169  | ((uint32_t)init->decCtrl.hystPRS2 << _LESENSE_DECCTRL_HYSTPRS2_SHIFT)
170  | ((uint32_t)init->decCtrl.hystIRQ << _LESENSE_DECCTRL_HYSTIRQ_SHIFT)
171  | ((uint32_t)init->decCtrl.prsCount << _LESENSE_DECCTRL_PRSCNT_SHIFT);
172 
173  /* Set initial LESENSE decoder state. */
174  LESENSE_DecoderStateSet((uint32_t)init->decCtrl.initState);
175 
176  /* LESENSE bias control configuration. */
177  LESENSE->BIASCTRL = (uint32_t)init->coreCtrl.biasMode;
178 }
179 
180 
181 /***************************************************************************/
207 uint32_t LESENSE_ScanFreqSet(uint32_t refFreq, uint32_t const scanFreq)
208 {
209  uint32_t tmp;
210  uint32_t pcPresc = 0UL; /* Period counter prescaler. */
211  uint32_t clkDiv = 1UL; /* Clock divisor value (2^pcPresc). */
212  uint32_t pcTop = 63UL; /* Period counter top value (max. 63). */
213  uint32_t calcScanFreq; /* Variable for testing the calculation algorithm. */
214 
215 
216  /* If refFreq is set to 0, the currently configured reference clock is
217  * assumed. */
218  if (!refFreq)
219  {
220  refFreq = CMU_ClockFreqGet(cmuClock_LESENSE);
221  }
222 
223  /* Max. value of pcPresc is 128, thus using reference frequency less than
224  * 33554431Hz (33.554431MHz), the frequency calculation in the while loop
225  * below will not overflow. */
226  EFM_ASSERT(refFreq < ((uint32_t)UINT32_MAX / 128UL));
227 
228  /* Sanity check of scan frequency value. */
229  EFM_ASSERT((scanFreq > 0U) && (scanFreq <= refFreq));
230 
231  /* Calculate the minimum necessary prescaler value in order to provide the
232  * biggest possible resolution for setting scan frequency.
233  * Maximum number of calculation cycles is 7 (value of lesenseClkDiv_128). */
234  while ((refFreq / ((uint32_t)scanFreq * clkDiv) > (pcTop + 1UL))
235  && (pcPresc < lesenseClkDiv_128))
236  {
237  ++pcPresc;
238  clkDiv = (uint32_t)1UL << pcPresc;
239  }
240 
241  /* Calculate pcTop value. */
242  pcTop = ((uint32_t)refFreq / ((uint32_t)scanFreq * clkDiv)) - 1UL;
243 
244  /* Clear current PCPRESC and PCTOP settings. Be aware of the effect of
245  * non-atomic Read-Modify-Write on LESENSE->TIMCRTL. */
246  tmp = LESENSE->TIMCTRL & (~_LESENSE_TIMCTRL_PCPRESC_MASK
247  & ~_LESENSE_TIMCTRL_PCTOP_MASK);
248 
249  /* Set new values in tmp while reserving other settings. */
250  tmp |= ((uint32_t)pcPresc << _LESENSE_TIMCTRL_PCPRESC_SHIFT)
251  | ((uint32_t)pcTop << _LESENSE_TIMCTRL_PCTOP_SHIFT);
252 
253  /* Set values in LESENSE_TIMCTRL register. */
254  LESENSE->TIMCTRL = tmp;
255 
256  /* For testing the calculation algorithm. */
257  calcScanFreq = ((uint32_t)refFreq / ((uint32_t)(1UL + pcTop) * clkDiv));
258 
259  return calcScanFreq;
260 }
261 
262 
263 /***************************************************************************/
289 void LESENSE_ScanModeSet(LESENSE_ScanMode_TypeDef const scanMode,
290  bool const start)
291 {
292  uint32_t tmp; /* temporary storage of the CTRL register value */
293 
294 
295  /* Save the CTRL register value to tmp.
296  * Please be aware the effects of the non-atomic Read-Modify-Write cycle! */
297  tmp = LESENSE->CTRL & ~(_LESENSE_CTRL_SCANMODE_MASK);
298  /* Setting the requested scanMode to the CTRL register. Casting signed int
299  * (enum) to unsigned long (uint32_t). */
300  tmp |= (uint32_t)scanMode;
301 
302  /* Write the new value to the CTRL register. */
303  LESENSE->CTRL = tmp;
304 
305  /* Start sensor scanning if requested. */
306  if (start)
307  {
308  LESENSE_ScanStart();
309  }
310 }
311 
312 
313 /***************************************************************************/
331 void LESENSE_StartDelaySet(uint8_t const startDelay)
332 {
333  uint32_t tmp; /* temporary storage of the TIMCTRL register value */
334 
335 
336  /* Sanity check of startDelay. */
337  EFM_ASSERT(startDelay < 4U);
338 
339  /* Save the TIMCTRL register value to tmp.
340  * Please be aware the effects of the non-atomic Read-Modify-Write cycle! */
341  tmp = LESENSE->TIMCTRL & ~(_LESENSE_TIMCTRL_STARTDLY_MASK);
342  /* Setting the requested startDelay to the TIMCTRL register. */
343  tmp |= (uint32_t)startDelay << _LESENSE_TIMCTRL_STARTDLY_SHIFT;
344 
345  /* Write the new value to the TIMCTRL register. */
346  LESENSE->TIMCTRL = tmp;
347 }
348 
349 
350 /***************************************************************************/
374 void LESENSE_ClkDivSet(LESENSE_ChClk_TypeDef const clk,
375  LESENSE_ClkPresc_TypeDef const clkDiv)
376 {
377  uint32_t tmp;
378 
379 
380  /* Select clock to prescale */
381  switch (clk)
382  {
383  case lesenseClkHF:
384  /* Sanity check of clock divisor for HF clock. */
385  EFM_ASSERT((uint32_t)clkDiv <= lesenseClkDiv_8);
386 
387  /* Clear current AUXPRESC settings. */
388  tmp = LESENSE->TIMCTRL & ~(_LESENSE_TIMCTRL_AUXPRESC_MASK);
389 
390  /* Set new values in tmp while reserving other settings. */
391  tmp |= ((uint32_t)clkDiv << _LESENSE_TIMCTRL_AUXPRESC_SHIFT);
392 
393  /* Set values in LESENSE_TIMCTRL register. */
394  LESENSE->TIMCTRL = tmp;
395  break;
396 
397  case lesenseClkLF:
398  /* Clear current LFPRESC settings. */
399  tmp = LESENSE->TIMCTRL & ~(_LESENSE_TIMCTRL_LFPRESC_MASK);
400 
401  /* Set new values in tmp while reserving other settings. */
402  tmp |= ((uint32_t)clkDiv << _LESENSE_TIMCTRL_LFPRESC_SHIFT);
403 
404  /* Set values in LESENSE_TIMCTRL register. */
405  LESENSE->TIMCTRL = tmp;
406  break;
407 
408  default:
409  EFM_ASSERT(0);
410  break;
411  }
412 }
413 
414 
415 /***************************************************************************/
436 void LESENSE_ChannelAllConfig(LESENSE_ChAll_TypeDef const *confChAll)
437 {
438  uint32_t i;
439 
440  /* Iterate through all the 16 channels */
441  for (i = 0U; i < 16U; ++i)
442  {
443  /* Configure scan channels. */
444  LESENSE_ChannelConfig(&confChAll->Ch[i], i);
445  }
446 }
447 
448 
449 /***************************************************************************/
471 void LESENSE_ChannelConfig(LESENSE_ChDesc_TypeDef const *confCh,
472  uint32_t const chIdx)
473 {
474  uint32_t tmp; /* Service variable. */
475 
476 
477  /* Sanity check of configuration parameters */
478  EFM_ASSERT(chIdx < 16U);
479  EFM_ASSERT(confCh->exTime < 64U);
480  EFM_ASSERT(confCh->sampleDelay < 128U);
481  EFM_ASSERT(confCh->measDelay < 128U);
482  /* Not a complete assert, as the max. value of acmpThres depends on other
483  * configuration parameters, check the parameter description of acmpThres for
484  * for more details! */
485  EFM_ASSERT(confCh->acmpThres < 4096U);
486  EFM_ASSERT(!(confCh->chPinExMode == lesenseChPinExDACOut
487  && (chIdx != 2U)
488  && (chIdx != 3U)
489  && (chIdx != 4U)
490  && (chIdx != 5U)));
491  EFM_ASSERT(!(confCh->chPinIdleMode == lesenseChPinIdleDACCh1
492  && ((chIdx != 12U)
493  && (chIdx != 13U)
494  && (chIdx != 14U)
495  && (chIdx != 15U))));
496  EFM_ASSERT(!(confCh->chPinIdleMode == lesenseChPinIdleDACCh0
497  && ((chIdx != 0U)
498  && (chIdx != 1U)
499  && (chIdx != 2U)
500  && (chIdx != 3U))));
501 
502  /* Configure chIdx setup in LESENSE idle phase.
503  * Read-modify-write in order to support reconfiguration during LESENSE
504  * operation. */
505  tmp = (LESENSE->IDLECONF & ~((uint32_t)0x3UL << (chIdx * 2UL)));
506  tmp |= ((uint32_t)confCh->chPinIdleMode << (chIdx * 2UL));
507  LESENSE->IDLECONF = tmp;
508 
509  /* Channel specific timing configuration on scan channel chIdx.
510  * Set excitation time, sampling delay, measurement delay. */
511  LESENSE_ChannelTimingSet(chIdx,
512  (uint32_t)confCh->exTime,
513  (uint32_t)confCh->sampleDelay,
514  (uint32_t)confCh->measDelay);
515 
516  /* Channel specific configuration of clocks, sample mode, excitation pin mode
517  * alternate excitation usage and interrupt mode on scan channel chIdx in
518  * LESENSE_CHchIdx_INTERACT. */
519  LESENSE->CH[chIdx].INTERACT =
520  ((uint32_t)confCh->exClk << _LESENSE_CH_INTERACT_EXCLK_SHIFT)
521  | ((uint32_t)confCh->sampleClk << _LESENSE_CH_INTERACT_SAMPLECLK_SHIFT)
522  | (uint32_t)confCh->sampleMode
523  | (uint32_t)confCh->intMode
524  | (uint32_t)confCh->chPinExMode
525  | ((uint32_t)confCh->useAltEx << _LESENSE_CH_INTERACT_ALTEX_SHIFT);
526 
527  /* Configure channel specific counter comparison mode, optional result
528  * forwarding to decoder, optional counter value storing and optional result
529  * inverting on scan channel chIdx in LESENSE_CHchIdx_EVAL. */
530  LESENSE->CH[chIdx].EVAL =
531  (uint32_t)confCh->compMode
532  | ((uint32_t)confCh->shiftRes << _LESENSE_CH_EVAL_DECODE_SHIFT)
533  | ((uint32_t)confCh->storeCntRes << _LESENSE_CH_EVAL_STRSAMPLE_SHIFT)
534  | ((uint32_t)confCh->invRes << _LESENSE_CH_EVAL_SCANRESINV_SHIFT);
535 
536  /* Configure analog comparator (ACMP) threshold and decision threshold for
537  * counter separately with the function provided for that. */
538  LESENSE_ChannelThresSet(chIdx,
539  (uint32_t)confCh->acmpThres,
540  (uint32_t)confCh->cntThres);
541 
542  /* Enable/disable interrupts on channel */
543  BUS_RegBitWrite(&(LESENSE->IEN), chIdx, confCh->enaInt);
544 
545  /* Enable/disable CHchIdx pin. */
546  BUS_RegBitWrite(&(LESENSE->ROUTE), chIdx, confCh->enaPin);
547 
548  /* Enable/disable scan channel chIdx. */
549  BUS_RegBitWrite(&(LESENSE->CHEN), chIdx, confCh->enaScanCh);
550 }
551 
552 
553 /***************************************************************************/
570 void LESENSE_AltExConfig(LESENSE_ConfAltEx_TypeDef const *confAltEx)
571 {
572  uint32_t i;
573  uint32_t tmp;
574 
575 
576  /* Configure alternate excitation mapping.
577  * Atomic read-modify-write using BUS_RegBitWrite function in order to
578  * support reconfiguration during LESENSE operation. */
579  BUS_RegBitWrite(&(LESENSE->CTRL),
580  _LESENSE_CTRL_ALTEXMAP_SHIFT,
581  confAltEx->altExMap);
582 
583  switch (confAltEx->altExMap)
584  {
585  case lesenseAltExMapALTEX:
586  /* Iterate through the 8 possible alternate excitation pin descriptors. */
587  for (i = 0U; i < 8U; ++i)
588  {
589  /* Enable/disable alternate excitation pin i.
590  * Atomic read-modify-write using BUS_RegBitWrite function in order to
591  * support reconfiguration during LESENSE operation. */
592  BUS_RegBitWrite(&(LESENSE->ROUTE),
593  (16UL + i),
594  confAltEx->AltEx[i].enablePin);
595 
596  /* Setup the idle phase state of alternate excitation pin i.
597  * Read-modify-write in order to support reconfiguration during LESENSE
598  * operation. */
599  tmp = (LESENSE->ALTEXCONF & ~((uint32_t)0x3UL << (i * 2UL)));
600  tmp |= ((uint32_t)confAltEx->AltEx[i].idleConf << (i * 2UL));
601  LESENSE->ALTEXCONF = tmp;
602 
603  /* Enable/disable always excite on channel i */
604  BUS_RegBitWrite(&(LESENSE->ALTEXCONF),
605  (16UL + i),
606  confAltEx->AltEx[i].alwaysEx);
607  }
608  break;
609 
610  case lesenseAltExMapACMP:
611  /* Iterate through all the 16 alternate excitation channels */
612  for (i = 0U; i < 16U; ++i)
613  {
614  /* Enable/disable alternate ACMP excitation channel pin i. */
615  /* Atomic read-modify-write using BUS_RegBitWrite function in order to
616  * support reconfiguration during LESENSE operation. */
617  BUS_RegBitWrite(&(LESENSE->ROUTE),
618  i,
619  confAltEx->AltEx[i].enablePin);
620  }
621  break;
622  default:
623  /* Illegal value. */
624  EFM_ASSERT(0);
625  break;
626  }
627 }
628 
629 
630 /***************************************************************************/
654 void LESENSE_ChannelEnable(uint8_t const chIdx,
655  bool const enaScanCh,
656  bool const enaPin)
657 {
658  /* Enable/disable the assigned pin of scan channel chIdx.
659  * Note: BUS_RegBitWrite() function is used for setting/clearing single
660  * bit peripheral register bitfields. Read the function description in
661  * em_bus.h for more details. */
662  BUS_RegBitWrite(&(LESENSE->ROUTE), chIdx, enaPin);
663 
664  /* Enable/disable scan channel chIdx. */
665  BUS_RegBitWrite(&(LESENSE->CHEN), chIdx, enaScanCh);
666 }
667 
668 
669 /***************************************************************************/
691 void LESENSE_ChannelEnableMask(uint16_t chMask, uint16_t pinMask)
692 {
693  /* Enable/disable all channels at once according to the mask. */
694  LESENSE->CHEN = chMask;
695  /* Enable/disable all channel pins at once according to the mask. */
696  LESENSE->ROUTE = pinMask;
697 }
698 
699 
700 /***************************************************************************/
728 void LESENSE_ChannelTimingSet(uint8_t const chIdx,
729  uint8_t const exTime,
730  uint8_t const sampleDelay,
731  uint8_t const measDelay)
732 {
733  /* Sanity check of parameters. */
734  EFM_ASSERT(exTime < 64U);
735  EFM_ASSERT(sampleDelay < 128U);
736  EFM_ASSERT(measDelay < 128U);
737 
738  /* Channel specific timing configuration on scan channel chIdx.
739  * Setting excitation time, sampling delay, measurement delay. */
740  LESENSE->CH[chIdx].TIMING =
741  ((uint32_t)exTime << _LESENSE_CH_TIMING_EXTIME_SHIFT)
742  | ((uint32_t)sampleDelay << _LESENSE_CH_TIMING_SAMPLEDLY_SHIFT)
743  | ((uint32_t)measDelay << _LESENSE_CH_TIMING_MEASUREDLY_SHIFT);
744 }
745 
746 
747 /***************************************************************************/
780 void LESENSE_ChannelThresSet(uint8_t const chIdx,
781  uint16_t const acmpThres,
782  uint16_t const cntThres)
783 {
784  uint32_t tmp; /* temporary storage */
785 
786 
787  /* Sanity check for acmpThres only, cntThres is 16bit value. */
788  EFM_ASSERT(acmpThres < 4096U);
789  /* Sanity check for LESENSE channel id. */
790  EFM_ASSERT(chIdx < 16);
791 
792  /* Save the INTERACT register value of channel chIdx to tmp.
793  * Please be aware the effects of the non-atomic Read-Modify-Write cycle! */
794  tmp = LESENSE->CH[chIdx].INTERACT & ~(_LESENSE_CH_INTERACT_ACMPTHRES_MASK);
795  /* Set the ACMP threshold value to the INTERACT register of channel chIdx. */
796  tmp |= (uint32_t)acmpThres << _LESENSE_CH_INTERACT_ACMPTHRES_SHIFT;
797  /* Write the new value to the INTERACT register. */
798  LESENSE->CH[chIdx].INTERACT = tmp;
799 
800  /* Save the EVAL register value of channel chIdx to tmp.
801  * Please be aware the effects of the non-atomic Read-Modify-Write cycle! */
802  tmp = LESENSE->CH[chIdx].EVAL & ~(_LESENSE_CH_EVAL_COMPTHRES_MASK);
803  /* Set the counter threshold value to the INTERACT register of channel chIdx. */
804  tmp |= (uint32_t)cntThres << _LESENSE_CH_EVAL_COMPTHRES_SHIFT;
805  /* Write the new value to the EVAL register. */
806  LESENSE->CH[chIdx].EVAL = tmp;
807 }
808 
809 
810 /***************************************************************************/
826 void LESENSE_DecoderStateAllConfig(LESENSE_DecStAll_TypeDef const *confDecStAll)
827 {
828  uint32_t i;
829 
830  /* Iterate through all the 16 decoder states. */
831  for (i = 0U; i < 16U; ++i)
832  {
833  /* Configure decoder state i. */
834  LESENSE_DecoderStateConfig(&confDecStAll->St[i], i);
835  }
836 }
837 
838 
839 /***************************************************************************/
854 void LESENSE_DecoderStateConfig(LESENSE_DecStDesc_TypeDef const *confDecSt,
855  uint32_t const decSt)
856 {
857  /* Sanity check of configuration parameters */
858  EFM_ASSERT(decSt < 16U);
859  EFM_ASSERT((uint32_t)confDecSt->confA.compMask < 16U);
860  EFM_ASSERT((uint32_t)confDecSt->confA.compVal < 16U);
861  EFM_ASSERT((uint32_t)confDecSt->confA.nextState < 16U);
862  EFM_ASSERT((uint32_t)confDecSt->confB.compMask < 16U);
863  EFM_ASSERT((uint32_t)confDecSt->confB.compVal < 16U);
864  EFM_ASSERT((uint32_t)confDecSt->confB.nextState < 16U);
865 
866  /* Configure state descriptor A (LESENSE_STi_TCONFA) for decoder state i.
867  * Setting sensor compare value, sensor mask, next state index,
868  * transition action, interrupt flag option and state descriptor chaining
869  * configurations. */
870  LESENSE->ST[decSt].TCONFA =
871  (uint32_t)confDecSt->confA.prsAct
872  | ((uint32_t)confDecSt->confA.compMask << _LESENSE_ST_TCONFA_MASK_SHIFT)
873  | ((uint32_t)confDecSt->confA.compVal << _LESENSE_ST_TCONFA_COMP_SHIFT)
874  | ((uint32_t)confDecSt->confA.nextState << _LESENSE_ST_TCONFA_NEXTSTATE_SHIFT)
875  | ((uint32_t)confDecSt->confA.setInt << _LESENSE_ST_TCONFA_SETIF_SHIFT)
876  | ((uint32_t)confDecSt->chainDesc << _LESENSE_ST_TCONFA_CHAIN_SHIFT);
877 
878  /* Configure state descriptor Bi (LESENSE_STi_TCONFB).
879  * Setting sensor compare value, sensor mask, next state index, transition
880  * action and interrupt flag option configurations. */
881  LESENSE->ST[decSt].TCONFB =
882  (uint32_t)confDecSt->confB.prsAct
883  | ((uint32_t)confDecSt->confB.compMask << _LESENSE_ST_TCONFB_MASK_SHIFT)
884  | ((uint32_t)confDecSt->confB.compVal << _LESENSE_ST_TCONFB_COMP_SHIFT)
885  | ((uint32_t)confDecSt->confB.nextState << _LESENSE_ST_TCONFB_NEXTSTATE_SHIFT)
886  | ((uint32_t)confDecSt->confB.setInt << _LESENSE_ST_TCONFB_SETIF_SHIFT);
887 }
888 
889 
890 /***************************************************************************/
905 void LESENSE_DecoderStateSet(uint32_t decSt)
906 {
907  EFM_ASSERT(decSt < 16U);
908 
909  LESENSE->DECSTATE = decSt & _LESENSE_DECSTATE_DECSTATE_MASK;
910 }
911 
912 
913 /***************************************************************************/
921 uint32_t LESENSE_DecoderStateGet(void)
922 {
923  return LESENSE->DECSTATE & _LESENSE_DECSTATE_DECSTATE_MASK;
924 }
925 
926 
927 /***************************************************************************/
940 void LESENSE_ScanStart(void)
941 {
942  /* Wait for any pending previous write operation to the CMD register to
943  complete before accessing the CMD register. */
944  while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY)
945  ;
946 
947  /* Start scanning of sensors */
948  LESENSE->CMD = LESENSE_CMD_START;
949 
950  /* Wait for the write operation to the CMD register to complete before
951  returning. */
952  while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY)
953  ;
954 }
955 
956 
957 /***************************************************************************/
973 void LESENSE_ScanStop(void)
974 {
975  /* Wait for any pending previous write operation to the CMD register to
976  complete before accessing the CMD register. */
977  while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY)
978  ;
979 
980  /* Stop scanning of sensors */
981  LESENSE->CMD = LESENSE_CMD_STOP;
982 
983  /* Wait for the write operation to the CMD register to complete before
984  returning. */
985  while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY)
986  ;
987 }
988 
989 
990 /***************************************************************************/
1003 void LESENSE_DecoderStart(void)
1004 {
1005  /* Wait for any pending previous write operation to the CMD register to
1006  complete before accessing the CMD register. */
1007  while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY)
1008  ;
1009 
1010  /* Start decoder */
1011  LESENSE->CMD = LESENSE_CMD_DECODE;
1012 
1013  /* Wait for the write operation to the CMD register to complete before
1014  returning. */
1015  while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY)
1016  ;
1017 }
1018 
1019 
1020 /***************************************************************************/
1033 void LESENSE_ResultBufferClear(void)
1034 {
1035  /* Wait for any pending previous write operation to the CMD register to
1036  complete before accessing the CMD register. */
1037  while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY)
1038  ;
1039 
1040  LESENSE->CMD = LESENSE_CMD_CLEARBUF;
1041 
1042  /* Wait for the write operation to the CMD register to complete before
1043  returning. */
1044  while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY)
1045  ;
1046 }
1047 
1048 
1049 /***************************************************************************/
1062 void LESENSE_Reset(void)
1063 {
1064  uint32_t i;
1065 
1066  /* Disable all LESENSE interrupts first */
1067  LESENSE->IEN = _LESENSE_IEN_RESETVALUE;
1068 
1069  /* Clear all pending LESENSE interrupts */
1070  LESENSE->IFC = _LESENSE_IFC_MASK;
1071 
1072  /* Stop the decoder */
1073  LESENSE->DECCTRL |= LESENSE_DECCTRL_DISABLE;
1074 
1075  /* Wait for any pending previous write operation to the CMD register to
1076  complete before accessing the CMD register. */
1077  while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY)
1078  ;
1079 
1080  /* Stop sensor scan and clear result buffer */
1081  LESENSE->CMD = (LESENSE_CMD_STOP | LESENSE_CMD_CLEARBUF);
1082 
1083  /* Reset LESENSE configuration registers */
1084  LESENSE->CTRL = _LESENSE_CTRL_RESETVALUE;
1085  LESENSE->PERCTRL = _LESENSE_PERCTRL_RESETVALUE;
1086  LESENSE->DECCTRL = _LESENSE_DECCTRL_RESETVALUE;
1087  LESENSE->BIASCTRL = _LESENSE_BIASCTRL_RESETVALUE;
1088  LESENSE->CHEN = _LESENSE_CHEN_RESETVALUE;
1089  LESENSE->IDLECONF = _LESENSE_IDLECONF_RESETVALUE;
1090  LESENSE->ALTEXCONF = _LESENSE_ALTEXCONF_RESETVALUE;
1091 
1092  /* Disable LESENSE to control GPIO pins */
1093  LESENSE->ROUTE = _LESENSE_ROUTE_RESETVALUE;
1094 
1095  /* Reset all channel configuration registers */
1096  for (i = 0U; i < 16U; ++i)
1097  {
1098  LESENSE->CH[i].TIMING = _LESENSE_CH_TIMING_RESETVALUE;
1099  LESENSE->CH[i].INTERACT = _LESENSE_CH_INTERACT_RESETVALUE;
1100  LESENSE->CH[i].EVAL = _LESENSE_CH_EVAL_RESETVALUE;
1101  }
1102 
1103  /* Reset all decoder state configuration registers */
1104  for (i = 0U; i < 16U; ++i)
1105  {
1106  LESENSE->ST[i].TCONFA = _LESENSE_ST_TCONFA_RESETVALUE;
1107  LESENSE->ST[i].TCONFB = _LESENSE_ST_TCONFB_RESETVALUE;
1108  }
1109 
1110  /* Wait for the write operation to the CMD register to complete before
1111  returning. */
1112  while (LESENSE_SYNCBUSY_CMD & LESENSE->SYNCBUSY)
1113  ;
1114 }
1115 
1116 
1120 #endif /* defined(LESENSE_COUNT) && (LESENSE_COUNT > 0) */
Clock management unit (CMU) API.
Emlib peripheral API "assert" implementation.
RAM and peripheral bit-field set and clear API.
Low Energy Sensor (LESENSE) peripheral API.
__STATIC_INLINE void BUS_RegBitWrite(volatile uint32_t *addr, unsigned int bit, unsigned int val)
Perform a single-bit write operation on a peripheral register.
Definition: em_bus.h:146
uint32_t CMU_ClockFreqGet(CMU_Clock_TypeDef clock)
Get clock frequency for a clock point.
Definition: em_cmu.c:1482