/***************************************************************************//** * @file * @brief Analog Comparator (ACMP) peripheral API for EFM32. * @author Energy Micro AS * @version 2.0.0 ******************************************************************************* * @section License * (C) Copyright 2010 Energy Micro AS, http://www.energymicro.com ******************************************************************************* * * This source code is the property of Energy Micro AS. The source and compiled * code may only be used on Energy Micro "EFM32" microcontrollers. * * This copyright notice may not be removed from the source code nor changed. * * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no * obligation to support this Software. Energy Micro AS 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. * * Energy Micro AS 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. * ******************************************************************************/ #ifndef __EFM32_ACMP_H #define __EFM32_ACMP_H #include #include #include "efm32.h" #ifdef __cplusplus extern "C" { #endif /***************************************************************************//** * @addtogroup EFM32_Library * @{ ******************************************************************************/ /***************************************************************************//** * @addtogroup ACMP * @{ ******************************************************************************/ /******************************************************************************* ******************************** ENUMS ************************************ ******************************************************************************/ /** Resistor values used for capacative sense. See the datasheet for your * device for details on each resistor value. */ typedef enum { /** resistor value 0 */ acmpResistor0 = _ACMP_INPUTSEL_CSRESSEL_RES0, /** resistor value 1 */ acmpResistor1 = _ACMP_INPUTSEL_CSRESSEL_RES1, /** resistor value 2 */ acmpResistor2 = _ACMP_INPUTSEL_CSRESSEL_RES2, /** resistor value 3 */ acmpResistor3 = _ACMP_INPUTSEL_CSRESSEL_RES3 } ACMP_CapsenseResistor_TypeDef; /** Hysteresis level. See datasheet for your device for details on each * level. */ typedef enum { acmpHysteresisLevel0 = _ACMP_CTRL_HYSTSEL_HYST0, /**< Hysteresis level 0 */ acmpHysteresisLevel1 = _ACMP_CTRL_HYSTSEL_HYST1, /**< Hysteresis level 1 */ acmpHysteresisLevel2 = _ACMP_CTRL_HYSTSEL_HYST2, /**< Hysteresis level 2 */ acmpHysteresisLevel3 = _ACMP_CTRL_HYSTSEL_HYST3, /**< Hysteresis level 3 */ acmpHysteresisLevel4 = _ACMP_CTRL_HYSTSEL_HYST4, /**< Hysteresis level 4 */ acmpHysteresisLevel5 = _ACMP_CTRL_HYSTSEL_HYST5, /**< Hysteresis level 5 */ acmpHysteresisLevel6 = _ACMP_CTRL_HYSTSEL_HYST6, /**< Hysteresis level 6 */ acmpHysteresisLevel7 = _ACMP_CTRL_HYSTSEL_HYST7 /**< Hysteresis level 7 */ } ACMP_HysteresisLevel_TypeDef; /** ACMP warmup time. The delay is measured in HFPERCLK cycles and should * be at least 10 us. */ typedef enum { /** 4 HFPERCLK cycles warmup */ acmpWarmTime4 = _ACMP_CTRL_WARMTIME_4CYCLES, /** 8 HFPERCLK cycles warmup */ acmpWarmTime8 = _ACMP_CTRL_WARMTIME_8CYCLES, /** 16 HFPERCLK cycles warmup */ acmpWarmTime16 = _ACMP_CTRL_WARMTIME_16CYCLES, /** 32 HFPERCLK cycles warmup */ acmpWarmTime32 = _ACMP_CTRL_WARMTIME_32CYCLES, /** 64 HFPERCLK cycles warmup */ acmpWarmTime64 = _ACMP_CTRL_WARMTIME_64CYCLES, /** 128 HFPERCLK cycles warmup */ acmpWarmTime128 = _ACMP_CTRL_WARMTIME_128CYCLES, /** 256 HFPERCLK cycles warmup */ acmpWarmTime256 = _ACMP_CTRL_WARMTIME_256CYCLES, /** 512 HFPERCLK cycles warmup */ acmpWarmTime512 = _ACMP_CTRL_WARMTIME_512CYCLES } ACMP_WarmTime_TypeDef; /** ACMP inputs. Note that scaled VDD and bandgap references can only be used * as negative inputs. */ typedef enum { /** Channel 0 */ acmpChannel0 = _ACMP_INPUTSEL_NEGSEL_CH0, /** Channel 1 */ acmpChannel1 = _ACMP_INPUTSEL_NEGSEL_CH1, /** Channel 2 */ acmpChannel2 = _ACMP_INPUTSEL_NEGSEL_CH2, /** Channel 3 */ acmpChannel3 = _ACMP_INPUTSEL_NEGSEL_CH3, /** Channel 4 */ acmpChannel4 = _ACMP_INPUTSEL_NEGSEL_CH4, /** Channel 5 */ acmpChannel5 = _ACMP_INPUTSEL_NEGSEL_CH5, /** Channel 6 */ acmpChannel6 = _ACMP_INPUTSEL_NEGSEL_CH6, /** Channel 7 */ acmpChannel7 = _ACMP_INPUTSEL_NEGSEL_CH7, /** 1.25V internal reference */ acmpChannel1V25 = _ACMP_INPUTSEL_NEGSEL_1V25, /** 2.5V internal reference */ acmpChannel2V5 = _ACMP_INPUTSEL_NEGSEL_2V5, /** Scaled VDD reference */ acmpChannelVDD = _ACMP_INPUTSEL_NEGSEL_VDD } ACMP_Channel_TypeDef; /******************************************************************************* ****************************** STRUCTS ************************************ ******************************************************************************/ /** Capsense initialization structure. */ typedef struct { /** Full bias current. See the ACMP chapter about bias and response time in * the reference manual for details. */ bool fullBias; /** Half bias current. See the ACMP chapter about bias and response time in * the reference manual for details. */ bool halfBias; /** Bias current. See the ACMP chapter about bias and response time in the * reference manual for details. Valid values are in the range 0-7. */ uint32_t biasProg; /** Warmup time. This is measured in HFPERCLK cycles and should be * about 10us in wall clock time. */ ACMP_WarmTime_TypeDef warmTime; /** Hysteresis level */ ACMP_HysteresisLevel_TypeDef hysteresisLevel; /** Resistor used in the capacative sensing circuit. For values see * your device datasheet. */ ACMP_CapsenseResistor_TypeDef resistor; /** Low power reference enabled. This setting, if enabled, reduces the * power used by the VDD and bandgap references. */ bool lowPowerReferenceEnabled; /** Vdd reference value. VDD_SCALED = VDD × VDDLEVEL × 50mV/3.8V. * Valid values are in the range 0-63. */ uint32_t vddLevel; /** If true, ACMP is being enabled after configuration. */ bool enable; } ACMP_CapsenseInit_TypeDef; /** Default config for capacitive sense mode initialization. */ #define ACMP_CAPSENSE_INIT_DEFAULT \ { false, /* fullBias */ \ false, /* halfBias */ \ 0x7, /* biasProg */ \ acmpWarmTime512, /* 512 cycle warmup to be safe */ \ acmpHysteresisLevel5, \ acmpResistor3, \ false, /* low power reference */ \ 0x3D, /* VDD level */ \ true /* Enable after init. */ \ } /** ACMP initialization structure. */ typedef struct { /** Full bias current. See the ACMP chapter about bias and response time in * the reference manual for details. */ bool fullBias; /** Half bias current. See the ACMP chapter about bias and response time in * the reference manual for details. */ bool halfBias; /** Bias current. See the ACMP chapter about bias and response time in the * reference manual for details. Valid values are in the range 0-7. */ uint32_t biasProg; /** Enable setting the interrupt flag on falling edge */ bool interruptOnFallingEdge; /** Enable setting the interrupt flag on rising edge */ bool interruptOnRisingEdge; /** Warmup time. This is measured in HFPERCLK cycles and should be * about 10us in wall clock time. */ ACMP_WarmTime_TypeDef warmTime; /** Hysteresis level */ ACMP_HysteresisLevel_TypeDef hysteresisLevel; /** Inactive value emitted by the ACMP during warmup */ bool inactiveValue; /** Low power reference enabled. This setting, if enabled, reduces the * power used by the VDD and bandgap references. */ bool lowPowerReferenceEnabled; /** Vdd reference value. VDD_SCALED = VDD × VDDLEVEL × 50mV/3.8V. * Valid values are in the range 0-63. */ uint32_t vddLevel; /** If true, ACMP is being enabled after configuration. */ bool enable; } ACMP_Init_TypeDef; /** Default config for ACMP regular initialization. */ #define ACMP_INIT_DEFAULT \ { false, /* fullBias */ \ false, /* halfBias */ \ 0x7, /* biasProg */ \ false, /* No interrupt on falling edge. */ \ false, /* No interrupt on rising edge. */ \ acmpWarmTime512, /* 512 cycle warmup to be safe */ \ acmpHysteresisLevel5, \ false, /* Disabled emitting inactive value during warmup. */ \ false, /* low power reference */ \ 0x3D, /* VDD level */ \ true /* Enable after init. */ \ } /******************************************************************************* ***************************** PROTOTYPES ********************************** ******************************************************************************/ void ACMP_CapsenseInit(ACMP_TypeDef *acmp, const ACMP_CapsenseInit_TypeDef *init); void ACMP_CapsenseChannelSet(ACMP_TypeDef *acmp, ACMP_Channel_TypeDef channel); void ACMP_ChannelSet(ACMP_TypeDef *acmp, ACMP_Channel_TypeDef negSel, ACMP_Channel_TypeDef posSel); void ACMP_Disable(ACMP_TypeDef *acmp); void ACMP_Enable(ACMP_TypeDef *acmp); void ACMP_GPIOSetup(ACMP_TypeDef *acmp, uint32_t location, bool enable, bool invert); void ACMP_Init(ACMP_TypeDef *acmp, const ACMP_Init_TypeDef *init); void ACMP_Reset(ACMP_TypeDef *acmp); /***************************************************************************//** * @brief * Clear one or more pending ACMP interrupts. * * @param[in] acmp * Pointer to ACMP peripheral register block. * * @param[in] flags * Pending ACMP interrupt source to clear. Use a bitwise logic OR combination * of valid interrupt flags for the ACMP module (ACMP_IF_nnn). ******************************************************************************/ static __INLINE void ACMP_IntClear(ACMP_TypeDef *acmp, uint32_t flags) { acmp->IFC = flags; } /***************************************************************************//** * @brief * Disable one or more ACMP interrupts. * * @param[in] acmp * Pointer to ACMP peripheral register block. * * @param[in] flags * ACMP interrupt sources to disable. Use a bitwise logic OR combination of * valid interrupt flags for the ACMP module (ACMP_IF_nnn). ******************************************************************************/ static __INLINE void ACMP_IntDisable(ACMP_TypeDef *acmp, uint32_t flags) { acmp->IEN &= ~(flags); } /***************************************************************************//** * @brief * Enable one or more ACMP interrupts. * * @note * Depending on the use, a pending interrupt may already be set prior to * enabling the interrupt. Consider using ACMP_IntClear() prior to enabling * if such a pending interrupt should be ignored. * * @param[in] acmp * Pointer to ACMP peripheral register block. * * @param[in] flags * ACMP interrupt sources to enable. Use a bitwise logic OR combination of * valid interrupt flags for the ACMP module (ACMP_IF_nnn). ******************************************************************************/ static __INLINE void ACMP_IntEnable(ACMP_TypeDef *acmp, uint32_t flags) { acmp->IEN |= flags; } /***************************************************************************//** * @brief * Get pending ACMP interrupt flags. * * @note * The event bits are not cleared by the use of this function. * * @param[in] acmp * Pointer to ACMP peripheral register block. * * @return * ACMP interrupt sources pending. A bitwise logic OR combination of valid * interrupt flags for the ACMP module (ACMP_IF_nnn). ******************************************************************************/ static __INLINE uint32_t ACMP_IntGet(ACMP_TypeDef *acmp) { return(acmp->IF); } /***************************************************************************//** * @brief * Get enabled and pending ACMP interrupt flags. * Useful for handling more interrupt sources in the same interrupt handler. * * @param[in] usart * Pointer to ACMP peripheral register block. * * @note * Interrupt flags are not cleared by the use of this function. * * @return * Pending and enabled ACMP interrupt sources. * The return value is the bitwise AND combination of * - the OR combination of enabled interrupt sources in ACMPx_IEN_nnn * register (ACMPx_IEN_nnn) and * - the OR combination of valid interrupt flags of the ACMP module * (ACMPx_IF_nnn). ******************************************************************************/ static __INLINE uint32_t ACMP_IntGetEnabled(ACMP_TypeDef *acmp) { uint32_t tmp; /* Store ACMPx->IEN in temporary variable in order to define explicit order * of volatile accesses. */ tmp = acmp->IEN; /* Bitwise AND of pending and enabled interrupts */ return acmp->IF & tmp; } /***************************************************************************//** * @brief * Set one or more pending ACMP interrupts from SW. * * @param[in] acmp * Pointer to ACMP peripheral register block. * * @param[in] flags * ACMP interrupt sources to set to pending. Use a bitwise logic OR * combination of valid interrupt flags for the ACMP module (ACMP_IF_nnn). ******************************************************************************/ static __INLINE void ACMP_IntSet(ACMP_TypeDef *acmp, uint32_t flags) { acmp->IFS = flags; } /** @} (end addtogroup ACMP) */ /** @} (end addtogroup EFM32_Library) */ #ifdef __cplusplus } #endif #endif /* __EFM32_ACMP_H */