1 /*!
2     \file    gd32f403_dac.c
3     \brief   DAC driver
4 
5     \version 2017-02-10, V1.0.0, firmware for GD32F403
6     \version 2018-12-25, V2.0.0, firmware for GD32F403
7     \version 2020-09-30, V2.1.0, firmware for GD32F403
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 "gd32f403_dac.h"
38 
39 /* DAC register bit offset */
40 #define DAC1_REG_OFFSET             ((uint32_t)16U)
41 #define DH_12BIT_OFFSET             ((uint32_t)16U)
42 #define DH_8BIT_OFFSET              ((uint32_t)8U)
43 
44 /*!
45     \brief      deinitialize DAC
46     \param[in]  none
47     \param[out] none
48     \retval     none
49 */
dac_deinit(void)50 void dac_deinit(void)
51 {
52     rcu_periph_reset_enable(RCU_DACRST);
53     rcu_periph_reset_disable(RCU_DACRST);
54 }
55 
56 /*!
57     \brief      enable DAC
58     \param[in]  dac_periph: DACx(x = 0,1)
59     \param[out] none
60     \retval     none
61 */
dac_enable(uint32_t dac_periph)62 void dac_enable(uint32_t dac_periph)
63 {
64     if(DAC0 == dac_periph){
65         DAC_CTL |= DAC_CTL_DEN0;
66     }else{
67         DAC_CTL |= DAC_CTL_DEN1;
68     }
69 }
70 
71 /*!
72     \brief      disable DAC
73     \param[in]  dac_periph: DACx(x = 0,1)
74     \param[out] none
75     \retval     none
76 */
dac_disable(uint32_t dac_periph)77 void dac_disable(uint32_t dac_periph)
78 {
79     if(DAC0 == dac_periph){
80         DAC_CTL &= ~DAC_CTL_DEN0;
81     }else{
82         DAC_CTL &= ~DAC_CTL_DEN1;
83     }
84 }
85 
86 /*!
87     \brief      enable DAC DMA function
88     \param[in]  dac_periph: DACx(x = 0,1)
89     \param[out] none
90     \retval     none
91 */
dac_dma_enable(uint32_t dac_periph)92 void dac_dma_enable(uint32_t dac_periph)
93 {
94     if(DAC0 == dac_periph){
95         DAC_CTL |= DAC_CTL_DDMAEN0;
96     }else{
97         DAC_CTL |= DAC_CTL_DDMAEN1;
98     }
99 }
100 
101 /*!
102     \brief      disable DAC DMA function
103     \param[in]  dac_periph: DACx(x = 0,1)
104     \param[out] none
105     \retval     none
106 */
dac_dma_disable(uint32_t dac_periph)107 void dac_dma_disable(uint32_t dac_periph)
108 {
109     if(DAC0 == dac_periph){
110         DAC_CTL &= ~DAC_CTL_DDMAEN0;
111     }else{
112         DAC_CTL &= ~DAC_CTL_DDMAEN1;
113     }
114 }
115 
116 /*!
117     \brief      enable DAC output buffer
118     \param[in]  dac_periph: DACx(x = 0,1)
119     \param[out] none
120     \retval     none
121 */
dac_output_buffer_enable(uint32_t dac_periph)122 void dac_output_buffer_enable(uint32_t dac_periph)
123 {
124     if(DAC0 == dac_periph){
125         DAC_CTL &= ~DAC_CTL_DBOFF0;
126     }else{
127         DAC_CTL &= ~DAC_CTL_DBOFF1;
128     }
129 }
130 
131 /*!
132     \brief      disable DAC output buffer
133     \param[in]  dac_periph: DACx(x = 0,1)
134     \param[out] none
135     \retval     none
136 */
dac_output_buffer_disable(uint32_t dac_periph)137 void dac_output_buffer_disable(uint32_t dac_periph)
138 {
139     if(DAC0 == dac_periph){
140         DAC_CTL |= DAC_CTL_DBOFF0;
141     }else{
142         DAC_CTL |= DAC_CTL_DBOFF1;
143     }
144 }
145 
146 /*!
147     \brief      get DAC output value
148     \param[in]  dac_periph: DACx(x = 0,1)
149     \param[out] none
150     \retval     DAC output data
151 */
dac_output_value_get(uint32_t dac_periph)152 uint16_t dac_output_value_get(uint32_t dac_periph)
153 {
154     uint16_t data = 0U;
155     if(DAC0 == dac_periph){
156         /* store the DAC0 output value */
157         data = (uint16_t)DAC0_DO;
158     }else{
159         /* store the DAC1 output value */
160         data = (uint16_t)DAC1_DO;
161     }
162     return data;
163 }
164 
165 /*!
166     \brief      set the DAC specified data holding register value
167     \param[in]  dac_periph: DACx(x = 0,1)
168     \param[in]  dac_align: data alignment
169                 only one parameter can be selected which is shown as below:
170       \arg        DAC_ALIGN_8B_R: data right 8 bit alignment
171       \arg        DAC_ALIGN_12B_R: data right 12 bit alignment
172       \arg        DAC_ALIGN_12B_L: data left 12 bit alignment
173     \param[in]  data: data to be loaded
174     \param[out] none
175     \retval     none
176 */
dac_data_set(uint32_t dac_periph,uint32_t dac_align,uint16_t data)177 void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data)
178 {
179     if(DAC0 == dac_periph){
180         switch(dac_align){
181         /* data right 12 bit alignment */
182         case DAC_ALIGN_12B_R:
183             DAC0_R12DH = data;
184             break;
185         /* data left 12 bit alignment */
186         case DAC_ALIGN_12B_L:
187             DAC0_L12DH = data;
188             break;
189         /* data right 8 bit alignment */
190         case DAC_ALIGN_8B_R:
191             DAC0_R8DH = data;
192             break;
193         default:
194             break;
195         }
196     }else{
197         switch(dac_align){
198         /* data right 12 bit alignment */
199         case DAC_ALIGN_12B_R:
200             DAC1_R12DH = data;
201             break;
202         /* data left 12 bit alignment */
203         case DAC_ALIGN_12B_L:
204             DAC1_L12DH = data;
205             break;
206         /* data right 8 bit alignment */
207         case DAC_ALIGN_8B_R:
208             DAC1_R8DH = data;
209             break;
210         default:
211             break;
212         }
213     }
214 }
215 
216 /*!
217     \brief      enable DAC trigger
218     \param[in]  dac_periph: DACx(x = 0,1)
219     \param[out] none
220     \retval     none
221 */
dac_trigger_enable(uint32_t dac_periph)222 void dac_trigger_enable(uint32_t dac_periph)
223 {
224     if(DAC0 == dac_periph){
225         DAC_CTL |= DAC_CTL_DTEN0;
226     }else{
227         DAC_CTL |= DAC_CTL_DTEN1;
228     }
229 }
230 
231 /*!
232     \brief      disable DAC trigger
233     \param[in]  dac_periph: DACx(x = 0,1)
234     \param[out] none
235     \retval     none
236 */
dac_trigger_disable(uint32_t dac_periph)237 void dac_trigger_disable(uint32_t dac_periph)
238 {
239     if(DAC0 == dac_periph){
240         DAC_CTL &= ~DAC_CTL_DTEN0;
241     }else{
242         DAC_CTL &= ~DAC_CTL_DTEN1;
243     }
244 }
245 
246 /*!
247     \brief      set DAC trigger source
248     \param[in]  dac_periph: DACx(x = 0,1)
249     \param[in]  triggersource: external triggers of DAC
250                 only one parameter can be selected which is shown as below:
251       \arg        DAC_TRIGGER_T2_TRGO: TIMER2 TRGO
252       \arg        DAC_TRIGGER_T3_TRGO: TIMER3 TRGO
253       \arg        DAC_TRIGGER_T5_TRGO: TIMER5 TRGO
254       \arg        DAC_TRIGGER_T6_TRGO: TIMER6 TRGO
255       \arg        DAC_TRIGGER_EXTI_9: EXTI interrupt line9 event
256       \arg        DAC_TRIGGER_SOFTWARE: software trigger
257     \param[out] none
258     \retval     none
259 */
dac_trigger_source_config(uint32_t dac_periph,uint32_t triggersource)260 void dac_trigger_source_config(uint32_t dac_periph,uint32_t triggersource)
261 {
262     if(DAC0 == dac_periph){
263         /* configure DAC0 trigger source */
264         DAC_CTL &= ~DAC_CTL_DTSEL0;
265         DAC_CTL |= triggersource;
266     }else{
267         /* configure DAC1 trigger source */
268         DAC_CTL &= ~DAC_CTL_DTSEL1;
269         DAC_CTL |= (triggersource << DAC1_REG_OFFSET);
270     }
271 }
272 
273 /*!
274     \brief      enable DAC software trigger
275     \param[in]  dac_periph: DACx(x = 0,1)
276     \retval     none
277 */
dac_software_trigger_enable(uint32_t dac_periph)278 void dac_software_trigger_enable(uint32_t dac_periph)
279 {
280     if(DAC0 == dac_periph){
281         DAC_SWT |= DAC_SWT_SWTR0;
282     }else{
283         DAC_SWT |= DAC_SWT_SWTR1;
284     }
285 }
286 
287 /*!
288     \brief      disable DAC software trigger
289     \param[in]  dac_periph: DACx(x = 0,1)
290     \param[out] none
291     \retval     none
292 */
dac_software_trigger_disable(uint32_t dac_periph)293 void dac_software_trigger_disable(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      configure DAC wave mode
304     \param[in]  dac_periph: DACx(x = 0,1)
305     \param[in]  wave_mode: noise wave mode
306                 only one parameter can be selected which is shown as below:
307       \arg        DAC_WAVE_DISABLE: wave disable
308       \arg        DAC_WAVE_MODE_LFSR: LFSR noise mode
309       \arg        DAC_WAVE_MODE_TRIANGLE: triangle noise mode
310     \param[out] none
311     \retval     none
312 */
dac_wave_mode_config(uint32_t dac_periph,uint32_t wave_mode)313 void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode)
314 {
315     if(DAC0 == dac_periph){
316         /* configure DAC0 wave mode */
317         DAC_CTL &= ~DAC_CTL_DWM0;
318         DAC_CTL |= wave_mode;
319     }else{
320         /* configure DAC1 wave mode */
321         DAC_CTL &= ~DAC_CTL_DWM1;
322         DAC_CTL |= (wave_mode << DAC1_REG_OFFSET);
323     }
324 }
325 
326 /*!
327     \brief      configure DAC wave bit width
328     \param[in]  dac_periph: DACx(x = 0,1)
329     \param[in]  bit_width: noise wave bit width
330                 only one parameter can be selected which is shown as below:
331       \arg        DAC_WAVE_BIT_WIDTH_1: bit width of the wave signal is 1
332       \arg        DAC_WAVE_BIT_WIDTH_2: bit width of the wave signal is 2
333       \arg        DAC_WAVE_BIT_WIDTH_3: bit width of the wave signal is 3
334       \arg        DAC_WAVE_BIT_WIDTH_4: bit width of the wave signal is 4
335       \arg        DAC_WAVE_BIT_WIDTH_5: bit width of the wave signal is 5
336       \arg        DAC_WAVE_BIT_WIDTH_6: bit width of the wave signal is 6
337       \arg        DAC_WAVE_BIT_WIDTH_7: bit width of the wave signal is 7
338       \arg        DAC_WAVE_BIT_WIDTH_8: bit width of the wave signal is 8
339       \arg        DAC_WAVE_BIT_WIDTH_9: bit width of the wave signal is 9
340       \arg        DAC_WAVE_BIT_WIDTH_10: bit width of the wave signal is 10
341       \arg        DAC_WAVE_BIT_WIDTH_11: bit width of the wave signal is 11
342       \arg        DAC_WAVE_BIT_WIDTH_12: bit width of the wave signal is 12
343     \param[out] none
344     \retval     none
345 */
dac_wave_bit_width_config(uint32_t dac_periph,uint32_t bit_width)346 void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width)
347 {
348     if(DAC0 == dac_periph){
349         /* configure DAC0 wave bit width */
350         DAC_CTL &= ~DAC_CTL_DWBW0;
351         DAC_CTL |= bit_width;
352     }else{
353         /* configure DAC1 wave bit width */
354         DAC_CTL &= ~DAC_CTL_DWBW1;
355         DAC_CTL |= (bit_width << DAC1_REG_OFFSET);
356     }
357 }
358 
359 /*!
360     \brief      configure DAC LFSR noise mode
361     \param[in]  dac_periph: DACx(x = 0,1)
362     \param[in]  unmask_bits: unmask LFSR bits in DAC LFSR noise mode
363                 only one parameter can be selected which is shown as below:
364       \arg        DAC_LFSR_BIT0: unmask the LFSR bit0
365       \arg        DAC_LFSR_BITS1_0: unmask the LFSR bits[1:0]
366       \arg        DAC_LFSR_BITS2_0: unmask the LFSR bits[2:0]
367       \arg        DAC_LFSR_BITS3_0: unmask the LFSR bits[3:0]
368       \arg        DAC_LFSR_BITS4_0: unmask the LFSR bits[4:0]
369       \arg        DAC_LFSR_BITS5_0: unmask the LFSR bits[5:0]
370       \arg        DAC_LFSR_BITS6_0: unmask the LFSR bits[6:0]
371       \arg        DAC_LFSR_BITS7_0: unmask the LFSR bits[7:0]
372       \arg        DAC_LFSR_BITS8_0: unmask the LFSR bits[8:0]
373       \arg        DAC_LFSR_BITS9_0: unmask the LFSR bits[9:0]
374       \arg        DAC_LFSR_BITS10_0: unmask the LFSR bits[10:0]
375       \arg        DAC_LFSR_BITS11_0: unmask the LFSR bits[11:0]
376     \param[out] none
377     \retval     none
378 */
dac_lfsr_noise_config(uint32_t dac_periph,uint32_t unmask_bits)379 void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits)
380 {
381     if(DAC0 == dac_periph){
382         /* configure DAC0 LFSR noise mode */
383         DAC_CTL &= ~DAC_CTL_DWBW0;
384         DAC_CTL |= unmask_bits;
385     }else{
386         /* configure DAC1 LFSR noise mode */
387         DAC_CTL &= ~DAC_CTL_DWBW1;
388         DAC_CTL |= (unmask_bits << DAC1_REG_OFFSET);
389     }
390 }
391 
392 /*!
393     \brief      configure DAC triangle noise mode
394     \param[in]  dac_periph: DACx(x = 0,1)
395     \param[in]  amplitude: triangle amplitude in DAC triangle noise mode
396                 only one parameter can be selected which is shown as below:
397       \arg        DAC_TRIANGLE_AMPLITUDE_1: triangle amplitude is 1
398       \arg        DAC_TRIANGLE_AMPLITUDE_3: triangle amplitude is 3
399       \arg        DAC_TRIANGLE_AMPLITUDE_7: triangle amplitude is 7
400       \arg        DAC_TRIANGLE_AMPLITUDE_15: triangle amplitude is 15
401       \arg        DAC_TRIANGLE_AMPLITUDE_31: triangle amplitude is 31
402       \arg        DAC_TRIANGLE_AMPLITUDE_63: triangle amplitude is 63
403       \arg        DAC_TRIANGLE_AMPLITUDE_127: triangle amplitude is 127
404       \arg        DAC_TRIANGLE_AMPLITUDE_255: triangle amplitude is 255
405       \arg        DAC_TRIANGLE_AMPLITUDE_511: triangle amplitude is 511
406       \arg        DAC_TRIANGLE_AMPLITUDE_1023: triangle amplitude is 1023
407       \arg        DAC_TRIANGLE_AMPLITUDE_2047: triangle amplitude is 2047
408       \arg        DAC_TRIANGLE_AMPLITUDE_4095: triangle amplitude is 4095
409     \param[out] none
410     \retval     none
411 */
dac_triangle_noise_config(uint32_t dac_periph,uint32_t amplitude)412 void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude)
413 {
414     if(DAC0 == dac_periph){
415         /* configure DAC0 triangle noise mode */
416         DAC_CTL &= ~DAC_CTL_DWBW0;
417         DAC_CTL |= amplitude;
418     }else{
419         /* configure DAC1 triangle noise mode */
420         DAC_CTL &= ~DAC_CTL_DWBW1;
421         DAC_CTL |= (amplitude << DAC1_REG_OFFSET);
422     }
423 }
424 
425 /*!
426     \brief      enable DAC concurrent mode
427     \param[in]  none
428     \param[out] none
429     \retval     none
430 */
dac_concurrent_enable(void)431 void dac_concurrent_enable(void)
432 {
433     uint32_t ctl = 0U;
434     ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1;
435     DAC_CTL |= (ctl);
436 }
437 
438 /*!
439     \brief      disable DAC concurrent mode
440     \param[in]  none
441     \param[out] none
442     \retval     none
443 */
dac_concurrent_disable(void)444 void dac_concurrent_disable(void)
445 {
446     uint32_t ctl = 0U;
447     ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1;
448     DAC_CTL &= (~ctl);
449 }
450 
451 /*!
452     \brief      enable DAC concurrent software trigger function
453     \param[in]  none
454     \param[out] none
455     \retval     none
456 */
dac_concurrent_software_trigger_enable(void)457 void dac_concurrent_software_trigger_enable(void)
458 {
459     uint32_t swt = 0U;
460     swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1;
461     DAC_SWT |= (swt);
462 }
463 
464 /*!
465     \brief      disable DAC concurrent software trigger function
466     \param[in]  none
467     \param[out] none
468     \retval     none
469 */
dac_concurrent_software_trigger_disable(void)470 void dac_concurrent_software_trigger_disable(void)
471 {
472     uint32_t swt = 0U;
473     swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1;
474     DAC_SWT &= (~swt);
475 }
476 
477 /*!
478     \brief      enable DAC concurrent buffer function
479     \param[in]  none
480     \param[out] none
481     \retval     none
482 */
dac_concurrent_output_buffer_enable(void)483 void dac_concurrent_output_buffer_enable(void)
484 {
485     uint32_t ctl = 0U;
486     ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1;
487     DAC_CTL &= (~ctl);
488 }
489 
490 /*!
491     \brief      disable DAC concurrent buffer function
492     \param[in]  none
493     \param[out] none
494     \retval     none
495 */
dac_concurrent_output_buffer_disable(void)496 void dac_concurrent_output_buffer_disable(void)
497 {
498     uint32_t ctl = 0U;
499     ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1;
500     DAC_CTL |= (ctl);
501 }
502 
503 /*!
504     \brief      set DAC concurrent mode data holding register value
505     \param[in]  dac_align: data alignment
506                 only one parameter can be selected which is shown as below:
507       \arg        DAC_ALIGN_8B_R: data right 8b alignment
508       \arg        DAC_ALIGN_12B_R: data right 12b alignment
509       \arg        DAC_ALIGN_12B_L: data left 12b alignment
510     \param[in]  data0: data to be loaded
511     \param[in]  data1: data to be loaded
512     \param[out] none
513     \retval     none
514 */
dac_concurrent_data_set(uint32_t dac_align,uint16_t data0,uint16_t data1)515 void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1)
516 {
517     uint32_t data = 0U;
518     switch(dac_align){
519     /* data right 12b alignment */
520     case DAC_ALIGN_12B_R:
521         data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0;
522         DACC_R12DH = data;
523         break;
524     /* data left 12b alignment */
525     case DAC_ALIGN_12B_L:
526         data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0;
527         DACC_L12DH = data;
528         break;
529     /* data right 8b alignment */
530     case DAC_ALIGN_8B_R:
531         data = ((uint32_t)data1 << DH_8BIT_OFFSET) | data0;
532         DACC_R8DH = data;
533         break;
534     default:
535         break;
536     }
537 }
538