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