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 #include "em_vcmp.h"
32 #if defined(VCMP_COUNT) && (VCMP_COUNT > 0)
33 
34 #include "sl_assert.h"
35 
36 /***************************************************************************//**
37  * @addtogroup vcmp VCMP - Voltage Comparator
38  * @brief Supply Voltage Comparator (VCMP) Peripheral API
39  * @details
40  *  This module contains functions to control the VCMP peripheral of Silicon
41  *  Labs 32-bit MCUs and SoCs. The VCMP monitors the input voltage supply and
42  *  generates interrupts on events using as little as 100 nA.
43  * @{
44  ******************************************************************************/
45 
46 /***************************************************************************//**
47  * @brief
48  *   Configure and enable Voltage Comparator.
49  *
50  * @param[in] vcmpInit
51  *   The VCMP Initialization structure.
52  ******************************************************************************/
VCMP_Init(const VCMP_Init_TypeDef * vcmpInit)53 void VCMP_Init(const VCMP_Init_TypeDef *vcmpInit)
54 {
55   /* Verify input. */
56   EFM_ASSERT((vcmpInit->inactive == 0) || (vcmpInit->inactive == 1));
57   EFM_ASSERT((vcmpInit->biasProg >= 0) && (vcmpInit->biasProg < 16));
58 
59   /* Configure the Half Bias setting. */
60   if (vcmpInit->halfBias) {
61     VCMP->CTRL |= VCMP_CTRL_HALFBIAS;
62   } else {
63     VCMP->CTRL &= ~(VCMP_CTRL_HALFBIAS);
64   }
65 
66   /* Configure the bias prog. */
67   VCMP->CTRL &= ~(_VCMP_CTRL_BIASPROG_MASK);
68   VCMP->CTRL |= (vcmpInit->biasProg << _VCMP_CTRL_BIASPROG_SHIFT);
69 
70   /* Configure sense for the falling edge. */
71   if (vcmpInit->irqFalling) {
72     VCMP->CTRL |= VCMP_CTRL_IFALL;
73   } else {
74     VCMP->CTRL &= ~(VCMP_CTRL_IFALL);
75   }
76 
77   /* Configure sense for the rising edge. */
78   if (vcmpInit->irqRising) {
79     VCMP->CTRL |= VCMP_CTRL_IRISE;
80   } else {
81     VCMP->CTRL &= ~(VCMP_CTRL_IRISE);
82   }
83 
84   /* Configure the warm-up time. */
85   VCMP->CTRL &= ~(_VCMP_CTRL_WARMTIME_MASK);
86   VCMP->CTRL |= (vcmpInit->warmup << _VCMP_CTRL_WARMTIME_SHIFT);
87 
88   /* Configure hysteresis. */
89   switch (vcmpInit->hyst) {
90     case vcmpHyst20mV:
91       VCMP->CTRL |= VCMP_CTRL_HYSTEN;
92       break;
93     case vcmpHystNone:
94       VCMP->CTRL &= ~(VCMP_CTRL_HYSTEN);
95       break;
96     default:
97       break;
98   }
99 
100   /* Configure the inactive output value. */
101   VCMP->CTRL |= (vcmpInit->inactive << _VCMP_CTRL_INACTVAL_SHIFT);
102 
103   /* Configure the trigger level. */
104   VCMP_TriggerSet(vcmpInit->triggerLevel);
105 
106   /* Enable or disable VCMP. */
107   if (vcmpInit->enable) {
108     VCMP->CTRL |= VCMP_CTRL_EN;
109   } else {
110     VCMP->CTRL &= ~(VCMP_CTRL_EN);
111   }
112 
113   /* If Low Power Reference is enabled, wait until VCMP is ready */
114   /* before enabling it. See the reference manual for deatils.        */
115   /* Configuring Low Power Ref without enable has no effect.      */
116   if (vcmpInit->lowPowerRef && vcmpInit->enable) {
117     /* Poll for VCMP ready. */
118     while (!VCMP_Ready()) ;
119     VCMP_LowPowerRefSet(vcmpInit->lowPowerRef);
120   }
121 
122   /* Clear the edge interrupt. */
123   VCMP_IntClear(VCMP_IF_EDGE);
124 }
125 
126 /***************************************************************************//**
127  * @brief
128  *    Enable or disable Low Power Reference setting.
129  *
130  * @param[in] enable
131  *    If true, enables low power reference. If false, disable low power reference.
132  ******************************************************************************/
VCMP_LowPowerRefSet(bool enable)133 void VCMP_LowPowerRefSet(bool enable)
134 {
135   if (enable) {
136     VCMP->INPUTSEL |= VCMP_INPUTSEL_LPREF;
137   } else {
138     VCMP->INPUTSEL &= ~VCMP_INPUTSEL_LPREF;
139   }
140 }
141 
142 /***************************************************************************//**
143  * @brief
144  *    Configure the trigger level of the voltage comparator.
145  *
146  * @param[in] level
147  *    A trigger value, in range 0-63.
148  ******************************************************************************/
VCMP_TriggerSet(int level)149 void VCMP_TriggerSet(int level)
150 {
151   /* Trigger range is 6 bits, value from 0-63. */
152   EFM_ASSERT((level > 0) && (level < 64));
153 
154   /* Set the trigger level. */
155   VCMP->INPUTSEL = (VCMP->INPUTSEL & ~(_VCMP_INPUTSEL_TRIGLEVEL_MASK))
156                    | (level << _VCMP_INPUTSEL_TRIGLEVEL_SHIFT);
157 }
158 
159 /** @} (end addtogroup vcmp) */
160 #endif /* defined(VCMP_COUNT) && (VCMP_COUNT > 0) */
161