1 /*!
2  * @file        apm32f0xx_dac.c
3  *
4  * @brief       This file contains all the functions for the DAC peripheral
5  *
6  * @note        It's only for APM32F051,APM32F072,APM32F091 devices
7  *
8  * @version     V1.0.3
9  *
10  * @date        2022-09-20
11  *
12  * @attention
13  *
14  *  Copyright (C) 2020-2022 Geehy Semiconductor
15  *
16  *  You may not use this file except in compliance with the
17  *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
18  *
19  *  The program is only for reference, which is distributed in the hope
20  *  that it will be useful and instructional for customers to develop
21  *  their software. Unless required by applicable law or agreed to in
22  *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
23  *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
24  *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
25  *  and limitations under the License.
26  */
27 
28 /* Includes */
29 #include "apm32f0xx_dac.h"
30 #include "apm32f0xx_rcm.h"
31 
32 /** @addtogroup APM32F0xx_StdPeriphDriver
33   @{
34 */
35 
36 /** @addtogroup DAC_Driver
37   @{
38 */
39 
40 /** @defgroup DAC_Macros Macros
41   @{
42 */
43 
44 /**@} end of group DAC_Macros */
45 
46 /** @defgroup DAC_Enumerations Enumerations
47   @{
48 */
49 
50 /**@} end of group DAC_Enumerations */
51 
52 /** @defgroup DAC_Structures Structures
53   @{
54 */
55 
56 /**@} end of group DAC_Structures */
57 
58 /** @defgroup DAC_Variables Variables
59   @{
60 */
61 
62 /**@} end of group DAC_Variables */
63 
64 /** @defgroup DAC_Functions Functions
65   @{
66 */
67 
68 /*!
69  * @brief    Resets the DAC peripheral registers to their default reset values.
70  *
71  * @param    None
72  *
73  * @retval   None
74  */
DAC_Reset(void)75 void DAC_Reset(void)
76 {
77     RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_DAC);
78     RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_DAC);
79 }
80 
81 /*!
82  * @brief    Initializes the DAC peripheral according to the specified parameters in the dacConfig.
83  *
84  * @param    channel: the selected DAC channel.
85  *                    This parameter can be:
86  *                      @arg DAC_Channel_1: DAC Channel1 selected
87  *                      @arg DAC_Channel_2: DAC Channel2 selected
88  *
89  * @param    dacConfig: pointer to a DAC_Config_T structure that contains
90  *                      the configuration information for the  specified DAC channel.
91  *
92  * @retval   None
93  *
94  * @note     DAC_Channel_2 is only for APM32F072 and APM32F091 devices
95  */
DAC_Config(uint32_t channel,DAC_Config_T * dacConfig)96 void DAC_Config(uint32_t channel, DAC_Config_T* dacConfig)
97 {
98     uint32_t tmp1 = 0, tmp2 = 0;
99 
100     tmp1 = DAC->CTRL;
101 
102     tmp1 &= ~(((uint32_t)0x00000FFE) << channel);
103 
104     tmp2 = ((uint32_t)dacConfig->trigger | \
105               (uint32_t)dacConfig->waveGeneration | \
106               (uint32_t)dacConfig->maskAmplitudeSelect | \
107               (uint32_t)dacConfig->outputBuff);
108 
109     tmp1 |= tmp2 << channel;
110 
111     DAC->CTRL = tmp1;
112 }
113 
114 /*!
115  * @brief    Fills each DAC_InitStruct member with its default value.
116  *
117  * @param    dacConfig: pointer to a DAC_InitTypeDef structure which will
118  *           be configed.
119  *
120  * @retval   None
121  */
DAC_ConfigStructInit(DAC_Config_T * dacConfig)122 void DAC_ConfigStructInit(DAC_Config_T* dacConfig)
123 {
124     dacConfig->trigger = DAC_TRIGGER_NONE;
125     dacConfig->waveGeneration = DAC_WAVE_GENERATION_NONE;
126     dacConfig->maskAmplitudeSelect = DAC_LFSRUNAMASK_BIT0;
127     dacConfig->outputBuff = DAC_OUTPUTBUFF_ENABLE;
128 }
129 
130 /*!
131  * @brief    Enables the specified DAC channel.
132  *
133  * @param    channel: The selected DAC channel.
134  *                    This parameter can be one of the following values:
135  *                      @arg DAC_CHANNEL_1: DAC Channel1 selected
136  *                      @arg DAC_CHANNEL_2: DAC Channel2 selected
137  *
138  * @retval   None
139  *
140  * @note     When the DAC channel is enabled the trigger source can no more be modified.
141  *
142  * @note     DAC_Channel_2 is only for APM32F072 and APM32F091 devices
143  */
DAC_Enable(DAC_CHANNEL_T channel)144 void DAC_Enable(DAC_CHANNEL_T channel)
145 {
146     if (channel == DAC_CHANNEL_1)
147     {
148         DAC->CTRL_B.ENCH1 = SET;
149     }
150     else
151     {
152         DAC->CTRL_B.ENCH2 = SET;
153     }
154 }
155 
156 /*!
157  * @brief    Disables the specified DAC channel.
158  *
159  * @param    channel: The selected DAC channel.
160  *                    This parameter can be one of the following values:
161  *                      @arg DAC_CHANNEL_1: DAC Channel1 selected
162  *                      @arg DAC_CHANNEL_2: DAC Channel2 selected
163  *
164  * @retval   None
165  *
166  * @note     DAC_Channel_2 is only for APM32F072 and APM32F091 devices
167  */
DAC_Disable(DAC_CHANNEL_T channel)168 void DAC_Disable(DAC_CHANNEL_T channel)
169 {
170     if (channel == DAC_CHANNEL_1)
171     {
172         DAC->CTRL_B.ENCH1 = RESET;
173     }
174     else
175     {
176         DAC->CTRL_B.ENCH2 = RESET;
177     }
178 }
179 
180 /*!
181  * @brief    Enables the selected DAC channel software trigger.
182  *
183  * @param    channel: The selected DAC channel.
184  *                    This parameter can be one of the following values:
185  *                      @arg DAC_CHANNEL_1: DAC Channel1 selected
186  *                      @arg DAC_CHANNEL_2: DAC Channel2 selected
187  *
188  * @retval   None
189  *
190  * @note     DAC_Channel_2 is only for APM32F072 and APM32F091 devices
191  */
DAC_EnableSoftwareTrigger(DAC_CHANNEL_T channel)192 void DAC_EnableSoftwareTrigger(DAC_CHANNEL_T channel)
193 {
194     if (channel == DAC_CHANNEL_1)
195     {
196         DAC->SWTRG_B.SWTRG1 = SET;
197     }
198     else
199     {
200         DAC->SWTRG_B.SWTRG2 = SET;
201     }
202 }
203 
204 /*!
205  * @brief    Disable the selected DAC channel software trigger.
206  *
207  * @param    channel: The selected DAC channel.
208  *                    This parameter can be one of the following values:
209  *                      @arg DAC_CHANNEL_1: DAC Channel1 selected
210  *                      @arg DAC_CHANNEL_2: DAC Channel2 selected
211  *
212  * @retval   None
213  *
214  * @note     DAC_Channel_2 is only for APM32F072 and APM32F091 devices
215  */
DAC_DisableSoftwareTrigger(DAC_CHANNEL_T channel)216 void DAC_DisableSoftwareTrigger(DAC_CHANNEL_T channel)
217 {
218     if (channel == DAC_CHANNEL_1)
219     {
220         DAC->SWTRG_B.SWTRG1 = RESET;
221     }
222     else
223     {
224         DAC->SWTRG_B.SWTRG2 = RESET;
225     }
226 }
227 
228 /*!
229  * @brief    Enables simultaneously the two DAC channels software triggers.
230  *
231  * @param    None
232  *
233  * @retval   None
234  *
235  * @note     This function is only for APM32F072 and APM32F091 devices
236  */
DAC_EnableDualSoftwareTrigger(void)237 void DAC_EnableDualSoftwareTrigger(void)
238 {
239     DAC->SWTRG |= DUAL_SWTRIG_SET;
240 }
241 
242 /*!
243  * @brief    Disables simultaneously the two DAC channels software triggers.
244  *
245  * @param    None
246  *
247  * @retval   None
248  *
249  * @note     This function is only for APM32F072 and APM32F091 devices
250  */
DAC_DisableDualSoftwareTrigger(void)251 void DAC_DisableDualSoftwareTrigger(void)
252 {
253     DAC->SWTRG &= DUAL_SWTRIG_RESET;
254 }
255 
256 /*!
257  * @brief    Enables the selected DAC channel wave generation.
258  *
259  * @param    channel: The selected DAC channel.
260  *                    This parameter can be:
261  *                      @arg DAC_CHANNEL_1: DAC Channel1 selected
262  *                      @arg DAC_CHANNEL_2: DAC Channel2 selected
263  *
264  * @param    wave: specifies the wave type to enable or disable.
265  *                 This parameter can be:
266  *                   @arg DAC_WAVE_GENERATION_NOISE: noise wave generation
267  *                   @arg DAC_WAVE_GENERATION_TRIANGLE: triangle wave generation
268  *
269  * @retval   None
270  *
271  * @note     This function is only for APM32F072 and APM32F091 devices
272  */
DAC_EnableWaveGeneration(DAC_CHANNEL_T channel,DAC_WAVE_GENERATION_T wave)273 void DAC_EnableWaveGeneration(DAC_CHANNEL_T channel, DAC_WAVE_GENERATION_T wave)
274 {
275     DAC->CTRL |= ((uint32_t)wave) << ((uint32_t)channel);
276 }
277 
278 /*!
279  * @brief    Disable the selected DAC channel wave generation.
280  *
281  * @param    channel: The selected DAC channel.
282  *                    This parameter can be:
283  *                      @arg DAC_CHANNEL_1: DAC Channel1 selected
284  *                      @arg DAC_CHANNEL_2: DAC Channel2 selected
285  *
286  * @param    wave: specifies the wave type to enable or disable.
287  *                 This parameter can be:
288  *                   @arg DAC_WAVE_GENERATION_NOISE: noise wave generation
289  *                   @arg DAC_WAVE_GENERATION_TRIANGLE: triangle wave generation
290  *
291  * @retval   None
292  *
293  * @note     This function is only for APM32F072 and APM32F091 devices
294  */
DAC_DisableWaveGeneration(DAC_CHANNEL_T channel,DAC_WAVE_GENERATION_T wave)295 void DAC_DisableWaveGeneration(DAC_CHANNEL_T channel, DAC_WAVE_GENERATION_T wave)
296 {
297     DAC->CTRL &= ~((uint32_t)wave) << ((uint32_t)channel);
298 }
299 
300 /*!
301  * @brief    Sets the specified data holding register value for DAC channel1.
302  *
303  * @param    dataAlign: Specifies the data alignment for DAC channel1.
304  *                      This parameter can be one of the following values:
305  *                        @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
306  *                        @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
307  *                        @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
308  *
309  * @param    data: Data to be loaded in the selected data holding register.
310  *
311  * @retval   None
312  */
DAC_ConfigChannel1Data(DAC_DATA_ALIGN_T dataAlign,uint16_t data)313 void DAC_ConfigChannel1Data(DAC_DATA_ALIGN_T dataAlign, uint16_t data)
314 {
315     __IO uint32_t tmp = 0;
316     tmp = (uint32_t)DAC_BASE;
317     tmp += DH12RCH1_OFFSET + dataAlign;
318     *(__IO uint32_t*) tmp = data;
319 }
320 
321 /*!
322  * @brief    Sets the specified data holding register value for DAC channel2.
323  *
324  * @param    dataAlign: Specifies the data alignment for DAC channel2.
325  *                      This parameter can be:
326  *                        @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
327  *                        @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
328  *                        @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
329  *
330  * @param    data: Data to be loaded in the selected data holding register.
331  *
332  * @retval   None
333  *
334  * @note     This function is only for APM32F072 and APM32F091 devices
335  */
DAC_ConfigChannel2Data(DAC_DATA_ALIGN_T dataAlign,uint16_t data)336 void DAC_ConfigChannel2Data(DAC_DATA_ALIGN_T dataAlign, uint16_t data)
337 {
338     __IO uint32_t tmp = 0;
339     tmp = (uint32_t)DAC_BASE;
340     tmp += DH12RCH2_OFFSET + dataAlign;
341     *(__IO uint32_t*)tmp = data;
342 }
343 
344 /*!
345  * @brief    Sets the specified data holding register value for dual channel DAC.
346  *
347  * @param    dataAlign: Specifies the data alignment for dual channel DAC.
348  *                      This parameter can be:
349  *                        @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
350  *                        @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
351  *                        @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
352  * @param    data2: Data for DAC Channel2 to be loaded in the selected data holding register.
353  * @param    data1: Data for DAC Channel1 to be loaded in the selected data  holding register.
354  *
355  * @retval   None
356  *
357  * @note     In dual mode, a unique register access is required to write in both
358  *           DAC channels at the same time.
359  *
360  * @note     This function is only for APM32F072 and APM32F091 devices
361  */
DAC_ConfigDualChannelData(DAC_DATA_ALIGN_T dataAlign,uint16_t data2,uint16_t data1)362 void DAC_ConfigDualChannelData(DAC_DATA_ALIGN_T dataAlign, uint16_t data2, uint16_t data1)
363 {
364     uint32_t data = 0, tmp = 0;
365 
366     if (dataAlign == DAC_ALIGN_8B_R)
367     {
368         data = ((uint32_t)data2 << 8) | data1;
369     }
370     else
371     {
372         data = ((uint32_t)data2 << 16) | data1;
373     }
374     tmp = (uint32_t)DAC_BASE;
375     tmp += DH12RD_OFFSET + dataAlign;
376     *(__IO uint32_t*)tmp = data;
377 }
378 
379 /*!
380  * @brief    Returns the last data output value of the selected DAC channel.
381  *
382  * @param    channel: The selected DAC channel.
383  *                    This parameter can be one of the following values:
384  *                      @arg DAC_CHANNEL_1: DAC Channel1 selected
385  *                      @arg DAC_CHANNEL_2: DAC Channel2 selected
386  *
387  * @retval   The selected DAC channel data output value.
388  *
389  * @note     DAC_Channel_2 is only for APM32F072 and APM32F091 devices
390  */
DAC_ReadDataOutputValue(DAC_CHANNEL_T channel)391 uint16_t DAC_ReadDataOutputValue(DAC_CHANNEL_T channel)
392 {
393     uint16_t data;
394     if (channel == DAC_CHANNEL_1)
395     {
396         data = DAC->DATAOCH1_B.DATA;
397     }
398     else
399     {
400         data = DAC->DATAOCH2_B.DATA;
401     }
402     return data;
403 }
404 
405 /*!
406  * @brief    Enables the specified DAC channel DMA request.
407  *           When enabled DMA1 is generated when an external trigger (EINT Line9,
408  *           TMR2, TMR3, TMR6 or TMR15  but not a software trigger) occurs
409 
410  * @param    channel: the selected DAC channel.
411  *                    This parameter can be one of the following values:
412  *                      @arg DAC_CHANNEL_1: DAC Channel1 selected
413  *                      @arg DAC_CHANNEL_2: DAC Channel2 selected
414  *
415  * @retval   None
416  *
417  * @note     The DAC channel1 is mapped on DMA1 channel3 which must be already configured.
418  *
419  * @note     The DAC channel2 is mapped on DMA1 channel4 which must be already configured.
420  *
421  * @note     DAC_Channel_2 is only for APM32F072 and APM32F091 devices
422  */
DAC_EnableDMA(DAC_CHANNEL_T channel)423 void DAC_EnableDMA(DAC_CHANNEL_T channel)
424 {
425     if (channel == DAC_CHANNEL_1)
426     {
427         DAC->CTRL_B.DMAENCH1 = SET;
428     }
429     else
430     {
431         DAC->CTRL_B.DMAENCH2 = SET;
432     }
433 }
434 
435 /*!
436  * @brief    Disable the specified DAC channel DMA request.
437  *
438  * @param    channel: the selected DAC channel.
439  *                    This parameter can be one of the following values:
440  *                      @arg DAC_CHANNEL_1: DAC Channel1 selected
441  *                      @arg DAC_CHANNEL_2: DAC Channel2 selected
442  *
443  * @retval   None
444  *
445  * @note     The DAC channel1 is mapped on DMA1 channel3 which must be already configured.
446  *
447  * @note     The DAC channel2 is mapped on DMA1 channel4 which must be already configured.
448  *
449  * @note     DAC_Channel_2 is only for APM32F072 and APM32F091 devices
450  */
DAC_DisableDMA(DAC_CHANNEL_T channel)451 void DAC_DisableDMA(DAC_CHANNEL_T channel)
452 {
453     if (channel == DAC_CHANNEL_1)
454     {
455         DAC->CTRL_B.DMAENCH1 = RESET;
456     }
457     else
458     {
459         DAC->CTRL_B.DMAENCH2 = RESET;
460     }
461 }
462 
463 /*!
464  * @brief    Enables the specified DAC interrupts.
465  *
466  * @param    channel: The selected DAC channel.
467  *                    This parameter can be:
468  *                      @arg DAC_CHANNEL_1: DAC Channel1 selected
469  *                      @arg DAC_CHANNEL_2: DAC Channel2 selected
470  *
471  * @retval   None
472  *
473  * @note     The DMA underrun occurs when a second external trigger arrives before the
474  *           acknowledgement for the first external trigger is received (first request).
475  *
476  * @note     DAC_Channel_2 is only for APM32F072 and APM32F091 devices
477  */
DAC_EnableInterrupt(DAC_CHANNEL_T channel)478 void DAC_EnableInterrupt(DAC_CHANNEL_T channel)
479 {
480     if (channel == DAC_CHANNEL_1)
481     {
482         DAC->CTRL_B.DMAUDRIEN1 = SET;
483     }
484     else
485     {
486         DAC->CTRL_B.DMAUDRIEN2 = SET;
487     }
488 }
489 
490 /*!
491  * @brief    Disables the specified DAC interrupts.
492  *
493  * @param    channel: The selected DAC channel.
494  *                    This parameter can be:
495  *                      @arg DAC_CHANNEL_1: DAC Channel1 selected
496  *                      @arg DAC_CHANNEL_2: DAC Channel2 selected
497  *
498  * @retval   None
499  *
500  * @note     The DMA underrun occurs when a second external trigger arrives before the
501  *           acknowledgement for the first external trigger is received (first request).
502  *
503  * @note     DAC_Channel_2 is only for APM32F072 and APM32F091 devices
504  */
DAC_DisableInterrupt(DAC_CHANNEL_T channel)505 void DAC_DisableInterrupt(DAC_CHANNEL_T channel)
506 {
507     if (channel == DAC_CHANNEL_1)
508     {
509         DAC->CTRL_B.DMAUDRIEN1 = RESET;
510     }
511     else
512     {
513         DAC->CTRL_B.DMAUDRIEN2 = RESET;
514     }
515 }
516 
517 /*!
518  * @brief    Reads the DAC status flag.
519  *
520  * @param    flag: specifies the flag to check.
521  *                 This parameter can be only of the following value:
522  *                    @arg DAC_FLAG_CH1_DMAUDR: DMA Channel1 underrun flag
523  *                    @arg DAC_FLAG_CH2_DMAUDR: DMA Channel2 underrun flag, only for APM32F072 and APM32F091 devices
524  *
525  * @retval   The new state of DAC flag (SET or RESET).
526  *
527  * @note     The DMA underrun occurs when a second external trigger arrives before the
528  *           acknowledgement for the first external trigger is received (first request).
529  */
DAC_ReadStatusFlag(DAC_FLAG_T flag)530 uint8_t DAC_ReadStatusFlag(DAC_FLAG_T flag)
531 {
532     uint16_t status;
533 
534     status = (uint16_t)(DAC->STS & flag);
535     if (status == flag)
536     {
537         return SET;
538     }
539     else
540         return RESET;
541 }
542 /*!
543  * @brief    Clears the DAC status flags.
544  *
545  * @param    flag: specifies the flag to check.
546  *                 This parameter can be only of the following value:
547  *                    @arg DAC_FLAG_CH1_DMAUDR: DMA Channel1 underrun flag
548  *                    @arg DAC_FLAG_CH2_DMAUDR: DMA Channel2 underrun flag, , only for APM32F072 and APM32F091 devices
549  *                    @arg DAC_FLAG_DMAUDR: DMA underrun flag
550  *
551  * @retval   None
552  */
DAC_ClearStatusFlag(DAC_FLAG_T flag)553 void DAC_ClearStatusFlag(DAC_FLAG_T flag)
554 {
555     DAC->STS &= (uint32_t)~flag;
556 }
557 
558 /*!
559  * @brief    Reads teh DAC interrupt flag.
560  *
561  * @param    intFlag: specifies the DAC interrupt source to check.
562  *                    This parameter can be the following values:
563  *                      @arg DAC_INT_CH1_DMAUDR: DMA Channel1 underrun interrupt mask
564  *                      @arg DAC_INT_CH2_DMAUDR: DMA Channel2 underrun interrupt mask, , only for APM32F072 and APM32F091 devices
565  *
566  * @retval   The new state of DAC interrupt flag (SET or RESET).
567  *
568  * @note     The DMA underrun occurs when a second external trigger arrives before the
569  *           acknowledgement for the first external trigger is received (first request).
570  */
DAC_ReadIntFlag(DAC_INT_T intFlag)571 uint8_t DAC_ReadIntFlag(DAC_INT_T intFlag)
572 {
573     uint32_t intEnable;
574     intEnable = (DAC->CTRL & intFlag);
575     if (((DAC->STS & intFlag) != (uint32_t)RESET) && intEnable)
576     {
577         return SET;
578     }
579     else
580     {
581         return RESET;
582     }
583 }
584 
585 /*!
586  * @brief  Clears the DAC channel's interrupt flag.
587  *
588  * @param  intFlag: specifies the DAC interrupt pending bit to clear.
589  *                  This parameter can be the following values:
590  *                    @arg DAC_INT_CH1_DMAUDR: DMA Channel1 underrun interrupt mask
591  *                    @arg DAC_INT_CH2_DMAUDR: DMA Channel2 underrun interrupt mask, , only for APM32F072 and APM32F091 devices
592  *
593  * @retval None
594  */
DAC_ClearIntFlag(DAC_INT_T intFlag)595 void DAC_ClearIntFlag(DAC_INT_T intFlag)
596 {
597     DAC->STS = intFlag;
598 }
599 
600 /**@} end of group DAC_Functions */
601 /**@} end of group DAC_Driver */
602 /**@} end of group APM32F0xx_StdPeriphDriver */
603