1 /**
2   ******************************************************************************
3   * @file    stm32l1xx_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) 2016 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      *** Signal generation operation ***
27      ===================================
28      [..]
29       (+) Use HAL_DACEx_TriangleWaveGenerate() to generate Triangle signal.
30       (+) Use HAL_DACEx_NoiseWaveGenerate() to generate Noise signal.
31 
32  @endverbatim
33   ******************************************************************************
34   */
35 
36 
37 /* Includes ------------------------------------------------------------------*/
38 #include "stm32l1xx_hal.h"
39 
40 /** @addtogroup STM32L1xx_HAL_Driver
41   * @{
42   */
43 
44 #ifdef HAL_DAC_MODULE_ENABLED
45 
46 #if defined(DAC1)
47 
48 /** @defgroup DACEx DACEx
49   * @brief DAC Extended HAL module driver
50   * @{
51   */
52 
53 /* Private typedef -----------------------------------------------------------*/
54 /* Private define ------------------------------------------------------------*/
55 
56 /* Private macro -------------------------------------------------------------*/
57 /* Private variables ---------------------------------------------------------*/
58 /* Private function prototypes -----------------------------------------------*/
59 /* Exported functions --------------------------------------------------------*/
60 
61 /** @defgroup DACEx_Exported_Functions DACEx Exported Functions
62   * @{
63   */
64 
65 /** @defgroup DACEx_Exported_Functions_Group2 IO operation functions
66   *  @brief    Extended IO operation functions
67   *
68 @verbatim
69   ==============================================================================
70                  ##### Extended features functions #####
71   ==============================================================================
72     [..]  This section provides functions allowing to:
73       (+) Start conversion.
74       (+) Stop conversion.
75       (+) Start conversion and enable DMA transfer.
76       (+) Stop conversion and disable DMA transfer.
77       (+) Get result of conversion.
78       (+) Get result of dual mode conversion.
79 
80 @endverbatim
81   * @{
82   */
83 
84 
85 /**
86   * @brief  Enables DAC and starts conversion of both channels.
87   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
88   *         the configuration information for the specified DAC.
89   * @retval HAL status
90   */
HAL_DACEx_DualStart(DAC_HandleTypeDef * hdac)91 HAL_StatusTypeDef HAL_DACEx_DualStart(DAC_HandleTypeDef *hdac)
92 {
93   uint32_t tmp_swtrig = 0UL;
94 
95   /* Check the DAC peripheral handle */
96   if (hdac == NULL)
97   {
98     return HAL_ERROR;
99   }
100 
101 
102   /* Process locked */
103   __HAL_LOCK(hdac);
104 
105   /* Change DAC state */
106   hdac->State = HAL_DAC_STATE_BUSY;
107 
108   /* Enable the Peripheral */
109   __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_1);
110   __HAL_DAC_ENABLE(hdac, DAC_CHANNEL_2);
111 
112   /* Check if software trigger enabled */
113   if ((hdac->Instance->CR & (DAC_CR_TEN1 | DAC_CR_TSEL1)) == DAC_TRIGGER_SOFTWARE)
114   {
115     tmp_swtrig |= DAC_SWTRIGR_SWTRIG1;
116   }
117   if ((hdac->Instance->CR & (DAC_CR_TEN2 | DAC_CR_TSEL2)) == (DAC_TRIGGER_SOFTWARE << (DAC_CHANNEL_2 & 0x10UL)))
118   {
119     tmp_swtrig |= DAC_SWTRIGR_SWTRIG2;
120   }
121   /* Enable the selected DAC software conversion*/
122   SET_BIT(hdac->Instance->SWTRIGR, tmp_swtrig);
123 
124   /* Change DAC state */
125   hdac->State = HAL_DAC_STATE_READY;
126 
127   /* Process unlocked */
128   __HAL_UNLOCK(hdac);
129 
130   /* Return function status */
131   return HAL_OK;
132 }
133 
134 /**
135   * @brief  Disables DAC and stop conversion of both channels.
136   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
137   *         the configuration information for the specified DAC.
138   * @retval HAL status
139   */
HAL_DACEx_DualStop(DAC_HandleTypeDef * hdac)140 HAL_StatusTypeDef HAL_DACEx_DualStop(DAC_HandleTypeDef *hdac)
141 {
142   /* Check the DAC peripheral handle */
143   if (hdac == NULL)
144   {
145     return HAL_ERROR;
146   }
147 
148 
149   /* Disable the Peripheral */
150   __HAL_DAC_DISABLE(hdac, DAC_CHANNEL_1);
151   __HAL_DAC_DISABLE(hdac, DAC_CHANNEL_2);
152 
153   /* Change DAC state */
154   hdac->State = HAL_DAC_STATE_READY;
155 
156   /* Return function status */
157   return HAL_OK;
158 }
159 
160 
161 /**
162   * @brief  Enable or disable the selected DAC channel wave generation.
163   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
164   *         the configuration information for the specified DAC.
165   * @param  Channel The selected DAC channel.
166   *          This parameter can be one of the following values:
167   *            @arg DAC_CHANNEL_1: DAC Channel1 selected
168   *            @arg DAC_CHANNEL_2: DAC Channel2 selected
169   * @param  Amplitude Select max triangle amplitude.
170   *          This parameter can be one of the following values:
171   *            @arg DAC_TRIANGLEAMPLITUDE_1: Select max triangle amplitude of 1
172   *            @arg DAC_TRIANGLEAMPLITUDE_3: Select max triangle amplitude of 3
173   *            @arg DAC_TRIANGLEAMPLITUDE_7: Select max triangle amplitude of 7
174   *            @arg DAC_TRIANGLEAMPLITUDE_15: Select max triangle amplitude of 15
175   *            @arg DAC_TRIANGLEAMPLITUDE_31: Select max triangle amplitude of 31
176   *            @arg DAC_TRIANGLEAMPLITUDE_63: Select max triangle amplitude of 63
177   *            @arg DAC_TRIANGLEAMPLITUDE_127: Select max triangle amplitude of 127
178   *            @arg DAC_TRIANGLEAMPLITUDE_255: Select max triangle amplitude of 255
179   *            @arg DAC_TRIANGLEAMPLITUDE_511: Select max triangle amplitude of 511
180   *            @arg DAC_TRIANGLEAMPLITUDE_1023: Select max triangle amplitude of 1023
181   *            @arg DAC_TRIANGLEAMPLITUDE_2047: Select max triangle amplitude of 2047
182   *            @arg DAC_TRIANGLEAMPLITUDE_4095: Select max triangle amplitude of 4095
183   * @retval HAL status
184   */
HAL_DACEx_TriangleWaveGenerate(DAC_HandleTypeDef * hdac,uint32_t Channel,uint32_t Amplitude)185 HAL_StatusTypeDef HAL_DACEx_TriangleWaveGenerate(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Amplitude)
186 {
187   /* Check the DAC peripheral handle */
188   if (hdac == NULL)
189   {
190     return HAL_ERROR;
191   }
192 
193   /* Check the parameters */
194   assert_param(IS_DAC_CHANNEL(Channel));
195   assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(Amplitude));
196 
197   /* Process locked */
198   __HAL_LOCK(hdac);
199 
200   /* Change DAC state */
201   hdac->State = HAL_DAC_STATE_BUSY;
202 
203   /* Enable the triangle wave generation for the selected DAC channel */
204   MODIFY_REG(hdac->Instance->CR, ((DAC_CR_WAVE1) | (DAC_CR_MAMP1)) << (Channel & 0x10UL),
205              (DAC_CR_WAVE1_1 | Amplitude) << (Channel & 0x10UL));
206 
207   /* Change DAC state */
208   hdac->State = HAL_DAC_STATE_READY;
209 
210   /* Process unlocked */
211   __HAL_UNLOCK(hdac);
212 
213   /* Return function status */
214   return HAL_OK;
215 }
216 
217 /**
218   * @brief  Enable or disable the selected DAC channel wave generation.
219   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
220   *         the configuration information for the specified DAC.
221   * @param  Channel The selected DAC channel.
222   *          This parameter can be one of the following values:
223   *            @arg DAC_CHANNEL_1: DAC Channel1 selected
224   *            @arg DAC_CHANNEL_2: DAC Channel2 selected
225   * @param  Amplitude Unmask DAC channel LFSR for noise wave generation.
226   *          This parameter can be one of the following values:
227   *            @arg DAC_LFSRUNMASK_BIT0: Unmask DAC channel LFSR bit0 for noise wave generation
228   *            @arg DAC_LFSRUNMASK_BITS1_0: Unmask DAC channel LFSR bit[1:0] for noise wave generation
229   *            @arg DAC_LFSRUNMASK_BITS2_0: Unmask DAC channel LFSR bit[2:0] for noise wave generation
230   *            @arg DAC_LFSRUNMASK_BITS3_0: Unmask DAC channel LFSR bit[3:0] for noise wave generation
231   *            @arg DAC_LFSRUNMASK_BITS4_0: Unmask DAC channel LFSR bit[4:0] for noise wave generation
232   *            @arg DAC_LFSRUNMASK_BITS5_0: Unmask DAC channel LFSR bit[5:0] for noise wave generation
233   *            @arg DAC_LFSRUNMASK_BITS6_0: Unmask DAC channel LFSR bit[6:0] for noise wave generation
234   *            @arg DAC_LFSRUNMASK_BITS7_0: Unmask DAC channel LFSR bit[7:0] for noise wave generation
235   *            @arg DAC_LFSRUNMASK_BITS8_0: Unmask DAC channel LFSR bit[8:0] for noise wave generation
236   *            @arg DAC_LFSRUNMASK_BITS9_0: Unmask DAC channel LFSR bit[9:0] for noise wave generation
237   *            @arg DAC_LFSRUNMASK_BITS10_0: Unmask DAC channel LFSR bit[10:0] for noise wave generation
238   *            @arg DAC_LFSRUNMASK_BITS11_0: Unmask DAC channel LFSR bit[11:0] for noise wave generation
239   * @retval HAL status
240   */
HAL_DACEx_NoiseWaveGenerate(DAC_HandleTypeDef * hdac,uint32_t Channel,uint32_t Amplitude)241 HAL_StatusTypeDef HAL_DACEx_NoiseWaveGenerate(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Amplitude)
242 {
243   /* Check the DAC peripheral handle */
244   if (hdac == NULL)
245   {
246     return HAL_ERROR;
247   }
248 
249   /* Check the parameters */
250   assert_param(IS_DAC_CHANNEL(Channel));
251   assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(Amplitude));
252 
253   /* Process locked */
254   __HAL_LOCK(hdac);
255 
256   /* Change DAC state */
257   hdac->State = HAL_DAC_STATE_BUSY;
258 
259   /* Enable the noise wave generation for the selected DAC channel */
260   MODIFY_REG(hdac->Instance->CR, ((DAC_CR_WAVE1) | (DAC_CR_MAMP1)) << (Channel & 0x10UL),
261              (DAC_CR_WAVE1_0 | Amplitude) << (Channel & 0x10UL));
262 
263   /* Change DAC state */
264   hdac->State = HAL_DAC_STATE_READY;
265 
266   /* Process unlocked */
267   __HAL_UNLOCK(hdac);
268 
269   /* Return function status */
270   return HAL_OK;
271 }
272 
273 
274 /**
275   * @brief  Set the specified data holding register value for dual DAC channel.
276   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
277   *               the configuration information for the specified DAC.
278   * @param  Alignment Specifies the data alignment for dual channel DAC.
279   *          This parameter can be one of the following values:
280   *            DAC_ALIGN_8B_R: 8bit right data alignment selected
281   *            DAC_ALIGN_12B_L: 12bit left data alignment selected
282   *            DAC_ALIGN_12B_R: 12bit right data alignment selected
283   * @param  Data1 Data for DAC Channel1 to be loaded in the selected data holding register.
284   * @param  Data2 Data for DAC Channel2 to be loaded in the selected data  holding register.
285   * @note   In dual mode, a unique register access is required to write in both
286   *          DAC channels at the same time.
287   * @retval HAL status
288   */
HAL_DACEx_DualSetValue(DAC_HandleTypeDef * hdac,uint32_t Alignment,uint32_t Data1,uint32_t Data2)289 HAL_StatusTypeDef HAL_DACEx_DualSetValue(DAC_HandleTypeDef *hdac, uint32_t Alignment, uint32_t Data1, uint32_t Data2)
290 {
291   uint32_t data;
292   uint32_t tmp;
293 
294   /* Check the DAC peripheral handle */
295   if (hdac == NULL)
296   {
297     return HAL_ERROR;
298   }
299 
300   /* Check the parameters */
301   assert_param(IS_DAC_ALIGN(Alignment));
302   assert_param(IS_DAC_DATA(Data1));
303   assert_param(IS_DAC_DATA(Data2));
304 
305   /* Calculate and set dual DAC data holding register value */
306   if (Alignment == DAC_ALIGN_8B_R)
307   {
308     data = ((uint32_t)Data2 << 8U) | Data1;
309   }
310   else
311   {
312     data = ((uint32_t)Data2 << 16U) | Data1;
313   }
314 
315   tmp = (uint32_t)hdac->Instance;
316   tmp += DAC_DHR12RD_ALIGNMENT(Alignment);
317 
318   /* Set the dual DAC selected data holding register */
319   *(__IO uint32_t *)tmp = data;
320 
321   /* Return function status */
322   return HAL_OK;
323 }
324 
325 /**
326   * @brief  Conversion complete callback in non-blocking mode for Channel2.
327   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
328   *         the configuration information for the specified DAC.
329   * @retval None
330   */
HAL_DACEx_ConvCpltCallbackCh2(DAC_HandleTypeDef * hdac)331 __weak void HAL_DACEx_ConvCpltCallbackCh2(DAC_HandleTypeDef *hdac)
332 {
333   /* Prevent unused argument(s) compilation warning */
334   UNUSED(hdac);
335 
336   /* NOTE : This function should not be modified, when the callback is needed,
337             the HAL_DACEx_ConvCpltCallbackCh2 could be implemented in the user file
338    */
339 }
340 
341 /**
342   * @brief  Conversion half DMA transfer callback in non-blocking mode for Channel2.
343   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
344   *         the configuration information for the specified DAC.
345   * @retval None
346   */
HAL_DACEx_ConvHalfCpltCallbackCh2(DAC_HandleTypeDef * hdac)347 __weak void HAL_DACEx_ConvHalfCpltCallbackCh2(DAC_HandleTypeDef *hdac)
348 {
349   /* Prevent unused argument(s) compilation warning */
350   UNUSED(hdac);
351 
352   /* NOTE : This function should not be modified, when the callback is needed,
353             the HAL_DACEx_ConvHalfCpltCallbackCh2 could be implemented in the user file
354    */
355 }
356 
357 /**
358   * @brief  Error DAC callback for Channel2.
359   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
360   *         the configuration information for the specified DAC.
361   * @retval None
362   */
HAL_DACEx_ErrorCallbackCh2(DAC_HandleTypeDef * hdac)363 __weak void HAL_DACEx_ErrorCallbackCh2(DAC_HandleTypeDef *hdac)
364 {
365   /* Prevent unused argument(s) compilation warning */
366   UNUSED(hdac);
367 
368   /* NOTE : This function should not be modified, when the callback is needed,
369             the HAL_DACEx_ErrorCallbackCh2 could be implemented in the user file
370    */
371 }
372 
373 /**
374   * @brief  DMA underrun DAC callback for Channel2.
375   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
376   *         the configuration information for the specified DAC.
377   * @retval None
378   */
HAL_DACEx_DMAUnderrunCallbackCh2(DAC_HandleTypeDef * hdac)379 __weak void HAL_DACEx_DMAUnderrunCallbackCh2(DAC_HandleTypeDef *hdac)
380 {
381   /* Prevent unused argument(s) compilation warning */
382   UNUSED(hdac);
383 
384   /* NOTE : This function should not be modified, when the callback is needed,
385             the HAL_DACEx_DMAUnderrunCallbackCh2 could be implemented in the user file
386    */
387 }
388 
389 
390 
391 /**
392   * @}
393   */
394 
395 /** @defgroup DACEx_Exported_Functions_Group3 Peripheral Control functions
396   *  @brief    Extended Peripheral Control functions
397   *
398 @verbatim
399   ==============================================================================
400              ##### Peripheral Control functions #####
401   ==============================================================================
402     [..]  This section provides functions allowing to:
403       (+) Set the specified data holding register value for DAC channel.
404 
405 @endverbatim
406   * @{
407   */
408 
409 
410 /**
411   * @brief  Return the last data output value of the selected DAC channel.
412   * @param  hdac pointer to a DAC_HandleTypeDef structure that contains
413   *         the configuration information for the specified DAC.
414   * @retval The selected DAC channel data output value.
415   */
HAL_DACEx_DualGetValue(const DAC_HandleTypeDef * hdac)416 uint32_t HAL_DACEx_DualGetValue(const DAC_HandleTypeDef *hdac)
417 {
418   uint32_t tmp = 0UL;
419 
420   tmp |= hdac->Instance->DOR1;
421 
422   tmp |= hdac->Instance->DOR2 << 16UL;
423 
424   /* Returns the DAC channel data output register value */
425   return tmp;
426 }
427 
428 
429 /**
430   * @}
431   */
432 /**
433   * @}
434   */
435 
436 /* Private functions ---------------------------------------------------------*/
437 /** @defgroup DACEx_Private_Functions DACEx private functions
438   *  @brief    Extended private functions
439   * @{
440   */
441 
442 
443 /**
444   * @brief  DMA conversion complete callback.
445   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
446   *                the configuration information for the specified DMA module.
447   * @retval None
448   */
DAC_DMAConvCpltCh2(DMA_HandleTypeDef * hdma)449 void DAC_DMAConvCpltCh2(DMA_HandleTypeDef *hdma)
450 {
451   DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
452 
453 #if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
454   hdac->ConvCpltCallbackCh2(hdac);
455 #else
456   HAL_DACEx_ConvCpltCallbackCh2(hdac);
457 #endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
458 
459   hdac->State = HAL_DAC_STATE_READY;
460 }
461 
462 /**
463   * @brief  DMA half transfer complete callback.
464   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
465   *                the configuration information for the specified DMA module.
466   * @retval None
467   */
DAC_DMAHalfConvCpltCh2(DMA_HandleTypeDef * hdma)468 void DAC_DMAHalfConvCpltCh2(DMA_HandleTypeDef *hdma)
469 {
470   DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
471   /* Conversion complete callback */
472 #if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
473   hdac->ConvHalfCpltCallbackCh2(hdac);
474 #else
475   HAL_DACEx_ConvHalfCpltCallbackCh2(hdac);
476 #endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
477 }
478 
479 /**
480   * @brief  DMA error callback.
481   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
482   *                the configuration information for the specified DMA module.
483   * @retval None
484   */
DAC_DMAErrorCh2(DMA_HandleTypeDef * hdma)485 void DAC_DMAErrorCh2(DMA_HandleTypeDef *hdma)
486 {
487   DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
488 
489   /* Set DAC error code to DMA error */
490   hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
491 
492 #if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
493   hdac->ErrorCallbackCh2(hdac);
494 #else
495   HAL_DACEx_ErrorCallbackCh2(hdac);
496 #endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
497 
498   hdac->State = HAL_DAC_STATE_READY;
499 }
500 
501 
502 /**
503   * @}
504   */
505 
506 /**
507   * @}
508   */
509 
510 #endif /* DAC1 */
511 
512 #endif /* HAL_DAC_MODULE_ENABLED */
513 
514 /**
515   * @}
516   */
517