1 /*!
2     \file    gd32e10x_dac.c
3     \brief   DAC driver
4 
5     \version 2017-12-26, V1.0.0, firmware for GD32E10x
6     \version 2020-09-30, V1.1.0, firmware for GD32E10x
7     \version 2020-12-31, V1.2.0, firmware for GD32E10x
8     \version 2022-06-30, V1.3.0, firmware for GD32E10x
9 */
10 
11 /*
12     Copyright (c) 2022, GigaDevice Semiconductor Inc.
13 
14     Redistribution and use in source and binary forms, with or without modification,
15 are permitted provided that the following conditions are met:
16 
17     1. Redistributions of source code must retain the above copyright notice, this
18        list of conditions and the following disclaimer.
19     2. Redistributions in binary form must reproduce the above copyright notice,
20        this list of conditions and the following disclaimer in the documentation
21        and/or other materials provided with the distribution.
22     3. Neither the name of the copyright holder nor the names of its contributors
23        may be used to endorse or promote products derived from this software without
24        specific prior written permission.
25 
26     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35 OF SUCH DAMAGE.
36 */
37 
38 #include "gd32e10x_dac.h"
39 
40 /* DAC register bit offset */
41 #define DAC1_REG_OFFSET           ((uint32_t)16U)
42 #define DH_12BIT_OFFSET           ((uint32_t)16U)
43 #define DH_8BIT_OFFSET            ((uint32_t)8U)
44 
45 /*!
46     \brief      deinitialize DAC
47     \param[in]  none
48     \param[out] none
49     \retval     none
50 */
dac_deinit(void)51 void dac_deinit(void)
52 {
53     rcu_periph_reset_enable(RCU_DACRST);
54     rcu_periph_reset_disable(RCU_DACRST);
55 }
56 
57 /*!
58     \brief      enable DAC
59     \param[in]  dac_periph
60       \arg        DACx(x=0,1)
61     \param[out] none
62     \retval     none
63 */
dac_enable(uint32_t dac_periph)64 void dac_enable(uint32_t dac_periph)
65 {
66     if(DAC0 == dac_periph){
67         DAC_CTL |= DAC_CTL_DEN0;
68     }else{
69         DAC_CTL |= DAC_CTL_DEN1;
70     }
71 }
72 
73 /*!
74     \brief      disable DAC
75     \param[in]  dac_periph
76       \arg        DACx(x=0,1)
77     \param[out] none
78     \retval     none
79 */
dac_disable(uint32_t dac_periph)80 void dac_disable(uint32_t dac_periph)
81 {
82     if(DAC0 == dac_periph){
83         DAC_CTL &= ~DAC_CTL_DEN0;
84     }else{
85         DAC_CTL &= ~DAC_CTL_DEN1;
86     }
87 }
88 
89 /*!
90     \brief      enable DAC DMA function
91     \param[in]  dac_periph
92       \arg        DACx(x=0,1)
93     \param[out] none
94     \retval     none
95 */
dac_dma_enable(uint32_t dac_periph)96 void dac_dma_enable(uint32_t dac_periph)
97 {
98     if(DAC0 == dac_periph){
99         DAC_CTL |= DAC_CTL_DDMAEN0;
100     }else{
101         DAC_CTL |= DAC_CTL_DDMAEN1;
102     }
103 }
104 
105 /*!
106     \brief      disable DAC DMA function
107     \param[in]  dac_periph
108       \arg        DACx(x=0,1)
109     \param[out] none
110     \retval     none
111 */
dac_dma_disable(uint32_t dac_periph)112 void dac_dma_disable(uint32_t dac_periph)
113 {
114     if(DAC0 == dac_periph){
115         DAC_CTL &= ~DAC_CTL_DDMAEN0;
116     }else{
117         DAC_CTL &= ~DAC_CTL_DDMAEN1;
118     }
119 }
120 
121 /*!
122     \brief      enable DAC output buffer
123     \param[in]  dac_periph
124       \arg        DACx(x=0,1)
125     \param[out] none
126     \retval     none
127 */
dac_output_buffer_enable(uint32_t dac_periph)128 void dac_output_buffer_enable(uint32_t dac_periph)
129 {
130     if(DAC0 == dac_periph){
131         DAC_CTL &= ~DAC_CTL_DBOFF0;
132     }else{
133         DAC_CTL &= ~DAC_CTL_DBOFF1;
134     }
135 }
136 
137 /*!
138     \brief      disable DAC output buffer
139     \param[in]  dac_periph
140       \arg        DACx(x=0,1)
141     \param[out] none
142     \retval     none
143 */
dac_output_buffer_disable(uint32_t dac_periph)144 void dac_output_buffer_disable(uint32_t dac_periph)
145 {
146     if(DAC0 == dac_periph){
147         DAC_CTL |= DAC_CTL_DBOFF0;
148     }else{
149         DAC_CTL |= DAC_CTL_DBOFF1;
150     }
151 }
152 
153 /*!
154     \brief      get DAC output value
155     \param[in]  dac_periph
156       \arg        DACx(x=0,1)
157     \param[out] none
158     \retval     DAC output data
159 */
dac_output_value_get(uint32_t dac_periph)160 uint16_t dac_output_value_get(uint32_t dac_periph)
161 {
162     uint16_t data = 0U;
163     if(DAC0 == dac_periph){
164         /* store the DAC0 output value */
165         data = (uint16_t)DAC0_DO;
166     }else{
167         /* store the DAC1 output value */
168         data = (uint16_t)DAC1_DO;
169     }
170     return data;
171 }
172 
173 /*!
174     \brief      set the DAC specified data holding register value
175     \param[in]  dac_periph
176       \arg        DACx(x=0,1)
177     \param[in]  dac_align
178                 only one parameter can be selected which is shown as below:
179       \arg        DAC_ALIGN_8B_R: data right 8b alignment
180       \arg        DAC_ALIGN_12B_R: data right 12b alignment
181       \arg        DAC_ALIGN_12B_L: data left 12b alignment
182     \param[in]  data: data to be loaded
183     \param[out] none
184     \retval     none
185 */
dac_data_set(uint32_t dac_periph,uint32_t dac_align,uint16_t data)186 void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data)
187 {
188     if(DAC0 == dac_periph){
189         switch(dac_align){
190         /* data right 12b alignment */
191         case DAC_ALIGN_12B_R:
192             DAC0_R12DH = data;
193             break;
194         /* data left 12b alignment */
195         case DAC_ALIGN_12B_L:
196             DAC0_L12DH = data;
197             break;
198         /* data right 8b alignment */
199         case DAC_ALIGN_8B_R:
200             DAC0_R8DH = data;
201             break;
202         default:
203             break;
204         }
205     }else{
206         switch(dac_align){
207         /* data right 12b alignment */
208         case DAC_ALIGN_12B_R:
209             DAC1_R12DH = data;
210             break;
211         /* data left 12b alignment */
212         case DAC_ALIGN_12B_L:
213             DAC1_L12DH = data;
214             break;
215         /* data right 8b alignment */
216         case DAC_ALIGN_8B_R:
217             DAC1_R8DH = data;
218             break;
219         default:
220             break;
221         }
222     }
223 }
224 
225 /*!
226     \brief      enable DAC trigger
227     \param[in]  dac_periph
228       \arg        DACx(x=0,1)
229     \param[out] none
230     \retval     none
231 */
dac_trigger_enable(uint32_t dac_periph)232 void dac_trigger_enable(uint32_t dac_periph)
233 {
234     if(DAC0 == dac_periph){
235         DAC_CTL |= DAC_CTL_DTEN0;
236     }else{
237         DAC_CTL |= DAC_CTL_DTEN1;
238     }
239 }
240 
241 /*!
242     \brief      disable DAC trigger
243     \param[in]  dac_periph
244       \arg        DACx(x=0,1)
245     \param[out] none
246     \retval     none
247 */
dac_trigger_disable(uint32_t dac_periph)248 void dac_trigger_disable(uint32_t dac_periph)
249 {
250     if(DAC0 == dac_periph){
251         DAC_CTL &= ~DAC_CTL_DTEN0;
252     }else{
253         DAC_CTL &= ~DAC_CTL_DTEN1;
254     }
255 }
256 
257 /*!
258     \brief      set DAC trigger source
259     \param[in]  dac_periph
260       \arg        DACx(x=0,1)
261     \param[in]  triggersource: external triggers of DAC
262                 only one parameter can be selected which is shown as below:
263       \arg        DAC_TRIGGER_T1_TRGO: TIMER1 TRGO
264       \arg        DAC_TRIGGER_T2_TRGO: TIMER2 TRGO
265       \arg        DAC_TRIGGER_T3_TRGO: TIMER3 TRGO
266       \arg        DAC_TRIGGER_T4_TRGO: TIMER4 TRGO
267       \arg        DAC_TRIGGER_T5_TRGO: TIMER5 TRGO
268       \arg        DAC_TRIGGER_T6_TRGO: TIMER6 TRGO
269       \arg        DAC_TRIGGER_EXTI_9: EXTI interrupt line9 event
270       \arg        DAC_TRIGGER_SOFTWARE: software trigger
271     \param[out] none
272     \retval     none
273 */
dac_trigger_source_config(uint32_t dac_periph,uint32_t triggersource)274 void dac_trigger_source_config(uint32_t dac_periph,uint32_t triggersource)
275 {
276     if(DAC0 == dac_periph){
277         /* configure DAC0 trigger source */
278         DAC_CTL &= ~DAC_CTL_DTSEL0;
279         DAC_CTL |= triggersource;
280     }else{
281         /* configure DAC1 trigger source */
282         DAC_CTL &= ~DAC_CTL_DTSEL1;
283         DAC_CTL |= (triggersource << DAC1_REG_OFFSET);
284     }
285 }
286 
287 /*!
288     \brief      enable DAC software trigger
289     \param[in]  dac_periph
290       \arg        DACx(x=0,1)
291     \retval     none
292 */
dac_software_trigger_enable(uint32_t dac_periph)293 void dac_software_trigger_enable(uint32_t dac_periph)
294 {
295     if(DAC0 == dac_periph){
296         DAC_SWT |= DAC_SWT_SWTR0;
297     }else{
298         DAC_SWT |= DAC_SWT_SWTR1;
299     }
300 }
301 
302 /*!
303     \brief      disable DAC software trigger
304     \param[in]  dac_periph
305       \arg        DACx(x=0,1)
306     \param[out] none
307     \retval     none
308 */
dac_software_trigger_disable(uint32_t dac_periph)309 void dac_software_trigger_disable(uint32_t dac_periph)
310 {
311     if(DAC0 == dac_periph){
312         DAC_SWT &= ~DAC_SWT_SWTR0;
313     }else{
314         DAC_SWT &= ~DAC_SWT_SWTR1;
315     }
316 }
317 
318 /*!
319     \brief      configure DAC wave mode
320     \param[in]  dac_periph
321       \arg        DACx(x=0,1)
322     \param[in]  wave_mode
323                 only one parameter can be selected which is shown as below:
324       \arg        DAC_WAVE_DISABLE: wave disable
325       \arg        DAC_WAVE_MODE_LFSR: LFSR noise mode
326       \arg        DAC_WAVE_MODE_TRIANGLE: triangle noise mode
327     \param[out] none
328     \retval     none
329 */
dac_wave_mode_config(uint32_t dac_periph,uint32_t wave_mode)330 void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode)
331 {
332     if(DAC0 == dac_periph){
333         /* configure DAC0 wave mode */
334         DAC_CTL &= ~DAC_CTL_DWM0;
335         DAC_CTL |= wave_mode;
336     }else{
337         /* configure DAC1 wave mode */
338         DAC_CTL &= ~DAC_CTL_DWM1;
339         DAC_CTL |= (wave_mode << DAC1_REG_OFFSET);
340     }
341 }
342 
343 /*!
344     \brief      configure DAC wave bit width
345     \param[in]  dac_periph
346       \arg        DACx(x=0,1)
347     \param[in]  bit_width
348                 only one parameter can be selected which is shown as below:
349       \arg        DAC_WAVE_BIT_WIDTH_1: bit width of the wave signal is 1
350       \arg        DAC_WAVE_BIT_WIDTH_2: bit width of the wave signal is 2
351       \arg        DAC_WAVE_BIT_WIDTH_3: bit width of the wave signal is 3
352       \arg        DAC_WAVE_BIT_WIDTH_4: bit width of the wave signal is 4
353       \arg        DAC_WAVE_BIT_WIDTH_5: bit width of the wave signal is 5
354       \arg        DAC_WAVE_BIT_WIDTH_6: bit width of the wave signal is 6
355       \arg        DAC_WAVE_BIT_WIDTH_7: bit width of the wave signal is 7
356       \arg        DAC_WAVE_BIT_WIDTH_8: bit width of the wave signal is 8
357       \arg        DAC_WAVE_BIT_WIDTH_9: bit width of the wave signal is 9
358       \arg        DAC_WAVE_BIT_WIDTH_10: bit width of the wave signal is 10
359       \arg        DAC_WAVE_BIT_WIDTH_11: bit width of the wave signal is 11
360       \arg        DAC_WAVE_BIT_WIDTH_12: bit width of the wave signal is 12
361     \param[out] none
362     \retval     none
363 */
dac_wave_bit_width_config(uint32_t dac_periph,uint32_t bit_width)364 void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width)
365 {
366     if(DAC0 == dac_periph){
367         /* configure DAC0 wave bit width */
368         DAC_CTL &= ~DAC_CTL_DWBW0;
369         DAC_CTL |= bit_width;
370     }else{
371         /* configure DAC1 wave bit width */
372         DAC_CTL &= ~DAC_CTL_DWBW1;
373         DAC_CTL |= (bit_width << DAC1_REG_OFFSET);
374     }
375 }
376 
377 /*!
378     \brief      configure DAC LFSR noise mode
379     \param[in]  dac_periph
380       \arg        DACx(x=0,1)
381     \param[in]  unmask_bits
382                 only one parameter can be selected which is shown as below:
383       \arg        DAC_LFSR_BIT0: unmask the LFSR bit0
384       \arg        DAC_LFSR_BITS1_0: unmask the LFSR bits[1:0]
385       \arg        DAC_LFSR_BITS2_0: unmask the LFSR bits[2:0]
386       \arg        DAC_LFSR_BITS3_0: unmask the LFSR bits[3:0]
387       \arg        DAC_LFSR_BITS4_0: unmask the LFSR bits[4:0]
388       \arg        DAC_LFSR_BITS5_0: unmask the LFSR bits[5:0]
389       \arg        DAC_LFSR_BITS6_0: unmask the LFSR bits[6:0]
390       \arg        DAC_LFSR_BITS7_0: unmask the LFSR bits[7:0]
391       \arg        DAC_LFSR_BITS8_0: unmask the LFSR bits[8:0]
392       \arg        DAC_LFSR_BITS9_0: unmask the LFSR bits[9:0]
393       \arg        DAC_LFSR_BITS10_0: unmask the LFSR bits[10:0]
394       \arg        DAC_LFSR_BITS11_0: unmask the LFSR bits[11:0]
395     \param[out] none
396     \retval     none
397 */
dac_lfsr_noise_config(uint32_t dac_periph,uint32_t unmask_bits)398 void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits)
399 {
400     if(DAC0 == dac_periph){
401         /* configure DAC0 LFSR noise mode */
402         DAC_CTL &= ~DAC_CTL_DWBW0;
403         DAC_CTL |= unmask_bits;
404     }else{
405         /* configure DAC1 LFSR noise mode */
406         DAC_CTL &= ~DAC_CTL_DWBW1;
407         DAC_CTL |= (unmask_bits << DAC1_REG_OFFSET);
408     }
409 }
410 
411 /*!
412     \brief      configure DAC triangle noise mode
413     \param[in]  dac_periph
414       \arg        DACx(x=0,1)
415     \param[in]  amplitude
416                 only one parameter can be selected which is shown as below:
417       \arg        DAC_TRIANGLE_AMPLITUDE_1: triangle amplitude is 1
418       \arg        DAC_TRIANGLE_AMPLITUDE_3: triangle amplitude is 3
419       \arg        DAC_TRIANGLE_AMPLITUDE_7: triangle amplitude is 7
420       \arg        DAC_TRIANGLE_AMPLITUDE_15: triangle amplitude is 15
421       \arg        DAC_TRIANGLE_AMPLITUDE_31: triangle amplitude is 31
422       \arg        DAC_TRIANGLE_AMPLITUDE_63: triangle amplitude is 63
423       \arg        DAC_TRIANGLE_AMPLITUDE_127: triangle amplitude is 127
424       \arg        DAC_TRIANGLE_AMPLITUDE_255: triangle amplitude is 255
425       \arg        DAC_TRIANGLE_AMPLITUDE_511: triangle amplitude is 511
426       \arg        DAC_TRIANGLE_AMPLITUDE_1023: triangle amplitude is 1023
427       \arg        DAC_TRIANGLE_AMPLITUDE_2047: triangle amplitude is 2047
428       \arg        DAC_TRIANGLE_AMPLITUDE_4095: triangle amplitude is 4095
429     \param[out] none
430     \retval     none
431 */
dac_triangle_noise_config(uint32_t dac_periph,uint32_t amplitude)432 void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude)
433 {
434     if(DAC0 == dac_periph){
435         /* configure DAC0 triangle noise mode */
436         DAC_CTL &= ~DAC_CTL_DWBW0;
437         DAC_CTL |= amplitude;
438     }else{
439         /* configure DAC1 triangle noise mode */
440         DAC_CTL &= ~DAC_CTL_DWBW1;
441         DAC_CTL |= (amplitude << DAC1_REG_OFFSET);
442     }
443 }
444 
445 /*!
446     \brief      enable DAC concurrent mode
447     \param[in]  none
448     \param[out] none
449     \retval     none
450 */
dac_concurrent_enable(void)451 void dac_concurrent_enable(void)
452 {
453     uint32_t ctl = 0U;
454     ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1;
455     DAC_CTL |= (ctl);
456 }
457 
458 /*!
459     \brief      disable DAC concurrent mode
460     \param[in]  none
461     \param[out] none
462     \retval     none
463 */
dac_concurrent_disable(void)464 void dac_concurrent_disable(void)
465 {
466     uint32_t ctl = 0U;
467     ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1;
468     DAC_CTL &= (~ctl);
469 }
470 
471 /*!
472     \brief      enable DAC concurrent software trigger function
473     \param[in]  none
474     \param[out] none
475     \retval     none
476 */
dac_concurrent_software_trigger_enable(void)477 void dac_concurrent_software_trigger_enable(void)
478 {
479     uint32_t swt = 0U;
480     swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1;
481     DAC_SWT |= (swt);
482 }
483 
484 /*!
485     \brief      disable DAC concurrent software trigger function
486     \param[in]  none
487     \param[out] none
488     \retval     none
489 */
dac_concurrent_software_trigger_disable(void)490 void dac_concurrent_software_trigger_disable(void)
491 {
492     uint32_t swt = 0U;
493     swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1;
494     DAC_SWT &= (~swt);
495 }
496 
497 /*!
498     \brief      enable DAC concurrent buffer function
499     \param[in]  none
500     \param[out] none
501     \retval     none
502 */
dac_concurrent_output_buffer_enable(void)503 void dac_concurrent_output_buffer_enable(void)
504 {
505     uint32_t ctl = 0U;
506     ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1;
507     DAC_CTL &= (~ctl);
508 }
509 
510 /*!
511     \brief      disable DAC concurrent buffer function
512     \param[in]  none
513     \param[out] none
514     \retval     none
515 */
dac_concurrent_output_buffer_disable(void)516 void dac_concurrent_output_buffer_disable(void)
517 {
518     uint32_t ctl = 0U;
519     ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1;
520     DAC_CTL |= (ctl);
521 }
522 
523 /*!
524     \brief      set DAC concurrent mode data holding register value
525     \param[in]  dac_align
526                 only one parameter can be selected which is shown as below:
527       \arg        DAC_ALIGN_8B_R: data right 8b alignment
528       \arg        DAC_ALIGN_12B_R: data right 12b alignment
529       \arg        DAC_ALIGN_12B_L: data left 12b alignment
530     \param[in]  data0: data to be loaded
531     \param[in]  data1: data to be loaded
532     \param[out] none
533     \retval     none
534 */
dac_concurrent_data_set(uint32_t dac_align,uint16_t data0,uint16_t data1)535 void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1)
536 {
537     uint32_t data = 0U;
538     switch(dac_align){
539     /* data right 12b alignment */
540     case DAC_ALIGN_12B_R:
541         data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0;
542         DACC_R12DH = data;
543         break;
544     /* data left 12b alignment */
545     case DAC_ALIGN_12B_L:
546         data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0;
547         DACC_L12DH = data;
548         break;
549     /* data right 8b alignment */
550     case DAC_ALIGN_8B_R:
551         data = ((uint32_t)data1 << DH_8BIT_OFFSET) | data0;
552         DACC_R8DH = data;
553         break;
554     default:
555         break;
556     }
557 }
558