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