ST / BSP_DISCO_L4R9I

Dependents:   DISCO_L4R9I-LCD-demo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32l4r9i_discovery_audio.c Source File

stm32l4r9i_discovery_audio.c

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l4r9i_discovery_audio.c
00004   * @author  MCD Application Team
00005   * @brief   This file provides a set of functions needed to manage the
00006   *          Audio driver for the STM32L4R9I_DISCOVERY board.
00007   ******************************************************************************
00008   * @attention
00009   *
00010   * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
00011   * All rights reserved.</center></h2>
00012   *
00013   * This software component is licensed by ST under BSD 3-Clause license,
00014   * the "License"; You may not use this file except in compliance with the
00015   * License. You may obtain a copy of the License at:
00016   *                        opensource.org/licenses/BSD-3-Clause
00017   *
00018   ******************************************************************************
00019   */
00020 
00021 /*==============================================================================
00022                                  User NOTES
00023 
00024 1. How To use this driver:
00025 --------------------------
00026    + This driver supports STM32L4xx devices on STM32L4R9I_DISCOVERY (MB1311) Discovery boards.
00027         a) to play an audio file through headset. All functions names start by BSP_AUDIO_OUT_xxx.
00028         b) to record an audio file through digital microphones (MP34DT01TR ST mems)
00029            or analog microphone (headset microphone). All functions names start by BSP_AUDIO_IN_xxx.
00030 
00031 a) PLAY A FILE:
00032 ==============
00033    + Call the function BSP_AUDIO_OUT_Init(
00034                                     OutputDevice: physical output mode (only OUTPUT_DEVICE_HEADPHONE).
00035                                     Volume      : Initial volume to be set (0 is min (mute), 100 is max (100%)
00036                                     AudioFreq   : Audio frequency in Hz (8000, 16000, 22500, 32000...)
00037                                                   this parameter is relative to the audio file/stream type.
00038                                    )
00039       This function configures all the hardware required for the audio application (codec, I2C, SAI,
00040       GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK.
00041       If the returned value is different from AUDIO_OK or the function is stuck then the communication with
00042       the audio codec has failed.
00043       - OUTPUT_DEVICE_HEADPHONE: only Headphone output is available on this board.
00044 
00045    + Call the function BSP_AUDIO_OUT_RegisterCallbacks to register user callbacks
00046      required to manage audio data streaming towards the audio codec (ErrorCallback(),
00047      HalfTransfer_CallBack() and TransferComplete_CallBack()).
00048 
00049    + Call the function BSP_AUDIO_OUT_Play() to start audio playback (for the first time).
00050    + Call the function BSP_AUDIO_OUT_Pause() to pause audio playback.
00051    + Call the function BSP_AUDIO_OUT_Resume() to resume audio playback.
00052        Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called
00053           for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case).
00054        Note. This function should be called only when the audio file is played or paused (not stopped).
00055    + Call the function BSP_AUDIO_OUT_Stop() to stop audio playback.
00056    + To modify the volume level, the sampling frequency, the device output mode,
00057       the mute status or the audio configuration or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(),
00058       AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetOutputMode(), BSP_AUDIO_OUT_SetMute()and
00059       BSP_AUDIO_OUT_ChangeAudioConfig().
00060 
00061 Driver architecture:
00062 --------------------
00063    + This driver provides the audio layer high level API: it consists in functions
00064      exported in the stm32l4r9i_discovery_audio.h file (e.g. BSP_AUDIO_OUT_Init(),
00065      BSP_AUDIO_OUT_Play(), ...).
00066    + This driver also includes the Media Access Layer (MAL): it consists in
00067      functions allowing to access setup the audio devices. These functions
00068      are  included as local functions into the stm32l4r9i_discovery_audio.c file
00069      (e.g. AUDIO_SAIx_Init()).
00070 
00071 Known Limitations:
00072 ------------------
00073    1- Communication with the audio codec (through I2C) may be corrupted if it is interrupted by some
00074       user interrupt routines (in this case, interrupts could be disabled just before the start of
00075       communication then re-enabled when it is over). Note that this communication is only done at
00076       the configuration phase (BSP_AUDIO_OUT_Init() or BSP_AUDIO_OUT_Stop()) and when Volume control modification is
00077       performed (BSP_AUDIO_OUT_SetVolume() or BSP_AUDIO_OUT_SetMute()or BSP_AUDIO_OUT_SetOutputMode()).
00078       When the audio data is played, no communication is required with the audio codec.
00079    2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size,
00080       File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file.
00081    3- Supports only 16-bits audio data size.
00082 
00083 b) RECORD A FILE:
00084 ================
00085    + Call the function BSP_AUDIO_IN_InitEx(
00086                                     InputDevice: physical input mode (INPUT_DEVICE_DIGITAL_MIC
00087                                                   INPUT_DEVICE_DIGITAL_MIC1, INPUT_DEVICE_DIGITAL_MIC2
00088                                                   or INPUT_DEVICE_ANALOG_MIC)
00089                                     AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...)
00090                                     )
00091       This function configures all the hardware required for the audio application (DFSDM or SAI,
00092       GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if the
00093       configuration completes successfully.
00094       - INPUT_DEVICE_DIGITAL_MIC: Record from digital microphones mounted on board.
00095       - INPUT_DEVICE_DIGITAL_MIC1: Record from digital microphone 1 mounted on board (left microphone).
00096       - INPUT_DEVICE_DIGITAL_MIC2: Record from digital microphone 2 mounted on board (right microphone).
00097       - INPUT_DEVICE_ANALOG_MIC: Record from headset microphone.
00098 
00099    + Call the function BSP_AUDIO_IN_RegisterCallbacks to register user callbacks
00100      used to stream audio data toward the record buffer (ErrorCallback(),
00101      HalfTransfer_CallBack() and TransferComplete_CallBack()).
00102 
00103    + Call the function BSP_AUDIO_IN_Record(
00104                             pbuf Main buffer pointer for the recorded data storing
00105                             size Current size of the recorded buffer
00106                             )
00107       to start recording from the microphone.
00108 
00109    + Call the function BSP_AUDIO_IN_Stop() to stop recording.
00110 ==============================================================================*/
00111 
00112 /* Includes ------------------------------------------------------------------*/
00113 #include <string.h>
00114 #include "stm32l4r9i_discovery_audio.h"
00115 
00116 /** @addtogroup BSP
00117   * @{
00118   */
00119 
00120 /** @addtogroup STM32L4R9I_DISCOVERY
00121   * @{
00122   */
00123 
00124 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO STM32L4R9I_DISCOVERY AUDIO
00125   * @brief This file includes the low layer driver for cs42l51 Audio Codec
00126   *        available on STM32L4R9I_DISCOVERY board (MB1311).
00127   * @{
00128   */
00129 
00130 /* Private typedef -----------------------------------------------------------*/
00131 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Private_Types Private Types
00132   * @{
00133   */
00134 typedef struct
00135 {
00136   AUDIO_DrvTypeDef *    AudioDrv;           /* Audio codec driver */
00137   uint32_t              OutputDevice;       /* Output device */
00138   uint32_t              Frequency;          /* Playback frequency */
00139   uint32_t              Volume;             /* Playback volume */
00140   Audio_CallbackTypeDef CbError;            /* pointer to the callback function invoked when error occurs */
00141   Audio_CallbackTypeDef CbHalfTransfer;     /* pointer to the callback function invoked when half transfer occurs */
00142   Audio_CallbackTypeDef CbTransferComplete; /* pointer to the callback function invoked when transfer complete occurs */
00143 } AUDIO_OUT_TypeDef;
00144 
00145 typedef struct
00146 {
00147   AUDIO_DrvTypeDef *          AudioDrv;           /* Audio codec driver */
00148   DFSDM_Channel_HandleTypeDef hDfsdmLeftChannel;  /* DFSDM channel handle used for left channel */
00149   DFSDM_Channel_HandleTypeDef hDfsdmRightChannel; /* DFSDM channel handle used for right channel */
00150   DMA_HandleTypeDef           hDmaDfsdmLeft;      /* DMA handle used for DFSDM regular conversions on left channel */
00151   DMA_HandleTypeDef           hDmaDfsdmRight;     /* DMA handle used for DFSDM regular conversions on right channel */
00152   int32_t *                   LeftRecBuff;        /* Buffers for left samples */
00153   int32_t *                   RightRecBuff;       /* Buffers for right samples */
00154   uint32_t                    InputDevice;        /* Input device */
00155   uint32_t                    Frequency;          /* Record Frequency */
00156   uint32_t                    BitResolution;      /* Record bit resolution */
00157   uint32_t                    ChannelNbr;         /* Record Channel Number */
00158   uint16_t *                  pRecBuf;            /* Pointer to record user buffer */
00159   uint32_t                    RecSize;            /* Size to record in mono, double size to record in stereo */
00160   Audio_CallbackTypeDef       CbError;            /* pointer to the callback function invoked when a DMA transfer fails */
00161   Audio_CallbackTypeDef       CbHalfTransfer;     /* pointer to the callback function invoked when half of the DMA transfer is completed */
00162   Audio_CallbackTypeDef       CbTransferComplete; /* pointer to the callback function invoked when the DMA transfer is completed */
00163 } AUDIO_IN_TypeDef;
00164 
00165 /**
00166   * @}
00167   */
00168 
00169 /* Private macros ------------------------------------------------------------*/
00170 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Private_Macros Private Macros
00171   * @{
00172   */
00173 /*### PLAY ###*/
00174 /* SCK(kHz) = SAI_CK_x/(SAIClockDivider*2*256) */
00175 #define SAIClockDivider(__FREQUENCY__) \
00176         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 24 \
00177       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \
00178       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 12 \
00179       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 2 \
00180       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 6 \
00181       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 1 \
00182       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 4 : 2  \
00183 
00184 /*### RECORD ###*/
00185 #define DFSDMOverSampling(__FREQUENCY__) \
00186         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 256 \
00187       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \
00188       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \
00189       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \
00190       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \
00191       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64  \
00192       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 16  \
00193 
00194 #define DFSDMClockDivider(__FREQUENCY__) \
00195         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 24 \
00196       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \
00197       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \
00198       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
00199       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \
00200       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4  \
00201       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 32  \
00202 
00203 #define DFSDMFilterOrder(__FREQUENCY__) \
00204         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? DFSDM_FILTER_SINC3_ORDER \
00205       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \
00206       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \
00207       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \
00208       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \
00209       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC4_ORDER  \
00210       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC4_ORDER : DFSDM_FILTER_SINC5_ORDER  \
00211 
00212 #define DFSDMRightBitShift(__FREQUENCY__) \
00213         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 7 \
00214       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 7 \
00215       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 4 \
00216       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
00217       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 7 \
00218       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 7  \
00219       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 3 : 4  \
00220 
00221 /* Saturate the record PCM sample */
00222 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N)))
00223 
00224 /**
00225   * @}
00226   */
00227 
00228 /* Private variables ---------------------------------------------------------*/
00229 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Private_Variables Private Variables
00230   * @{
00231   */
00232 /* Audio output context information */
00233 static AUDIO_OUT_TypeDef hAudioOut = {0};
00234 
00235 /* Audio input context information */
00236 static AUDIO_IN_TypeDef hAudioIn = {0};
00237 
00238 /* SAI DMA handle */
00239 static DMA_HandleTypeDef hDmaSaiTx;
00240 static DMA_HandleTypeDef hDmaSaiRx;
00241 
00242 static uint32_t DmaLeftRecHalfBuffCplt;
00243 static uint32_t DmaLeftRecBuffCplt;
00244 static uint32_t DmaRightRecHalfBuffCplt;
00245 static uint32_t DmaRightRecBuffCplt;
00246 
00247 /**
00248   * @}
00249   */
00250 
00251 /* Exported variables ---------------------------------------------------------*/
00252 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Exported_Variables Exported Variables
00253   * @{
00254   */
00255 /* SAIx handle */
00256 SAI_HandleTypeDef               BSP_AUDIO_hSai_Tx;
00257 SAI_HandleTypeDef               BSP_AUDIO_hSai_Rx;
00258 
00259 /* DFSDM filter handle */
00260 DFSDM_Filter_HandleTypeDef      BSP_AUDIO_hDfsdmLeftFilter;
00261 DFSDM_Filter_HandleTypeDef      BSP_AUDIO_hDfsdmRightFilter;
00262 /**
00263   * @}
00264   */
00265 
00266 /* Private function prototypes -----------------------------------------------*/
00267 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Private_Functions Private Functions
00268   * @{
00269   */
00270 static uint8_t AUDIO_SAIx_Init(uint32_t AudioFreq);
00271 static uint8_t AUDIO_SAIx_DeInit(void);
00272 static uint8_t AUDIO_DFSDMx_Init(uint32_t AudioFreq);
00273 static uint8_t AUDIO_DFSDMx_DeInit(void);
00274 static uint8_t AUDIO_SAIPLLConfig(uint32_t AudioFreq);
00275 /**
00276   * @}
00277   */
00278 
00279 /* Exported functions --------------------------------------------------------*/
00280 /** @addtogroup STM32L4R9I_DISCOVERY_AUDIO_Exported_Functions
00281   * @{
00282   */
00283 
00284 /**
00285   * @brief  Configures the audio codec related peripherals.
00286   * @param  OutputDevice: OUTPUT_DEVICE_HEADPHONE.
00287   * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
00288   * @param  AudioFreq: Audio frequency used to play the audio stream.
00289   * @retval BSP AUDIO status
00290   * @note   The SAI PLL input clock must be configure in the user application.
00291   *         The SAI PLL configuration done within this function assumes that
00292   *         the SAI PLL input clock runs at 8 MHz.
00293   */
00294 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice,
00295                            uint8_t  Volume,
00296                            uint32_t AudioFreq)
00297 {
00298   /* Initialize the audio output context */
00299   hAudioOut.AudioDrv           = &cs42l51_drv;
00300   hAudioOut.OutputDevice       = OutputDevice;
00301   hAudioOut.Frequency          = AudioFreq;
00302   hAudioOut.Volume             = Volume;
00303   hAudioOut.CbError            = (Audio_CallbackTypeDef)NULL;
00304   hAudioOut.CbHalfTransfer     = (Audio_CallbackTypeDef)NULL;
00305   hAudioOut.CbTransferComplete = (Audio_CallbackTypeDef)NULL;
00306 
00307   /* Check if input device is currently used */
00308   if(hAudioIn.InputDevice != 0)
00309   {
00310     /* If input device is currently used, SAI PLL is already initialized */
00311     /* Check that AudioFreq for record and playback is the same */
00312     if(hAudioIn.Frequency != hAudioOut.Frequency)
00313     {
00314       return AUDIO_ERROR;
00315     }
00316   }
00317   else
00318   {
00319     /* Configure the SAI PLL according to the requested audio frequency */
00320     if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK)
00321     {
00322       return AUDIO_ERROR;
00323     }
00324   }
00325 
00326   /* If input device is analogic mic, SAI is already initialized */
00327   if(hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
00328   {
00329     /* SAI data transfer preparation: prepare the Media to be used for the audio
00330     transfer from memory to SAI peripheral. */
00331     if (AUDIO_SAIx_Init(AudioFreq) != AUDIO_OK)
00332     {
00333       return AUDIO_ERROR;
00334     }
00335   }
00336 
00337   /* Initialize the audio codec internal registers */
00338   if (hAudioOut.AudioDrv->Init(AUDIO_I2C_ADDRESS,
00339                                (hAudioOut.OutputDevice | hAudioIn.InputDevice),
00340                                Volume,
00341                                AudioFreq) != 0)
00342   {
00343     return AUDIO_ERROR;
00344   }
00345 
00346   return AUDIO_OK;
00347 }
00348 
00349 /**
00350   * @brief  De-Initializes audio codec related peripherals
00351   * @retval BSP AUDIO status
00352 
00353   */
00354 uint8_t BSP_AUDIO_OUT_DeInit(void)
00355 {
00356   if(hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC)
00357   {
00358     /* Reset playback path on audio codec */
00359     if(hAudioIn.AudioDrv->Init(AUDIO_I2C_ADDRESS,
00360                                hAudioIn.InputDevice,
00361                                (uint8_t) hAudioOut.Volume,
00362                                hAudioIn.Frequency) != 0)
00363     {
00364       return AUDIO_ERROR;
00365     }
00366   }
00367   else
00368   {
00369     /* De-initializes SAI interface */
00370     if(AUDIO_SAIx_DeInit() != AUDIO_OK)
00371     {
00372       return AUDIO_ERROR;
00373     }
00374 
00375     /* DeInit audio codec */
00376     hAudioOut.AudioDrv->DeInit();
00377   }
00378 
00379   /* Disable SAI PLL if no more device is used */
00380   if(hAudioIn.InputDevice == 0)
00381   {
00382     if (AUDIO_SAIx_PLL_DISABLE() != AUDIO_OK)
00383     {
00384       return AUDIO_ERROR;
00385     }
00386   }
00387 
00388   /* Reset the audio output context */
00389   memset(&hAudioOut, 0, sizeof(hAudioOut));
00390 
00391   return AUDIO_OK;
00392 }
00393 
00394 /**
00395   * @brief  Starts playing audio stream from a data buffer for a determined size.
00396   * @param  pData: pointer on PCM samples buffer
00397   * @param  Size: Number of audio data HALF WORD.
00398   * @retval BSP AUDIO status
00399   */
00400 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pData, uint32_t Size)
00401 {
00402   /* Initiate a DMA transfer of PCM samples towards the serial audio interface */
00403   if (HAL_SAI_Transmit_DMA(&BSP_AUDIO_hSai_Tx, (uint8_t *)pData, DMA_MAX(Size))!= HAL_OK)
00404   {
00405     return AUDIO_ERROR;
00406   }
00407 
00408   /* Call the audio Codec Play function */
00409   if (hAudioOut.AudioDrv->Play(AUDIO_I2C_ADDRESS, pData, Size) != 0)
00410   {
00411     return AUDIO_ERROR;
00412   }
00413 
00414   return AUDIO_OK;
00415   }
00416 
00417 /**
00418   * @brief  Sends n-Bytes on the SAI interface.
00419   * @param  pData: pointer on PCM samples buffer
00420   * @param  Size: number of data to be written
00421   * @retval BSP AUDIO status
00422   */
00423 uint8_t BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size)
00424 {
00425   /* Initiate a DMA transfer of PCM samples towards the serial audio interface */
00426   if (HAL_SAI_Transmit_DMA(&BSP_AUDIO_hSai_Tx, (uint8_t *)pData, Size)!= HAL_OK)
00427   {
00428     return AUDIO_ERROR;
00429   }
00430 
00431   return AUDIO_OK;
00432 }
00433 
00434 /**
00435   * @brief  This function Pauses the audio file stream. In case
00436   *         of using DMA, the DMA Pause feature is used.
00437   * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only
00438   *       BSP_AUDIO_OUT_Resume() function should be called for resume
00439   *       (use of BSP_AUDIO_OUT_Play() function for resume could lead
00440   *       to unexpected behavior).
00441   * @retval BSP AUDIO status
00442   */
00443 uint8_t BSP_AUDIO_OUT_Pause(void)
00444 {
00445   /* Call the Audio Codec Pause function */
00446   if (hAudioOut.AudioDrv->Pause(AUDIO_I2C_ADDRESS) != 0)
00447   {
00448     return AUDIO_ERROR;
00449   }
00450 
00451   /* Pause DMA transfer of PCM samples towards the serial audio interface */
00452   if (HAL_SAI_DMAPause(&BSP_AUDIO_hSai_Tx)!= HAL_OK)
00453   {
00454     return AUDIO_ERROR;
00455   }
00456 
00457   return AUDIO_OK;
00458 }
00459 
00460 /**
00461   * @brief  This function  Resumes the audio file stream.
00462   * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only
00463   *       BSP_AUDIO_OUT_Resume() function should be called for resume
00464   *       (use of BSP_AUDIO_OUT_Play() function for resume could lead to
00465   *       unexpected behavior).
00466   * @retval BSP AUDIO status
00467   */
00468 uint8_t BSP_AUDIO_OUT_Resume(void)
00469 {
00470   /* Call the Audio Codec Resume function */
00471   if (hAudioOut.AudioDrv->Resume(AUDIO_I2C_ADDRESS) != 0)
00472   {
00473     return AUDIO_ERROR;
00474   }
00475 
00476   /* Resume DMA transfer of PCM samples towards the serial audio interface */
00477   if (HAL_SAI_DMAResume(&BSP_AUDIO_hSai_Tx)!= HAL_OK)
00478   {
00479     return AUDIO_ERROR;
00480   }
00481 
00482   return AUDIO_OK;
00483 }
00484 
00485 /**
00486   * @brief  Stops audio playing and Power down the Audio Codec.
00487   * @param  Option: could be one of the following parameters
00488   *           - CODEC_PDWN_SW: for software power off (by writing registers).
00489   *                            Then no need to reconfigure the Codec after power on.
00490   *           - CODEC_PDWN_HW: completely shut down the codec (physically).
00491   *                            Then need to reconfigure the Codec after power on.
00492   * @retval BSP AUDIO status
00493   */
00494 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
00495 {
00496   /* Prevent unused argument(s) compilation warning */
00497   UNUSED(Option);
00498 
00499   /* Call Audio Codec Stop function */
00500   if (hAudioOut.AudioDrv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
00501   {
00502     return AUDIO_ERROR;
00503   }
00504 
00505   /* Wait at least 100ms */
00506   HAL_Delay(100);
00507 
00508   /* Stop DMA transfer of PCM samples towards the serial audio interface */
00509   if (HAL_SAI_DMAStop(&BSP_AUDIO_hSai_Tx)!= HAL_OK)
00510   {
00511     return AUDIO_ERROR;
00512   }
00513 
00514   return AUDIO_OK;
00515 }
00516 
00517 /**
00518   * @brief  Controls the current audio volume level.
00519   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for
00520   *         Mute and 100 for Max volume level).
00521   * @retval BSP AUDIO status
00522   */
00523 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume)
00524 {
00525   /* Call the codec volume control function with converted volume value */
00526   if (hAudioOut.AudioDrv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
00527   {
00528     return AUDIO_ERROR;
00529   }
00530 
00531   hAudioOut.Volume = Volume;
00532 
00533   return AUDIO_OK;
00534 }
00535 
00536 /**
00537   * @brief  Enables or disables the MUTE mode by software
00538   * @param  Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to
00539   *         unmute the codec and restore previous volume level.
00540   * @retval BSP AUDIO status
00541   */
00542 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd)
00543 {
00544   /* Call the Codec Mute function */
00545   if (hAudioOut.AudioDrv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0)
00546   {
00547     return AUDIO_ERROR;
00548   }
00549 
00550   return AUDIO_OK;
00551 }
00552 
00553 /**
00554   * @brief  Switch dynamically (while audio file is being played) the output
00555   *          target (speaker or headphone).
00556   * @param  Output: The audio output target: OUTPUT_DEVICE_SPEAKER,
00557   *         OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH
00558   * @retval BSP AUDIO status
00559   */
00560 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)
00561 {
00562   /* Call the Codec output device function */
00563   if (hAudioOut.AudioDrv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0)
00564   {
00565     return AUDIO_ERROR;
00566   }
00567 
00568   return AUDIO_OK;
00569 }
00570 
00571 /**
00572   * @brief  Updates the audio frequency.
00573   * @param  AudioFreq: Audio frequency used to play the audio stream.
00574   * @note   The SAI PLL input clock must be configure in the user application.
00575   *         The SAI PLL configuration done within this function assumes that
00576   *         the SAI PLL input clock runs at 8 MHz.
00577   * @retval BSP AUDIO status
00578   */
00579 uint8_t BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)
00580 {
00581   uint8_t TxData[2] = {0x00, 0x00};
00582 
00583   /* Configure the SAI PLL according to the requested audio frequency */
00584   if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK)
00585   {
00586     return AUDIO_ERROR;
00587   }
00588 
00589   /* Disable SAI peripheral to allow access to SAI internal registers */
00590   __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx);
00591   __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Rx);
00592 
00593   /* Update the SAI audio frequency configuration */
00594   BSP_AUDIO_hSai_Tx.Init.Mckdiv = SAIClockDivider(AudioFreq);
00595   HAL_SAI_Init(&BSP_AUDIO_hSai_Tx);
00596   BSP_AUDIO_hSai_Rx.Init.Mckdiv = SAIClockDivider(AudioFreq);
00597   HAL_SAI_Init(&BSP_AUDIO_hSai_Rx);
00598 
00599   /* Enable SAI peripheral to generate MCLK */
00600   __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx);
00601   /* Transmit one byte to start FS generation */
00602   if(HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000) != HAL_OK)
00603   {
00604     return AUDIO_ERROR;
00605   }
00606 
00607   hAudioOut.Frequency = AudioFreq;
00608 
00609   return AUDIO_OK;
00610 }
00611 
00612 /**
00613   * @brief  Changes the Audio Out Configuration.
00614   * @param  AudioOutOption: specifies the audio out new configuration
00615   *         This parameter can be any value of @ref BSP_Audio_Out_Option
00616   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00617   *         audio out configuration.
00618   * @retval None
00619   */
00620 void BSP_AUDIO_OUT_ChangeAudioConfig(uint32_t AudioOutOption)
00621 {
00622   uint8_t TxData[2] = {0x00, 0x00};
00623 
00624   /********** Playback Buffer circular/normal mode **********/
00625   if(AudioOutOption & BSP_AUDIO_OUT_CIRCULARMODE)
00626   {
00627     /* Deinitialize the Stream to update DMA mode */
00628     HAL_DMA_DeInit(BSP_AUDIO_hSai_Tx.hdmatx);
00629 
00630     /* Update the SAI audio Transfer DMA mode */
00631     BSP_AUDIO_hSai_Tx.hdmatx->Init.Mode = DMA_CIRCULAR;
00632 
00633     /* Configure the DMA Stream with new Transfer DMA mode */
00634     HAL_DMA_Init(BSP_AUDIO_hSai_Tx.hdmatx);
00635   }
00636   else /* BSP_AUDIO_OUT_NORMALMODE */
00637   {
00638     /* Deinitialize the Stream to update DMA mode */
00639     HAL_DMA_DeInit(BSP_AUDIO_hSai_Tx.hdmatx);
00640 
00641     /* Update the SAI audio Transfer DMA mode */
00642     BSP_AUDIO_hSai_Tx.hdmatx->Init.Mode = DMA_NORMAL;
00643 
00644     /* Configure the DMA Stream with new Transfer DMA mode */
00645     HAL_DMA_Init(BSP_AUDIO_hSai_Tx.hdmatx);
00646   }
00647 
00648   /********** Playback Buffer stereo/mono mode **********/
00649   if(AudioOutOption & BSP_AUDIO_OUT_STEREOMODE)
00650   {
00651     /* Disable SAI peripheral to allow access to SAI internal registers */
00652     __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx);
00653 
00654     /* Update the SAI audio frame slot configuration */
00655     BSP_AUDIO_hSai_Tx.Init.MonoStereoMode = SAI_STEREOMODE;
00656     HAL_SAI_Init(&BSP_AUDIO_hSai_Tx);
00657 
00658     /* Enable SAI peripheral to generate MCLK */
00659     __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx);
00660     /* Transmit one byte to start FS generation */
00661     HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000);
00662   }
00663   else /* BSP_AUDIO_OUT_MONOMODE */
00664   {
00665     /* Disable SAI peripheral to allow access to SAI internal registers */
00666     __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx);
00667 
00668     /* Update the SAI audio frame slot configuration */
00669     BSP_AUDIO_hSai_Tx.Init.MonoStereoMode = SAI_MONOMODE;
00670     HAL_SAI_Init(&BSP_AUDIO_hSai_Tx);
00671 
00672     /* Enable SAI peripheral to generate MCLK */
00673     __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx);
00674     /* Transmit one byte to start FS generation */
00675     HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000);
00676   }
00677 }
00678 
00679 /**
00680   * @brief  register user callback functions
00681   * @param  ErrorCallback: pointer to the error callback function
00682   * @param  HalfTransferCallback: pointer to the half transfer callback function
00683   * @param  TransferCompleteCallback: pointer to the transfer complete callback function
00684   * @retval None
00685   */
00686 void BSP_AUDIO_OUT_RegisterCallbacks(Audio_CallbackTypeDef ErrorCallback,
00687                                      Audio_CallbackTypeDef HalfTransferCallback,
00688                                      Audio_CallbackTypeDef TransferCompleteCallback)
00689 {
00690   hAudioOut.CbError            = ErrorCallback;
00691   hAudioOut.CbHalfTransfer     = HalfTransferCallback;
00692   hAudioOut.CbTransferComplete = TransferCompleteCallback;
00693 }
00694 
00695 /**
00696   * @brief  Tx Transfer completed callbacks.
00697   * @param  hsai: SAI handle
00698   * @retval None
00699   */
00700 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
00701 {
00702   /* Invoke the registered 'TransferComplete' function (if any) */
00703   if (hAudioOut.CbTransferComplete != (Audio_CallbackTypeDef)NULL)
00704   {
00705     hAudioOut.CbTransferComplete();
00706   }
00707 }
00708 
00709 /**
00710   * @brief  Tx Half Transfer completed callbacks.
00711   * @param  hsai: SAI handle
00712   * @retval None
00713   */
00714 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
00715 {
00716   /* Invoke the registered 'HalfTransfer' callback function (if any) */
00717   if (hAudioOut.CbHalfTransfer != (Audio_CallbackTypeDef)NULL)
00718   {
00719     hAudioOut.CbHalfTransfer();
00720   }
00721 }
00722 
00723 /**
00724   * @brief  SAI error callbacks.
00725   * @param  hsai: SAI handle
00726   * @retval None
00727   */
00728 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
00729 {
00730   /* Invoke the registered 'ErrorCallback' callback function (if any) */
00731   if (hAudioOut.CbError != (Audio_CallbackTypeDef)NULL)
00732   {
00733     hAudioOut.CbError();
00734   }
00735   /* Invoke the registered 'ErrorCallback' callback function (if any) */
00736   if (hAudioIn.CbError != (Audio_CallbackTypeDef)NULL)
00737   {
00738     hAudioIn.CbError();
00739   }
00740 }
00741 
00742 /**
00743   * @}
00744   */
00745 
00746 /** @addtogroup STM32L4R9I_DISCOVERY_AUDIO_Exported_Functions
00747   * @{
00748   */
00749 
00750 /**
00751   * @brief  Initializes micropone related peripherals.
00752   * @note   This function assumes that the SAI input clock (through PLL_M)
00753   *         is already configured and ready to be used.
00754   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00755   * @param  BitRes: Audio frequency to be configured for the SAI peripheral.
00756   * @param  ChnlNbr: Audio frequency to be configured for the SAI peripheral.
00757   * @retval BSP AUDIO status
00758   */
00759 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00760 {
00761   return BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC, AudioFreq, BitRes, ChnlNbr);
00762 }
00763 
00764 /**
00765   * @brief  Initialize wave recording.
00766   * @param  InputDevice: INPUT_DEVICE_DIGITAL_MIC, INPUT_DEVICE_DIGITAL_MIC1,
00767   *                      INPUT_DEVICE_DIGITAL_MIC2 or INPUT_DEVICE_ANALOG_MIC.
00768   * @param  AudioFreq: Audio frequency to be configured.
00769   * @param  BitRes: Audio bit resolution to be configured..
00770   * @param  ChnlNbr: Number of channel to be configured.
00771   * @retval AUDIO_OK if correct communication, else wrong communication
00772   */
00773 uint8_t BSP_AUDIO_IN_InitEx(uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00774 {
00775   /* Update the audio input context */
00776   hAudioIn.AudioDrv           = &cs42l51_drv;
00777   hAudioIn.InputDevice        = InputDevice;
00778   hAudioIn.Frequency          = AudioFreq;
00779   hAudioIn.BitResolution      = BitRes;
00780   hAudioIn.ChannelNbr         = ChnlNbr;
00781   hAudioIn.CbError            = (Audio_CallbackTypeDef)NULL;
00782   hAudioIn.CbHalfTransfer     = (Audio_CallbackTypeDef)NULL;
00783   hAudioIn.CbTransferComplete = (Audio_CallbackTypeDef)NULL;
00784 
00785   /* Check channel number according device : only record mono with analog mic and stereo with digital mic are allowed */
00786   if(((InputDevice == INPUT_DEVICE_DIGITAL_MIC) && (ChnlNbr == 1)) ||
00787      ((InputDevice == INPUT_DEVICE_DIGITAL_MIC1) && (ChnlNbr == 2)) ||
00788      ((InputDevice == INPUT_DEVICE_DIGITAL_MIC2) && (ChnlNbr == 2)) ||
00789      ((InputDevice == INPUT_DEVICE_ANALOG_MIC) && (ChnlNbr == 2)))
00790   {
00791     return AUDIO_ERROR;
00792   }
00793 
00794   /* Check if output device is currently used */
00795   if(hAudioOut.OutputDevice != 0)
00796   {
00797     /* If output device is currently used, SAI PLL is already initialized */
00798     /* Check that AudioFreq for record and playback is the same */
00799     if(hAudioIn.Frequency != hAudioOut.Frequency)
00800     {
00801       return AUDIO_ERROR;
00802     }
00803   }
00804   else
00805   {
00806     /* Configure the SAI PLL according to the requested audio frequency */
00807     if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK)
00808     {
00809       return AUDIO_ERROR;
00810     }
00811   }
00812 
00813   if(InputDevice != INPUT_DEVICE_ANALOG_MIC)
00814   {
00815     /* Initializes the Digital Filter for Sigma-Delta Modulators interface */
00816     if(AUDIO_DFSDMx_Init(AudioFreq) != AUDIO_OK)
00817     {
00818       return AUDIO_ERROR;
00819     }
00820   }
00821   else
00822   { /* INPUT_DEVICE_ANALOG_MIC */
00823     /* If output device is currently used, SAI is already initialized */
00824     if(hAudioOut.OutputDevice == 0)
00825     {
00826       /* SAI data transfer preparation: prepare the Media to be used for the audio
00827       transfer from SAI peripheral to memory. */
00828       if(AUDIO_SAIx_Init(AudioFreq) != AUDIO_OK)
00829       {
00830         return AUDIO_ERROR;
00831       }
00832     }
00833 
00834     /* Initialize the audio codec internal registers */
00835     if(hAudioIn.AudioDrv->Init(AUDIO_I2C_ADDRESS,
00836                                (hAudioOut.OutputDevice | hAudioIn.InputDevice),
00837                                hAudioOut.Volume,
00838                                AudioFreq) != 0)
00839     {
00840       return AUDIO_ERROR;
00841     }
00842   }
00843 
00844   /* Initialise transfer control flag */
00845   DmaLeftRecHalfBuffCplt  = 0;
00846   DmaLeftRecBuffCplt      = 0;
00847   DmaRightRecHalfBuffCplt = 0;
00848   DmaRightRecBuffCplt     = 0;
00849 
00850   return AUDIO_OK;
00851 }
00852 
00853 /**
00854   * @brief  De-Initializes microphone related peripherals.
00855   * @retval BSP AUDIO status
00856 
00857   */
00858 uint8_t BSP_AUDIO_IN_DeInit(void)
00859 {
00860   if(hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
00861   {
00862     /* De-initializes the Digital Filter for Sigma-Delta Modulators interface */
00863     if (AUDIO_DFSDMx_DeInit() != AUDIO_OK)
00864     {
00865       return AUDIO_ERROR;
00866     }
00867   }
00868   else
00869   { /* INPUT_DEVICE_ANALOG_MIC */
00870     /* Check if output device is currently used */
00871     if(hAudioOut.OutputDevice != 0)
00872     {
00873       /* Reset record path on audio codec */
00874       if(hAudioOut.AudioDrv->Init(AUDIO_I2C_ADDRESS,
00875                                  hAudioOut.OutputDevice,
00876                                  (uint8_t) hAudioOut.Volume,
00877                                  hAudioOut.Frequency) != 0)
00878       {
00879         return AUDIO_ERROR;
00880       }
00881     }
00882     else
00883     {
00884       /* De-initializes SAI interface */
00885       if(AUDIO_SAIx_DeInit() != AUDIO_OK)
00886       {
00887         return AUDIO_ERROR;
00888       }
00889 
00890       /* DeInit audio codec */
00891       hAudioIn.AudioDrv->DeInit();
00892     }
00893   }
00894 
00895   /* Disable SAI PLL if no more device is used */
00896   if(hAudioOut.OutputDevice == 0)
00897   {
00898     if (AUDIO_SAIx_PLL_DISABLE() != AUDIO_OK)
00899     {
00900       return AUDIO_ERROR;
00901     }
00902   }
00903 
00904   /* Reset the audio input context */
00905   memset(&hAudioIn, 0, sizeof(hAudioIn));
00906 
00907   return AUDIO_OK;
00908 }
00909 
00910 /**
00911   * @brief  Starts audio recording.
00912   * @param  pbuf: Main buffer pointer for the recorded data storing
00913   * @param  size: Current size of the recorded buffer
00914   * @note   The Right channel is start at first with synchro on start of Left channel
00915   * @retval BSP AUDIO status
00916   */
00917 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size)
00918 {
00919   hAudioIn.pRecBuf = pbuf;
00920   hAudioIn.RecSize = size;
00921 
00922 
00923   if(hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
00924   {
00925     if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
00926     {
00927       /* Allocate hAudioIn.LeftRecBuff buffer */
00928 #if defined(BSP_AUDIO_USE_RTOS)
00929       hAudioIn.LeftRecBuff  = (int32_t *)k_malloc((size / hAudioIn.ChannelNbr) * sizeof(int32_t));
00930 #else
00931       hAudioIn.LeftRecBuff  = (int32_t *)malloc((size / hAudioIn.ChannelNbr) * sizeof(int32_t));
00932 #endif
00933       if(hAudioIn.LeftRecBuff == NULL)
00934       {
00935         return AUDIO_ERROR;
00936       }
00937     }
00938 
00939     if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
00940     {
00941       /* Allocate hAudioIn.RightRecBuff buffer */
00942 #if defined(BSP_AUDIO_USE_RTOS)
00943       hAudioIn.RightRecBuff  = (int32_t *)k_malloc((size / hAudioIn.ChannelNbr) * sizeof(int32_t));
00944 #else
00945       hAudioIn.RightRecBuff  = (int32_t *)malloc((size / hAudioIn.ChannelNbr) * sizeof(int32_t));
00946 #endif
00947       if(hAudioIn.RightRecBuff == NULL)
00948       {
00949         return AUDIO_ERROR;
00950       }
00951     }
00952 
00953     if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
00954     {
00955       /* Call the Media layer start function for right channel */
00956       if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmRightFilter,
00957                                           (int32_t*)hAudioIn.RightRecBuff,
00958                                           (hAudioIn.RecSize/hAudioIn.ChannelNbr)) != HAL_OK)
00959       {
00960         return AUDIO_ERROR;
00961       }
00962     }
00963 
00964     if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
00965     {
00966       /* Call the Media layer start function for left channel */
00967       if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmLeftFilter,
00968                                           (int32_t*)hAudioIn.LeftRecBuff,
00969                                           (hAudioIn.RecSize/hAudioIn.ChannelNbr)) != HAL_OK)
00970       {
00971         return AUDIO_ERROR;
00972       }
00973     }
00974   }
00975   else
00976   { /* INPUT_DEVICE_ANALOG_MIC */
00977     /* Call the audio Codec Play function */
00978     if (hAudioIn.AudioDrv->Play(AUDIO_I2C_ADDRESS, pbuf, size) != 0)
00979     {
00980       return AUDIO_ERROR;
00981     }
00982 
00983     /* Start the process receive DMA */
00984     if(HAL_OK != HAL_SAI_Receive_DMA(&BSP_AUDIO_hSai_Rx, (uint8_t*)pbuf, size))
00985     {
00986       return AUDIO_ERROR;
00987     }
00988   }
00989 
00990   return AUDIO_OK;
00991 }
00992 
00993 /**
00994   * @brief  Updates the audio frequency.
00995   * @param  AudioFreq: Audio frequency used to record the audio stream.
00996   * @note   This API should be called after the BSP_AUDIO_IN_Init() to adjust the
00997   *         audio frequency.
00998   * @retval BSP AUDIO status
00999   */
01000 uint8_t BSP_AUDIO_IN_SetFrequency(uint32_t AudioFreq)
01001 {
01002   uint8_t TxData[2] = {0x00, 0x00};
01003 
01004   /* Configure the SAI PLL according to the requested audio frequency */
01005   if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK)
01006   {
01007     return AUDIO_ERROR;
01008   }
01009 
01010   if (hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
01011   {
01012     /* De-initializes the Digital Filter for Sigma-Delta Modulators interface */
01013     if(AUDIO_DFSDMx_DeInit() != AUDIO_OK)
01014     {
01015       return AUDIO_ERROR;
01016     }
01017 
01018     /* Initializes the Digital Filter for Sigma-Delta Modulators interface */
01019     if(AUDIO_DFSDMx_Init(AudioFreq) != AUDIO_OK)
01020     {
01021       return AUDIO_ERROR;
01022     }
01023   }
01024   else
01025   { /* INPUT_DEVICE_ANALOG_MIC */
01026     /* Disable SAI peripheral to allow access to SAI internal registers */
01027     __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx);
01028     __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Rx);
01029 
01030     /* Update the SAI audio frequency configuration */
01031     BSP_AUDIO_hSai_Tx.Init.Mckdiv = SAIClockDivider(AudioFreq);
01032     HAL_SAI_Init(&BSP_AUDIO_hSai_Tx);
01033     BSP_AUDIO_hSai_Rx.Init.Mckdiv = SAIClockDivider(AudioFreq);
01034     HAL_SAI_Init(&BSP_AUDIO_hSai_Rx);
01035 
01036     /* Enable SAI peripheral to generate MCLK */
01037     __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx);
01038     /* Transmit one byte to start FS generation */
01039     if(HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000) != HAL_OK)
01040     {
01041       return AUDIO_ERROR;
01042     }
01043   }
01044 
01045   hAudioIn.Frequency = AudioFreq;
01046 
01047   return AUDIO_OK;
01048 }
01049 
01050 /**
01051   * @brief  Regular conversion complete callback.
01052   * @note   In interrupt mode, user has to read conversion value in this function
01053             using HAL_DFSDM_FilterGetRegularValue.
01054   * @param  hdfsdm_filter : DFSDM filter handle.
01055   * @retval None
01056   */
01057 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01058 {
01059   uint32_t index;
01060   uint32_t recbufsize = (hAudioIn.RecSize/hAudioIn.ChannelNbr);
01061 
01062   if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC)
01063   {
01064     for (index = (recbufsize / 2); index < recbufsize; index++)
01065     {
01066       hAudioIn.pRecBuf[2 * index]       = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32768, 32767));
01067       hAudioIn.pRecBuf[(2 * index) + 1] = (uint16_t)(SaturaLH((hAudioIn.RightRecBuff[index] >> 8), -32768, 32767));
01068     }
01069   }
01070   else if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC1)
01071   {
01072     for (index = (recbufsize / 2); index < recbufsize; index++)
01073     {
01074       hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32768, 32767));
01075     }
01076   }
01077   else if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)
01078   {
01079     for (index = (recbufsize / 2); index < recbufsize; index++)
01080     {
01081       hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.RightRecBuff[index] >> 8), -32768, 32767));
01082     }
01083   }
01084 
01085   /* Invoke the registered 'TransferCompete' callback function (if any) */
01086   if (hAudioIn.CbTransferComplete != (Audio_CallbackTypeDef)NULL)
01087   {
01088     if(hdfsdm_filter == &BSP_AUDIO_hDfsdmLeftFilter)
01089     {
01090       if (DmaLeftRecBuffCplt) BSP_ErrorHandler();
01091 
01092       DmaLeftRecBuffCplt = 1;
01093     }
01094     else
01095     {
01096       if (DmaRightRecBuffCplt) BSP_ErrorHandler();
01097 
01098       DmaRightRecBuffCplt = 1;
01099     }
01100 
01101     if (((DmaLeftRecBuffCplt != 0) && (DmaRightRecBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC)) ||
01102         ((DmaLeftRecBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC1)) ||
01103         ((DmaRightRecBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)))
01104     {
01105       hAudioIn.CbTransferComplete();
01106       DmaLeftRecBuffCplt = 0;
01107       DmaRightRecBuffCplt = 0;
01108     }
01109   }
01110 }
01111 
01112 /**
01113   * @brief  Half regular conversion complete callback.
01114   * @param  hdfsdm_filter : DFSDM filter handle.
01115   * @retval None
01116   */
01117 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01118 {
01119   uint32_t index;
01120   uint32_t recbufsize = (hAudioIn.RecSize/hAudioIn.ChannelNbr);
01121 
01122   if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC)
01123   {
01124     for (index = 0; index < (recbufsize / 2); index++)
01125     {
01126       hAudioIn.pRecBuf[2 * index]       = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32768, 32767));
01127       hAudioIn.pRecBuf[(2 * index) + 1] = (uint16_t)(SaturaLH((hAudioIn.RightRecBuff[index] >> 8), -32768, 32767));
01128     }
01129   }
01130   else if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC1)
01131   {
01132     for (index = 0; index < (recbufsize / 2); index++)
01133     {
01134       hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32768, 32767));
01135     }
01136   }
01137   else if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)
01138   {
01139     for (index = 0; index < (recbufsize / 2); index++)
01140     {
01141       hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.RightRecBuff[index] >> 8), -32768, 32767));
01142     }
01143   }
01144 
01145   /* Invoke the registered 'HalfTransfer' callback function (if any) */
01146   if (hAudioIn.CbHalfTransfer != (Audio_CallbackTypeDef)NULL)
01147   {
01148     if(hdfsdm_filter == &BSP_AUDIO_hDfsdmLeftFilter)
01149     {
01150       if (DmaLeftRecHalfBuffCplt) BSP_ErrorHandler();
01151 
01152       DmaLeftRecHalfBuffCplt = 1;
01153     }
01154     else
01155     {
01156       if (DmaRightRecHalfBuffCplt) BSP_ErrorHandler();
01157 
01158       DmaRightRecHalfBuffCplt = 1;
01159     }
01160 
01161 
01162     if (((DmaLeftRecHalfBuffCplt != 0) && (DmaRightRecHalfBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC)) ||
01163         ((DmaLeftRecHalfBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC1)) ||
01164         ((DmaRightRecHalfBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)))
01165     {
01166       hAudioIn.CbHalfTransfer();
01167       DmaLeftRecHalfBuffCplt = 0;
01168       DmaRightRecHalfBuffCplt = 0;
01169     }
01170   }
01171 }
01172 
01173 /**
01174   * @brief  Error callback.
01175   * @param  hdfsdm_filter : DFSDM filter handle.
01176   * @retval None
01177   */
01178 void HAL_DFSDM_FilterErrorCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01179 {
01180   /* Invoke the registered 'ErrorCallback' callback function (if any) */
01181   if (hAudioIn.CbError != (Audio_CallbackTypeDef)NULL)
01182   {
01183     hAudioIn.CbError();
01184   }
01185 }
01186 
01187 /**
01188   * @brief  SAI Rx Transfer completed callbacks.
01189   * @param  hsai: SAI handle
01190   * @retval None
01191   */
01192 void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
01193 {
01194   /* Invoke the registered 'TransferComplete' function (if any) */
01195   if (hAudioIn.CbTransferComplete != (Audio_CallbackTypeDef)NULL)
01196   {
01197     hAudioIn.CbTransferComplete();
01198   }
01199 }
01200 
01201 /**
01202   * @brief  SAI Rx Half Transfer completed callbacks.
01203   * @param  hsai: SAI handle
01204   * @retval None
01205   */
01206 void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
01207 {
01208   /* Invoke the registered 'HalfTransfer' callback function (if any) */
01209   if (hAudioIn.CbHalfTransfer != (Audio_CallbackTypeDef)NULL)
01210   {
01211     hAudioIn.CbHalfTransfer();
01212   }
01213 }
01214 
01215 /**
01216   * @brief  Stops audio recording.
01217   * @retval BSP AUDIO status
01218   */
01219 uint8_t BSP_AUDIO_IN_Stop(void)
01220 {
01221   if (hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
01222   {
01223     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01224     {
01225       /* Call the Media layer stop function for right channel */
01226       if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmRightFilter) != HAL_OK )
01227       {
01228         return AUDIO_ERROR;
01229       }
01230     }
01231     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01232     {
01233       /* Call the Media layer stop function for left channel */
01234       if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK )
01235       {
01236         return AUDIO_ERROR;
01237       }
01238     }
01239 
01240     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01241     {
01242       /* Free hAudioIn.LeftRecBuff buffer */
01243 #if defined(BSP_AUDIO_USE_RTOS)
01244       k_free((void *)hAudioIn.LeftRecBuff);
01245 #else
01246       free((void *)hAudioIn.LeftRecBuff);
01247 #endif
01248     }
01249     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01250     {
01251       /* Free hAudioIn.RightRecBuff buffer */
01252 #if defined(BSP_AUDIO_USE_RTOS)
01253       k_free((void *)hAudioIn.RightRecBuff);
01254 #else
01255       free((void *)hAudioIn.RightRecBuff);
01256 #endif
01257     }
01258   }
01259   else
01260   { /* INPUT_DEVICE_ANALOG_MIC */
01261     /* Call Audio Codec Stop function */
01262     if (hAudioIn.AudioDrv->Stop(AUDIO_I2C_ADDRESS, CODEC_PDWN_HW) != 0)
01263     {
01264       return AUDIO_ERROR;
01265     }
01266 
01267     /* Wait at least 100ms */
01268     HAL_Delay(100);
01269 
01270     /* Stop DMA transfer of PCM samples towards the serial audio interface */
01271     if (HAL_SAI_DMAStop(&BSP_AUDIO_hSai_Rx)!= HAL_OK)
01272     {
01273       return AUDIO_ERROR;
01274     }
01275   }
01276 
01277   return AUDIO_OK;
01278 }
01279 
01280 /**
01281   * @brief  Pauses the audio file stream.
01282   * @retval BSP AUDIO status
01283   */
01284 uint8_t BSP_AUDIO_IN_Pause(void)
01285 {
01286   if (hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
01287   {
01288     /* Call the Media layer stop function */
01289     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01290     {
01291       if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmRightFilter) != HAL_OK)
01292       {
01293         return AUDIO_ERROR;
01294       }
01295     }
01296 
01297     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01298     {
01299       if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK)
01300       {
01301         return AUDIO_ERROR;
01302       }
01303     }
01304   }
01305   else
01306   { /* INPUT_DEVICE_ANALOG_MIC */
01307     /* Pause DMA transfer of PCM samples towards the serial audio interface */
01308     if (HAL_SAI_DMAPause(&BSP_AUDIO_hSai_Rx)!= HAL_OK)
01309     {
01310       return AUDIO_ERROR;
01311     }
01312   }
01313 
01314   return AUDIO_OK;
01315 }
01316 
01317 /**
01318   * @brief  Resumes the audio file stream.
01319   * @retval BSP AUDIO status
01320   */
01321 uint8_t BSP_AUDIO_IN_Resume(void)
01322 {
01323   if (hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
01324   {
01325     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01326     {
01327       /* Call the Media layer start function for right channel */
01328       if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmRightFilter,
01329                                           (int32_t*)hAudioIn.RightRecBuff,
01330                                           (hAudioIn.RecSize/hAudioIn.ChannelNbr)) != HAL_OK)
01331       {
01332         return AUDIO_ERROR;
01333       }
01334     }
01335 
01336     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01337     {
01338       /* Call the Media layer start function for left channel */
01339       if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmLeftFilter,
01340                                           (int32_t*)hAudioIn.LeftRecBuff,
01341                                           (hAudioIn.RecSize/hAudioIn.ChannelNbr)) != HAL_OK)
01342       {
01343         return AUDIO_ERROR;
01344       }
01345     }
01346   }
01347   else
01348   { /* INPUT_DEVICE_ANALOG_MIC */
01349     /* Resume DMA transfer of PCM samples towards the serial audio interface */
01350     if (HAL_SAI_DMAResume(&BSP_AUDIO_hSai_Rx) != HAL_OK)
01351     {
01352       return AUDIO_ERROR;
01353     }
01354   }
01355 
01356   return AUDIO_OK;
01357 }
01358 
01359 /**
01360   * @brief  register user callback functions
01361   * @param  ErrorCallback: pointer to the error callback function
01362   * @param  HalfTransferCallback: pointer to the half transfer callback function
01363   * @param  TransferCompleteCallback: pointer to the transfer complete callback function
01364   * @retval None
01365   */
01366 void BSP_AUDIO_IN_RegisterCallbacks(Audio_CallbackTypeDef ErrorCallback,
01367                                     Audio_CallbackTypeDef HalfTransferCallback,
01368                                     Audio_CallbackTypeDef TransferCompleteCallback)
01369 {
01370   hAudioIn.CbError            = ErrorCallback;
01371   hAudioIn.CbHalfTransfer     = HalfTransferCallback;
01372   hAudioIn.CbTransferComplete = TransferCompleteCallback;
01373 }
01374 
01375 /**
01376   * @}
01377   */
01378 
01379 /* Private functions --------------------------------------------------------*/
01380 /** @addtogroup STM32L4R9I_DISCOVERY_AUDIO_Private_Functions
01381   * @{
01382   */
01383 /**
01384   * @brief  Initializes the Audio Codec audio interface (SAI).
01385   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
01386   * @retval BSP AUDIO status
01387   */
01388 static uint8_t AUDIO_SAIx_Init(uint32_t AudioFreq)
01389 {
01390   uint8_t TxData[2] = {0x00, 0x00};
01391 
01392   /* Initialize the BSP_AUDIO_hSai_Xx instances parameter */
01393   BSP_AUDIO_hSai_Tx.Instance = SAI1_Block_A;
01394   BSP_AUDIO_hSai_Rx.Instance = SAI1_Block_B;
01395 
01396   /* Disable SAI peripheral to allow access to SAI internal registers */
01397   __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx);
01398   __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Rx);
01399 
01400   /*******************************/
01401   /* SAI block used for playback */
01402   /*******************************/
01403   /* Configure SAI_Block_x used for transmit
01404   LSBFirst: Disabled
01405   DataSize: 16 */
01406   BSP_AUDIO_hSai_Tx.Init.AudioMode      = SAI_MODEMASTER_TX;
01407   BSP_AUDIO_hSai_Tx.Init.Synchro        = SAI_ASYNCHRONOUS;
01408   BSP_AUDIO_hSai_Tx.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
01409   BSP_AUDIO_hSai_Tx.Init.OutputDrive    = SAI_OUTPUTDRIVE_ENABLE;
01410   BSP_AUDIO_hSai_Tx.Init.NoDivider      = SAI_MASTERDIVIDER_ENABLE;
01411   BSP_AUDIO_hSai_Tx.Init.FIFOThreshold  = SAI_FIFOTHRESHOLD_1QF;
01412   BSP_AUDIO_hSai_Tx.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV;
01413   BSP_AUDIO_hSai_Tx.Init.Mckdiv         = SAIClockDivider(AudioFreq);
01414   BSP_AUDIO_hSai_Tx.Init.MonoStereoMode = SAI_STEREOMODE;
01415   BSP_AUDIO_hSai_Tx.Init.CompandingMode = SAI_NOCOMPANDING;
01416   BSP_AUDIO_hSai_Tx.Init.TriState       = SAI_OUTPUT_NOTRELEASED;
01417   BSP_AUDIO_hSai_Tx.Init.Protocol       = SAI_FREE_PROTOCOL;
01418   BSP_AUDIO_hSai_Tx.Init.DataSize       = SAI_DATASIZE_16;
01419   BSP_AUDIO_hSai_Tx.Init.FirstBit       = SAI_FIRSTBIT_MSB;
01420   BSP_AUDIO_hSai_Tx.Init.ClockStrobing  = SAI_CLOCKSTROBING_FALLINGEDGE;
01421 
01422   /* Configure SAI_Block_x Frame
01423   Frame Length: 32
01424   Frame active Length: 16
01425   FS Definition: Start frame + Channel Side identification
01426   FS Polarity: FS active Low
01427   FS Offset: FS asserted one bit before the first bit of slot 0 */
01428   BSP_AUDIO_hSai_Tx.FrameInit.FrameLength = 32;
01429   BSP_AUDIO_hSai_Tx.FrameInit.ActiveFrameLength = 16;
01430   BSP_AUDIO_hSai_Tx.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
01431   BSP_AUDIO_hSai_Tx.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
01432   BSP_AUDIO_hSai_Tx.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
01433 
01434   /* Configure SAI Block_x Slot
01435   Slot First Bit Offset: 0
01436   Slot Size  : 16
01437   Slot Number: 2
01438   Slot Active: Slots 0 and 1 actives */
01439   BSP_AUDIO_hSai_Tx.SlotInit.FirstBitOffset = 0;
01440   BSP_AUDIO_hSai_Tx.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
01441   BSP_AUDIO_hSai_Tx.SlotInit.SlotNumber = 2;
01442   BSP_AUDIO_hSai_Tx.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1;
01443 
01444   /*****************************/
01445   /* SAI block used for record */
01446   /*****************************/
01447   /* Configure SAI_Block_x used for receive
01448   LSBFirst: Disabled
01449   DataSize: 16 */
01450   BSP_AUDIO_hSai_Rx.Init.AudioMode      = SAI_MODESLAVE_RX;
01451   BSP_AUDIO_hSai_Rx.Init.Synchro        = SAI_SYNCHRONOUS;
01452   BSP_AUDIO_hSai_Rx.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
01453   BSP_AUDIO_hSai_Rx.Init.OutputDrive    = SAI_OUTPUTDRIVE_ENABLE;
01454   BSP_AUDIO_hSai_Rx.Init.NoDivider      = SAI_MASTERDIVIDER_ENABLE;
01455   BSP_AUDIO_hSai_Rx.Init.FIFOThreshold  = SAI_FIFOTHRESHOLD_1QF;
01456   BSP_AUDIO_hSai_Rx.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV;
01457   BSP_AUDIO_hSai_Rx.Init.Mckdiv         = SAIClockDivider(AudioFreq);
01458   BSP_AUDIO_hSai_Rx.Init.MonoStereoMode = SAI_MONOMODE;
01459   BSP_AUDIO_hSai_Rx.Init.CompandingMode = SAI_NOCOMPANDING;
01460   BSP_AUDIO_hSai_Rx.Init.TriState       = SAI_OUTPUT_NOTRELEASED;
01461   BSP_AUDIO_hSai_Rx.Init.Protocol       = SAI_FREE_PROTOCOL;
01462   BSP_AUDIO_hSai_Rx.Init.DataSize       = SAI_DATASIZE_16;
01463   BSP_AUDIO_hSai_Rx.Init.FirstBit       = SAI_FIRSTBIT_MSB;
01464   BSP_AUDIO_hSai_Rx.Init.ClockStrobing  = SAI_CLOCKSTROBING_FALLINGEDGE;
01465 
01466   /* Configure SAI_Block_x Frame
01467   Frame Length: 32
01468   Frame active Length: 16
01469   FS Definition: Start frame + Channel Side identification
01470   FS Polarity: FS active Low
01471   FS Offset: FS asserted one bit before the first bit of slot 0 */
01472   BSP_AUDIO_hSai_Rx.FrameInit.FrameLength = 32;
01473   BSP_AUDIO_hSai_Rx.FrameInit.ActiveFrameLength = 16;
01474   BSP_AUDIO_hSai_Rx.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
01475   BSP_AUDIO_hSai_Rx.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
01476   BSP_AUDIO_hSai_Rx.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
01477 
01478   /* Configure SAI Block_x Slot
01479   Slot First Bit Offset: 0
01480   Slot Size  : 16
01481   Slot Number: 2
01482   Slot Active: Slots 0 and 1 actives */
01483   BSP_AUDIO_hSai_Rx.SlotInit.FirstBitOffset = 0;
01484   BSP_AUDIO_hSai_Rx.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
01485   BSP_AUDIO_hSai_Rx.SlotInit.SlotNumber = 2;
01486   BSP_AUDIO_hSai_Rx.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1;
01487 
01488   /*********************************/
01489   /* Initializes the SAI peripheral*/
01490   /*********************************/
01491   if (HAL_SAI_Init(&BSP_AUDIO_hSai_Tx) != HAL_OK)
01492   {
01493     return AUDIO_ERROR;
01494   }
01495   if (HAL_SAI_Init(&BSP_AUDIO_hSai_Rx) != HAL_OK)
01496   {
01497     return AUDIO_ERROR;
01498   }
01499 
01500   /******************************************/
01501   /* Enable SAI peripheral to generate MCLK */
01502   /******************************************/
01503   __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx);
01504   /* Transmit one byte to start FS generation */
01505   if(HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000) != HAL_OK)
01506   {
01507     return AUDIO_ERROR;
01508   }
01509 
01510   return AUDIO_OK;
01511 }
01512 
01513 /**
01514   * @brief  De-initializes the Audio Codec audio interface (SAI).
01515   * @retval BSP AUDIO status
01516   */
01517 static uint8_t AUDIO_SAIx_DeInit(void)
01518 {
01519   /* Disable the SAI audio block */
01520   __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx);
01521   __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Rx);
01522 
01523   /* De-initializes the SAI peripheral */
01524   if (HAL_SAI_DeInit(&BSP_AUDIO_hSai_Tx) != HAL_OK)
01525   {
01526     return AUDIO_ERROR;
01527   }
01528   if (HAL_SAI_DeInit(&BSP_AUDIO_hSai_Rx) != HAL_OK)
01529   {
01530     return AUDIO_ERROR;
01531   }
01532 
01533   return AUDIO_OK;
01534 }
01535 
01536 /**
01537   * @brief  SAI MSP Init
01538   * @param  hsai : pointer to a SAI_HandleTypeDef structure
01539   * @retval None
01540   */
01541 void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
01542 {
01543   GPIO_InitTypeDef  GPIO_InitStruct;
01544 
01545   /* Enable SAI clock */
01546   __HAL_RCC_SAI1_CLK_ENABLE();
01547 
01548   if(hsai->Instance == SAI1_Block_A)
01549   {
01550     /* SAI pins configuration: FS, SCK, MCLK and SD pins */
01551     __HAL_RCC_GPIOB_CLK_ENABLE();
01552     __HAL_RCC_GPIOE_CLK_ENABLE();
01553     GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
01554     GPIO_InitStruct.Pull      = GPIO_NOPULL;
01555     GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
01556     GPIO_InitStruct.Alternate = GPIO_AF13_SAI1;
01557     GPIO_InitStruct.Pin       = GPIO_PIN_2;
01558     HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); /* SAI1_MCLK_A */
01559     GPIO_InitStruct.Pin       = GPIO_PIN_9;
01560     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* SAI1_FS_A */
01561     GPIO_InitStruct.Pin       = GPIO_PIN_5;
01562     HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); /* SAI1_SCK_A */
01563     GPIO_InitStruct.Pin       = GPIO_PIN_6;
01564     HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); /* SAI1_SD_A */
01565 
01566     /* Configure the hDmaSaiTx handle parameters */
01567     __HAL_RCC_DMA2_CLK_ENABLE();
01568     __HAL_RCC_DMAMUX1_CLK_ENABLE();
01569     hDmaSaiTx.Init.Request             = DMA_REQUEST_SAI1_A;
01570     hDmaSaiTx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
01571     hDmaSaiTx.Init.PeriphInc           = DMA_PINC_DISABLE;
01572     hDmaSaiTx.Init.MemInc              = DMA_MINC_ENABLE;
01573     hDmaSaiTx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
01574     hDmaSaiTx.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;
01575     hDmaSaiTx.Init.Mode                = DMA_CIRCULAR;
01576     hDmaSaiTx.Init.Priority            = DMA_PRIORITY_HIGH;
01577     hDmaSaiTx.Instance                 = DMA2_Channel1;
01578     /* Associate the DMA handle */
01579     __HAL_LINKDMA(hsai, hdmatx, hDmaSaiTx);
01580     /* Deinitialize the Stream for new transfer */
01581     HAL_DMA_DeInit(&hDmaSaiTx);
01582     /* Configure the DMA Stream */
01583     HAL_DMA_Init(&hDmaSaiTx);
01584     /* SAI DMA IRQ Channel configuration */
01585     HAL_NVIC_SetPriority(DMA2_Channel1_IRQn, 5, 0);
01586     HAL_NVIC_EnableIRQ(DMA2_Channel1_IRQn);
01587   }
01588   else /* SAI1_BlockB */
01589   {
01590     /* SAI pins configuration: SD pin */
01591     __HAL_RCC_GPIOB_CLK_ENABLE();
01592     GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
01593     GPIO_InitStruct.Pull      = GPIO_NOPULL;
01594     GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
01595     GPIO_InitStruct.Alternate = GPIO_AF13_SAI1;
01596     GPIO_InitStruct.Pin       = GPIO_PIN_5;
01597     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* SAI1_SD_B */
01598 
01599     /* Configure the hDmaSaiRx handle parameters */
01600     __HAL_RCC_DMA2_CLK_ENABLE();
01601     __HAL_RCC_DMAMUX1_CLK_ENABLE();
01602     hDmaSaiRx.Init.Request             = DMA_REQUEST_SAI1_B;
01603     hDmaSaiRx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
01604     hDmaSaiRx.Init.PeriphInc           = DMA_PINC_DISABLE;
01605     hDmaSaiRx.Init.MemInc              = DMA_MINC_ENABLE;
01606     hDmaSaiRx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
01607     hDmaSaiRx.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;
01608     hDmaSaiRx.Init.Mode                = DMA_CIRCULAR;
01609     hDmaSaiRx.Init.Priority            = DMA_PRIORITY_HIGH;
01610     hDmaSaiRx.Instance                 = DMA2_Channel2;
01611     /* Associate the DMA handle */
01612     __HAL_LINKDMA(hsai, hdmarx, hDmaSaiRx);
01613     /* Deinitialize the Stream for new transfer */
01614     HAL_DMA_DeInit(&hDmaSaiRx);
01615     /* Configure the DMA Stream */
01616     HAL_DMA_Init(&hDmaSaiRx);
01617     /* SAI DMA IRQ Channel configuration */
01618     HAL_NVIC_SetPriority(DMA2_Channel2_IRQn, 5, 0);
01619     HAL_NVIC_EnableIRQ(DMA2_Channel2_IRQn);
01620   }
01621 }
01622 
01623 /**
01624   * @brief  SAI MSP De-init
01625   * @param  hsai : pointer to a SAI_HandleTypeDef structure
01626   * @retval None
01627   */
01628 void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
01629 {
01630   if(hsai->Instance == SAI1_Block_A)
01631   {
01632     /* Disable SAI DMA Channel IRQ  */
01633     HAL_NVIC_DisableIRQ(DMA2_Channel1_IRQn);
01634 
01635     /* Reset the DMA Stream configuration*/
01636     HAL_DMA_DeInit(&hDmaSaiTx);
01637 
01638     /* Don't disable the DMA clock used for other SAI block */
01639     /* __HAL_RCC_DMA2_CLK_DISABLE(); */
01640     /* __HAL_RCC_DMAMUX1_CLK_DISABLE(); */
01641 
01642     /* De-initialize FS, SCK, MCK and SD pins*/
01643     HAL_GPIO_DeInit(GPIOE, GPIO_PIN_2);  /* SAI1_MCLK_A */
01644     HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9);  /* SAI1_FS_A */
01645     HAL_GPIO_DeInit(GPIOE, GPIO_PIN_5);  /* SAI1_SCK_A */
01646     HAL_GPIO_DeInit(GPIOE, GPIO_PIN_6);  /* SAI1_SD_A */
01647 
01648     /* Don't disable SAI clock used for other SAI block */
01649     /*__HAL_RCC_SAI1_CLK_DISABLE(); */
01650   }
01651   else /* SAI1_BlockB */
01652   {
01653     /* Disable SAI DMA Channel IRQ  */
01654     HAL_NVIC_DisableIRQ(DMA2_Channel2_IRQn);
01655 
01656     /* Reset the DMA Stream configuration*/
01657     HAL_DMA_DeInit(&hDmaSaiRx);
01658 
01659     /* De-initialize SD pin */
01660     HAL_GPIO_DeInit(GPIOB, GPIO_PIN_5);  /* SAI1_SD_B */
01661 
01662     /* Disable SAI clock */
01663     __HAL_RCC_SAI1_CLK_DISABLE();
01664   }
01665 }
01666 
01667 /**
01668   * @}
01669   */
01670 
01671 /** @addtogroup STM32L4R9I_DISCOVERY_AUDIO_Private_Functions
01672   * @{
01673   */
01674 
01675 /**
01676   * @brief  Initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01677   * @param  AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral.
01678   * @retval BSP AUDIO status
01679   */
01680 static uint8_t AUDIO_DFSDMx_Init(uint32_t AudioFreq)
01681 {
01682   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01683   {
01684     /*####CHANNEL 3####*/
01685     hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Activation   = ENABLE;
01686     hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
01687     /* Set the DFSDM clock OUT audio frequency configuration */
01688     hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Divider      = DFSDMClockDivider(AudioFreq);
01689     hAudioIn.hDfsdmLeftChannel.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
01690     hAudioIn.hDfsdmLeftChannel.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
01691     hAudioIn.hDfsdmLeftChannel.Init.Input.Pins               = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
01692     /* Request to sample stable data for LEFT micro on Rising edge */
01693     hAudioIn.hDfsdmLeftChannel.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_RISING;
01694     hAudioIn.hDfsdmLeftChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
01695     hAudioIn.hDfsdmLeftChannel.Init.Awd.FilterOrder          = DFSDM_CHANNEL_SINC1_ORDER;
01696     hAudioIn.hDfsdmLeftChannel.Init.Awd.Oversampling         = 10;
01697     hAudioIn.hDfsdmLeftChannel.Init.Offset                   = 0;
01698     hAudioIn.hDfsdmLeftChannel.Init.RightBitShift            = DFSDMRightBitShift(AudioFreq);
01699     hAudioIn.hDfsdmLeftChannel.Instance                      = DFSDM1_Channel1;
01700 
01701     /* Init the DFSDM Channel */
01702     if (HAL_DFSDM_ChannelInit(&hAudioIn.hDfsdmLeftChannel) != HAL_OK)
01703     {
01704       return AUDIO_ERROR;
01705     }
01706   }
01707 
01708   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01709   {
01710     /*####CHANNEL 2####*/
01711     hAudioIn.hDfsdmRightChannel.Init.OutputClock.Activation   = ENABLE;
01712     hAudioIn.hDfsdmRightChannel.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
01713     /* Set the DFSDM clock OUT audio frequency configuration */
01714     hAudioIn.hDfsdmRightChannel.Init.OutputClock.Divider      = DFSDMClockDivider(AudioFreq);
01715     hAudioIn.hDfsdmRightChannel.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
01716     hAudioIn.hDfsdmRightChannel.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
01717     hAudioIn.hDfsdmRightChannel.Init.Input.Pins               = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS;
01718     /* Request to sample stable data for LEFT micro on Rising edge */
01719     hAudioIn.hDfsdmRightChannel.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_FALLING;
01720     hAudioIn.hDfsdmRightChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
01721     hAudioIn.hDfsdmRightChannel.Init.Awd.FilterOrder          = DFSDM_CHANNEL_SINC1_ORDER;
01722     hAudioIn.hDfsdmRightChannel.Init.Awd.Oversampling         = 10;
01723     hAudioIn.hDfsdmRightChannel.Init.Offset                   = 0;
01724     hAudioIn.hDfsdmRightChannel.Init.RightBitShift            = DFSDMRightBitShift(AudioFreq);
01725     hAudioIn.hDfsdmRightChannel.Instance                      = DFSDM1_Channel0;
01726 
01727     /* Init the DFSDM Channel */
01728     if (HAL_DFSDM_ChannelInit(&hAudioIn.hDfsdmRightChannel) != HAL_OK)
01729     {
01730       return AUDIO_ERROR;
01731     }
01732   }
01733 
01734   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01735   {
01736     /*####FILTER 0####*/
01737     BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.Trigger         = DFSDM_FILTER_SW_TRIGGER;
01738     BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.FastMode        = ENABLE;
01739     BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.DmaMode         = ENABLE;
01740     BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
01741     BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ScanMode       = DISABLE;
01742     BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.DmaMode        = DISABLE;
01743     BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO;
01744     BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES;
01745     BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.SincOrder        = DFSDMFilterOrder(AudioFreq);
01746     /* Set the DFSDM Filters Oversampling to have correct sample rate */
01747     BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.Oversampling     = DFSDMOverSampling(AudioFreq);
01748     BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.IntOversampling  = 1;
01749     BSP_AUDIO_hDfsdmLeftFilter.Instance                          = DFSDM1_Filter0;
01750 
01751     /* Init the DFSDM Filter */
01752     if (HAL_DFSDM_FilterInit(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK)
01753     {
01754       return AUDIO_ERROR;
01755     }
01756 
01757     /* Configure regular channel */
01758     if (HAL_DFSDM_FilterConfigRegChannel(&BSP_AUDIO_hDfsdmLeftFilter,
01759                                          DFSDM_CHANNEL_1,
01760                                          DFSDM_CONTINUOUS_CONV_ON) != HAL_OK)
01761     {
01762       return AUDIO_ERROR;
01763     }
01764   }
01765 
01766   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01767   {
01768     /*####FILTER 1####*/
01769     if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)
01770     {
01771       BSP_AUDIO_hDfsdmRightFilter.Init.RegularParam.Trigger       = DFSDM_FILTER_SW_TRIGGER;
01772     }
01773     else
01774     {
01775       BSP_AUDIO_hDfsdmRightFilter.Init.RegularParam.Trigger       = DFSDM_FILTER_SYNC_TRIGGER;
01776     }
01777     BSP_AUDIO_hDfsdmRightFilter.Init.RegularParam.FastMode        = ENABLE;
01778     BSP_AUDIO_hDfsdmRightFilter.Init.RegularParam.DmaMode         = ENABLE;
01779     BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
01780     BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.ScanMode       = DISABLE;
01781     BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.DmaMode        = DISABLE;
01782     BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO;
01783     BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES;
01784     BSP_AUDIO_hDfsdmRightFilter.Init.FilterParam.SincOrder        = DFSDMFilterOrder(AudioFreq);
01785     /* Set the DFSDM Filters Oversampling to have correct sample rate */
01786     BSP_AUDIO_hDfsdmRightFilter.Init.FilterParam.Oversampling     = DFSDMOverSampling(AudioFreq);
01787     BSP_AUDIO_hDfsdmRightFilter.Init.FilterParam.IntOversampling  = 1;
01788     BSP_AUDIO_hDfsdmRightFilter.Instance                          = DFSDM1_Filter1;
01789 
01790     /* Init the DFSDM Filter */
01791     if (HAL_DFSDM_FilterInit(&BSP_AUDIO_hDfsdmRightFilter) != HAL_OK)
01792     {
01793       return AUDIO_ERROR;
01794     }
01795 
01796     /* Configure regular channel */
01797     if (HAL_DFSDM_FilterConfigRegChannel(&BSP_AUDIO_hDfsdmRightFilter,
01798                                          DFSDM_CHANNEL_0,
01799                                          DFSDM_CONTINUOUS_CONV_ON) != HAL_OK)
01800     {
01801       return AUDIO_ERROR;
01802     }
01803   }
01804 
01805   return AUDIO_OK;
01806 }
01807 
01808 /**
01809   * @brief  De-initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01810   * @retval BSP AUDIO status
01811   */
01812 static uint8_t AUDIO_DFSDMx_DeInit(void)
01813 {
01814   /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */
01815   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01816   {
01817     if (HAL_DFSDM_FilterDeInit(&BSP_AUDIO_hDfsdmRightFilter) != HAL_OK)
01818     {
01819       return AUDIO_ERROR;
01820     }
01821   }
01822   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01823   {
01824     if (HAL_DFSDM_FilterDeInit(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK)
01825     {
01826       return AUDIO_ERROR;
01827     }
01828   }
01829 
01830   /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */
01831   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01832   {
01833     if (HAL_DFSDM_ChannelDeInit(&hAudioIn.hDfsdmRightChannel) != HAL_OK)
01834     {
01835       return AUDIO_ERROR;
01836     }
01837   }
01838   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01839   {
01840     if (HAL_DFSDM_ChannelDeInit(&hAudioIn.hDfsdmLeftChannel) != HAL_OK)
01841     {
01842       return AUDIO_ERROR;
01843     }
01844   }
01845 
01846   /* DFSDM reset */
01847   __HAL_RCC_DFSDM1_FORCE_RESET();
01848   __HAL_RCC_DFSDM1_RELEASE_RESET();
01849 
01850   return AUDIO_OK;
01851 }
01852 
01853 /**
01854   * @brief  Initializes the DFSDM channel MSP.
01855   * @param  hdfsdm_channel : DFSDM channel handle.
01856   * @retval None
01857   */
01858 void HAL_DFSDM_ChannelMspInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
01859 {
01860   if (((hdfsdm_channel->Instance == DFSDM1_Channel1) && ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) != 0)) || \
01861       ((hdfsdm_channel->Instance == DFSDM1_Channel0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)))
01862   {
01863     GPIO_InitTypeDef  GPIO_InitStruct;
01864 
01865     /* Enable DFSDM clock */
01866     __HAL_RCC_DFSDM1_CLK_ENABLE();
01867 
01868     /* DFSDM pins configuration: DFSDM1_CKOUT, DFSDM1_DATIN1 pins */
01869     __HAL_RCC_GPIOB_CLK_ENABLE();
01870     __HAL_RCC_GPIOC_CLK_ENABLE();
01871     GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
01872     GPIO_InitStruct.Pull      = GPIO_NOPULL;
01873     GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
01874     GPIO_InitStruct.Alternate = GPIO_AF6_DFSDM1;
01875     GPIO_InitStruct.Pin       = GPIO_PIN_2;
01876     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /* DFSDM1_CKOUT */
01877     GPIO_InitStruct.Pin       = GPIO_PIN_12;
01878     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* DFSDM1_DATIN1 */
01879 
01880     /* Enable MIC_VDD (PH2) */
01881     __HAL_RCC_GPIOH_CLK_ENABLE();
01882     GPIO_InitStruct.Mode      = GPIO_MODE_OUTPUT_PP;
01883     GPIO_InitStruct.Pull      = GPIO_NOPULL;
01884     GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
01885     GPIO_InitStruct.Pin       = GPIO_PIN_2;
01886     HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
01887     HAL_GPIO_WritePin(GPIOH, GPIO_PIN_2, GPIO_PIN_SET);
01888   }
01889 }
01890 
01891 /**
01892   * @brief  De-initializes the DFSDM channel MSP.
01893   * @param  hdfsdm_channel : DFSDM channel handle.
01894   * @retval None
01895   */
01896 void HAL_DFSDM_ChannelMspDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
01897 {
01898   if (((hdfsdm_channel->Instance == DFSDM1_Channel1) && ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) != 0)) || \
01899       ((hdfsdm_channel->Instance == DFSDM1_Channel0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)))
01900   {
01901     /* Disable MIC_VDD (PH2) */
01902     HAL_GPIO_WritePin(GPIOH, GPIO_PIN_2, GPIO_PIN_RESET);
01903     HAL_GPIO_DeInit(GPIOH, GPIO_PIN_2);
01904 
01905     /* De-initialize DFSDM1_CKOUT, DFSDM1_DATIN1 pins */
01906     HAL_GPIO_DeInit(GPIOC, GPIO_PIN_2);  /* DFSDM1_CKOUT */
01907     HAL_GPIO_DeInit(GPIOB, GPIO_PIN_12); /* DFSDM1_DATIN1 */
01908 
01909     /* Disable DFSDM1 */
01910     __HAL_RCC_DFSDM1_CLK_DISABLE();
01911   }
01912 }
01913 
01914 /**
01915   * @brief  Initializes the DFSDM filter MSP.
01916   * @param  hdfsdm_filter : DFSDM filter handle.
01917   * @retval None
01918   */
01919 void HAL_DFSDM_FilterMspInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01920 {
01921   if(hdfsdm_filter->Instance == DFSDM1_Filter0)
01922   {
01923     /* Enable the DMA clock */
01924     __HAL_RCC_DMA1_CLK_ENABLE();
01925     __HAL_RCC_DMAMUX1_CLK_ENABLE();
01926 
01927     /* Configure the hAudioIn.hDmaDfsdmLeft handle parameters */
01928     hAudioIn.hDmaDfsdmLeft.Init.Request             = DMA_REQUEST_DFSDM1_FLT0;
01929     hAudioIn.hDmaDfsdmLeft.Init.Direction           = DMA_PERIPH_TO_MEMORY;
01930     hAudioIn.hDmaDfsdmLeft.Init.PeriphInc           = DMA_PINC_DISABLE;
01931     hAudioIn.hDmaDfsdmLeft.Init.MemInc              = DMA_MINC_ENABLE;
01932     hAudioIn.hDmaDfsdmLeft.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
01933     hAudioIn.hDmaDfsdmLeft.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
01934     hAudioIn.hDmaDfsdmLeft.Init.Mode                = DMA_CIRCULAR;
01935     hAudioIn.hDmaDfsdmLeft.Init.Priority            = DMA_PRIORITY_HIGH;
01936     hAudioIn.hDmaDfsdmLeft.Instance                 = DMA1_Channel4;
01937 
01938     /* Associate the DMA handle */
01939     __HAL_LINKDMA(hdfsdm_filter, hdmaReg, hAudioIn.hDmaDfsdmLeft);
01940 
01941     /* Reset DMA handle state */
01942     __HAL_DMA_RESET_HANDLE_STATE(&hAudioIn.hDmaDfsdmLeft);
01943 
01944     /* Configure the DMA Channel */
01945     HAL_DMA_Init(&hAudioIn.hDmaDfsdmLeft);
01946 
01947     /* DMA IRQ Channel configuration */
01948     HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 5, 0);
01949     HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
01950   }
01951   else /* DFSDM1_Filter1 */
01952   {
01953     if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)
01954     {
01955       /* Enable the DMA clock needed if only MIC2 is used */
01956       __HAL_RCC_DMA1_CLK_ENABLE();
01957       __HAL_RCC_DMAMUX1_CLK_ENABLE();
01958     }
01959 
01960     /* Configure the hAudioIn.hDmaDfsdmRight handle parameters */
01961     hAudioIn.hDmaDfsdmRight.Init.Request             = DMA_REQUEST_DFSDM1_FLT1;
01962     hAudioIn.hDmaDfsdmRight.Init.Direction           = DMA_PERIPH_TO_MEMORY;
01963     hAudioIn.hDmaDfsdmRight.Init.PeriphInc           = DMA_PINC_DISABLE;
01964     hAudioIn.hDmaDfsdmRight.Init.MemInc              = DMA_MINC_ENABLE;
01965     hAudioIn.hDmaDfsdmRight.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
01966     hAudioIn.hDmaDfsdmRight.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
01967     hAudioIn.hDmaDfsdmRight.Init.Mode                = DMA_CIRCULAR;
01968     hAudioIn.hDmaDfsdmRight.Init.Priority            = DMA_PRIORITY_HIGH;
01969     hAudioIn.hDmaDfsdmRight.Instance                 = DMA1_Channel5;
01970 
01971     /* Associate the DMA handle */
01972     __HAL_LINKDMA(hdfsdm_filter, hdmaReg, hAudioIn.hDmaDfsdmRight);
01973 
01974     /* Reset DMA handle state */
01975     __HAL_DMA_RESET_HANDLE_STATE(&hAudioIn.hDmaDfsdmRight);
01976 
01977     /* Configure the DMA Channel */
01978     HAL_DMA_Init(&hAudioIn.hDmaDfsdmRight);
01979 
01980     /* DMA IRQ Channel configuration */
01981     HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 5, 0);
01982     HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
01983   }
01984 }
01985 
01986  /**
01987   * @brief  De-initializes the DFSDM filter MSP.
01988   * @param  hdfsdm_filter : DFSDM filter handle.
01989   * @retval None
01990   */
01991 void HAL_DFSDM_FilterMspDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01992 {
01993   if(hdfsdm_filter->Instance == DFSDM1_Filter0)
01994   {
01995     /* Disable DMA  Channel IRQ */
01996     HAL_NVIC_DisableIRQ(DMA1_Channel4_IRQn);
01997 
01998     /* De-initialize the DMA Channel */
01999     HAL_DMA_DeInit(&hAudioIn.hDmaDfsdmLeft);
02000   }
02001   else /* DFSDM1_Filter1 */
02002   {
02003     /* Disable DMA  Channel IRQ */
02004     HAL_NVIC_DisableIRQ(DMA1_Channel5_IRQn);
02005 
02006     /* De-initialize the DMA Channel */
02007     HAL_DMA_DeInit(&hAudioIn.hDmaDfsdmRight);
02008   }
02009 }
02010 
02011 /**
02012   * @brief  Configures the SAI PLL clock according to the required audio frequency.
02013   * @param  Frequency: Audio frequency.
02014   * @retval BSP AUDIO status
02015   * @note   The SAI PLL input clock must be configured in the user application.
02016   *         The SAI PLL configuration done within this function assumes that
02017   *         the SAI PLL input clock runs at 4 MHz.
02018   */
02019 static uint8_t AUDIO_SAIPLLConfig(uint32_t Frequency)
02020 {
02021   RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct;
02022 
02023   /* Retrieve actual RCC configuration */
02024   HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct);
02025 
02026   if (   (Frequency == AUDIO_FREQUENCY_11K)
02027       || (Frequency == AUDIO_FREQUENCY_22K)
02028       || (Frequency == AUDIO_FREQUENCY_44K) )
02029   {
02030     /* Configure PLLSAI prescalers */
02031     /* SAI clock config
02032     PLLSAI1_VCO= 4 Mhz * PLLSAI1N = 4 * 48 = VCO_192M
02033     SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 192/17 = 11.294 Mhz */
02034     RCC_ExCLKInitStruct.PeriphClockSelection    = RCC_PERIPHCLK_SAI1;
02035     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1M        = 1;
02036     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N        = 48;
02037     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P        = 17;
02038     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
02039     RCC_ExCLKInitStruct.Sai1ClockSelection      = RCC_SAI1CLKSOURCE_PLLSAI1;
02040   }
02041   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
02042   {
02043     /* SAI clock config
02044     PLLSAI2_VCO= 4 Mhz * PLLSAI1N = 4 * 86 = VCO_344M
02045     SAI_CK_x = PLLSAI1_VCO/PLLSAI2P = 344/7 = 49.142 Mhz */
02046     RCC_ExCLKInitStruct.PeriphClockSelection    = RCC_PERIPHCLK_SAI1;
02047     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1M        = 1;
02048     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N        = 86;
02049     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P        = 7;
02050     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
02051     RCC_ExCLKInitStruct.Sai1ClockSelection      = RCC_SAI1CLKSOURCE_PLLSAI1;
02052   }
02053 
02054   if (HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct) != HAL_OK)
02055   {
02056     return AUDIO_ERROR;
02057   }
02058 
02059   return AUDIO_OK;
02060 }
02061 
02062 /**
02063   * @}
02064   */
02065 
02066 /**
02067   * @}
02068   */
02069 
02070 /**
02071   * @}
02072   */
02073 
02074 /**
02075   * @}
02076   */
02077 
02078 /**
02079   * @}
02080   */
02081 
02082 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/