Audio Demo with DISCO Board, takes control samples, waits for user input, samples regularly.

Dependencies:   CMSIS_DSP_401 STM32L4xx_HAL_Driver mbed-src_DISO_AUDIO_DEMO

Revision:
0:3eee9435dd17
diff -r 000000000000 -r 3eee9435dd17 stm32l476g_discovery_audio.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stm32l476g_discovery_audio.c	Sun Dec 13 19:12:11 2015 +0000
@@ -0,0 +1,1071 @@
+/**
+  ******************************************************************************
+  * @file    stm32l476g_discovery_audio.c
+  * @author  MCD Application Team
+  * @version V1.0.1
+  * @date    16-September-2015
+  * @brief   This file provides a set of functions needed to manage the 
+  *          Audio driver for the STM32L476G-Discovery board.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/*==============================================================================
+                                 User NOTES
+                                 
+1. How To use this driver:
+--------------------------
+   + This driver supports STM32L4xx devices on STM32L476G-Discovery (MB1184) Discovery boards.
+        a) to play an audio file (all functions names start by BSP_AUDIO_OUT_xxx)
+        b) to record an audio file through MP34DT01TR, ST MEMS (all functions names start by BSP_AUDIO_IN_xxx)
+
+a) PLAY A FILE:
+==============
+   + Call the function BSP_AUDIO_OUT_Init(
+                                    OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 
+                                                  OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH)
+                                    Volume      : Initial volume to be set (0 is min (mute), 100 is max (100%)
+                                    AudioFreq   : Audio frequency in Hz (8000, 16000, 22500, 32000...)
+                                                  this parameter is relative to the audio file/stream type.
+                                   )
+      This function configures all the hardware required for the audio application (codec, I2C, SAI, 
+      GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK.
+      If the returned value is different from AUDIO_OK or the function is stuck then the communication with
+      the audio codec has failed.
+      - OUTPUT_DEVICE_SPEAKER  : only speaker will be set as output for the audio stream.
+      - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream.
+      - OUTPUT_DEVICE_BOTH     : both Speaker and Headphone are used as outputs for the audio stream
+                                 at the same time.
+
+   + Call the function BSP_AUDIO_OUT_RegisterCallbacks to register user callbacks
+     required to manage audio data streaming towards the audio codec (ErrorCallback(),
+     HalfTransfer_CallBack() and TransferComplete_CallBack()).
+
+   + Call the function BSP_AUDIO_OUT_Play() to start audio playback (for the first time).
+   + Call the function BSP_AUDIO_OUT_Pause() to pause audio playabck   
+   + Call the function BSP_AUDIO_OUT_Resume() to resume audio playback.
+       Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called
+          for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case).
+       Note. This function should be called only when the audio file is played or paused (not stopped).
+   + Call the function BSP_AUDIO_OUT_Stop() to stop audio playback.
+   + To modify the volume level, the sampling frequency, the device output mode, 
+      the mute status or the audio configuration or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(), 
+      AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetOutputMode(), BSP_AUDIO_OUT_SetMute()and 
+      BSP_AUDIO_OUT_ChangeAudioConfig().
+ 
+Driver architecture:
+--------------------
+   + This driver provides the audio layer high level API: it consists in functions
+     exported in the stm32l476g_discovery_audio.h file (e.g. BSP_AUDIO_OUT_Init(),
+     BSP_AUDIO_OUT_Play(), ...).
+   + This driver also includes the Media Access Layer (MAL): it consists in 
+     functions allowing to access setup the audio devices. These functions 
+     are  included as local functions into the stm32l476g_discovery_audio.c file
+     (e.g. AUDIO_SAIx_Init()).
+
+Known Limitations:
+------------------
+   1- Communication with the audio codec (through I2C) may be corrupted if it is interrupted by some
+      user interrupt routines (in this case, interrupts could be disabled just before the start of 
+      communication then re-enabled when it is over). Note that this communication is only done at
+      the configuration phase (BSP_AUDIO_OUT_Init() or BSP_AUDIO_OUT_Stop()) and when Volume control modification is 
+      performed (BSP_AUDIO_OUT_SetVolume() or BSP_AUDIO_OUT_SetMute()or BSP_AUDIO_OUT_SetOutputMode()). 
+      When the audio data is played, no communication is required with the audio codec.
+   2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 
+      File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file.
+   3- Supports only 16-bits audio data size.
+
+b) RECORD A FILE:
+================
+   + Call the function BSP_AUDIO_IN_Init(
+                                    AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...)
+                                    )
+      This function configures all the hardware required for the audio application (DFSDM, 
+      GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if the 
+      configuration completes successfully.
+
+   + Call the function BSP_AUDIO_IN_RegisterCallbacks to register user callbacks
+     used to stream audio data toward the record buffer (ErrorCallback(),
+     HalfTransfer_CallBack() and TransferComplete_CallBack()).
+
+   + Call the function BSP_AUDIO_IN_Record(
+                            pbuf Main buffer pointer for the recorded data storing  
+                            size Current size of the recorded buffer
+                            )
+      to start recording from the microphone.
+
+   + Call the function AUDIO_IN_STOP() to stop recording 
+==============================================================================*/
+
+/* Includes ------------------------------------------------------------------*/
+#include <string.h>
+#include "stm32l476g_discovery_audio.h"
+
+/** @addtogroup BSP
+  * @{
+  */
+
+/** @addtogroup STM32L476G_DISCOVERY
+  * @{
+  */
+
+/** @defgroup STM32L476G_DISCOVERY_AUDIO STM32L476G-DISCOVERY AUDIO
+  * @brief This file includes the low layer driver for cs43l22 Audio Codec
+  *        available on STM32L476G-Discovery board(MB1184).
+  * @{
+  */ 
+
+/* Private typedef -----------------------------------------------------------*/
+/** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Types Private Types
+  * @{
+  */
+typedef struct
+{
+  
+  Audio_CallbackTypeDef CbError;            /* pointer to the callback function invoked when ... */
+  Audio_CallbackTypeDef CbHalfTransfer;     /* pointer to the callback function invoked when ... */
+  Audio_CallbackTypeDef CbTransferComplete; /* pointer to the callback function invoked when ... */
+} AUDIO_OUT_TypeDef;
+
+typedef struct
+{
+  DFSDM_Channel_HandleTypeDef hDfsdmLeftChannel;  /* DFSDM channel handle used for left channel */
+  DMA_HandleTypeDef           hDmaDfsdmLeft;      /* DMA handle used for DFSDM regular conversions on left channel */
+  int32_t *                   LeftRecBuff;        /* Buffers for left samples */
+  uint32_t                Frequency;        /* Record Frequency */
+  uint32_t                BitResolution;    /* Record bit resolution */
+  uint32_t                ChannelNbr;       /* Record Channel Number */
+  uint16_t *              pRecBuf;          /* Pointer to record user buffer */
+  uint32_t                RecSize;          /* Size to record in mono, double size to record in stereo */
+  Audio_CallbackTypeDef       CbError;            /* pointer to the callback function invoked when a DMA transfer fails */
+  Audio_CallbackTypeDef       CbHalfTransfer;     /* pointer to the callback function invoked when half of the DMA transfer is completed */
+  Audio_CallbackTypeDef       CbTransferComplete; /* pointer to the callback function invoked when the DMA transfer is completed */
+} AUDIO_IN_TypeDef;
+
+/**
+  * @}
+  */
+
+/* Private defines ------------------------------------------------------------*/
+/** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Constants Private Constants
+  * @{
+  */
+/**
+  * @}
+  */
+
+/* Private macros ------------------------------------------------------------*/
+/** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Macros Private Macros
+  * @{
+  */
+/*### PLAY ###*/
+/* SCK(kHz) = SAI_CK_x/(SAIClockDivider*2*256) */
+#define SAIClockDivider(__FREQUENCY__) \
+        (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 12 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 2 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 6 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 1 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 3 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 0 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 2 : 1  \
+
+/*### RECORD ###*/
+#define DFSDMOverSampling(__FREQUENCY__) \
+        (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 256 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64  \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 16  \
+
+#define DFSDMClockDivider(__FREQUENCY__) \
+        (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 24 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4  \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 32  \
+
+#define DFSDMFilterOrder(__FREQUENCY__) \
+        (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? DFSDM_FILTER_SINC3_ORDER \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC4_ORDER  \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC4_ORDER : DFSDM_FILTER_SINC5_ORDER  \
+
+#define DFSDMRightBitShift(__FREQUENCY__) \
+        (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 2 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 3 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 3 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 0 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 3 \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 3  \
+      : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 7 : 0  \
+
+/* Saturate the record PCM sample */
+#define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N)))
+
+/**
+  * @}
+  */ 
+  
+/* Private variables ---------------------------------------------------------*/
+/** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Variables Private Variables
+  * @{
+  */
+/* Audio output context information */
+static AUDIO_OUT_TypeDef hAudioOut;
+
+/* Audio input context information */
+static AUDIO_IN_TypeDef hAudioIn;
+
+/* SAI DMA handle */
+static DMA_HandleTypeDef hDmaSai;
+/**
+  * @}
+  */
+
+/* Exported variables ---------------------------------------------------------*/
+/** @defgroup STM32L476G_DISCOVERY_AUDIO_Exported_Variables Exported Variables
+  * @{
+  */
+/* SAIx handle */
+SAI_HandleTypeDef               BSP_AUDIO_hSai;
+    
+/* DFSDM filter handle */
+DFSDM_Filter_HandleTypeDef      BSP_AUDIO_hDfsdmLeftFilter;
+/**
+  * @}
+  */
+
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Functions Private Functions
+  * @{
+  */
+static void    AUDIO_CODEC_Reset(void);
+static uint8_t AUDIO_SAIx_Init(uint32_t AudioFreq);
+static uint8_t AUDIO_SAIx_DeInit(void);
+static uint8_t AUDIO_DFSDMx_Init(uint32_t AudioFreq);
+static uint8_t AUDIO_DFSDMx_DeInit(void);
+static uint8_t AUDIO_SAIPLLConfig(uint32_t AudioFreq);
+/**
+  * @}
+  */
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup STM32L476G_DISCOVERY_AUDIO_Exported_Functions
+  * @{
+  */ 
+
+/**
+  * @brief  Configures the audio codec related peripherals.
+  * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
+  *                       or OUTPUT_DEVICE_BOTH.
+  * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
+  * @param  AudioFreq: Audio frequency used to play the audio stream.ion.  
+  * @retval BSP AUDIO status
+  * @note   The SAI PLL input clock must be configure in the user application.
+  *         The SAI PLL configuration done within this function assumes that
+  *         the SAI PLL input clock runs at 8 MHz.
+  */
+
+/**
+  * @brief  Tx Transfer completed callbacks.
+  * @param  hsai: SAI handle
+  * @retval None
+  */
+void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
+{
+  /* Invoke the registered 'TransferComplete' function (if any) */
+  if (hAudioOut.CbTransferComplete != (Audio_CallbackTypeDef)NULL)
+  {
+    hAudioOut.CbTransferComplete();
+  }
+}
+
+/**
+  * @brief  Tx Half Transfer completed callbacks.
+  * @param  hsai: SAI handle
+  * @retval None
+  */
+void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
+{
+  /* Invoke the registered 'HalfTransfer' callback function (if any) */
+  if (hAudioOut.CbHalfTransfer != (Audio_CallbackTypeDef)NULL)
+  {
+    hAudioOut.CbHalfTransfer();
+  }
+}
+
+/**
+  * @brief  SAI error callbacks.
+  * @param  hsai: SAI handle
+  * @retval None
+  */
+void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
+{
+  /* Invoke the registered 'ErrorCallback' callback function (if any) */
+  if (hAudioOut.CbError != (Audio_CallbackTypeDef)NULL)
+  {
+    hAudioOut.CbError();
+  }
+}
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32L476G_EVAL_AUDIO_Exported_Functions
+  * @{
+  */
+  
+/**
+  * @brief  Initializes micropone related peripherals.
+  * @note   This function assumes that the SAI input clock (through PLL_M)
+  *         is already configured and ready to be used.  
+  * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral. 
+  * @param  BitRes: Audio frequency to be configured for the SAI peripheral.
+  * @param  ChnlNbr: Audio frequency to be configured for the SAI peripheral.
+  * @retval BSP AUDIO status
+  */
+uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
+{
+  /* Update the audio input context */
+  hAudioIn.Frequency          = AudioFreq;
+  hAudioIn.BitResolution      = BitRes;
+  hAudioIn.ChannelNbr         = ChnlNbr;
+  hAudioIn.CbError            = (Audio_CallbackTypeDef)NULL; 
+  hAudioIn.CbHalfTransfer     = (Audio_CallbackTypeDef)NULL; 
+  hAudioIn.CbTransferComplete = (Audio_CallbackTypeDef)NULL;
+
+  /* Configure the SAI PLL according to the requested audio frequency */
+  if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK)
+  {
+    return AUDIO_ERROR;
+  }
+ 
+  /* Initializes the Digital Filter for Sigma-Delta Modulators interface */
+  if(AUDIO_DFSDMx_Init(AudioFreq) != AUDIO_OK)
+  {
+    return AUDIO_ERROR;
+  }
+  
+  return AUDIO_OK;
+  }
+
+/**
+  * @brief  De-Initializes microphone related peripherals.
+  * @retval BSP AUDIO status
+
+  */
+uint8_t BSP_AUDIO_IN_DeInit(void)
+{
+  /* De-initializes the Digital Filter for Sigma-Delta Modulators interface */
+  if (AUDIO_DFSDMx_DeInit() != AUDIO_OK)
+  {
+    return AUDIO_ERROR;
+  }
+  
+  /* Reset the audio input context */
+  memset(&hAudioIn, 0, sizeof(hAudioIn));
+
+  return AUDIO_OK;
+}
+
+/**
+  * @brief  Starts audio recording.
+  * @param  pbuf: Main buffer pointer for the recorded data storing  
+  * @param  size: Current size of the recorded buffer
+  * @note   The Right channel is start at first with synchro on start of Left channel
+  * @retval BSP AUDIO status
+  */
+uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size)
+{
+  hAudioIn.pRecBuf = pbuf;
+  hAudioIn.RecSize = size;
+
+  /* Allocate hAudioIn.LeftRecBuff buffer */
+#if defined(BSP_AUDIO_USE_RTOS)
+  hAudioIn.LeftRecBuff  = (int32_t *)k_malloc(size * sizeof(int32_t));
+#else
+  hAudioIn.LeftRecBuff  = (int32_t *)malloc(size * sizeof(int32_t));
+#endif
+  if(hAudioIn.LeftRecBuff == NULL)
+  {
+    return AUDIO_ERROR;
+  }
+
+  /* Call the Media layer start function for left channel */
+  if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmLeftFilter, 
+                                      (int32_t*)hAudioIn.LeftRecBuff, 
+                                      (hAudioIn.RecSize/DEFAULT_AUDIO_IN_CHANNEL_NBR)) != HAL_OK)
+  {
+    return AUDIO_ERROR;
+  }
+
+  return AUDIO_OK;
+}
+
+/**
+  * @brief  Updates the audio frequency.
+  * @param  AudioFreq: Audio frequency used to record the audio stream.
+  * @note   This API should be called after the BSP_AUDIO_IN_Init() to adjust the
+  *         audio frequency.
+  * @retval BSP AUDIO status
+  */
+uint8_t BSP_AUDIO_IN_SetFrequency(uint32_t AudioFreq)
+{ 
+  /* Configure the SAI PLL according to the requested audio frequency */
+  if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK)
+  {
+    return AUDIO_ERROR;
+  }
+
+  /* De-initializes the Digital Filter for Sigma-Delta Modulators interface */
+  if(AUDIO_DFSDMx_DeInit() != AUDIO_OK)
+  {
+    return AUDIO_ERROR;
+  }
+  
+  /* Initializes the Digital Filter for Sigma-Delta Modulators interface */
+  if(AUDIO_DFSDMx_Init(AudioFreq) != AUDIO_OK)
+  {
+    return AUDIO_ERROR;
+  }
+  
+  return AUDIO_OK;
+}
+
+/**
+  * @brief  Regular conversion complete callback. 
+  * @note   In interrupt mode, user has to read conversion value in this function
+            using HAL_DFSDM_FilterGetRegularValue.
+  * @param  hdfsdm_filter : DFSDM filter handle.
+  * @retval None
+  */
+void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+  uint32_t index;
+  uint32_t recbufsize = (hAudioIn.RecSize/DEFAULT_AUDIO_IN_CHANNEL_NBR);
+  
+  for(index = (recbufsize/2); index < recbufsize; index++)
+  {
+    hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32760, 32760));
+  }
+  
+  /* Invoke the registered 'TransferComplete' function (if any) */
+  if (hAudioIn.CbTransferComplete != (Audio_CallbackTypeDef)NULL)
+  {
+    hAudioIn.CbTransferComplete();
+  }
+}
+
+/**
+  * @brief  Half regular conversion complete callback. 
+  * @param  hdfsdm_filter : DFSDM filter handle.
+  * @retval None
+  */
+void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+  uint32_t index;
+  uint32_t recbufsize = (hAudioIn.RecSize/DEFAULT_AUDIO_IN_CHANNEL_NBR);
+  
+  
+  for(index = 0; index < (recbufsize/2); index++)
+  {
+    hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32760, 32760));
+  }
+  
+  /* Invoke the registered 'HalfTransfer' callback function (if any) */
+  if (hAudioIn.CbHalfTransfer != (Audio_CallbackTypeDef)NULL)
+  {
+    hAudioIn.CbHalfTransfer();
+  }
+}
+
+/**
+  * @brief  Error callback. 
+  * @param  hdfsdm_filter : DFSDM filter handle.
+  * @retval None
+  */
+void HAL_DFSDM_FilterErrorCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+  /* Invoke the registered 'ErrorCallback' callback function (if any) */
+  if (hAudioIn.CbError != (Audio_CallbackTypeDef)NULL)
+  {
+    hAudioIn.CbError();
+  }
+}
+
+/**
+  * @brief  Stops audio recording.
+  * @retval BSP AUDIO status
+  */
+uint8_t BSP_AUDIO_IN_Stop(void)
+{
+  /* Call the Media layer stop function for left channel */
+  if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK )
+  {
+    return AUDIO_ERROR;
+  }
+
+  /* Free hAudioIn.LeftRecBuff buffer */
+#if defined(BSP_AUDIO_USE_RTOS)
+  k_free((void *)hAudioIn.LeftRecBuff);
+#else
+  free((void *)hAudioIn.LeftRecBuff);
+#endif
+  
+  return AUDIO_OK;
+}
+
+/**
+  * @brief  Pauses the audio file stream.
+  * @retval BSP AUDIO status
+  */
+uint8_t BSP_AUDIO_IN_Pause(void)
+{    
+  /* Call the Media layer stop function */
+  if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK)
+  {
+    return AUDIO_ERROR;
+  }
+  
+  return AUDIO_OK;
+}
+
+/**
+  * @brief  Resumes the audio file stream.
+  * @retval BSP AUDIO status
+  */
+uint8_t BSP_AUDIO_IN_Resume(void)
+{    
+  /* Call the Media layer start function for left channel */
+  if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmLeftFilter,
+                                      (int32_t*)hAudioIn.LeftRecBuff,
+                                      (hAudioIn.RecSize/DEFAULT_AUDIO_IN_CHANNEL_NBR)) != HAL_OK)
+  {
+    return AUDIO_ERROR;
+  }
+  
+  return AUDIO_OK;
+}
+
+/**
+  * @brief  register user callback functions 
+  * @param  ErrorCallback: pointer to the error callback function
+  * @param  HalfTransferCallback: pointer to the half transfer callback function
+  * @param  TransferCompleteCallback: pointer to the transfer complete callback function
+  * @retval None
+  */
+void BSP_AUDIO_IN_RegisterCallbacks(Audio_CallbackTypeDef ErrorCallback,
+                                    Audio_CallbackTypeDef HalfTransferCallback, 
+                                    Audio_CallbackTypeDef TransferCompleteCallback)
+{
+  hAudioIn.CbError            = ErrorCallback; 
+  hAudioIn.CbHalfTransfer     = HalfTransferCallback; 
+  hAudioIn.CbTransferComplete = TransferCompleteCallback;
+}
+/**
+  * @}
+  */
+
+/* private functions --------------------------------------------------------*/
+/** @addtogroup STM32L476G_DISCOVERY_AUDIO_Private_Functions
+  * @{
+  */
+/**
+  * @brief  Initializes the Audio Codec audio interface (SAI).
+  * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
+  * @note   The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 
+  *         and user can update this configuration using 
+  * @retval BSP AUDIO status
+  */
+static uint8_t AUDIO_SAIx_Init(uint32_t AudioFreq)
+{
+  /* Disable SAI peripheral to allow access to SAI internal registers */
+  __HAL_SAI_DISABLE(&BSP_AUDIO_hSai);
+  
+  /* Initialize the BSP_AUDIO_hSai Instance parameter */
+  BSP_AUDIO_hSai.Instance = AUDIO_SAIx;
+  
+  /* Configure SAI_Block_x 
+  LSBFirst: Disabled 
+  DataSize: 16 */
+  BSP_AUDIO_hSai.Init.AudioMode      = SAI_MODEMASTER_TX;
+  BSP_AUDIO_hSai.Init.Synchro        = SAI_ASYNCHRONOUS;
+  BSP_AUDIO_hSai.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
+  BSP_AUDIO_hSai.Init.OutputDrive    = SAI_OUTPUTDRIVE_ENABLE;
+  BSP_AUDIO_hSai.Init.NoDivider      = SAI_MASTERDIVIDER_ENABLE;
+  BSP_AUDIO_hSai.Init.FIFOThreshold  = SAI_FIFOTHRESHOLD_1QF;
+  BSP_AUDIO_hSai.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV;
+  BSP_AUDIO_hSai.Init.Mckdiv         = SAIClockDivider(AudioFreq);
+  BSP_AUDIO_hSai.Init.MonoStereoMode = SAI_STEREOMODE;
+  BSP_AUDIO_hSai.Init.CompandingMode = SAI_NOCOMPANDING;
+  BSP_AUDIO_hSai.Init.TriState       = SAI_OUTPUT_NOTRELEASED;
+  BSP_AUDIO_hSai.Init.Protocol       = SAI_FREE_PROTOCOL;
+  BSP_AUDIO_hSai.Init.DataSize       = SAI_DATASIZE_16;
+  BSP_AUDIO_hSai.Init.FirstBit       = SAI_FIRSTBIT_MSB;
+  BSP_AUDIO_hSai.Init.ClockStrobing  = SAI_CLOCKSTROBING_RISINGEDGE;
+  
+  /* Configure SAI_Block_x Frame 
+  Frame Length: 32
+  Frame active Length: 16
+  FS Definition: Start frame + Channel Side identification
+  FS Polarity: FS active Low
+  FS Offset: FS asserted one bit before the first bit of slot 0 */ 
+  BSP_AUDIO_hSai.FrameInit.FrameLength = 32;
+  BSP_AUDIO_hSai.FrameInit.ActiveFrameLength = 16;
+  BSP_AUDIO_hSai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
+  BSP_AUDIO_hSai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
+  BSP_AUDIO_hSai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
+  
+  /* Configure SAI Block_x Slot 
+  Slot First Bit Offset: 0
+  Slot Size  : 16
+  Slot Number: 2
+  Slot Active: Slots 0 and 1 actives */
+  BSP_AUDIO_hSai.SlotInit.FirstBitOffset = 0;
+  BSP_AUDIO_hSai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
+  BSP_AUDIO_hSai.SlotInit.SlotNumber = 2; 
+  BSP_AUDIO_hSai.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1;
+
+  /* Initializes the SAI peripheral*/
+  if (HAL_SAI_Init(&BSP_AUDIO_hSai) != HAL_OK)
+  {
+    return AUDIO_ERROR;
+  }
+  
+  /* Enable SAI peripheral to generate MCLK */
+  __HAL_SAI_ENABLE(&BSP_AUDIO_hSai);
+  
+  return AUDIO_OK;
+  
+}
+
+/**
+  * @brief  De-initializes the Audio Codec audio interface (SAI).
+  * @retval BSP AUDIO status
+  */
+static uint8_t AUDIO_SAIx_DeInit(void)
+{
+  /* Disable the SAI audio block */
+  __HAL_SAI_DISABLE(&BSP_AUDIO_hSai);
+
+  /* De-initializes the SAI peripheral */
+  if (HAL_SAI_DeInit(&BSP_AUDIO_hSai) != HAL_OK)
+  {
+    return AUDIO_ERROR;
+  }
+  
+  /* Disable SAIx PLL */
+  if (AUDIO_SAIx_PLL_DISABLE() != AUDIO_OK)
+  {
+    return AUDIO_ERROR;
+  }  
+  
+  return AUDIO_OK;
+}
+
+/**
+  * @brief  SAI MSP Init
+  * @param  hsai : pointer to a SAI_HandleTypeDef structure
+  * @retval None
+  */
+void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
+{ 
+  GPIO_InitTypeDef  GPIO_InitStruct;  
+
+  /* Enable SAI clock */
+  AUDIO_SAIx_CLK_ENABLE();
+  
+  /* Enable GPIO clock */
+  AUDIO_SAIx_MCK_SCK_SD_FS_ENABLE();
+  
+  /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/
+  GPIO_InitStruct.Pin = AUDIO_SAIx_FS_PIN | AUDIO_SAIx_SCK_PIN | AUDIO_SAIx_SD_PIN | AUDIO_SAIx_MCK_PIN;
+  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+  GPIO_InitStruct.Alternate = AUDIO_SAIx_MCK_SCK_SD_FS_AF;
+  HAL_GPIO_Init(AUDIO_SAIx_MCK_SCK_SD_FS_GPIO_PORT, &GPIO_InitStruct);
+
+  /* Enable the DMA clock */
+  AUDIO_SAIx_DMAx_CLK_ENABLE();
+    
+  if(hsai->Instance == AUDIO_SAIx)
+  {
+    /* Configure the hDmaSai handle parameters */   
+    hDmaSai.Init.Request             = DMA_REQUEST_1;
+    hDmaSai.Init.Direction           = DMA_MEMORY_TO_PERIPH;
+    hDmaSai.Init.PeriphInc           = DMA_PINC_DISABLE;
+    hDmaSai.Init.MemInc              = DMA_MINC_ENABLE;
+    hDmaSai.Init.PeriphDataAlignment = AUDIO_SAIx_DMAx_PERIPH_DATA_SIZE;
+    hDmaSai.Init.MemDataAlignment    = AUDIO_SAIx_DMAx_MEM_DATA_SIZE;
+    hDmaSai.Init.Mode                = DMA_NORMAL;
+    hDmaSai.Init.Priority            = DMA_PRIORITY_HIGH;
+    
+    hDmaSai.Instance = AUDIO_SAIx_DMAx_CHANNEL;
+    
+    /* Associate the DMA handle */
+    __HAL_LINKDMA(hsai, hdmatx, hDmaSai);
+    
+    /* Deinitialize the Stream for new transfer */
+    HAL_DMA_DeInit(&hDmaSai);
+    
+    /* Configure the DMA Stream */
+    HAL_DMA_Init(&hDmaSai);      
+  }
+  
+  /* SAI DMA IRQ Channel configuration */
+  HAL_NVIC_SetPriority(AUDIO_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
+  HAL_NVIC_EnableIRQ(AUDIO_SAIx_DMAx_IRQ); 
+}
+
+/**
+  * @brief  SAI MSP De-init
+  * @param  hsai : pointer to a SAI_HandleTypeDef structure
+  * @retval None
+  */
+void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
+{
+  /* Disable SAI DMA Channel IRQ  */
+  HAL_NVIC_DisableIRQ(AUDIO_SAIx_DMAx_IRQ); 
+
+  /* Reset the DMA Stream configuration*/
+  HAL_DMA_DeInit(&hDmaSai);
+  
+  /* Disable the DMA clock */
+  AUDIO_SAIx_DMAx_CLK_DISABLE();
+    
+  /* De-initialize FS, SCK, MCK and SD pins*/
+  HAL_GPIO_DeInit(AUDIO_SAIx_MCK_SCK_SD_FS_GPIO_PORT, 
+                  AUDIO_SAIx_FS_PIN | AUDIO_SAIx_SCK_PIN | AUDIO_SAIx_SD_PIN | AUDIO_SAIx_MCK_PIN);
+  
+  /* Disable GPIO clock */
+  AUDIO_SAIx_MCK_SCK_SD_FS_DISABLE();
+  
+  /* Disable SAI clock */
+  AUDIO_SAIx_CLK_DISABLE();
+}
+
+/**
+  * @brief  Resets the audio codec. It restores the default configuration of the 
+  *         codec (this function shall be called before initializing the codec).
+  * @retval None
+  */
+
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32L476G_DISCOVERY_AUDIO_Private_Functions
+  * @{
+  */ 
+
+/**
+  * @brief  Initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
+  * @param  AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral.
+  * @retval BSP AUDIO status
+  */
+static uint8_t AUDIO_DFSDMx_Init(uint32_t AudioFreq)
+{
+  /*####CHANNEL 2####*/
+  hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Activation   = ENABLE;
+  hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
+  /* Set the DFSDM clock OUT audio frequency configuration */
+  hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Divider      = DFSDMClockDivider(AudioFreq);
+  hAudioIn.hDfsdmLeftChannel.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
+  hAudioIn.hDfsdmLeftChannel.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
+  hAudioIn.hDfsdmLeftChannel.Init.Input.Pins               = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
+  /* Request to sample stable data for LEFT micro on Rising edge */
+  hAudioIn.hDfsdmLeftChannel.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_RISING;
+  hAudioIn.hDfsdmLeftChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
+  hAudioIn.hDfsdmLeftChannel.Init.Awd.FilterOrder          = DFSDM_CHANNEL_SINC1_ORDER;
+  hAudioIn.hDfsdmLeftChannel.Init.Awd.Oversampling         = 10;
+  hAudioIn.hDfsdmLeftChannel.Init.Offset                   = 0;
+  hAudioIn.hDfsdmLeftChannel.Init.RightBitShift            = DFSDMRightBitShift(AudioFreq);
+
+  hAudioIn.hDfsdmLeftChannel.Instance                      = DFSDM_Channel2;
+
+    /* Init the DFSDM Channel */
+  if (HAL_DFSDM_ChannelInit(&hAudioIn.hDfsdmLeftChannel) != HAL_OK)
+  {
+    return AUDIO_ERROR;
+  }
+
+  /*####FILTER 0####*/
+  BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.Trigger         = DFSDM_FILTER_SW_TRIGGER;
+  BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.FastMode        = ENABLE;
+  BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.DmaMode         = ENABLE;
+  BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
+  BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ScanMode       = DISABLE;
+  BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.DmaMode        = DISABLE;
+  BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO;
+  BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES;
+  BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.SincOrder        = DFSDMFilterOrder(AudioFreq);
+  /* Set the DFSDM Filters Oversampling to have correct sample rate */
+  BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.Oversampling     = DFSDMOverSampling(AudioFreq);
+  BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.IntOversampling  = 1;
+  
+  BSP_AUDIO_hDfsdmLeftFilter.Instance                          = AUDIO_DFSDMx_LEFT_FILTER;
+
+    /* Init the DFSDM Filter */
+  if (HAL_DFSDM_FilterInit(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK)
+  {
+    return AUDIO_ERROR;
+  }
+  
+  /* Configure regular channel */
+  if (HAL_DFSDM_FilterConfigRegChannel(&BSP_AUDIO_hDfsdmLeftFilter, 
+                                      DFSDM_CHANNEL_2, 
+                                      DFSDM_CONTINUOUS_CONV_ON) != HAL_OK)
+  {
+    return AUDIO_ERROR;
+  }
+
+  return AUDIO_OK;
+}
+
+/**
+  * @brief  De-initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
+  * @retval BSP AUDIO status
+  */
+static uint8_t AUDIO_DFSDMx_DeInit(void)
+{
+  /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */
+  if (HAL_DFSDM_FilterDeInit(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK)
+  {
+    return AUDIO_ERROR;
+  }
+
+  /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */
+  if (HAL_DFSDM_ChannelDeInit(&hAudioIn.hDfsdmLeftChannel) != HAL_OK)
+  {
+    return AUDIO_ERROR;
+  }
+
+  /* Disable DFSDM clock */
+  AUDIO_DFSDMx_CLK_DISABLE();
+
+  /* Disable SAIx PLL */
+  if (AUDIO_SAIx_PLL_DISABLE() != AUDIO_OK)
+  {
+    return AUDIO_ERROR;
+  }  
+
+  /* DFSDM reset */
+  __HAL_RCC_DFSDM_FORCE_RESET();
+  __HAL_RCC_DFSDM_RELEASE_RESET();
+
+  return AUDIO_OK;
+}
+
+/**
+  * @brief  Initializes the DFSDM channel MSP.
+  * @param  hdfsdm_channel : DFSDM channel handle.
+  * @retval None
+  */
+void HAL_DFSDM_ChannelMspInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+  GPIO_InitTypeDef  GPIO_InitStruct;  
+
+  /* Enable DFSDM clock */
+  AUDIO_DFSDMx_CLK_ENABLE();
+  
+  /* Enable GPIO clock */
+  AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_CLK_ENABLE();
+  
+  /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN pins ------------------*/
+  GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN | AUDIO_DFSDMx_DMIC_DATIN_PIN;
+  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+  GPIO_InitStruct.Alternate = AUDIO_DFSDMx_CKOUT_DMIC_DATIN_AF;
+  HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct);
+}
+
+/**
+  * @brief  De-initializes the DFSDM channel MSP.
+  * @param  hdfsdm_channel : DFSDM channel handle.
+  * @retval None
+  */
+void HAL_DFSDM_ChannelMspDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
+{
+  GPIO_InitTypeDef  GPIO_InitStruct;
+  
+  /* Enable GPIO clock */
+  AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_CLK_ENABLE();
+  
+  /* DFSDM pins configuration: DFSDM_CKOUT */
+  GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN;
+  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+  HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct);
+  HAL_GPIO_WritePin(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, AUDIO_DFSDMx_CKOUT_PIN, GPIO_PIN_RESET);
+
+
+  /* De-initialize DMIC_DATIN pin */
+  HAL_GPIO_DeInit(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, AUDIO_DFSDMx_DMIC_DATIN_PIN);
+}
+
+/**
+  * @brief  Initializes the DFSDM filter MSP.
+  * @param  hdfsdm_filter : DFSDM filter handle.
+  * @retval None
+  */
+void HAL_DFSDM_FilterMspInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+  /* Enable DFSDM clock */
+  AUDIO_DFSDMx_CLK_ENABLE();
+  
+  /* Enable the DMA clock */
+  AUDIO_DFSDMx_DMAx_CLK_ENABLE();
+    
+  /* Configure the hAudioIn.hDmaDfsdmLeft handle parameters */   
+  hAudioIn.hDmaDfsdmLeft.Init.Request             = DMA_REQUEST_0;
+  hAudioIn.hDmaDfsdmLeft.Init.Direction           = DMA_PERIPH_TO_MEMORY;
+  hAudioIn.hDmaDfsdmLeft.Init.PeriphInc           = DMA_PINC_DISABLE;
+  hAudioIn.hDmaDfsdmLeft.Init.MemInc              = DMA_MINC_ENABLE;
+  hAudioIn.hDmaDfsdmLeft.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
+  hAudioIn.hDmaDfsdmLeft.Init.MemDataAlignment    = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
+  hAudioIn.hDmaDfsdmLeft.Init.Mode                = DMA_CIRCULAR;
+  hAudioIn.hDmaDfsdmLeft.Init.Priority            = DMA_PRIORITY_HIGH;
+
+  hAudioIn.hDmaDfsdmLeft.Instance               = AUDIO_DFSDMx_DMAx_LEFT_CHANNEL;
+  
+  /* Associate the DMA handle */
+  __HAL_LINKDMA(hdfsdm_filter, hdmaReg, hAudioIn.hDmaDfsdmLeft);
+  
+  /* Reset DMA handle state */
+  __HAL_DMA_RESET_HANDLE_STATE(&hAudioIn.hDmaDfsdmLeft);
+
+  /* Configure the DMA Channel */
+  HAL_DMA_Init(&hAudioIn.hDmaDfsdmLeft);      
+
+  /* DMA IRQ Channel configuration */
+    HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_LEFT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
+    HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_LEFT_IRQ);
+  }
+
+ /**
+  * @brief  De-initializes the DFSDM filter MSP.
+  * @param  hdfsdm_filter : DFSDM filter handle.
+  * @retval None
+  */
+void HAL_DFSDM_FilterMspDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
+{
+  /* Disable DMA  Channel IRQ */
+  HAL_NVIC_DisableIRQ(AUDIO_DFSDMx_DMAx_LEFT_IRQ);
+
+  /* De-initialize the DMA Channel */
+  HAL_DMA_DeInit(&hAudioIn.hDmaDfsdmLeft);      
+
+  /* Disable the DMA clock */
+  AUDIO_DFSDMx_DMAx_CLK_DISABLE();
+}
+
+/**
+  * @brief  Configures the SAI PLL clock according to the required audio frequency.
+  * @param  Frequency: Audio frequency.  
+  * @retval BSP AUDIO status
+  * @note   The SAI PLL input clock must be configured in the user application.
+  *         The SAI PLL configuration done within this function assumes that
+  *         the SAI PLL input clock runs at 8 MHz.
+  */
+static uint8_t AUDIO_SAIPLLConfig(uint32_t Frequency)
+{
+  RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct;
+
+  /* Retreive actual RCC configuration */
+  HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct);
+  
+    if (   (Frequency == AUDIO_FREQUENCY_11K) 
+        || (Frequency == AUDIO_FREQUENCY_22K)
+        || (Frequency == AUDIO_FREQUENCY_44K) )
+  {
+    /* Configure PLLSAI prescalers */
+    /* SAI clock config 
+    PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 24 = VCO_192M 
+    SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 192/17 = 11.294 Mhz */  
+    RCC_ExCLKInitStruct.PeriphClockSelection    = RCC_PERIPHCLK_SAI1;
+    RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N        = 24; 
+    RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P        = 17; 
+    RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
+    RCC_ExCLKInitStruct.Sai1ClockSelection      = RCC_SAI1CLKSOURCE_PLLSAI1;
+  }
+  else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
+  {
+    /* SAI clock config 
+    PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 43 = VCO_344M 
+    SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 344/7 = 49.142 Mhz */  
+    RCC_ExCLKInitStruct.PeriphClockSelection    = RCC_PERIPHCLK_SAI1;
+    RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N        = 43;
+    RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P        = 7;
+    RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
+    RCC_ExCLKInitStruct.Sai1ClockSelection      = RCC_SAI1CLKSOURCE_PLLSAI1;
+  }
+  
+  if (HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct) != HAL_OK)
+  {
+    return AUDIO_ERROR;
+  }    
+
+  return AUDIO_OK;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
+