1 /**
2   ******************************************************************************
3   * @file    stm32h5xx_hal_dac_ex.c
4   * @author  MCD Application Team
5   * @brief   Extended DAC HAL module driver.
6   *          This file provides firmware functions to manage the extended
7   *          functionalities of the DAC peripheral.
8   *
9   *
10   ******************************************************************************
11   * @attention
12   *
13   * Copyright (c) 2023 STMicroelectronics.
14   * All rights reserved.
15   *
16   * This software is licensed under terms that can be found in the LICENSE file
17   * in the root directory of this software component.
18   * If no LICENSE file comes with this software, it is provided AS-IS.
19   *
20   ******************************************************************************
21   @verbatim
22   ==============================================================================
23                       ##### How to use this driver #####
24   ==============================================================================
25     [..]
26      *** Dual mode IO operation ***
27      ==============================
28      [..]
29       (+) Use HAL_DACEx_DualStart() to enable both channel and start conversion
30           for dual mode operation.
31           If software trigger is selected, using HAL_DACEx_DualStart() will start
32           the conversion of the value previously set by HAL_DACEx_DualSetValue().
33       (+) Use HAL_DACEx_DualStop() to disable both channel and stop conversion
34           for dual mode operation.
35       (+) Use HAL_DACEx_DualStart_DMA() to enable both channel and start conversion
36           for dual mode operation using DMA to feed DAC converters.
37           First issued trigger will start the conversion of the value previously
38           set by HAL_DACEx_DualSetValue().
39           The same callbacks that are used in single mode are called in dual mode to notify
40           transfer completion (half complete or complete), errors or underrun.
41       (+) Use HAL_DACEx_DualStop_DMA() to disable both channel and stop conversion
42           for dual mode operation using DMA to feed DAC converters.
43       (+) When Dual mode is enabled (i.e. DAC Channel1 and Channel2 are used simultaneously) :
44           Use HAL_DACEx_DualGetValue() to get digital data to be converted and use
45           HAL_DACEx_DualSetValue() to set digital value to converted simultaneously in
46           Channel 1 and Channel 2.
47      *** Signal generation operation ***
48      ===================================
49      [..]
50       (+) Use HAL_DACEx_TriangleWaveGenerate() to generate Triangle signal.
51       (+) Use HAL_DACEx_NoiseWaveGenerate() to generate Noise signal.
52 
53       (+) HAL_DACEx_SelfCalibrate to calibrate one DAC channel.
54       (+) HAL_DACEx_SetUserTrimming to set user trimming value.
55       (+) HAL_DACEx_GetTrimOffset to retrieve trimming value (factory setting
56           after reset, user setting if HAL_DACEx_SetUserTrimming have been used
57           at least one time after reset).
58 
59  @endverbatim
60   ******************************************************************************
61   */
62 
63 
64 /* Includes ------------------------------------------------------------------*/
65 #include "stm32h5xx_hal.h"
66 
67 /** @addtogroup STM32H5xx_HAL_Driver
68   * @{
69   */
70 
71 #ifdef HAL_DAC_MODULE_ENABLED
72 
73 #if defined(DAC1)
74 
75 /** @defgroup DACEx DACEx
76   * @brief DAC Extended HAL module driver
77   * @{
78   */
79 
80 /* Private typedef -----------------------------------------------------------*/
81 /* Private define ------------------------------------------------------------*/
82 
83 /* Delay for DAC minimum trimming time.                                       */
84 /* Note: minimum time needed between two calibration steps                    */
85 /*       The delay below is specified under conditions:                       */
86 /*        - DAC channel output buffer enabled                                 */
87 /* Literal set to maximum value (refer to device datasheet,                   */
88 /* electrical characteristics, parameter "tTRIM").                            */
89 /* Unit: us                                                                   */
90 #define DAC_DELAY_TRIM_US          (50UL)     /*!< Delay for DAC minimum trimming time */
91 
92 /* Private macro -------------------------------------------------------------*/
93 /* Private variables ---------------------------------------------------------*/
94 /* Private function prototypes -----------------------------------------------*/
95 /* Exported functions --------------------------------------------------------*/
96 
97 /** @defgroup DACEx_Exported_Functions DACEx Exported Functions
98   * @{
99   */
100 
101 /** @defgroup DACEx_Exported_Functions_Group2 IO operation functions
102   *  @brief    Extended IO operation functions
103   *
104 @verbatim
105   ==============================================================================
106                  ##### Extended features functions #####
107   ==============================================================================
108     [..]  This section provides functions allowing to:
109       (+) Start conversion.
110       (+) Stop conversion.
111       (+) Start conversion and enable DMA transfer.
112       (+) Stop conversion and disable DMA transfer.
113       (+) Get result of conversion.
114       (+) Get result of dual mode conversion.
115 
116 @endverbatim
117   * @{
118   */
119 
120 
121 /**
122   * @brief  Enables DAC and starts conversion of both channels.
123   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
124   *         the configuration information for the specified DAC.
125   * @retval HAL status
126   */
HAL_DACEx_DualStart(DAC_HandleTypeDef * hdac)127 HAL_StatusTypeDef HAL_DACEx_DualStart(DAC_HandleTypeDef *hdac)
128 {
129   uint32_t tmp_swtrig = 0UL;
130   __IO uint32_t wait_loop_index;
131 
132   /* Check the DAC peripheral handle */
133   if (hdac == NULL)
134   {
135     return HAL_ERROR;
136   }
137 
138 
139   /* Process locked */
140   __HAL_LOCK(hdac);
141 
142   /* Change DAC state */
143   hdac->State = HAL_DAC_STATE_BUSY;
144 
145   /* Enable the Peripheral */
146   __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_1);
147   __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_2);
148   /* Ensure minimum wait before using peripheral after enabling it */
149   /* Wait loop initialization and execution */
150   /* Note: Variable divided by 2 to compensate partially              */
151   /*       CPU processing cycles, scaling in us split to not          */
152   /*       exceed 32 bits register capacity and handle low frequency. */
153   wait_loop_index = ((DAC_DELAY_STARTUP_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
154   while (wait_loop_index != 0UL)
155   {
156     wait_loop_index--;
157   }
158 
159   /* Check if software trigger enabled */
160   if ((hdac->Instance->CR & (DAC_CR_TEN1 | DAC_CR_TSEL1)) == DAC_TRIGGER_SOFTWARE)
161   {
162     tmp_swtrig |= DAC_SWTRIGR_SWTRIG1;
163   }
164   if ((hdac->Instance->CR & (DAC_CR_TEN2 | DAC_CR_TSEL2)) == (DAC_TRIGGER_SOFTWARE << (DAC_CHANNEL_2 & 0x10UL)))
165   {
166     tmp_swtrig |= DAC_SWTRIGR_SWTRIG2;
167   }
168   /* Enable the selected DAC software conversion*/
169   SET_BIT(hdac->Instance->SWTRIGR, tmp_swtrig);
170 
171   /* Change DAC state */
172   hdac->State = HAL_DAC_STATE_READY;
173 
174   /* Process unlocked */
175   __HAL_UNLOCK(hdac);
176 
177   /* Return function status */
178   return HAL_OK;
179 }
180 
181 /**
182   * @brief  Disables DAC and stop conversion of both channels.
183   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
184   *         the configuration information for the specified DAC.
185   * @retval HAL status
186   */
HAL_DACEx_DualStop(DAC_HandleTypeDef * hdac)187 HAL_StatusTypeDef HAL_DACEx_DualStop(DAC_HandleTypeDef *hdac)
188 {
189   /* Check the DAC peripheral handle */
190   if (hdac == NULL)
191   {
192     return HAL_ERROR;
193   }
194 
195 
196   /* Disable the Peripheral */
197   __HAL_DAC_DISABLE(hdac, DAC_CHANNEL_1);
198   __HAL_DAC_DISABLE(hdac, DAC_CHANNEL_2);
199 
200   /* Change DAC state */
201   hdac->State = HAL_DAC_STATE_READY;
202 
203   /* Return function status */
204   return HAL_OK;
205 }
206 
207 /**
208   * @brief  Enables DAC and starts conversion of both channel 1 and 2 of the same DAC.
209   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
210   *         the configuration information for the specified DAC.
211   * @param  Channel The DAC channel that will request data from DMA.
212   *          This parameter can be one of the following values:
213   *            @arg DAC_CHANNEL_1: DAC Channel1 selected
214   *            @arg DAC_CHANNEL_2: DAC Channel2 selected
215   * @param  pData The destination peripheral Buffer address.
216   * @param  Length The length of data to be transferred from memory to DAC peripheral
217   * @param  Alignment Specifies the data alignment for DAC channel.
218   *          This parameter can be one of the following values:
219   *            @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
220   *            @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
221   *            @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
222   * @retval HAL status
223   */
HAL_DACEx_DualStart_DMA(DAC_HandleTypeDef * hdac,uint32_t Channel,const uint32_t * pData,uint32_t Length,uint32_t Alignment)224 HAL_StatusTypeDef HAL_DACEx_DualStart_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel,
225                                           const uint32_t *pData, uint32_t Length, uint32_t Alignment)
226 {
227   HAL_StatusTypeDef status;
228   uint32_t tmpreg = 0UL;
229   __IO uint32_t wait_loop_index;
230   uint32_t LengthInBytes;
231 
232   /* Check the DAC peripheral handle */
233   if (hdac == NULL)
234   {
235     return HAL_ERROR;
236   }
237 
238   /* Check the parameters */
239   assert_param(IS_DAC_CHANNEL(Channel));
240   assert_param(IS_DAC_ALIGN(Alignment));
241 
242   /* Process locked */
243   __HAL_LOCK(hdac);
244 
245   /* Change DAC state */
246   hdac->State = HAL_DAC_STATE_BUSY;
247 
248   if (Channel == DAC_CHANNEL_1)
249   {
250     /* Set the DMA transfer complete callback for channel1 */
251     hdac->DMA_Handle1->XferCpltCallback = DAC_DMAConvCpltCh1;
252 
253     /* Set the DMA half transfer complete callback for channel1 */
254     hdac->DMA_Handle1->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh1;
255 
256     /* Set the DMA error callback for channel1 */
257     hdac->DMA_Handle1->XferErrorCallback = DAC_DMAErrorCh1;
258 
259     /* Enable the selected DAC channel1 DMA request */
260     SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN1);
261   }
262   else
263   {
264     /* Set the DMA transfer complete callback for channel2 */
265     hdac->DMA_Handle2->XferCpltCallback = DAC_DMAConvCpltCh2;
266 
267     /* Set the DMA half transfer complete callback for channel2 */
268     hdac->DMA_Handle2->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh2;
269 
270     /* Set the DMA error callback for channel2 */
271     hdac->DMA_Handle2->XferErrorCallback = DAC_DMAErrorCh2;
272 
273     /* Enable the selected DAC channel2 DMA request */
274     SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN2);
275   }
276 
277   switch (Alignment)
278   {
279     case DAC_ALIGN_12B_R:
280       /* Get DHR12R1 address */
281       tmpreg = (uint32_t)&hdac->Instance->DHR12RD;
282       break;
283     case DAC_ALIGN_12B_L:
284       /* Get DHR12L1 address */
285       tmpreg = (uint32_t)&hdac->Instance->DHR12LD;
286       break;
287     case DAC_ALIGN_8B_R:
288       /* Get DHR8R1 address */
289       tmpreg = (uint32_t)&hdac->Instance->DHR8RD;
290       break;
291     default:
292       break;
293   }
294 
295   /* Enable the DMA channel */
296   if (Channel == DAC_CHANNEL_1)
297   {
298     /* Enable the DAC DMA underrun interrupt */
299     __HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR1);
300 
301     /* Length should be converted to number of bytes */
302     LengthInBytes = Length * 4U;
303 
304     /* Check linkedlist mode */
305     if ((hdac->DMA_Handle1->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
306     {
307       if ((hdac->DMA_Handle1->LinkedListQueue != NULL) && (hdac->DMA_Handle1->LinkedListQueue->Head != NULL))
308       {
309         /* Set DMA data size */
310         hdac->DMA_Handle1->LinkedListQueue->Head->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = LengthInBytes;
311 
312         /* Set DMA source address */
313         hdac->DMA_Handle1->LinkedListQueue->Head->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = (uint32_t)pData;
314 
315         /* Set DMA destination address */
316         hdac->DMA_Handle1->LinkedListQueue->Head->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = tmpreg;
317 
318         /* Enable the DMA channel */
319         status = HAL_DMAEx_List_Start_IT(hdac->DMA_Handle1);
320       }
321       else
322       {
323         /* Return error status */
324         return HAL_ERROR;
325       }
326     }
327     else
328     {
329       /* Enable the DMA channel */
330       status = HAL_DMA_Start_IT(hdac->DMA_Handle1, (uint32_t)pData, tmpreg, LengthInBytes);
331     }
332   }
333   else
334   {
335     /* Enable the DAC DMA underrun interrupt */
336     __HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR2);
337 
338     /* Length should be converted to number of bytes */
339     LengthInBytes = Length * 4U;
340 
341     /* Check linkedlist mode */
342     if ((hdac->DMA_Handle2->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
343     {
344       if ((hdac->DMA_Handle2->LinkedListQueue != NULL) && (hdac->DMA_Handle2->LinkedListQueue->Head != NULL))
345       {
346         /* Set DMA data size */
347         hdac->DMA_Handle2->LinkedListQueue->Head->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = LengthInBytes;
348 
349         /* Set DMA source address */
350         hdac->DMA_Handle2->LinkedListQueue->Head->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = (uint32_t)pData;
351 
352         /* Set DMA destination address */
353         hdac->DMA_Handle2->LinkedListQueue->Head->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = tmpreg;
354 
355         /* Enable the DMA channel */
356         status = HAL_DMAEx_List_Start_IT(hdac->DMA_Handle2);
357       }
358       else
359       {
360         /* Return error status */
361         return HAL_ERROR;
362       }
363     }
364     else
365     {
366       /* Enable the DMA channel */
367       status = HAL_DMA_Start_IT(hdac->DMA_Handle2, (uint32_t)pData, tmpreg, LengthInBytes);
368     }
369   }
370 
371   /* Process Unlocked */
372   __HAL_UNLOCK(hdac);
373 
374   if (status == HAL_OK)
375   {
376     /* Enable the Peripheral */
377     __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_1);
378     __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_2);
379     /* Ensure minimum wait before using peripheral after enabling it */
380     /* Wait loop initialization and execution */
381     /* Note: Variable divided by 2 to compensate partially              */
382     /*       CPU processing cycles, scaling in us split to not          */
383     /*       exceed 32 bits register capacity and handle low frequency. */
384     wait_loop_index = ((DAC_DELAY_STARTUP_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
385     while (wait_loop_index != 0UL)
386     {
387       wait_loop_index--;
388     }
389   }
390   else
391   {
392     hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
393   }
394 
395   /* Return function status */
396   return status;
397 }
398 
399 /**
400   * @brief  Disables DAC and stop conversion both channel.
401   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
402   *         the configuration information for the specified DAC.
403   * @param  Channel The DAC channel that requests data from DMA.
404   *          This parameter can be one of the following values:
405   *            @arg DAC_CHANNEL_1: DAC Channel1 selected
406   *            @arg DAC_CHANNEL_2: DAC Channel2 selected
407   * @retval HAL status
408   */
HAL_DACEx_DualStop_DMA(DAC_HandleTypeDef * hdac,uint32_t Channel)409 HAL_StatusTypeDef HAL_DACEx_DualStop_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel)
410 {
411   HAL_StatusTypeDef status;
412 
413   /* Check the DAC peripheral handle */
414   if (hdac == NULL)
415   {
416     return HAL_ERROR;
417   }
418 
419 
420   /* Disable the selected DAC channel DMA request */
421   CLEAR_BIT(hdac->Instance->CR, DAC_CR_DMAEN2 | DAC_CR_DMAEN1);
422 
423   /* Disable the Peripheral */
424   __HAL_DAC_DISABLE(hdac, DAC_CHANNEL_1);
425   __HAL_DAC_DISABLE(hdac, DAC_CHANNEL_2);
426 
427   /* Disable the DMA channel */
428 
429   /* Channel1 is used */
430   if (Channel == DAC_CHANNEL_1)
431   {
432     /* Disable the DMA channel */
433     status = HAL_DMA_Abort(hdac->DMA_Handle1);
434 
435     /* Disable the DAC DMA underrun interrupt */
436     __HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR1);
437   }
438   else
439   {
440     /* Disable the DMA channel */
441     status = HAL_DMA_Abort(hdac->DMA_Handle2);
442 
443     /* Disable the DAC DMA underrun interrupt */
444     __HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR2);
445   }
446 
447   /* Check if DMA Channel effectively disabled */
448   if (status != HAL_OK)
449   {
450     /* Update DAC state machine to error */
451     hdac->State = HAL_DAC_STATE_ERROR;
452   }
453   else
454   {
455     /* Change DAC state */
456     hdac->State = HAL_DAC_STATE_READY;
457   }
458 
459   /* Return function status */
460   return status;
461 }
462 
463 
464 /**
465   * @brief  Enable or disable the selected DAC channel wave generation.
466   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
467   *         the configuration information for the specified DAC.
468   * @param  Channel The selected DAC channel.
469   *          This parameter can be one of the following values:
470   *            @arg DAC_CHANNEL_1: DAC Channel1 selected
471   *            @arg DAC_CHANNEL_2: DAC Channel2 selected
472   * @param  Amplitude Select max triangle amplitude.
473   *          This parameter can be one of the following values:
474   *            @arg DAC_TRIANGLEAMPLITUDE_1: Select max triangle amplitude of 1
475   *            @arg DAC_TRIANGLEAMPLITUDE_3: Select max triangle amplitude of 3
476   *            @arg DAC_TRIANGLEAMPLITUDE_7: Select max triangle amplitude of 7
477   *            @arg DAC_TRIANGLEAMPLITUDE_15: Select max triangle amplitude of 15
478   *            @arg DAC_TRIANGLEAMPLITUDE_31: Select max triangle amplitude of 31
479   *            @arg DAC_TRIANGLEAMPLITUDE_63: Select max triangle amplitude of 63
480   *            @arg DAC_TRIANGLEAMPLITUDE_127: Select max triangle amplitude of 127
481   *            @arg DAC_TRIANGLEAMPLITUDE_255: Select max triangle amplitude of 255
482   *            @arg DAC_TRIANGLEAMPLITUDE_511: Select max triangle amplitude of 511
483   *            @arg DAC_TRIANGLEAMPLITUDE_1023: Select max triangle amplitude of 1023
484   *            @arg DAC_TRIANGLEAMPLITUDE_2047: Select max triangle amplitude of 2047
485   *            @arg DAC_TRIANGLEAMPLITUDE_4095: Select max triangle amplitude of 4095
486   * @retval HAL status
487   */
HAL_DACEx_TriangleWaveGenerate(DAC_HandleTypeDef * hdac,uint32_t Channel,uint32_t Amplitude)488 HAL_StatusTypeDef HAL_DACEx_TriangleWaveGenerate(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Amplitude)
489 {
490   /* Check the DAC peripheral handle */
491   if (hdac == NULL)
492   {
493     return HAL_ERROR;
494   }
495 
496   /* Check the parameters */
497   assert_param(IS_DAC_CHANNEL(Channel));
498   assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(Amplitude));
499 
500   /* Process locked */
501   __HAL_LOCK(hdac);
502 
503   /* Change DAC state */
504   hdac->State = HAL_DAC_STATE_BUSY;
505 
506   /* Enable the triangle wave generation for the selected DAC channel */
507   MODIFY_REG(hdac->Instance->CR, ((DAC_CR_WAVE1) | (DAC_CR_MAMP1)) << (Channel & 0x10UL),
508              (DAC_CR_WAVE1_1 | Amplitude) << (Channel & 0x10UL));
509 
510   /* Change DAC state */
511   hdac->State = HAL_DAC_STATE_READY;
512 
513   /* Process unlocked */
514   __HAL_UNLOCK(hdac);
515 
516   /* Return function status */
517   return HAL_OK;
518 }
519 
520 /**
521   * @brief  Enable or disable the selected DAC channel wave generation.
522   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
523   *         the configuration information for the specified DAC.
524   * @param  Channel The selected DAC channel.
525   *          This parameter can be one of the following values:
526   *            @arg DAC_CHANNEL_1: DAC Channel1 selected
527   *            @arg DAC_CHANNEL_2: DAC Channel2 selected
528   * @param  Amplitude Unmask DAC channel LFSR for noise wave generation.
529   *          This parameter can be one of the following values:
530   *            @arg DAC_LFSRUNMASK_BIT0: Unmask DAC channel LFSR bit0 for noise wave generation
531   *            @arg DAC_LFSRUNMASK_BITS1_0: Unmask DAC channel LFSR bit[1:0] for noise wave generation
532   *            @arg DAC_LFSRUNMASK_BITS2_0: Unmask DAC channel LFSR bit[2:0] for noise wave generation
533   *            @arg DAC_LFSRUNMASK_BITS3_0: Unmask DAC channel LFSR bit[3:0] for noise wave generation
534   *            @arg DAC_LFSRUNMASK_BITS4_0: Unmask DAC channel LFSR bit[4:0] for noise wave generation
535   *            @arg DAC_LFSRUNMASK_BITS5_0: Unmask DAC channel LFSR bit[5:0] for noise wave generation
536   *            @arg DAC_LFSRUNMASK_BITS6_0: Unmask DAC channel LFSR bit[6:0] for noise wave generation
537   *            @arg DAC_LFSRUNMASK_BITS7_0: Unmask DAC channel LFSR bit[7:0] for noise wave generation
538   *            @arg DAC_LFSRUNMASK_BITS8_0: Unmask DAC channel LFSR bit[8:0] for noise wave generation
539   *            @arg DAC_LFSRUNMASK_BITS9_0: Unmask DAC channel LFSR bit[9:0] for noise wave generation
540   *            @arg DAC_LFSRUNMASK_BITS10_0: Unmask DAC channel LFSR bit[10:0] for noise wave generation
541   *            @arg DAC_LFSRUNMASK_BITS11_0: Unmask DAC channel LFSR bit[11:0] for noise wave generation
542   * @retval HAL status
543   */
HAL_DACEx_NoiseWaveGenerate(DAC_HandleTypeDef * hdac,uint32_t Channel,uint32_t Amplitude)544 HAL_StatusTypeDef HAL_DACEx_NoiseWaveGenerate(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Amplitude)
545 {
546   /* Check the DAC peripheral handle */
547   if (hdac == NULL)
548   {
549     return HAL_ERROR;
550   }
551 
552   /* Check the parameters */
553   assert_param(IS_DAC_CHANNEL(Channel));
554   assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(Amplitude));
555 
556   /* Process locked */
557   __HAL_LOCK(hdac);
558 
559   /* Change DAC state */
560   hdac->State = HAL_DAC_STATE_BUSY;
561 
562   /* Enable the noise wave generation for the selected DAC channel */
563   MODIFY_REG(hdac->Instance->CR, ((DAC_CR_WAVE1) | (DAC_CR_MAMP1)) << (Channel & 0x10UL),
564              (DAC_CR_WAVE1_0 | Amplitude) << (Channel & 0x10UL));
565 
566   /* Change DAC state */
567   hdac->State = HAL_DAC_STATE_READY;
568 
569   /* Process unlocked */
570   __HAL_UNLOCK(hdac);
571 
572   /* Return function status */
573   return HAL_OK;
574 }
575 
576 
577 /**
578   * @brief  Set the specified data holding register value for dual DAC channel.
579   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
580   *               the configuration information for the specified DAC.
581   * @param  Alignment Specifies the data alignment for dual channel DAC.
582   *          This parameter can be one of the following values:
583   *            DAC_ALIGN_8B_R: 8bit right data alignment selected
584   *            DAC_ALIGN_12B_L: 12bit left data alignment selected
585   *            DAC_ALIGN_12B_R: 12bit right data alignment selected
586   * @param  Data1 Data for DAC Channel1 to be loaded in the selected data holding register.
587   * @param  Data2 Data for DAC Channel2 to be loaded in the selected data  holding register.
588   * @note   In dual mode, a unique register access is required to write in both
589   *          DAC channels at the same time.
590   * @retval HAL status
591   */
HAL_DACEx_DualSetValue(DAC_HandleTypeDef * hdac,uint32_t Alignment,uint32_t Data1,uint32_t Data2)592 HAL_StatusTypeDef HAL_DACEx_DualSetValue(DAC_HandleTypeDef *hdac, uint32_t Alignment, uint32_t Data1, uint32_t Data2)
593 {
594   uint32_t data;
595   uint32_t tmp;
596 
597   /* Check the DAC peripheral handle */
598   if (hdac == NULL)
599   {
600     return HAL_ERROR;
601   }
602 
603   /* Check the parameters */
604   assert_param(IS_DAC_ALIGN(Alignment));
605   assert_param(IS_DAC_DATA(Data1));
606   assert_param(IS_DAC_DATA(Data2));
607 
608   /* Calculate and set dual DAC data holding register value */
609   if (Alignment == DAC_ALIGN_8B_R)
610   {
611     data = ((uint32_t)Data2 << 8U) | Data1;
612   }
613   else
614   {
615     data = ((uint32_t)Data2 << 16U) | Data1;
616   }
617 
618   tmp = (uint32_t)hdac->Instance;
619   tmp += DAC_DHR12RD_ALIGNMENT(Alignment);
620 
621   /* Set the dual DAC selected data holding register */
622   *(__IO uint32_t *)tmp = data;
623 
624   /* Return function status */
625   return HAL_OK;
626 }
627 
628 /**
629   * @brief  Conversion complete callback in non-blocking mode for Channel2.
630   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
631   *         the configuration information for the specified DAC.
632   * @retval None
633   */
HAL_DACEx_ConvCpltCallbackCh2(DAC_HandleTypeDef * hdac)634 __weak void HAL_DACEx_ConvCpltCallbackCh2(DAC_HandleTypeDef *hdac)
635 {
636   /* Prevent unused argument(s) compilation warning */
637   UNUSED(hdac);
638 
639   /* NOTE : This function should not be modified, when the callback is needed,
640             the HAL_DACEx_ConvCpltCallbackCh2 could be implemented in the user file
641    */
642 }
643 
644 /**
645   * @brief  Conversion half DMA transfer callback in non-blocking mode for Channel2.
646   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
647   *         the configuration information for the specified DAC.
648   * @retval None
649   */
HAL_DACEx_ConvHalfCpltCallbackCh2(DAC_HandleTypeDef * hdac)650 __weak void HAL_DACEx_ConvHalfCpltCallbackCh2(DAC_HandleTypeDef *hdac)
651 {
652   /* Prevent unused argument(s) compilation warning */
653   UNUSED(hdac);
654 
655   /* NOTE : This function should not be modified, when the callback is needed,
656             the HAL_DACEx_ConvHalfCpltCallbackCh2 could be implemented in the user file
657    */
658 }
659 
660 /**
661   * @brief  Error DAC callback for Channel2.
662   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
663   *         the configuration information for the specified DAC.
664   * @retval None
665   */
HAL_DACEx_ErrorCallbackCh2(DAC_HandleTypeDef * hdac)666 __weak void HAL_DACEx_ErrorCallbackCh2(DAC_HandleTypeDef *hdac)
667 {
668   /* Prevent unused argument(s) compilation warning */
669   UNUSED(hdac);
670 
671   /* NOTE : This function should not be modified, when the callback is needed,
672             the HAL_DACEx_ErrorCallbackCh2 could be implemented in the user file
673    */
674 }
675 
676 /**
677   * @brief  DMA underrun DAC callback for Channel2.
678   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
679   *         the configuration information for the specified DAC.
680   * @retval None
681   */
HAL_DACEx_DMAUnderrunCallbackCh2(DAC_HandleTypeDef * hdac)682 __weak void HAL_DACEx_DMAUnderrunCallbackCh2(DAC_HandleTypeDef *hdac)
683 {
684   /* Prevent unused argument(s) compilation warning */
685   UNUSED(hdac);
686 
687   /* NOTE : This function should not be modified, when the callback is needed,
688             the HAL_DACEx_DMAUnderrunCallbackCh2 could be implemented in the user file
689    */
690 }
691 
692 
693 /**
694   * @brief  Run the self calibration of one DAC channel.
695   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
696   *         the configuration information for the specified DAC.
697   * @param  sConfig DAC channel configuration structure.
698   * @param  Channel The selected DAC channel.
699   *          This parameter can be one of the following values:
700   *            @arg DAC_CHANNEL_1: DAC Channel1 selected
701   *            @arg DAC_CHANNEL_2: DAC Channel2 selected
702   * @retval Updates DAC_TrimmingValue. , DAC_UserTrimming set to DAC_UserTrimming
703   * @retval HAL status
704   * @note   Calibration runs about 7 ms.
705   */
HAL_DACEx_SelfCalibrate(DAC_HandleTypeDef * hdac,DAC_ChannelConfTypeDef * sConfig,uint32_t Channel)706 HAL_StatusTypeDef HAL_DACEx_SelfCalibrate(DAC_HandleTypeDef *hdac, DAC_ChannelConfTypeDef *sConfig, uint32_t Channel)
707 {
708   HAL_StatusTypeDef status = HAL_OK;
709 
710   uint32_t trimmingvalue;
711   uint32_t delta;
712   __IO uint32_t wait_loop_index;
713 
714   /* store/restore channel configuration structure purpose */
715   uint32_t oldmodeconfiguration;
716 
717   /* Check the parameters */
718   assert_param(IS_DAC_CHANNEL(Channel));
719 
720   /* Check the DAC handle allocation */
721   /* Check if DAC running */
722   if ((hdac == NULL) || (sConfig == NULL))
723   {
724     status = HAL_ERROR;
725   }
726   else if (hdac->State == HAL_DAC_STATE_BUSY)
727   {
728     status = HAL_ERROR;
729   }
730   else
731   {
732     /* Process locked */
733     __HAL_LOCK(hdac);
734 
735     /* Store configuration */
736     oldmodeconfiguration = (hdac->Instance->MCR & (DAC_MCR_MODE1 << (Channel & 0x10UL)));
737 
738     /* Disable the selected DAC channel */
739     CLEAR_BIT((hdac->Instance->CR), (DAC_CR_EN1 << (Channel & 0x10UL)));
740     /* Wait for ready bit to be de-asserted */
741     HAL_Delay(1);
742 
743     /* Set mode in MCR  for calibration */
744     MODIFY_REG(hdac->Instance->MCR, (DAC_MCR_MODE1 << (Channel & 0x10UL)), 0U);
745 
746     /* Enable the selected DAC channel calibration */
747     /* i.e. set DAC_CR_CENx bit */
748     SET_BIT((hdac->Instance->CR), (DAC_CR_CEN1 << (Channel & 0x10UL)));
749 
750     /* Init trimming counter */
751     /* Medium value */
752     trimmingvalue = 0x10UL;
753     delta = 0x08UL;
754     while (delta != 0UL)
755     {
756       /* Set candidate trimming */
757       MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1 << (Channel & 0x10UL)), (trimmingvalue << (Channel & 0x10UL)));
758 
759       /* Wait minimum time needed between two calibration steps (OTRIM) */
760       /* Wait loop initialization and execution */
761       /* Note: Variable divided by 2 to compensate partially CPU processing cycles, scaling in us split to not exceed */
762       /*       32 bits register capacity and handle low frequency. */
763       wait_loop_index = ((DAC_DELAY_TRIM_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
764       while (wait_loop_index != 0UL)
765       {
766         wait_loop_index--;
767       }
768 
769       if ((hdac->Instance->SR & (DAC_SR_CAL_FLAG1 << (Channel & 0x10UL))) == (DAC_SR_CAL_FLAG1 << (Channel & 0x10UL)))
770       {
771         /* DAC_SR_CAL_FLAGx is HIGH try higher trimming */
772         trimmingvalue -= delta;
773       }
774       else
775       {
776         /* DAC_SR_CAL_FLAGx is LOW try lower trimming */
777         trimmingvalue += delta;
778       }
779       delta >>= 1UL;
780     }
781 
782     /* Still need to check if right calibration is current value or one step below */
783     /* Indeed the first value that causes the DAC_SR_CAL_FLAGx bit to change from 0 to 1  */
784     /* Set candidate trimming */
785     MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1 << (Channel & 0x10UL)), (trimmingvalue << (Channel & 0x10UL)));
786 
787     /* Wait minimum time needed between two calibration steps (OTRIM) */
788     /* Wait loop initialization and execution */
789     /* Note: Variable divided by 2 to compensate partially CPU processing cycles, scaling in us split to not exceed */
790     /*       32 bits register capacity and handle low frequency. */
791     wait_loop_index = ((DAC_DELAY_TRIM_US / 10UL) * ((SystemCoreClock / (100000UL * 2UL)) + 1UL));
792     while (wait_loop_index != 0UL)
793     {
794       wait_loop_index--;
795     }
796 
797     if ((hdac->Instance->SR & (DAC_SR_CAL_FLAG1 << (Channel & 0x10UL))) == 0UL)
798     {
799       /* Check trimming value below maximum */
800       if (trimmingvalue < 0x1FU)
801       {
802         /* Trimming is actually one value more */
803         trimmingvalue++;
804       }
805       /* Set right trimming */
806       MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1 << (Channel & 0x10UL)), (trimmingvalue << (Channel & 0x10UL)));
807     }
808 
809     /* Disable the selected DAC channel calibration */
810     /* i.e. clear DAC_CR_CENx bit */
811     CLEAR_BIT((hdac->Instance->CR), (DAC_CR_CEN1 << (Channel & 0x10UL)));
812 
813     sConfig->DAC_TrimmingValue = trimmingvalue;
814     sConfig->DAC_UserTrimming = DAC_TRIMMING_USER;
815 
816     /* Restore configuration */
817     MODIFY_REG(hdac->Instance->MCR, (DAC_MCR_MODE1 << (Channel & 0x10UL)), oldmodeconfiguration);
818 
819     /* Process unlocked */
820     __HAL_UNLOCK(hdac);
821   }
822 
823   return status;
824 }
825 
826 /**
827   * @brief  Set the trimming mode and trimming value (user trimming mode applied).
828   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
829   *         the configuration information for the specified DAC.
830   * @param  sConfig DAC configuration structure updated with new DAC trimming value.
831   * @param  Channel The selected DAC channel.
832   *          This parameter can be one of the following values:
833   *            @arg DAC_CHANNEL_1: DAC Channel1 selected
834   *            @arg DAC_CHANNEL_2: DAC Channel2 selected
835   * @param  NewTrimmingValue DAC new trimming value
836   * @retval HAL status
837   */
HAL_DACEx_SetUserTrimming(DAC_HandleTypeDef * hdac,DAC_ChannelConfTypeDef * sConfig,uint32_t Channel,uint32_t NewTrimmingValue)838 HAL_StatusTypeDef HAL_DACEx_SetUserTrimming(DAC_HandleTypeDef *hdac, DAC_ChannelConfTypeDef *sConfig, uint32_t Channel,
839                                             uint32_t NewTrimmingValue)
840 {
841   HAL_StatusTypeDef status = HAL_OK;
842 
843   /* Check the parameters */
844   assert_param(IS_DAC_CHANNEL(Channel));
845   assert_param(IS_DAC_NEWTRIMMINGVALUE(NewTrimmingValue));
846 
847   /* Check the DAC handle and channel configuration struct allocation */
848   if ((hdac == NULL) || (sConfig == NULL))
849   {
850     status = HAL_ERROR;
851   }
852   else
853   {
854     /* Process locked */
855     __HAL_LOCK(hdac);
856 
857     /* Set new trimming */
858     MODIFY_REG(hdac->Instance->CCR, (DAC_CCR_OTRIM1 << (Channel & 0x10UL)), (NewTrimmingValue << (Channel & 0x10UL)));
859 
860     /* Update trimming mode */
861     sConfig->DAC_UserTrimming = DAC_TRIMMING_USER;
862     sConfig->DAC_TrimmingValue = NewTrimmingValue;
863 
864     /* Process unlocked */
865     __HAL_UNLOCK(hdac);
866   }
867   return status;
868 }
869 
870 /**
871   * @brief  Return the DAC trimming value.
872   * @param  hdac DAC handle
873   * @param  Channel The selected DAC channel.
874   *          This parameter can be one of the following values:
875   *            @arg DAC_CHANNEL_1: DAC Channel1 selected
876   *            @arg DAC_CHANNEL_2: DAC Channel2 selected
877   * @retval TrimmingValue Value between Min_Data=0x00 and Max_Data=0x1F
878  */
HAL_DACEx_GetTrimOffset(const DAC_HandleTypeDef * hdac,uint32_t Channel)879 uint32_t HAL_DACEx_GetTrimOffset(const DAC_HandleTypeDef *hdac, uint32_t Channel)
880 {
881   /* Check the parameter */
882   assert_param(IS_DAC_CHANNEL(Channel));
883 
884   /* Retrieve trimming */
885   return ((hdac->Instance->CCR & (DAC_CCR_OTRIM1 << (Channel & 0x10UL))) >> (Channel & 0x10UL));
886 }
887 
888 /**
889   * @}
890   */
891 
892 /** @defgroup DACEx_Exported_Functions_Group3 Peripheral Control functions
893   *  @brief    Extended Peripheral Control functions
894   *
895 @verbatim
896   ==============================================================================
897              ##### Peripheral Control functions #####
898   ==============================================================================
899     [..]  This section provides functions allowing to:
900       (+) Set the specified data holding register value for DAC channel.
901 
902 @endverbatim
903   * @{
904   */
905 
906 
907 /**
908   * @brief  Return the last data output value of the selected DAC channel.
909   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
910   *         the configuration information for the specified DAC.
911   * @retval The selected DAC channel data output value.
912   */
HAL_DACEx_DualGetValue(const DAC_HandleTypeDef * hdac)913 uint32_t HAL_DACEx_DualGetValue(const DAC_HandleTypeDef *hdac)
914 {
915   uint32_t tmp = 0UL;
916 
917   tmp |= hdac->Instance->DOR1;
918 
919   tmp |= hdac->Instance->DOR2 << 16UL;
920 
921   /* Returns the DAC channel data output register value */
922   return tmp;
923 }
924 
925 
926 /**
927   * @}
928   */
929 /**
930   * @}
931   */
932 
933 /* Private functions ---------------------------------------------------------*/
934 /** @defgroup DACEx_Private_Functions DACEx private functions
935   *  @brief    Extended private functions
936   * @{
937   */
938 
939 
940 /**
941   * @brief  DMA conversion complete callback.
942   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
943   *                the configuration information for the specified DMA module.
944   * @retval None
945   */
DAC_DMAConvCpltCh2(DMA_HandleTypeDef * hdma)946 void DAC_DMAConvCpltCh2(DMA_HandleTypeDef *hdma)
947 {
948   DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
949 
950 #if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
951   hdac->ConvCpltCallbackCh2(hdac);
952 #else
953   HAL_DACEx_ConvCpltCallbackCh2(hdac);
954 #endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
955 
956   hdac->State = HAL_DAC_STATE_READY;
957 }
958 
959 /**
960   * @brief  DMA half transfer complete callback.
961   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
962   *                the configuration information for the specified DMA module.
963   * @retval None
964   */
DAC_DMAHalfConvCpltCh2(DMA_HandleTypeDef * hdma)965 void DAC_DMAHalfConvCpltCh2(DMA_HandleTypeDef *hdma)
966 {
967   DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
968   /* Conversion complete callback */
969 #if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
970   hdac->ConvHalfCpltCallbackCh2(hdac);
971 #else
972   HAL_DACEx_ConvHalfCpltCallbackCh2(hdac);
973 #endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
974 }
975 
976 /**
977   * @brief  DMA error callback.
978   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
979   *                the configuration information for the specified DMA module.
980   * @retval None
981   */
DAC_DMAErrorCh2(DMA_HandleTypeDef * hdma)982 void DAC_DMAErrorCh2(DMA_HandleTypeDef *hdma)
983 {
984   DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
985 
986   /* Set DAC error code to DMA error */
987   hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
988 
989 #if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
990   hdac->ErrorCallbackCh2(hdac);
991 #else
992   HAL_DACEx_ErrorCallbackCh2(hdac);
993 #endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
994 
995   hdac->State = HAL_DAC_STATE_READY;
996 }
997 
998 
999 /**
1000   * @}
1001   */
1002 
1003 /**
1004   * @}
1005   */
1006 
1007 #endif /* DAC1 */
1008 
1009 #endif /* HAL_DAC_MODULE_ENABLED */
1010 
1011 /**
1012   * @}
1013   */
1014