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