blob: 9cc1ca2954bb65a3cf0b084242de3cd1bc0ae232 [file] [log] [blame]
/***************************************************************************//**
* @file em_csen.c
* @brief Capacitive Sense Module (CSEN) peripheral API
* @version 5.6.0
*******************************************************************************
* # License
* <b>Copyright 2016 Silicon Laboratories, Inc. www.silabs.com</b>
*******************************************************************************
*
* 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.
* 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.
*
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
* obligation to support this Software. Silicon Labs is providing the
* Software "AS IS", with no express or implied warranties of any kind,
* including, but not limited to, any implied warranties of merchantability
* or fitness for any particular purpose or warranties against infringement
* of any proprietary rights of a third party.
*
* Silicon Labs will not be liable for any consequential, incidental, or
* special damages, or any other relief, or for any claim by any third party,
* arising from your use of this Software.
*
******************************************************************************/
#include "em_csen.h"
#if defined(CSEN_COUNT) && (CSEN_COUNT > 0)
#include "em_assert.h"
#include "em_cmu.h"
#include <stddef.h>
/***************************************************************************//**
* @addtogroup emlib
* @{
******************************************************************************/
/***************************************************************************//**
* @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) */
/** @} (end addtogroup emlib) */
#endif /* defined(CSEN_COUNT) && (CSEN_COUNT > 0) */