EFM32 Giant Gecko Software Documentation  efm32gg-doc-4.2.1
em_acmp.c
Go to the documentation of this file.
1 /***************************************************************************/
34 #include "em_acmp.h"
35 #if defined(ACMP_COUNT) && (ACMP_COUNT > 0)
36 
37 #include <stdbool.h>
38 #include "em_bus.h"
39 #include "em_assert.h"
40 
41 /***************************************************************************/
46 /***************************************************************************/
52 /*******************************************************************************
53  ******************************* DEFINES ***********************************
54  ******************************************************************************/
55 
61 #if (ACMP_COUNT == 1)
62 #define ACMP_REF_VALID(ref) ((ref) == ACMP0)
63 #elif (ACMP_COUNT == 2)
64 #define ACMP_REF_VALID(ref) (((ref) == ACMP0) || ((ref) == ACMP1))
65 #else
66 #error Undefined number of analog comparators (ACMP).
67 #endif
68 
71 #if defined(_ACMP_ROUTE_LOCATION_LOC3)
72 #define _ACMP_ROUTE_LOCATION_MAX _ACMP_ROUTE_LOCATION_LOC3
73 #elif defined(_ACMP_ROUTE_LOCATION_LOC2)
74 #define _ACMP_ROUTE_LOCATION_MAX _ACMP_ROUTE_LOCATION_LOC2
75 #elif defined(_ACMP_ROUTE_LOCATION_LOC1)
76 #define _ACMP_ROUTE_LOCATION_MAX _ACMP_ROUTE_LOCATION_LOC1
77 #elif defined(_ACMP_ROUTELOC0_OUTLOC_LOC31)
78 #define _ACMP_ROUTE_LOCATION_MAX _ACMP_ROUTELOC0_OUTLOC_LOC31
79 #else
80 #error Undefined max route locations
81 #endif
82 
85 /*******************************************************************************
86  ************************** GLOBAL FUNCTIONS *******************************
87  ******************************************************************************/
88 
89 /***************************************************************************/
111 {
112  /* Make sure the module exists on the selected chip */
113  EFM_ASSERT(ACMP_REF_VALID(acmp));
114 
115  /* Make sure that vddLevel is within bounds */
116 #if defined(_ACMP_INPUTSEL_VDDLEVEL_MASK)
117  EFM_ASSERT(init->vddLevel < 64);
118 #else
119  EFM_ASSERT(init->vddLevelLow < 64);
120  EFM_ASSERT(init->vddLevelHigh < 64);
121 #endif
122 
123  /* Make sure biasprog is within bounds */
124  EFM_ASSERT(init->biasProg <=
126 
127  /* Set control register. No need to set interrupt modes */
128  acmp->CTRL = (init->fullBias << _ACMP_CTRL_FULLBIAS_SHIFT)
129 #if defined(_ACMP_CTRL_HALFBIAS_MASK)
131 #endif
133 #if defined(_ACMP_CTRL_WARMTIME_MASK)
135 #endif
136 #if defined(_ACMP_CTRL_HYSTSEL_MASK)
138 #endif
139 #if defined(_ACMP_CTRL_ACCURACY_MASK)
140  | ACMP_CTRL_ACCURACY_HIGH
141 #endif
142  ;
143 
144 #if defined(_ACMP_HYSTERESIS0_MASK)
145  acmp->HYSTERESIS0 = (init->vddLevelHigh << _ACMP_HYSTERESIS0_DIVVA_SHIFT)
146  | (init->hysteresisLevel_0 << _ACMP_HYSTERESIS0_HYST_SHIFT);
147  acmp->HYSTERESIS1 = (init->vddLevelLow << _ACMP_HYSTERESIS1_DIVVA_SHIFT)
148  | (init->hysteresisLevel_1 << _ACMP_HYSTERESIS1_HYST_SHIFT);
149 #endif
150 
151  /* Select capacative sensing mode by selecting a resistor and enabling it */
154 #if defined(_ACMP_INPUTSEL_LPREF_MASK)
156 #endif
157 #if defined(_ACMP_INPUTSEL_VDDLEVEL_MASK)
159 #endif
162 #else
163  | ACMP_INPUTSEL_VASEL_VDD
164  | ACMP_INPUTSEL_NEGSEL_VADIV
165 #endif
166  ;
167 
168  /* Enable ACMP if requested. */
170 }
171 
172 /***************************************************************************/
187 {
188  /* Make sure the module exists on the selected chip */
189  EFM_ASSERT(ACMP_REF_VALID(acmp));
190 
191 #if defined(_ACMP_INPUTSEL_POSSEL_CH7)
192  /* Make sure that only external channels are used */
193  EFM_ASSERT(channel <= _ACMP_INPUTSEL_POSSEL_CH7);
194 #elif defined(_ACMP_INPUTSEL_POSSEL_BUS4XCH31)
195  /* Make sure that only external channels are used */
196  EFM_ASSERT(channel <= _ACMP_INPUTSEL_POSSEL_BUS4XCH31);
197 #endif
198 
199  /* Set channel as positive channel in ACMP */
201  channel << _ACMP_INPUTSEL_POSSEL_SHIFT);
202 }
203 
204 /***************************************************************************/
212 {
213  /* Make sure the module exists on the selected chip */
214  EFM_ASSERT(ACMP_REF_VALID(acmp));
215 
216  acmp->CTRL &= ~ACMP_CTRL_EN;
217 }
218 
219 /***************************************************************************/
227 {
228  /* Make sure the module exists on the selected chip */
229  EFM_ASSERT(ACMP_REF_VALID(acmp));
230 
231  acmp->CTRL |= ACMP_CTRL_EN;
232 }
233 
234 /***************************************************************************/
246 {
247  /* Make sure the module exists on the selected chip */
248  EFM_ASSERT(ACMP_REF_VALID(acmp));
249 
250  acmp->CTRL = _ACMP_CTRL_RESETVALUE;
252 #if defined(_ACMP_HYSTERESIS0_HYST_MASK)
253  acmp->HYSTERESIS0 = _ACMP_HYSTERESIS0_RESETVALUE;
254  acmp->HYSTERESIS1 = _ACMP_HYSTERESIS1_RESETVALUE;
255 #endif
256  acmp->IEN = _ACMP_IEN_RESETVALUE;
257  acmp->IFC = _ACMP_IF_MASK;
258 }
259 
260 /***************************************************************************/
280 void ACMP_GPIOSetup(ACMP_TypeDef *acmp, uint32_t location, bool enable, bool invert)
281 {
282  /* Make sure the module exists on the selected chip */
283  EFM_ASSERT(ACMP_REF_VALID(acmp));
284 
285  /* Sanity checking of location */
286  EFM_ASSERT(location <= _ACMP_ROUTE_LOCATION_MAX);
287 
288  /* Set GPIO inversion */
290  invert << _ACMP_CTRL_GPIOINV_SHIFT);
291 
292 #if defined(_ACMP_ROUTE_MASK)
293  acmp->ROUTE = (location << _ACMP_ROUTE_LOCATION_SHIFT)
294  | (enable << _ACMP_ROUTE_ACMPPEN_SHIFT);
295 #endif
296 #if defined(_ACMP_ROUTELOC0_MASK)
297  acmp->ROUTELOC0 = location << _ACMP_ROUTELOC0_OUTLOC_SHIFT;
298  acmp->ROUTEPEN = enable ? ACMP_ROUTEPEN_OUTPEN : 0;
299 #endif
300 }
301 
302 /***************************************************************************/
316  ACMP_Channel_TypeDef posSel)
317 {
318  /* Make sure the module exists on the selected chip */
319  EFM_ASSERT(ACMP_REF_VALID(acmp));
320 
321  /* Make sure that posSel and negSel channel selectors are valid. */
322 #if defined(_ACMP_INPUTSEL_NEGSEL_DAC0CH1)
323  EFM_ASSERT(negSel <= _ACMP_INPUTSEL_NEGSEL_DAC0CH1);
324 #elif defined(_ACMP_INPUTSEL_NEGSEL_CAPSENSE)
325  EFM_ASSERT(negSel <= _ACMP_INPUTSEL_NEGSEL_CAPSENSE);
326 #endif
327 
328 #if defined(_ACMP_INPUTSEL_POSSEL_CH7)
329  EFM_ASSERT(posSel <= _ACMP_INPUTSEL_POSSEL_CH7);
330 #endif
331 
332  acmp->INPUTSEL = (acmp->INPUTSEL & ~(_ACMP_INPUTSEL_POSSEL_MASK
334  | (negSel << _ACMP_INPUTSEL_NEGSEL_SHIFT)
335  | (posSel << _ACMP_INPUTSEL_POSSEL_SHIFT);
336 }
337 
338 /***************************************************************************/
349 void ACMP_Init(ACMP_TypeDef *acmp, const ACMP_Init_TypeDef *init)
350 {
351  /* Make sure the module exists on the selected chip */
352  EFM_ASSERT(ACMP_REF_VALID(acmp));
353 
354  /* Make sure biasprog is within bounds */
355  EFM_ASSERT(init->biasProg < 16);
356 
357  /* Make sure the ACMP is disable since we might be changing the
358  * ACMP power source */
360 
361  /* Set control register. No need to set interrupt modes */
362  acmp->CTRL = (init->fullBias << _ACMP_CTRL_FULLBIAS_SHIFT)
363 #if defined(_ACMP_CTRL_HALFBIAS_MASK)
365 #endif
369 #if defined(_ACMP_CTRL_INPUTRANGE_MASK)
370  | (init->inputRange << _ACMP_CTRL_INPUTRANGE_SHIFT)
371 #endif
372 #if defined(_ACMP_CTRL_ACCURACY_MASK)
373  | (init->accuracy << _ACMP_CTRL_ACCURACY_SHIFT)
374 #endif
375 #if defined(_ACMP_CTRL_PWRSEL_MASK)
376  | (init->powerSource << _ACMP_CTRL_PWRSEL_SHIFT)
377 #endif
378 #if defined(_ACMP_CTRL_WARMTIME_MASK)
380 #endif
381 #if defined(_ACMP_CTRL_HYSTSEL_MASK)
383 #endif
385 
386  acmp->INPUTSEL = (0)
387 #if defined(_ACMP_INPUTSEL_VLPSEL_MASK)
388  | (init->vlpInput << _ACMP_INPUTSEL_VLPSEL_SHIFT)
389 #endif
390 #if defined(_ACMP_INPUTSEL_LPREF_MASK)
392 #endif
393 #if defined(_ACMP_INPUTSEL_VDDLEVEL_MASK)
395 #endif
396  ;
397 
398  /* Enable ACMP if requested. */
400 }
401 
402 #if defined(_ACMP_INPUTSEL_VASEL_MASK)
403 /***************************************************************************/
414 void ACMP_VASetup(ACMP_TypeDef *acmp, const ACMP_VAConfig_TypeDef *vaconfig)
415 {
416  EFM_ASSERT(vaconfig->div0 < 64);
417  EFM_ASSERT(vaconfig->div1 < 64);
418 
419  BUS_RegMaskedWrite(&acmp->INPUTSEL, _ACMP_INPUTSEL_VASEL_MASK,
420  vaconfig->input << _ACMP_INPUTSEL_VASEL_SHIFT);
421  BUS_RegMaskedWrite(&acmp->HYSTERESIS0, _ACMP_HYSTERESIS0_DIVVA_MASK,
422  vaconfig->div0 << _ACMP_HYSTERESIS0_DIVVA_SHIFT);
423  BUS_RegMaskedWrite(&acmp->HYSTERESIS1, _ACMP_HYSTERESIS1_DIVVA_MASK,
424  vaconfig->div1 << _ACMP_HYSTERESIS1_DIVVA_SHIFT);
425 }
426 #endif
427 
428 #if defined(_ACMP_INPUTSEL_VBSEL_MASK)
429 /***************************************************************************/
440 void ACMP_VBSetup(ACMP_TypeDef *acmp, const ACMP_VBConfig_TypeDef *vbconfig)
441 {
442  EFM_ASSERT(vbconfig->div0 < 64);
443  EFM_ASSERT(vbconfig->div1 < 64);
444 
445  BUS_RegMaskedWrite(&acmp->INPUTSEL, _ACMP_INPUTSEL_VBSEL_MASK,
446  vbconfig->input << _ACMP_INPUTSEL_VBSEL_SHIFT);
447  BUS_RegMaskedWrite(&acmp->HYSTERESIS0, _ACMP_HYSTERESIS0_DIVVB_MASK,
448  vbconfig->div0 << _ACMP_HYSTERESIS0_DIVVB_SHIFT);
449  BUS_RegMaskedWrite(&acmp->HYSTERESIS1, _ACMP_HYSTERESIS1_DIVVB_MASK,
450  vbconfig->div1 << _ACMP_HYSTERESIS1_DIVVB_SHIFT);
451 }
452 #endif
453 
456 #endif /* defined(ACMP_COUNT) && (ACMP_COUNT > 0) */
__IO uint32_t ROUTE
Definition: efm32gg_acmp.h:50
ACMP_CapsenseResistor_TypeDef resistor
Definition: em_acmp.h:507
void ACMP_Disable(ACMP_TypeDef *acmp)
Disables the ACMP.
Definition: em_acmp.c:211
ACMP_HysteresisLevel_TypeDef hysteresisLevel
Definition: em_acmp.h:496
ACMP_Channel_TypeDef
Definition: em_acmp.h:425
Emlib peripheral API "assert" implementation.
#define _ACMP_INPUTSEL_NEGSEL_DAC0CH1
Definition: efm32gg_acmp.h:201
#define _ACMP_CTRL_HALFBIAS_SHIFT
Definition: efm32gg_acmp.h:152
#define _ACMP_CTRL_IFALL_SHIFT
Definition: efm32gg_acmp.h:139
#define _ACMP_CTRL_WARMTIME_MASK
Definition: efm32gg_acmp.h:110
RAM and peripheral bit-field set and clear API.
#define ACMP_CTRL_EN
Definition: efm32gg_acmp.h:61
#define _ACMP_INPUTSEL_LPREF_SHIFT
Definition: efm32gg_acmp.h:222
uint32_t biasProg
Definition: em_acmp.h:598
#define _ACMP_INPUTSEL_POSSEL_SHIFT
Definition: efm32gg_acmp.h:165
void ACMP_CapsenseChannelSet(ACMP_TypeDef *acmp, ACMP_Channel_TypeDef channel)
Sets the ACMP channel used for capacative sensing.
Definition: em_acmp.c:186
#define _ACMP_INPUTSEL_NEGSEL_SHIFT
Definition: efm32gg_acmp.h:185
__IO uint32_t IEN
Definition: efm32gg_acmp.h:46
bool interruptOnRisingEdge
Definition: em_acmp.h:604
#define _ACMP_INPUTSEL_LPREF_MASK
Definition: efm32gg_acmp.h:223
#define _ACMP_CTRL_WARMTIME_SHIFT
Definition: efm32gg_acmp.h:109
void ACMP_Enable(ACMP_TypeDef *acmp)
Enables the ACMP.
Definition: em_acmp.c:226
uint32_t vddLevel
Definition: em_acmp.h:659
#define _ACMP_INPUTSEL_NEGSEL_CAPSENSE
Definition: efm32gg_acmp.h:199
#define _ACMP_ROUTE_LOCATION_SHIFT
Definition: efm32gg_acmp.h:322
#define _ACMP_INPUTSEL_CSRESSEL_SHIFT
Definition: efm32gg_acmp.h:231
#define _ACMP_CTRL_BIASPROG_MASK
Definition: efm32gg_acmp.h:148
#define _ACMP_CTRL_GPIOINV_SHIFT
Definition: efm32gg_acmp.h:81
bool lowPowerReferenceEnabled
Definition: em_acmp.h:653
ACMP_WarmTime_TypeDef warmTime
Definition: em_acmp.h:491
void ACMP_ChannelSet(ACMP_TypeDef *acmp, ACMP_Channel_TypeDef negSel, ACMP_Channel_TypeDef posSel)
Sets which channels should be used in ACMP comparisons.
Definition: em_acmp.c:315
#define ACMP_INPUTSEL_CSRESEN
Definition: efm32gg_acmp.h:226
void ACMP_CapsenseInit(ACMP_TypeDef *acmp, const ACMP_CapsenseInit_TypeDef *init)
Sets up the ACMP for use in capacative sense applications.
Definition: em_acmp.c:110
void ACMP_Reset(ACMP_TypeDef *acmp)
Reset ACMP to same state as after a HW reset.
Definition: em_acmp.c:245
#define _ACMP_INPUTSEL_NEGSEL_MASK
Definition: efm32gg_acmp.h:186
#define _ACMP_INPUTSEL_POSSEL_MASK
Definition: efm32gg_acmp.h:166
ACMP_WarmTime_TypeDef warmTime
Definition: em_acmp.h:627
#define _ACMP_CTRL_HYSTSEL_MASK
Definition: efm32gg_acmp.h:90
#define _ACMP_CTRL_BIASPROG_SHIFT
Definition: efm32gg_acmp.h:147
#define _ACMP_CTRL_IRISE_SHIFT
Definition: efm32gg_acmp.h:130
#define _ACMP_IF_MASK
Definition: efm32gg_acmp.h:274
#define _ACMP_CTRL_GPIOINV_MASK
Definition: efm32gg_acmp.h:82
#define _ACMP_CTRL_RESETVALUE
Definition: efm32gg_acmp.h:59
#define _ACMP_INPUTSEL_RESETVALUE
Definition: efm32gg_acmp.h:163
Analog Comparator (ACMP) peripheral API.
#define _ACMP_CTRL_HALFBIAS_MASK
Definition: efm32gg_acmp.h:153
__IO uint32_t INPUTSEL
Definition: efm32gg_acmp.h:44
__STATIC_INLINE void BUS_RegMaskedWrite(volatile uint32_t *addr, uint32_t mask, uint32_t val)
Perform peripheral register masked clear and value write.
Definition: em_bus.h:283
bool interruptOnFallingEdge
Definition: em_acmp.h:601
#define ACMP_INPUTSEL_NEGSEL_CAPSENSE
Definition: efm32gg_acmp.h:214
__IO uint32_t IFC
Definition: efm32gg_acmp.h:49
#define _ACMP_INPUTSEL_VDDLEVEL_MASK
Definition: efm32gg_acmp.h:218
#define _ACMP_CTRL_HYSTSEL_SHIFT
Definition: efm32gg_acmp.h:89
#define _ACMP_CTRL_INACTVAL_SHIFT
Definition: efm32gg_acmp.h:72
#define _ACMP_CTRL_EN_SHIFT
Definition: efm32gg_acmp.h:62
__STATIC_INLINE void BUS_RegBitWrite(volatile uint32_t *addr, unsigned int bit, unsigned int val)
Perform a single-bit write operation on a peripheral register.
Definition: em_bus.h:146
#define _ACMP_INPUTSEL_POSSEL_CH7
Definition: efm32gg_acmp.h:175
void ACMP_Init(ACMP_TypeDef *acmp, const ACMP_Init_TypeDef *init)
Initialize ACMP.
Definition: em_acmp.c:349
#define _ACMP_ROUTE_ACMPPEN_SHIFT
Definition: efm32gg_acmp.h:318
__IO uint32_t CTRL
Definition: efm32gg_acmp.h:43
void ACMP_GPIOSetup(ACMP_TypeDef *acmp, uint32_t location, bool enable, bool invert)
Sets up GPIO output from the ACMP.
Definition: em_acmp.c:280
#define _ACMP_IEN_RESETVALUE
Definition: efm32gg_acmp.h:259
#define _ACMP_INPUTSEL_VDDLEVEL_SHIFT
Definition: efm32gg_acmp.h:217
#define _ACMP_CTRL_FULLBIAS_SHIFT
Definition: efm32gg_acmp.h:157
ACMP_HysteresisLevel_TypeDef hysteresisLevel
Definition: em_acmp.h:632
bool inactiveValue
Definition: em_acmp.h:648