ST / BSP_DISCO_H747I

Dependents:   DISCO_H747I_LCD_demo DISCO_H747I_AUDIO_demo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32h747i_discovery_audio.c Source File

stm32h747i_discovery_audio.c

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32h747i_discovery_audio.c
00004   * @author  MCD Application Team
00005   * @brief   This file provides the Audio driver for the STM32H747I-DISCOVERY  
00006   *          board.
00007   @verbatim
00008   How To use this driver:
00009   -----------------------
00010    + This driver supports STM32H7xx devices on STM32H747I-DISCOVERY (MB1248) Discovery boards.
00011    + Call the function BSP_AUDIO_OUT_Init(
00012                                     OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 
00013                                                   OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH)
00014                                     Volume      : Initial volume to be set (0 is min (mute), 100 is max (100%)
00015                                     AudioFreq   : Audio frequency in Hz (8000, 16000, 22500, 32000...)
00016                                                   this parameter is relative to the audio file/stream type.
00017                                    )
00018       This function configures all the hardware required for the audio application (codec, I2C, SAI, 
00019       GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK.
00020       If the returned value is different from AUDIO_OK or the function is stuck then the communication with
00021       the codec has failed (try to un-plug the power or reset device in this case).
00022       - OUTPUT_DEVICE_SPEAKER  : only speaker will be set as output for the audio stream.
00023       - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream.
00024       - OUTPUT_DEVICE_BOTH     : both Speaker and Headphone are used as outputs for the audio stream
00025                                  at the same time.
00026       Note. On STM32H747I-DISCOVERY SAI_DMA is configured in CIRCULAR mode. Due to this the application
00027         does NOT need to call BSP_AUDIO_OUT_ChangeBuffer() to assure streaming.
00028    + Call the function BSP_AUDIO_OUT_Play(
00029                                   pBuffer: pointer to the audio data file address
00030                                   Size   : size of the buffer to be sent in Bytes
00031                                  )
00032       to start playing (for the first time) from the audio file/stream.
00033    + Call the function BSP_AUDIO_OUT_Pause() to pause playing
00034    + Call the function BSP_AUDIO_OUT_Resume() to resume playing.
00035        Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called
00036           for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case).
00037        Note. This function should be called only when the audio file is played or paused (not stopped).
00038    + For each mode, you may need to implement the relative callback functions into your code.
00039       The Callback functions are named BSP_AUDIO_OUT_XXX_CallBack() and only their prototypes are declared in 
00040       the stm32h747i_discovery_audio.h file. (refer to the example for more details on the callbacks implementations)
00041    + To Stop playing, to modify the volume level, the frequency, the audio frame slot, 
00042       the device output mode the mute or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(), 
00043       AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetAudioFrameSlot(), BSP_AUDIO_OUT_SetOutputMode(),
00044       BSP_AUDIO_OUT_SetMute() and BSP_AUDIO_OUT_Stop().
00045 
00046    + Call the function BSP_AUDIO_IN_Init(
00047                                     AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000...)
00048                                                   this parameter is relative to the audio file/stream type.
00049                                     BitRes: Bit resolution fixed to 16bit
00050                                     ChnlNbr: Number of channel to be configured for the DFSDM peripheral
00051                                    )
00052       This function configures all the hardware required for the audio in application (channels, 
00053       Clock source for SAI PDM periphiral, GPIOs, DMA and interrupt if needed). 
00054       This function returns AUDIO_OK if configuration is OK.If the returned value is different from AUDIO_OK then
00055       the configuration should be wrong.
00056    + Call the function BSP_AUDIO_IN_AllocScratch(
00057                                         pScratch: pointer to scratch tables
00058                                         size: size of scratch buffer)
00059      This function must be called before BSP_AUDIO_IN_RECORD() to allocate buffer scratch for each DFSDM channel
00060      and its size.
00061      Note: These buffers scratch are used as intermidiate buffers to collect data within final record buffer.
00062            size is the total size of the four buffers scratch; If size is 512 then the size of each is 128.
00063            This function must be called after BSP_AUDIO_IN_Init()
00064    + Call the function BSP_AUDIO_IN_RECORD(
00065                                   pBuf: pointer to the recorded audio data file address
00066                                   Size: size of the buffer to be written in Bytes
00067                                  )
00068       to start recording from microphones.
00069 
00070    + Call the function BSP_AUDIO_IN_Pause() to pause recording
00071    + Call the function BSP_AUDIO_IN_Resume() to recording playing.
00072        Note. After calling BSP_AUDIO_IN_Pause() function for pause, only BSP_AUDIO_IN_Resume() should be called
00073           for resume (it is not allowed to call BSP_AUDIO_IN_RECORD() in this case).
00074    + Call the function BSP_AUDIO_IN_Stop() to stop recording
00075    + For each mode, you may need to implement the relative callback functions into your code.
00076       The Callback functions are named BSP_AUDIO_IN_XXX_CallBack() and only their prototypes are declared in 
00077       the stm32h747i_discovery_audio.h file. (refer to the example for more details on the callbacks implementations)
00078    + Call the function BSP_AUDIO_IN_SelectInterface(uint32_t Interface) to select one of the two interfaces
00079      available on the STM32H747I-Discovery board: SAI or PDM. This function is to be called before BSP_AUDIO_IN_InitEx().
00080    + Call the function BSP_AUDIO_IN_GetInterface() to get the current used interface.
00081    + Call the function BSP_AUDIO_IN_PDMToPCM_Init(uint32_t AudioFreq, uint32_t ChnlNbrIn, uint32_t ChnlNbrOut)
00082      to init PDM filters if the libPDMFilter is used for audio data filtering.
00083    + Call the function BSP_AUDIO_IN_PDMToPCM(uint16_t* PDMBuf, uint16_t* PCMBuf) to filter PDM data to PCM format
00084      if the libPDMFilter library is used for audio data filtering.
00085 
00086   Driver architecture:
00087   --------------------
00088    + This driver provides the High Audio Layer: consists of the function API exported in the stm32h747i_discovery_audio.h file
00089      (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...)
00090    + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/
00091      providing the audio file/stream. These functions are also included as local functions into
00092      the stm32h747i_discovery_audio.c file (DFSDMx_Init(), DFSDMx_DeInit(), SAIx_Init() and SAIx_DeInit())
00093 
00094   Known Limitations:
00095   ------------------
00096    1- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second
00097       Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams.
00098    2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size,
00099       File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file.
00100    3- Supports only Stereo audio streaming.
00101    4- Supports only 16-bits audio data size.
00102   @endverbatim
00103   ******************************************************************************
00104   * @attention
00105   *
00106   * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
00107   * All rights reserved.</center></h2>
00108   *
00109   * This software component is licensed by ST under BSD 3-Clause license,
00110   * the "License"; You may not use this file except in compliance with the
00111   * License. You may obtain a copy of the License at:
00112   *                        opensource.org/licenses/BSD-3-Clause
00113   *
00114   ******************************************************************************
00115   */
00116 /* Includes ------------------------------------------------------------------*/
00117 #include "stm32h747i_discovery_audio.h"
00118 
00119 /** @addtogroup BSP
00120   * @{
00121   */
00122 
00123 /** @addtogroup STM32H747I_DISCOVERY
00124   * @{
00125   */ 
00126   
00127 /** @defgroup STM32H747I_DISCOVERY_AUDIO STM32H747I_DISCOVERY_AUDIO
00128   * @brief This file includes the low layer driver for wm8994 Audio Codec
00129   *        available on STM32H747I-DISCOVERY discovery board(MB1248).
00130   * @{
00131   */ 
00132   
00133 /** @defgroup STM32H747I_DISCOVERY_AUDIO_Private_Variables Private Variables
00134   * @{
00135   */
00136 /* PLAY */
00137 AUDIO_DrvTypeDef                *audio_drv;
00138 SAI_HandleTypeDef               haudio_out_sai;
00139 SAI_HandleTypeDef               haudio_in_sai;
00140 
00141 /* RECORD */
00142 AUDIOIN_ContextTypeDef          hAudioIn;
00143 
00144 
00145 
00146 /* Audio in Volume value */
00147 __IO uint16_t                   AudioInVolume = DEFAULT_AUDIO_IN_VOLUME;
00148 
00149 /* PDM filters params */
00150 PDM_Filter_Handler_t  PDM_FilterHandler[2];
00151 PDM_Filter_Config_t   PDM_FilterConfig[2];
00152 
00153 /**
00154   * @}
00155   */ 
00156 
00157 /** @defgroup STM32H747I_DISCOVERY_AUDIO_Private_Function_Prototypes Private FunctionPrototypes
00158   * @{
00159   */
00160 static void SAIx_Out_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq);
00161 static void SAIx_Out_DeInit(SAI_HandleTypeDef *hsai);
00162 static void SAIx_In_MspInit(SAI_HandleTypeDef *hsai, void *Params);
00163 static void SAIx_In_MspDeInit(SAI_HandleTypeDef *hsai, void *Params);
00164 static void SAIx_In_Init(uint32_t SaiInMode, uint32_t SlotActive, uint32_t AudioFreq);
00165 static void SAIx_In_DeInit(SAI_HandleTypeDef *hsai);
00166 
00167 /**
00168   * @}
00169   */
00170 
00171 /** @defgroup STM32H747I_DISCOVERY_AUDIO_OUT_Exported_Functions OUT Exported Functions
00172   * @{
00173   */
00174 
00175 /**
00176   * @brief  Configures the audio Out peripheral.
00177   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
00178   *                       or OUTPUT_DEVICE_BOTH.
00179   * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
00180   * @param  AudioFreq: Audio frequency used to play the audio stream.
00181   * @retval AUDIO_OK if correct communication, else wrong communication
00182   */
00183 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
00184 {
00185   uint8_t ret = AUDIO_ERROR;
00186   uint32_t deviceid = 0x00;
00187   uint32_t slot_active;
00188 
00189   /* Initialize SAI1 sub_block A as MASTER TX */
00190   haudio_out_sai.Instance = AUDIO_OUT_SAIx;
00191 
00192   /* Disable SAI */
00193   SAIx_Out_DeInit(&haudio_out_sai);
00194 
00195   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */
00196   BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
00197 
00198   /* SAI data transfer preparation:
00199   Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
00200 
00201   if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET)
00202   {
00203     /* Init the SAI MSP: this __weak function can be redefined by the application*/
00204     BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL);
00205   }
00206 
00207   /* Init SAI as master RX output */
00208   slot_active = CODEC_AUDIOFRAME_SLOT_0123;
00209   SAIx_Out_Init(SAI_MODEMASTER_TX, slot_active, AudioFreq);
00210 
00211   /* wm8994 codec initialization */
00212   deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
00213 
00214   if((deviceid) == WM8994_ID)
00215   {
00216     /* Reset the Codec Registers */
00217     wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
00218     /* Initialize the audio driver structure */
00219     audio_drv = &wm8994_drv;
00220     ret = AUDIO_OK;
00221   }
00222   else
00223   {
00224     ret = AUDIO_ERROR;
00225   }
00226 
00227   if(ret == AUDIO_OK)
00228   {
00229     /* Initialize the codec internal registers */
00230     audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq);
00231   }
00232 
00233   return ret;
00234 }
00235 
00236 /**
00237   * @brief  Starts playing audio stream from a data buffer for a determined size.
00238   * @param  pBuffer: Pointer to the buffer
00239   * @param  Size: Number of audio data BYTES.
00240   * @retval AUDIO_OK if correct communication, else wrong communication
00241   */
00242 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size)
00243 {
00244   /* Call the audio Codec Play function */
00245   if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0)
00246   {
00247     return AUDIO_ERROR;
00248   }
00249   else
00250   {
00251     /* Update the Media layer and enable it for play */
00252     HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE));
00253 
00254     return AUDIO_OK;
00255   }
00256 }
00257 
00258 /**
00259   * @brief  Sends n-Bytes on the SAI interface.
00260   * @param  pData: pointer on data address
00261   * @param  Size: number of data to be written
00262   * @retval None
00263   */
00264 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size)
00265 {
00266    HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size);
00267 }
00268 
00269 /**
00270   * @brief  This function Pauses the audio file stream. In case
00271   *         of using DMA, the DMA Pause feature is used.
00272   * @warning When calling BSP_AUDIO_OUT_Pause() function for pause, only
00273   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play()
00274   *          function for resume could lead to unexpected behaviour).
00275   * @retval AUDIO_OK if correct communication, else wrong communication
00276   */
00277 uint8_t BSP_AUDIO_OUT_Pause(void)
00278 {
00279   /* Call the Audio Codec Pause/Resume function */
00280   if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0)
00281   {
00282     return AUDIO_ERROR;
00283   }
00284   else
00285   {
00286     /* Call the Media layer pause function */
00287     HAL_SAI_DMAPause(&haudio_out_sai);
00288 
00289     /* Return AUDIO_OK when all operations are correctly done */
00290     return AUDIO_OK;
00291   }
00292 }
00293 
00294 /**
00295   * @brief   Resumes the audio file stream.
00296   * @warning When calling BSP_AUDIO_OUT_Pause() function for pause, only
00297   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play()
00298   *          function for resume could lead to unexpected behaviour).
00299   * @retval AUDIO_OK if correct communication, else wrong communication
00300   */
00301 uint8_t BSP_AUDIO_OUT_Resume(void)
00302 {
00303   /* Call the Audio Codec Pause/Resume function */
00304   if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0)
00305   {
00306     return AUDIO_ERROR;
00307   }
00308   else
00309   {
00310     /* Call the Media layer pause/resume function */
00311     HAL_SAI_DMAResume(&haudio_out_sai);
00312 
00313     /* Return AUDIO_OK when all operations are correctly done */
00314     return AUDIO_OK;
00315   }
00316 }
00317 
00318 /**
00319   * @brief  Stops audio playing and Power down the Audio Codec.
00320   * @param  Option: could be one of the following parameters
00321   *           - CODEC_PDWN_SW: for software power off (by writing registers).
00322   *                            Then no need to reconfigure the Codec after power on.
00323   *           - CODEC_PDWN_HW: completely shut down the codec (physically).
00324   *                            Then need to reconfigure the Codec after power on.
00325   * @retval AUDIO_OK if correct communication, else wrong communication
00326   */
00327 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
00328 {
00329   /* Call the Media layer stop function */
00330   HAL_SAI_DMAStop(&haudio_out_sai);
00331 
00332   /* Call Audio Codec Stop function */
00333   if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
00334   {
00335     return AUDIO_ERROR;
00336   }
00337   else
00338   {
00339     if(Option == CODEC_PDWN_HW)
00340     {
00341       /* Wait at least 100us */
00342       HAL_Delay(1);
00343     }
00344     /* Return AUDIO_OK when all operations are correctly done */
00345     return AUDIO_OK;
00346   }
00347 }
00348 
00349 /**
00350   * @brief  Controls the current audio volume level.
00351   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for
00352   *         Mute and 100 for Max volume level).
00353   * @retval AUDIO_OK if correct communication, else wrong communication
00354   */
00355 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume)
00356 {
00357   /* Call the codec volume control function with converted volume value */
00358   if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
00359   {
00360     return AUDIO_ERROR;
00361   }
00362   else
00363   {
00364     /* Return AUDIO_OK when all operations are correctly done */
00365     return AUDIO_OK;
00366   }
00367 }
00368 
00369 /**
00370   * @brief  Enables or disables the MUTE mode by software
00371   * @param  Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to
00372   *         unmute the codec and restore previous volume level.
00373   * @retval AUDIO_OK if correct communication, else wrong communication
00374   */
00375 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd)
00376 {
00377   /* Call the Codec Mute function */
00378   if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0)
00379   {
00380     return AUDIO_ERROR;
00381   }
00382   else
00383   {
00384     /* Return AUDIO_OK when all operations are correctly done */
00385     return AUDIO_OK;
00386   }
00387 }
00388 
00389 /**
00390   * @brief  Switch dynamically (while audio file is played) the output target
00391   *         (speaker or headphone).
00392   * @param  Output: The audio output target: OUTPUT_DEVICE_SPEAKER,
00393   *         OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH
00394   * @retval AUDIO_OK if correct communication, else wrong communication
00395   */
00396 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)
00397 {
00398   /* Call the Codec output device function */
00399   if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0)
00400   {
00401     return AUDIO_ERROR;
00402   }
00403   else
00404   {
00405     /* Return AUDIO_OK when all operations are correctly done */
00406     return AUDIO_OK;
00407   }
00408 }
00409 
00410 /**
00411   * @brief  Updates the audio frequency.
00412   * @param  AudioFreq: Audio frequency used to play the audio stream.
00413   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00414   *         audio frequency.
00415   * @retval None
00416   */
00417 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)
00418 {
00419   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */
00420   BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
00421 
00422   /* Disable SAI peripheral to allow access to SAI internal registers */
00423   __HAL_SAI_DISABLE(&haudio_out_sai);
00424 
00425   /* Update the SAI audio frequency configuration */
00426   haudio_out_sai.Init.AudioFrequency = AudioFreq;
00427   HAL_SAI_Init(&haudio_out_sai);
00428 
00429   /* Enable SAI peripheral to generate MCLK */
00430   __HAL_SAI_ENABLE(&haudio_out_sai);
00431 }
00432 
00433 /**
00434   * @brief  Updates the Audio frame slot configuration.
00435   * @param  AudioFrameSlot: specifies the audio Frame slot
00436   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00437   *         audio frame slot.
00438   * @retval None
00439   */
00440 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot)
00441 {
00442   /* Disable SAI peripheral to allow access to SAI internal registers */
00443   __HAL_SAI_DISABLE(&haudio_out_sai);
00444 
00445   /* Update the SAI audio frame slot configuration */
00446   haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot;
00447   HAL_SAI_Init(&haudio_out_sai);
00448 
00449   /* Enable SAI peripheral to generate MCLK */
00450   __HAL_SAI_ENABLE(&haudio_out_sai);
00451 }
00452 
00453 /**
00454   * @brief  De-initializes the audio out peripheral.
00455   * @retval None
00456   */
00457 void BSP_AUDIO_OUT_DeInit(void)
00458 {
00459   SAIx_Out_DeInit(&haudio_out_sai);
00460   /* DeInit the SAI MSP : this __weak function can be rewritten by the application */
00461   BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL);
00462 }
00463 
00464 /**
00465   * @brief  Manages the DMA full Transfer complete event.
00466   * @retval None
00467   */
00468 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
00469 {
00470 }
00471 
00472 /**
00473   * @brief  Manages the DMA Half Transfer complete event.
00474   * @retval None
00475   */
00476 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void)
00477 {
00478 }
00479 
00480 /**
00481   * @brief  Manages the DMA FIFO error event.
00482   * @retval None
00483   */
00484 __weak void BSP_AUDIO_OUT_Error_CallBack(void)
00485 {
00486 }
00487 
00488 /**
00489   * @brief  Initializes BSP_AUDIO_OUT MSP.
00490   * @param  hsai: SAI handle
00491   * @param  Params: pointer on additional configuration parameters, can be NULL.
00492   * @retval None
00493   */
00494 __weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params)
00495 {
00496   static DMA_HandleTypeDef hdma_sai_tx;
00497   GPIO_InitTypeDef  gpio_init_structure;
00498 
00499   /* Enable SAI clock */
00500   AUDIO_OUT_SAIx_CLK_ENABLE();
00501 
00502   /* CODEC_SAI pins configuration: FS, SCK and SD pins */
00503   /* Enable FS, SCK and SD clocks */
00504   AUDIO_OUT_SAIx_SD_FS_CLK_ENABLE();
00505   /* Enable FS, SCK and SD pins */
00506   gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SD_PIN;
00507   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
00508   gpio_init_structure.Pull = GPIO_NOPULL;
00509   gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
00510   gpio_init_structure.Alternate = AUDIO_OUT_SAIx_AF;
00511   HAL_GPIO_Init(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, &gpio_init_structure);
00512 
00513   /* Enable MCLK clock */
00514   AUDIO_OUT_SAIx_MCLK_ENABLE();
00515   /* Enable MCLK pin */
00516   gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN;
00517   HAL_GPIO_Init(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, &gpio_init_structure);
00518 
00519   /* Enable the DMA clock */
00520   AUDIO_OUT_SAIx_DMAx_CLK_ENABLE();
00521 
00522   if(hsai->Instance == AUDIO_OUT_SAIx)
00523   {
00524     /* Configure the hdma_saiTx handle parameters */
00525     hdma_sai_tx.Init.Request             = AUDIO_OUT_SAIx_DMAx_REQUEST;
00526     hdma_sai_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
00527     hdma_sai_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
00528     hdma_sai_tx.Init.MemInc              = DMA_MINC_ENABLE;
00529     hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_OUT_SAIx_DMAx_PERIPH_DATA_SIZE;
00530     hdma_sai_tx.Init.MemDataAlignment    = AUDIO_OUT_SAIx_DMAx_MEM_DATA_SIZE;
00531     hdma_sai_tx.Init.Mode                = DMA_CIRCULAR;
00532     hdma_sai_tx.Init.Priority            = DMA_PRIORITY_HIGH;
00533     hdma_sai_tx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
00534     hdma_sai_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
00535     hdma_sai_tx.Init.MemBurst            = DMA_MBURST_SINGLE;
00536     hdma_sai_tx.Init.PeriphBurst         = DMA_PBURST_SINGLE;
00537 
00538     hdma_sai_tx.Instance = AUDIO_OUT_SAIx_DMAx_STREAM;
00539 
00540     /* Associate the DMA handle */
00541     __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx);
00542 
00543     /* Deinitialize the Stream for new transfer */
00544     HAL_DMA_DeInit(&hdma_sai_tx);
00545 
00546     /* Configure the DMA Stream */
00547     HAL_DMA_Init(&hdma_sai_tx);
00548   }
00549 
00550   /* SAI DMA IRQ Channel configuration */
00551   HAL_NVIC_SetPriority(AUDIO_OUT_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
00552   HAL_NVIC_EnableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ);
00553 }
00554 
00555 /**
00556   * @brief  Deinitializes SAI MSP.
00557   * @param  hsai: SAI handle
00558   * @param  Params: pointer on additional configuration parameters, can be NULL.
00559   * @retval None
00560   */
00561 __weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params)
00562 {
00563     GPIO_InitTypeDef  gpio_init_structure;
00564 
00565     /* SAI DMA IRQ Channel deactivation */
00566     HAL_NVIC_DisableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ);
00567 
00568     if(hsai->Instance == AUDIO_OUT_SAIx)
00569     {
00570       /* Deinitialize the DMA stream */
00571       HAL_DMA_DeInit(hsai->hdmatx);
00572     }
00573 
00574     /* Disable SAI peripheral */
00575     __HAL_SAI_DISABLE(hsai);
00576 
00577     /* Deactivates CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */
00578     gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SD_PIN;
00579     HAL_GPIO_DeInit(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, gpio_init_structure.Pin);
00580 
00581     gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN;
00582     HAL_GPIO_DeInit(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin);
00583 
00584     /* Disable SAI clock */
00585     AUDIO_OUT_SAIx_CLK_DISABLE();
00586 
00587     /* GPIO pins clock and DMA clock can be shut down in the applic
00588        by surcharging this __weak function */
00589 }
00590 
00591 /**
00592   * @brief  Clock Config.
00593   * @param  hsai: might be required to set audio peripheral predivider if any.
00594   * @param  AudioFreq: Audio frequency used to play the audio stream.
00595   * @param  Params: pointer on additional configuration parameters, can be NULL.
00596   * @note   This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency()
00597   *         Being __weak it can be overwritten by the application
00598   * @retval None
00599   */
00600 __weak void BSP_AUDIO_OUT_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params)
00601 {
00602   RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct;
00603 
00604   HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct);
00605 
00606   /* Set the PLL configuration according to the audio frequency */
00607   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
00608   {
00609     /* SAI clock config:
00610        PLL2_VCO Input = HSE_VALUE/PLL2M = 1 Mhz
00611        PLL2_VCO Output = PLL2_VCO Input * PLL2N = 429 Mhz
00612        SAI_CLK_x = PLL2_VCO Output/PLL2P = 429/38 = 11.289 Mhz */
00613     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
00614     rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2;
00615     rcc_ex_clk_init_struct.PLL2.PLL2P = 38;
00616     rcc_ex_clk_init_struct.PLL2.PLL2Q = 1;
00617     rcc_ex_clk_init_struct.PLL2.PLL2R = 1;
00618     rcc_ex_clk_init_struct.PLL2.PLL2N = 429;
00619     rcc_ex_clk_init_struct.PLL2.PLL2M = 25;
00620     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
00621   }
00622   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
00623   {
00624     /* SAI clock config:
00625        PLL2_VCO Input = HSE_VALUE/PLL2M = 1 Mhz
00626        PLL2_VCO Output = PLL2_VCO Input * PLL2N = 344 Mhz
00627        SAI_CLK_x = PLL2_VCO Output/PLL2P = 344/7 = 49.142 Mhz */
00628     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
00629     rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2;
00630     rcc_ex_clk_init_struct.PLL2.PLL2P = 7;
00631     rcc_ex_clk_init_struct.PLL2.PLL2Q = 1;
00632     rcc_ex_clk_init_struct.PLL2.PLL2R = 1;
00633     rcc_ex_clk_init_struct.PLL2.PLL2N = 344;
00634     rcc_ex_clk_init_struct.PLL2.PLL2M = 25;
00635     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
00636   }
00637 }
00638 /**
00639   * @}
00640   */
00641 
00642 /** @defgroup STM32H747I_DISCOVERY_AUDIO_OUT_Private_Functions OUT Private Functions
00643   * @{
00644   */
00645 
00646 /*******************************************************************************
00647                             HAL Callbacks
00648 *******************************************************************************/
00649 /**
00650   * @brief  Tx Transfer completed callbacks.
00651   * @param  hsai: SAI handle
00652   * @retval None
00653   */
00654 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
00655 {
00656   /* Manage the remaining file size and new address offset: This function
00657      should be coded by user (its prototype is already declared in stm32h747i_discovery_audio.h) */
00658   BSP_AUDIO_OUT_TransferComplete_CallBack();
00659 }
00660 
00661 /**
00662   * @brief  Tx Half Transfer completed callbacks.
00663   * @param  hsai: SAI handle
00664   * @retval None
00665   */
00666 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
00667 {
00668   /* Manage the remaining file size and new address offset: This function
00669      should be coded by user (its prototype is already declared in stm32h747i_discovery_audio.h) */
00670   BSP_AUDIO_OUT_HalfTransfer_CallBack();
00671 }
00672 
00673 /**
00674   * @brief  SAI error callbacks.
00675   * @param  hsai: SAI handle
00676   * @retval None
00677   */
00678 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
00679 {
00680   if(hsai->Instance == AUDIO_OUT_SAIx)
00681   {
00682     BSP_AUDIO_OUT_Error_CallBack();
00683   }
00684   else
00685   {
00686     BSP_AUDIO_IN_Error_CallBack();
00687   }
00688 }
00689 
00690 /*******************************************************************************
00691                             Static Functions
00692 *******************************************************************************/
00693 
00694 /**
00695   * @brief  Initializes the Audio Codec audio interface (SAI).
00696   * @param  SaiOutMode: Audio mode to be configured for the SAI peripheral.
00697   * @param  SlotActive: Audio active slot to be configured for the SAI peripheral.
00698   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00699   * @note   The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123
00700   *         and user can update this configuration using
00701   * @retval None
00702   */
00703 static void SAIx_Out_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq)
00704 {
00705   /* Disable SAI peripheral to allow access to SAI internal registers */
00706   __HAL_SAI_DISABLE(&haudio_out_sai);
00707 
00708   /* Configure SAI_Block_x
00709   LSBFirst: Disabled
00710   DataSize: 16 */
00711   haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE;
00712   haudio_out_sai.Init.AudioFrequency = AudioFreq;
00713   haudio_out_sai.Init.AudioMode = SaiOutMode;
00714   haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
00715   haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL;
00716   haudio_out_sai.Init.DataSize = SAI_DATASIZE_16;
00717   haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
00718   haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
00719   haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS;
00720   haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
00721   haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
00722   haudio_out_sai.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
00723   haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING;
00724   haudio_out_sai.Init.TriState       = SAI_OUTPUT_NOTRELEASED;
00725   haudio_out_sai.Init.Mckdiv         = 0;
00726   haudio_out_sai.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE;
00727   haudio_out_sai.Init.PdmInit.Activation = DISABLE;
00728   haudio_out_sai.Init.PdmInit.ClockEnable = 0;
00729   haudio_out_sai.Init.PdmInit.MicPairsNbr = 0;
00730 
00731   /* Configure SAI_Block_x Frame
00732   Frame Length: 64
00733   Frame active Length: 32
00734   FS Definition: Start frame + Channel Side identification
00735   FS Polarity: FS active Low
00736   FS Offset: FS asserted one bit before the first bit of slot 0 */
00737   haudio_out_sai.FrameInit.FrameLength = 128;
00738   haudio_out_sai.FrameInit.ActiveFrameLength = 64;
00739   haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
00740   haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
00741   haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
00742 
00743   /* Configure SAI Block_x Slot
00744   Slot First Bit Offset: 0
00745   Slot Size  : 16
00746   Slot Number: 4
00747   Slot Active: All slot actives */
00748   haudio_out_sai.SlotInit.FirstBitOffset = 0;
00749   haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
00750   haudio_out_sai.SlotInit.SlotNumber = 4;
00751   haudio_out_sai.SlotInit.SlotActive = SlotActive;
00752   HAL_SAI_Init(&haudio_out_sai);
00753 
00754   /* Enable SAI peripheral to generate MCLK */
00755   __HAL_SAI_ENABLE(&haudio_out_sai);
00756 }
00757 
00758 /**
00759   * @brief  Deinitializes the Audio Codec audio interface (SAI).
00760   * @retval None
00761   */
00762 static void SAIx_Out_DeInit(SAI_HandleTypeDef *hsai)
00763 {
00764   /* Disable SAI peripheral */
00765   __HAL_SAI_DISABLE(hsai);
00766 
00767   HAL_SAI_DeInit(hsai);
00768 }
00769 
00770 /**
00771   * @}
00772   */
00773 
00774 /** @defgroup STM32H747I_DISCOVERY_AUDIO_IN_Exported_Functions IN Exported Functions
00775   * @{
00776   */
00777 
00778 /**
00779   * @brief  Initialize wave recording.
00780   * @param  AudioFreq: Audio frequency to be configured for the DFSDM peripheral.
00781   * @param  BitRes: Audio frequency to be configured for the DFSDM peripheral.
00782   * @param  ChnlNbr: Audio frequency to be configured for the DFSDM peripheral.
00783   * @retval AUDIO_OK if correct communication, else wrong communication
00784   */
00785 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00786 {
00787   /* Set audio in interface to default one */
00788   BSP_AUDIO_IN_SelectInterface(AUDIO_IN_INTERFACE_PDM);
00789   return  BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC, AudioFreq, BitRes, ChnlNbr);
00790 }
00791 
00792 /**
00793   * @brief  Initialize wave recording.
00794   * @param  InputDevice: INPUT_DEVICE_DIGITAL_MIC or INPUT_DEVICE_ANALOG_MIC.
00795   * @param  AudioFreq: Audio frequency to be configured.
00796   * @param  BitRes: Audio bit resolution to be configured..
00797   * @param  ChnlNbr: Number of channel to be configured.
00798   * @retval AUDIO_OK if correct communication, else wrong communication
00799   */
00800 uint8_t BSP_AUDIO_IN_InitEx(uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00801 {
00802   uint8_t ret = AUDIO_OK;
00803   uint32_t slot_active;
00804 
00805   /* Store the audio record context */
00806   hAudioIn.Frequency     = AudioFreq;
00807   hAudioIn.BitResolution = BitRes;
00808   hAudioIn.InputDevice = InputDevice;
00809   hAudioIn.ChannelNbr = ChnlNbr;
00810 
00811   if(hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC)
00812   {
00813     if(hAudioIn.Interface == AUDIO_IN_INTERFACE_SAI)
00814     {
00815       /* Initialize SAI1 block B as SLAVE RX synchrounous with SAI1 block A */
00816       haudio_in_sai.Instance = AUDIO_IN_SAIx;
00817 
00818       /* Disable SAI */
00819       SAIx_In_DeInit(&haudio_in_sai);
00820 
00821       /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
00822       BSP_AUDIO_IN_ClockConfig(AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */
00823 
00824       /* SAI data transfer preparation:
00825       Prepare the Media to be used for the audio transfer from SAI peripheral to memory */
00826       if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET)
00827       {
00828         /* Init the SAI MSP: this __weak function can be redefined by the application*/
00829         BSP_AUDIO_IN_MspInit();
00830       }
00831 
00832       /* Configure SAI in master mode :
00833        *   - SAI1_block_B in slave RX mode synchronous from SAI1_block_A
00834        */
00835       slot_active = CODEC_AUDIOFRAME_SLOT_13;
00836       SAIx_In_Init(SAI_MODESLAVE_RX, slot_active, AudioFreq);
00837     }
00838     else if(hAudioIn.Interface == AUDIO_IN_INTERFACE_PDM)
00839     {
00840       /* Initialize SAI1 block A as MASTER RX */
00841       haudio_in_sai.Instance = AUDIO_IN_SAI_PDMx;
00842 
00843       /* Disable SAI */
00844       SAIx_In_DeInit(&haudio_in_sai);
00845 
00846       /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
00847       BSP_AUDIO_IN_ClockConfig(AudioFreq, NULL);
00848 
00849       /* SAI data transfer preparation:
00850       Prepare the Media to be used for the audio transfer from SAI peripheral to memory */
00851       /* Initialize the haudio_in_sai Instance parameter */
00852 
00853       if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET)
00854       {
00855         /* Init the SAI MSP: this __weak function can be redefined by the application*/
00856         BSP_AUDIO_IN_MspInit();
00857       }
00858 
00859       /* Configure SAI in master mode :
00860        *   - SAI1_block_A in master RX mode
00861        */
00862       slot_active = CODEC_AUDIOFRAME_SLOT_0;
00863       SAIx_In_Init(SAI_MODEMASTER_RX, slot_active, AudioFreq);
00864 
00865       if(BSP_AUDIO_IN_PDMToPCM_Init(AudioFreq, hAudioIn.ChannelNbr, hAudioIn.ChannelNbr) != AUDIO_OK)
00866       {
00867         ret = AUDIO_ERROR;
00868       }
00869     }
00870     else
00871     {
00872       ret = AUDIO_ERROR;
00873     }
00874   }
00875   else
00876   {
00877     /* Analog Input */
00878     ret = AUDIO_ERROR;
00879   }
00880 
00881   /* Return AUDIO_OK when all operations are correctly done */
00882   return ret;
00883 }
00884 
00885 
00886 /**
00887   * @brief  Initializes wave recording and playback in parallel.
00888   * @param  InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_2
00889   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
00890   *                       or OUTPUT_DEVICE_BOTH.
00891   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00892   * @param  BitRes: Audio frequency to be configured.
00893   * @param  ChnlNbr: Channel number.
00894   * @retval AUDIO_OK if correct communication, else wrong communication
00895   */
00896 uint8_t BSP_AUDIO_IN_OUT_Init(uint32_t InputDevice, uint32_t OutputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00897 {
00898   uint32_t slot_active;
00899   uint32_t deviceid = 0, ret = AUDIO_OK;
00900 
00901   /* Store the audio record context */
00902   hAudioIn.Frequency     = AudioFreq;
00903   hAudioIn.BitResolution = BitRes;
00904   hAudioIn.InputDevice = InputDevice;
00905   hAudioIn.ChannelNbr = ChnlNbr;
00906 
00907   /* Input device is Digital MIC2 and Codec interface is SAI */
00908   if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2)
00909   {
00910     haudio_in_sai.Instance = AUDIO_IN_SAIx;
00911     haudio_out_sai.Instance = AUDIO_OUT_SAIx;
00912 
00913     /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
00914     BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL);
00915     /* SAI data transfer preparation:
00916     Prepare the Media to be used for the audio transfer from SAI peripheral to memory */
00917     if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET)
00918     {
00919       /* Init the SAI MSP: this __weak function can be redefined by the application*/
00920       BSP_AUDIO_IN_MspInit();
00921     }
00922 
00923     /* SAI data transfer preparation:
00924     Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
00925     if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET)
00926     {
00927       /* Init the SAI MSP: this __weak function can be redefined by the application*/
00928       BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL);
00929     }
00930 
00931     /* Configure SAI in master TX mode :
00932     *   - SAI1_block_A in master TX mode
00933     *   - SAI1_block_B in slave RX mode synchronous from SAI1_block_A
00934     */
00935     slot_active = CODEC_AUDIOFRAME_SLOT_13;
00936     SAIx_In_Init(SAI_MODESLAVE_RX, slot_active, AudioFreq);
00937 
00938     slot_active = CODEC_AUDIOFRAME_SLOT_02;
00939     SAIx_Out_Init(SAI_MODEMASTER_TX, slot_active, AudioFreq);
00940 
00941     /* wm8994 codec initialization */
00942     deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
00943 
00944     if((deviceid) == WM8994_ID)
00945     {
00946       /* Reset the Codec Registers */
00947       wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
00948       /* Initialize the audio driver structure */
00949       audio_drv = &wm8994_drv;
00950       ret = AUDIO_OK;
00951     }
00952     else
00953     {
00954       ret = AUDIO_ERROR;
00955     }
00956 
00957     if(ret == AUDIO_OK)
00958     {
00959       /* Initialize the codec internal registers */
00960       audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice|OutputDevice, 90, AudioFreq);
00961     }
00962   }
00963   else
00964   {
00965     ret = AUDIO_ERROR;
00966   }
00967 
00968   /* Return AUDIO_OK when all operations are correctly done */
00969   return ret;
00970 }
00971 
00972 /**
00973   * @brief  Link digital mic to specified source
00974   * @param  Interface : Audio In interface for Digital mic. It can be:
00975   *                       AUDIO_IN_INTERFACE_SAI
00976   *                       AUDIO_IN_INTERFACE_PDM
00977   * @retval None
00978   */
00979 void BSP_AUDIO_IN_SelectInterface(uint32_t Interface)
00980 {
00981   hAudioIn.Interface = Interface;
00982 }
00983 
00984 /**
00985   * @brief  Get digital mic interface
00986   * @retval Digital mic interface.
00987   */
00988 uint32_t BSP_AUDIO_IN_GetInterface(void)
00989 {
00990   return (hAudioIn.Interface);
00991 }
00992 
00993 /**
00994   * @brief  Return audio in channel number
00995   * @retval Number of channel
00996   */
00997 uint8_t BSP_AUDIO_IN_GetChannelNumber(void)
00998 {
00999   return hAudioIn.ChannelNbr;
01000 }
01001 
01002 /**
01003   * @brief  Start audio recording.
01004   * @param  pBuf: Main buffer pointer for the recorded data storing
01005   * @param  size: Current size of the recorded buffer
01006   * @retval AUDIO_OK if correct communication, else wrong communication
01007   */
01008 uint8_t BSP_AUDIO_IN_Record(uint16_t *pBuf, uint32_t size)
01009 {
01010   /* Start the process receive DMA */
01011   if(HAL_OK != HAL_SAI_Receive_DMA(&haudio_in_sai, (uint8_t*)pBuf, size))
01012   {
01013     return AUDIO_ERROR;
01014   }
01015 
01016   /* Return AUDIO_OK when all operations are correctly done */
01017   return AUDIO_OK;
01018 }
01019 
01020 /**
01021   * @brief  Stop audio recording.
01022   * @retval AUDIO_OK if correct communication, else wrong communication
01023   */
01024 uint8_t BSP_AUDIO_IN_Stop(void)
01025 {
01026   /* Call the Media layer stop function */
01027   HAL_SAI_DMAStop(&haudio_in_sai);
01028   
01029   /* Return AUDIO_OK when all operations are correctly done */
01030   return AUDIO_OK;
01031 }
01032 
01033 /**
01034   * @brief  Pause the audio file stream.
01035   * @retval AUDIO_OK if correct communication, else wrong communication
01036   */
01037 uint8_t BSP_AUDIO_IN_Pause(void)
01038 {
01039   if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC)
01040   {
01041     return AUDIO_ERROR;
01042   }
01043   else
01044   {
01045      /* Call the Media layer pause function */
01046     HAL_SAI_DMAPause(&haudio_in_sai);
01047   }
01048   
01049   /* Return AUDIO_OK when all operations are correctly done */
01050   return AUDIO_OK;
01051 }
01052 
01053 /**
01054   * @brief  Resume the audio file stream.
01055   * @retval AUDIO_OK if correct communication, else wrong communication
01056   */
01057 uint8_t BSP_AUDIO_IN_Resume(void)
01058 {
01059   if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC)
01060   {
01061     return AUDIO_ERROR;
01062   }
01063   else
01064   {
01065      /* Call the Media layer resume function */
01066     HAL_SAI_DMAResume(&haudio_in_sai);
01067   }
01068   
01069   /* Return AUDIO_OK when all operations are correctly done */
01070   return AUDIO_OK;
01071 }
01072 
01073 /**
01074   * @brief  Controls the audio in volume level.
01075   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for
01076   *         Mute and 100 for Max volume level).
01077   * @retval AUDIO_OK if correct communication, else wrong communication
01078   */
01079 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume)
01080 {
01081   /* Set the Global variable AudioInVolume  */
01082   AudioInVolume = Volume;
01083 
01084   /* Return AUDIO_OK when all operations are correctly done */
01085   return AUDIO_OK;
01086 }
01087 
01088 /**
01089   * @brief  Deinit the audio IN peripherals.
01090   * @retval None
01091   */
01092 void BSP_AUDIO_IN_DeInit(void)
01093 {
01094   SAIx_In_DeInit(&haudio_in_sai);
01095   
01096   BSP_AUDIO_IN_MspDeInit();
01097 }
01098 
01099 /**
01100 * @brief  Initialize the PDM library.
01101 * @param  AudioFreq: Audio sampling frequency
01102 * @param  ChnlNbrIn: Number of input audio channels in the PDM buffer
01103 * @param  ChnlNbrOut: Number of desired output audio channels in the  resulting PCM buffer
01104 * @retval None
01105 */
01106 uint8_t BSP_AUDIO_IN_PDMToPCM_Init(uint32_t AudioFreq, uint32_t ChnlNbrIn, uint32_t ChnlNbrOut)
01107 {
01108   uint32_t index = 0;
01109 
01110   /* Enable CRC peripheral to unlock the PDM library */
01111   __HAL_RCC_CRC_CLK_ENABLE();
01112 
01113   for(index = 0; index < ChnlNbrIn; index++)
01114   {
01115     /* Init PDM filters */
01116     PDM_FilterHandler[index].bit_order  = PDM_FILTER_BIT_ORDER_MSB;
01117     PDM_FilterHandler[index].endianness = PDM_FILTER_ENDIANNESS_LE;
01118     PDM_FilterHandler[index].high_pass_tap = 2122358088;
01119     PDM_FilterHandler[index].out_ptr_channels = ChnlNbrOut;
01120     PDM_FilterHandler[index].in_ptr_channels  = ChnlNbrIn;
01121     PDM_Filter_Init((PDM_Filter_Handler_t *)(&PDM_FilterHandler[index]));
01122 
01123     /* PDM lib config phase */
01124     PDM_FilterConfig[index].output_samples_number = AudioFreq/1000;
01125     PDM_FilterConfig[index].mic_gain = 24;
01126     PDM_FilterConfig[index].decimation_factor = PDM_FILTER_DEC_FACTOR_64;
01127     PDM_Filter_setConfig((PDM_Filter_Handler_t *)&PDM_FilterHandler[index], &PDM_FilterConfig[index]);
01128   }
01129 
01130   return AUDIO_OK;
01131 }
01132 
01133 
01134 /**
01135 * @brief  Converts audio format from PDM to PCM.
01136 
01137 * @param  PDMBuf: Pointer to PDM buffer data
01138 * @param  PCMBuf: Pointer to PCM buffer data
01139 * @retval AUDIO_OK in case of success, AUDIO_ERROR otherwise
01140 */
01141 uint8_t BSP_AUDIO_IN_PDMToPCM(uint16_t *PDMBuf, uint16_t *PCMBuf)
01142 {
01143   uint32_t index = 0;
01144 
01145   for(index = 0; index < hAudioIn.ChannelNbr; index++)
01146   {
01147     PDM_Filter(&((uint8_t*)(PDMBuf))[index], (uint16_t*)&(PCMBuf[index]), &PDM_FilterHandler[index]);
01148   }
01149 
01150   return AUDIO_OK;
01151 }
01152 
01153 /**
01154   * @brief  User callback when record buffer is filled.
01155   * @retval None
01156   */
01157 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void)
01158 {
01159   /* This function should be implemented by the user application.
01160      It is called into this driver when the current buffer is filled
01161      to prepare the next buffer pointer and its size. */
01162 }
01163 
01164 /**
01165   * @brief  Manages the DMA Half Transfer complete event.
01166   * @retval None
01167   */
01168 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
01169 {
01170   /* This function should be implemented by the user application.
01171      It is called into this driver when the current buffer is filled
01172      to prepare the next buffer pointer and its size. */
01173 }
01174 
01175 /**
01176   * @brief  User callback when record buffer is filled.
01177   * @param  InputDevice: INPUT_DEVICE_DIGITAL_MIC1 or INPUT_DEVICE_DIGITAL_MIC2
01178   */
01179 __weak void BSP_AUDIO_IN_TransferComplete_CallBackEx(uint32_t InputDevice)
01180 {
01181   /* This function should be implemented by the user application.
01182      It is called into this driver when the current buffer is filled
01183      to prepare the next buffer pointer and its size. */
01184 }
01185 
01186 /**
01187   * @brief  User callback when record buffer is filled.
01188   * @param InputDevice: INPUT_DEVICE_DIGITAL_MIC1 or INPUT_DEVICE_DIGITAL_MIC2
01189   */
01190 __weak void BSP_AUDIO_IN_HalfTransfer_CallBackEx(uint32_t InputDevice)
01191 {
01192   /* This function should be implemented by the user application.
01193      It is called into this driver when the current buffer is filled
01194      to prepare the next buffer pointer and its size. */
01195 }
01196 
01197 /**
01198   * @brief  Audio IN Error callback function.
01199   * @retval None
01200   */
01201 __weak void BSP_AUDIO_IN_Error_CallBack(void)
01202 {
01203   /* This function is called when an Interrupt due to transfer error on or peripheral
01204      error occurs. */
01205 }
01206 
01207 /**
01208   * @brief  Initialize BSP_AUDIO_IN MSP.
01209   * @retval None
01210   */
01211 __weak void BSP_AUDIO_IN_MspInit(void)
01212 {
01213   SAIx_In_MspInit(&haudio_in_sai, NULL);
01214 }
01215 
01216 /**
01217   * @brief  DeInitialize BSP_AUDIO_IN MSP.
01218   * @retval None
01219   */
01220 __weak void BSP_AUDIO_IN_MspDeInit(void)
01221 {
01222   SAIx_In_MspDeInit(&haudio_in_sai, NULL);
01223 }
01224 
01225 /**
01226   * @brief  Clock Config.
01227   * @param  AudioFreq: Audio frequency used to play the audio stream.
01228   * @param  Params: pointer on additional configuration parameters, can be NULL.
01229   * @note   This API is called by BSP_AUDIO_IN_Init()
01230   *         Being __weak it can be overwritten by the application
01231   * @retval None
01232   */
01233 __weak void BSP_AUDIO_IN_ClockConfig(uint32_t AudioFreq, void *Params)
01234 {
01235   RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct;
01236 
01237   HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct);
01238 
01239   /* Set the PLL configuration according to the audio frequency */
01240   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
01241   {
01242     /* SAI clock config:
01243        PLL2_VCO Input = HSE_VALUE/PLL2M = 1 Mhz
01244        PLL2_VCO Output = PLL2_VCO Input * PLL2N = 429 Mhz
01245        SAI_CLK_x = PLL2_VCO Output/PLL2P = 429/38 = 11.289 Mhz */
01246     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
01247     rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2;
01248     rcc_ex_clk_init_struct.PLL2.PLL2P = 38;
01249     rcc_ex_clk_init_struct.PLL2.PLL2Q = 1;
01250     rcc_ex_clk_init_struct.PLL2.PLL2R = 1;
01251     rcc_ex_clk_init_struct.PLL2.PLL2N = 429;
01252     rcc_ex_clk_init_struct.PLL2.PLL2M = 25;
01253     if (hAudioIn.Interface == AUDIO_IN_INTERFACE_PDM)
01254     {
01255       rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI4A;
01256       rcc_ex_clk_init_struct.Sai4AClockSelection = RCC_SAI4ACLKSOURCE_PLL2;
01257     }
01258     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
01259 
01260   }
01261   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_32K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
01262   {
01263     /* SAI clock config:
01264        PLL2_VCO Input = HSE_VALUE/PLL2M = 1 Mhz
01265        PLL2_VCO Output = PLL2_VCO Input * PLL2N = 344 Mhz
01266        SAI_CLK_x = PLL2_VCO Output/PLL2P = 344/7 = 49.142 Mhz */
01267     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
01268     rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2;
01269     rcc_ex_clk_init_struct.PLL2.PLL2P = 7;
01270     rcc_ex_clk_init_struct.PLL2.PLL2Q = 1;
01271     rcc_ex_clk_init_struct.PLL2.PLL2R = 1;
01272     rcc_ex_clk_init_struct.PLL2.PLL2N = 344;
01273     rcc_ex_clk_init_struct.PLL2.PLL2M = 25;
01274     if (hAudioIn.Interface == AUDIO_IN_INTERFACE_PDM)
01275     {
01276       rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI4A;
01277       rcc_ex_clk_init_struct.Sai4AClockSelection = RCC_SAI4ACLKSOURCE_PLL2;
01278     }
01279     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
01280   }
01281 }
01282 /**
01283   * @}
01284   */
01285 
01286 
01287 /** @defgroup STM32H747I_DISCOVERY_AUDIO_IN_Private_Functions IN Private Functions
01288   * @{
01289   */
01290 
01291 /*******************************************************************************
01292                             HAL Callbacks
01293 *******************************************************************************/
01294 
01295 /**
01296   * @brief  Half reception complete callback.
01297   * @param  hsai: SAI handle.
01298   * @retval None
01299   */
01300 void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
01301 {
01302   /* Manage the remaining file size and new address offset: This function should be coded by user */
01303   BSP_AUDIO_IN_HalfTransfer_CallBack();
01304 }
01305 
01306 /**
01307   * @brief  Reception complete callback.
01308   * @param  hsai: SAI handle.
01309   * @retval None
01310   */
01311 void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
01312 {
01313   /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01314   BSP_AUDIO_IN_TransferComplete_CallBack();
01315 }
01316 
01317 /*******************************************************************************
01318                             Static Functions
01319 *******************************************************************************/
01320 /**
01321   * @brief  Initializes SAI Audio IN MSP.
01322   * @param  hsai: SAI handle
01323   * @param  Params: pointer on additional configuration parameters, can be NULL.
01324   * @retval None
01325   */
01326 static void SAIx_In_MspInit(SAI_HandleTypeDef *hsai, void *Params)
01327 {
01328   static DMA_HandleTypeDef hdma_sai_rx;
01329   GPIO_InitTypeDef  gpio_init_structure;
01330 
01331   if(hsai->Instance == AUDIO_IN_SAI_PDMx)
01332   {
01333      /* Enable SAI clock */
01334     AUDIO_IN_SAI_PDMx_CLK_ENABLE();
01335 
01336     AUDIO_IN_SAI_PDMx_CLK_IN_ENABLE();
01337     AUDIO_IN_SAI_PDMx_DATA_IN_ENABLE();
01338 
01339     gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_CLK_IN_PIN;
01340     gpio_init_structure.Mode = GPIO_MODE_AF_PP;
01341     gpio_init_structure.Pull = GPIO_NOPULL;
01342     gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH;
01343     gpio_init_structure.Alternate = AUDIO_IN_SAI_PDMx_DATA_CLK_AF;
01344     HAL_GPIO_Init(AUDIO_IN_SAI_PDMx_CLK_IN_PORT, &gpio_init_structure);
01345 
01346     gpio_init_structure.Pull = GPIO_PULLUP;
01347     gpio_init_structure.Speed = GPIO_SPEED_FREQ_MEDIUM;
01348     gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_DATA_IN_PIN;
01349     HAL_GPIO_Init(AUDIO_IN_SAI_PDMx_DATA_IN_PORT, &gpio_init_structure);
01350 
01351     AUDIO_IN_SAI_PDMx_FS_SCK_ENABLE();
01352 
01353     /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/
01354     gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_FS_PIN | AUDIO_IN_SAI_PDMx_SCK_PIN;
01355     gpio_init_structure.Mode = GPIO_MODE_AF_PP;
01356     gpio_init_structure.Pull = GPIO_NOPULL;
01357     gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH;
01358     gpio_init_structure.Alternate = AUDIO_IN_SAI_PDMx_FS_SCK_AF;
01359     HAL_GPIO_Init(AUDIO_IN_SAI_PDMx_FS_SCK_GPIO_PORT, &gpio_init_structure);
01360 
01361     /* Enable the DMA clock */
01362     AUDIO_IN_SAI_PDMx_DMAx_CLK_ENABLE();
01363 
01364     /* Configure the hdma_sai_rx handle parameters */
01365     hdma_sai_rx.Init.Request             = AUDIO_IN_SAI_PDMx_DMAx_REQUEST;
01366     hdma_sai_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
01367     hdma_sai_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
01368     hdma_sai_rx.Init.MemInc              = DMA_MINC_ENABLE;
01369     hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAI_PDMx_DMAx_PERIPH_DATA_SIZE;
01370     hdma_sai_rx.Init.MemDataAlignment    = AUDIO_IN_SAI_PDMx_DMAx_MEM_DATA_SIZE;
01371     hdma_sai_rx.Init.Mode                = DMA_CIRCULAR;
01372     hdma_sai_rx.Init.Priority            = DMA_PRIORITY_HIGH;
01373     hdma_sai_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
01374     hdma_sai_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
01375     hdma_sai_rx.Init.MemBurst            = DMA_MBURST_SINGLE;
01376     hdma_sai_rx.Init.PeriphBurst         = DMA_MBURST_SINGLE;
01377 
01378     hdma_sai_rx.Instance = AUDIO_IN_SAI_PDMx_DMAx_STREAM;
01379 
01380     /* Associate the DMA handle */
01381     __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx);
01382 
01383     /* Deinitialize the Stream for new transfer */
01384     HAL_DMA_DeInit(&hdma_sai_rx);
01385 
01386     /* Configure the DMA Stream */
01387     HAL_DMA_Init(&hdma_sai_rx);
01388 
01389     /* SAI DMA IRQ Channel configuration */
01390     HAL_NVIC_SetPriority(AUDIO_IN_SAI_PDMx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
01391     HAL_NVIC_EnableIRQ(AUDIO_IN_SAI_PDMx_DMAx_IRQ);
01392   }
01393   else
01394   {
01395     /* Enable SAI clock */
01396     AUDIO_IN_SAIx_CLK_ENABLE();
01397 
01398     /* Enable SD GPIO clock */
01399     AUDIO_IN_SAIx_SD_ENABLE();
01400     /* CODEC_SAI pin configuration: SD pin */
01401     gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN;
01402     gpio_init_structure.Mode = GPIO_MODE_AF_PP;
01403     gpio_init_structure.Pull = GPIO_NOPULL;
01404     gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH;
01405     gpio_init_structure.Alternate = AUDIO_IN_SAIx_AF;
01406     HAL_GPIO_Init(AUDIO_IN_SAIx_SD_GPIO_PORT, &gpio_init_structure);
01407 
01408     /* Enable Audio INT GPIO clock */
01409     AUDIO_IN_INT_GPIO_ENABLE();
01410     /* Audio INT pin configuration: input */
01411     gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN;
01412     gpio_init_structure.Mode = GPIO_MODE_INPUT;
01413     gpio_init_structure.Pull = GPIO_NOPULL;
01414     gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH;
01415     HAL_GPIO_Init(AUDIO_IN_INT_GPIO_PORT, &gpio_init_structure);
01416 
01417     /* Enable the DMA clock */
01418     AUDIO_IN_SAIx_DMAx_CLK_ENABLE();
01419 
01420     /* Configure the hdma_sai_rx handle parameters */
01421     hdma_sai_rx.Init.Request             = AUDIO_IN_SAIx_DMAx_REQUEST;
01422     hdma_sai_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
01423     hdma_sai_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
01424     hdma_sai_rx.Init.MemInc              = DMA_MINC_ENABLE;
01425     hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAIx_DMAx_PERIPH_DATA_SIZE;
01426     hdma_sai_rx.Init.MemDataAlignment    = AUDIO_IN_SAIx_DMAx_MEM_DATA_SIZE;
01427     hdma_sai_rx.Init.Mode                = DMA_CIRCULAR;
01428     hdma_sai_rx.Init.Priority            = DMA_PRIORITY_HIGH;
01429     hdma_sai_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
01430     hdma_sai_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
01431     hdma_sai_rx.Init.MemBurst            = DMA_MBURST_SINGLE;
01432     hdma_sai_rx.Init.PeriphBurst         = DMA_MBURST_SINGLE;
01433 
01434     hdma_sai_rx.Instance = AUDIO_IN_SAIx_DMAx_STREAM;
01435 
01436     /* Associate the DMA handle */
01437     __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx);
01438 
01439     /* Deinitialize the Stream for new transfer */
01440     HAL_DMA_DeInit(&hdma_sai_rx);
01441 
01442     /* Configure the DMA Stream */
01443     HAL_DMA_Init(&hdma_sai_rx);
01444 
01445     /* SAI DMA IRQ Channel configuration */
01446     HAL_NVIC_SetPriority(AUDIO_IN_SAIx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
01447     HAL_NVIC_EnableIRQ(AUDIO_IN_SAIx_DMAx_IRQ);
01448 
01449     /* Audio INT IRQ Channel configuration */
01450     HAL_NVIC_SetPriority(AUDIO_IN_INT_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
01451     HAL_NVIC_EnableIRQ(AUDIO_IN_INT_IRQ);
01452   }
01453 }
01454 
01455 /**
01456   * @brief  De-Initializes SAI Audio IN MSP.
01457   * @param  hsai: SAI handle
01458   * @param  Params: pointer on additional configuration parameters, can be NULL.
01459   * @retval None
01460   */
01461 static void SAIx_In_MspDeInit(SAI_HandleTypeDef *hsai, void *Params)
01462 {
01463   GPIO_InitTypeDef  gpio_init_structure;
01464 
01465   if(hsai->Instance == AUDIO_IN_SAI_PDMx)
01466   {
01467     /* Deinitialize the DMA stream */
01468     HAL_DMA_Abort(hsai->hdmarx);
01469 
01470     HAL_SAI_DeInit(hsai);
01471     /* Disable SAI peripheral */
01472     __HAL_SAI_DISABLE(hsai);
01473 
01474     /* Deinitialize the DMA stream */
01475     HAL_DMA_DeInit(hsai->hdmarx);
01476 
01477     gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_CLK_IN_PIN;
01478     HAL_GPIO_DeInit(AUDIO_IN_SAI_PDMx_CLK_IN_PORT, gpio_init_structure.Pin);
01479 
01480     gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_DATA_IN_PIN;
01481     HAL_GPIO_DeInit(AUDIO_IN_SAI_PDMx_DATA_IN_PORT, gpio_init_structure.Pin);
01482 
01483     /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/
01484     gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_FS_PIN | AUDIO_IN_SAI_PDMx_SCK_PIN;
01485     HAL_GPIO_DeInit(AUDIO_IN_SAI_PDMx_FS_SCK_GPIO_PORT, gpio_init_structure.Pin);
01486 
01487     /* Disable SAI clock */
01488     AUDIO_IN_SAI_PDMx_CLK_DISABLE();
01489   }
01490   else
01491   {
01492     /* SAI DMA IRQ Channel deactivation */
01493     HAL_NVIC_DisableIRQ(AUDIO_IN_SAIx_DMAx_IRQ);
01494 
01495     if(hsai->Instance == AUDIO_IN_SAIx)
01496     {
01497       /* Deinitialize the DMA stream */
01498       HAL_DMA_DeInit(hsai->hdmatx);
01499     }
01500 
01501     /* Disable SAI peripheral */
01502     __HAL_SAI_DISABLE(hsai);
01503 
01504     /* Deactivates CODEC_SAI pin SD by putting them in input mode */
01505     gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN;
01506     HAL_GPIO_DeInit(AUDIO_IN_SAIx_SD_GPIO_PORT, gpio_init_structure.Pin);
01507 
01508     gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN;
01509     HAL_GPIO_DeInit(AUDIO_IN_INT_GPIO_PORT, gpio_init_structure.Pin);
01510 
01511     /* Disable SAI clock */
01512     AUDIO_IN_SAIx_CLK_DISABLE();
01513   }
01514 }
01515 
01516 /**
01517   * @brief  Initializes the Audio Codec audio interface (SAI).
01518   * @param  SaiInMode: Audio mode to be configured for the SAI peripheral.
01519   * @param  SlotActive: Audio active slot to be configured for the SAI peripheral.
01520   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
01521   * @retval None
01522   */
01523 static void SAIx_In_Init(uint32_t SaiInMode, uint32_t SlotActive, uint32_t AudioFreq)
01524 {
01525   /* Disable SAI peripheral to allow access to SAI internal registers */
01526   __HAL_SAI_DISABLE(&haudio_in_sai);
01527 
01528   /* Configure SAI_Block_x
01529   LSBFirst: Disabled
01530   DataSize: 16 */
01531   haudio_in_sai.Init.MonoStereoMode = SAI_STEREOMODE;
01532   haudio_in_sai.Init.AudioFrequency = AudioFreq;
01533   haudio_in_sai.Init.AudioMode      = SaiInMode;
01534   haudio_in_sai.Init.NoDivider      = SAI_MASTERDIVIDER_ENABLE;
01535   haudio_in_sai.Init.Protocol       = SAI_FREE_PROTOCOL;
01536   haudio_in_sai.Init.DataSize       = SAI_DATASIZE_16;
01537   haudio_in_sai.Init.FirstBit       = SAI_FIRSTBIT_MSB;
01538   haudio_in_sai.Init.ClockStrobing  = SAI_CLOCKSTROBING_RISINGEDGE;
01539   haudio_in_sai.Init.Synchro        = SAI_SYNCHRONOUS;
01540   haudio_in_sai.Init.OutputDrive    = SAI_OUTPUTDRIVE_DISABLE;
01541   haudio_in_sai.Init.FIFOThreshold  = SAI_FIFOTHRESHOLD_1QF;
01542   haudio_in_sai.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
01543   haudio_in_sai.Init.CompandingMode = SAI_NOCOMPANDING;
01544   haudio_in_sai.Init.TriState       = SAI_OUTPUT_RELEASED;
01545   haudio_in_sai.Init.Mckdiv         = 0;
01546   haudio_in_sai.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE;
01547   haudio_in_sai.Init.PdmInit.Activation  = DISABLE;
01548 
01549   /* Configure SAI_Block_x Frame
01550   Frame Length: 64
01551   Frame active Length: 32
01552   FS Definition: Start frame + Channel Side identification
01553   FS Polarity: FS active Low
01554   FS Offset: FS asserted one bit before the first bit of slot 0 */
01555   haudio_in_sai.FrameInit.FrameLength       = 128;
01556   haudio_in_sai.FrameInit.ActiveFrameLength = 64;
01557   haudio_in_sai.FrameInit.FSDefinition      = SAI_FS_CHANNEL_IDENTIFICATION;
01558   haudio_in_sai.FrameInit.FSPolarity        = SAI_FS_ACTIVE_LOW;
01559   haudio_in_sai.FrameInit.FSOffset          = SAI_FS_BEFOREFIRSTBIT;
01560 
01561   /* Configure SAI Block_x Slot
01562   Slot First Bit Offset: 0
01563   Slot Size  : 16
01564   Slot Number: 4
01565   Slot Active: All slot active */
01566   haudio_in_sai.SlotInit.FirstBitOffset = 0;
01567   haudio_in_sai.SlotInit.SlotSize       = SAI_SLOTSIZE_DATASIZE;
01568   haudio_in_sai.SlotInit.SlotNumber     = 4;
01569   haudio_in_sai.SlotInit.SlotActive     = SlotActive;
01570 
01571   if(hAudioIn.Interface == AUDIO_IN_INTERFACE_PDM)
01572   {
01573     haudio_in_sai.Init.AudioFrequency      = AudioFreq * 8;
01574     haudio_in_sai.Init.Synchro             = SAI_ASYNCHRONOUS;
01575     haudio_in_sai.Init.NoDivider           = SAI_MASTERDIVIDER_DISABLE;
01576 
01577     haudio_in_sai.Init.PdmInit.Activation  = ENABLE;
01578     haudio_in_sai.Init.PdmInit.MicPairsNbr = 1;
01579     haudio_in_sai.Init.PdmInit.ClockEnable = SAI_PDM_CLOCK1_ENABLE;
01580     haudio_in_sai.Init.FirstBit            = SAI_FIRSTBIT_LSB;
01581     haudio_in_sai.Init.ClockStrobing       = SAI_CLOCKSTROBING_FALLINGEDGE;
01582 
01583     haudio_in_sai.FrameInit.FrameLength       = 16;
01584     haudio_in_sai.FrameInit.ActiveFrameLength = 1;
01585     haudio_in_sai.FrameInit.FSDefinition      = SAI_FS_STARTFRAME;
01586     haudio_in_sai.FrameInit.FSPolarity        = SAI_FS_ACTIVE_HIGH;
01587     haudio_in_sai.FrameInit.FSOffset          = SAI_FS_FIRSTBIT;
01588 
01589     haudio_in_sai.SlotInit.SlotNumber     = 1;
01590     haudio_in_sai.SlotInit.SlotActive     = SlotActive;
01591   }
01592 
01593   HAL_SAI_Init(&haudio_in_sai);
01594 
01595   /* Enable SAI peripheral */
01596   __HAL_SAI_ENABLE(&haudio_in_sai);
01597 }
01598 
01599 /**
01600   * @brief  De-initializes the output Audio Codec audio interface (SAI).
01601   * @retval None
01602   */
01603 static void SAIx_In_DeInit(SAI_HandleTypeDef *hsai)
01604 {
01605   /* Disable SAI peripheral */
01606   __HAL_SAI_DISABLE(hsai);
01607 
01608   HAL_SAI_DeInit(hsai);
01609 }
01610 
01611 /**
01612   * @}
01613   */
01614 
01615 /**
01616   * @}
01617   */
01618 
01619 /**
01620   * @}
01621   */
01622 
01623 /**
01624   * @}
01625   */
01626 
01627 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/