1 /*!
2     \file    gd32l23x_cmp.c
3     \brief   CMP driver
4 
5     \version 2021-08-04, V1.0.0, firmware for GD32L23x
6 */
7 
8 /*
9     Copyright (c) 2021, GigaDevice Semiconductor Inc.
10 
11     Redistribution and use in source and binary forms, with or without modification,
12 are permitted provided that the following conditions are met:
13 
14     1. Redistributions of source code must retain the above copyright notice, this
15        list of conditions and the following disclaimer.
16     2. Redistributions in binary form must reproduce the above copyright notice,
17        this list of conditions and the following disclaimer in the documentation
18        and/or other materials provided with the distribution.
19     3. Neither the name of the copyright holder nor the names of its contributors
20        may be used to endorse or promote products derived from this software without
21        specific prior written permission.
22 
23     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 OF SUCH DAMAGE.
33 */
34 
35 #include "gd32l23x_cmp.h"
36 
37 #define CMP_MODE_DEFAULT                         ((uint32_t)0xFFFFCF83)         /*!< cmp mode default */
38 #define CMP_OUTPUT_DEFAULT                       ((uint32_t)0xFFFFF0FF)         /*!< cmp output default */
39 /*!
40     \brief      deinitialize comparator
41     \param[in]  cmp_periph
42       \arg        CMP0: comparator 0
43       \arg        CMP1: comparator 1
44     \param[out] none
45     \retval     none
46 */
cmp_deinit(uint32_t cmp_periph)47 void cmp_deinit(uint32_t cmp_periph)
48 {
49     if(CMP0 == cmp_periph){
50         CMP0_CS &= ~(uint32_t)CMP0_CS_EN;
51     }else{
52         CMP1_CS &= ~(uint32_t)CMP1_CS_EN;
53     }
54 }
55 
56 /*!
57     \brief      initialize comparator mode
58     \param[in]  cmp_periph
59       \arg        CMP0: comparator 0
60       \arg        CMP1: comparator 1
61     \param[in]  operating_mode
62       \arg        CMP_HIGHSPEED: high speed mode
63       \arg        CMP_MEDIUMSPEED: medium speed mode
64       \arg        CMP_LOWSPEED: low speed mode
65     \param[in]  inverting_input
66       \arg        CMP_1_4VREFINT: VREFINT *1/4 input
67       \arg        CMP_1_2VREFINT: VREFINT *1/2 input
68       \arg        CMP_3_4VREFINT: VREFINT *3/4 input
69       \arg        CMP_VREFINT: VREFINT input
70       \arg        CMP_PA0_PA2: PA0 input when selecting CMP0, PA2 input when selecting CMP1
71       \arg        CMP_DACOUT_PA4: DAC_OUT(PA4) input
72       \arg        CMP_PB3: PB3 input when selecting CMP1
73     \param[in]  output_hysteresis
74       \arg        CMP_HYSTERESIS_NO: output no hysteresis
75       \arg        CMP_HYSTERESIS_LOW: output low hysteresis
76       \arg        CMP_HYSTERESIS_MEDIUM: output medium hysteresis
77       \arg        CMP_HYSTERESIS_HIGH: output high hysteresis
78     \param[out] none
79     \retval     none
80 */
cmp_mode_init(uint32_t cmp_periph,operating_mode_enum operating_mode,inverting_input_enum inverting_input,cmp_hysteresis_enum output_hysteresis)81 void cmp_mode_init(uint32_t cmp_periph, operating_mode_enum operating_mode, inverting_input_enum inverting_input, cmp_hysteresis_enum output_hysteresis)
82 {
83     uint32_t CMPx_CS = 0x00000000U;
84     if(CMP0 == cmp_periph){
85         /* initialize comparator 0 mode */
86         CMPx_CS = CMP0_CS;
87         CMPx_CS &= ~(uint32_t)(CMP0_CS_PM | CMP0_CS_MSEL | CMP0_CS_HST);
88         CMPx_CS |= (uint32_t)(CS_CMP0PM(operating_mode) | CS_CMP0MSEL(inverting_input) | CS_CMP0HST(output_hysteresis));
89         CMP0_CS = CMPx_CS;
90     }else if(CMP1 == cmp_periph){
91         /* initialize comparator 1 mode */
92         CMPx_CS = CMP1_CS;
93         CMPx_CS &= ~(uint32_t)(CMP1_CS_PM | CMP1_CS_MSEL | CMP1_CS_HST);
94         CMPx_CS |= (uint32_t)(CS_CMP1PM(operating_mode) | CS_CMP1MSEL(inverting_input) | CS_CMP1HST(output_hysteresis));
95         CMP1_CS = CMPx_CS;
96     }else{
97     }
98 }
99 
100 /*!
101     \brief      Selecte the plus input for CMP1
102     \param[in]  plus_input
103       \arg        CMP1_PA3: selecte PA3 as plus input for CMP1
104       \arg        CMP1_PB4: selecte PB4 as plus input for CMP1
105       \arg        CMP1_PB5: selecte PB5 as plus input for CMP1
106       \arg        CMP1_PB6: selecte PB6 as plus input for CMP1
107       \arg        CMP1_PB7: selecte PB7 as plus input for CMP1
108     \param[out] none
109     \retval     none
110 */
cmp1_plus_selection(CMP1_plus_input_enum plus_input)111 void cmp1_plus_selection(CMP1_plus_input_enum plus_input)
112 {
113     uint32_t CMPx_CS = 0x00000000U;
114     CMPx_CS = CMP1_CS;
115     CMPx_CS &= ~(uint32_t)(CMP1_CS_PSEL);
116     CMPx_CS |= CS_CMP1PSEL(plus_input);
117     CMP1_CS = CMPx_CS;
118 }
119 
120 /*!
121     \brief      initialize comparator output
122     \param[in]  cmp_periph
123       \arg        CMP0: comparator 0
124       \arg        CMP1: comparator 1
125       \param[in]  output_selection
126       \arg        CMP_OUTPUT_NONE: output no selection
127       \arg        CMP_OUTPUT_TIMER1IC3: TIMER 1 channel3 input capture
128       \arg        CMP_OUTPUT_TIMER2IC0: TIMER 2 channel0 input capture
129       \arg        CMP_OUTPUT_LPTIMERIC0_IC1: LPTIMER channel0 or channel1 input capture
130     \param[in]  output_polarity
131       \arg        CMP_OUTPUT_POLARITY_INVERTED: output is inverted
132       \arg        CMP_OUTPUT_POLARITY_NOINVERTED: output is not inverted
133     \param[out] none
134     \retval     none
135 */
cmp_output_init(uint32_t cmp_periph,cmp_output_enum output_selection,cmp_output_inv_enum output_polarity)136 void cmp_output_init(uint32_t cmp_periph, cmp_output_enum output_selection, cmp_output_inv_enum output_polarity)
137 {
138     uint32_t CMPx_CS = 0x00000000U;
139     if(CMP0 == cmp_periph){
140         /* initialize comparator 0 output */
141         CMPx_CS = CMP0_CS;
142         CMPx_CS &= ~(uint32_t)CMP0_CS_OSEL;
143         CMPx_CS |= (uint32_t)CS_CMP0OSEL(output_selection);
144         /* output polarity */
145         if(CMP_OUTPUT_POLARITY_INVERTED == output_polarity){
146             CMPx_CS |= (uint32_t)CMP0_CS_PL;
147         }else{
148             CMPx_CS &= ~(uint32_t)CMP0_CS_PL;
149         }
150         CMP0_CS = CMPx_CS;
151     }else if(CMP1 == cmp_periph){
152         /* initialize comparator 1 output */
153         CMPx_CS = CMP1_CS;
154         CMPx_CS &= ~(uint32_t)CMP1_CS_OSEL;
155         CMPx_CS |= (uint32_t)CS_CMP1OSEL(output_selection);
156         /* output polarity */
157         if(CMP_OUTPUT_POLARITY_INVERTED == output_polarity){
158             CMPx_CS |= (uint32_t)CMP1_CS_PL;
159         }else{
160             CMPx_CS &= ~(uint32_t)CMP1_CS_PL;
161         }
162         CMP1_CS = CMPx_CS;
163     } else {
164     }
165 }
166 
167 /*!
168     \brief      initialize comparator blanking function
169     \param[in]  cmp_periph
170       \arg        CMP0: comparator 0
171       \arg        CMP1: comparator 1
172     \param[in]  blanking_source_selection
173       \arg        CMP_BLANKING_NONE: output no selection
174       \arg        CMP_BLANKING_TIMER1_OC1: TIMER 1 output channel 1
175       \arg        CMP_BLANKING_TIMER2_OC1: TIMER 2 output channel 1
176       \arg        CMP_BLANKING_TIMER8_OC1: TIMER 8 output channel 1
177       \arg        CMP_BLANKING_TIMER11_OC1: TIMER 11 output channel 1
178     \param[out] none
179     \retval     none
180 */
cmp_blanking_init(uint32_t cmp_periph,blanking_source_enum blanking_source_selection)181 void cmp_blanking_init(uint32_t cmp_periph, blanking_source_enum blanking_source_selection)
182 {
183     uint32_t CMPx_CS = 0x00000000U;
184     if(CMP0 == cmp_periph){
185         CMPx_CS = CMP0_CS;
186         CMP0_CS |= (uint32_t)CS_CMP0BLK(blanking_source_selection);
187         CMP0_CS = CMPx_CS;
188     }else if(CMP1 == cmp_periph){
189         CMPx_CS = CMP1_CS;
190         CMP1_CS |= (uint32_t)CS_CMP1BLK(blanking_source_selection);
191         CMP1_CS = CMPx_CS;
192     }else{
193     }
194 }
195 
196 /*!
197     \brief      enable comparator
198     \param[in]  cmp_periph
199       \arg        CMP0: comparator 0
200       \arg        CMP1: comparator 1
201     \param[out] none
202     \retval     none
203 */
cmp_enable(uint32_t cmp_periph)204 void cmp_enable(uint32_t cmp_periph)
205 {
206     if(CMP0 == cmp_periph){
207         CMP0_CS |= (uint32_t)CMP0_CS_EN;
208     }else{
209         CMP1_CS |= (uint32_t)CMP1_CS_EN;
210     }
211 }
212 
213 /*!
214     \brief      disable comparator
215     \param[in]  cmp_periph
216       \arg        CMP0: comparator 0
217       \arg        CMP1: comparator 1
218     \param[out] none
219     \retval     none
220 */
cmp_disable(uint32_t cmp_periph)221 void cmp_disable(uint32_t cmp_periph)
222 {
223     if(CMP0 == cmp_periph){
224         CMP0_CS &= ~(uint32_t)CMP0_CS_EN;
225     }else{
226         CMP1_CS &= ~(uint32_t)CMP1_CS_EN;
227     }
228 }
229 
230 /*!
231     \brief      enable the window mode
232     \param[in]  none
233     \param[out] none
234     \retval     none
235 */
cmp_window_enable(void)236 void cmp_window_enable(void)
237 {
238     CMP1_CS |= (uint32_t)CS_CMP1WEN_ENABLE;
239 }
240 
241 /*!
242     \brief      disable the window mode
243     \param[in]  none
244     \param[out] none
245     \retval     none
246 */
cmp_window_disable(void)247 void cmp_window_disable(void)
248 {
249     CMP1_CS &= ~(uint32_t)CS_CMP1WEN_ENABLE;
250 }
251 
252 /*!
253     \brief      enable the voltage scaler
254     \param[in]  none
255     \param[out] none
256     \retval     none
257 */
cmp_voltage_scaler_enable(uint32_t cmp_periph)258 void cmp_voltage_scaler_enable(uint32_t cmp_periph)
259 {
260     if(CMP0 == cmp_periph){
261         CMP0_CS |= (uint32_t)CMP0_CS_SEN;
262     }else{
263         CMP1_CS |= (uint32_t)CMP1_CS_SEN;
264     }
265 }
266 /*!
267     \brief      disable the voltage scaler
268     \param[in]  none
269     \param[out] none
270     \retval     none
271 */
cmp_voltage_scaler_disable(uint32_t cmp_periph)272 void cmp_voltage_scaler_disable(uint32_t cmp_periph)
273 {
274     if(CMP0 == cmp_periph){
275         CMP0_CS &= ~(uint32_t)CMP0_CS_SEN;
276     }else{
277         CMP1_CS &= ~(uint32_t)CMP1_CS_SEN;
278     }
279 }
280 /*!
281     \brief      enable the scaler bridge
282     \param[in]  none
283     \param[out] none
284     \retval     none
285 */
cmp_scaler_bridge_enable(uint32_t cmp_periph)286 void cmp_scaler_bridge_enable(uint32_t cmp_periph)
287 {
288     if(CMP0 == cmp_periph){
289         CMP0_CS |= (uint32_t)CMP0_CS_BEN;
290     }else{
291         CMP1_CS |= (uint32_t)CMP1_CS_BEN;
292     }
293 }
294 /*!
295     \brief      disable the scaler bridge
296     \param[in]  none
297     \param[out] none
298     \retval     none
299 */
cmp_scaler_bridge_disable(uint32_t cmp_periph)300 void cmp_scaler_bridge_disable(uint32_t cmp_periph)
301 {
302     if(CMP0 == cmp_periph){
303         CMP0_CS &= ~(uint32_t)CMP0_CS_BEN;
304     }else{
305         CMP1_CS &= ~(uint32_t)CMP1_CS_BEN;
306     }
307 }
308 
309 /*!
310     \brief      lock the comparator
311     \param[in]  cmp_periph
312       \arg        CMP0: comparator 0
313       \arg        CMP1: comparator 1
314     \param[out] none
315     \retval     none
316 */
cmp_lock_enable(uint32_t cmp_periph)317 void cmp_lock_enable(uint32_t cmp_periph)
318 {
319     if(CMP0 == cmp_periph){
320         /* lock CMP0 */
321         CMP0_CS |= (uint32_t)CMP0_CS_LK;
322     }else{
323         /* lock CMP1 */
324         CMP1_CS |= (uint32_t)CMP1_CS_LK;
325     }
326 }
327 
328 /*!
329     \brief      get output level
330     \param[in]  cmp_periph
331       \arg        CMP0: comparator 0
332       \arg        CMP1: comparator 1
333     \param[out] none
334     \retval     the output level
335 */
cmp_output_level_get(uint32_t cmp_periph)336 uint32_t cmp_output_level_get(uint32_t cmp_periph)
337 {
338     if(CMP0 == cmp_periph){
339         /* get output level of CMP0 */
340         if(CMP0_CS & CMP0_CS_OUT){
341             return CMP_OUTPUTLEVEL_HIGH;
342         }else{
343             return CMP_OUTPUTLEVEL_LOW;
344         }
345     }else{
346         /* get output level of CMP1 */
347         if(CMP1_CS & CMP1_CS_OUT){
348             return CMP_OUTPUTLEVEL_HIGH;
349         }else{
350             return CMP_OUTPUTLEVEL_LOW;
351         }
352     }
353 }
354