mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Revision:
161:2cc1468da177
Parent:
150:02e0a0aed4ec
Child:
179:b0033dcd6934
--- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_lesense.c	Tue Mar 14 16:40:56 2017 +0000
+++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_lesense.c	Thu Mar 30 13:45:57 2017 +0100
@@ -1,7 +1,7 @@
 /***************************************************************************//**
  * @file em_lesense.c
  * @brief Low Energy Sensor (LESENSE) Peripheral API
- * @version 5.0.0
+ * @version 5.1.2
  *******************************************************************************
  * @section License
  * <b>Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com</b>
@@ -31,9 +31,8 @@
  ******************************************************************************/
 
 #include "em_lesense.h"
-/* LESENSE is currently only supported on Platform 1. Full support for Platform 2 LESENSE
-   will be included in the next release. */
-#if defined(LESENSE_COUNT) && (LESENSE_COUNT > 0) && defined(_SILICON_LABS_32B_PLATFORM_1)
+
+#if defined(LESENSE_COUNT) && (LESENSE_COUNT > 0)
 #include "em_assert.h"
 #include "em_bus.h"
 #include "em_cmu.h"
@@ -60,6 +59,22 @@
  * @{
  ******************************************************************************/
 
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+#if defined(_LESENSE_ROUTE_MASK)
+#define GENERIC_LESENSE_ROUTE    LESENSE->ROUTE
+#else
+#define GENERIC_LESENSE_ROUTE    LESENSE->ROUTEPEN
+#endif
+
+#if defined(_SILICON_LABS_32B_SERIES_0)
+/* DACOUT mode only available on channel 0,1,2,3,12,13,14,15 */
+#define DACOUT_SUPPORT  0xF00F
+#else
+/* DACOUT mode only available on channel 4,5,7,10,12,13 */
+#define DACOUT_SUPPORT  0x34B0
+#endif
+/** @endcond */
+
 /*******************************************************************************
  **************************   LOCAL FUNCTIONS   ********************************
  ******************************************************************************/
@@ -100,11 +115,13 @@
  *   Request to call @ref LESENSE_Reset() first in order to initialize all
  *   LESENSE registers with the default value.
  ******************************************************************************/
-void LESENSE_Init(LESENSE_Init_TypeDef const *init, bool const reqReset)
+void LESENSE_Init(const LESENSE_Init_TypeDef * init, bool reqReset)
 {
   /* Sanity check of initialization values */
   EFM_ASSERT((uint32_t)init->timeCtrl.startDelay < 4U);
+#if defined(_LESENSE_PERCTRL_DACPRESC_MASK)
   EFM_ASSERT((uint32_t)init->perCtrl.dacPresc < 32U);
+#endif
 
   /* Reset LESENSE registers if requested. */
   if (reqReset)
@@ -114,6 +131,11 @@
 
   /* Set sensor start delay for each channel. */
   LESENSE_StartDelaySet((uint32_t)init->timeCtrl.startDelay);
+#if defined(_LESENSE_TIMCTRL_AUXSTARTUP_MASK)
+  /* Configure the AUXHRFCO startup delay. */
+  LESENSE->TIMCTRL = (LESENSE->TIMCTRL & (~_LESENSE_TIMCTRL_AUXSTARTUP_MASK))
+                     | (init->timeCtrl.delayAuxStartup << _LESENSE_TIMCTRL_AUXSTARTUP_SHIFT);
+#endif
 
   /* LESENSE core control configuration.
    * Set PRS source, SCANCONF register usage strategy, interrupt and
@@ -127,8 +149,10 @@
     | (uint32_t)init->coreCtrl.scanConfSel
     | (uint32_t)init->coreCtrl.bufTrigLevel
     | (uint32_t)init->coreCtrl.wakeupOnDMA
+#if defined(_LESENSE_CTRL_ACMP0INV_MASK)
     | ((uint32_t)init->coreCtrl.invACMP0     << _LESENSE_CTRL_ACMP0INV_SHIFT)
     | ((uint32_t)init->coreCtrl.invACMP1     << _LESENSE_CTRL_ACMP1INV_SHIFT)
+#endif
     | ((uint32_t)init->coreCtrl.dualSample   << _LESENSE_CTRL_DUALSAMPLE_SHIFT)
     | ((uint32_t)init->coreCtrl.storeScanRes << _LESENSE_CTRL_STRSCANRES_SHIFT)
     | ((uint32_t)init->coreCtrl.bufOverWr    << _LESENSE_CTRL_BUFOW_SHIFT)
@@ -144,15 +168,24 @@
    * duty cycle (warm up) mode. */
   LESENSE->PERCTRL =
     ((uint32_t)init->perCtrl.dacCh0Data       << _LESENSE_PERCTRL_DACCH0DATA_SHIFT)
+    | ((uint32_t)init->perCtrl.dacCh1Data     << _LESENSE_PERCTRL_DACCH1DATA_SHIFT)
+#if defined(_LESENSE_PERCTRL_DACCH0CONV_MASK)
     | ((uint32_t)init->perCtrl.dacCh0ConvMode << _LESENSE_PERCTRL_DACCH0CONV_SHIFT)
     | ((uint32_t)init->perCtrl.dacCh0OutMode  << _LESENSE_PERCTRL_DACCH0OUT_SHIFT)
-    | ((uint32_t)init->perCtrl.dacCh1Data     << _LESENSE_PERCTRL_DACCH1DATA_SHIFT)
     | ((uint32_t)init->perCtrl.dacCh1ConvMode << _LESENSE_PERCTRL_DACCH1CONV_SHIFT)
     | ((uint32_t)init->perCtrl.dacCh1OutMode  << _LESENSE_PERCTRL_DACCH1OUT_SHIFT)
     | ((uint32_t)init->perCtrl.dacPresc       << _LESENSE_PERCTRL_DACPRESC_SHIFT)
     | (uint32_t)init->perCtrl.dacRef
+#endif
     | ((uint32_t)init->perCtrl.acmp0Mode      << _LESENSE_PERCTRL_ACMP0MODE_SHIFT)
     | ((uint32_t)init->perCtrl.acmp1Mode      << _LESENSE_PERCTRL_ACMP1MODE_SHIFT)
+#if defined(_LESENSE_PERCTRL_ACMP0INV_MASK)
+    | ((uint32_t)init->coreCtrl.invACMP0      << _LESENSE_PERCTRL_ACMP0INV_SHIFT)
+    | ((uint32_t)init->coreCtrl.invACMP1      << _LESENSE_PERCTRL_ACMP1INV_SHIFT)
+#endif
+#if defined(_LESENSE_PERCTRL_DACCONVTRIG_MASK)
+    | ((uint32_t)init->perCtrl.dacScan        << _LESENSE_PERCTRL_DACCONVTRIG_SHIFT)
+#endif
     | (uint32_t)init->perCtrl.warmupMode;
 
   /* LESENSE decoder general control configuration.
@@ -211,7 +244,7 @@
  *   Frequency in Hz calculated and set by this function. Users can use this to
  *   compare the requested and set values.
  ******************************************************************************/
-uint32_t LESENSE_ScanFreqSet(uint32_t refFreq, uint32_t const scanFreq)
+uint32_t LESENSE_ScanFreqSet(uint32_t refFreq, uint32_t scanFreq)
 {
   uint32_t tmp;
   uint32_t pcPresc = 0UL;  /* Period counter prescaler. */
@@ -293,8 +326,8 @@
  * @param[in] start
  *   If true, LESENSE_ScanStart() is immediately issued after configuration.
  ******************************************************************************/
-void LESENSE_ScanModeSet(LESENSE_ScanMode_TypeDef const scanMode,
-                         bool const start)
+void LESENSE_ScanModeSet(LESENSE_ScanMode_TypeDef scanMode,
+                         bool start)
 {
   uint32_t tmp; /* temporary storage of the CTRL register value */
 
@@ -335,7 +368,7 @@
  * @param[in] startDelay
  *   Number of LFACLK cycles to delay. Valid range: 0-3 (2 bit).
  ******************************************************************************/
-void LESENSE_StartDelaySet(uint8_t const startDelay)
+void LESENSE_StartDelaySet(uint8_t startDelay)
 {
   uint32_t tmp; /* temporary storage of the TIMCTRL register value */
 
@@ -378,8 +411,8 @@
  * @param[in] clkDiv
  *   Clock divisor value. Valid range depends on the @p clk value.
  ******************************************************************************/
-void LESENSE_ClkDivSet(LESENSE_ChClk_TypeDef const clk,
-                       LESENSE_ClkPresc_TypeDef const clkDiv)
+void LESENSE_ClkDivSet(LESENSE_ChClk_TypeDef clk,
+                       LESENSE_ClkPresc_TypeDef clkDiv)
 {
   uint32_t tmp;
 
@@ -440,12 +473,12 @@
  * @param[in] confChAll
  *   Configuration structure for all (16) LESENSE sensor channels.
  ******************************************************************************/
-void LESENSE_ChannelAllConfig(LESENSE_ChAll_TypeDef const *confChAll)
+void LESENSE_ChannelAllConfig(const LESENSE_ChAll_TypeDef * confChAll)
 {
   uint32_t i;
 
   /* Iterate through all the 16 channels */
-  for (i = 0U; i < 16U; ++i)
+  for (i = 0U; i < LESENSE_NUM_CHANNELS; ++i)
   {
     /* Configure scan channels. */
     LESENSE_ChannelConfig(&confChAll->Ch[i], i);
@@ -475,26 +508,31 @@
  * @param[in] chIdx
  *   Channel index to configure (0-15).
  ******************************************************************************/
-void LESENSE_ChannelConfig(LESENSE_ChDesc_TypeDef const *confCh,
-                           uint32_t const chIdx)
+void LESENSE_ChannelConfig(const LESENSE_ChDesc_TypeDef * confCh,
+                           uint32_t chIdx)
 {
   uint32_t tmp; /* Service variable. */
 
 
   /* Sanity check of configuration parameters */
-  EFM_ASSERT(chIdx < 16U);
-  EFM_ASSERT(confCh->exTime < 64U);
-  EFM_ASSERT(confCh->sampleDelay < 128U);
-  EFM_ASSERT(confCh->measDelay < 128U);
+  EFM_ASSERT(chIdx < LESENSE_NUM_CHANNELS);
+  EFM_ASSERT(confCh->exTime      <= (_LESENSE_CH_TIMING_EXTIME_MASK >> _LESENSE_CH_TIMING_EXTIME_SHIFT));
+  EFM_ASSERT(confCh->measDelay   <= (_LESENSE_CH_TIMING_MEASUREDLY_MASK >> _LESENSE_CH_TIMING_MEASUREDLY_SHIFT));
+#if defined(_SILICON_LABS_32B_SERIES_0)
+  // Sample delay on other devices are 8 bits which fits perfectly in uint8_t
+  EFM_ASSERT(confCh->sampleDelay <= (_LESENSE_CH_TIMING_SAMPLEDLY_MASK >> _LESENSE_CH_TIMING_SAMPLEDLY_SHIFT));
+#endif
+
   /* Not a complete assert, as the max. value of acmpThres depends on other
    * configuration parameters, check the parameter description of acmpThres for
    * for more details! */
   EFM_ASSERT(confCh->acmpThres < 4096U);
-  EFM_ASSERT(!(confCh->chPinExMode == lesenseChPinExDACOut
-               && (chIdx != 2U)
-               && (chIdx != 3U)
-               && (chIdx != 4U)
-               && (chIdx != 5U)));
+  if (confCh->chPinExMode == lesenseChPinExDACOut)
+  {
+    EFM_ASSERT((0x1 << chIdx) & DACOUT_SUPPORT);
+  }
+
+#if defined(_LESENSE_IDLECONF_CH0_DACCH0)
   EFM_ASSERT(!(confCh->chPinIdleMode == lesenseChPinIdleDACCh1
                && ((chIdx != 12U)
                    && (chIdx != 13U)
@@ -505,6 +543,7 @@
                    && (chIdx != 1U)
                    && (chIdx != 2U)
                    && (chIdx != 3U))));
+#endif
 
   /* Configure chIdx setup in LESENSE idle phase.
    * Read-modify-write in order to support reconfiguration during LESENSE
@@ -516,9 +555,9 @@
   /* Channel specific timing configuration on scan channel chIdx.
    * Set excitation time, sampling delay, measurement delay. */
   LESENSE_ChannelTimingSet(chIdx,
-                           (uint32_t)confCh->exTime,
-                           (uint32_t)confCh->sampleDelay,
-                           (uint32_t)confCh->measDelay);
+                           confCh->exTime,
+                           confCh->sampleDelay,
+                           confCh->measDelay);
 
   /* Channel specific configuration of clocks, sample mode, excitation pin mode
    * alternate excitation usage and interrupt mode on scan channel chIdx in
@@ -538,22 +577,26 @@
         (uint32_t)confCh->compMode
         | ((uint32_t)confCh->shiftRes    << _LESENSE_CH_EVAL_DECODE_SHIFT)
         | ((uint32_t)confCh->storeCntRes << _LESENSE_CH_EVAL_STRSAMPLE_SHIFT)
-        | ((uint32_t)confCh->invRes      << _LESENSE_CH_EVAL_SCANRESINV_SHIFT);
+        | ((uint32_t)confCh->invRes      << _LESENSE_CH_EVAL_SCANRESINV_SHIFT)
+#if defined(_LESENSE_CH_EVAL_MODE_MASK)
+        | ((uint32_t)confCh->evalMode    << _LESENSE_CH_EVAL_MODE_SHIFT)
+#endif
+        ;
 
   /* Configure analog comparator (ACMP) threshold and decision threshold for
    * counter separately with the function provided for that. */
   LESENSE_ChannelThresSet(chIdx,
-                         (uint32_t)confCh->acmpThres,
-                         (uint32_t)confCh->cntThres);
+                          confCh->acmpThres,
+                          confCh->cntThres);
 
   /* Enable/disable interrupts on channel */
-  BUS_RegBitWrite(&(LESENSE->IEN), chIdx, confCh->enaInt);
+  BUS_RegBitWrite(&LESENSE->IEN, chIdx, confCh->enaInt);
 
   /* Enable/disable CHchIdx pin. */
-  BUS_RegBitWrite(&(LESENSE->ROUTE), chIdx, confCh->enaPin);
+  BUS_RegBitWrite(&GENERIC_LESENSE_ROUTE, chIdx, confCh->enaPin);
 
   /* Enable/disable scan channel chIdx. */
-  BUS_RegBitWrite(&(LESENSE->CHEN), chIdx, confCh->enaScanCh);
+  BUS_RegBitWrite(&LESENSE->CHEN, chIdx, confCh->enaScanCh);
 }
 
 
@@ -574,7 +617,7 @@
  * @param[in] confAltEx
  *   Configuration structure for LESENSE alternate excitation pins.
  ******************************************************************************/
-void LESENSE_AltExConfig(LESENSE_ConfAltEx_TypeDef const *confAltEx)
+void LESENSE_AltExConfig(const LESENSE_ConfAltEx_TypeDef * confAltEx)
 {
   uint32_t i;
   uint32_t tmp;
@@ -583,7 +626,7 @@
   /* Configure alternate excitation mapping.
    * Atomic read-modify-write using BUS_RegBitWrite function in order to
    * support reconfiguration during LESENSE operation. */
-  BUS_RegBitWrite(&(LESENSE->CTRL),
+  BUS_RegBitWrite(&LESENSE->CTRL,
                   _LESENSE_CTRL_ALTEXMAP_SHIFT,
                   confAltEx->altExMap);
 
@@ -596,7 +639,7 @@
         /* Enable/disable alternate excitation pin i.
          * Atomic read-modify-write using BUS_RegBitWrite function in order to
          * support reconfiguration during LESENSE operation. */
-        BUS_RegBitWrite(&(LESENSE->ROUTE),
+        BUS_RegBitWrite(&GENERIC_LESENSE_ROUTE,
                         (16UL + i),
                         confAltEx->AltEx[i].enablePin);
 
@@ -608,20 +651,24 @@
         LESENSE->ALTEXCONF = tmp;
 
         /* Enable/disable always excite on channel i */
-        BUS_RegBitWrite(&(LESENSE->ALTEXCONF),
+        BUS_RegBitWrite(&LESENSE->ALTEXCONF,
                         (16UL + i),
                         confAltEx->AltEx[i].alwaysEx);
       }
       break;
 
+#if defined(_LESENSE_CTRL_ALTEXMAP_ACMP)
     case lesenseAltExMapACMP:
+#else
+    case lesenseAltExMapCH:
+#endif
       /* Iterate through all the 16 alternate excitation channels */
       for (i = 0U; i < 16U; ++i)
       {
         /* Enable/disable alternate ACMP excitation channel pin i. */
         /* Atomic read-modify-write using BUS_RegBitWrite function in order to
          * support reconfiguration during LESENSE operation. */
-        BUS_RegBitWrite(&(LESENSE->ROUTE),
+        BUS_RegBitWrite(&GENERIC_LESENSE_ROUTE,
                         i,
                         confAltEx->AltEx[i].enablePin);
       }
@@ -658,18 +705,18 @@
  * @param[in] enaPin
  *   Enable/disable the pin assigned to the channel selected by @p chIdx.
  ******************************************************************************/
-void LESENSE_ChannelEnable(uint8_t const chIdx,
-                           bool const enaScanCh,
-                           bool const enaPin)
+void LESENSE_ChannelEnable(uint8_t chIdx,
+                           bool enaScanCh,
+                           bool enaPin)
 {
   /* Enable/disable the assigned pin of scan channel chIdx.
    * Note: BUS_RegBitWrite() function is used for setting/clearing single
    * bit peripheral register bitfields. Read the function description in
    * em_bus.h for more details. */
-  BUS_RegBitWrite(&(LESENSE->ROUTE), chIdx, enaPin);
+  BUS_RegBitWrite(&GENERIC_LESENSE_ROUTE, chIdx, enaPin);
 
   /* Enable/disable scan channel chIdx. */
-  BUS_RegBitWrite(&(LESENSE->CHEN), chIdx, enaScanCh);
+  BUS_RegBitWrite(&LESENSE->CHEN, chIdx, enaScanCh);
 }
 
 
@@ -700,7 +747,7 @@
   /* Enable/disable all channels at once according to the mask. */
   LESENSE->CHEN = chMask;
   /* Enable/disable all channel pins at once according to the mask. */
-  LESENSE->ROUTE = pinMask;
+  GENERIC_LESENSE_ROUTE = pinMask;
 }
 
 
@@ -732,15 +779,18 @@
  *   Measure delay on chIdx. Sensor measuring is delayed for measDelay+1
  *   excitation clock cycles. Valid range: 0-127 (7 bits).
  ******************************************************************************/
-void LESENSE_ChannelTimingSet(uint8_t const chIdx,
-                              uint8_t const exTime,
-                              uint8_t const sampleDelay,
-                              uint8_t const measDelay)
+void LESENSE_ChannelTimingSet(uint8_t chIdx,
+                              uint8_t exTime,
+                              uint8_t sampleDelay,
+                              uint16_t measDelay)
 {
   /* Sanity check of parameters. */
-  EFM_ASSERT(exTime < 64U);
-  EFM_ASSERT(sampleDelay < 128U);
-  EFM_ASSERT(measDelay < 128U);
+  EFM_ASSERT(exTime      <= (_LESENSE_CH_TIMING_EXTIME_MASK >> _LESENSE_CH_TIMING_EXTIME_SHIFT));
+  EFM_ASSERT(measDelay   <= (_LESENSE_CH_TIMING_MEASUREDLY_MASK >> _LESENSE_CH_TIMING_MEASUREDLY_SHIFT));
+#if defined(_SILICON_LABS_32B_SERIES_0)
+  // Sample delay on other devices are 8 bits which fits perfectly in uint8_t
+  EFM_ASSERT(sampleDelay <= (_LESENSE_CH_TIMING_SAMPLEDLY_MASK >> _LESENSE_CH_TIMING_SAMPLEDLY_SHIFT));
+#endif
 
   /* Channel specific timing configuration on scan channel chIdx.
    * Setting excitation time, sampling delay, measurement delay. */
@@ -784,9 +834,9 @@
  *   Decision threshold for counter comparison.
  *   Valid range: 0-65535 (16 bits).
  ******************************************************************************/
-void LESENSE_ChannelThresSet(uint8_t const chIdx,
-                             uint16_t const acmpThres,
-                             uint16_t const cntThres)
+void LESENSE_ChannelThresSet(uint8_t chIdx,
+                             uint16_t acmpThres,
+                             uint16_t cntThres)
 {
   uint32_t tmp; /* temporary storage */
 
@@ -794,13 +844,13 @@
   /* Sanity check for acmpThres only, cntThres is 16bit value. */
   EFM_ASSERT(acmpThres < 4096U);
   /* Sanity check for LESENSE channel id. */
-  EFM_ASSERT(chIdx < 16);
+  EFM_ASSERT(chIdx < LESENSE_NUM_CHANNELS);
 
   /* Save the INTERACT register value of channel chIdx to tmp.
    * Please be aware the effects of the non-atomic Read-Modify-Write cycle! */
-  tmp = LESENSE->CH[chIdx].INTERACT & ~(_LESENSE_CH_INTERACT_ACMPTHRES_MASK);
+  tmp = LESENSE->CH[chIdx].INTERACT & ~(0xFFF);
   /* Set the ACMP threshold value to the INTERACT register of channel chIdx. */
-  tmp |= (uint32_t)acmpThres << _LESENSE_CH_INTERACT_ACMPTHRES_SHIFT;
+  tmp |= (uint32_t)acmpThres;
   /* Write the new value to the INTERACT register. */
   LESENSE->CH[chIdx].INTERACT = tmp;
 
@@ -813,6 +863,122 @@
   LESENSE->CH[chIdx].EVAL = tmp;
 }
 
+#if defined(_LESENSE_CH_EVAL_MODE_MASK)
+/***************************************************************************//**
+ * @brief
+ *   Configure Sliding Window evaluation mode for a specific channel
+ *
+ * @details
+ *   This function will configure the evaluation mode, the initial
+ *   sensor measurement (COMPTHRES) and the window size. For other channel
+ *   related configuration see the @ref LESENSE_ChannelConfig() function.
+ *
+ * @warning
+ *   Beware that the step size and window size configuration are global to all
+ *   LESENSE channels and use the same register field in the hardware. This
+ *   means that any windowSize configuration passed to this function will
+ *   apply for all channels and override all other stepSize/windowSize
+ *   configurations.
+ *
+ * @param[in] chIdx
+ *   Identifier of the scan channel. Valid range: 0-15.
+ *
+ * @param[in] windowSize
+ *   Window size to be used on all channels.
+ *
+ * @param[in] initValue
+ *   The initial sensor value for the channel.
+ ******************************************************************************/
+void LESENSE_ChannelSlidingWindow(uint8_t chIdx,
+                                  uint32_t windowSize,
+                                  uint32_t initValue)
+{
+  LESENSE_CH_TypeDef * ch = &LESENSE->CH[chIdx];
+
+  LESENSE_WindowSizeSet(windowSize);
+  ch->EVAL = (ch->EVAL & ~(_LESENSE_CH_EVAL_COMPTHRES_MASK | _LESENSE_CH_EVAL_MODE_MASK))
+             | (initValue << _LESENSE_CH_EVAL_COMPTHRES_SHIFT)
+             | LESENSE_CH_EVAL_MODE_SLIDINGWIN;
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Configure step detection evaluation mode for a specific channel
+ *
+ * @details
+ *   This function will configure the evaluation mode, the initial
+ *   sensor measurement (COMPTHRES) and the window size. For other channel
+ *   related configuration see the @ref LESENSE_ChannelConfig() function.
+ *
+ * @warning
+ *   Beware that the step size and window size configuration are global to all
+ *   LESENSE channels and use the same register field in the hardware. This
+ *   means that any stepSize configuration passed to this function will
+ *   apply for all channels and override all other stepSize/windowSize
+ *   configurations.
+ *
+ * @param[in] chIdx
+ *   Identifier of the scan channel. Valid range: 0-15.
+ *
+ * @param[in] stepSize
+ *   Step size to be used on all channels.
+ *
+ * @param[in] initValue
+ *   The initial sensor value for the channel.
+ ******************************************************************************/
+void LESENSE_ChannelStepDetection(uint8_t chIdx,
+                                  uint32_t stepSize,
+                                  uint32_t initValue)
+{
+  LESENSE_CH_TypeDef * ch = &LESENSE->CH[chIdx];
+
+  LESENSE_StepSizeSet(stepSize);
+  ch->EVAL = (ch->EVAL & ~(_LESENSE_CH_EVAL_COMPTHRES_MASK | _LESENSE_CH_EVAL_MODE_MASK))
+             | (initValue << _LESENSE_CH_EVAL_COMPTHRES_SHIFT)
+             | LESENSE_CH_EVAL_MODE_STEPDET;
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Set the window size for all LESENSE channels.
+ *
+ * @details
+ *   The window size is used by all channels that are configured as
+ *   @ref lesenseEvalModeSlidingWindow.
+ *
+ * @warning
+ *   The window size configuration is using the same register field as the
+ *   step detection size. So the window size configuration will have an
+ *   effect on channels configured with the @ref lesenseEvalModeStepDetection
+ *   evaluation mode as well.
+ *
+ * @param[in] windowSize
+ *   The window size to use for all channels.
+ ******************************************************************************/
+void LESENSE_WindowSizeSet(uint32_t windowSize)
+{
+  LESENSE->EVALCTRL = (LESENSE->EVALCTRL & ~_LESENSE_EVALCTRL_WINSIZE_MASK)
+                      | windowSize;
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Set the step size for all LESENSE channels.
+ *
+ * @details
+ *   The step size is configured using the same register field as use to
+ *   configure window size. So calling this function will overwrite any
+ *   previously configured window size as done by the
+ *   @ref LESENSE_WindowSizeSet() function.
+ *
+ * @param[in] stepSize
+ *   The step size to use for all channels.
+ ******************************************************************************/
+void LESENSE_StepSizeSet(uint32_t stepSize)
+{
+  LESENSE_WindowSizeSet(stepSize);
+}
+#endif
 
 /***************************************************************************//**
  * @brief
@@ -828,14 +994,14 @@
  *   LESENSE_DecoderStateConfig() function.
  *
  * @param[in] confDecStAll
- *   Configuration structure for all (16) LESENSE decoder states.
+ *   Configuration structure for all (16 or 32) LESENSE decoder states.
  ******************************************************************************/
-void LESENSE_DecoderStateAllConfig(LESENSE_DecStAll_TypeDef const *confDecStAll)
+void LESENSE_DecoderStateAllConfig(const LESENSE_DecStAll_TypeDef * confDecStAll)
 {
   uint32_t i;
 
-  /* Iterate through all the 16 decoder states. */
-  for (i = 0U; i < 16U; ++i)
+  /* Iterate through all the 16 or 32 decoder states. */
+  for (i = 0U; i < LESENSE_NUM_DECODER_STATES; ++i)
   {
     /* Configure decoder state i. */
     LESENSE_DecoderStateConfig(&confDecStAll->St[i], i);
@@ -856,19 +1022,19 @@
  *   Configuration structure for a single LESENSE decoder state.
  *
  * @param[in] decSt
- *   Decoder state index to configure (0-15).
+ *   Decoder state index to configure (0-15) or (0-31) depending on device.
  ******************************************************************************/
-void LESENSE_DecoderStateConfig(LESENSE_DecStDesc_TypeDef const *confDecSt,
-                                uint32_t const decSt)
+void LESENSE_DecoderStateConfig(const LESENSE_DecStDesc_TypeDef * confDecSt,
+                                uint32_t decSt)
 {
   /* Sanity check of configuration parameters */
-  EFM_ASSERT(decSt < 16U);
+  EFM_ASSERT(decSt < LESENSE_NUM_DECODER_STATES);
   EFM_ASSERT((uint32_t)confDecSt->confA.compMask < 16U);
   EFM_ASSERT((uint32_t)confDecSt->confA.compVal < 16U);
-  EFM_ASSERT((uint32_t)confDecSt->confA.nextState < 16U);
+  EFM_ASSERT((uint32_t)confDecSt->confA.nextState < LESENSE_NUM_DECODER_STATES);
   EFM_ASSERT((uint32_t)confDecSt->confB.compMask < 16U);
   EFM_ASSERT((uint32_t)confDecSt->confB.compVal < 16U);
-  EFM_ASSERT((uint32_t)confDecSt->confB.nextState < 16U);
+  EFM_ASSERT((uint32_t)confDecSt->confB.nextState < LESENSE_NUM_DECODER_STATES);
 
   /* Configure state descriptor A (LESENSE_STi_TCONFA) for decoder state i.
    * Setting sensor compare value, sensor mask, next state index,
@@ -907,11 +1073,12 @@
  *   enabling the decoder!
  *
  * @param[in] decSt
- *   Decoder state to set as current state. Valid range: 0-15
+ *   Decoder state to set as current state. Valid range: 0-15 or 0-31
+ *   depending on device.
  ******************************************************************************/
 void LESENSE_DecoderStateSet(uint32_t decSt)
 {
-  EFM_ASSERT(decSt < 16U);
+  EFM_ASSERT(decSt <= _LESENSE_DECSTATE_DECSTATE_MASK);
 
   LESENSE->DECSTATE = decSt & _LESENSE_DECSTATE_DECSTATE_MASK;
 }
@@ -930,6 +1097,28 @@
   return LESENSE->DECSTATE & _LESENSE_DECSTATE_DECSTATE_MASK;
 }
 
+#if defined(_LESENSE_PRSCTRL_MASK)
+/***************************************************************************//**
+ * @brief
+ *   Enable or disable PRS output from the LESENSE decoder.
+ *
+ * @param[in] enable
+ *   enable/disable the PRS output from the LESENSE decoder. true to enable and
+ *   false to disable.
+ *
+ * @param[in] decMask
+ *   Decoder state compare value mask
+ *
+ * @param[in] decVal
+ *   Decoder state compare value.
+ ******************************************************************************/
+void LESENSE_DecoderPrsOut(bool enable, uint32_t decMask, uint32_t decVal)
+{
+  LESENSE->PRSCTRL = (enable << _LESENSE_PRSCTRL_DECCMPEN_SHIFT)
+                     | (decMask << _LESENSE_PRSCTRL_DECCMPMASK_SHIFT)
+                     | (decVal << _LESENSE_PRSCTRL_DECCMPVAL_SHIFT);
+}
+#endif
 
 /***************************************************************************//**
  * @brief
@@ -1092,15 +1281,23 @@
   LESENSE->PERCTRL   = _LESENSE_PERCTRL_RESETVALUE;
   LESENSE->DECCTRL   = _LESENSE_DECCTRL_RESETVALUE;
   LESENSE->BIASCTRL  = _LESENSE_BIASCTRL_RESETVALUE;
+#if defined(_LESENSE_EVALCTRL_MASK)
+  LESENSE->EVALCTRL  = _LESENSE_EVALCTRL_RESETVALUE;
+  LESENSE->PRSCTRL   = _LESENSE_PRSCTRL_RESETVALUE;
+#endif
   LESENSE->CHEN      = _LESENSE_CHEN_RESETVALUE;
   LESENSE->IDLECONF  = _LESENSE_IDLECONF_RESETVALUE;
   LESENSE->ALTEXCONF = _LESENSE_ALTEXCONF_RESETVALUE;
 
   /* Disable LESENSE to control GPIO pins */
-  LESENSE->ROUTE = _LESENSE_ROUTE_RESETVALUE;
+#if defined(_LESENSE_ROUTE_MASK)
+  LESENSE->ROUTE    = _LESENSE_ROUTE_RESETVALUE;
+#else
+  LESENSE->ROUTEPEN = _LESENSE_ROUTEPEN_RESETVALUE;
+#endif
 
   /* Reset all channel configuration registers */
-  for (i = 0U; i < 16U; ++i)
+  for (i = 0U; i < LESENSE_NUM_CHANNELS; ++i)
   {
     LESENSE->CH[i].TIMING   = _LESENSE_CH_TIMING_RESETVALUE;
     LESENSE->CH[i].INTERACT = _LESENSE_CH_INTERACT_RESETVALUE;
@@ -1108,7 +1305,7 @@
   }
 
   /* Reset all decoder state configuration registers */
-  for (i = 0U; i < 16U; ++i)
+  for (i = 0U; i < LESENSE_NUM_DECODER_STATES; ++i)
   {
     LESENSE->ST[i].TCONFA = _LESENSE_ST_TCONFA_RESETVALUE;
     LESENSE->ST[i].TCONFB = _LESENSE_ST_TCONFB_RESETVALUE;