efm32_pcnt.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. /***************************************************************************//**
  2. * @file
  3. * @brief Pulse Counter (PCNT) peripheral API for EFM32.
  4. * @author Energy Micro AS
  5. * @version 2.0.0
  6. *******************************************************************************
  7. * @section License
  8. * <b>(C) Copyright 2010 Energy Micro AS, http://www.energymicro.com</b>
  9. *******************************************************************************
  10. *
  11. * This source code is the property of Energy Micro AS. The source and compiled
  12. * code may only be used on Energy Micro "EFM32" microcontrollers.
  13. *
  14. * This copyright notice may not be removed from the source code nor changed.
  15. *
  16. * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
  17. * obligation to support this Software. Energy Micro AS is providing the
  18. * Software "AS IS", with no express or implied warranties of any kind,
  19. * including, but not limited to, any implied warranties of merchantability
  20. * or fitness for any particular purpose or warranties against infringement
  21. * of any proprietary rights of a third party.
  22. *
  23. * Energy Micro AS will not be liable for any consequential, incidental, or
  24. * special damages, or any other relief, or for any claim by any third party,
  25. * arising from your use of this Software.
  26. *
  27. ******************************************************************************/
  28. #ifndef __EFM32_PCNT_H
  29. #define __EFM32_PCNT_H
  30. #include <stdbool.h>
  31. #include "efm32.h"
  32. #ifdef __cplusplus
  33. extern "C" {
  34. #endif
  35. /***************************************************************************//**
  36. * @addtogroup EFM32_Library
  37. * @{
  38. ******************************************************************************/
  39. /***************************************************************************//**
  40. * @addtogroup PCNT
  41. * @{
  42. ******************************************************************************/
  43. /*******************************************************************************
  44. ******************************** ENUMS ************************************
  45. ******************************************************************************/
  46. /** Mode selection. */
  47. typedef enum
  48. {
  49. /** Disable pulse counter. */
  50. pcntModeDisable = _PCNT_CTRL_MODE_DISABLE,
  51. /** Single input LFACLK oversampling mode (available in EM0-EM2). */
  52. pcntModeOvsSingle = _PCNT_CTRL_MODE_OVSSINGLE,
  53. /** Externally clocked single input counter mode (available in EM0-EM3). */
  54. pcntModeExtSingle = _PCNT_CTRL_MODE_EXTCLKSINGLE,
  55. /** Externally clocked quadrature decoder mode (available in EM0-EM3). */
  56. pcntModeExtQuad = _PCNT_CTRL_MODE_EXTCLKQUAD
  57. } PCNT_Mode_TypeDef;
  58. #if (defined (_EFM32_TINY_FAMILY) || defined (_EFM32_GIANT_FAMILY))
  59. /** Counter event selection.
  60. * Note: unshifted values are being used for enumeration because multiple
  61. * configuration structure members use this type definition. */
  62. typedef enum
  63. {
  64. /** Counts up on up-count and down on down-count events. */
  65. pcntCntEventBoth = _PCNT_CTRL_CNTEV_BOTH,
  66. /** Only counts up on up-count events. */
  67. pcntCntEventUp = _PCNT_CTRL_CNTEV_UP,
  68. /** Only counts down on down-count events. */
  69. pcntCntEventDown = _PCNT_CTRL_CNTEV_DOWN,
  70. /** Never counts. */
  71. pcntCntEventNone = _PCNT_CTRL_CNTEV_NONE
  72. } PCNT_CntEvent_TypeDef;
  73. /** PRS sources for @p s0PRS and @p s1PRS. */
  74. typedef enum
  75. {
  76. pcntPRSCh0 = 0, /**< PRS channel 0. */
  77. pcntPRSCh1 = 1, /**< PRS channel 1. */
  78. pcntPRSCh2 = 2, /**< PRS channel 2. */
  79. pcntPRSCh3 = 3, /**< PRS channel 3. */
  80. pcntPRSCh4 = 4, /**< PRS channel 4. */
  81. pcntPRSCh5 = 5, /**< PRS channel 5. */
  82. pcntPRSCh6 = 6, /**< PRS channel 6. */
  83. pcntPRSCh7 = 7 /**< PRS channel 7. */
  84. } PCNT_PRSSel_TypeDef;
  85. /** PRS inputs of PCNT. */
  86. typedef enum
  87. {
  88. pcntPRSInputS0 = 0, /** PRS input 0. */
  89. pcntPRSInputS1 = 1 /** PRS input 1. */
  90. } PCNT_PRSInput_TypeDef;
  91. #endif
  92. /*******************************************************************************
  93. ******************************* STRUCTS ***********************************
  94. ******************************************************************************/
  95. /** Init structure. */
  96. typedef struct
  97. {
  98. /** Mode to operate in. */
  99. PCNT_Mode_TypeDef mode;
  100. /** Initial counter value (refer to reference manual for max value allowed).
  101. * Only used for #pcntModeOvsSingle (and possibly #pcntModeDisable) modes.
  102. * If using #pcntModeExtSingle or #pcntModeExtQuad modes, the counter
  103. * value is reset to HW reset value. */
  104. uint32_t counter;
  105. /** Initial top value (refer to reference manual for max value allowed).
  106. * Only used for #pcntModeOvsSingle (and possibly #pcntModeDisable) modes.
  107. * If using #pcntModeExtSingle or #pcntModeExtQuad modes, the top
  108. * value is reset to HW reset value. */
  109. uint32_t top;
  110. /** Polarity of incoming edge.
  111. * @li #pcntModeExtSingle mode - if false, positive edges are counted,
  112. * otherwise negative edges.
  113. * @li #pcntModeExtQuad mode - if true, counting direction is inverted. */
  114. bool negEdge;
  115. /** Counting direction, only applicable for #pcntModeOvsSingle and
  116. * #pcntModeExtSingle modes. */
  117. bool countDown;
  118. /** Enable filter, only available in #pcntModeOvsSingle mode. */
  119. bool filter;
  120. #if (defined (_EFM32_TINY_FAMILY) || defined (_EFM32_GIANT_FAMILY))
  121. /** Set to true to enable hysteresis. When its enabled, the PCNT will always
  122. * overflow and underflow to TOP/2. */
  123. bool hyst;
  124. /** Set to true to enable S1 to determine the direction of counting in
  125. * OVSSINGLE or EXTCLKSINGLE modes.
  126. * When S1 is high, the count direction is given by CNTDIR, and when S1 is
  127. * low, the count direction is the opposite. */
  128. bool s1CntDir;
  129. /** Selects whether the regular counter responds to up-count events,
  130. * down-count events, both or none. */
  131. PCNT_CntEvent_TypeDef cntEvent;
  132. /** Selects whether the auxiliary counter responds to up-count events,
  133. * down-count events, both or none. */
  134. PCNT_CntEvent_TypeDef auxCntEvent;
  135. /** Select PRS channel as input to S0IN in PCNTx_INPUT register. */
  136. PCNT_PRSSel_TypeDef s0PRS;
  137. /** Select PRS channel as input to S1IN in PCNTx_INPUT register. */
  138. PCNT_PRSSel_TypeDef s1PRS;
  139. #endif
  140. } PCNT_Init_TypeDef;
  141. /** Default config for PCNT init structure. */
  142. #if defined (_EFM32_GECKO_FAMILY)
  143. #define PCNT_INIT_DEFAULT \
  144. { pcntModeDisable, /* Disabled by default. */ \
  145. _PCNT_CNT_RESETVALUE, /* Default counter HW reset value. */ \
  146. _PCNT_TOP_RESETVALUE, /* Default counter HW reset value. */ \
  147. false, /* Use positive edge. */ \
  148. false, /* Up-counting. */ \
  149. false /* Filter disabled. */ \
  150. }
  151. #elif (defined (_EFM32_TINY_FAMILY) || defined (_EFM32_GIANT_FAMILY))
  152. #define PCNT_INIT_DEFAULT \
  153. { pcntModeDisable, /* Disabled by default. */ \
  154. _PCNT_CNT_RESETVALUE, /* Default counter HW reset value. */ \
  155. _PCNT_TOP_RESETVALUE, /* Default counter HW reset value. */ \
  156. false, /* Use positive edge. */ \
  157. false, /* Up-counting. */ \
  158. false, /* Filter disabled. */ \
  159. false, /* Hysteresis disabled. */ \
  160. true, /* Counter direction is given by CNTDIR. */ \
  161. pcntCntEventUp, /* Regular counter counts up on upcount events. */ \
  162. pcntCntEventNone, /* Auxiliary counter doesn't respond to events. */ \
  163. pcntPRSCh0, /* PRS channel 0 selected as S0IN. */ \
  164. pcntPRSCh0 /* PRS channel 0 selected as S1IN. */ \
  165. }
  166. #endif
  167. /*******************************************************************************
  168. ***************************** PROTOTYPES **********************************
  169. ******************************************************************************/
  170. /***************************************************************************//**
  171. * @brief
  172. * Get pulse counter value.
  173. *
  174. * @param[in] pcnt
  175. * Pointer to PCNT peripheral register block.
  176. *
  177. * @return
  178. * Current pulse counter value.
  179. ******************************************************************************/
  180. static __INLINE uint32_t PCNT_CounterGet(PCNT_TypeDef *pcnt)
  181. {
  182. return pcnt->CNT;
  183. }
  184. #if (defined (_EFM32_TINY_FAMILY) || defined (_EFM32_GIANT_FAMILY))
  185. /***************************************************************************//**
  186. * @brief
  187. * Get auxiliary counter value.
  188. *
  189. * @param[in] pcnt
  190. * Pointer to PCNT peripheral register block.
  191. *
  192. * @return
  193. * Current auxiliary counter value.
  194. ******************************************************************************/
  195. static __INLINE uint32_t PCNT_AuxCounterGet(PCNT_TypeDef *pcnt)
  196. {
  197. return pcnt->AUXCNT;
  198. }
  199. #endif
  200. void PCNT_CounterReset(PCNT_TypeDef *pcnt);
  201. void PCNT_CounterTopSet(PCNT_TypeDef *pcnt, uint32_t count, uint32_t top);
  202. /***************************************************************************//**
  203. * @brief
  204. * Set counter value.
  205. *
  206. * @details
  207. * The pulse counter is disabled while changing counter value, and reenabled
  208. * (if originally enabled) when counter value has been set.
  209. *
  210. * @note
  211. * This function will stall until synchronization to low frequency domain is
  212. * completed. For that reason, it should normally not be used when using
  213. * an external clock to clock the PCNT module, since stall time may be
  214. * undefined in that case. The counter should normally only be set when
  215. * operating in (or about to enable) #pcntModeOvsSingle mode.
  216. *
  217. * @param[in] pcnt
  218. * Pointer to PCNT peripheral register block.
  219. *
  220. * @param[in] count
  221. * Value to set in counter register.
  222. ******************************************************************************/
  223. static __INLINE void PCNT_CounterSet(PCNT_TypeDef *pcnt, uint32_t count)
  224. {
  225. PCNT_CounterTopSet(pcnt, count, pcnt->TOP);
  226. }
  227. void PCNT_Enable(PCNT_TypeDef *pcnt, PCNT_Mode_TypeDef mode);
  228. void PCNT_FreezeEnable(PCNT_TypeDef *pcnt, bool enable);
  229. void PCNT_Init(PCNT_TypeDef *pcnt, const PCNT_Init_TypeDef *init);
  230. #if (defined (_EFM32_TINY_FAMILY) || defined (_EFM32_GIANT_FAMILY))
  231. void PCNT_PRSInputEnable(PCNT_TypeDef *pcnt,
  232. PCNT_PRSInput_TypeDef prsInput,
  233. bool enable);
  234. #endif
  235. /***************************************************************************//**
  236. * @brief
  237. * Clear one or more pending PCNT interrupts.
  238. *
  239. * @param[in] pcnt
  240. * Pointer to PCNT peripheral register block.
  241. *
  242. * @param[in] flags
  243. * Pending PCNT interrupt source to clear. Use a bitwise logic OR combination
  244. * of valid interrupt flags for the PCNT module (PCNT_IF_nnn).
  245. ******************************************************************************/
  246. static __INLINE void PCNT_IntClear(PCNT_TypeDef *pcnt, uint32_t flags)
  247. {
  248. pcnt->IFC = flags;
  249. }
  250. /***************************************************************************//**
  251. * @brief
  252. * Disable one or more PCNT interrupts.
  253. *
  254. * @param[in] pcnt
  255. * Pointer to PCNT peripheral register block.
  256. *
  257. * @param[in] flags
  258. * PCNT interrupt sources to disable. Use a bitwise logic OR combination of
  259. * valid interrupt flags for the PCNT module (PCNT_IF_nnn).
  260. ******************************************************************************/
  261. static __INLINE void PCNT_IntDisable(PCNT_TypeDef *pcnt, uint32_t flags)
  262. {
  263. pcnt->IEN &= ~(flags);
  264. }
  265. /***************************************************************************//**
  266. * @brief
  267. * Enable one or more PCNT interrupts.
  268. *
  269. * @note
  270. * Depending on the use, a pending interrupt may already be set prior to
  271. * enabling the interrupt. Consider using PCNT_IntClear() prior to enabling
  272. * if such a pending interrupt should be ignored.
  273. *
  274. * @param[in] pcnt
  275. * Pointer to PCNT peripheral register block.
  276. *
  277. * @param[in] flags
  278. * PCNT interrupt sources to enable. Use a bitwise logic OR combination of
  279. * valid interrupt flags for the PCNT module (PCNT_IF_nnn).
  280. ******************************************************************************/
  281. static __INLINE void PCNT_IntEnable(PCNT_TypeDef *pcnt, uint32_t flags)
  282. {
  283. pcnt->IEN |= flags;
  284. }
  285. /***************************************************************************//**
  286. * @brief
  287. * Get pending PCNT interrupt flags.
  288. *
  289. * @note
  290. * The event bits are not cleared by the use of this function.
  291. *
  292. * @param[in] pcnt
  293. * Pointer to PCNT peripheral register block.
  294. *
  295. * @return
  296. * PCNT interrupt sources pending. A bitwise logic OR combination of valid
  297. * interrupt flags for the PCNT module (PCNT_IF_nnn).
  298. ******************************************************************************/
  299. static __INLINE uint32_t PCNT_IntGet(PCNT_TypeDef *pcnt)
  300. {
  301. return pcnt->IF;
  302. }
  303. /***************************************************************************//**
  304. * @brief
  305. * Get enabled and pending PCNT interrupt flags.
  306. *
  307. * @details
  308. * Useful for handling more interrupt sources in the same interrupt handler.
  309. *
  310. * @note
  311. * The event bits are not cleared by the use of this function.
  312. *
  313. * @param[in] pcnt
  314. * Pointer to PCNT peripheral register block.
  315. *
  316. * @return
  317. * Pending and enabled PCNT interrupt sources.
  318. * The return value is the bitwise AND combination of
  319. * - the OR combination of enabled interrupt sources in PCNT_IEN_nnn
  320. * register (PCNT_IEN_nnn) and
  321. * - the OR combination of valid interrupt flags of the PCNT module
  322. * (PCNT_IF_nnn).
  323. ******************************************************************************/
  324. static __INLINE uint32_t PCNT_IntGetEnabled(PCNT_TypeDef *pcnt)
  325. {
  326. uint32_t tmp = 0U;
  327. /* Store pcnt->IEN in temporary variable in order to define explicit order
  328. * of volatile accesses. */
  329. tmp = pcnt->IEN;
  330. /* Bitwise AND of pending and enabled interrupts */
  331. return pcnt->IF & tmp;
  332. }
  333. /***************************************************************************//**
  334. * @brief
  335. * Set one or more pending PCNT interrupts from SW.
  336. *
  337. * @param[in] pcnt
  338. * Pointer to PCNT peripheral register block.
  339. *
  340. * @param[in] flags
  341. * PCNT interrupt sources to set to pending. Use a bitwise logic OR combination
  342. * of valid interrupt flags for the PCNT module (PCNT_IF_nnn).
  343. ******************************************************************************/
  344. static __INLINE void PCNT_IntSet(PCNT_TypeDef *pcnt, uint32_t flags)
  345. {
  346. pcnt->IFS = flags;
  347. }
  348. void PCNT_Reset(PCNT_TypeDef *pcnt);
  349. /***************************************************************************//**
  350. * @brief
  351. * Get pulse counter top buffer value.
  352. *
  353. * @param[in] pcnt
  354. * Pointer to PCNT peripheral register block.
  355. *
  356. * @return
  357. * Current pulse counter top buffer value.
  358. ******************************************************************************/
  359. static __INLINE uint32_t PCNT_TopBufferGet(PCNT_TypeDef *pcnt)
  360. {
  361. return pcnt->TOPB;
  362. }
  363. void PCNT_TopBufferSet(PCNT_TypeDef *pcnt, uint32_t val);
  364. /***************************************************************************//**
  365. * @brief
  366. * Get pulse counter top value.
  367. *
  368. * @param[in] pcnt
  369. * Pointer to PCNT peripheral register block.
  370. *
  371. * @return
  372. * Current pulse counter top value.
  373. ******************************************************************************/
  374. static __INLINE uint32_t PCNT_TopGet(PCNT_TypeDef *pcnt)
  375. {
  376. return pcnt->TOP;
  377. }
  378. void PCNT_TopSet(PCNT_TypeDef *pcnt, uint32_t val);
  379. /** @} (end addtogroup PCNT) */
  380. /** @} (end addtogroup EFM32_Library) */
  381. #ifdef __cplusplus
  382. }
  383. #endif
  384. #endif /* __EFM32_PCNT_H */