/***************************************************************************//** * @file * @brief Capacitive Sense Module (CSEN) peripheral API ******************************************************************************* * # License * Copyright 2018 Silicon Laboratories Inc. www.silabs.com ******************************************************************************* * * SPDX-License-Identifier: Zlib * * The licensor of this software is Silicon Laboratories Inc. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * ******************************************************************************/ #include "em_csen.h" #if defined(CSEN_COUNT) && (CSEN_COUNT > 0) #include "sl_assert.h" #include "em_cmu.h" #include /***************************************************************************//** * @addtogroup csen * @{ ******************************************************************************/ /******************************************************************************* ******************************* DEFINES *********************************** ******************************************************************************/ /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ /** Validation of CSEN register block pointer reference for assert statements. */ #define CSEN_REF_VALID(ref) ((ref) == CSEN) /** @endcond */ /******************************************************************************* ************************** GLOBAL FUNCTIONS ******************************* ******************************************************************************/ /***************************************************************************//** * @brief * Set the DM integrator initial value. * * @details * Sets the initial value of the integrator(s) for the Delta Modulation (DM) * converter. The initial value for the ramp-down integrator has no effect * if the low-frequency attenuation was not selected by the mode initialization * function @ref CSEN_InitMode(). * * @note * Confirm CSEN is idle before calling this function. * * @param[in] csen * A pointer to the CSEN peripheral register block. * * @param[in] up * An initial value for the ramp-up integrator. * * @param[in] down * An initial value for the ramp-down integrator. Has no effect if low-frequency * attenuation is not configured. ******************************************************************************/ void CSEN_DMBaselineSet(CSEN_TypeDef *csen, uint32_t up, uint32_t down) { EFM_ASSERT(up < 0x10000); EFM_ASSERT(down < 0x10000); csen->DMBASELINE = (up << _CSEN_DMBASELINE_BASELINEUP_SHIFT) | (down << _CSEN_DMBASELINE_BASELINEDN_SHIFT); } /***************************************************************************//** * @brief * Initialize CSEN. * * @details * Initializes common functionality for all measurement types. In addition, * measurement mode must be configured. See @ref CSEN_InitMode(). * * @note * This function will stop any ongoing conversion and disable CSEN. * * @param[in] csen * A pointer to the CSEN peripheral register block. * * @param[in] init * A pointer to the CSEN initialization structure. ******************************************************************************/ void CSEN_Init(CSEN_TypeDef *csen, const CSEN_Init_TypeDef *init) { uint32_t tmp; EFM_ASSERT(CSEN_REF_VALID(csen)); EFM_ASSERT(init->warmUpCount < 4); /* Initialize CTRL. This will stop any conversion in progress. */ tmp = CSEN_CTRL_STM_DEFAULT; if (init->cpAccuracyHi) { tmp |= CSEN_CTRL_CPACCURACY_HI; } if (init->localSense) { tmp |= _CSEN_CTRL_LOCALSENS_MASK; } if (init->keepWarm) { tmp |= CSEN_CTRL_WARMUPMODE_KEEPCSENWARM; } csen->CTRL = tmp; /* Initialize TIMCTRL. */ csen->TIMCTRL = (init->warmUpCount << _CSEN_TIMCTRL_WARMUPCNT_SHIFT) | (init->pcReload << _CSEN_TIMCTRL_PCTOP_SHIFT) | (init->pcPrescale << _CSEN_TIMCTRL_PCPRESC_SHIFT); /* PRSSEL only has one field */ csen->PRSSEL = init->prsSel << _CSEN_PRSSEL_PRSSEL_SHIFT; /* Set input selections for inputs 0 to 31. */ csen->SCANINPUTSEL0 = (init->input0To7 << _CSEN_SCANINPUTSEL0_INPUT0TO7SEL_SHIFT) | (init->input8To15 << _CSEN_SCANINPUTSEL0_INPUT8TO15SEL_SHIFT) | (init->input16To23 << _CSEN_SCANINPUTSEL0_INPUT16TO23SEL_SHIFT) | (init->input24To31 << _CSEN_SCANINPUTSEL0_INPUT24TO31SEL_SHIFT); /* Set input selections for inputs 32 to 63. */ csen->SCANINPUTSEL1 = (init->input32To39 << _CSEN_SCANINPUTSEL1_INPUT32TO39SEL_SHIFT) | (init->input40To47 << _CSEN_SCANINPUTSEL1_INPUT40TO47SEL_SHIFT) | (init->input48To55 << _CSEN_SCANINPUTSEL1_INPUT48TO55SEL_SHIFT) | (init->input56To63 << _CSEN_SCANINPUTSEL1_INPUT56TO63SEL_SHIFT); } /***************************************************************************//** * @brief * Initialize a CSEN measurement mode. * * @details * Used to configure any type of measurement mode. After the measurement * has been configured, calling @ref CSEN_Enable() will enable CSEN and * allow it to start a conversion from the selected trigger source. To * manually start a conversion, use @ref CSEN_Start(). To check if a * conversion is in progress, use @ref CSEN_IsBusy(), or alternatively * use the interrupt flags returned by @ref CSEN_IntGet() to detect when * a conversion is completed. * * @note * This function will stop any ongoing conversion and disable CSEN. * * @param[in] csen * A pointer to the CSEN peripheral register block. * * @param[in] init * A pointer to the CSEN measurement mode initialization structure. ******************************************************************************/ void CSEN_InitMode(CSEN_TypeDef *csen, const CSEN_InitMode_TypeDef *init) { uint32_t tmp; EFM_ASSERT(CSEN_REF_VALID(csen)); EFM_ASSERT(init->dmIterPerCycle < 0x10); EFM_ASSERT(init->dmCycles < 0x10); /* Initialize CTRL. This will stop any conversion in progress. * These composite inputs set multiple fields. They do not need * to be shifted. */ tmp = ((uint32_t)init->sampleMode | (uint32_t)init->convSel | (uint32_t)init->cmpMode); tmp |= (init->trigSel << _CSEN_CTRL_STM_SHIFT) | (init->accMode << _CSEN_CTRL_ACU_SHIFT) | (init->sarRes << _CSEN_CTRL_SARCR_SHIFT); if (init->enableDma) { tmp |= CSEN_CTRL_DMAEN_ENABLE; } if (init->sumOnly) { tmp |= CSEN_CTRL_DRSF_ENABLE; } if (init->autoGnd) { tmp |= CSEN_CTRL_AUTOGND_ENABLE; } /* Preserve the fields that were initialized by CSEN_Init(). */ tmp |= csen->CTRL & (_CSEN_CTRL_CPACCURACY_MASK | _CSEN_CTRL_LOCALSENS_MASK | _CSEN_CTRL_WARMUPMODE_MASK); csen->CTRL = tmp; /* EMACTRL only has one field. */ csen->EMACTRL = init->emaSample << _CSEN_EMACTRL_EMASAMPLE_SHIFT; /* CMPTHR only has one field. */ csen->CMPTHR = init->cmpThr << _CSEN_CMPTHR_CMPTHR_SHIFT; /* SINGLECTRL only has one field. */ csen->SINGLECTRL = init->singleSel << _CSEN_SINGLECTRL_SINGLESEL_SHIFT; /* Set all input enables. */ csen->SCANMASK0 = init->inputMask0; csen->SCANMASK1 = init->inputMask1; /* Initialize DMCFG. */ tmp = (init->dmRes << _CSEN_DMCFG_CRMODE_SHIFT) | (init->dmCycles << _CSEN_DMCFG_DMCR_SHIFT) | (init->dmIterPerCycle << _CSEN_DMCFG_DMR_SHIFT) | (init->dmDelta << _CSEN_DMCFG_DMG_SHIFT); if (init->dmFixedDelta) { tmp |= CSEN_DMCFG_DMGRDIS; } csen->DMCFG = tmp; /* Initialize ANACTRL. */ csen->ANACTRL = (init->resetPhase << _CSEN_ANACTRL_TRSTPROG_SHIFT) | (init->driveSel << _CSEN_ANACTRL_IDACIREFS_SHIFT) | (init->gainSel << _CSEN_ANACTRL_IREFPROG_SHIFT); } /***************************************************************************//** * @brief * Reset CSEN to same state that it was in after a hardware reset. * * @param[in] csen * A pointer to the CSEN peripheral register block. ******************************************************************************/ void CSEN_Reset(CSEN_TypeDef *csen) { EFM_ASSERT(CSEN_REF_VALID(csen)); /* Resetting CTRL stops any conversion in progress. */ csen->CTRL = _CSEN_CTRL_RESETVALUE; csen->TIMCTRL = _CSEN_TIMCTRL_RESETVALUE; csen->PRSSEL = _CSEN_PRSSEL_RESETVALUE; csen->DATA = _CSEN_DATA_RESETVALUE; csen->SCANMASK0 = _CSEN_SCANMASK0_RESETVALUE; csen->SCANINPUTSEL0 = _CSEN_SCANINPUTSEL0_RESETVALUE; csen->SCANMASK1 = _CSEN_SCANMASK1_RESETVALUE; csen->SCANINPUTSEL1 = _CSEN_SCANINPUTSEL1_RESETVALUE; csen->CMPTHR = _CSEN_CMPTHR_RESETVALUE; csen->EMA = _CSEN_EMA_RESETVALUE; csen->EMACTRL = _CSEN_EMACTRL_RESETVALUE; csen->SINGLECTRL = _CSEN_SINGLECTRL_RESETVALUE; csen->DMBASELINE = _CSEN_DMBASELINE_RESETVALUE; csen->DMCFG = _CSEN_DMCFG_RESETVALUE; csen->ANACTRL = _CSEN_ANACTRL_RESETVALUE; csen->IEN = _CSEN_IEN_RESETVALUE; csen->IFC = _CSEN_IF_MASK; } /** @} (end addtogroup csen) */ #endif /* defined(CSEN_COUNT) && (CSEN_COUNT > 0) */