STM32H743I_EVAL BSP User Manual: stm32h743i_eval_audio.c Source File

STM32H743I_EVAL BSP

stm32h743i_eval_audio.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32h743i_eval_audio.c
00004   * @author  MCD Application Team
00005   * @version V1.0.0
00006   * @date    21-April-2017
00007   * @brief   This file provides the Audio driver for the STM32H743I-EVAL
00008   *          board.
00009   @verbatim
00010   How To use this driver:
00011   -----------------------
00012    + This driver supports STM32H7xx devices on STM32H743I-EVAL (MB1246) Evaluation boards.
00013    + Call the function BSP_AUDIO_OUT_Init(
00014                                     OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER,
00015                                                   OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH)
00016                                     Volume      : Initial volume to be set (0 is min (mute), 100 is max (100%)
00017                                     AudioFreq   : Audio frequency in Hz (8000, 16000, 22500, 32000...)
00018                                                   this parameter is relative to the audio file/stream type.
00019                                    )
00020       This function configures all the hardware required for the audio application (codec, I2C, SAI,
00021       GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK.
00022       If the returned value is different from AUDIO_OK or the function is stuck then the communication with
00023       the codec or the MFX has failed (try to un-plug the power or reset device in this case).
00024       - OUTPUT_DEVICE_SPEAKER  : only speaker will be set as output for the audio stream.
00025       - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream.
00026       - OUTPUT_DEVICE_BOTH     : both Speaker and Headphone are used as outputs for the audio stream
00027                                  at the same time.
00028       Note. On STM32H743I-EVAL SAI_DMA is configured in CIRCULAR mode. Due to this the application
00029         does NOT need to call BSP_AUDIO_OUT_ChangeBuffer() to assure streaming.
00030    + Call the function BSP_AUDIO_OUT_Play(
00031                                   pBuffer: pointer to the audio data file address
00032                                   Size   : size of the buffer to be sent in Bytes
00033                                  )
00034       to start playing (for the first time) from the audio file/stream.
00035    + Call the function BSP_AUDIO_OUT_Pause() to pause playing
00036    + Call the function BSP_AUDIO_OUT_Resume() to resume playing.
00037        Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called
00038           for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case).
00039        Note. This function should be called only when the audio file is played or paused (not stopped).
00040    + For each mode, you may need to implement the relative callback functions into your code.
00041       The Callback functions are named BSP_AUDIO_OUT_XXX_CallBack() and only their prototypes are declared in
00042       the stm32h743i_eval_audio.h file. (refer to the example for more details on the callbacks implementations)
00043    + To Stop playing, to modify the volume level, the frequency, the audio frame slot,
00044       the device output mode the mute or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(),
00045       AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetAudioFrameSlot(), BSP_AUDIO_OUT_SetOutputMode(),
00046       BSP_AUDIO_OUT_SetMute() and BSP_AUDIO_OUT_Stop().
00047 
00048    + Call the function BSP_AUDIO_IN_Init(
00049                                     AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000...)
00050                                                   this parameter is relative to the audio file/stream type.
00051                                     BitRes: Bit resolution fixed to 16bit
00052                                     ChnlNbr: Number of channel to be configured for the DFSDM peripheral
00053                                    )
00054       This function configures all the hardware required for the audio in application (DFSDM filters and channels,
00055       Clock source for DFSDM periphiral, GPIOs, DMA and interrupt if needed).
00056       This function returns AUDIO_OK if configuration is OK.If the returned value is different from AUDIO_OK then
00057       the configuration should be wrong.
00058       Note: On STM32H743I-EVAL, two DFSDM Channel/Filters are configured and their DMA streams are configured
00059             in CIRCULAR mode.
00060    + Call the function BSP_AUDIO_IN_AllocScratch(
00061                                         pScratch: pointer to scratch tables
00062                                         size: size of scratch buffer)
00063      This function must be called before BSP_AUDIO_IN_RECORD() to allocate buffer scratch for each DFSDM channel
00064      and its size.
00065      Note: These buffers scratch are used as intermidiate buffers to collect data within final record buffer.
00066            size is the total size of the four buffers scratch; If size is 512 then the size of each is 128.
00067            This function must be called after BSP_AUDIO_IN_Init()
00068    + Call the function BSP_AUDIO_IN_RECORD(
00069                                   pBuf: pointer to the recorded audio data file address
00070                                   Size: size of the buffer to be written in Bytes
00071                                  )
00072       to start recording from microphones.
00073 
00074    + Call the function BSP_AUDIO_IN_Pause() to pause recording
00075    + Call the function BSP_AUDIO_IN_Resume() to recording playing.
00076        Note. After calling BSP_AUDIO_IN_Pause() function for pause, only BSP_AUDIO_IN_Resume() should be called
00077           for resume (it is not allowed to call BSP_AUDIO_IN_RECORD() in this case).
00078    + Call the function BSP_AUDIO_IN_Stop() to stop recording
00079    + For each mode, you may need to implement the relative callback functions into your code.
00080       The Callback functions are named BSP_AUDIO_IN_XXX_CallBack() and only their prototypes are declared in
00081       the stm32h743i_eval_audio.h file. (refer to the example for more details on the callbacks implementations)
00082    + Call the function BSP_AUDIO_IN_SelectInterface(uint32_t Interface) to select one of the three interfaces
00083      available on the STM32H743I-EVAL board: SAI, DFSDM or PDM. This function is to be called before BSP_AUDIO_IN_InitEx().
00084    + Call the function BSP_AUDIO_IN_GetInterface() to get the current used interface.
00085    + Call the function BSP_AUDIO_IN_PDMToPCM_Init(uint32_t AudioFreq, uint32_t ChnlNbrIn, uint32_t ChnlNbrOut)
00086      to init PDM filters if the libPDMFilter is used for audio data filtering.
00087    + Call the function BSP_AUDIO_IN_PDMToPCM(uint16_t* PDMBuf, uint16_t* PCMBuf) to filter PDM data to PCM format
00088      if the libPDMFilter library is used for audio data filtering.
00089 
00090   Driver architecture:
00091   --------------------
00092    + This driver provides the High Audio Layer: consists of the function API exported in the stm32h743i_eval_audio.h file
00093      (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...)
00094    + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/
00095      providing the audio file/stream. These functions are also included as local functions into
00096      the stm32h743i_eval_audio.c file (DFSDMx_Init(), DFSDMx_DeInit(), SAIx_Init() and SAIx_DeInit())
00097 
00098   Known Limitations:
00099   ------------------
00100    1- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second
00101       Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams.
00102    2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size,
00103       File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file.
00104    3- Supports only Stereo audio streaming.
00105    4- Supports only 16-bits audio data size.
00106   @endverbatim
00107   ******************************************************************************
00108   * @attention
00109   *
00110   * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
00111   *
00112   * Redistribution and use in source and binary forms, with or without modification,
00113   * are permitted provided that the following conditions are met:
00114   *   1. Redistributions of source code must retain the above copyright notice,
00115   *      this list of conditions and the following disclaimer.
00116   *   2. Redistributions in binary form must reproduce the above copyright notice,
00117   *      this list of conditions and the following disclaimer in the documentation
00118   *      and/or other materials provided with the distribution.
00119   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00120   *      may be used to endorse or promote products derived from this software
00121   *      without specific prior written permission.
00122   *
00123   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00124   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00125   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00126   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00127   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00128   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00129   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00130   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00131   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00132   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00133   *
00134   ******************************************************************************
00135   */
00136 /* Includes ------------------------------------------------------------------*/
00137 #include "stm32h743i_eval_audio.h"
00138 
00139 /** @addtogroup BSP
00140   * @{
00141   */
00142 
00143 /** @addtogroup STM32H743I_EVAL
00144   * @{
00145   */
00146 
00147 /** @addtogroup STM32H743I_EVAL_AUDIO STM32H743I EVAL board BSP AUDIO
00148   * @brief    This file includes the low layer driver for wm8994 Audio Codec
00149   *           available on STM32H743I-EVAL board (MB1246).
00150   * @{
00151   */
00152 
00153 /** @defgroup STM32H743I_EVAL_AUDIO_Private_Types AUDIO Private Types
00154   * @{
00155   */
00156 /**
00157   * @}
00158   */
00159 
00160 /** @defgroup STM32H743I_EVAL_AUDIO_Private_Defines AUDIO Private Defines
00161   * @{
00162   */
00163 /**
00164   * @}
00165   */
00166 
00167 /** @defgroup STM32H743I_EVAL_AUDIO_Private_Macros AUDIO Private Macros
00168   * @{
00169   */
00170 #define DFSDM_OVER_SAMPLING(__FREQUENCY__) \
00171         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 256 \
00172       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \
00173       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \
00174       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \
00175       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \
00176       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64  \
00177       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 40 : 20  \
00178 
00179 #define DFSDM_CLOCK_DIVIDER(__FREQUENCY__) \
00180         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 24 \
00181       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \
00182       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \
00183       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
00184       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \
00185       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4  \
00186       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 25 : 25  \
00187 
00188 #define DFSDM_FILTER_ORDER(__FREQUENCY__) \
00189         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? DFSDM_FILTER_SINC3_ORDER \
00190       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \
00191       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \
00192       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \
00193       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \
00194       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC3_ORDER  \
00195       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC3_ORDER : DFSDM_FILTER_SINC5_ORDER  \
00196 
00197 #define DFSDM_MIC_BIT_SHIFT(__FREQUENCY__) \
00198         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 8 \
00199       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 8 \
00200       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 3 \
00201       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
00202       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 7 \
00203       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 2  \
00204       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 0 : 4  \
00205 
00206 /* Saturate the record PCM sample */
00207 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N)))
00208 
00209 /**
00210   * @}
00211   */
00212 
00213 /** @defgroup STM32H743I_EVAL_AUDIO_Private_Variables AUDIO Private Variables
00214   * @{
00215   */
00216 /* PLAY */
00217 AUDIO_DrvTypeDef                *audio_drv;
00218 SAI_HandleTypeDef               haudio_out_sai;
00219 SAI_HandleTypeDef               haudio_in_sai;
00220 
00221 /* RECORD */
00222 AUDIOIN_ContextTypeDef          hAudioIn;
00223 
00224 DFSDM_Channel_HandleTypeDef     hAudioInDfsdmChannel[DFSDM_MIC_NUMBER];  /* 2 DFSDM channel handle used for all microphones */
00225 DFSDM_Filter_HandleTypeDef      hAudioInDfsdmFilter[DFSDM_MIC_NUMBER];   /* 2 DFSDM filter handle */
00226 DMA_HandleTypeDef               hDmaDfsdm[DFSDM_MIC_NUMBER];             /* 2 DMA handle used for DFSDM regular conversions */
00227 
00228 /* Buffers for right and left samples */
00229 int32_t                         *pScratchBuff[DEFAULT_AUDIO_IN_CHANNEL_NBR];
00230 int32_t                         ScratchSize;
00231 
00232 uint32_t                        DmaRecHalfBuffCplt[DFSDM_MIC_NUMBER]  = {0};
00233 uint32_t                        DmaRecBuffCplt[DFSDM_MIC_NUMBER]  = {0};
00234 
00235 
00236 /* Application Buffer Trigger */
00237 __IO uint32_t                   AppBuffTrigger          = 0;
00238 __IO uint32_t                   AppBuffHalf             = 0;
00239 __IO uint32_t                   MicBuff[DFSDM_MIC_NUMBER] = {0};
00240 __IO uint16_t                   AudioInVolume = DEFAULT_AUDIO_IN_VOLUME;
00241 
00242 /* PDM filters params */
00243 PDM_Filter_Handler_t  PDM_FilterHandler[2];
00244 PDM_Filter_Config_t   PDM_FilterConfig[2];
00245 
00246 /**
00247   * @}
00248   */
00249 
00250 /** @defgroup STM32H743I_EVAL_AUDIO_OUT_Private_Function_Prototypes AUDIO OUT Private Function Prototypes
00251   * @{
00252   */
00253 static void SAIx_Out_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq);
00254 static void SAIx_Out_DeInit(SAI_HandleTypeDef *hsai);
00255 
00256 /**
00257   * @}
00258   */
00259 
00260 /** @defgroup STM32H743I_EVAL_AUDIO_IN_Private_Function_Prototypes AUDIO IN Private Function Prototypes
00261   * @{
00262   */
00263 static void SAIx_In_MspInit(SAI_HandleTypeDef *hsai, void *Params);
00264 static void SAIx_In_MspDeInit(SAI_HandleTypeDef *hsai, void *Params);
00265 static void SAIx_In_Init(uint32_t SaiInMode, uint32_t SlotActive, uint32_t AudioFreq);
00266 static void SAIx_In_DeInit(SAI_HandleTypeDef *hsai);
00267 static uint8_t DFSDMx_DeInit(void);
00268 static void DFSDMx_ChannelMspInit(void);
00269 static void DFSDMx_ChannelMspDeInit(void);
00270 static void DFSDMx_FilterMspInit(void);
00271 static void DFSDMx_FilterMspDeInit(void);
00272 
00273 /**
00274   * @}
00275   */
00276 
00277 /** @addtogroup STM32H743I_EVAL_AUDIO_OUT_Exported_Functions
00278   * @{
00279   */
00280 
00281 /**
00282   * @brief  Configures the audio Out peripheral.
00283   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
00284   *                       or OUTPUT_DEVICE_BOTH.
00285   * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
00286   * @param  AudioFreq: Audio frequency used to play the audio stream.
00287   * @retval AUDIO_OK if correct communication, else wrong communication
00288   */
00289 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
00290 {
00291   uint8_t ret = AUDIO_ERROR;
00292   uint32_t deviceid = 0x00;
00293   uint32_t slot_active;
00294 
00295   /* Initialize SAI1 sub_block A as MASTER TX */
00296   haudio_out_sai.Instance = AUDIO_OUT_SAIx;
00297 
00298   /* Disable SAI */
00299   SAIx_Out_DeInit(&haudio_out_sai);
00300 
00301   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */
00302   BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
00303 
00304   /* SAI data transfer preparation:
00305   Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
00306 
00307   if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET)
00308   {
00309     /* Init the SAI MSP: this __weak function can be redefined by the application*/
00310     BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL);
00311   }
00312 
00313   /* Init SAI as master RX output */
00314   slot_active = CODEC_AUDIOFRAME_SLOT_0123;
00315   SAIx_Out_Init(SAI_MODEMASTER_TX, slot_active, AudioFreq);
00316 
00317   /* wm8994 codec initialization */
00318   deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
00319 
00320   if((deviceid) == WM8994_ID)
00321   {
00322     /* Reset the Codec Registers */
00323     wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
00324     /* Initialize the audio driver structure */
00325     audio_drv = &wm8994_drv;
00326     ret = AUDIO_OK;
00327   }
00328   else
00329   {
00330     ret = AUDIO_ERROR;
00331   }
00332 
00333   if(ret == AUDIO_OK)
00334   {
00335     /* Initialize the codec internal registers */
00336     audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq);
00337   }
00338 
00339   return ret;
00340 }
00341 
00342 /**
00343   * @brief  Starts playing audio stream from a data buffer for a determined size.
00344   * @param  pBuffer: Pointer to the buffer
00345   * @param  Size: Number of audio data BYTES.
00346   * @retval AUDIO_OK if correct communication, else wrong communication
00347   */
00348 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size)
00349 {
00350   /* Call the audio Codec Play function */
00351   if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0)
00352   {
00353     return AUDIO_ERROR;
00354   }
00355   else
00356   {
00357     /* Update the Media layer and enable it for play */
00358     HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE));
00359 
00360     return AUDIO_OK;
00361   }
00362 }
00363 
00364 /**
00365   * @brief  Sends n-Bytes on the SAI interface.
00366   * @param  pData: pointer on data address
00367   * @param  Size: number of data to be written
00368   * @retval None
00369   */
00370 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size)
00371 {
00372    HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size);
00373 }
00374 
00375 /**
00376   * @brief  This function Pauses the audio file stream. In case
00377   *         of using DMA, the DMA Pause feature is used.
00378   * @warning When calling BSP_AUDIO_OUT_Pause() function for pause, only
00379   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play()
00380   *          function for resume could lead to unexpected behaviour).
00381   * @retval AUDIO_OK if correct communication, else wrong communication
00382   */
00383 uint8_t BSP_AUDIO_OUT_Pause(void)
00384 {
00385   /* Call the Audio Codec Pause/Resume function */
00386   if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0)
00387   {
00388     return AUDIO_ERROR;
00389   }
00390   else
00391   {
00392     /* Call the Media layer pause function */
00393     HAL_SAI_DMAPause(&haudio_out_sai);
00394 
00395     /* Return AUDIO_OK when all operations are correctly done */
00396     return AUDIO_OK;
00397   }
00398 }
00399 
00400 /**
00401   * @brief   Resumes the audio file stream.
00402   * @warning When calling BSP_AUDIO_OUT_Pause() function for pause, only
00403   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play()
00404   *          function for resume could lead to unexpected behaviour).
00405   * @retval AUDIO_OK if correct communication, else wrong communication
00406   */
00407 uint8_t BSP_AUDIO_OUT_Resume(void)
00408 {
00409   /* Call the Audio Codec Pause/Resume function */
00410   if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0)
00411   {
00412     return AUDIO_ERROR;
00413   }
00414   else
00415   {
00416     /* Call the Media layer pause/resume function */
00417     HAL_SAI_DMAResume(&haudio_out_sai);
00418 
00419     /* Return AUDIO_OK when all operations are correctly done */
00420     return AUDIO_OK;
00421   }
00422 }
00423 
00424 /**
00425   * @brief  Stops audio playing and Power down the Audio Codec.
00426   * @param  Option: could be one of the following parameters
00427   *           - CODEC_PDWN_SW: for software power off (by writing registers).
00428   *                            Then no need to reconfigure the Codec after power on.
00429   *           - CODEC_PDWN_HW: completely shut down the codec (physically).
00430   *                            Then need to reconfigure the Codec after power on.
00431   * @retval AUDIO_OK if correct communication, else wrong communication
00432   */
00433 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
00434 {
00435   /* Call the Media layer stop function */
00436   HAL_SAI_DMAStop(&haudio_out_sai);
00437 
00438   /* Call Audio Codec Stop function */
00439   if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
00440   {
00441     return AUDIO_ERROR;
00442   }
00443   else
00444   {
00445     if(Option == CODEC_PDWN_HW)
00446     {
00447       /* Wait at least 100us */
00448       HAL_Delay(1);
00449     }
00450     /* Return AUDIO_OK when all operations are correctly done */
00451     return AUDIO_OK;
00452   }
00453 }
00454 
00455 /**
00456   * @brief  Controls the current audio volume level.
00457   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for
00458   *         Mute and 100 for Max volume level).
00459   * @retval AUDIO_OK if correct communication, else wrong communication
00460   */
00461 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume)
00462 {
00463   /* Call the codec volume control function with converted volume value */
00464   if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
00465   {
00466     return AUDIO_ERROR;
00467   }
00468   else
00469   {
00470     /* Return AUDIO_OK when all operations are correctly done */
00471     return AUDIO_OK;
00472   }
00473 }
00474 
00475 /**
00476   * @brief  Enables or disables the MUTE mode by software
00477   * @param  Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to
00478   *         unmute the codec and restore previous volume level.
00479   * @retval AUDIO_OK if correct communication, else wrong communication
00480   */
00481 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd)
00482 {
00483   /* Call the Codec Mute function */
00484   if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0)
00485   {
00486     return AUDIO_ERROR;
00487   }
00488   else
00489   {
00490     /* Return AUDIO_OK when all operations are correctly done */
00491     return AUDIO_OK;
00492   }
00493 }
00494 
00495 /**
00496   * @brief  Switch dynamically (while audio file is played) the output target
00497   *         (speaker or headphone).
00498   * @param  Output: The audio output target: OUTPUT_DEVICE_SPEAKER,
00499   *         OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH
00500   * @retval AUDIO_OK if correct communication, else wrong communication
00501   */
00502 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)
00503 {
00504   /* Call the Codec output device function */
00505   if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0)
00506   {
00507     return AUDIO_ERROR;
00508   }
00509   else
00510   {
00511     /* Return AUDIO_OK when all operations are correctly done */
00512     return AUDIO_OK;
00513   }
00514 }
00515 
00516 /**
00517   * @brief  Updates the audio frequency.
00518   * @param  AudioFreq: Audio frequency used to play the audio stream.
00519   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00520   *         audio frequency.
00521   * @retval None
00522   */
00523 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)
00524 {
00525   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */
00526   BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
00527 
00528   /* Disable SAI peripheral to allow access to SAI internal registers */
00529   __HAL_SAI_DISABLE(&haudio_out_sai);
00530 
00531   /* Update the SAI audio frequency configuration */
00532   haudio_out_sai.Init.AudioFrequency = AudioFreq;
00533   HAL_SAI_Init(&haudio_out_sai);
00534 
00535   /* Enable SAI peripheral to generate MCLK */
00536   __HAL_SAI_ENABLE(&haudio_out_sai);
00537 }
00538 
00539 /**
00540   * @brief  Updates the Audio frame slot configuration.
00541   * @param  AudioFrameSlot: specifies the audio Frame slot
00542   *         This parameter can be any value of @ref CODEC_AUDIO_FRAME_SLOT_TDM
00543   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00544   *         audio frame slot.
00545   * @retval None
00546   */
00547 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot)
00548 {
00549   /* Disable SAI peripheral to allow access to SAI internal registers */
00550   __HAL_SAI_DISABLE(&haudio_out_sai);
00551 
00552   /* Update the SAI audio frame slot configuration */
00553   haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot;
00554   HAL_SAI_Init(&haudio_out_sai);
00555 
00556   /* Enable SAI peripheral to generate MCLK */
00557   __HAL_SAI_ENABLE(&haudio_out_sai);
00558 }
00559 
00560 /**
00561   * @brief  De-initializes the audio out peripheral.
00562   * @retval None
00563   */
00564 void BSP_AUDIO_OUT_DeInit(void)
00565 {
00566   SAIx_Out_DeInit(&haudio_out_sai);
00567   /* DeInit the SAI MSP : this __weak function can be rewritten by the application */
00568   BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL);
00569 }
00570 
00571 /**
00572   * @brief  Manages the DMA full Transfer complete event.
00573   * @retval None
00574   */
00575 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
00576 {
00577 }
00578 
00579 /**
00580   * @brief  Manages the DMA Half Transfer complete event.
00581   * @retval None
00582   */
00583 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void)
00584 {
00585 }
00586 
00587 /**
00588   * @brief  Manages the DMA FIFO error event.
00589   * @retval None
00590   */
00591 __weak void BSP_AUDIO_OUT_Error_CallBack(void)
00592 {
00593 }
00594 
00595 /**
00596   * @brief  Initializes BSP_AUDIO_OUT MSP.
00597   * @param  hsai: SAI handle
00598   * @param  Params: pointer on additional configuration parameters, can be NULL.
00599   * @retval None
00600   */
00601 __weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params)
00602 {
00603   static DMA_HandleTypeDef hdma_sai_tx;
00604   GPIO_InitTypeDef  gpio_init_structure;
00605 
00606   /* Enable SAI clock */
00607   AUDIO_OUT_SAIx_CLK_ENABLE();
00608 
00609   /* CODEC_SAI pins configuration: FS, SCK and SD pins */
00610   /* Enable FS, SCK and SD clocks */
00611   AUDIO_OUT_SAIx_SD_FS_CLK_ENABLE();
00612   /* Enable FS, SCK and SD pins */
00613   gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SD_PIN;
00614   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
00615   gpio_init_structure.Pull = GPIO_NOPULL;
00616   gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
00617   gpio_init_structure.Alternate = AUDIO_OUT_SAIx_AF;
00618   HAL_GPIO_Init(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, &gpio_init_structure);
00619 
00620   /* Enable MCLK pin if the PDM input interface is not activated
00621     (since if PDM input interface is activated the MCLK pin is configured in BSP_AUDIO_IN_MspInit) */
00622   if(hAudioIn.Interface != AUDIO_IN_INTERFACE_PDM && (haudio_in_sai.State != HAL_SAI_STATE_READY))
00623   {
00624     /* Enable MCLK clock */
00625     AUDIO_OUT_SAIx_MCLK_ENABLE();
00626     /* Enable MCLK pin */
00627     gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN;
00628     HAL_GPIO_Init(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, &gpio_init_structure);
00629   }
00630 
00631   /* Enable the DMA clock */
00632   AUDIO_OUT_SAIx_DMAx_CLK_ENABLE();
00633 
00634   if(hsai->Instance == AUDIO_OUT_SAIx)
00635   {
00636     /* Configure the hdma_saiTx handle parameters */
00637     hdma_sai_tx.Init.Request             = AUDIO_OUT_SAIx_DMAx_REQUEST;
00638     hdma_sai_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
00639     hdma_sai_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
00640     hdma_sai_tx.Init.MemInc              = DMA_MINC_ENABLE;
00641     hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_OUT_SAIx_DMAx_PERIPH_DATA_SIZE;
00642     hdma_sai_tx.Init.MemDataAlignment    = AUDIO_OUT_SAIx_DMAx_MEM_DATA_SIZE;
00643     hdma_sai_tx.Init.Mode                = DMA_CIRCULAR;
00644     hdma_sai_tx.Init.Priority            = DMA_PRIORITY_HIGH;
00645     hdma_sai_tx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
00646     hdma_sai_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
00647     hdma_sai_tx.Init.MemBurst            = DMA_MBURST_SINGLE;
00648     hdma_sai_tx.Init.PeriphBurst         = DMA_PBURST_SINGLE;
00649 
00650     hdma_sai_tx.Instance = AUDIO_OUT_SAIx_DMAx_STREAM;
00651 
00652     /* Associate the DMA handle */
00653     __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx);
00654 
00655     /* Deinitialize the Stream for new transfer */
00656     HAL_DMA_DeInit(&hdma_sai_tx);
00657 
00658     /* Configure the DMA Stream */
00659     HAL_DMA_Init(&hdma_sai_tx);
00660   }
00661 
00662   /* SAI DMA IRQ Channel configuration */
00663   HAL_NVIC_SetPriority(AUDIO_OUT_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
00664   HAL_NVIC_EnableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ);
00665 }
00666 
00667 /**
00668   * @brief  Deinitializes SAI MSP.
00669   * @param  hsai: SAI handle
00670   * @param  Params: pointer on additional configuration parameters, can be NULL.
00671   * @retval None
00672   */
00673 __weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params)
00674 {
00675     GPIO_InitTypeDef  gpio_init_structure;
00676 
00677     /* SAI DMA IRQ Channel deactivation */
00678     HAL_NVIC_DisableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ);
00679 
00680     if(hsai->Instance == AUDIO_OUT_SAIx)
00681     {
00682       /* Deinitialize the DMA stream */
00683       HAL_DMA_DeInit(hsai->hdmatx);
00684     }
00685 
00686     /* Disable SAI peripheral */
00687     __HAL_SAI_DISABLE(hsai);
00688 
00689     /* Deactivates CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */
00690     gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SD_PIN;
00691     HAL_GPIO_DeInit(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, gpio_init_structure.Pin);
00692 
00693     gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN;
00694     HAL_GPIO_DeInit(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin);
00695 
00696     /* Disable SAI clock */
00697     AUDIO_OUT_SAIx_CLK_DISABLE();
00698 
00699     /* GPIO pins clock and DMA clock can be shut down in the applic
00700        by surcharging this __weak function */
00701 }
00702 
00703 /**
00704   * @brief  Clock Config.
00705   * @param  hsai: might be required to set audio peripheral predivider if any.
00706   * @param  AudioFreq: Audio frequency used to play the audio stream.
00707   * @param  Params: pointer on additional configuration parameters, can be NULL.
00708   * @note   This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency()
00709   *         Being __weak it can be overwritten by the application
00710   * @retval None
00711   */
00712 __weak void BSP_AUDIO_OUT_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params)
00713 {
00714   RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct;
00715 
00716   HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct);
00717 
00718   /* Set the PLL configuration according to the audio frequency */
00719   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
00720   {
00721     /* SAI clock config:
00722        PLL2_VCO Input = HSE_VALUE/PLL2M = 1 Mhz
00723        PLL2_VCO Output = PLL2_VCO Input * PLL2N = 429 Mhz
00724        SAI_CLK_x = PLL2_VCO Output/PLL2P = 429/38 = 11.289 Mhz */
00725     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
00726     rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2;
00727     rcc_ex_clk_init_struct.PLL2.PLL2P = 38;
00728     rcc_ex_clk_init_struct.PLL2.PLL2Q = 1;
00729     rcc_ex_clk_init_struct.PLL2.PLL2R = 1;
00730     rcc_ex_clk_init_struct.PLL2.PLL2N = 429;
00731     rcc_ex_clk_init_struct.PLL2.PLL2M = 25;
00732     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
00733   }
00734   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
00735   {
00736     /* SAI clock config:
00737        PLL2_VCO Input = HSE_VALUE/PLL2M = 1 Mhz
00738        PLL2_VCO Output = PLL2_VCO Input * PLL2N = 344 Mhz
00739        SAI_CLK_x = PLL2_VCO Output/PLL2P = 344/7 = 49.142 Mhz */
00740     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
00741     rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2;
00742     rcc_ex_clk_init_struct.PLL2.PLL2P = 7;
00743     rcc_ex_clk_init_struct.PLL2.PLL2Q = 1;
00744     rcc_ex_clk_init_struct.PLL2.PLL2R = 1;
00745     rcc_ex_clk_init_struct.PLL2.PLL2N = 344;
00746     rcc_ex_clk_init_struct.PLL2.PLL2M = 25;
00747     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
00748   }
00749 }
00750 /**
00751   * @}
00752   */
00753 
00754 /** @addtogroup STM32H743I_EVAL_AUDIO_Out_Private_Functions
00755   * @{
00756   */
00757 
00758 /*******************************************************************************
00759                             HAL Callbacks
00760 *******************************************************************************/
00761 /**
00762   * @brief  Tx Transfer completed callbacks.
00763   * @param  hsai: SAI handle
00764   * @retval None
00765   */
00766 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
00767 {
00768   /* Manage the remaining file size and new address offset: This function
00769      should be coded by user (its prototype is already declared in stm32h743i_eval_audio.h) */
00770   BSP_AUDIO_OUT_TransferComplete_CallBack();
00771 }
00772 
00773 /**
00774   * @brief  Tx Half Transfer completed callbacks.
00775   * @param  hsai: SAI handle
00776   * @retval None
00777   */
00778 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
00779 {
00780   /* Manage the remaining file size and new address offset: This function
00781      should be coded by user (its prototype is already declared in stm32h743i_eval_audio.h) */
00782   BSP_AUDIO_OUT_HalfTransfer_CallBack();
00783 }
00784 
00785 /**
00786   * @brief  SAI error callbacks.
00787   * @param  hsai: SAI handle
00788   * @retval None
00789   */
00790 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
00791 {
00792   if(hsai->Instance == AUDIO_OUT_SAIx)
00793   {
00794     BSP_AUDIO_OUT_Error_CallBack();
00795   }
00796   else
00797   {
00798     BSP_AUDIO_IN_Error_CallBack();
00799   }
00800 }
00801 
00802 /*******************************************************************************
00803                             Static Functions
00804 *******************************************************************************/
00805 
00806 /**
00807   * @brief  Initializes the Audio Codec audio interface (SAI).
00808   * @param  SaiOutMode: Audio mode to be configured for the SAI peripheral.
00809   * @param  SlotActive: Audio active slot to be configured for the SAI peripheral.
00810   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00811   * @note   The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123
00812   *         and user can update this configuration using
00813   * @retval None
00814   */
00815 static void SAIx_Out_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq)
00816 {
00817   /* Disable SAI peripheral to allow access to SAI internal registers */
00818   __HAL_SAI_DISABLE(&haudio_out_sai);
00819 
00820   /* Configure SAI_Block_x
00821   LSBFirst: Disabled
00822   DataSize: 16 */
00823   haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE;
00824   haudio_out_sai.Init.AudioFrequency = AudioFreq;
00825   haudio_out_sai.Init.AudioMode = SaiOutMode;
00826   haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
00827   haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL;
00828   haudio_out_sai.Init.DataSize = SAI_DATASIZE_16;
00829   haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
00830   haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
00831   haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS;
00832   haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
00833   haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
00834   haudio_out_sai.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
00835   haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING;
00836   haudio_out_sai.Init.TriState       = SAI_OUTPUT_NOTRELEASED;
00837   haudio_out_sai.Init.Mckdiv         = 0;
00838   haudio_out_sai.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE;
00839   haudio_out_sai.Init.PdmInit.Activation = DISABLE;
00840   haudio_out_sai.Init.PdmInit.ClockEnable = 0;
00841   haudio_out_sai.Init.PdmInit.MicPairsNbr = 0;
00842 
00843   /* Configure SAI_Block_x Frame
00844   Frame Length: 64
00845   Frame active Length: 32
00846   FS Definition: Start frame + Channel Side identification
00847   FS Polarity: FS active Low
00848   FS Offset: FS asserted one bit before the first bit of slot 0 */
00849   haudio_out_sai.FrameInit.FrameLength = 128;
00850   haudio_out_sai.FrameInit.ActiveFrameLength = 64;
00851   haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
00852   haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
00853   haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
00854 
00855   /* Configure SAI Block_x Slot
00856   Slot First Bit Offset: 0
00857   Slot Size  : 16
00858   Slot Number: 4
00859   Slot Active: All slot actives */
00860   haudio_out_sai.SlotInit.FirstBitOffset = 0;
00861   haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
00862   haudio_out_sai.SlotInit.SlotNumber = 4;
00863   haudio_out_sai.SlotInit.SlotActive = SlotActive;
00864   HAL_SAI_Init(&haudio_out_sai);
00865 
00866   /* Enable SAI peripheral to generate MCLK */
00867   __HAL_SAI_ENABLE(&haudio_out_sai);
00868 }
00869 
00870 /**
00871   * @brief  Deinitializes the Audio Codec audio interface (SAI).
00872   * @retval None
00873   */
00874 static void SAIx_Out_DeInit(SAI_HandleTypeDef *hsai)
00875 {
00876   /* Disable SAI peripheral */
00877   __HAL_SAI_DISABLE(hsai);
00878 
00879   HAL_SAI_DeInit(hsai);
00880 }
00881 
00882 /**
00883   * @}
00884   */
00885 
00886 /** @addtogroup STM32H743I_EVAL_AUDIO_IN_Exported_Functions
00887   * @{
00888   */
00889 
00890 /**
00891   * @brief  Initialize wave recording.
00892   * @param  AudioFreq: Audio frequency to be configured for the DFSDM peripheral.
00893   * @param  BitRes: Audio frequency to be configured for the DFSDM peripheral.
00894   * @param  ChnlNbr: Audio frequency to be configured for the DFSDM peripheral.
00895   * @retval AUDIO_OK if correct communication, else wrong communication
00896   */
00897 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00898 {
00899   /* Set audio in interface to default one */
00900   BSP_AUDIO_IN_SelectInterface(AUDIO_IN_INTERFACE_DFSDM);
00901   return  BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC, AudioFreq, BitRes, ChnlNbr);
00902 }
00903 
00904 /**
00905   * @brief  Initialize wave recording.
00906   * @param  InputDevice: INPUT_DEVICE_DIGITAL_MIC or INPUT_DEVICE_ANALOG_MIC.
00907   * @param  AudioFreq: Audio frequency to be configured.
00908   * @param  BitRes: Audio bit resolution to be configured..
00909   * @param  ChnlNbr: Number of channel to be configured.
00910   * @retval AUDIO_OK if correct communication, else wrong communication
00911   */
00912 uint8_t BSP_AUDIO_IN_InitEx(uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00913 {
00914   uint8_t ret = AUDIO_OK;
00915   uint32_t mic_enabled = 0;
00916   uint32_t slot_active;
00917   uint32_t i = 0;
00918 
00919   /* Store the audio record context */
00920   hAudioIn.Frequency     = AudioFreq;
00921   hAudioIn.BitResolution = BitRes;
00922   hAudioIn.InputDevice = InputDevice;
00923   hAudioIn.ChannelNbr = ChnlNbr;
00924 
00925   /* Store the total number of microphones enabled */
00926   for(i = 0; i < DFSDM_MIC_NUMBER; i ++)
00927   {
00928     if(((hAudioIn.InputDevice >> i) & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
00929     {
00930       mic_enabled++;
00931     }
00932   }
00933 
00934   if(hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC)
00935   {
00936     if(hAudioIn.Interface == AUDIO_IN_INTERFACE_DFSDM)
00937     {
00938       if(hAudioIn.ChannelNbr != mic_enabled)
00939       {
00940         return AUDIO_ERROR;
00941       }
00942       else
00943       {
00944         /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
00945         BSP_AUDIO_IN_ClockConfig(AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT for analog mic */
00946 
00947         /* Init the DFSDM MSP: this __weak function can be redefined by the application*/
00948         BSP_AUDIO_IN_MspInit();
00949 
00950         /* Default configuration of DFSDM filters and channels */
00951         ret = BSP_AUDIO_IN_ConfigDigitalMic(hAudioIn.InputDevice, NULL);
00952       }
00953     }
00954     else if(hAudioIn.Interface == AUDIO_IN_INTERFACE_SAI)
00955     {
00956       /* Initialize SAI1 block B as SLAVE RX synchrounous with SAI1 block A */
00957       haudio_in_sai.Instance = AUDIO_IN_SAIx;
00958 
00959       /* Disable SAI */
00960       SAIx_In_DeInit(&haudio_in_sai);
00961 
00962       /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
00963       BSP_AUDIO_IN_ClockConfig(AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */
00964 
00965       /* SAI data transfer preparation:
00966       Prepare the Media to be used for the audio transfer from SAI peripheral to memory */
00967       if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET)
00968       {
00969         /* Init the SAI MSP: this __weak function can be redefined by the application*/
00970         BSP_AUDIO_IN_MspInit();
00971       }
00972 
00973       /* Configure SAI in master mode :
00974        *   - SAI1_block_B in slave RX mode synchronous from SAI1_block_A
00975        */
00976       slot_active = CODEC_AUDIOFRAME_SLOT_13;
00977       SAIx_In_Init(SAI_MODESLAVE_RX, slot_active, AudioFreq);
00978     }
00979     else if(hAudioIn.Interface == AUDIO_IN_INTERFACE_PDM)
00980     {
00981       /* Initialize SAI1 block A as MASTER RX */
00982       haudio_in_sai.Instance = AUDIO_IN_SAI_PDMx;
00983 
00984       /* Disable SAI */
00985       SAIx_In_DeInit(&haudio_in_sai);
00986 
00987       /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
00988       BSP_AUDIO_IN_ClockConfig(AudioFreq, NULL);
00989 
00990       /* SAI data transfer preparation:
00991       Prepare the Media to be used for the audio transfer from SAI peripheral to memory */
00992       /* Initialize the haudio_in_sai Instance parameter */
00993 
00994       if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET)
00995       {
00996         /* Init the SAI MSP: this __weak function can be redefined by the application*/
00997         BSP_AUDIO_IN_MspInit();
00998       }
00999 
01000       /* Configure SAI in master mode :
01001        *   - SAI1_block_A in master RX mode
01002        */
01003       slot_active = CODEC_AUDIOFRAME_SLOT_0;
01004       SAIx_In_Init(SAI_MODEMASTER_RX, slot_active, AudioFreq);
01005 
01006       if(BSP_AUDIO_IN_PDMToPCM_Init(AudioFreq, hAudioIn.ChannelNbr, hAudioIn.ChannelNbr) != AUDIO_OK)
01007       {
01008         ret = AUDIO_ERROR;
01009       }
01010     }
01011     else
01012     {
01013       ret = AUDIO_ERROR;
01014     }
01015   }
01016   else
01017   {
01018     /* Analog Input */
01019     ret = AUDIO_ERROR;
01020   }
01021 
01022   /* Return AUDIO_OK when all operations are correctly done */
01023   return ret;
01024 }
01025 
01026 /**
01027   * @brief  Initializes default configuration of the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01028   * @param  InputDevice: The microphone to be configured. Can be INPUT_DEVICE_DIGITAL_MIC1..INPUT_DEVICE_DIGITAL_MIC5
01029   * @note   Channel output Clock Divider and Filter Oversampling are calculated as follow:
01030   *         - Clock_Divider = CLK(input DFSDM)/CLK(micro) with
01031   *           1MHZ < CLK(micro) < 3.2MHZ (TYP 2.4MHZ for MP34DT01TR)
01032   *         - Oversampling = CLK(input DFSDM)/(Clock_Divider * AudioFreq)
01033   * @retval AUDIO_OK if correct communication, else wrong communication
01034   */
01035 uint8_t BSP_AUDIO_IN_ConfigMicDefault(uint32_t InputDevice)
01036 {
01037   uint32_t i = 0, mic_init[DFSDM_MIC_NUMBER] = {0};
01038   uint32_t filter_ch = 0, mic_num = 0;
01039 
01040   DFSDM_Filter_TypeDef* FilterInstnace[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_MIC1_FILTER, AUDIO_DFSDMx_MIC2_FILTER};
01041   DFSDM_Channel_TypeDef* ChannelInstnace[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_MIC1_CHANNEL, AUDIO_DFSDMx_MIC2_CHANNEL};
01042   uint32_t DigitalMicPins[DFSDM_MIC_NUMBER] = {DFSDM_CHANNEL_SAME_CHANNEL_PINS, DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS};
01043   uint32_t DigitalMicType[DFSDM_MIC_NUMBER] = {DFSDM_CHANNEL_SPI_RISING, DFSDM_CHANNEL_SPI_FALLING};
01044   uint32_t Channel4Filter[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_MIC1_CHANNEL_FOR_FILTER, AUDIO_DFSDMx_MIC2_CHANNEL_FOR_FILTER};
01045 
01046   for(i = 0; i < hAudioIn.ChannelNbr; i++)
01047   {
01048     if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] != 1))
01049     {
01050       mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC1);
01051     }
01052     else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] != 1))
01053     {
01054       mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC2);
01055     }
01056 
01057     mic_init[mic_num] = 1;
01058 
01059     HAL_DFSDM_ChannelDeInit(&hAudioInDfsdmChannel[mic_num]);
01060     /* MIC channels initialization */
01061     __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInDfsdmChannel[mic_num]);
01062     hAudioInDfsdmChannel[mic_num].Init.OutputClock.Activation   = ENABLE;
01063     hAudioInDfsdmChannel[mic_num].Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
01064     hAudioInDfsdmChannel[mic_num].Init.OutputClock.Divider      = DFSDM_CLOCK_DIVIDER(hAudioIn.Frequency);
01065     hAudioInDfsdmChannel[mic_num].Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
01066     hAudioInDfsdmChannel[mic_num].Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
01067     hAudioInDfsdmChannel[mic_num].Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
01068     hAudioInDfsdmChannel[mic_num].Init.Awd.FilterOrder          = DFSDM_CHANNEL_FASTSINC_ORDER;
01069     hAudioInDfsdmChannel[mic_num].Init.Awd.Oversampling         = 10;
01070     hAudioInDfsdmChannel[mic_num].Init.Offset                   = 0;
01071     hAudioInDfsdmChannel[mic_num].Init.RightBitShift            = DFSDM_MIC_BIT_SHIFT(hAudioIn.Frequency);
01072     hAudioInDfsdmChannel[mic_num].Instance                      = ChannelInstnace[mic_num];
01073     hAudioInDfsdmChannel[mic_num].Init.Input.Pins               = DigitalMicPins[mic_num];
01074     hAudioInDfsdmChannel[mic_num].Init.SerialInterface.Type     = DigitalMicType[mic_num];
01075 
01076     if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInDfsdmChannel[mic_num]))
01077     {
01078       return AUDIO_ERROR;
01079     }
01080 
01081     HAL_DFSDM_FilterDeInit(&hAudioInDfsdmFilter[mic_num]);
01082     /* MIC filters  initialization */
01083     __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInDfsdmFilter[mic_num]);
01084     hAudioInDfsdmFilter[mic_num].Instance                          = FilterInstnace[mic_num];
01085     hAudioInDfsdmFilter[mic_num].Init.RegularParam.Trigger         = DFSDM_FILTER_SW_TRIGGER;
01086     hAudioInDfsdmFilter[mic_num].Init.RegularParam.FastMode        = ENABLE;
01087     hAudioInDfsdmFilter[mic_num].Init.RegularParam.DmaMode         = ENABLE;
01088     hAudioInDfsdmFilter[mic_num].Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
01089     hAudioInDfsdmFilter[mic_num].Init.InjectedParam.ScanMode       = ENABLE;
01090     hAudioInDfsdmFilter[mic_num].Init.InjectedParam.DmaMode        = DISABLE;
01091     hAudioInDfsdmFilter[mic_num].Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
01092     hAudioInDfsdmFilter[mic_num].Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
01093     hAudioInDfsdmFilter[mic_num].Init.FilterParam.SincOrder        = DFSDM_FILTER_ORDER(hAudioIn.Frequency);
01094     hAudioInDfsdmFilter[mic_num].Init.FilterParam.Oversampling     = DFSDM_OVER_SAMPLING(hAudioIn.Frequency);
01095     hAudioInDfsdmFilter[mic_num].Init.FilterParam.IntOversampling  = 1;
01096 
01097     if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInDfsdmFilter[mic_num]))
01098     {
01099       return AUDIO_ERROR;
01100     }
01101 
01102     filter_ch = Channel4Filter[mic_num];
01103     /* Configure injected channel */
01104     if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInDfsdmFilter[mic_num], filter_ch, DFSDM_CONTINUOUS_CONV_ON))
01105     {
01106       return AUDIO_ERROR;
01107     }
01108   }
01109 
01110   return AUDIO_OK;
01111 }
01112 
01113 /**
01114   * @brief  Initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01115   * @param  InputDevice: The microphone to be configured. Can be INPUT_DEVICE_DIGITAL_MIC1..INPUT_DEVICE_DIGITAL_MIC5
01116   * @param  Params: pointer on additional configuration parameters, can be NULL.
01117   * @retval AUDIO_OK if correct communication, else wrong communication
01118   */
01119 __weak uint8_t BSP_AUDIO_IN_ConfigDigitalMic(uint32_t InputDevice, void *Params)
01120 {
01121   /* Prevent unused argument(s) compilation warning */
01122   UNUSED(Params);
01123 
01124   /* Default configuration of DFSDM filters and channels */
01125   return(BSP_AUDIO_IN_ConfigMicDefault(InputDevice));
01126   /* Note: This function can be called at application level and default configuration
01127            can be ovewritten to fit user's need */
01128 }
01129 
01130 /**
01131   * @brief  Initializes wave recording and playback in parallel.
01132   * @param  InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_2
01133   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
01134   *                       or OUTPUT_DEVICE_BOTH.
01135   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
01136   * @param  BitRes: Audio frequency to be configured.
01137   * @param  ChnlNbr: Channel number.
01138   * @retval AUDIO_OK if correct communication, else wrong communication
01139   */
01140 uint8_t BSP_AUDIO_IN_OUT_Init(uint32_t InputDevice, uint32_t OutputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
01141 {
01142   uint32_t slot_active;
01143   uint32_t deviceid = 0, ret = AUDIO_OK;
01144 
01145   /* Store the audio record context */
01146   hAudioIn.Frequency     = AudioFreq;
01147   hAudioIn.BitResolution = BitRes;
01148   hAudioIn.InputDevice = InputDevice;
01149   hAudioIn.ChannelNbr = ChnlNbr;
01150 
01151   /* Input device is Digital MIC2 and Codec interface is SAI */
01152   if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2)
01153   {
01154     haudio_in_sai.Instance = AUDIO_IN_SAIx;
01155     haudio_out_sai.Instance = AUDIO_OUT_SAIx;
01156 
01157     /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
01158     BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL);
01159     /* SAI data transfer preparation:
01160     Prepare the Media to be used for the audio transfer from SAI peripheral to memory */
01161     if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET)
01162     {
01163       /* Init the SAI MSP: this __weak function can be redefined by the application*/
01164       BSP_AUDIO_IN_MspInit();
01165     }
01166 
01167     /* SAI data transfer preparation:
01168     Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
01169     if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET)
01170     {
01171       /* Init the SAI MSP: this __weak function can be redefined by the application*/
01172       BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL);
01173     }
01174 
01175     /* Configure SAI in master TX mode :
01176     *   - SAI1_block_A in master TX mode
01177     *   - SAI1_block_B in slave RX mode synchronous from SAI1_block_A
01178     */
01179     slot_active = CODEC_AUDIOFRAME_SLOT_13;
01180     SAIx_In_Init(SAI_MODESLAVE_RX, slot_active, AudioFreq);
01181 
01182     slot_active = CODEC_AUDIOFRAME_SLOT_02;
01183     SAIx_Out_Init(SAI_MODEMASTER_TX, slot_active, AudioFreq);
01184 
01185     /* wm8994 codec initialization */
01186     deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
01187 
01188     if((deviceid) == WM8994_ID)
01189     {
01190       /* Reset the Codec Registers */
01191       wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
01192       /* Initialize the audio driver structure */
01193       audio_drv = &wm8994_drv;
01194       ret = AUDIO_OK;
01195     }
01196     else
01197     {
01198       ret = AUDIO_ERROR;
01199     }
01200 
01201     if(ret == AUDIO_OK)
01202     {
01203       /* Initialize the codec internal registers */
01204       audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice|OutputDevice, 90, AudioFreq);
01205     }
01206   }
01207   else
01208   {
01209     ret = AUDIO_ERROR;
01210   }
01211 
01212   /* Return AUDIO_OK when all operations are correctly done */
01213   return ret;
01214 }
01215 
01216 /**
01217   * @brief  Link digital mic to specified source
01218   * @param  Interface : Audio In interface for Digital mic. It can be:
01219   *                       AUDIO_IN_INTERFACE_SAI
01220   *                       AUDIO_IN_INTERFACE_PDM
01221   *                       AUDIO_IN_INTERFACE_DFSDM
01222   * @retval None
01223   */
01224 void BSP_AUDIO_IN_SelectInterface(uint32_t Interface)
01225 {
01226   hAudioIn.Interface = Interface;
01227 }
01228 
01229 /**
01230   * @brief  Get digital mic interface
01231   * @retval Digital mic interface.
01232   */
01233 uint32_t BSP_AUDIO_IN_GetInterface(void)
01234 {
01235   return (hAudioIn.Interface);
01236 }
01237 
01238 /**
01239   * @brief  Allocate channel buffer scratch
01240   * @param  pScratch : pointer to scratch tables.
01241   * @param  size of scratch buffer
01242   */
01243 uint8_t BSP_AUDIO_IN_AllocScratch (int32_t *pScratch, uint32_t size)
01244 {
01245   uint32_t idx;
01246 
01247   ScratchSize = (size / hAudioIn.ChannelNbr);
01248 
01249   /* copy scratch pointers */
01250   for (idx = 0; idx < hAudioIn.ChannelNbr; idx++)
01251   {
01252     pScratchBuff[idx] = (int32_t *)(pScratch + idx * ScratchSize);
01253   }
01254   /* Return AUDIO_OK */
01255   return AUDIO_OK;
01256 }
01257 
01258 /**
01259   * @brief  Return audio in channel number
01260   * @retval Number of channel
01261   */
01262 uint8_t BSP_AUDIO_IN_GetChannelNumber(void)
01263 {
01264   return hAudioIn.ChannelNbr;
01265 }
01266 
01267 /**
01268   * @brief  Start audio recording.
01269   * @param  pBuf: Main buffer pointer for the recorded data storing
01270   * @param  size: Current size of the recorded buffer
01271   * @retval AUDIO_OK if correct communication, else wrong communication
01272   */
01273 uint8_t BSP_AUDIO_IN_Record(uint16_t *pBuf, uint32_t size)
01274 {
01275   if (hAudioIn.Interface == AUDIO_IN_INTERFACE_DFSDM)
01276   {
01277     hAudioIn.pRecBuf = pBuf;
01278     hAudioIn.RecSize = size;
01279     /* Reset Application Buffer Trigger */
01280     AppBuffTrigger = 0;
01281     AppBuffHalf = 0;
01282 
01283     /* Call the Media layer start function for MIC1 channel */
01284     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], ScratchSize))
01285     {
01286       return AUDIO_ERROR;
01287     }
01288 
01289     /* Call the Media layer start function for MIC2 channel */
01290     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], ScratchSize))
01291     {
01292       return AUDIO_ERROR;
01293     }
01294   }
01295   else
01296   {
01297     /* Start the process receive DMA */
01298     if(HAL_OK != HAL_SAI_Receive_DMA(&haudio_in_sai, (uint8_t*)pBuf, size))
01299     {
01300       return AUDIO_ERROR;
01301     }
01302   }
01303   /* Return AUDIO_OK when all operations are correctly done */
01304   return AUDIO_OK;
01305 }
01306 
01307 /**
01308   * @brief  Stop audio recording.
01309   * @retval AUDIO_OK if correct communication, else wrong communication
01310   */
01311 uint8_t BSP_AUDIO_IN_Stop(void)
01312 {
01313   if (hAudioIn.Interface == AUDIO_IN_INTERFACE_DFSDM)
01314   {
01315     AppBuffTrigger = 0;
01316     AppBuffHalf    = 0;
01317 
01318     /* Call the Media layer stop function for MIC1 channel */
01319     if(AUDIO_OK != BSP_AUDIO_IN_PauseEx(INPUT_DEVICE_DIGITAL_MIC1))
01320     {
01321       return AUDIO_ERROR;
01322     }
01323 
01324     /* Call the Media layer stop function for MIC2 channel */
01325     if(AUDIO_OK != BSP_AUDIO_IN_PauseEx(INPUT_DEVICE_DIGITAL_MIC2))
01326     {
01327       return AUDIO_ERROR;
01328     }
01329   }
01330   else
01331   {
01332     /* Call the Media layer stop function */
01333     HAL_SAI_DMAStop(&haudio_in_sai);
01334   }
01335   /* Return AUDIO_OK when all operations are correctly done */
01336   return AUDIO_OK;
01337 }
01338 
01339 /**
01340   * @brief  Stops audio recording.
01341   * @param  InputDevice: Microphone to be stopped. Can be INPUT_DEVICE_DIGITAL_MIC1 or INPUT_DEVICE_DIGITAL_MIC2.
01342   * @retval AUDIO_OK if correct communication, else wrong communication
01343   */
01344 uint8_t BSP_AUDIO_IN_StopEx(uint32_t InputDevice)
01345 {
01346   if((InputDevice < INPUT_DEVICE_DIGITAL_MIC1) || (InputDevice > INPUT_DEVICE_DIGITAL_MIC2))
01347   {
01348     return AUDIO_ERROR;
01349   }
01350   else
01351   {
01352     BSP_AUDIO_IN_PauseEx(InputDevice);
01353   }
01354 
01355   /* Return AUDIO_OK when all operations are correctly done */
01356   return AUDIO_OK;
01357 }
01358 
01359 /**
01360   * @brief  Pause the audio file stream.
01361   * @retval AUDIO_OK if correct communication, else wrong communication
01362   */
01363 uint8_t BSP_AUDIO_IN_Pause(void)
01364 {
01365   if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC)
01366   {
01367     return AUDIO_ERROR;
01368   }
01369   else
01370   {
01371     /* Call the Media layer stop function */
01372     if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)]))
01373     {
01374       return AUDIO_ERROR;
01375     }
01376 
01377     /* Call the Media layer stop function */
01378     if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)]))
01379     {
01380       return AUDIO_ERROR;
01381     }
01382   }
01383   /* Return AUDIO_OK when all operations are correctly done */
01384   return AUDIO_OK;
01385 }
01386 
01387 /**
01388   * @brief  Pauses the audio file stream.
01389   * @param  InputDevice: Microphone to be paused. Can be INPUT_DEVICE_DIGITAL_MIC1 or INPUT_DEVICE_DIGITAL_MIC2.
01390   * @retval AUDIO_OK if correct communication, else wrong communication
01391   */
01392 uint8_t BSP_AUDIO_IN_PauseEx(uint32_t InputDevice)
01393 {
01394   if((InputDevice < INPUT_DEVICE_DIGITAL_MIC1) || (InputDevice > INPUT_DEVICE_DIGITAL_MIC2))
01395   {
01396     return AUDIO_ERROR;
01397   }
01398   else
01399   {
01400     /* Call the Media layer stop function */
01401     if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInDfsdmFilter[POS_VAL(InputDevice)]))
01402     {
01403       return AUDIO_ERROR;
01404     }
01405   }
01406   /* Return AUDIO_OK when all operations are correctly done */
01407   return AUDIO_OK;
01408 }
01409 
01410 /**
01411   * @brief  Resume the audio file stream.
01412   * @retval AUDIO_OK if correct communication, else wrong communication
01413   */
01414 uint8_t BSP_AUDIO_IN_Resume(void)
01415 {
01416   if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC)
01417   {
01418     return AUDIO_ERROR;
01419   }
01420   else
01421   {
01422     /* Call the Media layer start function for MIC2 channel */
01423     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], ScratchSize))
01424     {
01425       return AUDIO_ERROR;
01426     }
01427 
01428     /* Call the Media layer start function for MIC1 channel */
01429     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], ScratchSize))
01430     {
01431       return AUDIO_ERROR;
01432     }
01433   }
01434   /* Return AUDIO_OK when all operations are correctly done */
01435   return AUDIO_OK;
01436 }
01437 
01438 /**
01439   * @brief  Resumes the audio file stream.
01440   * @param  pBuf: Main buffer pointer for the recorded data storing
01441   * @param  InputDevice: Microphone to be paused. Can be INPUT_DEVICE_DIGITAL_MIC1 or INPUT_DEVICE_DIGITAL_MIC2.
01442   * @retval AUDIO_OK if correct communication, else wrong communication
01443   */
01444 uint8_t BSP_AUDIO_IN_ResumeEx(uint32_t *pBuf, uint32_t InputDevice)
01445 {
01446   if((InputDevice < INPUT_DEVICE_DIGITAL_MIC1) || (InputDevice > INPUT_DEVICE_DIGITAL_MIC2))
01447   {
01448     return AUDIO_ERROR;
01449   }
01450   else
01451   {
01452     /* Call the Media layer stop function */
01453     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(InputDevice)], (int32_t*)pBuf[MicBuff[POS_VAL(InputDevice)]], hAudioIn.RecSize))
01454     {
01455       return AUDIO_ERROR;
01456     }
01457   }
01458   /* Return AUDIO_OK when all operations are correctly done */
01459   return AUDIO_OK;
01460 }
01461 
01462 /**
01463   * @brief  Controls the audio in volume level.
01464   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for
01465   *         Mute and 100 for Max volume level).
01466   * @retval AUDIO_OK if correct communication, else wrong communication
01467   */
01468 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume)
01469 {
01470   /* Set the Global variable AudioInVolume  */
01471   AudioInVolume = Volume;
01472 
01473   /* Return AUDIO_OK when all operations are correctly done */
01474   return AUDIO_OK;
01475 }
01476 
01477 /**
01478   * @brief  Deinit the audio IN peripherals.
01479   * @retval None
01480   */
01481 void BSP_AUDIO_IN_DeInit(void)
01482 {
01483   if(hAudioIn.Interface == AUDIO_IN_INTERFACE_DFSDM)
01484   {
01485     DFSDMx_DeInit();
01486   }
01487   else
01488   {
01489     SAIx_In_DeInit(&haudio_in_sai);
01490   }
01491   BSP_AUDIO_IN_MspDeInit();
01492 }
01493 
01494 /**
01495 * @brief  Initialize the PDM library.
01496 * @param  AudioFreq: Audio sampling frequency
01497 * @param  ChnlNbrIn: Number of input audio channels in the PDM buffer
01498 * @param  ChnlNbrOut: Number of desired output audio channels in the  resulting PCM buffer
01499 * @retval None
01500 */
01501 uint8_t BSP_AUDIO_IN_PDMToPCM_Init(uint32_t AudioFreq, uint32_t ChnlNbrIn, uint32_t ChnlNbrOut)
01502 {
01503   uint32_t index = 0;
01504 
01505   /* Enable CRC peripheral to unlock the PDM library */
01506   __HAL_RCC_CRC_CLK_ENABLE();
01507 
01508   for(index = 0; index < ChnlNbrIn; index++)
01509   {
01510     /* Init PDM filters */
01511     PDM_FilterHandler[index].bit_order  = PDM_FILTER_BIT_ORDER_MSB;
01512     PDM_FilterHandler[index].endianness = PDM_FILTER_ENDIANNESS_LE;
01513     PDM_FilterHandler[index].high_pass_tap = 2122358088;
01514     PDM_FilterHandler[index].out_ptr_channels = ChnlNbrOut;
01515     PDM_FilterHandler[index].in_ptr_channels  = ChnlNbrIn;
01516     PDM_Filter_Init((PDM_Filter_Handler_t *)(&PDM_FilterHandler[index]));
01517 
01518     /* PDM lib config phase */
01519     PDM_FilterConfig[index].output_samples_number = AudioFreq/1000;
01520     PDM_FilterConfig[index].mic_gain = 0;
01521     PDM_FilterConfig[index].decimation_factor = PDM_FILTER_DEC_FACTOR_64;
01522     PDM_Filter_setConfig((PDM_Filter_Handler_t *)&PDM_FilterHandler[index], &PDM_FilterConfig[index]);
01523   }
01524 
01525   return AUDIO_OK;
01526 }
01527 
01528 
01529 /**
01530 * @brief  Converts audio format from PDM to PCM.
01531 
01532 * @param  PDMBuf: Pointer to PDM buffer data
01533 * @param  PCMBuf: Pointer to PCM buffer data
01534 * @retval AUDIO_OK in case of success, AUDIO_ERROR otherwise
01535 */
01536 uint8_t BSP_AUDIO_IN_PDMToPCM(uint16_t *PDMBuf, uint16_t *PCMBuf)
01537 {
01538   uint32_t index = 0;
01539 
01540   for(index = 0; index < hAudioIn.ChannelNbr; index++)
01541   {
01542     PDM_Filter(&((uint8_t*)(PDMBuf))[index], (uint16_t*)&(PCMBuf[index]), &PDM_FilterHandler[index]);
01543   }
01544 
01545   return AUDIO_OK;
01546 }
01547 
01548 /**
01549   * @brief  User callback when record buffer is filled.
01550   * @retval None
01551   */
01552 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void)
01553 {
01554   /* This function should be implemented by the user application.
01555      It is called into this driver when the current buffer is filled
01556      to prepare the next buffer pointer and its size. */
01557 }
01558 
01559 /**
01560   * @brief  Manages the DMA Half Transfer complete event.
01561   * @retval None
01562   */
01563 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
01564 {
01565   /* This function should be implemented by the user application.
01566      It is called into this driver when the current buffer is filled
01567      to prepare the next buffer pointer and its size. */
01568 }
01569 
01570 /**
01571   * @brief  User callback when record buffer is filled.
01572   * @param  InputDevice: INPUT_DEVICE_DIGITAL_MIC1 or INPUT_DEVICE_DIGITAL_MIC2
01573   */
01574 __weak void BSP_AUDIO_IN_TransferComplete_CallBackEx(uint32_t InputDevice)
01575 {
01576   /* This function should be implemented by the user application.
01577      It is called into this driver when the current buffer is filled
01578      to prepare the next buffer pointer and its size. */
01579 }
01580 
01581 /**
01582   * @brief  User callback when record buffer is filled.
01583   * @param InputDevice: INPUT_DEVICE_DIGITAL_MIC1 or INPUT_DEVICE_DIGITAL_MIC2
01584   */
01585 __weak void BSP_AUDIO_IN_HalfTransfer_CallBackEx(uint32_t InputDevice)
01586 {
01587   /* This function should be implemented by the user application.
01588      It is called into this driver when the current buffer is filled
01589      to prepare the next buffer pointer and its size. */
01590 }
01591 
01592 /**
01593   * @brief  Audio IN Error callback function.
01594   * @retval None
01595   */
01596 __weak void BSP_AUDIO_IN_Error_CallBack(void)
01597 {
01598   /* This function is called when an Interrupt due to transfer error on or peripheral
01599      error occurs. */
01600 }
01601 
01602 /**
01603   * @brief  Initialize BSP_AUDIO_IN MSP.
01604   * @retval None
01605   */
01606 __weak void BSP_AUDIO_IN_MspInit(void)
01607 {
01608   if (hAudioIn.Interface == AUDIO_IN_INTERFACE_DFSDM)
01609   {
01610     /* MSP channels initialization */
01611     DFSDMx_ChannelMspInit();
01612 
01613     /* MSP filters initialization */
01614     DFSDMx_FilterMspInit();
01615   }
01616   else
01617   {
01618     SAIx_In_MspInit(&haudio_in_sai, NULL);
01619   }
01620 }
01621 
01622 /**
01623   * @brief  DeInitialize BSP_AUDIO_IN MSP.
01624   * @retval None
01625   */
01626 __weak void BSP_AUDIO_IN_MspDeInit(void)
01627 {
01628   if (hAudioIn.Interface == AUDIO_IN_INTERFACE_DFSDM)
01629   {
01630     /* MSP channels initialization */
01631     DFSDMx_ChannelMspDeInit();
01632     /* MSP filters initialization */
01633     DFSDMx_FilterMspDeInit();
01634   }
01635   else
01636   {
01637     SAIx_In_MspDeInit(&haudio_in_sai, NULL);
01638   }
01639 }
01640 
01641 /**
01642   * @brief  Clock Config.
01643   * @param  AudioFreq: Audio frequency used to play the audio stream.
01644   * @param  Params: pointer on additional configuration parameters, can be NULL.
01645   * @note   This API is called by BSP_AUDIO_IN_Init()
01646   *         Being __weak it can be overwritten by the application
01647   * @retval None
01648   */
01649 __weak void BSP_AUDIO_IN_ClockConfig(uint32_t AudioFreq, void *Params)
01650 {
01651   RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct;
01652 
01653   HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct);
01654 
01655   /* Set the PLL configuration according to the audio frequency */
01656   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
01657   {
01658     /* SAI clock config:
01659        PLL2_VCO Input = HSE_VALUE/PLL2M = 1 Mhz
01660        PLL2_VCO Output = PLL2_VCO Input * PLL2N = 429 Mhz
01661        SAI_CLK_x = PLL2_VCO Output/PLL2P = 429/38 = 11.289 Mhz */
01662     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
01663     rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2;
01664     rcc_ex_clk_init_struct.PLL2.PLL2P = 38;
01665     rcc_ex_clk_init_struct.PLL2.PLL2Q = 1;
01666     rcc_ex_clk_init_struct.PLL2.PLL2R = 1;
01667     rcc_ex_clk_init_struct.PLL2.PLL2N = 429;
01668     rcc_ex_clk_init_struct.PLL2.PLL2M = 25;
01669     if (hAudioIn.Interface == AUDIO_IN_INTERFACE_PDM)
01670     {
01671       rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI4A;
01672       rcc_ex_clk_init_struct.Sai4AClockSelection = RCC_SAI4ACLKSOURCE_PLL2;
01673     }
01674     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
01675 
01676   }
01677   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_32K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
01678   {
01679     /* SAI clock config:
01680        PLL2_VCO Input = HSE_VALUE/PLL2M = 1 Mhz
01681        PLL2_VCO Output = PLL2_VCO Input * PLL2N = 344 Mhz
01682        SAI_CLK_x = PLL2_VCO Output/PLL2P = 344/7 = 49.142 Mhz */
01683     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
01684     rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2;
01685     rcc_ex_clk_init_struct.PLL2.PLL2P = 7;
01686     rcc_ex_clk_init_struct.PLL2.PLL2Q = 1;
01687     rcc_ex_clk_init_struct.PLL2.PLL2R = 1;
01688     rcc_ex_clk_init_struct.PLL2.PLL2N = 344;
01689     rcc_ex_clk_init_struct.PLL2.PLL2M = 25;
01690     if (hAudioIn.Interface == AUDIO_IN_INTERFACE_PDM)
01691     {
01692       rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI4A;
01693       rcc_ex_clk_init_struct.Sai4AClockSelection = RCC_SAI4ACLKSOURCE_PLL2;
01694     }
01695     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
01696   }
01697 }
01698 /**
01699   * @}
01700   */
01701 
01702 
01703 /** @addtogroup STM32H743I_EVAL_AUDIO_IN_Private_Functions
01704   * @{
01705   */
01706 
01707 /*******************************************************************************
01708                             HAL Callbacks
01709 *******************************************************************************/
01710 /**
01711   * @brief  Regular conversion complete callback.
01712   * @note   In interrupt mode, user has to read conversion value in this function
01713             using HAL_DFSDM_FilterGetRegularValue.
01714   * @param  hdfsdm_filter : DFSDM filter handle.
01715   * @retval None
01716   */
01717 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01718 {
01719   uint32_t index, input_device = 0;
01720 
01721   if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC1_FILTER)
01722   {
01723     DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 1;
01724     input_device = INPUT_DEVICE_DIGITAL_MIC1;
01725   }
01726   else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC2_FILTER)
01727   {
01728     DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = 1;
01729     input_device = INPUT_DEVICE_DIGITAL_MIC2;
01730   }
01731 
01732   if(hAudioIn.MultiBuffMode == 1)
01733   {
01734     BSP_AUDIO_IN_TransferComplete_CallBackEx(input_device);
01735   }
01736   else
01737   {
01738     if((DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] == 1) && (DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] == 1))
01739     {
01740       if(AppBuffTrigger >= hAudioIn.RecSize)
01741         AppBuffTrigger = 0;
01742 
01743       for(index = (ScratchSize/2) ; index < ScratchSize; index++)
01744       {
01745         hAudioIn.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)][index] >> 8), -32760, 32760));
01746         hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)][index] >> 8), -32760, 32760));
01747         AppBuffTrigger += 2;
01748       }
01749       DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 0;
01750     }
01751 
01752     /* Update Trigger with Remaining Byte before callback if necessary */
01753     if(AppBuffTrigger >= hAudioIn.RecSize)
01754     {
01755       /* Reset Application Buffer Trigger */
01756       AppBuffTrigger = 0;
01757       AppBuffHalf = 0;
01758 
01759       /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01760       BSP_AUDIO_IN_TransferComplete_CallBack();
01761     }
01762     else if((AppBuffTrigger >= hAudioIn.RecSize/2))
01763     {
01764       if(AppBuffHalf == 0)
01765       {
01766         AppBuffHalf = 1;
01767         /* Manage the remaining file size and new address offset: This function
01768         should be coded by user (its prototype is already declared in stm32xx_eval_audio.h) */
01769         BSP_AUDIO_IN_HalfTransfer_CallBack();
01770       }
01771     }
01772   }
01773 }
01774 
01775 /**
01776   * @brief  Half regular conversion complete callback.
01777   * @param  hdfsdm_filter : DFSDM filter handle.
01778   * @retval None
01779   */
01780 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01781 {
01782   uint32_t index, input_device = 0;
01783 
01784   if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC1_FILTER)
01785   {
01786     DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 1;
01787     input_device = INPUT_DEVICE_DIGITAL_MIC1;
01788   }
01789   else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC2_FILTER)
01790   {
01791     DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = 1;
01792     input_device = INPUT_DEVICE_DIGITAL_MIC2;
01793   }
01794 
01795   if(hAudioIn.MultiBuffMode == 1)
01796   {
01797     BSP_AUDIO_IN_HalfTransfer_CallBackEx(input_device);
01798   }
01799   else
01800   {
01801     if((DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] == 1) && (DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] == 1))
01802     {
01803       if(AppBuffTrigger >= hAudioIn.RecSize)
01804         AppBuffTrigger = 0;
01805 
01806       for(index = 0; index < ScratchSize/2; index++)
01807       {
01808         hAudioIn.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)][index] >> 8), -32760, 32760));
01809         hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)][index] >> 8), -32760, 32760));
01810         AppBuffTrigger += 2;
01811       }
01812       DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 0;
01813     }
01814 
01815 
01816     /* Update Trigger with Remaining Byte before callback if necessary */
01817     if(AppBuffTrigger >= hAudioIn.RecSize)
01818     {
01819       /* Reset Application Buffer Trigger */
01820       AppBuffTrigger = 0;
01821       AppBuffHalf = 0;
01822 
01823       /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01824       BSP_AUDIO_IN_TransferComplete_CallBack();
01825     }
01826     else if((AppBuffTrigger >= hAudioIn.RecSize/2))
01827     {
01828       if(AppBuffHalf == 0)
01829       {
01830         AppBuffHalf = 1;
01831         /* Manage the remaining file size and new address offset: This function
01832         should be coded by user (its prototype is already declared in stm32xx_eval_audio.h) */
01833         BSP_AUDIO_IN_HalfTransfer_CallBack();
01834       }
01835     }
01836   }
01837 }
01838 
01839 /**
01840   * @brief  Half reception complete callback.
01841   * @param  hsai: SAI handle.
01842   * @retval None
01843   */
01844 void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
01845 {
01846   /* Manage the remaining file size and new address offset: This function should be coded by user */
01847   BSP_AUDIO_IN_HalfTransfer_CallBack();
01848 }
01849 
01850 /**
01851   * @brief  Reception complete callback.
01852   * @param  hsai: SAI handle.
01853   * @retval None
01854   */
01855 void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
01856 {
01857   /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01858   BSP_AUDIO_IN_TransferComplete_CallBack();
01859 }
01860 
01861 /*******************************************************************************
01862                             Static Functions
01863 *******************************************************************************/
01864 /**
01865   * @brief  De-initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01866   * @retval AUDIO_OK if correct communication, else wrong communication
01867   */
01868 static uint8_t DFSDMx_DeInit(void)
01869 {
01870   for(uint32_t i = 0; i < DFSDM_MIC_NUMBER; i++)
01871   {
01872     if(hAudioInDfsdmFilter[i].Instance != NULL)
01873     {
01874       if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInDfsdmFilter[i]))
01875       {
01876         return AUDIO_ERROR;
01877       }
01878       hAudioInDfsdmFilter[i].Instance = NULL;
01879     }
01880     if(hAudioInDfsdmChannel[i].Instance != NULL)
01881     {
01882       if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInDfsdmChannel[i]))
01883       {
01884         return AUDIO_ERROR;
01885       }
01886       hAudioInDfsdmChannel[i].Instance = NULL;
01887     }
01888   }
01889   return AUDIO_OK;
01890 }
01891 
01892 /**
01893   * @brief  Initializes the DFSDM channel MSP.
01894   */
01895 static void DFSDMx_ChannelMspInit(void)
01896 {
01897   GPIO_InitTypeDef  GPIO_InitStruct;
01898 
01899   /* Enable DFSDM clock */
01900   AUDIO_DFSDMx_CLK_ENABLE();
01901 
01902   /* Enable GPIO clock */
01903   AUDIO_DFSDMx_CKOUT_DMIC_GPIO_CLK_ENABLE();
01904   /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN pins ------------------*/
01905   GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN;
01906   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
01907   GPIO_InitStruct.Pull = GPIO_NOPULL;
01908   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
01909   GPIO_InitStruct.Alternate = AUDIO_DFSDMx_CKOUT_DMIC_AF;
01910   HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT, &GPIO_InitStruct);
01911 
01912   /* MP34DT01TR microphones uses DFSDM_DATIN0 input pin */
01913   AUDIO_DFSDMx_DMIC_GPIO_CLK_ENABLE();
01914   GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_PIN;
01915   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
01916   GPIO_InitStruct.Pull = GPIO_NOPULL;
01917   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
01918   GPIO_InitStruct.Alternate = AUDIO_DFSDMx_DMIC_AF;
01919   HAL_GPIO_Init(AUDIO_DFSDMx_DMIC_GPIO_PORT, &GPIO_InitStruct);
01920 
01921 }
01922 
01923 /**
01924   * @brief  DeInitializes the DFSDM channel MSP.
01925   */
01926 static void DFSDMx_ChannelMspDeInit(void)
01927 {
01928   GPIO_InitTypeDef  GPIO_InitStruct;
01929 
01930   /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN pins ------------------*/
01931   GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN;
01932   HAL_GPIO_DeInit(AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT, GPIO_InitStruct.Pin);
01933 
01934   /* MP34DT01TR microphones uses DFSDM_DATIN0 input pin */
01935   GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_PIN;
01936   HAL_GPIO_DeInit(AUDIO_DFSDMx_DMIC_GPIO_PORT, GPIO_InitStruct.Pin);
01937 
01938 }
01939 
01940 /**
01941   * @brief  Initializes the DFSDM filter MSP.
01942   */
01943 static void DFSDMx_FilterMspInit(void)
01944 {
01945   uint32_t i = 0, mic_num = 0, mic_init[DFSDM_MIC_NUMBER] = {0};
01946   IRQn_Type AUDIO_DFSDM_DMAx_MIC_IRQHandler[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_DMAx_MIC1_IRQ, AUDIO_DFSDMx_DMAx_MIC2_IRQ};
01947   DMA_Stream_TypeDef* AUDIO_DFSDMx_DMAx_MIC_STREAM[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_DMAx_MIC1_STREAM, AUDIO_DFSDMx_DMAx_MIC2_STREAM};
01948   uint32_t AUDIO_DFSDMx_DMAx_MIC_REQUEST[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_DMAx_MIC1_REQUEST, AUDIO_DFSDMx_DMAx_MIC2_REQUEST};
01949 
01950   /* Enable the DMA clock */
01951   AUDIO_DFSDMx_DMAx_CLK_ENABLE();
01952 
01953   for(i = 0; i < hAudioIn.ChannelNbr; i++)
01954   {
01955     if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] != 1))
01956     {
01957       mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC1);
01958       mic_init[mic_num] = 1;
01959     }
01960     else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] != 1))
01961     {
01962       mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC2);
01963       mic_init[mic_num] = 1;
01964     }
01965 
01966     /* Configure the hDmaDfsdm[i] handle parameters */
01967     hDmaDfsdm[mic_num].Init.Request             = AUDIO_DFSDMx_DMAx_MIC_REQUEST[mic_num];
01968     hDmaDfsdm[mic_num].Instance                 = AUDIO_DFSDMx_DMAx_MIC_STREAM[mic_num];
01969     hDmaDfsdm[mic_num].Init.Direction           = DMA_PERIPH_TO_MEMORY;
01970     hDmaDfsdm[mic_num].Init.PeriphInc           = DMA_PINC_DISABLE;
01971     hDmaDfsdm[mic_num].Init.MemInc              = DMA_MINC_ENABLE;
01972     hDmaDfsdm[mic_num].Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
01973     hDmaDfsdm[mic_num].Init.MemDataAlignment    = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
01974     hDmaDfsdm[mic_num].Init.Mode                = DMA_CIRCULAR;
01975     hDmaDfsdm[mic_num].Init.Priority            = DMA_PRIORITY_HIGH;
01976     hDmaDfsdm[mic_num].Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
01977     hDmaDfsdm[mic_num].Init.MemBurst            = DMA_MBURST_SINGLE;
01978     hDmaDfsdm[mic_num].Init.PeriphBurst         = DMA_PBURST_SINGLE;
01979     hDmaDfsdm[mic_num].State                    = HAL_DMA_STATE_RESET;
01980 
01981     /* Associate the DMA handle */
01982     __HAL_LINKDMA(&hAudioInDfsdmFilter[mic_num], hdmaReg, hDmaDfsdm[mic_num]);
01983 
01984     /* Reset DMA handle state */
01985     __HAL_DMA_RESET_HANDLE_STATE(&hDmaDfsdm[mic_num]);
01986 
01987     /* Configure the DMA Channel */
01988     HAL_DMA_Init(&hDmaDfsdm[mic_num]);
01989 
01990     /* DMA IRQ Channel configuration */
01991     HAL_NVIC_SetPriority(AUDIO_DFSDM_DMAx_MIC_IRQHandler[mic_num], AUDIO_IN_IRQ_PREPRIO, 0);
01992     HAL_NVIC_EnableIRQ(AUDIO_DFSDM_DMAx_MIC_IRQHandler[mic_num]);
01993   }
01994 }
01995 
01996 /**
01997   * @brief  DeInitializes the DFSDM filter MSP.
01998   */
01999 static void DFSDMx_FilterMspDeInit(void)
02000 {
02001   /* Configure the DMA Channel */
02002   for(uint32_t i = 0; i < DFSDM_MIC_NUMBER; i++)
02003   {
02004     if(hDmaDfsdm[i].Instance != NULL)
02005     {
02006       HAL_DMA_DeInit(&hDmaDfsdm[i]);
02007     }
02008   }
02009 }
02010 
02011 /**
02012   * @brief  Initializes SAI Audio IN MSP.
02013   * @param  hsai: SAI handle
02014   * @param  Params: pointer on additional configuration parameters, can be NULL.
02015   * @retval None
02016   */
02017 static void SAIx_In_MspInit(SAI_HandleTypeDef *hsai, void *Params)
02018 {
02019   static DMA_HandleTypeDef hdma_sai_rx;
02020   GPIO_InitTypeDef  gpio_init_structure;
02021 
02022   if(hsai->Instance == AUDIO_IN_SAI_PDMx)
02023   {
02024      /* Enable SAI clock */
02025     AUDIO_IN_SAI_PDMx_CLK_ENABLE();
02026 
02027     AUDIO_IN_SAI_PDMx_CLK_IN_ENABLE();
02028     AUDIO_IN_SAI_PDMx_DATA_IN_ENABLE();
02029 
02030     gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_CLK_IN_PIN;
02031     gpio_init_structure.Mode = GPIO_MODE_AF_PP;
02032     gpio_init_structure.Pull = GPIO_NOPULL;
02033     gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH;
02034     gpio_init_structure.Alternate = AUDIO_IN_SAI_PDMx_DATA_CLK_AF;
02035     HAL_GPIO_Init(AUDIO_IN_SAI_PDMx_CLK_IN_PORT, &gpio_init_structure);
02036 
02037     gpio_init_structure.Pull = GPIO_PULLUP;
02038     gpio_init_structure.Speed = GPIO_SPEED_FREQ_MEDIUM;
02039     gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_DATA_IN_PIN;
02040     HAL_GPIO_Init(AUDIO_IN_SAI_PDMx_DATA_IN_PORT, &gpio_init_structure);
02041 
02042     AUDIO_IN_SAI_PDMx_FS_SCK_ENABLE();
02043 
02044     /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/
02045     gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_FS_PIN | AUDIO_IN_SAI_PDMx_SCK_PIN;
02046     gpio_init_structure.Mode = GPIO_MODE_AF_PP;
02047     gpio_init_structure.Pull = GPIO_NOPULL;
02048     gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH;
02049     gpio_init_structure.Alternate = AUDIO_IN_SAI_PDMx_FS_SCK_AF;
02050     HAL_GPIO_Init(AUDIO_IN_SAI_PDMx_FS_SCK_GPIO_PORT, &gpio_init_structure);
02051 
02052     /* Enable the DMA clock */
02053     AUDIO_IN_SAI_PDMx_DMAx_CLK_ENABLE();
02054 
02055     /* Configure the hdma_sai_rx handle parameters */
02056     hdma_sai_rx.Init.Request             = AUDIO_IN_SAI_PDMx_DMAx_REQUEST;
02057     hdma_sai_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
02058     hdma_sai_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
02059     hdma_sai_rx.Init.MemInc              = DMA_MINC_ENABLE;
02060     hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAI_PDMx_DMAx_PERIPH_DATA_SIZE;
02061     hdma_sai_rx.Init.MemDataAlignment    = AUDIO_IN_SAI_PDMx_DMAx_MEM_DATA_SIZE;
02062     hdma_sai_rx.Init.Mode                = DMA_CIRCULAR;
02063     hdma_sai_rx.Init.Priority            = DMA_PRIORITY_HIGH;
02064     hdma_sai_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
02065     hdma_sai_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
02066     hdma_sai_rx.Init.MemBurst            = DMA_MBURST_SINGLE;
02067     hdma_sai_rx.Init.PeriphBurst         = DMA_MBURST_SINGLE;
02068 
02069     hdma_sai_rx.Instance = AUDIO_IN_SAI_PDMx_DMAx_STREAM;
02070 
02071     /* Associate the DMA handle */
02072     __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx);
02073 
02074     /* Deinitialize the Stream for new transfer */
02075     HAL_DMA_DeInit(&hdma_sai_rx);
02076 
02077     /* Configure the DMA Stream */
02078     HAL_DMA_Init(&hdma_sai_rx);
02079 
02080     /* SAI DMA IRQ Channel configuration */
02081     HAL_NVIC_SetPriority(AUDIO_IN_SAI_PDMx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
02082     HAL_NVIC_EnableIRQ(AUDIO_IN_SAI_PDMx_DMAx_IRQ);
02083   }
02084   else
02085   {
02086     /* Enable SAI clock */
02087     AUDIO_IN_SAIx_CLK_ENABLE();
02088 
02089     /* Enable SD GPIO clock */
02090     AUDIO_IN_SAIx_SD_ENABLE();
02091     /* CODEC_SAI pin configuration: SD pin */
02092     gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN;
02093     gpio_init_structure.Mode = GPIO_MODE_AF_PP;
02094     gpio_init_structure.Pull = GPIO_NOPULL;
02095     gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH;
02096     gpio_init_structure.Alternate = AUDIO_IN_SAIx_AF;
02097     HAL_GPIO_Init(AUDIO_IN_SAIx_SD_GPIO_PORT, &gpio_init_structure);
02098 
02099     /* Enable Audio INT GPIO clock */
02100     AUDIO_IN_INT_GPIO_ENABLE();
02101     /* Audio INT pin configuration: input */
02102     gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN;
02103     gpio_init_structure.Mode = GPIO_MODE_INPUT;
02104     gpio_init_structure.Pull = GPIO_NOPULL;
02105     gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH;
02106     HAL_GPIO_Init(AUDIO_IN_INT_GPIO_PORT, &gpio_init_structure);
02107 
02108     /* Enable the DMA clock */
02109     AUDIO_IN_SAIx_DMAx_CLK_ENABLE();
02110 
02111     /* Configure the hdma_sai_rx handle parameters */
02112     hdma_sai_rx.Init.Request             = AUDIO_IN_SAIx_DMAx_REQUEST;
02113     hdma_sai_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
02114     hdma_sai_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
02115     hdma_sai_rx.Init.MemInc              = DMA_MINC_ENABLE;
02116     hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAIx_DMAx_PERIPH_DATA_SIZE;
02117     hdma_sai_rx.Init.MemDataAlignment    = AUDIO_IN_SAIx_DMAx_MEM_DATA_SIZE;
02118     hdma_sai_rx.Init.Mode                = DMA_CIRCULAR;
02119     hdma_sai_rx.Init.Priority            = DMA_PRIORITY_HIGH;
02120     hdma_sai_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
02121     hdma_sai_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
02122     hdma_sai_rx.Init.MemBurst            = DMA_MBURST_SINGLE;
02123     hdma_sai_rx.Init.PeriphBurst         = DMA_MBURST_SINGLE;
02124 
02125     hdma_sai_rx.Instance = AUDIO_IN_SAIx_DMAx_STREAM;
02126 
02127     /* Associate the DMA handle */
02128     __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx);
02129 
02130     /* Deinitialize the Stream for new transfer */
02131     HAL_DMA_DeInit(&hdma_sai_rx);
02132 
02133     /* Configure the DMA Stream */
02134     HAL_DMA_Init(&hdma_sai_rx);
02135 
02136     /* SAI DMA IRQ Channel configuration */
02137     HAL_NVIC_SetPriority(AUDIO_IN_SAIx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
02138     HAL_NVIC_EnableIRQ(AUDIO_IN_SAIx_DMAx_IRQ);
02139 
02140     /* Audio INT IRQ Channel configuration */
02141     HAL_NVIC_SetPriority(AUDIO_IN_INT_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
02142     HAL_NVIC_EnableIRQ(AUDIO_IN_INT_IRQ);
02143   }
02144 }
02145 
02146 /**
02147   * @brief  De-Initializes SAI Audio IN MSP.
02148   * @param  hsai: SAI handle
02149   * @param  Params: pointer on additional configuration parameters, can be NULL.
02150   * @retval None
02151   */
02152 static void SAIx_In_MspDeInit(SAI_HandleTypeDef *hsai, void *Params)
02153 {
02154   GPIO_InitTypeDef  gpio_init_structure;
02155 
02156   if(hsai->Instance == AUDIO_IN_SAI_PDMx)
02157   {
02158     /* Deinitialize the DMA stream */
02159     HAL_DMA_Abort(hsai->hdmarx);
02160 
02161     HAL_SAI_DeInit(hsai);
02162     /* Disable SAI peripheral */
02163     __HAL_SAI_DISABLE(hsai);
02164 
02165     /* Deinitialize the DMA stream */
02166     HAL_DMA_DeInit(hsai->hdmarx);
02167 
02168     gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_CLK_IN_PIN;
02169     HAL_GPIO_DeInit(AUDIO_IN_SAI_PDMx_CLK_IN_PORT, gpio_init_structure.Pin);
02170 
02171     gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_DATA_IN_PIN;
02172     HAL_GPIO_DeInit(AUDIO_IN_SAI_PDMx_DATA_IN_PORT, gpio_init_structure.Pin);
02173 
02174     /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/
02175     gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_FS_PIN | AUDIO_IN_SAI_PDMx_SCK_PIN;
02176     HAL_GPIO_DeInit(AUDIO_IN_SAI_PDMx_FS_SCK_GPIO_PORT, gpio_init_structure.Pin);
02177 
02178     /* Disable SAI clock */
02179     AUDIO_IN_SAI_PDMx_CLK_DISABLE();
02180 
02181     /* Set audio_in interface as default one */
02182     hAudioIn.Interface = AUDIO_IN_INTERFACE_DFSDM;
02183   }
02184   else
02185   {
02186     /* SAI DMA IRQ Channel deactivation */
02187     HAL_NVIC_DisableIRQ(AUDIO_IN_SAIx_DMAx_IRQ);
02188 
02189     if(hsai->Instance == AUDIO_IN_SAIx)
02190     {
02191       /* Deinitialize the DMA stream */
02192       HAL_DMA_DeInit(hsai->hdmatx);
02193     }
02194 
02195     /* Disable SAI peripheral */
02196     __HAL_SAI_DISABLE(hsai);
02197 
02198     /* Deactivates CODEC_SAI pin SD by putting them in input mode */
02199     gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN;
02200     HAL_GPIO_DeInit(AUDIO_IN_SAIx_SD_GPIO_PORT, gpio_init_structure.Pin);
02201 
02202     gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN;
02203     HAL_GPIO_DeInit(AUDIO_IN_INT_GPIO_PORT, gpio_init_structure.Pin);
02204 
02205     /* Disable SAI clock */
02206     AUDIO_IN_SAIx_CLK_DISABLE();
02207   }
02208 }
02209 
02210 /**
02211   * @brief  Initializes the Audio Codec audio interface (SAI).
02212   * @param  SaiInMode: Audio mode to be configured for the SAI peripheral.
02213   * @param  SlotActive: Audio active slot to be configured for the SAI peripheral.
02214   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
02215   * @retval None
02216   */
02217 static void SAIx_In_Init(uint32_t SaiInMode, uint32_t SlotActive, uint32_t AudioFreq)
02218 {
02219   /* Disable SAI peripheral to allow access to SAI internal registers */
02220   __HAL_SAI_DISABLE(&haudio_in_sai);
02221 
02222   /* Configure SAI_Block_x
02223   LSBFirst: Disabled
02224   DataSize: 16 */
02225   haudio_in_sai.Init.MonoStereoMode = SAI_STEREOMODE;
02226   haudio_in_sai.Init.AudioFrequency = AudioFreq;
02227   haudio_in_sai.Init.AudioMode      = SaiInMode;
02228   haudio_in_sai.Init.NoDivider      = SAI_MASTERDIVIDER_ENABLE;
02229   haudio_in_sai.Init.Protocol       = SAI_FREE_PROTOCOL;
02230   haudio_in_sai.Init.DataSize       = SAI_DATASIZE_16;
02231   haudio_in_sai.Init.FirstBit       = SAI_FIRSTBIT_MSB;
02232   haudio_in_sai.Init.ClockStrobing  = SAI_CLOCKSTROBING_RISINGEDGE;
02233   haudio_in_sai.Init.Synchro        = SAI_SYNCHRONOUS;
02234   haudio_in_sai.Init.OutputDrive    = SAI_OUTPUTDRIVE_DISABLE;
02235   haudio_in_sai.Init.FIFOThreshold  = SAI_FIFOTHRESHOLD_1QF;
02236   haudio_in_sai.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
02237   haudio_in_sai.Init.CompandingMode = SAI_NOCOMPANDING;
02238   haudio_in_sai.Init.TriState       = SAI_OUTPUT_RELEASED;
02239   haudio_in_sai.Init.Mckdiv         = 0;
02240   haudio_in_sai.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE;
02241   haudio_in_sai.Init.PdmInit.Activation  = DISABLE;
02242 
02243   /* Configure SAI_Block_x Frame
02244   Frame Length: 64
02245   Frame active Length: 32
02246   FS Definition: Start frame + Channel Side identification
02247   FS Polarity: FS active Low
02248   FS Offset: FS asserted one bit before the first bit of slot 0 */
02249   haudio_in_sai.FrameInit.FrameLength       = 128;
02250   haudio_in_sai.FrameInit.ActiveFrameLength = 64;
02251   haudio_in_sai.FrameInit.FSDefinition      = SAI_FS_CHANNEL_IDENTIFICATION;
02252   haudio_in_sai.FrameInit.FSPolarity        = SAI_FS_ACTIVE_LOW;
02253   haudio_in_sai.FrameInit.FSOffset          = SAI_FS_BEFOREFIRSTBIT;
02254 
02255   /* Configure SAI Block_x Slot
02256   Slot First Bit Offset: 0
02257   Slot Size  : 16
02258   Slot Number: 4
02259   Slot Active: All slot active */
02260   haudio_in_sai.SlotInit.FirstBitOffset = 0;
02261   haudio_in_sai.SlotInit.SlotSize       = SAI_SLOTSIZE_DATASIZE;
02262   haudio_in_sai.SlotInit.SlotNumber     = 4;
02263   haudio_in_sai.SlotInit.SlotActive     = SlotActive;
02264 
02265   if(hAudioIn.Interface == AUDIO_IN_INTERFACE_PDM)
02266   {
02267     haudio_in_sai.Init.AudioFrequency      = AudioFreq * 8;
02268     haudio_in_sai.Init.Synchro             = SAI_ASYNCHRONOUS;
02269     haudio_in_sai.Init.NoDivider           = SAI_MASTERDIVIDER_DISABLE;
02270 
02271     haudio_in_sai.Init.PdmInit.Activation  = ENABLE;
02272     haudio_in_sai.Init.PdmInit.MicPairsNbr = 1;
02273     haudio_in_sai.Init.PdmInit.ClockEnable = SAI_PDM_CLOCK1_ENABLE;
02274     haudio_in_sai.Init.FirstBit            = SAI_FIRSTBIT_LSB;
02275     haudio_in_sai.Init.ClockStrobing       = SAI_CLOCKSTROBING_FALLINGEDGE;
02276 
02277     haudio_in_sai.FrameInit.FrameLength       = 16;
02278     haudio_in_sai.FrameInit.ActiveFrameLength = 1;
02279     haudio_in_sai.FrameInit.FSDefinition      = SAI_FS_STARTFRAME;
02280     haudio_in_sai.FrameInit.FSPolarity        = SAI_FS_ACTIVE_HIGH;
02281     haudio_in_sai.FrameInit.FSOffset          = SAI_FS_FIRSTBIT;
02282 
02283     haudio_in_sai.SlotInit.SlotNumber     = 1;
02284     haudio_in_sai.SlotInit.SlotActive     = SlotActive;
02285   }
02286 
02287   HAL_SAI_Init(&haudio_in_sai);
02288 
02289   /* Enable SAI peripheral */
02290   __HAL_SAI_ENABLE(&haudio_in_sai);
02291 }
02292 
02293 /**
02294   * @brief  Deinitializes the output Audio Codec audio interface (SAI).
02295   * @retval None
02296   */
02297 static void SAIx_In_DeInit(SAI_HandleTypeDef *hsai)
02298 {
02299   /* Disable SAI peripheral */
02300   __HAL_SAI_DISABLE(hsai);
02301 
02302   HAL_SAI_DeInit(hsai);
02303 }
02304 
02305 /**
02306   * @}
02307   */
02308 
02309 /**
02310   * @}
02311   */
02312 
02313 /**
02314   * @}
02315   */
02316 
02317 /**
02318   * @}
02319   */
02320 
02321 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Wed Aug 23 2017 17:45:13 for STM32H743I_EVAL BSP User Manual by   doxygen 1.7.6.1