em_pcnt.h 16 KB

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