1 /*!
2     \file    gd32f3x0_cmp.c
3     \brief   CMP driver
4 
5     \version 2017-06-06, V1.0.0, firmware for GD32F3x0
6     \version 2019-06-01, V2.0.0, firmware for GD32F3x0
7     \version 2020-09-30, V2.1.0, firmware for GD32F3x0
8 */
9 
10 /*
11     Copyright (c) 2020, GigaDevice Semiconductor Inc.
12 
13     Redistribution and use in source and binary forms, with or without modification,
14 are permitted provided that the following conditions are met:
15 
16     1. Redistributions of source code must retain the above copyright notice, this
17        list of conditions and the following disclaimer.
18     2. Redistributions in binary form must reproduce the above copyright notice,
19        this list of conditions and the following disclaimer in the documentation
20        and/or other materials provided with the distribution.
21     3. Neither the name of the copyright holder nor the names of its contributors
22        may be used to endorse or promote products derived from this software without
23        specific prior written permission.
24 
25     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 OF SUCH DAMAGE.
35 */
36 
37 #include "gd32f3x0_cmp.h"
38 
39 /*!
40     \brief      deinitialize comparator
41     \param[in]  none
42     \param[out] none
43     \retval     none
44 */
cmp_deinit(void)45 void cmp_deinit(void)
46 {
47     CMP_CS = ((uint32_t)0x00000000U);
48 }
49 
50 /*!
51     \brief      initialize comparator mode
52     \param[in]  cmp_periph
53       \arg        CMP0: comparator 0
54       \arg        CMP1: comparator 1
55     \param[in]  operating_mode
56       \arg        CMP_HIGHSPEED: high speed mode
57       \arg        CMP_MIDDLESPEED: medium speed mode
58       \arg        CMP_LOWSPEED: low speed mode
59       \arg        CMP_VERYLOWSPEED: very-low speed mode
60     \param[in]  inverting_input
61       \arg        CMP_1_4VREFINT: VREFINT *1/4 input
62       \arg        CMP_1_2VREFINT: VREFINT *1/2 input
63       \arg        CMP_3_4VREFINT: VREFINT *3/4 input
64       \arg        CMP_VREFINT: VREFINT input
65       \arg        CMP_DAC: PA4 (DAC) input
66       \arg        CMP_PA5: PA5 input
67       \arg        CMP_PA_0_2: PA0 or PA2 input
68     \param[in]  hysteresis
69       \arg        CMP_HYSTERESIS_NO: output no hysteresis
70       \arg        CMP_HYSTERESIS_LOW: output low hysteresis
71       \arg        CMP_HYSTERESIS_MIDDLE: output middle hysteresis
72       \arg        CMP_HYSTERESIS_HIGH: output high hysteresis
73     \param[out] none
74     \retval     none
75 */
cmp_mode_init(uint32_t cmp_periph,operating_mode_enum operating_mode,inverting_input_enum inverting_input,cmp_hysteresis_enum output_hysteresis)76 void cmp_mode_init(uint32_t cmp_periph, operating_mode_enum operating_mode, inverting_input_enum inverting_input, cmp_hysteresis_enum output_hysteresis)
77 {
78     uint32_t CMPx_CS = 0;
79     if(CMP0 == cmp_periph){
80         /* initialize comparator 0 mode */
81         CMPx_CS = CMP_CS;
82         CMPx_CS &= ~(uint32_t)(CMP_CS_CMP0M | CMP_CS_CMP0MSEL | CMP_CS_CMP0HST );
83         CMPx_CS |= CS_CMP0M(operating_mode) | CS_CMP0MSEL(inverting_input) | CS_CMP0HST(output_hysteresis);
84         CMP_CS = CMPx_CS;
85     }else{
86         /* initialize comparator 1 mode */
87         CMPx_CS = CMP_CS;
88         CMPx_CS &= ~(uint32_t)(CMP_CS_CMP1M | CMP_CS_CMP1MSEL | CMP_CS_CMP1HST );
89         CMPx_CS |= CS_CMP1M(operating_mode) | CS_CMP1MSEL(inverting_input) | CS_CMP1HST(output_hysteresis);
90         CMP_CS = CMPx_CS;
91     }
92 }
93 
94 /*!
95     \brief      initialize comparator output
96     \param[in]  cmp_periph
97       \arg        CMP0: comparator 0
98       \arg        CMP1: comparator 1
99     \param[in]  output_slection
100       \arg        CMP_OUTPUT_NONE: output no selection
101       \arg        CMP_OUTPUT_TIMER0BKIN: TIMER 0 break input
102       \arg        CMP_OUTPUT_TIMER0IC0: TIMER 0 channel0 input capture
103       \arg        CMP_OUTPUT_TIMER0OCPRECLR: TIMER 0 OCPRE_CLR input
104       \arg        CMP_OUTPUT_TIMER1IC3: TIMER 1 channel3 input capture
105       \arg        CMP_OUTPUT_TIMER1OCPRECLR: TIMER 1 OCPRE_CLR input
106       \arg        CMP_OUTPUT_TIMER2IC0: TIMER 2 channel0 input capture
107       \arg        CMP_OUTPUT_TIMER2OCPRECLR: TIMER 2 OCPRE_CLR input
108     \param[in]  output_polarity
109       \arg        CMP_OUTPUT_POLARITY_INVERTED: output is inverted
110       \arg        CMP_OUTPUT_POLARITY_NOINVERTED: output is not inverted
111     \param[out] none
112     \retval     none
113 */
cmp_output_init(uint32_t cmp_periph,cmp_output_enum output_slection,uint32_t output_polarity)114 void cmp_output_init(uint32_t cmp_periph, cmp_output_enum output_slection, uint32_t output_polarity)
115 {
116     uint32_t CMPx_CS = 0;
117     /* initialize comparator 0 output */
118     if(CMP0 == cmp_periph){
119         CMPx_CS = CMP_CS;
120         CMPx_CS &= ~(uint32_t)CMP_CS_CMP0OSEL;
121         CMPx_CS |= CS_CMP0OSEL(output_slection);
122         /* output polarity */
123         if(CMP_OUTPUT_POLARITY_INVERTED == output_polarity){
124             CMPx_CS |= CMP_CS_CMP0PL;
125         }else{
126             CMPx_CS &= ~CMP_CS_CMP0PL;
127         }
128         CMP_CS = CMPx_CS;
129     }else if(CMP1 == cmp_periph){
130         /* initialize comparator 1 output */
131         CMPx_CS = CMP_CS;
132         CMPx_CS &= ~(uint32_t)CMP_CS_CMP1OSEL;
133         CMPx_CS |= CS_CMP1OSEL(output_slection);
134         /* output polarity */
135         if(CMP_OUTPUT_POLARITY_INVERTED == output_polarity){
136             CMPx_CS |= CMP_CS_CMP1PL;
137         }else{
138             CMPx_CS &= ~CMP_CS_CMP1PL;
139         }
140         CMP_CS = CMPx_CS;
141     }
142 }
143 
144 /*!
145     \brief      enable comparator
146     \param[in]  cmp_periph
147       \arg        CMP0: comparator 0
148       \arg        CMP1: comparator 1
149     \param[out] none
150     \retval     none
151 */
cmp_enable(uint32_t cmp_periph)152 void cmp_enable(uint32_t cmp_periph)
153 {
154     if(CMP0 == cmp_periph){
155         CMP_CS |= CMP_CS_CMP0EN;
156     }else{
157         CMP_CS |= CMP_CS_CMP1EN;
158     }
159 }
160 
161 /*!
162     \brief      disable comparator
163     \param[in]  cmp_periph
164       \arg        CMP0: comparator 0
165       \arg        CMP1: comparator 1
166     \param[out] none
167     \retval     none
168 */
cmp_disable(uint32_t cmp_periph)169 void cmp_disable(uint32_t cmp_periph)
170 {
171     if(CMP0 == cmp_periph){
172         CMP_CS &= ~CMP_CS_CMP0EN;
173     }else{
174         CMP_CS &= ~CMP_CS_CMP1EN;
175     }
176 }
177 
178 /*!
179     \brief      enable comparator switch
180     \param[in]  none
181     \param[out] none
182     \retval     none
183 */
cmp_switch_enable(void)184 void cmp_switch_enable(void)
185 {
186     CMP_CS |= CMP_CS_CMP0SW;
187 }
188 
189 /*!
190     \brief      disable comparator switch
191     \param[in]  none
192     \param[out] none
193     \retval     none
194 */
cmp_switch_disable(void)195 void cmp_switch_disable(void)
196 {
197     CMP_CS &= ~CMP_CS_CMP0SW;
198 }
199 
200 /*!
201     \brief      enable the window mode
202     \param[in]  none
203     \param[out] none
204     \retval     none
205 */
cmp_window_enable(void)206 void cmp_window_enable(void)
207 {
208     CMP_CS |= CMP_CS_WNDEN;
209 }
210 
211 /*!
212     \brief      disable the window mode
213     \param[in]  none
214     \param[out] none
215     \retval     none
216 */
cmp_window_disable(void)217 void cmp_window_disable(void)
218 {
219     CMP_CS &= ~CMP_CS_WNDEN;
220 }
221 
222 /*!
223     \brief      lock the comparator
224     \param[in]  cmp_periph
225       \arg        CMP0: comparator 0
226       \arg        CMP1: comparator 1
227     \param[out] none
228     \retval     none
229 */
cmp_lock_enable(uint32_t cmp_periph)230 void cmp_lock_enable(uint32_t cmp_periph)
231 {
232     if(CMP0 == cmp_periph){
233         /* lock CMP0 */
234         CMP_CS |= CMP_CS_CMP0LK;
235     }else{
236         /* lock CMP1 */
237         CMP_CS |= CMP_CS_CMP1LK;
238     }
239 }
240 
241 /*!
242     \brief      get output level
243     \param[in]  cmp_periph
244       \arg        CMP0: comparator 0
245       \arg        CMP1: comparator 1
246     \param[out] none
247     \retval     the output level
248 */
cmp_output_level_get(uint32_t cmp_periph)249 uint32_t cmp_output_level_get(uint32_t cmp_periph)
250 {
251     if(CMP0 == cmp_periph){
252         /* get output level of CMP0 */
253         if(CMP_CS & CMP_CS_CMP0O){
254             return CMP_OUTPUTLEVEL_HIGH;
255         }else{
256             return CMP_OUTPUTLEVEL_LOW;
257         }
258     }else{
259         /* get output level of CMP1 */
260         if(CMP_CS & CMP_CS_CMP1O){
261             return CMP_OUTPUTLEVEL_HIGH;
262         }else{
263             return CMP_OUTPUTLEVEL_LOW;
264         }
265     }
266 }
267