1 /***************************************************************************//**
2 * @file
3 * @brief Low Energy Timer (LETIMER) peripheral API
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7 *******************************************************************************
8 *
9 * SPDX-License-Identifier: Zlib
10 *
11 * The licensor of this software is Silicon Laboratories Inc.
12 *
13 * This software is provided 'as-is', without any express or implied
14 * warranty. In no event will the authors be held liable for any damages
15 * arising from the use of this software.
16 *
17 * Permission is granted to anyone to use this software for any purpose,
18 * including commercial applications, and to alter it and redistribute it
19 * freely, subject to the following restrictions:
20 *
21 * 1. The origin of this software must not be misrepresented; you must not
22 * claim that you wrote the original software. If you use this software
23 * in a product, an acknowledgment in the product documentation would be
24 * appreciated but is not required.
25 * 2. Altered source versions must be plainly marked as such, and must not be
26 * misrepresented as being the original software.
27 * 3. This notice may not be removed or altered from any source distribution.
28 *
29 ******************************************************************************/
30
31 #ifndef EM_LETIMER_H
32 #define EM_LETIMER_H
33
34 #include <stdbool.h>
35 #include "em_device.h"
36 #if defined(LETIMER_COUNT) && (LETIMER_COUNT > 0)
37
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41
42 /***************************************************************************//**
43 * @addtogroup letimer
44 * @{
45 ******************************************************************************/
46
47 /*******************************************************************************
48 ******************************** ENUMS ************************************
49 ******************************************************************************/
50
51 /** Repeat mode. */
52 typedef enum {
53 /** Count until stopped by SW. */
54 letimerRepeatFree = _LETIMER_CTRL_REPMODE_FREE,
55 /** Count REP0 times. */
56 letimerRepeatOneshot = _LETIMER_CTRL_REPMODE_ONESHOT,
57 /**
58 * Count REP0 times, if REP1 has been written to, it is loaded into
59 * REP0 when REP0 is about to be decremented to 0.
60 */
61 letimerRepeatBuffered = _LETIMER_CTRL_REPMODE_BUFFERED,
62 /**
63 * Run as long as both REP0 and REP1 are not 0. Both REP0 and REP1
64 * are decremented when counter underflows.
65 */
66 letimerRepeatDouble = _LETIMER_CTRL_REPMODE_DOUBLE
67 } LETIMER_RepeatMode_TypeDef;
68
69 /** Underflow action on output. */
70 typedef enum {
71 /** No output action. */
72 letimerUFOANone = _LETIMER_CTRL_UFOA0_NONE,
73 /** Toggle output when counter underflows. */
74 letimerUFOAToggle = _LETIMER_CTRL_UFOA0_TOGGLE,
75 /** Hold output one LETIMER clock cycle when counter underflows. */
76 letimerUFOAPulse = _LETIMER_CTRL_UFOA0_PULSE,
77 /** Set output idle when counter underflows, and active when matching COMP1. */
78 letimerUFOAPwm = _LETIMER_CTRL_UFOA0_PWM
79 } LETIMER_UFOA_TypeDef;
80
81 /*******************************************************************************
82 ******************************* STRUCTS ***********************************
83 ******************************************************************************/
84
85 /** LETIMER initialization structure. */
86 typedef struct {
87 bool enable; /**< Start counting when initialization completes. */
88 bool debugRun; /**< Counter shall keep running during debug halt. */
89 #if defined(LETIMER_CTRL_RTCC0TEN)
90 bool rtcComp0Enable; /**< Start counting on RTC COMP0 match. */
91 bool rtcComp1Enable; /**< Start counting on RTC COMP1 match. */
92 #endif
93 bool comp0Top; /**< Load COMP0 register into CNT when counter underflows. */
94 bool bufTop; /**< Load COMP1 into COMP0 when REP0 reaches 0. */
95 uint8_t out0Pol; /**< Idle value for output 0. */
96 uint8_t out1Pol; /**< Idle value for output 1. */
97 LETIMER_UFOA_TypeDef ufoa0; /**< Underflow output 0 action. */
98 LETIMER_UFOA_TypeDef ufoa1; /**< Underflow output 1 action. */
99 LETIMER_RepeatMode_TypeDef repMode; /**< Repeat mode. */
100 uint32_t topValue; /**< Top value. Counter wraps when top value matches counter value is reached. */
101 } LETIMER_Init_TypeDef;
102
103 /** Default configuration for LETIMER initialization structure. */
104 #if defined(LETIMER_CTRL_RTCC0TEN)
105 #define LETIMER_INIT_DEFAULT \
106 { \
107 true, /* Enable timer when initialization completes. */ \
108 false, /* Stop counter during debug halt. */ \
109 false, /* Do not start counting on RTC COMP0 match. */ \
110 false, /* Do not start counting on RTC COMP1 match. */ \
111 false, /* Do not load COMP0 into CNT on underflow. */ \
112 false, /* Do not load COMP1 into COMP0 when REP0 reaches 0. */ \
113 0, /* Idle value 0 for output 0. */ \
114 0, /* Idle value 0 for output 1. */ \
115 letimerUFOANone, /* No action on underflow on output 0. */ \
116 letimerUFOANone, /* No action on underflow on output 1. */ \
117 letimerRepeatFree, /* Count until stopped by SW. */ \
118 0 /* Use default top Value. */ \
119 }
120 #else
121 #define LETIMER_INIT_DEFAULT \
122 { \
123 true, /* Enable timer when initialization completes. */ \
124 false, /* Stop counter during debug halt. */ \
125 false, /* Do not load COMP0 into CNT on underflow. */ \
126 false, /* Do not load COMP1 into COMP0 when REP0 reaches 0. */ \
127 0, /* Idle value 0 for output 0. */ \
128 0, /* Idle value 0 for output 1. */ \
129 letimerUFOANone, /* No action on underflow on output 0. */ \
130 letimerUFOANone, /* No action on underflow on output 1. */ \
131 letimerRepeatFree, /* Count until stopped by SW. */ \
132 0 /* Use default top Value. */ \
133 }
134 #endif
135
136 /*******************************************************************************
137 ***************************** PROTOTYPES **********************************
138 ******************************************************************************/
139
140 uint32_t LETIMER_CompareGet(LETIMER_TypeDef *letimer, unsigned int comp);
141 void LETIMER_CompareSet(LETIMER_TypeDef *letimer,
142 unsigned int comp,
143 uint32_t value);
144 uint32_t LETIMER_CounterGet(LETIMER_TypeDef *letimer);
145 #if !defined(_EFM32_GECKO_FAMILY)
146 void LETIMER_CounterSet(LETIMER_TypeDef *letimer, uint32_t value);
147 #endif
148
149 void LETIMER_Enable(LETIMER_TypeDef *letimer, bool enable);
150 #if defined(_LETIMER_FREEZE_MASK)
151 void LETIMER_FreezeEnable(LETIMER_TypeDef *letimer, bool enable);
152 #endif
153 void LETIMER_Init(LETIMER_TypeDef *letimer, const LETIMER_Init_TypeDef *init);
154
155 /***************************************************************************//**
156 * @brief
157 * Clear one or more pending LETIMER interrupts.
158 *
159 * @param[in] letimer
160 * Pointer to LETIMER peripheral register block.
161 *
162 * @param[in] flags
163 * Pending LETIMER interrupt source to clear. Use a bitwise logic OR
164 * combination of valid interrupt flags for the LETIMER module
165 * (LETIMER_IF_nnn).
166 ******************************************************************************/
LETIMER_IntClear(LETIMER_TypeDef * letimer,uint32_t flags)167 __STATIC_INLINE void LETIMER_IntClear(LETIMER_TypeDef *letimer, uint32_t flags)
168 {
169 #if defined (LETIMER_HAS_SET_CLEAR)
170 letimer->IF_CLR = flags;
171 #else
172 letimer->IFC = flags;
173 #endif
174 }
175
176 /***************************************************************************//**
177 * @brief
178 * Disable one or more LETIMER interrupts.
179 *
180 * @param[in] letimer
181 * Pointer to LETIMER peripheral register block.
182 *
183 * @param[in] flags
184 * LETIMER interrupt sources to disable. Use a bitwise logic OR combination of
185 * valid interrupt flags for the LETIMER module (LETIMER_IF_nnn).
186 ******************************************************************************/
LETIMER_IntDisable(LETIMER_TypeDef * letimer,uint32_t flags)187 __STATIC_INLINE void LETIMER_IntDisable(LETIMER_TypeDef *letimer, uint32_t flags)
188 {
189 letimer->IEN &= ~flags;
190 }
191
192 /***************************************************************************//**
193 * @brief
194 * Enable one or more LETIMER interrupts.
195 *
196 * @note
197 * Depending on the use, a pending interrupt may already be set prior to
198 * enabling the interrupt. To ignore a pending interrupt, consider using
199 * LETIMER_IntClear() prior to enabling the interrupt.
200 *
201 * @param[in] letimer
202 * Pointer to the LETIMER peripheral register block.
203 *
204 * @param[in] flags
205 * LETIMER interrupt sources to enable. Use a bitwise logic OR combination of
206 * valid interrupt flags for the LETIMER module (LETIMER_IF_nnn).
207 ******************************************************************************/
LETIMER_IntEnable(LETIMER_TypeDef * letimer,uint32_t flags)208 __STATIC_INLINE void LETIMER_IntEnable(LETIMER_TypeDef *letimer, uint32_t flags)
209 {
210 letimer->IEN |= flags;
211 }
212
213 /***************************************************************************//**
214 * @brief
215 * Get pending LETIMER interrupt flags.
216 *
217 * @note
218 * Event bits are not cleared by the use of this function.
219 *
220 * @param[in] letimer
221 * Pointer to LETIMER peripheral register block.
222 *
223 * @return
224 * LETIMER interrupt sources pending. A bitwise logic OR combination of
225 * valid interrupt flags for the LETIMER module (LETIMER_IF_nnn).
226 ******************************************************************************/
LETIMER_IntGet(LETIMER_TypeDef * letimer)227 __STATIC_INLINE uint32_t LETIMER_IntGet(LETIMER_TypeDef *letimer)
228 {
229 return letimer->IF;
230 }
231
232 /***************************************************************************//**
233 * @brief
234 * Get enabled and pending LETIMER interrupt flags.
235 *
236 * @details
237 * Useful for handling more interrupt sources in the same interrupt handler.
238 *
239 * @note
240 * Event bits are not cleared by the use of this function.
241 *
242 * @param[in] letimer
243 * Pointer to LETIMER peripheral register block.
244 *
245 * @return
246 * Pending and enabled LETIMER interrupt sources.
247 * Return value is the bitwise AND combination of
248 * - the OR combination of enabled interrupt sources in LETIMER_IEN_nnn
249 * register (LETIMER_IEN_nnn) and
250 * - the OR combination of valid interrupt flags of the LETIMER module
251 * (LETIMER_IF_nnn).
252 ******************************************************************************/
LETIMER_IntGetEnabled(LETIMER_TypeDef * letimer)253 __STATIC_INLINE uint32_t LETIMER_IntGetEnabled(LETIMER_TypeDef *letimer)
254 {
255 uint32_t ien;
256
257 /* Store flags in temporary variable in order to define explicit order
258 * of volatile accesses. */
259 ien = letimer->IEN;
260
261 /* Bitwise AND of pending and enabled interrupts */
262 return letimer->IF & ien;
263 }
264
265 /***************************************************************************//**
266 * @brief
267 * Set one or more pending LETIMER interrupts from SW.
268 *
269 * @param[in] letimer
270 * Pointer to LETIMER peripheral register block.
271 *
272 * @param[in] flags
273 * LETIMER interrupt sources to set to pending. Use a bitwise logic OR
274 * combination of valid interrupt flags for the LETIMER module (LETIMER_IF_nnn).
275 ******************************************************************************/
LETIMER_IntSet(LETIMER_TypeDef * letimer,uint32_t flags)276 __STATIC_INLINE void LETIMER_IntSet(LETIMER_TypeDef *letimer, uint32_t flags)
277 {
278 #if defined (LETIMER_HAS_SET_CLEAR)
279 letimer->IF_SET = flags;
280 #else
281 letimer->IFS = flags;
282 #endif
283 }
284
285 #if defined(_LETIMER_LOCK_MASK)
286 /***************************************************************************//**
287 * @brief
288 * Locks LETIMER registers.
289 *
290 * @param[in] letimer
291 * Pointer to LETIMER peripheral register block.
292 *
293 * @note When LETIMER registers are locked LETIMER_EN, LETIMER_SWRST,
294 * LETIMER_CTRL, LETIMER_CMD, LETIMER_CNT, LETIMER_COMPx,
295 * LETIMER_TOP, LETIMER_TOPBUFF, LETIMER_REPx, and PRSMODE registers
296 * cannot be written to.
297 ******************************************************************************/
LETIMER_Lock(LETIMER_TypeDef * letimer)298 __STATIC_INLINE void LETIMER_Lock(LETIMER_TypeDef *letimer)
299 {
300 letimer->LOCK = ~LETIMER_LOCK_LETIMERLOCKKEY_UNLOCK;
301 }
302 #endif
303
304 #if defined(_LETIMER_LOCK_MASK)
305 /***************************************************************************//**
306 * @brief
307 * Unlocks LETIMER registers.
308 *
309 * @param[in] letimer
310 * Pointer to LETIMER peripheral register block.
311 ******************************************************************************/
LETIMER_Unlock(LETIMER_TypeDef * letimer)312 __STATIC_INLINE void LETIMER_Unlock(LETIMER_TypeDef *letimer)
313 {
314 letimer->LOCK = LETIMER_LOCK_LETIMERLOCKKEY_UNLOCK;
315 }
316 #endif
317
318 uint32_t LETIMER_RepeatGet(LETIMER_TypeDef *letimer, unsigned int rep);
319 void LETIMER_RepeatSet(LETIMER_TypeDef *letimer,
320 unsigned int rep,
321 uint32_t value);
322 void LETIMER_Reset(LETIMER_TypeDef *letimer);
323 void LETIMER_SyncWait(LETIMER_TypeDef *letimer);
324 void LETIMER_TopSet(LETIMER_TypeDef *letimer, uint32_t value);
325 uint32_t LETIMER_TopGet(LETIMER_TypeDef *letimer);
326
327 /** @} (end addtogroup letimer) */
328
329 #ifdef __cplusplus
330 }
331 #endif
332
333 #endif /* defined(LETIMER_COUNT) && (LETIMER_COUNT > 0) */
334 #endif /* EM_LETIMER_H */
335