1 /***************************************************************************//**
2 * @file
3 * @brief Analog Comparator (ACMP) 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_ACMP_H
34 #define __EM_ACMP_H
35
36 #include <stdint.h>
37 #include <stdbool.h>
38 #include "em_part.h"
39
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43
44 /***************************************************************************//**
45 * @addtogroup EM_Library
46 * @{
47 ******************************************************************************/
48
49 /***************************************************************************//**
50 * @addtogroup ACMP
51 * @{
52 ******************************************************************************/
53
54 /*******************************************************************************
55 ******************************** ENUMS ************************************
56 ******************************************************************************/
57
58 /** Resistor values used for capacative sense. See the datasheet for your
59 * device for details on each resistor value. */
60 typedef enum
61 {
62 /** resistor value 0 */
63 acmpResistor0 = _ACMP_INPUTSEL_CSRESSEL_RES0,
64 /** resistor value 1 */
65 acmpResistor1 = _ACMP_INPUTSEL_CSRESSEL_RES1,
66 /** resistor value 2 */
67 acmpResistor2 = _ACMP_INPUTSEL_CSRESSEL_RES2,
68 /** resistor value 3 */
69 acmpResistor3 = _ACMP_INPUTSEL_CSRESSEL_RES3
70 } ACMP_CapsenseResistor_TypeDef;
71
72 /** Hysteresis level. See datasheet for your device for details on each
73 * level. */
74 typedef enum
75 {
76 acmpHysteresisLevel0 = _ACMP_CTRL_HYSTSEL_HYST0, /**< Hysteresis level 0 */
77 acmpHysteresisLevel1 = _ACMP_CTRL_HYSTSEL_HYST1, /**< Hysteresis level 1 */
78 acmpHysteresisLevel2 = _ACMP_CTRL_HYSTSEL_HYST2, /**< Hysteresis level 2 */
79 acmpHysteresisLevel3 = _ACMP_CTRL_HYSTSEL_HYST3, /**< Hysteresis level 3 */
80 acmpHysteresisLevel4 = _ACMP_CTRL_HYSTSEL_HYST4, /**< Hysteresis level 4 */
81 acmpHysteresisLevel5 = _ACMP_CTRL_HYSTSEL_HYST5, /**< Hysteresis level 5 */
82 acmpHysteresisLevel6 = _ACMP_CTRL_HYSTSEL_HYST6, /**< Hysteresis level 6 */
83 acmpHysteresisLevel7 = _ACMP_CTRL_HYSTSEL_HYST7 /**< Hysteresis level 7 */
84 } ACMP_HysteresisLevel_TypeDef;
85
86 /** ACMP warmup time. The delay is measured in HFPERCLK cycles and should
87 * be at least 10 us. */
88 typedef enum
89 {
90 /** 4 HFPERCLK cycles warmup */
91 acmpWarmTime4 = _ACMP_CTRL_WARMTIME_4CYCLES,
92 /** 8 HFPERCLK cycles warmup */
93 acmpWarmTime8 = _ACMP_CTRL_WARMTIME_8CYCLES,
94 /** 16 HFPERCLK cycles warmup */
95 acmpWarmTime16 = _ACMP_CTRL_WARMTIME_16CYCLES,
96 /** 32 HFPERCLK cycles warmup */
97 acmpWarmTime32 = _ACMP_CTRL_WARMTIME_32CYCLES,
98 /** 64 HFPERCLK cycles warmup */
99 acmpWarmTime64 = _ACMP_CTRL_WARMTIME_64CYCLES,
100 /** 128 HFPERCLK cycles warmup */
101 acmpWarmTime128 = _ACMP_CTRL_WARMTIME_128CYCLES,
102 /** 256 HFPERCLK cycles warmup */
103 acmpWarmTime256 = _ACMP_CTRL_WARMTIME_256CYCLES,
104 /** 512 HFPERCLK cycles warmup */
105 acmpWarmTime512 = _ACMP_CTRL_WARMTIME_512CYCLES
106 } ACMP_WarmTime_TypeDef;
107
108 /** ACMP inputs. Note that scaled VDD and bandgap references can only be used
109 * as negative inputs. */
110 typedef enum
111 {
112 /** Channel 0 */
113 acmpChannel0 = _ACMP_INPUTSEL_NEGSEL_CH0,
114 /** Channel 1 */
115 acmpChannel1 = _ACMP_INPUTSEL_NEGSEL_CH1,
116 /** Channel 2 */
117 acmpChannel2 = _ACMP_INPUTSEL_NEGSEL_CH2,
118 /** Channel 3 */
119 acmpChannel3 = _ACMP_INPUTSEL_NEGSEL_CH3,
120 /** Channel 4 */
121 acmpChannel4 = _ACMP_INPUTSEL_NEGSEL_CH4,
122 /** Channel 5 */
123 acmpChannel5 = _ACMP_INPUTSEL_NEGSEL_CH5,
124 /** Channel 6 */
125 acmpChannel6 = _ACMP_INPUTSEL_NEGSEL_CH6,
126 /** Channel 7 */
127 acmpChannel7 = _ACMP_INPUTSEL_NEGSEL_CH7,
128 /** 1.25V internal reference */
129 acmpChannel1V25 = _ACMP_INPUTSEL_NEGSEL_1V25,
130 /** 2.5V internal reference */
131 acmpChannel2V5 = _ACMP_INPUTSEL_NEGSEL_2V5,
132 /** Scaled VDD reference */
133 acmpChannelVDD = _ACMP_INPUTSEL_NEGSEL_VDD,
134 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_TINY_FAMILY)
135 /** DAC0 channel 0 */
136 acmpChannelDAC0Ch0 = _ACMP_INPUTSEL_NEGSEL_DAC0CH0,
137 /** DAC0 channel 1 */
138 acmpChannelDAC0Ch1 = _ACMP_INPUTSEL_NEGSEL_DAC0CH1,
139 #endif
140 } ACMP_Channel_TypeDef;
141
142 /*******************************************************************************
143 ****************************** STRUCTS ************************************
144 ******************************************************************************/
145
146 /** Capsense initialization structure. */
147 typedef struct
148 {
149 /** Full bias current. See the ACMP chapter about bias and response time in
150 * the reference manual for details. */
151 bool fullBias;
152
153 /** Half bias current. See the ACMP chapter about bias and response time in
154 * the reference manual for details. */
155 bool halfBias;
156
157 /** Bias current. See the ACMP chapter about bias and response time in the
158 * reference manual for details. Valid values are in the range 0-7. */
159 uint32_t biasProg;
160
161 /** Warmup time. This is measured in HFPERCLK cycles and should be
162 * about 10us in wall clock time. */
163 ACMP_WarmTime_TypeDef warmTime;
164
165 /** Hysteresis level */
166 ACMP_HysteresisLevel_TypeDef hysteresisLevel;
167
168 /** Resistor used in the capacative sensing circuit. For values see
169 * your device datasheet. */
170 ACMP_CapsenseResistor_TypeDef resistor;
171
172 /** Low power reference enabled. This setting, if enabled, reduces the
173 * power used by the VDD and bandgap references. */
174 bool lowPowerReferenceEnabled;
175
176 /** Vdd reference value. VDD_SCALED = VDD × VDDLEVEL × 50mV/3.8V.
177 * Valid values are in the range 0-63. */
178 uint32_t vddLevel;
179
180 /** If true, ACMP is being enabled after configuration. */
181 bool enable;
182 } ACMP_CapsenseInit_TypeDef;
183
184 /** Default config for capacitive sense mode initialization. */
185 #define ACMP_CAPSENSE_INIT_DEFAULT \
186 { false, /* fullBias */ \
187 false, /* halfBias */ \
188 0x7, /* biasProg */ \
189 acmpWarmTime512, /* 512 cycle warmup to be safe */ \
190 acmpHysteresisLevel5, \
191 acmpResistor3, \
192 false, /* low power reference */ \
193 0x3D, /* VDD level */ \
194 true /* Enable after init. */ \
195 }
196
197 /** ACMP initialization structure. */
198 typedef struct
199 {
200 /** Full bias current. See the ACMP chapter about bias and response time in
201 * the reference manual for details. */
202 bool fullBias;
203
204 /** Half bias current. See the ACMP chapter about bias and response time in
205 * the reference manual for details. */
206 bool halfBias;
207
208 /** Bias current. See the ACMP chapter about bias and response time in the
209 * reference manual for details. Valid values are in the range 0-7. */
210 uint32_t biasProg;
211
212 /** Enable setting the interrupt flag on falling edge */
213 bool interruptOnFallingEdge;
214
215 /** Enable setting the interrupt flag on rising edge */
216 bool interruptOnRisingEdge;
217
218 /** Warmup time. This is measured in HFPERCLK cycles and should be
219 * about 10us in wall clock time. */
220 ACMP_WarmTime_TypeDef warmTime;
221
222 /** Hysteresis level */
223 ACMP_HysteresisLevel_TypeDef hysteresisLevel;
224
225 /** Inactive value emitted by the ACMP during warmup */
226 bool inactiveValue;
227
228 /** Low power reference enabled. This setting, if enabled, reduces the
229 * power used by the VDD and bandgap references. */
230 bool lowPowerReferenceEnabled;
231
232 /** Vdd reference value. VDD_SCALED = VDD × VDDLEVEL × 50mV/3.8V.
233 * Valid values are in the range 0-63. */
234 uint32_t vddLevel;
235
236 /** If true, ACMP is being enabled after configuration. */
237 bool enable;
238 } ACMP_Init_TypeDef;
239
240 /** Default config for ACMP regular initialization. */
241 #define ACMP_INIT_DEFAULT \
242 { false, /* fullBias */ \
243 false, /* halfBias */ \
244 0x7, /* biasProg */ \
245 false, /* No interrupt on falling edge. */ \
246 false, /* No interrupt on rising edge. */ \
247 acmpWarmTime512, /* 512 cycle warmup to be safe */ \
248 acmpHysteresisLevel5, \
249 false, /* Disabled emitting inactive value during warmup. */ \
250 false, /* low power reference */ \
251 0x3D, /* VDD level */ \
252 true /* Enable after init. */ \
253 }
254
255
256 /*******************************************************************************
257 ***************************** PROTOTYPES **********************************
258 ******************************************************************************/
259
260 void ACMP_CapsenseInit(ACMP_TypeDef *acmp, const ACMP_CapsenseInit_TypeDef *init);
261 void ACMP_CapsenseChannelSet(ACMP_TypeDef *acmp, ACMP_Channel_TypeDef channel);
262 void ACMP_ChannelSet(ACMP_TypeDef *acmp, ACMP_Channel_TypeDef negSel, ACMP_Channel_TypeDef posSel);
263 void ACMP_Disable(ACMP_TypeDef *acmp);
264 void ACMP_Enable(ACMP_TypeDef *acmp);
265 void ACMP_GPIOSetup(ACMP_TypeDef *acmp, uint32_t location, bool enable, bool invert);
266 void ACMP_Init(ACMP_TypeDef *acmp, const ACMP_Init_TypeDef *init);
267 void ACMP_Reset(ACMP_TypeDef *acmp);
268
269 /***************************************************************************//**
270 * @brief
271 * Clear one or more pending ACMP interrupts.
272 *
273 * @param[in] acmp
274 * Pointer to ACMP peripheral register block.
275 *
276 * @param[in] flags
277 * Pending ACMP interrupt source to clear. Use a bitwise logic OR combination
278 * of valid interrupt flags for the ACMP module (ACMP_IF_nnn).
279 ******************************************************************************/
ACMP_IntClear(ACMP_TypeDef * acmp,uint32_t flags)280 __STATIC_INLINE void ACMP_IntClear(ACMP_TypeDef *acmp, uint32_t flags)
281 {
282 acmp->IFC = flags;
283 }
284
285
286 /***************************************************************************//**
287 * @brief
288 * Disable one or more ACMP interrupts.
289 *
290 * @param[in] acmp
291 * Pointer to ACMP peripheral register block.
292 *
293 * @param[in] flags
294 * ACMP interrupt sources to disable. Use a bitwise logic OR combination of
295 * valid interrupt flags for the ACMP module (ACMP_IF_nnn).
296 ******************************************************************************/
ACMP_IntDisable(ACMP_TypeDef * acmp,uint32_t flags)297 __STATIC_INLINE void ACMP_IntDisable(ACMP_TypeDef *acmp, uint32_t flags)
298 {
299 acmp->IEN &= ~(flags);
300 }
301
302
303 /***************************************************************************//**
304 * @brief
305 * Enable one or more ACMP interrupts.
306 *
307 * @note
308 * Depending on the use, a pending interrupt may already be set prior to
309 * enabling the interrupt. Consider using ACMP_IntClear() prior to enabling
310 * if such a pending interrupt should be ignored.
311 *
312 * @param[in] acmp
313 * Pointer to ACMP peripheral register block.
314 *
315 * @param[in] flags
316 * ACMP interrupt sources to enable. Use a bitwise logic OR combination of
317 * valid interrupt flags for the ACMP module (ACMP_IF_nnn).
318 ******************************************************************************/
ACMP_IntEnable(ACMP_TypeDef * acmp,uint32_t flags)319 __STATIC_INLINE void ACMP_IntEnable(ACMP_TypeDef *acmp, uint32_t flags)
320 {
321 acmp->IEN |= flags;
322 }
323
324
325 /***************************************************************************//**
326 * @brief
327 * Get pending ACMP interrupt flags.
328 *
329 * @note
330 * The event bits are not cleared by the use of this function.
331 *
332 * @param[in] acmp
333 * Pointer to ACMP peripheral register block.
334 *
335 * @return
336 * ACMP interrupt sources pending. A bitwise logic OR combination of valid
337 * interrupt flags for the ACMP module (ACMP_IF_nnn).
338 ******************************************************************************/
ACMP_IntGet(ACMP_TypeDef * acmp)339 __STATIC_INLINE uint32_t ACMP_IntGet(ACMP_TypeDef *acmp)
340 {
341 return(acmp->IF);
342 }
343
344
345 /***************************************************************************//**
346 * @brief
347 * Get enabled and pending ACMP interrupt flags.
348 * Useful for handling more interrupt sources in the same interrupt handler.
349 *
350 * @param[in] usart
351 * Pointer to ACMP peripheral register block.
352 *
353 * @note
354 * Interrupt flags are not cleared by the use of this function.
355 *
356 * @return
357 * Pending and enabled ACMP interrupt sources.
358 * The return value is the bitwise AND combination of
359 * - the OR combination of enabled interrupt sources in ACMPx_IEN_nnn
360 * register (ACMPx_IEN_nnn) and
361 * - the OR combination of valid interrupt flags of the ACMP module
362 * (ACMPx_IF_nnn).
363 ******************************************************************************/
ACMP_IntGetEnabled(ACMP_TypeDef * acmp)364 __STATIC_INLINE uint32_t ACMP_IntGetEnabled(ACMP_TypeDef *acmp)
365 {
366 uint32_t tmp;
367
368 /* Store ACMPx->IEN in temporary variable in order to define explicit order
369 * of volatile accesses. */
370 tmp = acmp->IEN;
371
372 /* Bitwise AND of pending and enabled interrupts */
373 return acmp->IF & tmp;
374 }
375
376
377 /***************************************************************************//**
378 * @brief
379 * Set one or more pending ACMP interrupts from SW.
380 *
381 * @param[in] acmp
382 * Pointer to ACMP peripheral register block.
383 *
384 * @param[in] flags
385 * ACMP interrupt sources to set to pending. Use a bitwise logic OR
386 * combination of valid interrupt flags for the ACMP module (ACMP_IF_nnn).
387 ******************************************************************************/
ACMP_IntSet(ACMP_TypeDef * acmp,uint32_t flags)388 __STATIC_INLINE void ACMP_IntSet(ACMP_TypeDef *acmp, uint32_t flags)
389 {
390 acmp->IFS = flags;
391 }
392
393 /** @} (end addtogroup ACMP) */
394 /** @} (end addtogroup EM_Library) */
395
396 #ifdef __cplusplus
397 }
398 #endif
399
400 #endif /* __EM_ACMP_H */
401