Files
2026-10-18 14:06:40 +02:00

2237 lines
68 KiB
C

/**
******************************************************************************
* @file stm32h7rsxx_hal_mdf.c
* @author MCD Application Team
* @brief This file provides firmware functions to manage the following
* functionalities of the Multi-function Digital Filter (MDF)
* peripheral:
* + Initialization and de-initialization
* + Acquisition
* + Clock absence detection
*
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
@verbatim
==============================================================================
##### How to use this driver #####
==============================================================================
[..]
*** Initialization and de-initialization ***
============================================
[..]
(#) User has first to initialize ADF instance.
(#) As prerequisite, fill in the HAL_MDF_MspInit() :
(++) Enable ADFz clock interface with __HAL_RCC_ADFz_CLK_ENABLE().
(++) Enable the clocks for the used GPIOS with __HAL_RCC_GPIOx_CLK_ENABLE().
(++) Configure these pins in alternate mode using HAL_GPIO_Init().
(++) If interrupt mode is used, enable and configure ADFz_FLTx
interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ().
(++) If DMA mode is used, initialize and configure DMA.
(#) Configure the common parameters, serial interface parameters and
filter bitstream selection by calling HAL_MDF_Init() function.
[..]
(#) User can de-initialize ADF instance with HAL_MDF_DeInit() function.
*** Acquisition ***
===================
[..]
(#) Configure filter parameters and start acquisition using HAL_MDF_AcqStart(),
HAL_MDF_AcqStart_IT() or HAL_MDF_AcqStart_DMA().
(#) In polling mode :
(++) Use HAL_MDF_PollForAcq() to detect the end of acquisition.
Use HAL_MDF_GetAcqValue to get acquisition value.
(++) Use HAL_MDF_PollForSndLvl() to detect and get
new sound level value and ambient noise value.
(++) Use HAL_MDF_PollForSad() to detect sound activity.
(#) In interrupt mode :
(++) HAL_MDF_AcqCpltCallback() will be called at the end of acquisition.
Use HAL_MDF_GetAcqValue to get acquisition value.
(++) HAL_MDF_SndLvlCallback() will be called when new
sound level and ambient noise values are available.
(++) HAL_MDF_SadCallback() will be called when
sound activity detection occurs.
(++) HAL_MDF_ErrorCallback() will be called if overflow, filter overrun or
saturation occurs.
Use HAL_MDF_GetErrorCode() to get the corresponding error.
(#) In DMA mode :
(++) HAL_MDF_AcqHalfCpltCallback() and HAL_MDF_AcqCpltCallback() will be called
respectively at the half acquisition and at the acquisition complete.
(++) HAL_MDF_SndLvlCallback() will be called when new
sound level and ambient noise values are available.
(++) HAL_MDF_SadCallback() will be called when
sound activity detection occurs.
(++) HAL_MDF_ErrorCallback() will be called if overflow, filter overrun,
saturation or DMA error occurs.
Use HAL_MDF_GetErrorCode() to get the corresponding error.
(#) Use HAL_MDF_GenerateTrgo() to generate pulse on TRGO signal.
(#) During acquisition, use HAL_MDF_SetDelay() and HAL_MDF_GetDelay() to respectively
set and get the delay on data source.
(#) During acquisition, use HAL_MDF_SetGain() and HAL_MDF_GetGain() to respectively
set and get the filter gain.
(#) Stop acquisition using HAL_MDF_AcqStop(), HAL_MDF_AcqStop_IT() or HAL_MDF_AcqStop_DMA().
*** Clock absence detection ***
===============================
[..]
(#) Clock absence detection is always enabled so no need to start clock absence detection
in polling mode.
Use HAL_MDF_CkabStart_IT() to start clock absence detection in interrupt mode.
(#) In polling mode, use HAL_MDF_PollForCkab() to detect the clock absence.
(#) In interrupt mode, HAL_MDF_ErrorCallback() will be called if clock absence detection
occurs.
Use HAL_MDF_GetErrorCode() to get the corresponding error.
(#) Stop clock absence detection in interrupt mode using HAL_MDF_CkabStop_IT().
*** generic functions ***
=========================
[..]
(#) HAL_MDF_IRQHandler will be called when ADF interrupt occurs.
(#) HAL_MDF_ErrorCallback will be called when ADF error occurs.
(#) Use HAL_MDF_GetState() to get the current ADF instance state.
(#) Use HAL_MDF_GetErrorCode() to get the current ADF instance error code.
*** Callback registration ***
=============================
[..]
The compilation define USE_HAL_MDF_REGISTER_CALLBACKS when set to 1
allows the user to configure dynamically the driver callbacks.
Use functions HAL_MDF_RegisterCallback(), HAL_MDF_RegisterOldCallback()
or HAL_MDF_RegisterSndLvlCallback() to register a user callback.
[..]
Function HAL_MDF_RegisterCallback() allows to register following callbacks :
(+) AcqCpltCallback : Acquisition complete callback.
(+) AcqHalfCpltCallback : Acquisition half complete callback.
(+) SadCallback : Sound activity detection callback (only for ADF instance).
(+) ErrorCallback : Error callback.
(+) MspInitCallback : MSP init callback.
(+) MspDeInitCallback : MSP de-init callback.
[..]
This function takes as parameters the HAL peripheral handle, the Callback ID
and a pointer to the user callback function.
[..]
For specific sound level callback use dedicated register callback :
HAL_MDF_RegisterSndLvlCallback().
[..]
Use function HAL_MDF_UnRegisterCallback() to reset a callback to the default weak function.
[..]
HAL_MDF_UnRegisterCallback() takes as parameters the HAL peripheral handle and the Callback ID.
[..]
This function allows to reset following callbacks :
(+) AcqCpltCallback : Acquisition complete callback.
(+) AcqHalfCpltCallback : Acquisition half complete callback.
(+) SadCallback : Sound activity detection callback (only for ADF instance).
(+) ErrorCallback : Error callback.
(+) MspInitCallback : MSP init callback.
(+) MspDeInitCallback : MSP de-init callback.
[..]
For specific sound level callback use dedicated unregister callback :
HAL_MDF_UnRegisterSndLvlCallback().
[..]
By default, after the call of init function and if the state is RESET
all callbacks are reset to the corresponding legacy weak functions :
examples HAL_MDF_AcqCpltCallback(), HAL_MDF_ErrorCallback().
Exception done for MspInit and MspDeInit callbacks that are respectively
reset to the legacy weak functions in the init and de-init only when these
callbacks are null (not registered beforehand).
If not, MspInit or MspDeInit are not null, the init and de-init keep and use
the user MspInit/MspDeInit callbacks (registered beforehand).
[..]
Callbacks can be registered/unregistered in READY state only.
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
during the init/de-init.
In that case first register the MspInit/MspDeInit user callbacks using
HAL_MDF_RegisterCallback() before calling init or de-init function.
[..]
When the compilation define USE_HAL_MDF_REGISTER_CALLBACKS is set to 0 or
not defined, the callback registering feature is not available
and weak callbacks are used.
@endverbatim
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32h7rsxx_hal.h"
/** @addtogroup STM32H7RSxx_HAL_Driver
* @{
*/
/** @defgroup MDF MDF
* @brief MDF HAL module driver
* @{
*/
#ifdef HAL_MDF_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/** @defgroup MDF_Private_Typedefs MDF Private Typedefs
* @{
*/
/**
* @}
*/
/* Private define ------------------------------------------------------------*/
/** @defgroup MDF_Private_Constants MDF Private Constants
* @{
*/
/**
* @}
*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/** @defgroup MDF_Private_Variables MDF Private Variables
* @{
*/
static MDF_HandleTypeDef *v_mdfHandle = NULL;
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/** @defgroup MDF_Private_Functions MDF Private Functions
* @{
*/
static void MDF_AcqStart(MDF_HandleTypeDef *const hmdf, const MDF_FilterConfigTypeDef *const pFilterConfig);
static void MDF_DmaXferCpltCallback(DMA_HandleTypeDef *hdma);
static void MDF_DmaXferHalfCpltCallback(DMA_HandleTypeDef *hdma);
static void MDF_DmaErrorCallback(DMA_HandleTypeDef *hdma);
/**
* @}
*/
/* Exported functions ---------------------------------------------------------*/
/** @defgroup MDF_Exported_Functions MDF Exported Functions
* @{
*/
/** @defgroup MDF_Exported_Functions_Group1 Initialization and de-initialization functions
* @brief Initialization and de-initialization functions
*
@verbatim
==============================================================================
##### Initialization and de-initialization functions #####
==============================================================================
[..] This section provides functions allowing to :
(+) Initialize the ADF instance.
(+) De-initialize the ADF instance.
(+) Register and unregister callbacks.
@endverbatim
* @{
*/
/**
* @brief Initialize the MDF instance according to the specified parameters
* in the MDF_InitTypeDef structure and initialize the associated handle.
* @param hmdf MDF handle.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_Init(MDF_HandleTypeDef *hmdf)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check MDF handle */
if (hmdf == NULL)
{
status = HAL_ERROR;
}
else
{
/* Check parameters */
assert_param(IS_MDF_ALL_INSTANCE(hmdf->Instance));
assert_param(IS_MDF_FILTER_BITSTREAM(hmdf->Init.FilterBistream));
assert_param(IS_FUNCTIONAL_STATE(hmdf->Init.SerialInterface.Activation));
/* Check that instance has not been already initialized */
if (v_mdfHandle != NULL)
{
status = HAL_ERROR;
}
else
{
#if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
/* Reset callback pointers to the weak predefined callbacks */
hmdf->SndLvCallback = HAL_MDF_SndLvlCallback;
hmdf->SadCallback = HAL_MDF_SadCallback;
hmdf->AcqCpltCallback = HAL_MDF_AcqCpltCallback;
hmdf->AcqHalfCpltCallback = HAL_MDF_AcqHalfCpltCallback;
hmdf->ErrorCallback = HAL_MDF_ErrorCallback;
/* Call MDF MSP init function */
if (hmdf->MspInitCallback == NULL)
{
hmdf->MspInitCallback = HAL_MDF_MspInit;
}
hmdf->MspInitCallback(hmdf);
#else /* USE_HAL_MDF_REGISTER_CALLBACKS */
/* Call MDF MSP init function */
HAL_MDF_MspInit(hmdf);
#endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
/* Configure common parameters */
/* Check clock generator status */
if ((ADF1->CKGCR & MDF_CKGCR_CKGACTIVE) != 0U)
{
status = HAL_ERROR;
}
else
{
/* Configure processing clock divider, output clock divider,
output clock pins and output clock generation trigger */
assert_param(IS_MDF_PROC_CLOCK_DIVIDER(hmdf->Init.CommonParam.ProcClockDivider));
assert_param(IS_FUNCTIONAL_STATE(hmdf->Init.CommonParam.OutputClock.Activation));
ADF1->CKGCR = 0U;
ADF1->CKGCR |= ((hmdf->Init.CommonParam.ProcClockDivider - 1U) << MDF_CKGCR_PROCDIV_Pos);
if (hmdf->Init.CommonParam.OutputClock.Activation == ENABLE)
{
assert_param(IS_MDF_OUTPUT_CLOCK_PINS(hmdf->Init.CommonParam.OutputClock.Pins));
assert_param(IS_MDF_OUTPUT_CLOCK_DIVIDER(hmdf->Init.CommonParam.OutputClock.Divider));
assert_param(IS_FUNCTIONAL_STATE(hmdf->Init.CommonParam.OutputClock.Trigger.Activation));
ADF1->CKGCR |= (((hmdf->Init.CommonParam.OutputClock.Divider - 1U) << MDF_CKGCR_CCKDIV_Pos) |
hmdf->Init.CommonParam.OutputClock.Pins |
(hmdf->Init.CommonParam.OutputClock.Pins >> 4U));
if (hmdf->Init.CommonParam.OutputClock.Trigger.Activation == ENABLE)
{
assert_param(IS_MDF_OUTPUT_CLOCK_TRIGGER_SOURCE(hmdf->Init.CommonParam.OutputClock.Trigger.Source));
assert_param(IS_MDF_OUTPUT_CLOCK_TRIGGER_EDGE(hmdf->Init.CommonParam.OutputClock.Trigger.Edge));
ADF1->CKGCR |= (hmdf->Init.CommonParam.OutputClock.Trigger.Source |
hmdf->Init.CommonParam.OutputClock.Trigger.Edge |
MDF_CKGCR_CKGMOD);
}
}
/* Activate clock generator */
ADF1->CKGCR |= MDF_CKGCR_CKGDEN;
}
/* Configure serial interface */
if ((status == HAL_OK) && (hmdf->Init.SerialInterface.Activation == ENABLE))
{
/* Check serial interface status */
if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFACTIVE) != 0U)
{
status = HAL_ERROR;
}
else
{
/* Configure mode, clock source and threshold */
assert_param(IS_MDF_SITF_MODE(hmdf->Init.SerialInterface.Mode));
assert_param(IS_MDF_SITF_CLOCK_SOURCE(hmdf->Init.SerialInterface.ClockSource));
assert_param(IS_MDF_SITF_THRESHOLD(hmdf->Init.SerialInterface.Threshold));
hmdf->Instance->SITFCR = 0U;
hmdf->Instance->SITFCR |= ((hmdf->Init.SerialInterface.Threshold << MDF_SITFCR_STH_Pos) |
hmdf->Init.SerialInterface.Mode | hmdf->Init.SerialInterface.ClockSource);
/* Activate serial interface */
hmdf->Instance->SITFCR |= MDF_SITFCR_SITFEN;
}
}
if (status == HAL_OK)
{
/* Configure filter bitstream */
hmdf->Instance->BSMXCR &= ~(MDF_BSMXCR_BSSEL);
hmdf->Instance->BSMXCR |= hmdf->Init.FilterBistream;
/* Update instance pointer */
v_mdfHandle = hmdf;
/* Update error code and state */
hmdf->ErrorCode = MDF_ERROR_NONE;
hmdf->State = HAL_MDF_STATE_READY;
}
}
}
/* Return function status */
return status;
}
/**
* @brief De-initialize the MDF instance.
* @param hmdf MDF handle.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_DeInit(MDF_HandleTypeDef *hmdf)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check MDF handle */
if (hmdf == NULL)
{
status = HAL_ERROR;
}
else
{
/* Check parameters */
assert_param(IS_MDF_ALL_INSTANCE(hmdf->Instance));
/* Check that instance has not been already deinitialized */
if (v_mdfHandle == NULL)
{
status = HAL_ERROR;
}
else
{
/* Disable sound activity detector if needed */
if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) != 0U)
{
hmdf->Instance->SADCR &= ~(MDF_SADCR_SADEN);
}
/* Disable filter if needed */
if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_DFLTACTIVE) != 0U)
{
hmdf->Instance->DFLTCR &= ~(MDF_DFLTCR_DFLTEN);
}
/* Disable serial interface if needed */
if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFACTIVE) != 0U)
{
hmdf->Instance->SITFCR &= ~(MDF_SITFCR_SITFEN);
}
/* Disable all interrupts and clear all pending flags */
hmdf->Instance->DFLTIER = 0U;
hmdf->Instance->DFLTISR = 0xFFFFFFFFU;
/* Disable clock generator */
ADF1->CKGCR &= ~(MDF_CKGCR_CKGDEN);
/* Call MDF MSP deinit function */
#if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
if (hmdf->MspDeInitCallback == NULL)
{
hmdf->MspDeInitCallback = HAL_MDF_MspDeInit;
}
hmdf->MspDeInitCallback(hmdf);
#else /* USE_HAL_MDF_REGISTER_CALLBACKS */
HAL_MDF_MspDeInit(hmdf);
#endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
/* Update instance pointer */
v_mdfHandle = (MDF_HandleTypeDef *) NULL;
/* Update state */
hmdf->State = HAL_MDF_STATE_RESET;
}
}
/* Return function status */
return status;
}
/**
* @brief Initialize the MDF instance MSP.
* @param hmdf MDF handle.
* @retval None.
*/
__weak void HAL_MDF_MspInit(MDF_HandleTypeDef *hmdf)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hmdf);
/* NOTE : This function should not be modified, when the function is needed,
the HAL_MDF_MspInit could be implemented in the user file */
}
/**
* @brief De-initialize the MDF instance MSP.
* @param hmdf MDF handle.
* @retval None.
*/
__weak void HAL_MDF_MspDeInit(MDF_HandleTypeDef *hmdf)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hmdf);
/* NOTE : This function should not be modified, when the function is needed,
the HAL_MDF_MspDeInit could be implemented in the user file */
}
#if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
/**
* @brief Register a user MDF callback to be used instead of the weak predefined callback.
* @param hmdf MDF handle.
* @param CallbackID ID of the callback to be registered.
* This parameter can be one of the following values:
* @arg @ref HAL_MDF_ACQ_COMPLETE_CB_ID acquisition complete callback ID.
* @arg @ref HAL_MDF_ACQ_HALFCOMPLETE_CB_ID acquisition half complete callback ID.
* @arg @ref HAL_MDF_SAD_CB_ID sound activity detector callback ID (only for ADF instance).
* @arg @ref HAL_MDF_ERROR_CB_ID error callback ID.
* @arg @ref HAL_MDF_MSPINIT_CB_ID MSP init callback ID.
* @arg @ref HAL_MDF_MSPDEINIT_CB_ID MSP de-init callback ID.
* @param pCallback pointer to the callback function.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_RegisterCallback(MDF_HandleTypeDef *hmdf,
HAL_MDF_CallbackIDTypeDef CallbackID,
pMDF_CallbackTypeDef pCallback)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check parameters */
if (pCallback == NULL)
{
/* Update error code and status */
hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
status = HAL_ERROR;
}
else
{
if (hmdf->State == HAL_MDF_STATE_READY)
{
switch (CallbackID)
{
case HAL_MDF_ACQ_COMPLETE_CB_ID :
hmdf->AcqCpltCallback = pCallback;
break;
case HAL_MDF_ACQ_HALFCOMPLETE_CB_ID :
hmdf->AcqHalfCpltCallback = pCallback;
break;
case HAL_MDF_SAD_CB_ID :
hmdf->SadCallback = pCallback;
break;
case HAL_MDF_ERROR_CB_ID :
hmdf->ErrorCallback = pCallback;
break;
case HAL_MDF_MSPINIT_CB_ID :
hmdf->MspInitCallback = pCallback;
break;
case HAL_MDF_MSPDEINIT_CB_ID :
hmdf->MspDeInitCallback = pCallback;
break;
default :
/* Update error code and status */
hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
status = HAL_ERROR;
break;
}
}
else if (hmdf->State == HAL_MDF_STATE_RESET)
{
switch (CallbackID)
{
case HAL_MDF_MSPINIT_CB_ID :
hmdf->MspInitCallback = pCallback;
break;
case HAL_MDF_MSPDEINIT_CB_ID :
hmdf->MspDeInitCallback = pCallback;
break;
default :
/* Update error code and status */
hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
status = HAL_ERROR;
break;
}
}
else
{
/* Update error code and status */
hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
status = HAL_ERROR;
}
}
/* Return function status */
return status;
}
/**
* @brief Unregister a user MDF callback.
* MDF callback is redirected to the weak predefined callback.
* @param hmdf MDF handle.
* @param CallbackID ID of the callback to be unregistered.
* This parameter can be one of the following values:
* @arg @ref HAL_MDF_ACQ_COMPLETE_CB_ID acquisition complete callback ID.
* @arg @ref HAL_MDF_ACQ_HALFCOMPLETE_CB_ID acquisition half complete callback ID.
* @arg @ref HAL_MDF_SAD_CB_ID sound activity detector callback ID (only for ADF instance).
* @arg @ref HAL_MDF_ERROR_CB_ID error callback ID.
* @arg @ref HAL_MDF_MSPINIT_CB_ID MSP init callback ID.
* @arg @ref HAL_MDF_MSPDEINIT_CB_ID MSP de-init callback ID.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_UnRegisterCallback(MDF_HandleTypeDef *hmdf,
HAL_MDF_CallbackIDTypeDef CallbackID)
{
HAL_StatusTypeDef status = HAL_OK;
if (hmdf->State == HAL_MDF_STATE_READY)
{
switch (CallbackID)
{
case HAL_MDF_ACQ_COMPLETE_CB_ID :
hmdf->AcqCpltCallback = HAL_MDF_AcqCpltCallback;
break;
case HAL_MDF_ACQ_HALFCOMPLETE_CB_ID :
hmdf->AcqHalfCpltCallback = HAL_MDF_AcqHalfCpltCallback;
break;
case HAL_MDF_SAD_CB_ID :
hmdf->SadCallback = HAL_MDF_SadCallback;
break;
case HAL_MDF_ERROR_CB_ID :
hmdf->ErrorCallback = HAL_MDF_ErrorCallback;
break;
case HAL_MDF_MSPINIT_CB_ID :
hmdf->MspInitCallback = HAL_MDF_MspInit;
break;
case HAL_MDF_MSPDEINIT_CB_ID :
hmdf->MspDeInitCallback = HAL_MDF_MspDeInit;
break;
default :
/* Update error code and status */
hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
status = HAL_ERROR;
break;
}
}
else if (hmdf->State == HAL_MDF_STATE_RESET)
{
switch (CallbackID)
{
case HAL_MDF_MSPINIT_CB_ID :
hmdf->MspInitCallback = HAL_MDF_MspInit;
break;
case HAL_MDF_MSPDEINIT_CB_ID :
hmdf->MspDeInitCallback = HAL_MDF_MspDeInit;
break;
default :
/* Update error code and status */
hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
status = HAL_ERROR;
break;
}
}
else
{
/* Update error code and status */
hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
status = HAL_ERROR;
}
/* Return function status */
return status;
}
/**
* @brief Register specific MDF sound level callback
* to be used instead of the weak predefined callback.
* @param hmdf MDF handle.
* @param pCallback pointer to the sound level callback function.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_RegisterSndLvlCallback(MDF_HandleTypeDef *hmdf,
pMDF_SndLvlCallbackTypeDef pCallback)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check parameters */
if (pCallback == NULL)
{
/* Update error code and status */
hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
status = HAL_ERROR;
}
else
{
if (hmdf->State == HAL_MDF_STATE_READY)
{
hmdf->SndLvCallback = pCallback;
}
else
{
/* Update error code and status */
hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
status = HAL_ERROR;
}
}
/* Return function status */
return status;
}
/**
* @brief Unregister the specific MDF sound level callback.
* MDF sound level callback is redirected to the weak predefined callback.
* @param hmdf MDF handle.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_UnRegisterSndLvlCallback(MDF_HandleTypeDef *hmdf)
{
HAL_StatusTypeDef status = HAL_OK;
if (hmdf->State == HAL_MDF_STATE_READY)
{
hmdf->SndLvCallback = HAL_MDF_SndLvlCallback;
}
else
{
/* Update error code and status */
hmdf->ErrorCode |= MDF_ERROR_INVALID_CALLBACK;
status = HAL_ERROR;
}
/* Return function status */
return status;
}
#endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
/**
* @}
*/
/** @defgroup MDF_Exported_Functions_Group2 Acquisition functions
* @brief Acquisition functions
*
@verbatim
==============================================================================
##### Acquisition functions #####
==============================================================================
[..] This section provides functions allowing to :
(+) Start and stop acquisition in polling, interrupt or DMA mode.
(+) Wait and get acquisition values.
(+) Generate pulse on TRGO signal.
(+) Modify and get some filter parameters during acquisition.
(+) Wait and get sound level values.
(+) Detect sound activity.
@endverbatim
* @{
*/
/**
* @brief This function allows to start acquisition in polling mode.
* @param hmdf MDF handle.
* @param pFilterConfig Filter configuration parameters.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_AcqStart(MDF_HandleTypeDef *hmdf, const MDF_FilterConfigTypeDef *pFilterConfig)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check parameters */
if (pFilterConfig == NULL)
{
status = HAL_ERROR;
}
else
{
assert_param(IS_MDF_ACQUISITION_MODE(pFilterConfig->AcquisitionMode));
assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->SoundActivity.Activation));
if ((pFilterConfig->SoundActivity.Activation == ENABLE) &&
((pFilterConfig->AcquisitionMode == MDF_MODE_ASYNC_SINGLE) ||
(pFilterConfig->AcquisitionMode == MDF_MODE_SYNC_SINGLE) ||
(pFilterConfig->AcquisitionMode == MDF_MODE_WINDOW_CONT)))
{
status = HAL_ERROR;
}
/* Check state */
else if (hmdf->State != HAL_MDF_STATE_READY)
{
status = HAL_ERROR;
}
/* Check filter status */
else if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_DFLTACTIVE) != 0U)
{
status = HAL_ERROR;
}
else
{
/* Check SAD status */
if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) != 0U)
{
status = HAL_ERROR;
}
}
if (status == HAL_OK)
{
/* Configure filter and start acquisition */
hmdf->Instance->DFLTCR = 0U;
MDF_AcqStart(hmdf, pFilterConfig);
}
}
/* Return function status */
return status;
}
/**
* @brief This function allows to poll for available acquisition value.
* @param hmdf MDF handle.
* @param Timeout Timeout value in milliseconds.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_PollForAcq(MDF_HandleTypeDef *hmdf, uint32_t Timeout)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check state */
if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
status = HAL_ERROR;
}
else
{
uint32_t tickstart = HAL_GetTick();
/* Wait for available acquisition value */
while (((hmdf->Instance->DFLTISR & MDF_DFLTISR_RXNEF) != MDF_DFLTISR_RXNEF) && (status == HAL_OK))
{
/* Check the timeout */
if (Timeout != HAL_MAX_DELAY)
{
if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
{
status = HAL_TIMEOUT;
}
}
}
/* Check if data overflow, saturation or reshape filter occurs */
uint32_t error_flags = (hmdf->Instance->DFLTISR & (MDF_DFLTISR_DOVRF | MDF_DFLTISR_SATF | MDF_DFLTISR_RFOVRF));
if (error_flags != 0U)
{
/* Update error code */
if ((error_flags & MDF_DFLTISR_DOVRF) == MDF_DFLTISR_DOVRF)
{
hmdf->ErrorCode |= MDF_ERROR_ACQUISITION_OVERFLOW;
}
if ((error_flags & MDF_DFLTISR_SATF) == MDF_DFLTISR_SATF)
{
hmdf->ErrorCode |= MDF_ERROR_SATURATION;
}
if ((error_flags & MDF_DFLTISR_RFOVRF) == MDF_DFLTISR_RFOVRF)
{
hmdf->ErrorCode |= MDF_ERROR_RSF_OVERRUN;
}
/* Clear corresponding flags */
hmdf->Instance->DFLTISR |= error_flags;
/* Call error callback */
#if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
hmdf->ErrorCallback(hmdf);
#else /* USE_HAL_MDF_REGISTER_CALLBACKS */
HAL_MDF_ErrorCallback(hmdf);
#endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
}
if (status == HAL_OK)
{
/* Update state only in asynchronous single shot mode */
if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_ACQMOD) == MDF_MODE_ASYNC_SINGLE)
{
hmdf->State = HAL_MDF_STATE_READY;
}
}
}
/* Return function status */
return status;
}
/**
* @brief This function allows to get acquisition value.
* @param hmdf MDF handle.
* @param pValue Acquisition value on 24 MSB.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_GetAcqValue(const MDF_HandleTypeDef *hmdf, int32_t *pValue)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check parameters */
if (pValue == NULL)
{
status = HAL_ERROR;
}
else
{
/* Check state */
if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
if (hmdf->State != HAL_MDF_STATE_READY)
{
status = HAL_ERROR;
}
}
}
if (status == HAL_OK)
{
/* Get acquisition value */
*pValue = (int32_t) hmdf->Instance->DFLTDR;
}
/* Return function status */
return status;
}
/**
* @brief This function allows to stop acquisition in polling mode.
* @param hmdf MDF handle.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_AcqStop(MDF_HandleTypeDef *hmdf)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check state */
if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
/* Check if state is ready and filter active */
if (hmdf->State == HAL_MDF_STATE_READY)
{
if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_DFLTACTIVE) != MDF_DFLTCR_DFLTACTIVE)
{
status = HAL_ERROR;
}
}
else
{
status = HAL_ERROR;
}
}
else
{
/* Disable sound activity detector if needed */
if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) != 0U)
{
hmdf->Instance->SADCR &= ~(MDF_SADCR_SADEN);
}
}
if (status == HAL_OK)
{
/* Disable filter */
hmdf->Instance->DFLTCR &= ~(MDF_DFLTCR_DFLTEN);
/* Clear all potential pending flags */
hmdf->Instance->DFLTISR |= (MDF_DFLTISR_DOVRF | MDF_DFLTISR_SATF | MDF_DFLTISR_RFOVRF |
MDF_DFLTISR_SDDETF | MDF_DFLTISR_SDLVLF);
/* Update state */
hmdf->State = HAL_MDF_STATE_READY;
}
/* Return function status */
return status;
}
/**
* @brief This function allows to start acquisition in interrupt mode.
* @param hmdf MDF handle.
* @param pFilterConfig Filter configuration parameters.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_AcqStart_IT(MDF_HandleTypeDef *hmdf, const MDF_FilterConfigTypeDef *pFilterConfig)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check parameters */
if (pFilterConfig == NULL)
{
status = HAL_ERROR;
}
else
{
assert_param(IS_MDF_ACQUISITION_MODE(pFilterConfig->AcquisitionMode));
assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->SoundActivity.Activation));
if ((pFilterConfig->SoundActivity.Activation == ENABLE) &&
((pFilterConfig->AcquisitionMode == MDF_MODE_ASYNC_SINGLE) ||
(pFilterConfig->AcquisitionMode == MDF_MODE_SYNC_SINGLE) ||
(pFilterConfig->AcquisitionMode == MDF_MODE_WINDOW_CONT)))
{
status = HAL_ERROR;
}
/* Check state */
else if (hmdf->State != HAL_MDF_STATE_READY)
{
status = HAL_ERROR;
}
/* Check filter status */
else if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_DFLTACTIVE) != 0U)
{
status = HAL_ERROR;
}
else
{
/* Check SAD status */
if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) != 0U)
{
status = HAL_ERROR;
}
}
if (status == HAL_OK)
{
if ((pFilterConfig->SoundActivity.Activation == DISABLE) ||
(pFilterConfig->SoundActivity.DataMemoryTransfer != MDF_SAD_NO_MEMORY_TRANSFER))
{
/* Enable data overflow and fifo threshold interrupts */
hmdf->Instance->DFLTIER |= (MDF_DFLTIER_DOVRIE | MDF_DFLTIER_FTHIE);
}
if (pFilterConfig->ReshapeFilter.Activation == ENABLE)
{
/* Enable reshape filter overrun interrupt */
hmdf->Instance->DFLTIER |= MDF_DFLTIER_RFOVRIE;
}
/* Enable saturation interrupt */
hmdf->Instance->DFLTIER |= MDF_DFLTIER_SATIE;
if (pFilterConfig->SoundActivity.Activation == ENABLE)
{
/* Enable sound level value ready and sound activity detection interrupts */
assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->SoundActivity.SoundLevelInterrupt));
hmdf->Instance->DFLTIER |= (pFilterConfig->SoundActivity.SoundLevelInterrupt == ENABLE) ?
(MDF_DFLTIER_SDLVLIE | MDF_DFLTIER_SDDETIE) :
MDF_DFLTIER_SDDETIE;
}
/* Configure filter and start acquisition */
hmdf->Instance->DFLTCR = 0U;
MDF_AcqStart(hmdf, pFilterConfig);
}
}
/* Return function status */
return status;
}
/**
* @brief This function allows to stop acquisition in interrupt mode.
* @param hmdf MDF handle.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_AcqStop_IT(MDF_HandleTypeDef *hmdf)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check state */
if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
/* Check if state is ready and filter active */
if (hmdf->State == HAL_MDF_STATE_READY)
{
if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_DFLTACTIVE) != MDF_DFLTCR_DFLTACTIVE)
{
status = HAL_ERROR;
}
}
else
{
status = HAL_ERROR;
}
}
else
{
/* Disable sound activity detector if needed */
if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) != 0U)
{
hmdf->Instance->SADCR &= ~(MDF_SADCR_SADEN);
}
}
if (status == HAL_OK)
{
/* Disable filter */
hmdf->Instance->DFLTCR &= ~(MDF_DFLTCR_DFLTEN);
/* Disable interrupts and clear all potential pending flags */
hmdf->Instance->DFLTIER &= ~(MDF_DFLTIER_FTHIE | MDF_DFLTIER_DOVRIE | MDF_DFLTIER_SATIE |
MDF_DFLTIER_RFOVRIE | MDF_DFLTIER_SDDETIE | MDF_DFLTIER_SDLVLIE);
hmdf->Instance->DFLTISR |= (MDF_DFLTISR_DOVRF | MDF_DFLTISR_SATF | MDF_DFLTISR_RFOVRF |
MDF_DFLTISR_SDDETF | MDF_DFLTISR_SDLVLF);
/* Update state */
hmdf->State = HAL_MDF_STATE_READY;
}
/* Return function status */
return status;
}
/**
* @brief This function allows to start acquisition in DMA mode.
* @param hmdf MDF handle.
* @param pFilterConfig Filter configuration parameters.
* @param pDmaConfig DMA configuration parameters.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_AcqStart_DMA(MDF_HandleTypeDef *hmdf, const MDF_FilterConfigTypeDef *pFilterConfig,
const MDF_DmaConfigTypeDef *pDmaConfig)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check parameters */
if ((pFilterConfig == NULL) || (pDmaConfig == NULL))
{
status = HAL_ERROR;
}
else
{
assert_param(IS_FUNCTIONAL_STATE(pDmaConfig->MsbOnly));
assert_param(IS_MDF_ACQUISITION_MODE(pFilterConfig->AcquisitionMode));
assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->SoundActivity.Activation));
if ((pFilterConfig->SoundActivity.Activation == ENABLE) &&
((pFilterConfig->AcquisitionMode == MDF_MODE_ASYNC_SINGLE) ||
(pFilterConfig->AcquisitionMode == MDF_MODE_SYNC_SINGLE) ||
(pFilterConfig->AcquisitionMode == MDF_MODE_WINDOW_CONT)))
{
status = HAL_ERROR;
}
/* Check state */
else if (hmdf->State != HAL_MDF_STATE_READY)
{
status = HAL_ERROR;
}
/* Check filter status */
else if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_DFLTACTIVE) != 0U)
{
status = HAL_ERROR;
}
else
{
/* Check SAD status */
if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) != 0U)
{
status = HAL_ERROR;
}
}
if (status == HAL_OK)
{
uint32_t SrcAddress;
if (pFilterConfig->ReshapeFilter.Activation == ENABLE)
{
/* Enable reshape filter overrun interrupt */
hmdf->Instance->DFLTIER |= MDF_DFLTIER_RFOVRIE;
}
/* Enable saturation interrupt */
hmdf->Instance->DFLTIER |= MDF_DFLTIER_SATIE;
if (pFilterConfig->SoundActivity.Activation == ENABLE)
{
/* Enable sound level value ready and sound activity detection interrupts */
assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->SoundActivity.SoundLevelInterrupt));
hmdf->Instance->DFLTIER |= (pFilterConfig->SoundActivity.SoundLevelInterrupt == ENABLE) ?
(MDF_DFLTIER_SDLVLIE | MDF_DFLTIER_SDDETIE) :
MDF_DFLTIER_SDDETIE;
}
/* Enable MDF DMA requests */
hmdf->Instance->DFLTCR = MDF_DFLTCR_DMAEN;
/* Start DMA transfer */
hmdf->hdma->XferCpltCallback = MDF_DmaXferCpltCallback;
hmdf->hdma->XferHalfCpltCallback = MDF_DmaXferHalfCpltCallback;
hmdf->hdma->XferErrorCallback = MDF_DmaErrorCallback;
SrcAddress = (pDmaConfig->MsbOnly == ENABLE) ? (((uint32_t) &hmdf->Instance->DFLTDR) + 2U) :
(uint32_t) &hmdf->Instance->DFLTDR;
if ((hmdf->hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
{
if (hmdf->hdma->LinkedListQueue != NULL)
{
hmdf->hdma->LinkedListQueue->Head->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = pDmaConfig->DataLength;
hmdf->hdma->LinkedListQueue->Head->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = SrcAddress;
hmdf->hdma->LinkedListQueue->Head->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = pDmaConfig->Address;
status = HAL_DMAEx_List_Start_IT(hmdf->hdma);
}
else
{
status = HAL_ERROR;
}
}
else
{
status = HAL_DMA_Start_IT(hmdf->hdma, SrcAddress, pDmaConfig->Address, pDmaConfig->DataLength);
}
if (status != HAL_OK)
{
/* Update state */
hmdf->State = HAL_MDF_STATE_ERROR;
status = HAL_ERROR;
}
else
{
/* Configure filter and start acquisition */
MDF_AcqStart(hmdf, pFilterConfig);
}
}
}
/* Return function status */
return status;
}
/**
* @brief This function allows to stop acquisition in DMA mode.
* @param hmdf MDF handle.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_AcqStop_DMA(MDF_HandleTypeDef *hmdf)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check if state is ready and filter active */
if (hmdf->State == HAL_MDF_STATE_READY)
{
if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_DFLTACTIVE) != MDF_DFLTCR_DFLTACTIVE)
{
status = HAL_ERROR;
}
}
else
{
/* Check state */
if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
status = HAL_ERROR;
}
else
{
/* Stop the DMA transfer */
if (HAL_DMA_Abort(hmdf->hdma) != HAL_OK)
{
/* Update state */
hmdf->State = HAL_MDF_STATE_ERROR;
status = HAL_ERROR;
}
}
}
if (status == HAL_OK)
{
/* Disable sound activity detector if needed */
if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) != 0U)
{
hmdf->Instance->SADCR &= ~(MDF_SADCR_SADEN);
}
/* Disable filter */
hmdf->Instance->DFLTCR &= ~(MDF_DFLTCR_DFLTEN);
/* Disable interrupts and clear all potential pending flags */
hmdf->Instance->DFLTIER &= ~(MDF_DFLTIER_SATIE | MDF_DFLTIER_RFOVRIE | MDF_DFLTIER_SDDETIE |
MDF_DFLTIER_SDLVLIE);
hmdf->Instance->DFLTISR |= (MDF_DFLTISR_SATF | MDF_DFLTISR_RFOVRF | MDF_DFLTISR_SDDETF |
MDF_DFLTISR_SDLVLF);
/* Disable MDF DMA requests */
hmdf->Instance->DFLTCR &= ~(MDF_DFLTCR_DMAEN);
/* Update state */
hmdf->State = HAL_MDF_STATE_READY;
}
/* Return function status */
return status;
}
/**
* @brief This function allows to generate pulse on TRGO signal.
* @param hmdf MDF handle.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_GenerateTrgo(const MDF_HandleTypeDef *hmdf)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check state */
if (hmdf->State != HAL_MDF_STATE_READY)
{
if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
status = HAL_ERROR;
}
}
if (status == HAL_OK)
{
/* Check if trigger output control is already active */
if ((ADF1->GCR & MDF_GCR_TRGO) == MDF_GCR_TRGO)
{
status = HAL_ERROR;
}
else
{
/* Generate pulse on trigger output control signal */
ADF1->GCR |= MDF_GCR_TRGO;
}
}
/* Return function status */
return status;
}
/**
* @brief This function allows to set delay to apply on data source in number of samples.
* @param hmdf MDF handle.
* @param Delay Delay to apply on data source in number of samples.
* This parameter must be a number between Min_Data = 0 and Max_Data = 127.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_SetDelay(MDF_HandleTypeDef *hmdf, uint32_t Delay)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check parameters */
assert_param(IS_MDF_DELAY(Delay));
/* Check state */
if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
status = HAL_ERROR;
}
else
{
/* Check if bitstream delay is already active */
if ((hmdf->Instance->DLYCR & MDF_DLYCR_SKPBF) == MDF_DLYCR_SKPBF)
{
status = HAL_ERROR;
}
else
{
/* Configure bitstream delay */
hmdf->Instance->DLYCR |= Delay;
}
}
/* Return function status */
return status;
}
/**
* @brief This function allows to get current delay applied on data source in number of samples.
* @param hmdf MDF handle.
* @param pDelay Current delay applied on data source in number of samples.
* This value is between Min_Data = 0 and Max_Data = 127.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_GetDelay(const MDF_HandleTypeDef *hmdf, uint32_t *pDelay)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check parameters */
if (pDelay == NULL)
{
status = HAL_ERROR;
}
/* Check state */
else if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
status = HAL_ERROR;
}
else
{
/* Get current bitstream delay */
*pDelay = (hmdf->Instance->DLYCR & MDF_DLYCR_SKPDLY);
}
/* Return function status */
return status;
}
/**
* @brief This function allows to set filter gain.
* @param hmdf MDF handle.
* @param Gain Filter gain in step of around 3db (from -48db to 72dB).
* This parameter must be a number between Min_Data = -16 and Max_Data = 24.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_SetGain(MDF_HandleTypeDef *hmdf, int32_t Gain)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check parameters */
assert_param(IS_MDF_GAIN(Gain));
/* Check state */
if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
status = HAL_ERROR;
}
else
{
uint32_t register_gain_value;
uint32_t tmp_register;
if (Gain < 0)
{
int32_t adjust_gain;
/* adjust gain value to set on register for negative value (offset of -16) */
adjust_gain = Gain - 16;
register_gain_value = ((uint32_t) adjust_gain & 0x3FU);
}
else
{
/* for positive value, no offset to apply */
register_gain_value = (uint32_t) Gain;
}
/* Set gain */
tmp_register = (hmdf->Instance->DFLTCICR & ~(MDF_DFLTCICR_SCALE));
hmdf->Instance->DFLTCICR = (tmp_register | (register_gain_value << MDF_DFLTCICR_SCALE_Pos));
}
/* Return function status */
return status;
}
/**
* @brief This function allows to get filter gain.
* @param hmdf MDF handle.
* @param pGain Filter gain in step of around 3db (from -48db to 72dB).
* This parameter is between Min_Data = -16 and Max_Data = 24.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_GetGain(const MDF_HandleTypeDef *hmdf, int32_t *pGain)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check parameters */
if (pGain == NULL)
{
status = HAL_ERROR;
}
/* Check state */
else if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
status = HAL_ERROR;
}
else
{
uint32_t register_gain_value;
/* Get current gain */
register_gain_value = ((hmdf->Instance->DFLTCICR & MDF_DFLTCICR_SCALE) >> MDF_DFLTCICR_SCALE_Pos);
if (register_gain_value > 31U)
{
/* adjust gain value to set on register for negative value (offset of +16) */
register_gain_value |= 0xFFFFFFC0U;
*pGain = (int32_t) register_gain_value + 16;
}
else
{
/* for positive value, no offset to apply */
*pGain = (int32_t) register_gain_value;
}
}
/* Return function status */
return status;
}
/**
* @brief This function allows to poll for sound level data.
* @param hmdf MDF handle.
* @param Timeout Timeout value in milliseconds.
* @param pSoundLevel Sound level.
This parameter can be a value between Min_Data = 0 and Max_Data = 32767.
* @param pAmbientNoise Ambient noise.
This parameter can be a value between Min_Data = 0 and Max_Data = 32767.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_PollForSndLvl(MDF_HandleTypeDef *hmdf, uint32_t Timeout, uint32_t *pSoundLevel,
uint32_t *pAmbientNoise)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check parameters */
if ((pSoundLevel == NULL) || (pAmbientNoise == NULL))
{
status = HAL_ERROR;
}
/* Check state */
else if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
status = HAL_ERROR;
}
/* Check SAD status */
else if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) == 0U)
{
status = HAL_ERROR;
}
else
{
uint32_t tickstart = HAL_GetTick();
/* Wait for available sound level data */
while (((hmdf->Instance->DFLTISR & MDF_DFLTISR_SDLVLF) != MDF_DFLTISR_SDLVLF) && (status == HAL_OK))
{
/* Check the timeout */
if (Timeout != HAL_MAX_DELAY)
{
if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
{
status = HAL_TIMEOUT;
}
}
}
if (status == HAL_OK)
{
/* Get sound level */
*pSoundLevel = hmdf->Instance->SADSDLVR;
/* Get ambient noise */
*pAmbientNoise = hmdf->Instance->SADANLVR;
/* Clear sound level ready flag */
hmdf->Instance->DFLTISR |= MDF_DFLTISR_SDLVLF;
}
}
/* Return function status */
return status;
}
/**
* @brief This function allows to poll for sound activity detection.
* @param hmdf MDF handle.
* @param Timeout Timeout value in milliseconds.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_PollForSad(MDF_HandleTypeDef *hmdf, uint32_t Timeout)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check state */
if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
status = HAL_ERROR;
}
/* Check SAD status */
else if ((hmdf->Instance->SADCR & MDF_SADCR_SADACTIVE) == 0U)
{
status = HAL_ERROR;
}
else
{
uint32_t tickstart = HAL_GetTick();
/* Wait for sound activity detection */
while (((hmdf->Instance->DFLTISR & MDF_DFLTISR_SDDETF) != MDF_DFLTISR_SDDETF) && (status == HAL_OK))
{
/* Check the timeout */
if (Timeout != HAL_MAX_DELAY)
{
if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
{
status = HAL_TIMEOUT;
}
}
}
if (status == HAL_OK)
{
/* Clear sound activity detection flag */
hmdf->Instance->DFLTISR |= MDF_DFLTISR_SDDETF;
}
}
/* Return function status */
return status;
}
/**
* @brief MDF acquisition complete callback.
* @param hmdf MDF handle.
* @retval None.
*/
__weak void HAL_MDF_AcqCpltCallback(MDF_HandleTypeDef *hmdf)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hmdf);
/* NOTE : This function should not be modified, when the function is needed,
the HAL_MDF_AcqCpltCallback could be implemented in the user file */
}
/**
* @brief MDF acquisition half complete callback.
* @param hmdf MDF handle.
* @retval None.
*/
__weak void HAL_MDF_AcqHalfCpltCallback(MDF_HandleTypeDef *hmdf)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hmdf);
/* NOTE : This function should not be modified, when the function is needed,
the HAL_MDF_AcqHalfCpltCallback could be implemented in the user file */
}
/**
* @brief MDF sound level callback.
* @param hmdf MDF handle.
* @param SoundLevel Sound level value computed by sound activity detector.
* This parameter can be a value between Min_Data = 0 and Max_Data = 32767.
* @param AmbientNoise Ambient noise value computed by sound activity detector.
* This parameter can be a value between Min_Data = 0 and Max_Data = 32767.
* @retval None.
*/
__weak void HAL_MDF_SndLvlCallback(MDF_HandleTypeDef *hmdf, uint32_t SoundLevel, uint32_t AmbientNoise)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hmdf);
UNUSED(SoundLevel);
UNUSED(AmbientNoise);
/* NOTE : This function should not be modified, when the function is needed,
the HAL_MDF_SndLvlCallback could be implemented in the user file */
}
/**
* @brief MDF sound activity detector callback.
* @param hmdf MDF handle.
* @retval None.
*/
__weak void HAL_MDF_SadCallback(MDF_HandleTypeDef *hmdf)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hmdf);
/* NOTE : This function should not be modified, when the function is needed,
the HAL_MDF_SadCallback could be implemented in the user file */
}
/**
* @}
*/
/** @defgroup MDF_Exported_Functions_Group3 Clock absence detection functions
* @brief Clock absence detection functions
*
@verbatim
==============================================================================
##### Clock absence detection functions #####
==============================================================================
[..] This section provides functions allowing to :
(+) Start and stop clock absence detection in interrupt mode.
(+) Detect clock absence.
@endverbatim
* @{
*/
/**
* @brief This function allows to poll for the clock absence detection.
* @param hmdf MDF handle.
* @param Timeout Timeout value in milliseconds.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_PollForCkab(MDF_HandleTypeDef *hmdf, uint32_t Timeout)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check state */
if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
if (hmdf->State != HAL_MDF_STATE_READY)
{
status = HAL_ERROR;
}
}
if (status == HAL_OK)
{
/* Check serial interface status and mode */
if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFACTIVE) == 0U)
{
status = HAL_ERROR;
}
else
{
if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFMOD) != MDF_SITF_NORMAL_SPI_MODE)
{
status = HAL_ERROR;
}
}
}
if (status == HAL_OK)
{
uint32_t tickstart = HAL_GetTick();
/* Wait for clock absence detection */
while (((hmdf->Instance->DFLTISR & MDF_DFLTISR_CKABF) != MDF_DFLTISR_CKABF) && (status == HAL_OK))
{
/* Check the timeout */
if (Timeout != HAL_MAX_DELAY)
{
if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
{
status = HAL_TIMEOUT;
}
}
}
if (status == HAL_OK)
{
/* Clear clock absence detection flag */
hmdf->Instance->DFLTISR |= MDF_DFLTISR_CKABF;
}
}
/* Return function status */
return status;
}
/**
* @brief This function allows to start clock absence detection in interrupt mode.
* @param hmdf MDF handle.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_CkabStart_IT(MDF_HandleTypeDef *hmdf)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check state */
if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
if (hmdf->State != HAL_MDF_STATE_READY)
{
status = HAL_ERROR;
}
}
if (status == HAL_OK)
{
/* Check serial interface status and mode */
if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFACTIVE) == 0U)
{
status = HAL_ERROR;
}
else
{
if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFMOD) != MDF_SITF_NORMAL_SPI_MODE)
{
status = HAL_ERROR;
}
}
}
if (status == HAL_OK)
{
/* Clear clock absence detection flag */
hmdf->Instance->DFLTISR |= MDF_DFLTISR_CKABF;
/* Check clock absence detection flag */
if ((hmdf->Instance->DFLTISR & MDF_DFLTISR_CKABF) == MDF_DFLTISR_CKABF)
{
status = HAL_ERROR;
}
else
{
/* Enable clock absence detection interrupt */
hmdf->Instance->DFLTIER |= MDF_DFLTIER_CKABIE;
}
}
/* Return function status */
return status;
}
/**
* @brief This function allows to stop clock absence detection in interrupt mode.
* @param hmdf MDF handle.
* @retval HAL status.
*/
HAL_StatusTypeDef HAL_MDF_CkabStop_IT(MDF_HandleTypeDef *hmdf)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check state */
if (hmdf->State != HAL_MDF_STATE_ACQUISITION)
{
if (hmdf->State != HAL_MDF_STATE_READY)
{
status = HAL_ERROR;
}
}
if (status == HAL_OK)
{
/* Check serial interface status and mode */
if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFACTIVE) == 0U)
{
status = HAL_ERROR;
}
else
{
if ((hmdf->Instance->SITFCR & MDF_SITFCR_SITFMOD) != MDF_SITF_NORMAL_SPI_MODE)
{
status = HAL_ERROR;
}
}
}
if (status == HAL_OK)
{
/* Disable clock absence detection interrupt */
hmdf->Instance->DFLTIER &= ~(MDF_DFLTIER_CKABIE);
/* Clear potential pending clock absence detection flag */
hmdf->Instance->DFLTISR |= MDF_DFLTISR_CKABF;
}
/* Return function status */
return status;
}
/**
* @}
*/
/** @defgroup MDF_Exported_Functions_Group4 Generic functions
* @brief Generic functions
*
@verbatim
==============================================================================
##### Generic functions #####
==============================================================================
[..] This section provides functions allowing to :
(+) Handle MDF interrupt.
(+) Inform user that error occurs.
(+) Get the current MDF instance state.
(+) Get the current MDF instance error code.
@endverbatim
* @{
*/
/**
* @brief This function handles the MDF interrupts.
* @param hmdf MDF handle.
* @retval None.
*/
void HAL_MDF_IRQHandler(MDF_HandleTypeDef *hmdf)
{
uint32_t tmp_reg1;
uint32_t tmp_reg2;
uint32_t interrupts;
/* Read current flags and interrupts and determine which ones occur */
tmp_reg1 = hmdf->Instance->DFLTIER;
tmp_reg2 = hmdf->Instance->DFLTISR;
interrupts = (tmp_reg1 & tmp_reg2);
/* Check if data overflow occurs */
if ((interrupts & MDF_DFLTISR_DOVRF) == MDF_DFLTISR_DOVRF)
{
/* Clear data overflow flag */
hmdf->Instance->DFLTISR |= MDF_DFLTISR_DOVRF;
/* Update error code */
hmdf->ErrorCode |= MDF_ERROR_ACQUISITION_OVERFLOW;
/* Call error callback */
#if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
hmdf->ErrorCallback(hmdf);
#else /* USE_HAL_MDF_REGISTER_CALLBACKS */
HAL_MDF_ErrorCallback(hmdf);
#endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
}
/* Check if RXFIFO threshold occurs */
else if ((interrupts & MDF_DFLTISR_FTHF) == MDF_DFLTISR_FTHF)
{
/* Call acquisition complete callback */
#if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
hmdf->AcqCpltCallback(hmdf);
#else /* USE_HAL_MDF_REGISTER_CALLBACKS */
HAL_MDF_AcqCpltCallback(hmdf);
#endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
/* Update state only in asynchronous single shot mode */
if ((hmdf->Instance->DFLTCR & MDF_DFLTCR_ACQMOD) == MDF_MODE_ASYNC_SINGLE)
{
hmdf->State = HAL_MDF_STATE_READY;
}
}
/* Check if reshape filter overrun occurs */
else if ((interrupts & MDF_DFLTISR_RFOVRF) == MDF_DFLTISR_RFOVRF)
{
/* Clear reshape filter overrun flag */
hmdf->Instance->DFLTISR |= MDF_DFLTISR_RFOVRF;
/* Update error code */
hmdf->ErrorCode |= MDF_ERROR_RSF_OVERRUN;
/* Call error callback */
#if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
hmdf->ErrorCallback(hmdf);
#else /* USE_HAL_MDF_REGISTER_CALLBACKS */
HAL_MDF_ErrorCallback(hmdf);
#endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
}
/* Check if clock absence detection occurs */
else if ((interrupts & MDF_DFLTISR_CKABF) == MDF_DFLTISR_CKABF)
{
/* Clear clock absence detection flag */
hmdf->Instance->DFLTISR |= MDF_DFLTISR_CKABF;
/* Update error code */
hmdf->ErrorCode |= MDF_ERROR_CLOCK_ABSENCE;
/* Call error callback */
#if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
hmdf->ErrorCallback(hmdf);
#else /* USE_HAL_MDF_REGISTER_CALLBACKS */
HAL_MDF_ErrorCallback(hmdf);
#endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
}
/* Check if saturation occurs */
else if ((interrupts & MDF_DFLTISR_SATF) == MDF_DFLTISR_SATF)
{
/* Clear saturation flag */
hmdf->Instance->DFLTISR |= MDF_DFLTISR_SATF;
/* Update error code */
hmdf->ErrorCode |= MDF_ERROR_SATURATION;
/* Call error callback */
#if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
hmdf->ErrorCallback(hmdf);
#else /* USE_HAL_MDF_REGISTER_CALLBACKS */
HAL_MDF_ErrorCallback(hmdf);
#endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
}
/* Check if sound activity detection occurs */
else if ((interrupts & MDF_DFLTISR_SDDETF) == MDF_DFLTISR_SDDETF)
{
/* Clear sound activity detection flag */
hmdf->Instance->DFLTISR |= MDF_DFLTISR_SDDETF;
/* Call sound activity detection callback */
#if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
hmdf->SadCallback(hmdf);
#else /* USE_HAL_MDF_REGISTER_CALLBACKS */
HAL_MDF_SadCallback(hmdf);
#endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
}
else
{
/* Check if sound level ready occurs */
if ((interrupts & MDF_DFLTISR_SDLVLF) == MDF_DFLTISR_SDLVLF)
{
uint32_t sound_level;
uint32_t ambient_noise;
/* Get sound level */
sound_level = hmdf->Instance->SADSDLVR;
/* Get ambient noise */
ambient_noise = hmdf->Instance->SADANLVR;
/* Clear sound level ready flag */
hmdf->Instance->DFLTISR |= MDF_DFLTISR_SDLVLF;
/* Call sound level callback */
#if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
hmdf->SndLvCallback(hmdf, sound_level, ambient_noise);
#else /* USE_HAL_MDF_REGISTER_CALLBACKS */
HAL_MDF_SndLvlCallback(hmdf, sound_level, ambient_noise);
#endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
}
}
}
/**
* @brief MDF error callback.
* @param hmdf MDF handle.
* @retval None.
*/
__weak void HAL_MDF_ErrorCallback(MDF_HandleTypeDef *hmdf)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hmdf);
/* NOTE : This function should not be modified, when the function is needed,
the HAL_MDF_ErrorCallback could be implemented in the user file */
}
/**
* @brief This function allows to get the current MDF state.
* @param hmdf MDF handle.
* @retval MDF state.
*/
HAL_MDF_StateTypeDef HAL_MDF_GetState(const MDF_HandleTypeDef *hmdf)
{
/* Return MDF state */
return hmdf->State;
}
/**
* @brief This function allows to get the current MDF error.
* @param hmdf MDF handle.
* @retval MDF error code.
*/
uint32_t HAL_MDF_GetError(const MDF_HandleTypeDef *hmdf)
{
/* Return MDF error code */
return hmdf->ErrorCode;
}
/**
* @}
*/
/**
* @}
*/
/** @addtogroup MDF_Private_Functions
* @brief Private functions
* @{
*/
/**
* @brief This function allows to configure filter and start acquisition.
* @param hmdf MDF handle.
* @param pFilterConfig Filter configuration parameters.
* @retval None.
*/
static void MDF_AcqStart(MDF_HandleTypeDef *const hmdf, const MDF_FilterConfigTypeDef *const pFilterConfig)
{
uint32_t register_gain_value;
/* Configure acquisition mode, discard samples, trigger and fifo threshold */
assert_param(IS_MDF_DISCARD_SAMPLES(pFilterConfig->DiscardSamples));
assert_param(IS_MDF_FIFO_THRESHOLD(pFilterConfig->FifoThreshold));
if ((pFilterConfig->AcquisitionMode == MDF_MODE_ASYNC_CONT) ||
(pFilterConfig->AcquisitionMode == MDF_MODE_ASYNC_SINGLE))
{
/* Trigger parameters are not used */
hmdf->Instance->DFLTCR |= (pFilterConfig->AcquisitionMode | pFilterConfig->FifoThreshold |
(pFilterConfig->DiscardSamples << MDF_DFLTCR_NBDIS_Pos));
}
else
{
/* Trigger parameters are used */
assert_param(IS_MDF_TRIGGER_SOURCE(pFilterConfig->Trigger.Source));
assert_param(IS_MDF_TRIGGER_EDGE(pFilterConfig->Trigger.Edge));
hmdf->Instance->DFLTCR |= (pFilterConfig->AcquisitionMode | pFilterConfig->FifoThreshold |
pFilterConfig->Trigger.Source | pFilterConfig->Trigger.Edge |
(pFilterConfig->DiscardSamples << MDF_DFLTCR_NBDIS_Pos));
}
/* Configure data source, CIC mode, decimation ratio and gain */
assert_param(IS_MDF_DATA_SOURCE(pFilterConfig->DataSource));
assert_param(IS_MDF_CIC_MODE(pFilterConfig->CicMode));
assert_param(IS_MDF_DECIMATION_RATIO(pFilterConfig->DecimationRatio));
assert_param(IS_MDF_GAIN(pFilterConfig->Gain));
if (pFilterConfig->Gain < 0)
{
int32_t adjust_gain;
/* adjust gain value to set on register for negative value (offset of -16) */
adjust_gain = pFilterConfig->Gain - 16;
register_gain_value = ((uint32_t) adjust_gain & 0x3FU);
}
else
{
/* for positive value, no offset to apply */
register_gain_value = (uint32_t) pFilterConfig->Gain;
}
hmdf->Instance->DFLTCICR = (pFilterConfig->DataSource | pFilterConfig->CicMode |
((pFilterConfig->DecimationRatio - 1U) << MDF_DFLTCICR_MCICD_Pos) |
(register_gain_value << MDF_DFLTCICR_SCALE_Pos));
/* Configure bitstream delay */
assert_param(IS_MDF_DELAY(pFilterConfig->Delay));
hmdf->Instance->DLYCR = pFilterConfig->Delay;
/* Configure reshape filter */
assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->ReshapeFilter.Activation));
hmdf->Instance->DFLTRSFR = 0U;
if (pFilterConfig->ReshapeFilter.Activation == ENABLE)
{
/* Configure reshape filter decimation ratio */
assert_param(IS_MDF_RSF_DECIMATION_RATIO(pFilterConfig->ReshapeFilter.DecimationRatio));
hmdf->Instance->DFLTRSFR |= pFilterConfig->ReshapeFilter.DecimationRatio;
}
else
{
/* Bypass reshape filter */
hmdf->Instance->DFLTRSFR |= MDF_DFLTRSFR_RSFLTBYP;
}
/* Configure high-pass filter */
assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->HighPassFilter.Activation));
if (pFilterConfig->HighPassFilter.Activation == ENABLE)
{
/* Configure high-pass filter cut-off frequency */
assert_param(IS_MDF_HPF_CUTOFF_FREQ(pFilterConfig->HighPassFilter.CutOffFrequency));
hmdf->Instance->DFLTRSFR |= pFilterConfig->HighPassFilter.CutOffFrequency;
}
else
{
/* Bypass high-pass filter */
hmdf->Instance->DFLTRSFR |= MDF_DFLTRSFR_HPFBYP;
}
assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->SoundActivity.Activation));
if (pFilterConfig->SoundActivity.Activation == ENABLE)
{
/* Configure SAD mode, frame size, hysteresis, sound trigger event
and data memory transfer only for ADF instance */
assert_param(IS_MDF_SAD_MODE(pFilterConfig->SoundActivity.Mode));
assert_param(IS_MDF_SAD_FRAME_SIZE(pFilterConfig->SoundActivity.FrameSize));
if (pFilterConfig->SoundActivity.Mode != MDF_SAD_AMBIENT_NOISE_DETECTOR)
{
assert_param(IS_FUNCTIONAL_STATE(pFilterConfig->SoundActivity.Hysteresis));
}
assert_param(IS_MDF_SAD_SOUND_TRIGGER(pFilterConfig->SoundActivity.SoundTriggerEvent));
assert_param(IS_MDF_SAD_DATA_MEMORY_TRANSFER(pFilterConfig->SoundActivity.DataMemoryTransfer));
if ((pFilterConfig->SoundActivity.Mode != MDF_SAD_AMBIENT_NOISE_DETECTOR) &&
(pFilterConfig->SoundActivity.Hysteresis == ENABLE))
{
hmdf->Instance->SADCR = (pFilterConfig->SoundActivity.Mode | pFilterConfig->SoundActivity.FrameSize |
MDF_SADCR_HYSTEN | pFilterConfig->SoundActivity.SoundTriggerEvent |
pFilterConfig->SoundActivity.DataMemoryTransfer);
}
else
{
hmdf->Instance->SADCR = (pFilterConfig->SoundActivity.Mode | pFilterConfig->SoundActivity.FrameSize |
pFilterConfig->SoundActivity.SoundTriggerEvent |
pFilterConfig->SoundActivity.DataMemoryTransfer);
}
/* Configure SAD minimum noise level, hangover window, learning frames,
ambient noise slope control and signal noise threshold only for ADF instance */
assert_param(IS_MDF_SAD_MIN_NOISE_LEVEL(pFilterConfig->SoundActivity.MinNoiseLevel));
assert_param(IS_MDF_SAD_HANGOVER_WINDOW(pFilterConfig->SoundActivity.HangoverWindow));
assert_param(IS_MDF_SAD_LEARNING_FRAMES(pFilterConfig->SoundActivity.LearningFrames));
assert_param(IS_MDF_SAD_SIGNAL_NOISE_THRESHOLD(pFilterConfig->SoundActivity.SignalNoiseThreshold));
if (pFilterConfig->SoundActivity.Mode != MDF_SAD_SOUND_DETECTOR)
{
assert_param(IS_MDF_SAD_AMBIENT_NOISE_SLOPE(pFilterConfig->SoundActivity.AmbientNoiseSlope));
hmdf->Instance->SADCFGR = ((pFilterConfig->SoundActivity.MinNoiseLevel << MDF_SADCFGR_ANMIN_Pos) |
pFilterConfig->SoundActivity.HangoverWindow |
pFilterConfig->SoundActivity.LearningFrames |
(pFilterConfig->SoundActivity.AmbientNoiseSlope << MDF_SADCFGR_ANSLP_Pos) |
pFilterConfig->SoundActivity.SignalNoiseThreshold);
}
else
{
hmdf->Instance->SADCFGR = ((pFilterConfig->SoundActivity.MinNoiseLevel << MDF_SADCFGR_ANMIN_Pos) |
pFilterConfig->SoundActivity.HangoverWindow |
pFilterConfig->SoundActivity.LearningFrames |
pFilterConfig->SoundActivity.SignalNoiseThreshold);
}
}
else
{
/* SAD is not used */
hmdf->Instance->SADCR = 0U;
hmdf->Instance->SADCFGR = 0U;
}
/* Update instance state */
hmdf->State = HAL_MDF_STATE_ACQUISITION;
/* Enable sound activity detector if needed */
if (pFilterConfig->SoundActivity.Activation == ENABLE)
{
hmdf->Instance->SADCR |= MDF_SADCR_SADEN;
}
/* Enable filter */
hmdf->Instance->DFLTCR |= MDF_DFLTCR_DFLTEN;
}
/**
* @brief This function handles DMA transfer complete callback.
* @param hdma DMA handle.
* @retval None.
*/
static void MDF_DmaXferCpltCallback(DMA_HandleTypeDef *hdma)
{
MDF_HandleTypeDef *hmdf = (MDF_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
/* Check if DMA in circular mode */
if (hdma->Mode != DMA_LINKEDLIST_CIRCULAR)
{
hmdf->State = HAL_MDF_STATE_READY;
}
#if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
hmdf->AcqCpltCallback(hmdf);
#else /* USE_HAL_MDF_REGISTER_CALLBACKS */
HAL_MDF_AcqCpltCallback(hmdf);
#endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
}
/**
* @brief This function handles DMA half transfer complete callback.
* @param hdma DMA handle.
* @retval None.
*/
static void MDF_DmaXferHalfCpltCallback(DMA_HandleTypeDef *hdma)
{
MDF_HandleTypeDef *hmdf = (MDF_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
#if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
hmdf->AcqHalfCpltCallback(hmdf);
#else /* USE_HAL_MDF_REGISTER_CALLBACKS */
HAL_MDF_AcqHalfCpltCallback(hmdf);
#endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
}
/**
* @brief This function handles DMA error callback.
* @param hdma DMA handle.
* @retval None.
*/
static void MDF_DmaErrorCallback(DMA_HandleTypeDef *hdma)
{
MDF_HandleTypeDef *hmdf = (MDF_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
/* Update error code */
hmdf->ErrorCode |= MDF_ERROR_DMA;
#if (USE_HAL_MDF_REGISTER_CALLBACKS == 1)
hmdf->ErrorCallback(hmdf);
#else /* USE_HAL_MDF_REGISTER_CALLBACKS */
HAL_MDF_ErrorCallback(hmdf);
#endif /* USE_HAL_MDF_REGISTER_CALLBACKS */
}
/**
* @}
*/
#endif /* HAL_MDF_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/