/***************************************************************************//**
* @file
* @brief Pulse Counter (PCNT) peripheral API for EFM32.
* @author Energy Micro AS
* @version 1.3.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_PCNT_H
#define __EFM32_PCNT_H
#include
#include "efm32.h"
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup EFM32_Library
* @{
******************************************************************************/
/***************************************************************************//**
* @addtogroup PCNT
* @{
******************************************************************************/
/*******************************************************************************
******************************* DEFINES ***********************************
******************************************************************************/
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
/** PCNT counter width mask. */
/* TBD: Remove use with efm32 include file defines when corrected */
#define PCNT_WIDTH_MASK 0xff
/** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */
/*******************************************************************************
******************************** ENUMS ************************************
******************************************************************************/
/** Mode selection. */
typedef enum
{
/** Disable pulse counter. */
pcntModeDisable = _PCNT_CTRL_MODE_DISABLE,
/** Single input LFACLK oversampling mode (available in EM0-EM2). */
pcntModeOvsSingle = _PCNT_CTRL_MODE_OVSSINGLE,
/** Externally clocked single input counter mode (available in EM0-EM3). */
pcntModeExtSingle = _PCNT_CTRL_MODE_EXTCLKSINGLE,
/** Externally clocked quadrature decoder mode (available in EM0-EM3). */
pcntModeExtQuad = _PCNT_CTRL_MODE_EXTCLKQUAD
} PCNT_Mode_TypeDef;
/*******************************************************************************
******************************* STRUCTS ***********************************
******************************************************************************/
/** Init structure. */
typedef struct
{
/** Mode to operate in. */
PCNT_Mode_TypeDef mode;
/**
* Initial counter value (refer to reference manual for max value allowed).
* Only used for #pcntModeOvsSingle (and possibly #pcntModeDisable) modes.
* If using #pcntModeExtSingle or #pcntModeExtQuad modes, the counter
* value is reset to HW reset value.
*/
uint32_t counter;
/**
* Initial top value (refer to reference manual for max value allowed).
* Only used for #pcntModeOvsSingle (and possibly #pcntModeDisable) modes.
* If using #pcntModeExtSingle or #pcntModeExtQuad modes, the top
* value is reset to HW reset value.
*/
uint32_t top;
/**
* Polarity of incoming edge.
* @li #pcntModeExtSingle mode - if false, positive edges are counted,
* otherwise negative edges.
* @li #pcntModeExtQuad mode - if true, counting direction is inverted.
*/
bool negEdge;
/**
* Counting direction, only applicable for #pcntModeOvsSingle and
* #pcntModeExtSingle modes.
*/
bool countDown;
/** Enable filter, only available in #pcntModeOvsSingle mode. */
bool filter;
} PCNT_Init_TypeDef;
/** Default config for PCNT init structure. */
/* TBD: Remove PCNT_WIDTH_MASK use when _PCNT_TOP_RESETVALUE corrected */
#define PCNT_INIT_DEFAULT \
{ pcntModeDisable, /* Disabled by default. */ \
_PCNT_CNT_RESETVALUE, /* Default counter HW reset value. */ \
_PCNT_TOP_RESETVALUE & PCNT_WIDTH_MASK, /* Default counter HW reset value. */ \
false, /* Use positive edge. */ \
false, /* Up-counting. */ \
false /* Filter disabled. */ \
}
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
/***************************************************************************//**
* @brief
* Get pulse counter value.
*
* @param[in] pcnt
* Pointer to PCNT peripheral register block.
*
* @return
* Current pulse counter value.
******************************************************************************/
static __INLINE uint32_t PCNT_CounterGet(PCNT_TypeDef *pcnt)
{
return(pcnt->CNT);
}
void PCNT_CounterReset(PCNT_TypeDef *pcnt);
void PCNT_CounterTopSet(PCNT_TypeDef *pcnt, uint32_t count, uint32_t top);
/***************************************************************************//**
* @brief
* Set counter value.
*
* @details
* The pulse counter is disabled while changing counter value, and reenabled
* (if originally enabled) when counter value has been set.
*
* @note
* This function will stall until synchronization to low frequency domain is
* completed. For that reason, it should normally not be used when using
* an external clock to clock the PCNT module, since stall time may be
* undefined in that case. The counter should normally only be set when
* operating in (or about to enable) #pcntModeOvsSingle mode.
*
* @param[in] pcnt
* Pointer to PCNT peripheral register block.
*
* @param[in] count
* Value to set in counter register.
******************************************************************************/
static __INLINE void PCNT_CounterSet(PCNT_TypeDef *pcnt, uint32_t count)
{
PCNT_CounterTopSet(pcnt, count, pcnt->TOP);
}
void PCNT_Enable(PCNT_TypeDef *pcnt, PCNT_Mode_TypeDef mode);
void PCNT_FreezeEnable(PCNT_TypeDef *pcnt, bool enable);
void PCNT_Init(PCNT_TypeDef *pcnt, PCNT_Init_TypeDef *init);
/***************************************************************************//**
* @brief
* Clear one or more pending PCNT interrupts.
*
* @param[in] pcnt
* Pointer to PCNT peripheral register block.
*
* @param[in] flags
* Pending PCNT interrupt source to clear. Use a logical OR combination
* of valid interrupt flags for the PCNT module (PCNT_IF_nnn).
******************************************************************************/
static __INLINE void PCNT_IntClear(PCNT_TypeDef *pcnt, uint32_t flags)
{
pcnt->IFC = flags;
}
/***************************************************************************//**
* @brief
* Disable one or more PCNT interrupts.
*
* @param[in] pcnt
* Pointer to PCNT peripheral register block.
*
* @param[in] flags
* PCNT interrupt sources to disable. Use a logical OR combination of
* valid interrupt flags for the PCNT module (PCNT_IF_nnn).
******************************************************************************/
static __INLINE void PCNT_IntDisable(PCNT_TypeDef *pcnt, uint32_t flags)
{
pcnt->IEN &= ~(flags);
}
/***************************************************************************//**
* @brief
* Enable one or more PCNT interrupts.
*
* @note
* Depending on the use, a pending interrupt may already be set prior to
* enabling the interrupt. Consider using PCNT_IntClear() prior to enabling
* if such a pending interrupt should be ignored.
*
* @param[in] pcnt
* Pointer to PCNT peripheral register block.
*
* @param[in] flags
* PCNT interrupt sources to enable. Use a logical OR combination of
* valid interrupt flags for the PCNT module (PCNT_IF_nnn).
******************************************************************************/
static __INLINE void PCNT_IntEnable(PCNT_TypeDef *pcnt, uint32_t flags)
{
pcnt->IEN |= flags;
}
/***************************************************************************//**
* @brief
* Get pending PCNT interrupt flags.
*
* @note
* The event bits are not cleared by the use of this function.
*
* @param[in] pcnt
* Pointer to PCNT peripheral register block.
*
* @return
* PCNT interrupt sources pending. A logical OR combination of valid
* interrupt flags for the PCNT module (PCNT_IF_nnn).
******************************************************************************/
static __INLINE uint32_t PCNT_IntGet(PCNT_TypeDef *pcnt)
{
return(pcnt->IF);
}
/***************************************************************************//**
* @brief
* Set one or more pending PCNT interrupts from SW.
*
* @param[in] pcnt
* Pointer to PCNT peripheral register block.
*
* @param[in] flags
* PCNT interrupt sources to set to pending. Use a logical OR combination
* of valid interrupt flags for the PCNT module (PCNT_IF_nnn).
******************************************************************************/
static __INLINE void PCNT_IntSet(PCNT_TypeDef *pcnt, uint32_t flags)
{
pcnt->IFS = flags;
}
void PCNT_Reset(PCNT_TypeDef *pcnt);
/***************************************************************************//**
* @brief
* Get pulse counter top buffer value.
*
* @param[in] pcnt
* Pointer to PCNT peripheral register block.
*
* @return
* Current pulse counter top buffer value.
******************************************************************************/
static __INLINE uint32_t PCNT_TopBufferGet(PCNT_TypeDef *pcnt)
{
return(pcnt->TOPB);
}
void PCNT_TopBufferSet(PCNT_TypeDef *pcnt, uint32_t val);
/***************************************************************************//**
* @brief
* Get pulse counter top value.
*
* @param[in] pcnt
* Pointer to PCNT peripheral register block.
*
* @return
* Current pulse counter top value.
******************************************************************************/
static __INLINE uint32_t PCNT_TopGet(PCNT_TypeDef *pcnt)
{
return(pcnt->TOP);
}
void PCNT_TopSet(PCNT_TypeDef *pcnt, uint32_t val);
/** @} (end addtogroup PCNT) */
/** @} (end addtogroup EFM32_Library) */
#ifdef __cplusplus
}
#endif
#endif /* __EFM32_PCNT_H */