1 /***************************************************************************//**
2  * @file
3  * @brief Voltage Comparator (VCMP) 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_VCMP_H
32 #define EM_VCMP_H
33 
34 #include "em_device.h"
35 #if defined(VCMP_COUNT) && (VCMP_COUNT > 0)
36 
37 #include <stdint.h>
38 #include <stdbool.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /***************************************************************************//**
45  * @addtogroup vcmp
46  * @{
47  ******************************************************************************/
48 
49 /*******************************************************************************
50  ********************************   ENUMS   ************************************
51  ******************************************************************************/
52 
53 /** Warm-up Time in High Frequency Peripheral Clock cycles. */
54 typedef enum {
55   /** 4 cycles */
56   vcmpWarmTime4Cycles   = _VCMP_CTRL_WARMTIME_4CYCLES,
57   /** 8 cycles */
58   vcmpWarmTime8Cycles   = _VCMP_CTRL_WARMTIME_8CYCLES,
59   /** 16 cycles */
60   vcmpWarmTime16Cycles  = _VCMP_CTRL_WARMTIME_16CYCLES,
61   /** 32 cycles */
62   vcmpWarmTime32Cycles  = _VCMP_CTRL_WARMTIME_32CYCLES,
63   /** 64 cycles */
64   vcmpWarmTime64Cycles  = _VCMP_CTRL_WARMTIME_64CYCLES,
65   /** 128 cycles */
66   vcmpWarmTime128Cycles = _VCMP_CTRL_WARMTIME_128CYCLES,
67   /** 256 cycles */
68   vcmpWarmTime256Cycles = _VCMP_CTRL_WARMTIME_256CYCLES,
69   /** 512 cycles */
70   vcmpWarmTime512Cycles = _VCMP_CTRL_WARMTIME_512CYCLES
71 } VCMP_WarmTime_TypeDef;
72 
73 /** Hysteresis configuration. */
74 typedef enum {
75   /** Normal operation, no hysteresis. */
76   vcmpHystNone,
77   /** Digital output will not toggle until positive edge is at least
78    *  20 mV above or below negative input voltage. */
79   vcmpHyst20mV
80 } VCMP_Hysteresis_TypeDef;
81 
82 /*******************************************************************************
83  *******************************   STRUCTS   ***********************************
84  ******************************************************************************/
85 
86 /** VCMP Initialization structure. */
87 typedef struct {
88   /** If set to true, reduces the bias current by half.  */
89   bool                    halfBias;
90   /** BIAS current configuration, depends on Half Bias setting above,
91    *  see reference manual for more information. */
92   int                     biasProg;
93   /** Enable interrupt for falling edge. */
94   bool                    irqFalling;
95   /** Enable interrupt for rising edge. */
96   bool                    irqRising;
97   /** Warm-up time in clock cycles. */
98   VCMP_WarmTime_TypeDef   warmup;
99   /** Hysteresis configuration */
100   VCMP_Hysteresis_TypeDef hyst;
101   /** Output value when comparator is inactive, should be 0 or 1. */
102   int                     inactive;
103   /** Enable low power mode for VDD and band gap reference. */
104   bool                    lowPowerRef;
105   /** Trigger level, according to formula:
106    *  VDD Trigger Level = 1.667V + 0.034V x triggerLevel */
107   int                     triggerLevel;
108   /** Enable VCMP after configuration. */
109   bool                    enable;
110 } VCMP_Init_TypeDef;
111 
112 /** Default VCMP initialization structure. */
113 #define VCMP_INIT_DEFAULT                                                    \
114   {                                                                          \
115     true,              /** Half Bias enabled. */                             \
116     0x7,               /** Bias current 0.7 uA when half bias is enabled. */ \
117     false,             /** Falling edge sense not enabled. */                \
118     false,             /** Rising edge sense not enabled. */                 \
119     vcmpWarmTime4Cycles, /** 4 clock cycles warm-up time. */                 \
120     vcmpHystNone,      /** No hysteresis. */                                 \
121     0,                 /** 0 in digital output when inactive. */             \
122     true,              /** Do not use low power reference. */                \
123     39,                /** Trigger level just below 3V. */                   \
124     true,              /** Enable after initialization. */                   \
125   }
126 
127 /*******************************************************************************
128  *****************************   PROTOTYPES   **********************************
129  ******************************************************************************/
130 
131 void VCMP_Init(const VCMP_Init_TypeDef *vcmpInit);
132 void VCMP_LowPowerRefSet(bool enable);
133 void VCMP_TriggerSet(int level);
134 
135 /***************************************************************************//**
136  * @brief
137  *   Enable Voltage Comparator.
138  ******************************************************************************/
VCMP_Enable(void)139 __STATIC_INLINE void VCMP_Enable(void)
140 {
141   VCMP->CTRL |= VCMP_CTRL_EN;
142 }
143 
144 /***************************************************************************//**
145  * @brief
146  *   Disable Voltage Comparator.
147  ******************************************************************************/
VCMP_Disable(void)148 __STATIC_INLINE void VCMP_Disable(void)
149 {
150   VCMP->CTRL &= ~VCMP_CTRL_EN;
151 }
152 
153 /***************************************************************************//**
154  * @brief
155  *   Calculate voltage to trigger level.
156  *
157  * @note
158  *   Soft float support is needed for this function to work.
159  *
160  * @param[in] v
161  *   Voltage Level for trigger.
162  *
163  * @return
164  *   Trigger level.
165  ******************************************************************************/
VCMP_VoltageToLevel(float v)166 __STATIC_INLINE uint32_t VCMP_VoltageToLevel(float v)
167 {
168   return (uint32_t)((v - (float)1.667) / (float)0.034);
169 }
170 
171 /***************************************************************************//**
172  * @brief
173  *   Check whether VDD is lower than the trigger level.
174  *
175  * @return
176  *   True if Voltage Comparator indicated VDD < trigger level, else
177  *   returns false.
178  ******************************************************************************/
VCMP_VDDLower(void)179 __STATIC_INLINE bool VCMP_VDDLower(void)
180 {
181   if (VCMP->STATUS & VCMP_STATUS_VCMPOUT) {
182     return false;
183   } else {
184     return true;
185   }
186 }
187 
188 /***************************************************************************//**
189  * @brief
190  *   Check whether VDD is higher than the trigger level.
191  *
192  * @return
193  *   True if Voltage Comparator indicated VDD > trigger level, else
194  *   returns false.
195  ******************************************************************************/
VCMP_VDDHigher(void)196 __STATIC_INLINE bool VCMP_VDDHigher(void)
197 {
198   if (VCMP->STATUS & VCMP_STATUS_VCMPOUT) {
199     return true;
200   } else {
201     return false;
202   }
203 }
204 
205 /***************************************************************************//**
206  * @brief
207  *    Check whether the VCMP output is ready.
208  *
209  * @return
210  *   True if VCMP output is ready.
211  ******************************************************************************/
VCMP_Ready(void)212 __STATIC_INLINE bool VCMP_Ready(void)
213 {
214   if (VCMP->STATUS & VCMP_STATUS_VCMPACT) {
215     return true;
216   } else {
217     return false;
218   }
219 }
220 
221 /***************************************************************************//**
222  * @brief
223  *   Clear one or more pending VCMP interrupts.
224  *
225  * @param[in] flags
226  *   VCMP interrupt sources to clear. Use a set of interrupt flags OR-ed
227  *   together to clear multiple interrupt sources for the VCMP module
228  *   (VCMP_IFS_nnn).
229  ******************************************************************************/
VCMP_IntClear(uint32_t flags)230 __STATIC_INLINE void VCMP_IntClear(uint32_t flags)
231 {
232   VCMP->IFC = flags;
233 }
234 
235 /***************************************************************************//**
236  * @brief
237  *   Set one or more pending VCMP interrupts from SW.
238  *
239  * @param[in] flags
240  *   VCMP interrupt sources to set to pending. Use a set of interrupt flags
241  *   OR-ed together to set multiple interrupt sources for the VCMP module
242  *   (VCMP_IFS_nnn).
243  ******************************************************************************/
VCMP_IntSet(uint32_t flags)244 __STATIC_INLINE void VCMP_IntSet(uint32_t flags)
245 {
246   VCMP->IFS = flags;
247 }
248 
249 /***************************************************************************//**
250  * @brief
251  *   Disable one or more VCMP interrupts.
252  *
253  * @param[in] flags
254  *   VCMP interrupt sources to enable. Use a set of interrupt flags OR-ed
255  *   together to set multiple interrupt sources for the VCMP module
256  *   (VCMP_IFS_nnn).
257  ******************************************************************************/
VCMP_IntDisable(uint32_t flags)258 __STATIC_INLINE void VCMP_IntDisable(uint32_t flags)
259 {
260   VCMP->IEN &= ~flags;
261 }
262 
263 /***************************************************************************//**
264  * @brief
265  *   Enable one or more VCMP interrupts.
266  *
267  * @param[in] flags
268  *   VCMP interrupt sources to enable. Use a set of interrupt flags OR-ed
269  *   together to set multiple interrupt sources for the VCMP module
270  *   (VCMP_IFS_nnn).
271  ******************************************************************************/
VCMP_IntEnable(uint32_t flags)272 __STATIC_INLINE void VCMP_IntEnable(uint32_t flags)
273 {
274   VCMP->IEN |= flags;
275 }
276 
277 /***************************************************************************//**
278  * @brief
279  *   Get pending VCMP interrupt flags.
280  *
281  * @note
282  *   The event bits are not cleared by the use of this function.
283  *
284  * @return
285  *   Pending VCMP interrupt sources. Returns a set of interrupt flags OR-ed
286  *   together for multiple interrupt sources in the VCMP module (VCMP_IFS_nnn).
287  ******************************************************************************/
VCMP_IntGet(void)288 __STATIC_INLINE uint32_t VCMP_IntGet(void)
289 {
290   return VCMP->IF;
291 }
292 
293 /***************************************************************************//**
294  * @brief
295  *   Get enabled and pending VCMP interrupt flags.
296  *
297  * @details
298  *   Useful for handling more interrupt sources in the same interrupt handler.
299  *
300  * @note
301  *   The event bits are not cleared by the use of this function.
302  *
303  * @return
304  *   Pending and enabled VCMP interrupt sources.
305  *   The return value is the bitwise AND combination of
306  *   - the OR combination of enabled interrupt sources in VCMP_IEN_nnn
307  *   register (VCMP_IEN_nnn) and
308  *   - the OR combination of valid interrupt flags of the VCMP module
309  *   (VCMP_IF_nnn).
310  ******************************************************************************/
VCMP_IntGetEnabled(void)311 __STATIC_INLINE uint32_t VCMP_IntGetEnabled(void)
312 {
313   uint32_t tmp = 0U;
314 
315   /* Store VCMP->IEN in a temporary variable to define explicit order
316    * of volatile accesses. */
317   tmp = VCMP->IEN;
318 
319   /* Bitwise AND of pending and enabled interrupts */
320   return VCMP->IF & tmp;
321 }
322 
323 /** @} (end addtogroup vcmp) */
324 
325 #ifdef __cplusplus
326 }
327 #endif
328 
329 #endif /* defined(VCMP_COUNT) && (VCMP_COUNT > 0) */
330 #endif /* EM_VCMP_H */
331