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