1 /**
2   ******************************************************************************
3   * @file    stm32h7rsxx_hal_mdf.c
4   * @author  MCD Application Team
5   * @brief   This file provides firmware functions to manage the following
6   *          functionalities of the Multi-function Digital Filter (MDF)
7   *          peripheral:
8   *           + Initialization and de-initialization
9   *           + Acquisition
10   *           + Clock absence detection
11   *
12   ******************************************************************************
13   * @attention
14   *
15   * Copyright (c) 2022 STMicroelectronics.
16   * All rights reserved.
17   *
18   * This software is licensed under terms that can be found in the LICENSE file
19   * in the root directory of this software component.
20   * If no LICENSE file comes with this software, it is provided AS-IS.
21   *
22   ******************************************************************************
23   @verbatim
24   ==============================================================================
25                      ##### How to use this driver #####
26   ==============================================================================
27   [..]
28     *** Initialization and de-initialization ***
29     ============================================
30     [..]
31       (#) User has first to initialize ADF instance.
32       (#) As prerequisite, fill in the HAL_MDF_MspInit() :
33         (++) Enable ADFz clock interface with __HAL_RCC_ADFz_CLK_ENABLE().
34         (++) Enable the clocks for the used GPIOS with __HAL_RCC_GPIOx_CLK_ENABLE().
35         (++) Configure these pins in alternate mode using HAL_GPIO_Init().
36         (++) If interrupt mode is used, enable and configure ADFz_FLTx
37              interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ().
38         (++) If DMA mode is used, initialize and configure DMA.
39       (#) Configure the common parameters, serial interface parameters and
40           filter bitstream selection by calling HAL_MDF_Init() function.
41 
42     [..]
43       (#) User can de-initialize ADF instance with HAL_MDF_DeInit() function.
44 
45     *** Acquisition ***
46     ===================
47     [..]
48       (#) Configure filter parameters and start acquisition using HAL_MDF_AcqStart(),
49           HAL_MDF_AcqStart_IT() or HAL_MDF_AcqStart_DMA().
50       (#) In polling mode :
51             (++) Use HAL_MDF_PollForAcq() to detect the end of acquisition.
52                  Use HAL_MDF_GetAcqValue to get acquisition value.
53             (++) Use HAL_MDF_PollForSndLvl() to detect and get
54                  new sound level value and ambient noise value.
55             (++) Use HAL_MDF_PollForSad() to detect sound activity.
56       (#) In interrupt mode :
57             (++) HAL_MDF_AcqCpltCallback() will be called at the end of acquisition.
58                  Use HAL_MDF_GetAcqValue to get acquisition value.
59             (++) HAL_MDF_SndLvlCallback() will be called when new
60                  sound level and ambient noise values are available.
61             (++) HAL_MDF_SadCallback() will be called when
62                  sound activity detection occurs.
63             (++) HAL_MDF_ErrorCallback() will be called if overflow, filter overrun or
64                  saturation occurs.
65                  Use HAL_MDF_GetErrorCode() to get the corresponding error.
66       (#) In DMA mode :
67             (++) HAL_MDF_AcqHalfCpltCallback() and HAL_MDF_AcqCpltCallback() will be called
68                  respectively at the half acquisition and at the acquisition complete.
69             (++) HAL_MDF_SndLvlCallback() will be called when new
70                  sound level and ambient noise values are available.
71             (++) HAL_MDF_SadCallback() will be called when
72                  sound activity detection occurs.
73             (++) HAL_MDF_ErrorCallback() will be called if overflow, filter overrun,
74                  saturation or DMA error occurs.
75                  Use HAL_MDF_GetErrorCode() to get the corresponding error.
76       (#) Use HAL_MDF_GenerateTrgo() to generate pulse on TRGO signal.
77       (#) During acquisition, use HAL_MDF_SetDelay() and HAL_MDF_GetDelay() to respectively
78           set and get the delay on data source.
79       (#) During acquisition, use HAL_MDF_SetGain() and HAL_MDF_GetGain() to respectively
80           set and get the filter gain.
81       (#) Stop acquisition using HAL_MDF_AcqStop(), HAL_MDF_AcqStop_IT() or HAL_MDF_AcqStop_DMA().
82 
83     *** Clock absence detection ***
84     ===============================
85     [..]
86       (#) Clock absence detection is always enabled so no need to start clock absence detection
87           in polling mode.
88           Use HAL_MDF_CkabStart_IT() to start clock absence detection in interrupt mode.
89       (#) In polling mode, use HAL_MDF_PollForCkab() to detect the clock absence.
90       (#) In interrupt mode, HAL_MDF_ErrorCallback() will be called if clock absence detection
91           occurs.
92           Use HAL_MDF_GetErrorCode() to get the corresponding error.
93       (#) Stop clock absence detection in interrupt mode using HAL_MDF_CkabStop_IT().
94 
95     *** generic functions ***
96     =========================
97     [..]
98       (#) HAL_MDF_IRQHandler will be called when ADF interrupt occurs.
99       (#) HAL_MDF_ErrorCallback will be called when ADF error occurs.
100       (#) Use HAL_MDF_GetState() to get the current ADF instance state.
101       (#) Use HAL_MDF_GetErrorCode() to get the current ADF instance error code.
102 
103     *** Callback registration ***
104     =============================
105     [..]
106     The compilation define USE_HAL_MDF_REGISTER_CALLBACKS when set to 1
107     allows the user to configure dynamically the driver callbacks.
108     Use functions HAL_MDF_RegisterCallback(), HAL_MDF_RegisterOldCallback()
109     or HAL_MDF_RegisterSndLvlCallback() to register a user callback.
110 
111     [..]
112     Function HAL_MDF_RegisterCallback() allows to register following callbacks :
113       (+) AcqCpltCallback     : Acquisition complete callback.
114       (+) AcqHalfCpltCallback : Acquisition half complete callback.
115       (+) SadCallback         : Sound activity detection callback (only for ADF instance).
116       (+) ErrorCallback       : Error callback.
117       (+) MspInitCallback     : MSP init callback.
118       (+) MspDeInitCallback   : MSP de-init callback.
119     [..]
120     This function takes as parameters the HAL peripheral handle, the Callback ID
121     and a pointer to the user callback function.
122 
123     [..]
124     For specific sound level callback use dedicated register callback :
125     HAL_MDF_RegisterSndLvlCallback().
126 
127     [..]
128     Use function HAL_MDF_UnRegisterCallback() to reset a callback to the default weak function.
129 
130     [..]
131     HAL_MDF_UnRegisterCallback() takes as parameters the HAL peripheral handle and the Callback ID.
132     [..]
133     This function allows to reset following callbacks :
134       (+) AcqCpltCallback     : Acquisition complete callback.
135       (+) AcqHalfCpltCallback : Acquisition half complete callback.
136       (+) SadCallback         : Sound activity detection callback (only for ADF instance).
137       (+) ErrorCallback       : Error callback.
138       (+) MspInitCallback     : MSP init callback.
139       (+) MspDeInitCallback   : MSP de-init callback.
140 
141     [..]
142     For specific sound level callback use dedicated unregister callback :
143     HAL_MDF_UnRegisterSndLvlCallback().
144 
145     [..]
146     By default, after the call of init function and if the state is RESET
147     all callbacks are reset to the corresponding legacy weak functions :
148     examples HAL_MDF_AcqCpltCallback(), HAL_MDF_ErrorCallback().
149     Exception done for MspInit and MspDeInit callbacks that are respectively
150     reset to the legacy weak functions in the init and de-init only when these
151     callbacks are null (not registered beforehand).
152     If not, MspInit or MspDeInit are not null, the init and de-init keep and use
153     the user MspInit/MspDeInit callbacks (registered beforehand).
154 
155     [..]
156     Callbacks can be registered/unregistered in READY state only.
157     Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
158     in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
159     during the init/de-init.
160     In that case first register the MspInit/MspDeInit user callbacks using
161     HAL_MDF_RegisterCallback() before calling init or de-init function.
162 
163     [..]
164     When the compilation define USE_HAL_MDF_REGISTER_CALLBACKS is set to 0 or
165     not defined, the callback registering feature is not available
166     and weak callbacks are used.
167 
168     @endverbatim
169   */
170 
171 /* Includes ------------------------------------------------------------------*/
172 #include "stm32h7rsxx_hal.h"
173 
174 /** @addtogroup STM32H7RSxx_HAL_Driver
175   * @{
176   */
177 
178 /** @defgroup MDF MDF
179   * @brief MDF HAL module driver
180   * @{
181   */
182 
183 #ifdef HAL_MDF_MODULE_ENABLED
184 
185 /* Private typedef -----------------------------------------------------------*/
186 /** @defgroup MDF_Private_Typedefs  MDF Private Typedefs
187   * @{
188   */
189 /**
190   * @}
191   */
192 
193 /* Private define ------------------------------------------------------------*/
194 /** @defgroup MDF_Private_Constants  MDF Private Constants
195   * @{
196   */
197 /**
198   * @}
199   */
200 
201 /* Private macro -------------------------------------------------------------*/
202 /* Private variables ---------------------------------------------------------*/
203 /** @defgroup MDF_Private_Variables  MDF Private Variables
204   * @{
205   */
206 static MDF_HandleTypeDef *v_mdfHandle = NULL;
207 /**
208   * @}
209   */
210 
211 /* Private function prototypes -----------------------------------------------*/
212 /** @defgroup MDF_Private_Functions  MDF Private Functions
213   * @{
214   */
215 static void     MDF_AcqStart(MDF_HandleTypeDef *const hmdf, const MDF_FilterConfigTypeDef *const pFilterConfig);
216 static void     MDF_DmaXferCpltCallback(DMA_HandleTypeDef *hdma);
217 static void     MDF_DmaXferHalfCpltCallback(DMA_HandleTypeDef *hdma);
218 static void     MDF_DmaErrorCallback(DMA_HandleTypeDef *hdma);
219 /**
220   * @}
221   */
222 
223 /* Exported functions ---------------------------------------------------------*/
224 /** @defgroup MDF_Exported_Functions  MDF Exported Functions
225   * @{
226   */
227 
228 /** @defgroup MDF_Exported_Functions_Group1  Initialization and de-initialization functions
229   * @brief    Initialization and de-initialization functions
230   *
231 @verbatim
232   ==============================================================================
233             ##### Initialization and de-initialization functions #####
234   ==============================================================================
235     [..]  This section provides functions allowing to :
236       (+) Initialize the ADF instance.
237       (+) De-initialize the ADF instance.
238       (+) Register and unregister callbacks.
239 @endverbatim
240   * @{
241   */
242 
243 /**
244   * @brief  Initialize the MDF instance according to the specified parameters
245   *         in the MDF_InitTypeDef structure and initialize the associated handle.
246   * @param  hmdf MDF handle.
247   * @retval HAL status.
248   */
HAL_MDF_Init(MDF_HandleTypeDef * hmdf)249 HAL_StatusTypeDef HAL_MDF_Init(MDF_HandleTypeDef *hmdf)
250 {
251   HAL_StatusTypeDef status = HAL_OK;
252 
253   /* Check MDF handle */
254   if (hmdf == NULL)
255   {
256     status = HAL_ERROR;
257   }
258   else
259   {
260     /* Check parameters */
261     assert_param(IS_MDF_ALL_INSTANCE(hmdf->Instance));
262     assert_param(IS_MDF_FILTER_BITSTREAM(hmdf->Init.FilterBistream));
263     assert_param(IS_FUNCTIONAL_STATE(hmdf->Init.SerialInterface.Activation));
264 
265     /* Check that instance has not been already initialized */
266     if (v_mdfHandle != NULL)
267     {
268       status = HAL_ERROR;
269     }
270     else
271     {
272 #if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
273       /* Reset callback pointers to the weak predefined callbacks */
274       hmdf->SndLvCallback       = HAL_MDF_SndLvlCallback;
275       hmdf->SadCallback         = HAL_MDF_SadCallback;
276       hmdf->AcqCpltCallback     = HAL_MDF_AcqCpltCallback;
277       hmdf->AcqHalfCpltCallback = HAL_MDF_AcqHalfCpltCallback;
278       hmdf->ErrorCallback       = HAL_MDF_ErrorCallback;
279 
280       /* Call MDF MSP init function */
281       if (hmdf->MspInitCallback == NULL)
282       {
283         hmdf->MspInitCallback = HAL_MDF_MspInit;
284       }
285       hmdf->MspInitCallback(hmdf);
286 #else /* USE_HAL_MDF_REGISTER_CALLBACKS */
287       /* Call MDF MSP init function */
288       HAL_MDF_MspInit(hmdf);
289 #endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
290 
291       /* Configure common parameters */
292       /* Check clock generator status */
293       if ((ADF1->CKGCR & MDF_CKGCR_CKGACTIVE) != 0U)
294       {
295         status = HAL_ERROR;
296       }
297       else
298       {
299         /* Configure processing clock divider, output clock divider,
300            output clock pins and output clock generation trigger */
301         assert_param(IS_MDF_PROC_CLOCK_DIVIDER(hmdf->Init.CommonParam.ProcClockDivider));
302         assert_param(IS_FUNCTIONAL_STATE(hmdf->Init.CommonParam.OutputClock.Activation));
303         ADF1->CKGCR = 0U;
304         ADF1->CKGCR |= ((hmdf->Init.CommonParam.ProcClockDivider - 1U) << MDF_CKGCR_PROCDIV_Pos);
305         if (hmdf->Init.CommonParam.OutputClock.Activation == ENABLE)
306         {
307           assert_param(IS_MDF_OUTPUT_CLOCK_PINS(hmdf->Init.CommonParam.OutputClock.Pins));
308           assert_param(IS_MDF_OUTPUT_CLOCK_DIVIDER(hmdf->Init.CommonParam.OutputClock.Divider));
309           assert_param(IS_FUNCTIONAL_STATE(hmdf->Init.CommonParam.OutputClock.Trigger.Activation));
310           ADF1->CKGCR |= (((hmdf->Init.CommonParam.OutputClock.Divider - 1U) << MDF_CKGCR_CCKDIV_Pos) |
311                           hmdf->Init.CommonParam.OutputClock.Pins |
312                           (hmdf->Init.CommonParam.OutputClock.Pins >> 4U));
313           if (hmdf->Init.CommonParam.OutputClock.Trigger.Activation == ENABLE)
314           {
315             assert_param(IS_MDF_OUTPUT_CLOCK_TRIGGER_SOURCE(hmdf->Init.CommonParam.OutputClock.Trigger.Source));
316             assert_param(IS_MDF_OUTPUT_CLOCK_TRIGGER_EDGE(hmdf->Init.CommonParam.OutputClock.Trigger.Edge));
317             ADF1->CKGCR |= (hmdf->Init.CommonParam.OutputClock.Trigger.Source |
318                             hmdf->Init.CommonParam.OutputClock.Trigger.Edge |
319                             MDF_CKGCR_CKGMOD);
320           }
321         }
322 
323         /* Activate clock generator */
324         ADF1->CKGCR |= MDF_CKGCR_CKGDEN;
325       }
326 
327       /* Configure serial interface */
328       if ((status == HAL_OK) && (hmdf->Init.SerialInterface.Activation == ENABLE))
329       {
330         /* Check serial interface status */
331         if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFACTIVE) != 0U)
332         {
333           status = HAL_ERROR;
334         }
335         else
336         {
337           /* Configure mode, clock source and threshold */
338           assert_param(IS_MDF_SITF_MODE(hmdf->Init.SerialInterface.Mode));
339           assert_param(IS_MDF_SITF_CLOCK_SOURCE(hmdf->Init.SerialInterface.ClockSource));
340           assert_param(IS_MDF_SITF_THRESHOLD(hmdf->Init.SerialInterface.Threshold));
341           hmdf->Instance->SITFCR = 0U;
342           hmdf->Instance->SITFCR |= ((hmdf->Init.SerialInterface.Threshold << MDF_SITFCR_STH_Pos) |
343                                      hmdf->Init.SerialInterface.Mode | hmdf->Init.SerialInterface.ClockSource);
344 
345           /* Activate serial interface */
346           hmdf->Instance->SITFCR |= MDF_SITFCR_SITFEN;
347         }
348       }
349 
350       if (status == HAL_OK)
351       {
352         /* Configure filter bitstream */
353         hmdf->Instance->BSMXCR &= ~(MDF_BSMXCR_BSSEL);
354         hmdf->Instance->BSMXCR |= hmdf->Init.FilterBistream;
355 
356         /* Update instance pointer */
357         v_mdfHandle = hmdf;
358 
359         /* Update error code and state */
360         hmdf->ErrorCode = MDF_ERROR_NONE;
361         hmdf->State     = HAL_MDF_STATE_READY;
362       }
363     }
364   }
365 
366   /* Return function status */
367   return status;
368 }
369 
370 /**
371   * @brief  De-initialize the MDF instance.
372   * @param  hmdf MDF handle.
373   * @retval HAL status.
374   */
HAL_MDF_DeInit(MDF_HandleTypeDef * hmdf)375 HAL_StatusTypeDef HAL_MDF_DeInit(MDF_HandleTypeDef *hmdf)
376 {
377   HAL_StatusTypeDef status = HAL_OK;
378 
379   /* Check MDF handle */
380   if (hmdf == NULL)
381   {
382     status = HAL_ERROR;
383   }
384   else
385   {
386     /* Check parameters */
387     assert_param(IS_MDF_ALL_INSTANCE(hmdf->Instance));
388 
389     /* Check that instance has not been already deinitialized */
390     if (v_mdfHandle == NULL)
391     {
392       status = HAL_ERROR;
393     }
394     else
395     {
396       /* Disable sound activity detector if needed */
397       if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) != 0U)
398       {
399         hmdf->Instance->SADCR &= ~(MDF_SADCR_SADEN);
400       }
401 
402       /* Disable filter if needed */
403       if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_DFLTACTIVE) != 0U)
404       {
405         hmdf->Instance->DFLTCR &= ~(MDF_DFLTCR_DFLTEN);
406       }
407 
408       /* Disable serial interface if needed */
409       if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFACTIVE) != 0U)
410       {
411         hmdf->Instance->SITFCR &= ~(MDF_SITFCR_SITFEN);
412       }
413 
414       /* Disable all interrupts and clear all pending flags */
415       hmdf->Instance->DFLTIER = 0U;
416       hmdf->Instance->DFLTISR = 0xFFFFFFFFU;
417 
418       /* Disable clock generator */
419       ADF1->CKGCR &= ~(MDF_CKGCR_CKGDEN);
420 
421       /* Call MDF MSP deinit function */
422 #if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
423       if (hmdf->MspDeInitCallback == NULL)
424       {
425         hmdf->MspDeInitCallback = HAL_MDF_MspDeInit;
426       }
427       hmdf->MspDeInitCallback(hmdf);
428 #else /* USE_HAL_MDF_REGISTER_CALLBACKS */
429       HAL_MDF_MspDeInit(hmdf);
430 #endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
431 
432       /* Update instance pointer */
433       v_mdfHandle = (MDF_HandleTypeDef *) NULL;
434 
435       /* Update state */
436       hmdf->State = HAL_MDF_STATE_RESET;
437     }
438   }
439 
440   /* Return function status */
441   return status;
442 }
443 
444 /**
445   * @brief  Initialize the MDF instance MSP.
446   * @param  hmdf MDF handle.
447   * @retval None.
448   */
HAL_MDF_MspInit(MDF_HandleTypeDef * hmdf)449 __weak void HAL_MDF_MspInit(MDF_HandleTypeDef *hmdf)
450 {
451   /* Prevent unused argument(s) compilation warning */
452   UNUSED(hmdf);
453 
454   /* NOTE : This function should not be modified, when the function is needed,
455             the HAL_MDF_MspInit could be implemented in the user file */
456 }
457 
458 /**
459   * @brief  De-initialize the MDF instance MSP.
460   * @param  hmdf MDF handle.
461   * @retval None.
462   */
HAL_MDF_MspDeInit(MDF_HandleTypeDef * hmdf)463 __weak void HAL_MDF_MspDeInit(MDF_HandleTypeDef *hmdf)
464 {
465   /* Prevent unused argument(s) compilation warning */
466   UNUSED(hmdf);
467 
468   /* NOTE : This function should not be modified, when the function is needed,
469             the HAL_MDF_MspDeInit could be implemented in the user file */
470 }
471 
472 #if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
473 /**
474   * @brief  Register a user MDF callback to be used instead of the weak predefined callback.
475   * @param  hmdf MDF handle.
476   * @param  CallbackID ID of the callback to be registered.
477   *         This parameter can be one of the following values:
478   *           @arg @ref HAL_MDF_ACQ_COMPLETE_CB_ID acquisition complete callback ID.
479   *           @arg @ref HAL_MDF_ACQ_HALFCOMPLETE_CB_ID acquisition half complete callback ID.
480   *           @arg @ref HAL_MDF_SAD_CB_ID sound activity detector callback ID (only for ADF instance).
481   *           @arg @ref HAL_MDF_ERROR_CB_ID error callback ID.
482   *           @arg @ref HAL_MDF_MSPINIT_CB_ID MSP init callback ID.
483   *           @arg @ref HAL_MDF_MSPDEINIT_CB_ID MSP de-init callback ID.
484   * @param  pCallback pointer to the callback function.
485   * @retval HAL status.
486   */
HAL_MDF_RegisterCallback(MDF_HandleTypeDef * hmdf,HAL_MDF_CallbackIDTypeDef CallbackID,pMDF_CallbackTypeDef pCallback)487 HAL_StatusTypeDef HAL_MDF_RegisterCallback(MDF_HandleTypeDef        *hmdf,
488                                            HAL_MDF_CallbackIDTypeDef CallbackID,
489                                            pMDF_CallbackTypeDef      pCallback)
490 {
491   HAL_StatusTypeDef status = HAL_OK;
492 
493   /* Check parameters */
494   if (pCallback == NULL)
495   {
496     /* Update error code and status */
497     hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
498     status = HAL_ERROR;
499   }
500   else
501   {
502     if (hmdf->State == HAL_MDF_STATE_READY)
503     {
504       switch (CallbackID)
505       {
506         case HAL_MDF_ACQ_COMPLETE_CB_ID :
507           hmdf->AcqCpltCallback = pCallback;
508           break;
509         case HAL_MDF_ACQ_HALFCOMPLETE_CB_ID :
510           hmdf->AcqHalfCpltCallback = pCallback;
511           break;
512         case HAL_MDF_SAD_CB_ID :
513           hmdf->SadCallback = pCallback;
514           break;
515         case HAL_MDF_ERROR_CB_ID :
516           hmdf->ErrorCallback = pCallback;
517           break;
518         case HAL_MDF_MSPINIT_CB_ID :
519           hmdf->MspInitCallback = pCallback;
520           break;
521         case HAL_MDF_MSPDEINIT_CB_ID :
522           hmdf->MspDeInitCallback = pCallback;
523           break;
524         default :
525           /* Update error code and status */
526           hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
527           status = HAL_ERROR;
528           break;
529       }
530     }
531     else if (hmdf->State == HAL_MDF_STATE_RESET)
532     {
533       switch (CallbackID)
534       {
535         case HAL_MDF_MSPINIT_CB_ID :
536           hmdf->MspInitCallback = pCallback;
537           break;
538         case HAL_MDF_MSPDEINIT_CB_ID :
539           hmdf->MspDeInitCallback = pCallback;
540           break;
541         default :
542           /* Update error code and status */
543           hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
544           status = HAL_ERROR;
545           break;
546       }
547     }
548     else
549     {
550       /* Update error code and status */
551       hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
552       status = HAL_ERROR;
553     }
554   }
555 
556   /* Return function status */
557   return status;
558 }
559 
560 /**
561   * @brief  Unregister a user MDF callback.
562   *         MDF callback is redirected to the weak predefined callback.
563   * @param  hmdf MDF handle.
564   * @param  CallbackID ID of the callback to be unregistered.
565   *         This parameter can be one of the following values:
566   *           @arg @ref HAL_MDF_ACQ_COMPLETE_CB_ID acquisition complete callback ID.
567   *           @arg @ref HAL_MDF_ACQ_HALFCOMPLETE_CB_ID acquisition half complete callback ID.
568   *           @arg @ref HAL_MDF_SAD_CB_ID sound activity detector callback ID (only for ADF instance).
569   *           @arg @ref HAL_MDF_ERROR_CB_ID error callback ID.
570   *           @arg @ref HAL_MDF_MSPINIT_CB_ID MSP init callback ID.
571   *           @arg @ref HAL_MDF_MSPDEINIT_CB_ID MSP de-init callback ID.
572   * @retval HAL status.
573   */
HAL_MDF_UnRegisterCallback(MDF_HandleTypeDef * hmdf,HAL_MDF_CallbackIDTypeDef CallbackID)574 HAL_StatusTypeDef HAL_MDF_UnRegisterCallback(MDF_HandleTypeDef        *hmdf,
575                                              HAL_MDF_CallbackIDTypeDef CallbackID)
576 {
577   HAL_StatusTypeDef status = HAL_OK;
578 
579   if (hmdf->State == HAL_MDF_STATE_READY)
580   {
581     switch (CallbackID)
582     {
583       case HAL_MDF_ACQ_COMPLETE_CB_ID :
584         hmdf->AcqCpltCallback = HAL_MDF_AcqCpltCallback;
585         break;
586       case HAL_MDF_ACQ_HALFCOMPLETE_CB_ID :
587         hmdf->AcqHalfCpltCallback = HAL_MDF_AcqHalfCpltCallback;
588         break;
589       case HAL_MDF_SAD_CB_ID :
590         hmdf->SadCallback = HAL_MDF_SadCallback;
591         break;
592       case HAL_MDF_ERROR_CB_ID :
593         hmdf->ErrorCallback = HAL_MDF_ErrorCallback;
594         break;
595       case HAL_MDF_MSPINIT_CB_ID :
596         hmdf->MspInitCallback = HAL_MDF_MspInit;
597         break;
598       case HAL_MDF_MSPDEINIT_CB_ID :
599         hmdf->MspDeInitCallback = HAL_MDF_MspDeInit;
600         break;
601       default :
602         /* Update error code and status */
603         hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
604         status = HAL_ERROR;
605         break;
606     }
607   }
608   else if (hmdf->State == HAL_MDF_STATE_RESET)
609   {
610     switch (CallbackID)
611     {
612       case HAL_MDF_MSPINIT_CB_ID :
613         hmdf->MspInitCallback = HAL_MDF_MspInit;
614         break;
615       case HAL_MDF_MSPDEINIT_CB_ID :
616         hmdf->MspDeInitCallback = HAL_MDF_MspDeInit;
617         break;
618       default :
619         /* Update error code and status */
620         hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
621         status = HAL_ERROR;
622         break;
623     }
624   }
625   else
626   {
627     /* Update error code and status */
628     hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
629     status = HAL_ERROR;
630   }
631 
632   /* Return function status */
633   return status;
634 }
635 
636 /**
637   * @brief  Register specific MDF sound level callback
638   *         to be used instead of the weak predefined callback.
639   * @param  hmdf MDF handle.
640   * @param  pCallback pointer to the sound level callback function.
641   * @retval HAL status.
642   */
HAL_MDF_RegisterSndLvlCallback(MDF_HandleTypeDef * hmdf,pMDF_SndLvlCallbackTypeDef pCallback)643 HAL_StatusTypeDef HAL_MDF_RegisterSndLvlCallback(MDF_HandleTypeDef         *hmdf,
644                                                  pMDF_SndLvlCallbackTypeDef pCallback)
645 {
646   HAL_StatusTypeDef status = HAL_OK;
647 
648   /* Check parameters */
649   if (pCallback == NULL)
650   {
651     /* Update error code and status */
652     hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
653     status = HAL_ERROR;
654   }
655   else
656   {
657     if (hmdf->State == HAL_MDF_STATE_READY)
658     {
659       hmdf->SndLvCallback = pCallback;
660     }
661     else
662     {
663       /* Update error code and status */
664       hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
665       status = HAL_ERROR;
666     }
667   }
668 
669   /* Return function status */
670   return status;
671 }
672 
673 /**
674   * @brief  Unregister the specific MDF sound level callback.
675   *         MDF sound level callback is redirected to the weak predefined callback.
676   * @param  hmdf MDF handle.
677   * @retval HAL status.
678   */
HAL_MDF_UnRegisterSndLvlCallback(MDF_HandleTypeDef * hmdf)679 HAL_StatusTypeDef HAL_MDF_UnRegisterSndLvlCallback(MDF_HandleTypeDef *hmdf)
680 {
681   HAL_StatusTypeDef status = HAL_OK;
682 
683   if (hmdf->State == HAL_MDF_STATE_READY)
684   {
685     hmdf->SndLvCallback = HAL_MDF_SndLvlCallback;
686   }
687   else
688   {
689     /* Update error code and status */
690     hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
691     status = HAL_ERROR;
692   }
693 
694   /* Return function status */
695   return status;
696 }
697 #endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
698 
699 /**
700   * @}
701   */
702 
703 /** @defgroup MDF_Exported_Functions_Group2  Acquisition functions
704   * @brief    Acquisition functions
705   *
706 @verbatim
707   ==============================================================================
708                         ##### Acquisition functions #####
709   ==============================================================================
710     [..]  This section provides functions allowing to :
711       (+) Start and stop acquisition in polling, interrupt or DMA mode.
712       (+) Wait and get acquisition values.
713       (+) Generate pulse on TRGO signal.
714       (+) Modify and get some filter parameters during acquisition.
715       (+) Wait and get sound level values.
716       (+) Detect sound activity.
717 @endverbatim
718   * @{
719   */
720 
721 /**
722   * @brief  This function allows to start acquisition in polling mode.
723   * @param  hmdf MDF handle.
724   * @param  pFilterConfig Filter configuration parameters.
725   * @retval HAL status.
726   */
HAL_MDF_AcqStart(MDF_HandleTypeDef * hmdf,const MDF_FilterConfigTypeDef * pFilterConfig)727 HAL_StatusTypeDef HAL_MDF_AcqStart(MDF_HandleTypeDef *hmdf, const MDF_FilterConfigTypeDef *pFilterConfig)
728 {
729   HAL_StatusTypeDef status = HAL_OK;
730 
731   /* Check parameters */
732   if (pFilterConfig == NULL)
733   {
734     status = HAL_ERROR;
735   }
736   else
737   {
738     assert_param(IS_MDF_ACQUISITION_MODE(pFilterConfig->AcquisitionMode));
739     assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->SoundActivity.Activation));
740     if ((pFilterConfig->SoundActivity.Activation == ENABLE) &&
741         ((pFilterConfig->AcquisitionMode == MDF_MODE_ASYNC_SINGLE) ||
742          (pFilterConfig->AcquisitionMode == MDF_MODE_SYNC_SINGLE) ||
743          (pFilterConfig->AcquisitionMode == MDF_MODE_WINDOW_CONT)))
744     {
745       status = HAL_ERROR;
746     }
747     /* Check state */
748     else if (hmdf->State != HAL_MDF_STATE_READY)
749     {
750       status = HAL_ERROR;
751     }
752     /* Check filter status */
753     else if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_DFLTACTIVE) != 0U)
754     {
755       status = HAL_ERROR;
756     }
757     else
758     {
759       /* Check SAD status */
760       if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) != 0U)
761       {
762         status = HAL_ERROR;
763       }
764     }
765 
766     if (status == HAL_OK)
767     {
768       /* Configure filter and start acquisition */
769       hmdf->Instance->DFLTCR = 0U;
770       MDF_AcqStart(hmdf, pFilterConfig);
771     }
772   }
773 
774   /* Return function status */
775   return status;
776 }
777 
778 /**
779   * @brief  This function allows to poll for available acquisition value.
780   * @param  hmdf MDF handle.
781   * @param  Timeout Timeout value in milliseconds.
782   * @retval HAL status.
783   */
HAL_MDF_PollForAcq(MDF_HandleTypeDef * hmdf,uint32_t Timeout)784 HAL_StatusTypeDef HAL_MDF_PollForAcq(MDF_HandleTypeDef *hmdf, uint32_t Timeout)
785 {
786   HAL_StatusTypeDef status = HAL_OK;
787 
788   /* Check state */
789   if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
790   {
791     status = HAL_ERROR;
792   }
793   else
794   {
795     uint32_t tickstart = HAL_GetTick();
796 
797     /* Wait for available acquisition value */
798     while (((hmdf->Instance->DFLTISR & MDF_DFLTISR_RXNEF) != MDF_DFLTISR_RXNEF) && (status == HAL_OK))
799     {
800       /* Check the timeout */
801       if (Timeout != HAL_MAX_DELAY)
802       {
803         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
804         {
805           status = HAL_TIMEOUT;
806         }
807       }
808     }
809 
810     /* Check if data overflow, saturation or reshape filter occurs */
811     uint32_t error_flags = (hmdf->Instance->DFLTISR & (MDF_DFLTISR_DOVRF | MDF_DFLTISR_SATF | MDF_DFLTISR_RFOVRF));
812     if (error_flags != 0U)
813     {
814       /* Update error code */
815       if ((error_flags & MDF_DFLTISR_DOVRF) == MDF_DFLTISR_DOVRF)
816       {
817         hmdf->ErrorCode |= MDF_ERROR_ACQUISITION_OVERFLOW;
818       }
819       if ((error_flags & MDF_DFLTISR_SATF) == MDF_DFLTISR_SATF)
820       {
821         hmdf->ErrorCode |= MDF_ERROR_SATURATION;
822       }
823       if ((error_flags & MDF_DFLTISR_RFOVRF) == MDF_DFLTISR_RFOVRF)
824       {
825         hmdf->ErrorCode |= MDF_ERROR_RSF_OVERRUN;
826       }
827 
828       /* Clear corresponding flags */
829       hmdf->Instance->DFLTISR |= error_flags;
830 
831       /* Call error callback */
832 #if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
833       hmdf->ErrorCallback(hmdf);
834 #else /* USE_HAL_MDF_REGISTER_CALLBACKS */
835       HAL_MDF_ErrorCallback(hmdf);
836 #endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
837     }
838 
839     if (status == HAL_OK)
840     {
841       /* Update state only in asynchronous single shot mode */
842       if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_ACQMOD) == MDF_MODE_ASYNC_SINGLE)
843       {
844         hmdf->State = HAL_MDF_STATE_READY;
845       }
846     }
847   }
848 
849   /* Return function status */
850   return status;
851 }
852 
853 /**
854   * @brief  This function allows to get acquisition value.
855   * @param  hmdf MDF handle.
856   * @param  pValue Acquisition value on 24 MSB.
857   * @retval HAL status.
858   */
HAL_MDF_GetAcqValue(const MDF_HandleTypeDef * hmdf,int32_t * pValue)859 HAL_StatusTypeDef HAL_MDF_GetAcqValue(const MDF_HandleTypeDef *hmdf, int32_t *pValue)
860 {
861   HAL_StatusTypeDef status = HAL_OK;
862 
863   /* Check parameters */
864   if (pValue == NULL)
865   {
866     status = HAL_ERROR;
867   }
868   else
869   {
870     /* Check state */
871     if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
872     {
873       if (hmdf->State != HAL_MDF_STATE_READY)
874       {
875         status = HAL_ERROR;
876       }
877     }
878   }
879 
880   if (status == HAL_OK)
881   {
882     /* Get acquisition value */
883     *pValue = (int32_t) hmdf->Instance->DFLTDR;
884   }
885 
886   /* Return function status */
887   return status;
888 }
889 
890 /**
891   * @brief  This function allows to stop acquisition in polling mode.
892   * @param  hmdf MDF handle.
893   * @retval HAL status.
894   */
HAL_MDF_AcqStop(MDF_HandleTypeDef * hmdf)895 HAL_StatusTypeDef HAL_MDF_AcqStop(MDF_HandleTypeDef *hmdf)
896 {
897   HAL_StatusTypeDef status = HAL_OK;
898 
899   /* Check state */
900   if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
901   {
902     /* Check if state is ready and filter active */
903     if (hmdf->State == HAL_MDF_STATE_READY)
904     {
905       if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_DFLTACTIVE) != MDF_DFLTCR_DFLTACTIVE)
906       {
907         status = HAL_ERROR;
908       }
909     }
910     else
911     {
912       status = HAL_ERROR;
913     }
914   }
915   else
916   {
917     /* Disable sound activity detector if needed */
918     if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) != 0U)
919     {
920       hmdf->Instance->SADCR &= ~(MDF_SADCR_SADEN);
921     }
922   }
923 
924   if (status == HAL_OK)
925   {
926     /* Disable filter */
927     hmdf->Instance->DFLTCR &= ~(MDF_DFLTCR_DFLTEN);
928 
929     /* Clear all potential pending flags */
930     hmdf->Instance->DFLTISR |= (MDF_DFLTISR_DOVRF | MDF_DFLTISR_SATF | MDF_DFLTISR_RFOVRF |
931                                 MDF_DFLTISR_SDDETF | MDF_DFLTISR_SDLVLF);
932 
933     /* Update state */
934     hmdf->State = HAL_MDF_STATE_READY;
935   }
936 
937   /* Return function status */
938   return status;
939 }
940 
941 /**
942   * @brief  This function allows to start acquisition in interrupt mode.
943   * @param  hmdf MDF handle.
944   * @param  pFilterConfig Filter configuration parameters.
945   * @retval HAL status.
946   */
HAL_MDF_AcqStart_IT(MDF_HandleTypeDef * hmdf,const MDF_FilterConfigTypeDef * pFilterConfig)947 HAL_StatusTypeDef HAL_MDF_AcqStart_IT(MDF_HandleTypeDef *hmdf, const MDF_FilterConfigTypeDef *pFilterConfig)
948 {
949   HAL_StatusTypeDef status = HAL_OK;
950 
951   /* Check parameters */
952   if (pFilterConfig == NULL)
953   {
954     status = HAL_ERROR;
955   }
956   else
957   {
958     assert_param(IS_MDF_ACQUISITION_MODE(pFilterConfig->AcquisitionMode));
959     assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->SoundActivity.Activation));
960     if ((pFilterConfig->SoundActivity.Activation == ENABLE) &&
961         ((pFilterConfig->AcquisitionMode == MDF_MODE_ASYNC_SINGLE) ||
962          (pFilterConfig->AcquisitionMode == MDF_MODE_SYNC_SINGLE) ||
963          (pFilterConfig->AcquisitionMode == MDF_MODE_WINDOW_CONT)))
964     {
965       status = HAL_ERROR;
966     }
967     /* Check state */
968     else if (hmdf->State != HAL_MDF_STATE_READY)
969     {
970       status = HAL_ERROR;
971     }
972     /* Check filter status */
973     else if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_DFLTACTIVE) != 0U)
974     {
975       status = HAL_ERROR;
976     }
977     else
978     {
979       /* Check SAD status */
980       if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) != 0U)
981       {
982         status = HAL_ERROR;
983       }
984     }
985 
986     if (status == HAL_OK)
987     {
988       if ((pFilterConfig->SoundActivity.Activation == DISABLE) ||
989           (pFilterConfig->SoundActivity.DataMemoryTransfer != MDF_SAD_NO_MEMORY_TRANSFER))
990       {
991         /* Enable data overflow and fifo threshold interrupts */
992         hmdf->Instance->DFLTIER |= (MDF_DFLTIER_DOVRIE | MDF_DFLTIER_FTHIE);
993       }
994 
995       if (pFilterConfig->ReshapeFilter.Activation == ENABLE)
996       {
997         /* Enable reshape filter overrun interrupt */
998         hmdf->Instance->DFLTIER |= MDF_DFLTIER_RFOVRIE;
999       }
1000 
1001       /* Enable saturation interrupt */
1002       hmdf->Instance->DFLTIER |= MDF_DFLTIER_SATIE;
1003 
1004       if (pFilterConfig->SoundActivity.Activation == ENABLE)
1005       {
1006         /* Enable sound level value ready and sound activity detection interrupts */
1007         assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->SoundActivity.SoundLevelInterrupt));
1008         hmdf->Instance->DFLTIER |= (pFilterConfig->SoundActivity.SoundLevelInterrupt == ENABLE) ?
1009                                    (MDF_DFLTIER_SDLVLIE | MDF_DFLTIER_SDDETIE) :
1010                                    MDF_DFLTIER_SDDETIE;
1011       }
1012 
1013       /* Configure filter and start acquisition */
1014       hmdf->Instance->DFLTCR = 0U;
1015       MDF_AcqStart(hmdf, pFilterConfig);
1016     }
1017   }
1018 
1019   /* Return function status */
1020   return status;
1021 }
1022 
1023 /**
1024   * @brief  This function allows to stop acquisition in interrupt mode.
1025   * @param  hmdf MDF handle.
1026   * @retval HAL status.
1027   */
HAL_MDF_AcqStop_IT(MDF_HandleTypeDef * hmdf)1028 HAL_StatusTypeDef HAL_MDF_AcqStop_IT(MDF_HandleTypeDef *hmdf)
1029 {
1030   HAL_StatusTypeDef status = HAL_OK;
1031 
1032   /* Check state */
1033   if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
1034   {
1035     /* Check if state is ready and filter active */
1036     if (hmdf->State == HAL_MDF_STATE_READY)
1037     {
1038       if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_DFLTACTIVE) != MDF_DFLTCR_DFLTACTIVE)
1039       {
1040         status = HAL_ERROR;
1041       }
1042     }
1043     else
1044     {
1045       status = HAL_ERROR;
1046     }
1047   }
1048   else
1049   {
1050     /* Disable sound activity detector if needed */
1051     if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) != 0U)
1052     {
1053       hmdf->Instance->SADCR &= ~(MDF_SADCR_SADEN);
1054     }
1055   }
1056 
1057   if (status == HAL_OK)
1058   {
1059     /* Disable filter */
1060     hmdf->Instance->DFLTCR &= ~(MDF_DFLTCR_DFLTEN);
1061 
1062     /* Disable interrupts and clear all potential pending flags */
1063     hmdf->Instance->DFLTIER &= ~(MDF_DFLTIER_FTHIE | MDF_DFLTIER_DOVRIE | MDF_DFLTIER_SATIE |
1064                                  MDF_DFLTIER_RFOVRIE | MDF_DFLTIER_SDDETIE | MDF_DFLTIER_SDLVLIE);
1065     hmdf->Instance->DFLTISR |= (MDF_DFLTISR_DOVRF | MDF_DFLTISR_SATF | MDF_DFLTISR_RFOVRF |
1066                                 MDF_DFLTISR_SDDETF | MDF_DFLTISR_SDLVLF);
1067 
1068     /* Update state */
1069     hmdf->State = HAL_MDF_STATE_READY;
1070   }
1071 
1072   /* Return function status */
1073   return status;
1074 }
1075 
1076 /**
1077   * @brief  This function allows to start acquisition in DMA mode.
1078   * @param  hmdf MDF handle.
1079   * @param  pFilterConfig Filter configuration parameters.
1080   * @param  pDmaConfig DMA configuration parameters.
1081   * @retval HAL status.
1082   */
HAL_MDF_AcqStart_DMA(MDF_HandleTypeDef * hmdf,const MDF_FilterConfigTypeDef * pFilterConfig,const MDF_DmaConfigTypeDef * pDmaConfig)1083 HAL_StatusTypeDef HAL_MDF_AcqStart_DMA(MDF_HandleTypeDef *hmdf, const MDF_FilterConfigTypeDef *pFilterConfig,
1084                                        const MDF_DmaConfigTypeDef *pDmaConfig)
1085 {
1086   HAL_StatusTypeDef status = HAL_OK;
1087 
1088   /* Check parameters */
1089   if ((pFilterConfig == NULL) || (pDmaConfig == NULL))
1090   {
1091     status = HAL_ERROR;
1092   }
1093   else
1094   {
1095     assert_param(IS_FUNCTIONAL_STATE(pDmaConfig->MsbOnly));
1096     assert_param(IS_MDF_ACQUISITION_MODE(pFilterConfig->AcquisitionMode));
1097     assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->SoundActivity.Activation));
1098     if ((pFilterConfig->SoundActivity.Activation == ENABLE) &&
1099         ((pFilterConfig->AcquisitionMode == MDF_MODE_ASYNC_SINGLE) ||
1100          (pFilterConfig->AcquisitionMode == MDF_MODE_SYNC_SINGLE) ||
1101          (pFilterConfig->AcquisitionMode == MDF_MODE_WINDOW_CONT)))
1102     {
1103       status = HAL_ERROR;
1104     }
1105     /* Check state */
1106     else if (hmdf->State != HAL_MDF_STATE_READY)
1107     {
1108       status = HAL_ERROR;
1109     }
1110     /* Check filter status */
1111     else if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_DFLTACTIVE) != 0U)
1112     {
1113       status = HAL_ERROR;
1114     }
1115     else
1116     {
1117       /* Check SAD status */
1118       if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) != 0U)
1119       {
1120         status = HAL_ERROR;
1121       }
1122     }
1123 
1124     if (status == HAL_OK)
1125     {
1126       uint32_t SrcAddress;
1127 
1128       if (pFilterConfig->ReshapeFilter.Activation == ENABLE)
1129       {
1130         /* Enable reshape filter overrun interrupt */
1131         hmdf->Instance->DFLTIER |= MDF_DFLTIER_RFOVRIE;
1132       }
1133 
1134       /* Enable saturation interrupt */
1135       hmdf->Instance->DFLTIER |= MDF_DFLTIER_SATIE;
1136 
1137       if (pFilterConfig->SoundActivity.Activation == ENABLE)
1138       {
1139         /* Enable sound level value ready and sound activity detection interrupts */
1140         assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->SoundActivity.SoundLevelInterrupt));
1141         hmdf->Instance->DFLTIER |= (pFilterConfig->SoundActivity.SoundLevelInterrupt == ENABLE) ?
1142                                    (MDF_DFLTIER_SDLVLIE | MDF_DFLTIER_SDDETIE) :
1143                                    MDF_DFLTIER_SDDETIE;
1144       }
1145 
1146       /* Enable MDF DMA requests */
1147       hmdf->Instance->DFLTCR = MDF_DFLTCR_DMAEN;
1148 
1149       /* Start DMA transfer */
1150       hmdf->hdma->XferCpltCallback     = MDF_DmaXferCpltCallback;
1151       hmdf->hdma->XferHalfCpltCallback = MDF_DmaXferHalfCpltCallback;
1152       hmdf->hdma->XferErrorCallback    = MDF_DmaErrorCallback;
1153       SrcAddress = (pDmaConfig->MsbOnly == ENABLE) ? (((uint32_t) &hmdf->Instance->DFLTDR) + 2U) :
1154                    (uint32_t) &hmdf->Instance->DFLTDR;
1155       if ((hmdf->hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
1156       {
1157         if (hmdf->hdma->LinkedListQueue != NULL)
1158         {
1159           hmdf->hdma->LinkedListQueue->Head->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = pDmaConfig->DataLength;
1160           hmdf->hdma->LinkedListQueue->Head->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = SrcAddress;
1161           hmdf->hdma->LinkedListQueue->Head->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = pDmaConfig->Address;
1162 
1163           status = HAL_DMAEx_List_Start_IT(hmdf->hdma);
1164         }
1165         else
1166         {
1167           status = HAL_ERROR;
1168         }
1169       }
1170       else
1171       {
1172         status = HAL_DMA_Start_IT(hmdf->hdma, SrcAddress, pDmaConfig->Address, pDmaConfig->DataLength);
1173       }
1174       if (status != HAL_OK)
1175       {
1176         /* Update state */
1177         hmdf->State = HAL_MDF_STATE_ERROR;
1178         status = HAL_ERROR;
1179       }
1180       else
1181       {
1182         /* Configure filter and start acquisition */
1183         MDF_AcqStart(hmdf, pFilterConfig);
1184       }
1185     }
1186   }
1187 
1188   /* Return function status */
1189   return status;
1190 }
1191 
1192 /**
1193   * @brief  This function allows to stop acquisition in DMA mode.
1194   * @param  hmdf MDF handle.
1195   * @retval HAL status.
1196   */
HAL_MDF_AcqStop_DMA(MDF_HandleTypeDef * hmdf)1197 HAL_StatusTypeDef HAL_MDF_AcqStop_DMA(MDF_HandleTypeDef *hmdf)
1198 {
1199   HAL_StatusTypeDef status = HAL_OK;
1200 
1201   /* Check if state is ready and filter active */
1202   if (hmdf->State == HAL_MDF_STATE_READY)
1203   {
1204     if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_DFLTACTIVE) != MDF_DFLTCR_DFLTACTIVE)
1205     {
1206       status = HAL_ERROR;
1207     }
1208   }
1209   else
1210   {
1211     /* Check state */
1212     if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
1213     {
1214       status = HAL_ERROR;
1215     }
1216     else
1217     {
1218       /* Stop the DMA transfer */
1219       if (HAL_DMA_Abort(hmdf->hdma) != HAL_OK)
1220       {
1221         /* Update state */
1222         hmdf->State = HAL_MDF_STATE_ERROR;
1223         status = HAL_ERROR;
1224       }
1225     }
1226   }
1227 
1228   if (status == HAL_OK)
1229   {
1230     /* Disable sound activity detector if needed */
1231     if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) != 0U)
1232     {
1233       hmdf->Instance->SADCR &= ~(MDF_SADCR_SADEN);
1234     }
1235 
1236     /* Disable filter */
1237     hmdf->Instance->DFLTCR &= ~(MDF_DFLTCR_DFLTEN);
1238 
1239     /* Disable interrupts and clear all potential pending flags */
1240     hmdf->Instance->DFLTIER &= ~(MDF_DFLTIER_SATIE | MDF_DFLTIER_RFOVRIE | MDF_DFLTIER_SDDETIE |
1241                                  MDF_DFLTIER_SDLVLIE);
1242     hmdf->Instance->DFLTISR |= (MDF_DFLTISR_SATF | MDF_DFLTISR_RFOVRF | MDF_DFLTISR_SDDETF |
1243                                 MDF_DFLTISR_SDLVLF);
1244 
1245     /* Disable MDF DMA requests */
1246     hmdf->Instance->DFLTCR &= ~(MDF_DFLTCR_DMAEN);
1247 
1248     /* Update state */
1249     hmdf->State = HAL_MDF_STATE_READY;
1250   }
1251 
1252   /* Return function status */
1253   return status;
1254 }
1255 
1256 /**
1257   * @brief  This function allows to generate pulse on TRGO signal.
1258   * @param  hmdf MDF handle.
1259   * @retval HAL status.
1260   */
HAL_MDF_GenerateTrgo(const MDF_HandleTypeDef * hmdf)1261 HAL_StatusTypeDef HAL_MDF_GenerateTrgo(const MDF_HandleTypeDef *hmdf)
1262 {
1263   HAL_StatusTypeDef status = HAL_OK;
1264 
1265   /* Check state */
1266   if (hmdf->State != HAL_MDF_STATE_READY)
1267   {
1268     if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
1269     {
1270       status = HAL_ERROR;
1271     }
1272   }
1273 
1274   if (status == HAL_OK)
1275   {
1276     /* Check if trigger output control is already active */
1277     if ((ADF1->GCR & MDF_GCR_TRGO) == MDF_GCR_TRGO)
1278     {
1279       status = HAL_ERROR;
1280     }
1281     else
1282     {
1283       /* Generate pulse on trigger output control signal */
1284       ADF1->GCR |= MDF_GCR_TRGO;
1285     }
1286   }
1287 
1288   /* Return function status */
1289   return status;
1290 }
1291 
1292 /**
1293   * @brief  This function allows to set delay to apply on data source in number of samples.
1294   * @param  hmdf MDF handle.
1295   * @param  Delay Delay to apply on data source in number of samples.
1296   *         This parameter must be a number between Min_Data = 0 and Max_Data = 127.
1297   * @retval HAL status.
1298   */
HAL_MDF_SetDelay(MDF_HandleTypeDef * hmdf,uint32_t Delay)1299 HAL_StatusTypeDef HAL_MDF_SetDelay(MDF_HandleTypeDef *hmdf, uint32_t Delay)
1300 {
1301   HAL_StatusTypeDef status = HAL_OK;
1302 
1303   /* Check parameters */
1304   assert_param(IS_MDF_DELAY(Delay));
1305 
1306   /* Check state */
1307   if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
1308   {
1309     status = HAL_ERROR;
1310   }
1311   else
1312   {
1313     /* Check if bitstream delay is already active */
1314     if ((hmdf->Instance->DLYCR & MDF_DLYCR_SKPBF) == MDF_DLYCR_SKPBF)
1315     {
1316       status = HAL_ERROR;
1317     }
1318     else
1319     {
1320       /* Configure bitstream delay */
1321       hmdf->Instance->DLYCR |= Delay;
1322     }
1323   }
1324 
1325   /* Return function status */
1326   return status;
1327 }
1328 
1329 /**
1330   * @brief  This function allows to get current delay applied on data source in number of samples.
1331   * @param  hmdf MDF handle.
1332   * @param  pDelay Current delay applied on data source in number of samples.
1333   *         This value is between Min_Data = 0 and Max_Data = 127.
1334   * @retval HAL status.
1335   */
HAL_MDF_GetDelay(const MDF_HandleTypeDef * hmdf,uint32_t * pDelay)1336 HAL_StatusTypeDef HAL_MDF_GetDelay(const MDF_HandleTypeDef *hmdf, uint32_t *pDelay)
1337 {
1338   HAL_StatusTypeDef status = HAL_OK;
1339 
1340   /* Check parameters */
1341   if (pDelay == NULL)
1342   {
1343     status = HAL_ERROR;
1344   }
1345   /* Check state */
1346   else if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
1347   {
1348     status = HAL_ERROR;
1349   }
1350   else
1351   {
1352     /* Get current bitstream delay */
1353     *pDelay = (hmdf->Instance->DLYCR & MDF_DLYCR_SKPDLY);
1354   }
1355 
1356   /* Return function status */
1357   return status;
1358 }
1359 
1360 /**
1361   * @brief  This function allows to set filter gain.
1362   * @param  hmdf MDF handle.
1363   * @param  Gain Filter gain in step of around 3db (from -48db to 72dB).
1364   *         This parameter must be a number between Min_Data = -16 and Max_Data = 24.
1365   * @retval HAL status.
1366   */
HAL_MDF_SetGain(MDF_HandleTypeDef * hmdf,int32_t Gain)1367 HAL_StatusTypeDef HAL_MDF_SetGain(MDF_HandleTypeDef *hmdf, int32_t Gain)
1368 {
1369   HAL_StatusTypeDef status = HAL_OK;
1370 
1371   /* Check parameters */
1372   assert_param(IS_MDF_GAIN(Gain));
1373 
1374   /* Check state */
1375   if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
1376   {
1377     status = HAL_ERROR;
1378   }
1379   else
1380   {
1381     uint32_t register_gain_value;
1382     uint32_t tmp_register;
1383 
1384     if (Gain < 0)
1385     {
1386       int32_t adjust_gain;
1387 
1388       /* adjust gain value to set on register for negative value (offset of -16) */
1389       adjust_gain = Gain - 16;
1390       register_gain_value = ((uint32_t) adjust_gain & 0x3FU);
1391     }
1392     else
1393     {
1394       /* for positive value, no offset to apply */
1395       register_gain_value = (uint32_t) Gain;
1396     }
1397     /* Set gain */
1398     tmp_register = (hmdf->Instance->DFLTCICR & ~(MDF_DFLTCICR_SCALE));
1399     hmdf->Instance->DFLTCICR = (tmp_register | (register_gain_value << MDF_DFLTCICR_SCALE_Pos));
1400   }
1401 
1402   /* Return function status */
1403   return status;
1404 }
1405 
1406 /**
1407   * @brief  This function allows to get filter gain.
1408   * @param  hmdf MDF handle.
1409   * @param  pGain Filter gain in step of around 3db (from -48db to 72dB).
1410   *         This parameter is between Min_Data = -16 and Max_Data = 24.
1411   * @retval HAL status.
1412   */
HAL_MDF_GetGain(const MDF_HandleTypeDef * hmdf,int32_t * pGain)1413 HAL_StatusTypeDef HAL_MDF_GetGain(const MDF_HandleTypeDef *hmdf, int32_t *pGain)
1414 {
1415   HAL_StatusTypeDef status = HAL_OK;
1416 
1417   /* Check parameters */
1418   if (pGain == NULL)
1419   {
1420     status = HAL_ERROR;
1421   }
1422   /* Check state */
1423   else if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
1424   {
1425     status = HAL_ERROR;
1426   }
1427   else
1428   {
1429     uint32_t register_gain_value;
1430 
1431     /* Get current gain */
1432     register_gain_value = ((hmdf->Instance->DFLTCICR & MDF_DFLTCICR_SCALE) >> MDF_DFLTCICR_SCALE_Pos);
1433     if (register_gain_value > 31U)
1434     {
1435       /* adjust gain value to set on register for negative value (offset of +16) */
1436       register_gain_value |= 0xFFFFFFC0U;
1437       *pGain = (int32_t) register_gain_value + 16;
1438     }
1439     else
1440     {
1441       /* for positive value, no offset to apply */
1442       *pGain = (int32_t) register_gain_value;
1443     }
1444   }
1445 
1446   /* Return function status */
1447   return status;
1448 }
1449 
1450 /**
1451   * @brief  This function allows to poll for sound level data.
1452   * @param  hmdf MDF handle.
1453   * @param  Timeout Timeout value in milliseconds.
1454   * @param  pSoundLevel Sound level.
1455             This parameter can be a value between Min_Data = 0 and Max_Data = 32767.
1456   * @param  pAmbientNoise Ambient noise.
1457             This parameter can be a value between Min_Data = 0 and Max_Data = 32767.
1458   * @retval HAL status.
1459   */
HAL_MDF_PollForSndLvl(MDF_HandleTypeDef * hmdf,uint32_t Timeout,uint32_t * pSoundLevel,uint32_t * pAmbientNoise)1460 HAL_StatusTypeDef HAL_MDF_PollForSndLvl(MDF_HandleTypeDef *hmdf, uint32_t Timeout, uint32_t *pSoundLevel,
1461                                         uint32_t *pAmbientNoise)
1462 {
1463   HAL_StatusTypeDef status = HAL_OK;
1464 
1465   /* Check parameters */
1466   if ((pSoundLevel == NULL) || (pAmbientNoise == NULL))
1467   {
1468     status = HAL_ERROR;
1469   }
1470   /* Check state */
1471   else if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
1472   {
1473     status = HAL_ERROR;
1474   }
1475   /* Check SAD status */
1476   else if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) == 0U)
1477   {
1478     status = HAL_ERROR;
1479   }
1480   else
1481   {
1482     uint32_t tickstart = HAL_GetTick();
1483 
1484     /* Wait for available sound level data */
1485     while (((hmdf->Instance->DFLTISR & MDF_DFLTISR_SDLVLF) != MDF_DFLTISR_SDLVLF) && (status == HAL_OK))
1486     {
1487       /* Check the timeout */
1488       if (Timeout != HAL_MAX_DELAY)
1489       {
1490         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
1491         {
1492           status = HAL_TIMEOUT;
1493         }
1494       }
1495     }
1496 
1497     if (status == HAL_OK)
1498     {
1499       /* Get sound level */
1500       *pSoundLevel = hmdf->Instance->SADSDLVR;
1501 
1502       /* Get ambient noise */
1503       *pAmbientNoise = hmdf->Instance->SADANLVR;
1504 
1505       /* Clear sound level ready flag */
1506       hmdf->Instance->DFLTISR |= MDF_DFLTISR_SDLVLF;
1507     }
1508   }
1509 
1510   /* Return function status */
1511   return status;
1512 }
1513 
1514 /**
1515   * @brief  This function allows to poll for sound activity detection.
1516   * @param  hmdf MDF handle.
1517   * @param  Timeout Timeout value in milliseconds.
1518   * @retval HAL status.
1519   */
HAL_MDF_PollForSad(MDF_HandleTypeDef * hmdf,uint32_t Timeout)1520 HAL_StatusTypeDef HAL_MDF_PollForSad(MDF_HandleTypeDef *hmdf, uint32_t Timeout)
1521 {
1522   HAL_StatusTypeDef status = HAL_OK;
1523 
1524   /* Check state */
1525   if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
1526   {
1527     status = HAL_ERROR;
1528   }
1529   /* Check SAD status */
1530   else if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) == 0U)
1531   {
1532     status = HAL_ERROR;
1533   }
1534   else
1535   {
1536     uint32_t tickstart = HAL_GetTick();
1537 
1538     /* Wait for sound activity detection */
1539     while (((hmdf->Instance->DFLTISR & MDF_DFLTISR_SDDETF) != MDF_DFLTISR_SDDETF) && (status == HAL_OK))
1540     {
1541       /* Check the timeout */
1542       if (Timeout != HAL_MAX_DELAY)
1543       {
1544         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
1545         {
1546           status = HAL_TIMEOUT;
1547         }
1548       }
1549     }
1550 
1551     if (status == HAL_OK)
1552     {
1553       /* Clear sound activity detection flag */
1554       hmdf->Instance->DFLTISR |= MDF_DFLTISR_SDDETF;
1555     }
1556   }
1557 
1558   /* Return function status */
1559   return status;
1560 }
1561 
1562 /**
1563   * @brief  MDF acquisition complete callback.
1564   * @param  hmdf MDF handle.
1565   * @retval None.
1566   */
HAL_MDF_AcqCpltCallback(MDF_HandleTypeDef * hmdf)1567 __weak void HAL_MDF_AcqCpltCallback(MDF_HandleTypeDef *hmdf)
1568 {
1569   /* Prevent unused argument(s) compilation warning */
1570   UNUSED(hmdf);
1571 
1572   /* NOTE : This function should not be modified, when the function is needed,
1573             the HAL_MDF_AcqCpltCallback could be implemented in the user file */
1574 }
1575 
1576 /**
1577   * @brief  MDF acquisition half complete callback.
1578   * @param  hmdf MDF handle.
1579   * @retval None.
1580   */
HAL_MDF_AcqHalfCpltCallback(MDF_HandleTypeDef * hmdf)1581 __weak void HAL_MDF_AcqHalfCpltCallback(MDF_HandleTypeDef *hmdf)
1582 {
1583   /* Prevent unused argument(s) compilation warning */
1584   UNUSED(hmdf);
1585 
1586   /* NOTE : This function should not be modified, when the function is needed,
1587             the HAL_MDF_AcqHalfCpltCallback could be implemented in the user file */
1588 }
1589 
1590 /**
1591   * @brief  MDF sound level callback.
1592   * @param  hmdf MDF handle.
1593   * @param  SoundLevel Sound level value computed by sound activity detector.
1594   *         This parameter can be a value between Min_Data = 0 and Max_Data = 32767.
1595   * @param  AmbientNoise Ambient noise value computed by sound activity detector.
1596   *         This parameter can be a value between Min_Data = 0 and Max_Data = 32767.
1597   * @retval None.
1598   */
HAL_MDF_SndLvlCallback(MDF_HandleTypeDef * hmdf,uint32_t SoundLevel,uint32_t AmbientNoise)1599 __weak void HAL_MDF_SndLvlCallback(MDF_HandleTypeDef *hmdf, uint32_t SoundLevel, uint32_t AmbientNoise)
1600 {
1601   /* Prevent unused argument(s) compilation warning */
1602   UNUSED(hmdf);
1603   UNUSED(SoundLevel);
1604   UNUSED(AmbientNoise);
1605 
1606   /* NOTE : This function should not be modified, when the function is needed,
1607             the HAL_MDF_SndLvlCallback could be implemented in the user file */
1608 }
1609 
1610 /**
1611   * @brief  MDF sound activity detector callback.
1612   * @param  hmdf MDF handle.
1613   * @retval None.
1614   */
HAL_MDF_SadCallback(MDF_HandleTypeDef * hmdf)1615 __weak void HAL_MDF_SadCallback(MDF_HandleTypeDef *hmdf)
1616 {
1617   /* Prevent unused argument(s) compilation warning */
1618   UNUSED(hmdf);
1619 
1620   /* NOTE : This function should not be modified, when the function is needed,
1621             the HAL_MDF_SadCallback could be implemented in the user file */
1622 }
1623 
1624 /**
1625   * @}
1626   */
1627 
1628 /** @defgroup MDF_Exported_Functions_Group3  Clock absence detection functions
1629   * @brief    Clock absence detection functions
1630   *
1631 @verbatim
1632   ==============================================================================
1633                   ##### Clock absence detection functions #####
1634   ==============================================================================
1635     [..]  This section provides functions allowing to :
1636       (+) Start and stop clock absence detection in interrupt mode.
1637       (+) Detect clock absence.
1638 @endverbatim
1639   * @{
1640   */
1641 
1642 /**
1643   * @brief  This function allows to poll for the clock absence detection.
1644   * @param  hmdf MDF handle.
1645   * @param  Timeout Timeout value in milliseconds.
1646   * @retval HAL status.
1647   */
HAL_MDF_PollForCkab(MDF_HandleTypeDef * hmdf,uint32_t Timeout)1648 HAL_StatusTypeDef HAL_MDF_PollForCkab(MDF_HandleTypeDef *hmdf, uint32_t Timeout)
1649 {
1650   HAL_StatusTypeDef status = HAL_OK;
1651 
1652   /* Check state */
1653   if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
1654   {
1655     if (hmdf->State != HAL_MDF_STATE_READY)
1656     {
1657       status = HAL_ERROR;
1658     }
1659   }
1660 
1661   if (status == HAL_OK)
1662   {
1663     /* Check serial interface status and mode */
1664     if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFACTIVE) == 0U)
1665     {
1666       status = HAL_ERROR;
1667     }
1668     else
1669     {
1670       if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFMOD) != MDF_SITF_NORMAL_SPI_MODE)
1671       {
1672         status = HAL_ERROR;
1673       }
1674     }
1675   }
1676 
1677   if (status == HAL_OK)
1678   {
1679     uint32_t tickstart = HAL_GetTick();
1680 
1681     /* Wait for clock absence detection */
1682     while (((hmdf->Instance->DFLTISR & MDF_DFLTISR_CKABF) != MDF_DFLTISR_CKABF) && (status == HAL_OK))
1683     {
1684       /* Check the timeout */
1685       if (Timeout != HAL_MAX_DELAY)
1686       {
1687         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
1688         {
1689           status = HAL_TIMEOUT;
1690         }
1691       }
1692     }
1693 
1694     if (status == HAL_OK)
1695     {
1696       /* Clear clock absence detection flag */
1697       hmdf->Instance->DFLTISR |= MDF_DFLTISR_CKABF;
1698     }
1699   }
1700 
1701   /* Return function status */
1702   return status;
1703 }
1704 
1705 /**
1706   * @brief  This function allows to start clock absence detection in interrupt mode.
1707   * @param  hmdf MDF handle.
1708   * @retval HAL status.
1709   */
HAL_MDF_CkabStart_IT(MDF_HandleTypeDef * hmdf)1710 HAL_StatusTypeDef HAL_MDF_CkabStart_IT(MDF_HandleTypeDef *hmdf)
1711 {
1712   HAL_StatusTypeDef status = HAL_OK;
1713 
1714   /* Check state */
1715   if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
1716   {
1717     if (hmdf->State != HAL_MDF_STATE_READY)
1718     {
1719       status = HAL_ERROR;
1720     }
1721   }
1722 
1723   if (status == HAL_OK)
1724   {
1725     /* Check serial interface status and mode */
1726     if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFACTIVE) == 0U)
1727     {
1728       status = HAL_ERROR;
1729     }
1730     else
1731     {
1732       if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFMOD) != MDF_SITF_NORMAL_SPI_MODE)
1733       {
1734         status = HAL_ERROR;
1735       }
1736     }
1737   }
1738 
1739   if (status == HAL_OK)
1740   {
1741     /* Clear clock absence detection flag */
1742     hmdf->Instance->DFLTISR |= MDF_DFLTISR_CKABF;
1743 
1744     /* Check clock absence detection flag */
1745     if ((hmdf->Instance->DFLTISR & MDF_DFLTISR_CKABF) == MDF_DFLTISR_CKABF)
1746     {
1747       status = HAL_ERROR;
1748     }
1749     else
1750     {
1751       /* Enable clock absence detection interrupt */
1752       hmdf->Instance->DFLTIER |= MDF_DFLTIER_CKABIE;
1753     }
1754   }
1755 
1756   /* Return function status */
1757   return status;
1758 }
1759 
1760 /**
1761   * @brief  This function allows to stop clock absence detection in interrupt mode.
1762   * @param  hmdf MDF handle.
1763   * @retval HAL status.
1764   */
HAL_MDF_CkabStop_IT(MDF_HandleTypeDef * hmdf)1765 HAL_StatusTypeDef HAL_MDF_CkabStop_IT(MDF_HandleTypeDef *hmdf)
1766 {
1767   HAL_StatusTypeDef status = HAL_OK;
1768 
1769   /* Check state */
1770   if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
1771   {
1772     if (hmdf->State != HAL_MDF_STATE_READY)
1773     {
1774       status = HAL_ERROR;
1775     }
1776   }
1777 
1778   if (status == HAL_OK)
1779   {
1780     /* Check serial interface status and mode */
1781     if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFACTIVE) == 0U)
1782     {
1783       status = HAL_ERROR;
1784     }
1785     else
1786     {
1787       if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFMOD) != MDF_SITF_NORMAL_SPI_MODE)
1788       {
1789         status = HAL_ERROR;
1790       }
1791     }
1792   }
1793 
1794   if (status == HAL_OK)
1795   {
1796     /* Disable clock absence detection interrupt */
1797     hmdf->Instance->DFLTIER &= ~(MDF_DFLTIER_CKABIE);
1798 
1799     /* Clear potential pending clock absence detection flag */
1800     hmdf->Instance->DFLTISR |= MDF_DFLTISR_CKABF;
1801   }
1802 
1803   /* Return function status */
1804   return status;
1805 }
1806 
1807 /**
1808   * @}
1809   */
1810 
1811 /** @defgroup MDF_Exported_Functions_Group4  Generic functions
1812   * @brief    Generic functions
1813   *
1814 @verbatim
1815   ==============================================================================
1816                           ##### Generic functions #####
1817   ==============================================================================
1818     [..]  This section provides functions allowing to :
1819       (+) Handle MDF interrupt.
1820       (+) Inform user that error occurs.
1821       (+) Get the current MDF instance state.
1822       (+) Get the current MDF instance error code.
1823 @endverbatim
1824   * @{
1825   */
1826 
1827 /**
1828   * @brief  This function handles the MDF interrupts.
1829   * @param  hmdf MDF handle.
1830   * @retval None.
1831   */
HAL_MDF_IRQHandler(MDF_HandleTypeDef * hmdf)1832 void HAL_MDF_IRQHandler(MDF_HandleTypeDef *hmdf)
1833 {
1834   uint32_t tmp_reg1;
1835   uint32_t tmp_reg2;
1836   uint32_t interrupts;
1837 
1838   /* Read current flags and interrupts and determine which ones occur */
1839   tmp_reg1 = hmdf->Instance->DFLTIER;
1840   tmp_reg2 = hmdf->Instance->DFLTISR;
1841   interrupts = (tmp_reg1 & tmp_reg2);
1842 
1843   /* Check if data overflow occurs */
1844   if ((interrupts & MDF_DFLTISR_DOVRF) == MDF_DFLTISR_DOVRF)
1845   {
1846     /* Clear data overflow flag */
1847     hmdf->Instance->DFLTISR |= MDF_DFLTISR_DOVRF;
1848 
1849     /* Update error code */
1850     hmdf->ErrorCode |= MDF_ERROR_ACQUISITION_OVERFLOW;
1851 
1852     /* Call error callback */
1853 #if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
1854     hmdf->ErrorCallback(hmdf);
1855 #else /* USE_HAL_MDF_REGISTER_CALLBACKS */
1856     HAL_MDF_ErrorCallback(hmdf);
1857 #endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
1858   }
1859   /* Check if RXFIFO threshold occurs */
1860   else if ((interrupts & MDF_DFLTISR_FTHF) == MDF_DFLTISR_FTHF)
1861   {
1862     /* Call acquisition complete callback */
1863 #if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
1864     hmdf->AcqCpltCallback(hmdf);
1865 #else /* USE_HAL_MDF_REGISTER_CALLBACKS */
1866     HAL_MDF_AcqCpltCallback(hmdf);
1867 #endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
1868 
1869     /* Update state only in asynchronous single shot mode */
1870     if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_ACQMOD) == MDF_MODE_ASYNC_SINGLE)
1871     {
1872       hmdf->State = HAL_MDF_STATE_READY;
1873     }
1874   }
1875   /* Check if reshape filter overrun occurs */
1876   else if ((interrupts & MDF_DFLTISR_RFOVRF) == MDF_DFLTISR_RFOVRF)
1877   {
1878     /* Clear reshape filter overrun flag */
1879     hmdf->Instance->DFLTISR |= MDF_DFLTISR_RFOVRF;
1880 
1881     /* Update error code */
1882     hmdf->ErrorCode |= MDF_ERROR_RSF_OVERRUN;
1883 
1884     /* Call error callback */
1885 #if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
1886     hmdf->ErrorCallback(hmdf);
1887 #else /* USE_HAL_MDF_REGISTER_CALLBACKS */
1888     HAL_MDF_ErrorCallback(hmdf);
1889 #endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
1890   }
1891   /* Check if clock absence detection occurs */
1892   else if ((interrupts & MDF_DFLTISR_CKABF) == MDF_DFLTISR_CKABF)
1893   {
1894     /* Clear clock absence detection flag */
1895     hmdf->Instance->DFLTISR |= MDF_DFLTISR_CKABF;
1896 
1897     /* Update error code */
1898     hmdf->ErrorCode |= MDF_ERROR_CLOCK_ABSENCE;
1899 
1900     /* Call error callback */
1901 #if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
1902     hmdf->ErrorCallback(hmdf);
1903 #else /* USE_HAL_MDF_REGISTER_CALLBACKS */
1904     HAL_MDF_ErrorCallback(hmdf);
1905 #endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
1906   }
1907   /* Check if saturation occurs */
1908   else if ((interrupts & MDF_DFLTISR_SATF) == MDF_DFLTISR_SATF)
1909   {
1910     /* Clear saturation flag */
1911     hmdf->Instance->DFLTISR |= MDF_DFLTISR_SATF;
1912 
1913     /* Update error code */
1914     hmdf->ErrorCode |= MDF_ERROR_SATURATION;
1915 
1916     /* Call error callback */
1917 #if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
1918     hmdf->ErrorCallback(hmdf);
1919 #else /* USE_HAL_MDF_REGISTER_CALLBACKS */
1920     HAL_MDF_ErrorCallback(hmdf);
1921 #endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
1922   }
1923   /* Check if sound activity detection occurs */
1924   else if ((interrupts & MDF_DFLTISR_SDDETF) == MDF_DFLTISR_SDDETF)
1925   {
1926     /* Clear sound activity detection flag */
1927     hmdf->Instance->DFLTISR |= MDF_DFLTISR_SDDETF;
1928 
1929     /* Call sound activity detection callback */
1930 #if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
1931     hmdf->SadCallback(hmdf);
1932 #else /* USE_HAL_MDF_REGISTER_CALLBACKS */
1933     HAL_MDF_SadCallback(hmdf);
1934 #endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
1935   }
1936   else
1937   {
1938     /* Check if sound level ready occurs */
1939     if ((interrupts & MDF_DFLTISR_SDLVLF) == MDF_DFLTISR_SDLVLF)
1940     {
1941       uint32_t sound_level;
1942       uint32_t ambient_noise;
1943 
1944       /* Get sound level */
1945       sound_level = hmdf->Instance->SADSDLVR;
1946 
1947       /* Get ambient noise */
1948       ambient_noise = hmdf->Instance->SADANLVR;
1949 
1950       /* Clear sound level ready flag */
1951       hmdf->Instance->DFLTISR |= MDF_DFLTISR_SDLVLF;
1952 
1953       /* Call sound level callback */
1954 #if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
1955       hmdf->SndLvCallback(hmdf, sound_level, ambient_noise);
1956 #else /* USE_HAL_MDF_REGISTER_CALLBACKS */
1957       HAL_MDF_SndLvlCallback(hmdf, sound_level, ambient_noise);
1958 #endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
1959     }
1960   }
1961 }
1962 
1963 /**
1964   * @brief  MDF error callback.
1965   * @param  hmdf MDF handle.
1966   * @retval None.
1967   */
HAL_MDF_ErrorCallback(MDF_HandleTypeDef * hmdf)1968 __weak void HAL_MDF_ErrorCallback(MDF_HandleTypeDef *hmdf)
1969 {
1970   /* Prevent unused argument(s) compilation warning */
1971   UNUSED(hmdf);
1972 
1973   /* NOTE : This function should not be modified, when the function is needed,
1974             the HAL_MDF_ErrorCallback could be implemented in the user file */
1975 }
1976 
1977 /**
1978   * @brief  This function allows to get the current MDF state.
1979   * @param  hmdf MDF handle.
1980   * @retval MDF state.
1981   */
HAL_MDF_GetState(const MDF_HandleTypeDef * hmdf)1982 HAL_MDF_StateTypeDef HAL_MDF_GetState(const MDF_HandleTypeDef *hmdf)
1983 {
1984   /* Return MDF state */
1985   return hmdf->State;
1986 }
1987 
1988 /**
1989   * @brief  This function allows to get the current MDF error.
1990   * @param  hmdf MDF handle.
1991   * @retval MDF error code.
1992   */
HAL_MDF_GetError(const MDF_HandleTypeDef * hmdf)1993 uint32_t HAL_MDF_GetError(const MDF_HandleTypeDef *hmdf)
1994 {
1995   /* Return MDF error code */
1996   return hmdf->ErrorCode;
1997 }
1998 
1999 /**
2000   * @}
2001   */
2002 
2003 /**
2004   * @}
2005   */
2006 
2007 /** @addtogroup MDF_Private_Functions
2008   * @brief      Private functions
2009   * @{
2010   */
2011 
2012 /**
2013   * @brief  This function allows to configure filter and start acquisition.
2014   * @param  hmdf MDF handle.
2015   * @param  pFilterConfig Filter configuration parameters.
2016   * @retval None.
2017   */
MDF_AcqStart(MDF_HandleTypeDef * const hmdf,const MDF_FilterConfigTypeDef * const pFilterConfig)2018 static void MDF_AcqStart(MDF_HandleTypeDef *const hmdf, const MDF_FilterConfigTypeDef *const pFilterConfig)
2019 {
2020   uint32_t register_gain_value;
2021 
2022   /* Configure acquisition mode, discard samples, trigger and fifo threshold */
2023   assert_param(IS_MDF_DISCARD_SAMPLES(pFilterConfig->DiscardSamples));
2024   assert_param(IS_MDF_FIFO_THRESHOLD(pFilterConfig->FifoThreshold));
2025   if ((pFilterConfig->AcquisitionMode == MDF_MODE_ASYNC_CONT) ||
2026       (pFilterConfig->AcquisitionMode == MDF_MODE_ASYNC_SINGLE))
2027   {
2028     /* Trigger parameters are not used */
2029     hmdf->Instance->DFLTCR |= (pFilterConfig->AcquisitionMode | pFilterConfig->FifoThreshold |
2030                                (pFilterConfig->DiscardSamples << MDF_DFLTCR_NBDIS_Pos));
2031   }
2032   else
2033   {
2034     /* Trigger parameters are used */
2035     assert_param(IS_MDF_TRIGGER_SOURCE(pFilterConfig->Trigger.Source));
2036     assert_param(IS_MDF_TRIGGER_EDGE(pFilterConfig->Trigger.Edge));
2037     hmdf->Instance->DFLTCR |= (pFilterConfig->AcquisitionMode | pFilterConfig->FifoThreshold |
2038                                pFilterConfig->Trigger.Source | pFilterConfig->Trigger.Edge |
2039                                (pFilterConfig->DiscardSamples << MDF_DFLTCR_NBDIS_Pos));
2040   }
2041 
2042   /* Configure data source, CIC mode, decimation ratio and gain */
2043   assert_param(IS_MDF_DATA_SOURCE(pFilterConfig->DataSource));
2044   assert_param(IS_MDF_CIC_MODE(pFilterConfig->CicMode));
2045   assert_param(IS_MDF_DECIMATION_RATIO(pFilterConfig->DecimationRatio));
2046   assert_param(IS_MDF_GAIN(pFilterConfig->Gain));
2047   if (pFilterConfig->Gain < 0)
2048   {
2049     int32_t adjust_gain;
2050 
2051     /* adjust gain value to set on register for negative value (offset of -16) */
2052     adjust_gain = pFilterConfig->Gain - 16;
2053     register_gain_value = ((uint32_t) adjust_gain & 0x3FU);
2054   }
2055   else
2056   {
2057     /* for positive value, no offset to apply */
2058     register_gain_value = (uint32_t) pFilterConfig->Gain;
2059   }
2060   hmdf->Instance->DFLTCICR = (pFilterConfig->DataSource | pFilterConfig->CicMode |
2061                               ((pFilterConfig->DecimationRatio - 1U) << MDF_DFLTCICR_MCICD_Pos) |
2062                               (register_gain_value << MDF_DFLTCICR_SCALE_Pos));
2063 
2064   /* Configure bitstream delay */
2065   assert_param(IS_MDF_DELAY(pFilterConfig->Delay));
2066   hmdf->Instance->DLYCR = pFilterConfig->Delay;
2067 
2068   /* Configure reshape filter */
2069   assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->ReshapeFilter.Activation));
2070   hmdf->Instance->DFLTRSFR = 0U;
2071   if (pFilterConfig->ReshapeFilter.Activation == ENABLE)
2072   {
2073     /* Configure reshape filter decimation ratio */
2074     assert_param(IS_MDF_RSF_DECIMATION_RATIO(pFilterConfig->ReshapeFilter.DecimationRatio));
2075     hmdf->Instance->DFLTRSFR |= pFilterConfig->ReshapeFilter.DecimationRatio;
2076   }
2077   else
2078   {
2079     /* Bypass reshape filter */
2080     hmdf->Instance->DFLTRSFR |= MDF_DFLTRSFR_RSFLTBYP;
2081   }
2082 
2083   /* Configure high-pass filter */
2084   assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->HighPassFilter.Activation));
2085   if (pFilterConfig->HighPassFilter.Activation == ENABLE)
2086   {
2087     /* Configure high-pass filter cut-off frequency */
2088     assert_param(IS_MDF_HPF_CUTOFF_FREQ(pFilterConfig->HighPassFilter.CutOffFrequency));
2089     hmdf->Instance->DFLTRSFR |= pFilterConfig->HighPassFilter.CutOffFrequency;
2090   }
2091   else
2092   {
2093     /* Bypass high-pass filter */
2094     hmdf->Instance->DFLTRSFR |= MDF_DFLTRSFR_HPFBYP;
2095   }
2096 
2097   assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->SoundActivity.Activation));
2098   if (pFilterConfig->SoundActivity.Activation == ENABLE)
2099   {
2100     /* Configure SAD mode, frame size, hysteresis, sound trigger event
2101        and data memory transfer only for ADF instance */
2102     assert_param(IS_MDF_SAD_MODE(pFilterConfig->SoundActivity.Mode));
2103     assert_param(IS_MDF_SAD_FRAME_SIZE(pFilterConfig->SoundActivity.FrameSize));
2104     if (pFilterConfig->SoundActivity.Mode != MDF_SAD_AMBIENT_NOISE_DETECTOR)
2105     {
2106       assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->SoundActivity.Hysteresis));
2107     }
2108     assert_param(IS_MDF_SAD_SOUND_TRIGGER(pFilterConfig->SoundActivity.SoundTriggerEvent));
2109     assert_param(IS_MDF_SAD_DATA_MEMORY_TRANSFER(pFilterConfig->SoundActivity.DataMemoryTransfer));
2110     if ((pFilterConfig->SoundActivity.Mode != MDF_SAD_AMBIENT_NOISE_DETECTOR) &&
2111         (pFilterConfig->SoundActivity.Hysteresis == ENABLE))
2112     {
2113       hmdf->Instance->SADCR = (pFilterConfig->SoundActivity.Mode | pFilterConfig->SoundActivity.FrameSize |
2114                                MDF_SADCR_HYSTEN | pFilterConfig->SoundActivity.SoundTriggerEvent |
2115                                pFilterConfig->SoundActivity.DataMemoryTransfer);
2116     }
2117     else
2118     {
2119       hmdf->Instance->SADCR = (pFilterConfig->SoundActivity.Mode | pFilterConfig->SoundActivity.FrameSize |
2120                                pFilterConfig->SoundActivity.SoundTriggerEvent |
2121                                pFilterConfig->SoundActivity.DataMemoryTransfer);
2122     }
2123 
2124     /* Configure SAD minimum noise level, hangover window, learning frames,
2125        ambient noise slope control and signal noise threshold only for ADF instance */
2126     assert_param(IS_MDF_SAD_MIN_NOISE_LEVEL(pFilterConfig->SoundActivity.MinNoiseLevel));
2127     assert_param(IS_MDF_SAD_HANGOVER_WINDOW(pFilterConfig->SoundActivity.HangoverWindow));
2128     assert_param(IS_MDF_SAD_LEARNING_FRAMES(pFilterConfig->SoundActivity.LearningFrames));
2129     assert_param(IS_MDF_SAD_SIGNAL_NOISE_THRESHOLD(pFilterConfig->SoundActivity.SignalNoiseThreshold));
2130     if (pFilterConfig->SoundActivity.Mode != MDF_SAD_SOUND_DETECTOR)
2131     {
2132       assert_param(IS_MDF_SAD_AMBIENT_NOISE_SLOPE(pFilterConfig->SoundActivity.AmbientNoiseSlope));
2133       hmdf->Instance->SADCFGR = ((pFilterConfig->SoundActivity.MinNoiseLevel << MDF_SADCFGR_ANMIN_Pos) |
2134                                  pFilterConfig->SoundActivity.HangoverWindow |
2135                                  pFilterConfig->SoundActivity.LearningFrames |
2136                                  (pFilterConfig->SoundActivity.AmbientNoiseSlope << MDF_SADCFGR_ANSLP_Pos) |
2137                                  pFilterConfig->SoundActivity.SignalNoiseThreshold);
2138     }
2139     else
2140     {
2141       hmdf->Instance->SADCFGR = ((pFilterConfig->SoundActivity.MinNoiseLevel << MDF_SADCFGR_ANMIN_Pos) |
2142                                  pFilterConfig->SoundActivity.HangoverWindow |
2143                                  pFilterConfig->SoundActivity.LearningFrames |
2144                                  pFilterConfig->SoundActivity.SignalNoiseThreshold);
2145     }
2146   }
2147   else
2148   {
2149     /* SAD is not used */
2150     hmdf->Instance->SADCR = 0U;
2151     hmdf->Instance->SADCFGR = 0U;
2152   }
2153 
2154   /* Update instance state */
2155   hmdf->State = HAL_MDF_STATE_ACQUISITION;
2156 
2157   /* Enable sound activity detector if needed */
2158   if (pFilterConfig->SoundActivity.Activation == ENABLE)
2159   {
2160     hmdf->Instance->SADCR |= MDF_SADCR_SADEN;
2161   }
2162 
2163   /* Enable filter */
2164   hmdf->Instance->DFLTCR |= MDF_DFLTCR_DFLTEN;
2165 }
2166 
2167 /**
2168   * @brief  This function handles DMA transfer complete callback.
2169   * @param  hdma DMA handle.
2170   * @retval None.
2171   */
MDF_DmaXferCpltCallback(DMA_HandleTypeDef * hdma)2172 static void MDF_DmaXferCpltCallback(DMA_HandleTypeDef *hdma)
2173 {
2174   MDF_HandleTypeDef *hmdf = (MDF_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2175 
2176   /* Check if DMA in circular mode */
2177   if (hdma->Mode != DMA_LINKEDLIST_CIRCULAR)
2178   {
2179     hmdf->State = HAL_MDF_STATE_READY;
2180   }
2181 
2182 #if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
2183   hmdf->AcqCpltCallback(hmdf);
2184 #else /* USE_HAL_MDF_REGISTER_CALLBACKS */
2185   HAL_MDF_AcqCpltCallback(hmdf);
2186 #endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
2187 }
2188 
2189 /**
2190   * @brief  This function handles DMA half transfer complete callback.
2191   * @param  hdma DMA handle.
2192   * @retval None.
2193   */
MDF_DmaXferHalfCpltCallback(DMA_HandleTypeDef * hdma)2194 static void MDF_DmaXferHalfCpltCallback(DMA_HandleTypeDef *hdma)
2195 {
2196   MDF_HandleTypeDef *hmdf = (MDF_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2197 
2198 #if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
2199   hmdf->AcqHalfCpltCallback(hmdf);
2200 #else /* USE_HAL_MDF_REGISTER_CALLBACKS */
2201   HAL_MDF_AcqHalfCpltCallback(hmdf);
2202 #endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
2203 }
2204 
2205 /**
2206   * @brief  This function handles DMA error callback.
2207   * @param  hdma DMA handle.
2208   * @retval None.
2209   */
MDF_DmaErrorCallback(DMA_HandleTypeDef * hdma)2210 static void MDF_DmaErrorCallback(DMA_HandleTypeDef *hdma)
2211 {
2212   MDF_HandleTypeDef *hmdf = (MDF_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2213 
2214   /* Update error code */
2215   hmdf->ErrorCode |= MDF_ERROR_DMA;
2216 
2217 #if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
2218   hmdf->ErrorCallback(hmdf);
2219 #else /* USE_HAL_MDF_REGISTER_CALLBACKS */
2220   HAL_MDF_ErrorCallback(hmdf);
2221 #endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
2222 }
2223 
2224 /**
2225   * @}
2226   */
2227 
2228 #endif /* HAL_MDF_MODULE_ENABLED */
2229 
2230 /**
2231   * @}
2232   */
2233 
2234 /**
2235   * @}
2236   */
2237