Daniel Lee / BSP_DISCO_F413ZH

Dependents:   DISCO_F413ZH-AUDIO-demo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32f413h_discovery_audio.c Source File

stm32f413h_discovery_audio.c

00001 /**
00002   ******************************************************************************
00003   * @file    STM32f413h_discovery_audio.c
00004   * @author  MCD Application Team
00005   * @brief   This file provides the Audio driver for the STM32F413H-DISCOVERY board.
00006   ******************************************************************************
00007   * @attention
00008   *
00009   * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
00010   *
00011   * Redistribution and use in source and binary forms, with or without modification,
00012   * are permitted provided that the following conditions are met:
00013   *   1. Redistributions of source code must retain the above copyright notice,
00014   *      this list of conditions and the following disclaimer.
00015   *   2. Redistributions in binary form must reproduce the above copyright notice,
00016   *      this list of conditions and the following disclaimer in the documentation
00017   *      and/or other materials provided with the distribution.
00018   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00019   *      may be used to endorse or promote products derived from this software
00020   *      without specific prior written permission.
00021   *
00022   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00023   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00025   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00026   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00028   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00030   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00031   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032   *
00033   ******************************************************************************
00034   */
00035 
00036 /*==============================================================================
00037                                  User NOTES
00038                                  
00039 How To use this driver:
00040 -----------------------
00041    + This driver supports STM32F4xx devices on STM32F413H-DISCOVERY boards.
00042    + Call the function BSP_AUDIO_OUT_Init(
00043                                     OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 
00044                                                   OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH)
00045                                     Volume      : Initial volume to be set (0 is min (mute), 100 is max (100%)
00046                                     AudioFreq   : Audio frequency in Hz (8000, 16000, 22500, 32000...)
00047                                                   this parameter is relative to the audio file/stream type.
00048                                    )
00049       This function configures all the hardware required for the audio application (codec, I2C, I2S, 
00050       GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK.
00051       If the returned value is different from AUDIO_OK or the function is stuck then the communication with
00052       the codec has failed (try to un-plug the power or reset device in this case).
00053       - OUTPUT_DEVICE_SPEAKER  : only speaker will be set as output for the audio stream.
00054       - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream.
00055       - OUTPUT_DEVICE_BOTH     : both Speaker and Headphone are used as outputs for the audio stream
00056                                  at the same time.
00057    + Call the function BSP_AUDIO_OUT_Play(
00058                                   pBuffer: pointer to the audio data file address
00059                                   Size   : size of the buffer to be sent in Bytes
00060                                  )
00061       to start playing (for the first time) from the audio file/stream.
00062    + Call the function BSP_AUDIO_OUT_Pause() to pause playing   
00063    + Call the function BSP_AUDIO_OUT_Resume() to resume playing.
00064        Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called
00065           for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case).
00066        Note. This function should be called only when the audio file is played or paused (not stopped).
00067    + For each mode, you may need to implement the relative callback functions into your code.
00068       The Callback functions are named AUDIO_OUT_XXX_CallBack() and only their prototypes are declared in 
00069       the STM32F413H_discovery_audio.h file. (refer to the example for more details on the callbacks implementations)
00070    + To Stop playing, to modify the volume level, the frequency, use the functions: BSP_AUDIO_OUT_SetVolume(), 
00071       AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetOutputMode(), BSP_AUDIO_OUT_SetMute() and BSP_AUDIO_OUT_Stop().
00072    + The driver API and the callback functions are at the end of the STM32F413H_discovery_audio.h file.
00073  
00074 
00075 Driver architecture:
00076 --------------------
00077    + This driver provides the High Audio Layer: consists of the function API exported in the stm32f413h_discovery_audio.h file
00078      (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...)
00079    + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/
00080      providing the audio file/stream. These functions are also included as local functions into
00081      the stm32f413h_discovery_audio_codec.c file (I2Sx_Out_Init(), I2Sx_Out_DeInit(), I2Sx_In_Init() and I2Sx_In_DeInit())
00082 
00083 Known Limitations:
00084 ------------------
00085    1- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second 
00086       Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams.
00087    2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 
00088       File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file.
00089    3- Supports only Stereo audio streaming.
00090    4- Supports only 16-bits audio data size.
00091 ==============================================================================*/
00092 
00093 /* Includes ------------------------------------------------------------------*/
00094 #include "stm32f413h_discovery_audio.h"
00095 
00096 /** @addtogroup BSP
00097   * @{
00098   */
00099 
00100 /** @addtogroup STM32F413H_DISCOVERY
00101   * @{
00102   */ 
00103   
00104 /** @defgroup STM32F413H_DISCOVERY_AUDIO STM32F413H_DISCOVERY AUDIO
00105   * @brief This file includes the low layer driver for wm8994 Audio Codec
00106   *        available on STM32F413H-DISCOVERY board(MB1209).
00107   * @{
00108   */ 
00109 
00110 /** @defgroup STM32F413H_DISCOVERY_AUDIO_Private_Macros STM32F413H DISCOVERY Audio Private macros 
00111   * @{
00112   */
00113 
00114 #define DFSDM_OVER_SAMPLING(__FREQUENCY__) \
00115         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 256 \
00116       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \
00117       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \
00118       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \
00119       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \
00120       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64  \
00121       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 25  \
00122 
00123 #define DFSDM_CLOCK_DIVIDER(__FREQUENCY__) \
00124         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 24 \
00125       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 48 \
00126       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \
00127       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 48 \
00128       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \
00129       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 48  \
00130       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 72  \
00131         
00132 #define DFSDM_FILTER_ORDER(__FREQUENCY__) \
00133         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? DFSDM_FILTER_SINC3_ORDER \
00134       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \
00135       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \
00136       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \
00137       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \
00138       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC4_ORDER  \
00139       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC4_ORDER : DFSDM_FILTER_SINC4_ORDER  \
00140 
00141 #define DFSDM_MIC_BIT_SHIFT(__FREQUENCY__) \
00142         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 5 \
00143       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \
00144       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 2 \
00145       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 2 \
00146       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 5 \
00147       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 6  \
00148       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 2 : 0  \
00149         
00150 /* Saturate the record PCM sample */
00151 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N)))
00152 /**
00153   * @}
00154   */ 
00155   
00156 /** @defgroup STM32F413H_DISCOVERY_AUDIO_Private_Variables STM32F413H DISCOVERY Audio Private Variables
00157   * @{
00158   */
00159 
00160 AUDIO_DrvTypeDef                *audio_drv;
00161 I2S_HandleTypeDef               haudio_i2s;       /* for Audio_OUT and Audio_IN_analog mic */
00162 I2S_HandleTypeDef               haudio_in_i2sext; /* for Analog mic with full duplex mode  */
00163 AUDIOIN_ContextTypeDef          hAudioIn;
00164 
00165 DFSDM_Channel_HandleTypeDef     hAudioInDfsdmChannel[DFSDM_MIC_NUMBER];  /* 5 DFSDM channel handle used for all microphones */
00166 DFSDM_Filter_HandleTypeDef      hAudioInDfsdmFilter[DFSDM_MIC_NUMBER];   /* 5 DFSDM filter handle */
00167 DMA_HandleTypeDef               hDmaDfsdm[DFSDM_MIC_NUMBER];             /* 5 DMA handle used for DFSDM regular conversions */
00168 
00169 /* Buffers for right and left samples */
00170 int32_t                         *pScratchBuff[DEFAULT_AUDIO_IN_CHANNEL_NBR];
00171 uint32_t                         ScratchSize;
00172 
00173 uint32_t                        DmaRecHalfBuffCplt[DFSDM_MIC_NUMBER]  = {0};
00174 uint32_t                        DmaRecBuffCplt[DFSDM_MIC_NUMBER]  = {0};
00175 
00176 /* Application Buffer Trigger */
00177 __IO uint32_t                   AppBuffTrigger          = 0;
00178 __IO uint32_t                   AppBuffHalf             = 0;
00179 __IO uint32_t                   MicBuff[DFSDM_MIC_NUMBER] = {0};
00180 __IO uint16_t                   AudioInVolume = DEFAULT_AUDIO_IN_VOLUME; 
00181 
00182 /**
00183   * @}
00184   */ 
00185 
00186 /** @defgroup STM32F413H_DISCOVERY_AUDIO_Private_Function_Prototypes STM32F413H DISCOVERY Audio Private Prototypes
00187   * @{
00188   */
00189 static void I2Sx_In_Init(uint32_t AudioFreq);
00190 static void I2Sx_In_DeInit(void);
00191 static void I2Sx_In_MspInit(void);
00192 static void I2Sx_In_MspDeInit(void);
00193 
00194 static void I2Sx_Out_Init(uint32_t AudioFreq);
00195 static void I2Sx_Out_DeInit(void);
00196 
00197 static uint8_t DFSDMx_DeInit(void);
00198 static void DFSDMx_ChannelMspInit(void);
00199 static void DFSDMx_ChannelMspDeInit(void);
00200 static void DFSDMx_FilterMspInit(void);
00201 static void DFSDMx_FilterMspDeInit(void);
00202 
00203 /**
00204   * @}
00205   */ 
00206 
00207 /** @defgroup STM32F413H_DISCOVERY_AUDIO_out_Private_Functions STM32F413H DISCOVERY AUDIO OUT Private Functions
00208   * @{
00209   */ 
00210 
00211 /**
00212   * @brief  Configures the audio peripherals.
00213   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
00214   *                       or OUTPUT_DEVICE_BOTH.
00215   * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
00216   * @param  AudioFreq: Audio frequency used to play the audio stream.
00217   * @note   The I2S PLL input clock must be done in the user application.  
00218   * @retval AUDIO_OK if correct communication, else wrong communication
00219   */
00220 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
00221 { 
00222   uint8_t  ret = AUDIO_ERROR;
00223   uint32_t deviceid = 0x00;
00224   uint16_t buffer_fake[16] = {0x00};
00225 
00226   I2Sx_Out_DeInit();
00227   AUDIO_IO_DeInit();
00228   
00229   /* PLL clock is set depending on the AudioFreq (44.1 kHz vs 48kHz groups) */
00230   BSP_AUDIO_OUT_ClockConfig(&haudio_i2s, AudioFreq, NULL);
00231   
00232   /* Configure the I2S peripheral */
00233   haudio_i2s.Instance = AUDIO_OUT_I2Sx;
00234   if(HAL_I2S_GetState(&haudio_i2s) == HAL_I2S_STATE_RESET)
00235   {
00236     /* Initialize the I2S Msp: this __weak function can be rewritten by the application */
00237     BSP_AUDIO_OUT_MspInit(&haudio_i2s, NULL);
00238   }
00239   I2Sx_Out_Init(AudioFreq);
00240 
00241   AUDIO_IO_Init();
00242 
00243   /* wm8994 codec initialization */
00244   deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
00245 
00246   if(deviceid == WM8994_ID)
00247   {
00248     /* Reset the Codec Registers */
00249     wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
00250     /* Initialize the audio driver structure */
00251     audio_drv = &wm8994_drv;
00252     ret = AUDIO_OK;
00253   }
00254   else
00255   {
00256     ret = AUDIO_ERROR;
00257   }
00258 
00259   if(ret == AUDIO_OK)
00260   {
00261     /* Send fake I2S data in order to generate MCLK needed by WM8994 to set its registers
00262      * MCLK is generated only when a data stream is sent on I2S */
00263     HAL_I2S_Transmit_DMA(&haudio_i2s, buffer_fake, 16);
00264     /* Initialize the codec internal registers */
00265     audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq);
00266     /* Stop sending fake I2S data */
00267     HAL_I2S_DMAStop(&haudio_i2s);
00268   }
00269 
00270   return ret;
00271 }
00272 
00273 /**
00274   * @brief  Starts playing audio stream from a data buffer for a determined size. 
00275   * @param  pBuffer: Pointer to the buffer 
00276   * @param  Size: Number of audio data BYTES.
00277   * @retval AUDIO_OK if correct communication, else wrong communication
00278   */
00279 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size)
00280 {
00281   /* Call the audio Codec Play function */
00282   if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0)
00283   {  
00284     return AUDIO_ERROR;
00285   }
00286   else
00287   {
00288     /* Update the Media layer and enable it for play */  
00289     HAL_I2S_Transmit_DMA(&haudio_i2s, pBuffer, DMA_MAX(Size / AUDIODATA_SIZE));
00290     
00291     return AUDIO_OK;
00292   }
00293 }
00294 
00295 /**
00296   * @brief  Sends n-Bytes on the I2S interface.
00297   * @param  pData: pointer on data address 
00298   * @param  Size: number of data to be written
00299   */
00300 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size)
00301 {
00302    HAL_I2S_Transmit_DMA(&haudio_i2s, pData, Size);
00303 }
00304 
00305 /**
00306   * @brief  This function Pauses the audio file stream. In case
00307   *         of using DMA, the DMA Pause feature is used.
00308   * @note   When calling BSP_AUDIO_OUT_Pause() function for pause, only
00309   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00310   *          function for resume could lead to unexpected behavior).
00311   * @retval AUDIO_OK if correct communication, else wrong communication
00312   */
00313 uint8_t BSP_AUDIO_OUT_Pause(void)
00314 {    
00315   /* Call the Audio Codec Pause/Resume function */
00316   if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0)
00317   {
00318     return AUDIO_ERROR;
00319   }
00320   else
00321   {
00322     /* Call the Media layer pause function */
00323     HAL_I2S_DMAPause(&haudio_i2s);
00324     
00325     /* Return AUDIO_OK when all operations are correctly done */
00326     return AUDIO_OK;
00327   }
00328 }
00329 
00330 /**
00331   * @brief  This function  Resumes the audio file stream.  
00332   * @note   When calling BSP_AUDIO_OUT_Pause() function for pause, only
00333   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00334   *          function for resume could lead to unexpected behavior).
00335   * @retval AUDIO_OK if correct communication, else wrong communication
00336   */
00337 uint8_t BSP_AUDIO_OUT_Resume(void)
00338 {    
00339   /* Call the Media layer pause/resume function */
00340   /* DMA stream resumed before accessing WM8994 register as WM8994 needs the MCLK to be generated to access its registers
00341    * MCLK is generated only when a data stream is sent on I2S */
00342   HAL_I2S_DMAResume(&haudio_i2s);
00343 
00344   /* Call the Audio Codec Pause/Resume function */
00345   if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0)
00346   {
00347     return AUDIO_ERROR;
00348   }
00349   else
00350   {
00351     /* Return AUDIO_OK when all operations are correctly done */
00352     return AUDIO_OK;
00353   }
00354 }
00355 
00356 /**
00357   * @brief  Stops audio playing and Power down the Audio Codec. 
00358   * @param  Option: could be one of the following parameters 
00359   *           - CODEC_PDWN_SW: for software power off (by writing registers). 
00360   *                            Then no need to reconfigure the Codec after power on.
00361   *           - CODEC_PDWN_HW: completely shut down the codec (physically). 
00362   *                            Then need to reconfigure the Codec after power on.  
00363   * @retval AUDIO_OK if correct communication, else wrong communication
00364   */
00365 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
00366 {
00367   /* Call the Media layer stop function */
00368   HAL_I2S_DMAStop(&haudio_i2s);
00369 
00370   /* Call Audio Codec Stop function */
00371   if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
00372   {
00373     return AUDIO_ERROR;
00374   }
00375   else
00376   {
00377     if(Option == CODEC_PDWN_HW)
00378     { 
00379       /* Wait at least 100us */
00380       HAL_Delay(1);
00381     }
00382     /* Return AUDIO_OK when all operations are correctly done */
00383     return AUDIO_OK;
00384   }
00385 }
00386 
00387 /**
00388   * @brief  Controls the current audio volume level. 
00389   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for 
00390   *         Mute and 100 for Max volume level).
00391   * @retval AUDIO_OK if correct communication, else wrong communication
00392   */
00393 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume)
00394 {
00395   /* Call the codec volume control function with converted volume value */
00396   if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
00397   {
00398     return AUDIO_ERROR;
00399   }
00400   else
00401   {
00402     /* Return AUDIO_OK when all operations are correctly done */
00403     return AUDIO_OK;
00404   }
00405 }
00406 
00407 /**
00408   * @brief  Enables or disables the MUTE mode by software 
00409   * @param  Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 
00410   *         unmute the codec and restore previous volume level.
00411   * @retval AUDIO_OK if correct communication, else wrong communication
00412   */
00413 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd)
00414 { 
00415   /* Call the Codec Mute function */
00416   if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0)
00417   {
00418     return AUDIO_ERROR;
00419   }
00420   else
00421   {
00422     /* Return AUDIO_OK when all operations are correctly done */
00423     return AUDIO_OK;
00424   }
00425 }
00426 
00427 /**
00428   * @brief  Switch dynamically (while audio file is played) the output target 
00429   *         (speaker or headphone).
00430   * @param  Output: The audio output target: OUTPUT_DEVICE_SPEAKER,
00431   *         OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH
00432   * @retval AUDIO_OK if correct communication, else wrong communication
00433   */
00434 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)
00435 {
00436   /* Call the Codec output device function */
00437   if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0)
00438   {
00439     return AUDIO_ERROR;
00440   }
00441   else
00442   {
00443     /* Return AUDIO_OK when all operations are correctly done */
00444     return AUDIO_OK;
00445   }
00446 }
00447 
00448 /**
00449   * @brief  Updates the audio frequency.
00450   * @param  AudioFreq: Audio frequency used to play the audio stream.
00451   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00452   *         audio frequency.
00453   * @retval None
00454   */
00455 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)
00456 { 
00457   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
00458   BSP_AUDIO_OUT_ClockConfig(&haudio_i2s, AudioFreq, NULL);
00459 
00460   /* Disable I2S peripheral to allow access to I2S internal registers */
00461   __HAL_I2S_DISABLE(&haudio_i2s);
00462     
00463   /* Update the I2S audio frequency configuration */
00464   haudio_i2s.Init.AudioFreq = AudioFreq;
00465   HAL_I2S_Init(&haudio_i2s);
00466   
00467   /* Enable I2S peripheral to generate MCLK */
00468   __HAL_I2S_ENABLE(&haudio_i2s);
00469 }
00470 
00471 /**
00472   * @brief  Deinit the audio peripherals.
00473   */
00474 void BSP_AUDIO_OUT_DeInit(void)
00475 {
00476   I2Sx_Out_DeInit();
00477   /* DeInit the I2S MSP : this __weak function can be rewritten by the application */
00478   BSP_AUDIO_OUT_MspDeInit(&haudio_i2s, NULL);
00479 }
00480 
00481 /**
00482   * @brief  Tx Transfer completed callbacks.
00483   * @param  hi2s: I2S handle
00484   */
00485 void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
00486 {
00487   /* Manage the remaining file size and new address offset: This function 
00488      should be coded by user (its prototype is already declared in STM32F413H_discovery_audio.h) */
00489   BSP_AUDIO_OUT_TransferComplete_CallBack();
00490 }
00491 
00492 /**
00493   * @brief  Tx Half Transfer completed callbacks.
00494   * @param  hi2s: I2S handle
00495   */
00496 void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
00497 {
00498   /* Manage the remaining file size and new address offset: This function 
00499      should be coded by user (its prototype is already declared in STM32F413H_discovery_audio.h) */
00500   BSP_AUDIO_OUT_HalfTransfer_CallBack();
00501 }
00502 
00503 /**
00504   * @brief  I2S error callbacks.
00505   * @param  hi2s: I2S handle
00506   */
00507 void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s)
00508 {
00509   BSP_AUDIO_OUT_Error_CallBack();
00510 }
00511 
00512 /**
00513   * @brief  Manages the DMA full Transfer complete event.
00514   */
00515 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
00516 {
00517 }
00518 
00519 /**
00520   * @brief  Manages the DMA Half Transfer complete event.
00521   */
00522 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void)
00523 { 
00524 }
00525 
00526 /**
00527   * @brief  Manages the DMA FIFO error event.
00528   */
00529 __weak void BSP_AUDIO_OUT_Error_CallBack(void)
00530 {
00531 }
00532 
00533 /**
00534   * @brief  Initializes BSP_AUDIO_OUT MSP.
00535   * @param  hi2s: I2S handle
00536   * @param  Params : pointer on additional configuration parameters, can be NULL.
00537   */
00538 __weak void BSP_AUDIO_OUT_MspInit(I2S_HandleTypeDef *hi2s, void *Params)
00539 { 
00540   static DMA_HandleTypeDef hdma_i2s_tx;
00541   GPIO_InitTypeDef  gpio_init_structure;
00542 
00543   /* Prevent unused argument(s) compilation warning */
00544   UNUSED(Params);
00545 
00546   /* Enable I2S clock */
00547   AUDIO_OUT_I2Sx_CLK_ENABLE();
00548 
00549   /* Enable MCK, SCK, WS, SD and CODEC_INT GPIO clock */
00550   AUDIO_OUT_I2Sx_MCK_GPIO_CLK_ENABLE();
00551   AUDIO_OUT_I2Sx_SCK_GPIO_CLK_ENABLE();
00552   AUDIO_OUT_I2Sx_SD_GPIO_CLK_ENABLE();
00553   AUDIO_OUT_I2Sx_WS_GPIO_CLK_ENABLE();
00554 
00555   /* CODEC_I2S pins configuration: MCK, SCK, WS and SD pins */
00556   gpio_init_structure.Pin = AUDIO_OUT_I2Sx_MCK_PIN;
00557   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
00558   gpio_init_structure.Pull = GPIO_NOPULL;
00559   gpio_init_structure.Speed = GPIO_SPEED_FAST;
00560   gpio_init_structure.Alternate = AUDIO_OUT_I2Sx_MCK_AF;
00561   HAL_GPIO_Init(AUDIO_OUT_I2Sx_MCK_GPIO_PORT, &gpio_init_structure);
00562 
00563   gpio_init_structure.Pin = AUDIO_OUT_I2Sx_SCK_PIN;
00564   gpio_init_structure.Alternate = AUDIO_OUT_I2Sx_SCK_AF;
00565   HAL_GPIO_Init(AUDIO_OUT_I2Sx_SCK_GPIO_PORT, &gpio_init_structure);
00566 
00567   gpio_init_structure.Pin = AUDIO_OUT_I2Sx_WS_PIN;
00568   gpio_init_structure.Alternate = AUDIO_OUT_I2Sx_WS_AF;
00569   HAL_GPIO_Init(AUDIO_OUT_I2Sx_WS_GPIO_PORT, &gpio_init_structure);
00570 
00571   gpio_init_structure.Pin = AUDIO_OUT_I2Sx_SD_PIN;
00572   gpio_init_structure.Alternate = AUDIO_OUT_I2Sx_SD_AF;
00573   HAL_GPIO_Init(AUDIO_OUT_I2Sx_SD_GPIO_PORT, &gpio_init_structure);
00574 
00575   /* Enable the DMA clock */
00576   AUDIO_OUT_I2Sx_DMAx_CLK_ENABLE();
00577 
00578   if(hi2s->Instance == AUDIO_OUT_I2Sx)
00579   {
00580     /* Configure the hdma_i2s_rx handle parameters */
00581     hdma_i2s_tx.Init.Channel             = AUDIO_OUT_I2Sx_DMAx_CHANNEL;
00582     hdma_i2s_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
00583     hdma_i2s_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
00584     hdma_i2s_tx.Init.MemInc              = DMA_MINC_ENABLE;
00585     hdma_i2s_tx.Init.PeriphDataAlignment = AUDIO_OUT_I2Sx_DMAx_PERIPH_DATA_SIZE;
00586     hdma_i2s_tx.Init.MemDataAlignment    = AUDIO_OUT_I2Sx_DMAx_MEM_DATA_SIZE;
00587     hdma_i2s_tx.Init.Mode                = DMA_CIRCULAR;
00588     hdma_i2s_tx.Init.Priority            = DMA_PRIORITY_HIGH;
00589     hdma_i2s_tx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
00590     hdma_i2s_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
00591     hdma_i2s_tx.Init.MemBurst            = DMA_MBURST_SINGLE;
00592     hdma_i2s_tx.Init.PeriphBurst         = DMA_MBURST_SINGLE;
00593 
00594     hdma_i2s_tx.Instance = AUDIO_OUT_I2Sx_DMAx_STREAM;
00595 
00596     /* Associate the DMA handle */
00597     __HAL_LINKDMA(hi2s, hdmatx, hdma_i2s_tx);
00598 
00599     /* Deinitialize the Stream for new transfer */
00600     HAL_DMA_DeInit(&hdma_i2s_tx);
00601 
00602     /* Configure the DMA Stream */
00603     HAL_DMA_Init(&hdma_i2s_tx);
00604   }
00605   
00606   /* Enable and set I2Sx Interrupt to a lower priority */
00607   HAL_NVIC_SetPriority(SPI3_IRQn, 0x0F, 0x00);
00608   HAL_NVIC_EnableIRQ(SPI3_IRQn);
00609 
00610   /* I2S DMA IRQ Channel configuration */
00611   HAL_NVIC_SetPriority(AUDIO_OUT_I2Sx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
00612   HAL_NVIC_EnableIRQ(AUDIO_OUT_I2Sx_DMAx_IRQ);
00613 }
00614 
00615 /**
00616   * @brief  Deinitializes I2S MSP.
00617   * @param  hi2s: I2S handle
00618   * @param  Params : pointer on additional configuration parameters, can be NULL.
00619   */
00620 __weak void BSP_AUDIO_OUT_MspDeInit(I2S_HandleTypeDef *hi2s, void *Params)
00621 {
00622   GPIO_InitTypeDef  gpio_init_structure;
00623   
00624   /* Prevent unused argument(s) compilation warning */
00625   UNUSED(Params);
00626   
00627   /* I2S DMA IRQ Channel deactivation */
00628   HAL_NVIC_DisableIRQ(AUDIO_OUT_I2Sx_DMAx_IRQ);
00629   
00630   if(hi2s->Instance == AUDIO_OUT_I2Sx)
00631   {
00632     /* Deinitialize the DMA stream */
00633     HAL_DMA_DeInit(hi2s->hdmatx);
00634   }
00635   
00636   /* Disable I2S peripheral */
00637   __HAL_I2S_DISABLE(hi2s);
00638   
00639   /* Deactives CODEC_I2S pins MCK, SCK, WS and SD by putting them in input mode */
00640   gpio_init_structure.Pin = AUDIO_OUT_I2Sx_MCK_PIN;
00641   HAL_GPIO_DeInit(AUDIO_OUT_I2Sx_MCK_GPIO_PORT, gpio_init_structure.Pin);
00642   
00643   gpio_init_structure.Pin = AUDIO_OUT_I2Sx_SCK_PIN;
00644   HAL_GPIO_DeInit(AUDIO_OUT_I2Sx_SCK_GPIO_PORT, gpio_init_structure.Pin);
00645   
00646   gpio_init_structure.Pin = AUDIO_OUT_I2Sx_WS_PIN;
00647   HAL_GPIO_DeInit(AUDIO_OUT_I2Sx_WS_GPIO_PORT, gpio_init_structure.Pin);
00648   
00649   gpio_init_structure.Pin = AUDIO_OUT_I2Sx_SD_PIN;
00650   HAL_GPIO_DeInit(AUDIO_OUT_I2Sx_SD_GPIO_PORT, gpio_init_structure.Pin);
00651   
00652   /* Disable I2S clock */
00653   AUDIO_OUT_I2Sx_CLK_DISABLE();
00654   
00655   /* GPIO pins clock and DMA clock can be shut down in the application 
00656   by surcharging this __weak function */ 
00657 }
00658 
00659 /**
00660   * @brief  Clock Config.
00661   * @param  hi2s: might be required to set audio peripheral predivider if any.
00662   * @param  AudioFreq: Audio frequency used to play the audio stream.
00663   * @param  Params : pointer on additional configuration parameters, can be NULL.
00664   * @note   This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency()
00665   *         Being __weak it can be overwritten by the application
00666   */
00667 __weak void BSP_AUDIO_OUT_ClockConfig(I2S_HandleTypeDef *hi2s, uint32_t AudioFreq, void *Params)
00668 { 
00669   RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct;
00670 
00671   /* Prevent unused argument(s) compilation warning */
00672   UNUSED(Params);
00673 
00674   HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct);
00675 
00676   /* Set the PLL configuration according to the audio frequency */
00677   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
00678   {
00679     /* Configure PLLI2S prescalers */
00680     rcc_ex_clk_init_struct.PeriphClockSelection = (RCC_PERIPHCLK_I2S_APB1  | RCC_PERIPHCLK_PLLI2S);
00681     rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S;
00682     rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC;    
00683     rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8;
00684     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 271;
00685     rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 2;
00686     
00687     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
00688   }
00689   else if(AudioFreq == AUDIO_FREQUENCY_96K) /* AUDIO_FREQUENCY_96K */
00690   {
00691     /* I2S clock config */
00692     rcc_ex_clk_init_struct.PeriphClockSelection = (RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_PLLI2S);
00693     rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S;
00694     rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC;    
00695     rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8;
00696     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344;
00697     rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 2;
00698 
00699     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);    
00700   }  
00701   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K */
00702   {
00703     /* I2S clock config
00704     PLLI2S_VCO: VCO_344M
00705     I2S_CLK(first level) = PLLI2S_VCO/PLLI2SR = 344/7 = 49.142 Mhz
00706     I2S_CLK_x = I2S_CLK(first level)/PLLI2SDIVR = 49.142/1 = 49.142 Mhz */
00707     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_PLLI2S;
00708     rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S;
00709     rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC;
00710     rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8;
00711     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344;
00712     rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 7;
00713     
00714     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
00715   }
00716 }
00717 
00718 /*******************************************************************************
00719                             Static Functions
00720 *******************************************************************************/
00721 
00722 /**
00723   * @brief  Initializes the Audio Codec audio interface (I2S)
00724   * @note   This function assumes that the I2S input clock
00725   *         is already configured and ready to be used.
00726   * @param  AudioFreq: Audio frequency to be configured for the I2S peripheral.
00727   */
00728 static void I2Sx_Out_Init(uint32_t AudioFreq)
00729 {
00730   /* Initialize the hAudioInI2s Instance parameter */
00731   haudio_i2s.Instance = AUDIO_OUT_I2Sx;
00732 
00733  /* Disable I2S block */
00734   __HAL_I2S_DISABLE(&haudio_i2s);
00735   
00736   /* I2S peripheral configuration */
00737   haudio_i2s.Init.AudioFreq = AudioFreq;
00738   haudio_i2s.Init.ClockSource = I2S_CLOCK_PLL;
00739   haudio_i2s.Init.CPOL = I2S_CPOL_LOW;
00740   haudio_i2s.Init.DataFormat = I2S_DATAFORMAT_16B;
00741   haudio_i2s.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
00742   haudio_i2s.Init.Mode = I2S_MODE_MASTER_TX;
00743   haudio_i2s.Init.Standard =  I2S_STANDARD_PHILIPS;
00744   haudio_i2s.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE;
00745   
00746   /* Init the I2S */
00747   HAL_I2S_Init(&haudio_i2s);
00748 
00749  /* Enable I2S block */
00750   __HAL_I2S_ENABLE(&haudio_i2s);
00751 }
00752 
00753 /**
00754   * @brief  Deinitializes the Audio Codec audio interface (I2S).
00755   */
00756 static void I2Sx_Out_DeInit(void)
00757 {
00758   /* Initialize the hAudioInI2s Instance parameter */
00759   haudio_i2s.Instance = AUDIO_OUT_I2Sx;
00760 
00761  /* Disable I2S block */
00762   __HAL_I2S_DISABLE(&haudio_i2s);
00763 
00764   /* DeInit the I2S */
00765   HAL_I2S_DeInit(&haudio_i2s);
00766 }
00767  
00768 /**
00769   * @}
00770   */
00771 
00772 /** @defgroup STM32F413H_DISCOVERY_AUDIO_IN_Private_Functions STM32F413H DISCOVERY AUDIO IN Private functions
00773   * @{
00774   */ 
00775 
00776 /**
00777   * @brief  Initializes wave recording.                    
00778   * @param  AudioFreq: Audio frequency to be configured for the audio in peripheral.
00779   * @param  BitRes: Audio bit resolution.
00780   * @param  ChnlNbr: Audio channel number.
00781   * @retval AUDIO_OK if correct communication, else wrong communication
00782   */
00783 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00784 {
00785   return BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC, AudioFreq, BitRes, ChnlNbr);  
00786 }
00787 
00788 /**
00789   * @brief  Initializes wave recording.
00790   * @param  InputDevice: INPUT_DEVICE_DIGITAL_MICx or INPUT_DEVICE_ANALOG_MIC.                     
00791   * @param  AudioFreq: Audio frequency to be configured for the audio in peripheral.
00792   * @param  BitRes: Audio bit resolution.
00793   * @param  ChnlNbr: Audio channel number.
00794   * @retval AUDIO_OK if correct communication, else wrong communication
00795   */
00796 uint8_t BSP_AUDIO_IN_InitEx(uint32_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00797 {
00798   uint32_t ret = AUDIO_ERROR;
00799   uint32_t deviceid =0;
00800   uint32_t mic_enabled =0;
00801   uint16_t buffer_fake[16] = {0x00};
00802   uint32_t i = 0;
00803   
00804   /* Store the audio record context */
00805   hAudioIn.Frequency     = AudioFreq;
00806   hAudioIn.BitResolution = BitRes;
00807   hAudioIn.InputDevice = InputDevice; 
00808   hAudioIn.ChannelNbr = ChnlNbr;
00809   
00810   /* Store the total number of microphones enabled */  
00811   for(i = 0; i < DFSDM_MIC_NUMBER; i ++)
00812   {
00813     if(((hAudioIn.InputDevice >> i) & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
00814     {
00815       mic_enabled++;
00816     }   
00817   }
00818   
00819   if (InputDevice == INPUT_DEVICE_ANALOG_MIC)
00820   { 
00821     InputDevice = INPUT_DEVICE_INPUT_LINE_1;
00822     /* INPUT_DEVICE_ANALOG_MIC */
00823     /* Disable I2S */
00824     I2Sx_In_DeInit();
00825     
00826     /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
00827     BSP_AUDIO_IN_ClockConfig(AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT for analog mic */
00828     
00829     /* I2S data transfer preparation:
00830     Prepare the Media to be used for the audio transfer from I2S peripheral to memory */
00831     haudio_i2s.Instance = AUDIO_IN_I2Sx;
00832     if(HAL_I2S_GetState(&haudio_i2s) == HAL_I2S_STATE_RESET)
00833     {
00834       BSP_AUDIO_OUT_MspInit(&haudio_i2s, NULL); /* Initialize GPIOs for SPI3 Master signals */
00835       /* Init the I2S MSP: this __weak function can be redefined by the application*/
00836       BSP_AUDIO_IN_MspInit(NULL);
00837     }
00838     
00839     /* Configure I2S */
00840     I2Sx_In_Init(AudioFreq);
00841     
00842     AUDIO_IO_Init();
00843     
00844     /* wm8994 codec initialization */
00845     deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
00846     
00847     if((deviceid) == WM8994_ID)
00848     {
00849       /* Reset the Codec Registers */
00850       wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
00851       /* Initialize the audio driver structure */
00852       audio_drv = &wm8994_drv;
00853       ret = AUDIO_OK;
00854     }
00855     else
00856     {
00857       ret = AUDIO_ERROR;
00858     }
00859     
00860     if(ret == AUDIO_OK)
00861     {
00862       /* Receive fake I2S data in order to generate MCLK needed by WM8994 to set its registers */
00863       HAL_I2S_Receive_DMA(&haudio_i2s, buffer_fake, 16);
00864       /* Initialize the codec internal registers */
00865       audio_drv->Init(AUDIO_I2C_ADDRESS, (OUTPUT_DEVICE_HEADPHONE|InputDevice), 100, AudioFreq);
00866       /* Stop receiving fake I2S data */
00867       HAL_I2S_DMAStop(&haudio_i2s);
00868     }    
00869   }
00870   else
00871   {
00872     if(hAudioIn.ChannelNbr != mic_enabled)  
00873     {
00874       return AUDIO_ERROR;
00875     }
00876     else
00877     {
00878       /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
00879       BSP_AUDIO_IN_ClockConfig(AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT for analog mic */
00880       
00881       /* Init the DFSDM MSP: this __weak function can be redefined by the application*/
00882       BSP_AUDIO_IN_MspInit(NULL);
00883       
00884       /* Default configuration of DFSDM filters and channels */
00885       ret = BSP_AUDIO_IN_ConfigDigitalMic(hAudioIn.InputDevice, NULL);
00886     } 
00887   }
00888   
00889   /* Return AUDIO_OK when all operations are correctly done */
00890   return ret;
00891 }
00892 
00893 /**
00894   * @brief  DeInitializes the audio peripheral.
00895   */
00896 void BSP_AUDIO_IN_DeInit(void)
00897 {
00898   if(hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
00899   {    
00900     /* MSP filters/channels initialization */   
00901     BSP_AUDIO_IN_MspDeInit(NULL);
00902     
00903     DFSDMx_DeInit();
00904   }
00905   else
00906   {
00907     I2Sx_In_DeInit();
00908   }
00909 }
00910 
00911 /**
00912   * @brief  Initializes default configuration of the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
00913   * @param  InputDevice: The microphone to be configured. Can be INPUT_DEVICE_DIGITAL_MIC1..INPUT_DEVICE_DIGITAL_MIC5
00914   * @note   Channel output Clock Divider and Filter Oversampling are calculated as follow: 
00915   *         - Clock_Divider = CLK(input DFSDM)/CLK(micro) with
00916   *           1MHZ < CLK(micro) < 3.2MHZ (TYP 2.4MHZ for MP34DT01TR)
00917   *         - Oversampling = CLK(input DFSDM)/(Clock_Divider * AudioFreq)
00918   * @retval AUDIO_OK if correct communication, else wrong communication
00919   */
00920 uint8_t BSP_AUDIO_IN_ConfigMicDefault(uint32_t InputDevice)
00921 {
00922   uint32_t i = 0, mic_init[DFSDM_MIC_NUMBER] = {0};
00923   uint32_t filter_ch = 0, mic_num = 0;
00924   
00925   DFSDM_Filter_TypeDef* FilterInstnace[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_MIC1_FILTER, AUDIO_DFSDMx_MIC2_FILTER, AUDIO_DFSDMx_MIC3_FILTER, AUDIO_DFSDMx_MIC4_FILTER, AUDIO_DFSDMx_MIC5_FILTER};
00926   DFSDM_Channel_TypeDef* ChannelInstnace[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_MIC1_CHANNEL, AUDIO_DFSDMx_MIC2_CHANNEL, AUDIO_DFSDMx_MIC3_CHANNEL, AUDIO_DFSDMx_MIC4_CHANNEL, AUDIO_DFSDMx_MIC5_CHANNEL};
00927   uint32_t DigitalMicPins[DFSDM_MIC_NUMBER] = {DFSDM_CHANNEL_SAME_CHANNEL_PINS, DFSDM_CHANNEL_SAME_CHANNEL_PINS, DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS, DFSDM_CHANNEL_SAME_CHANNEL_PINS, DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS};
00928   uint32_t DigitalMicType[DFSDM_MIC_NUMBER] = {DFSDM_CHANNEL_SPI_RISING, DFSDM_CHANNEL_SPI_RISING, DFSDM_CHANNEL_SPI_FALLING, DFSDM_CHANNEL_SPI_RISING, DFSDM_CHANNEL_SPI_FALLING};
00929   uint32_t Channel4Filter[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_MIC1_CHANNEL_FOR_FILTER, AUDIO_DFSDMx_MIC2_CHANNEL_FOR_FILTER, AUDIO_DFSDMx_MIC3_CHANNEL_FOR_FILTER, AUDIO_DFSDMx_MIC4_CHANNEL_FOR_FILTER, AUDIO_DFSDMx_MIC5_CHANNEL_FOR_FILTER};
00930   
00931   for(i = 0; i < hAudioIn.ChannelNbr; i++)
00932   {  
00933     if(((InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] != 1))
00934     { 
00935       mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC1);   
00936     }    
00937     else if(((InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] != 1))
00938     {
00939       mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC2); 
00940     } 
00941     else if(((InputDevice & INPUT_DEVICE_DIGITAL_MIC3) == INPUT_DEVICE_DIGITAL_MIC3) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)] != 1))
00942     {
00943       mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC3); 
00944     } 
00945     else if(((InputDevice & INPUT_DEVICE_DIGITAL_MIC4) == INPUT_DEVICE_DIGITAL_MIC4) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)] != 1))
00946     { 
00947       mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC4); 
00948     } 
00949     else if(((InputDevice & INPUT_DEVICE_DIGITAL_MIC5) == INPUT_DEVICE_DIGITAL_MIC5) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)] != 1))
00950     {
00951       mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC5); 
00952     }
00953   
00954     mic_init[mic_num] = 1;
00955   
00956     /* Filter **********************************************************************************************************/
00957     if(hAudioInDfsdmFilter[mic_num].Instance != NULL)
00958     {
00959       if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInDfsdmFilter[mic_num]))
00960       {
00961         return AUDIO_ERROR;
00962       } 
00963       /* MIC filters  initialization */
00964       __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInDfsdmFilter[mic_num]); 
00965     }
00966     
00967     /* MIC filters  initialization */
00968     __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInDfsdmFilter[mic_num]); 
00969     hAudioInDfsdmFilter[mic_num].Instance                          = FilterInstnace[mic_num]; 
00970     hAudioInDfsdmFilter[mic_num].Init.RegularParam.Trigger         = DFSDM_FILTER_SW_TRIGGER;
00971     hAudioInDfsdmFilter[mic_num].Init.RegularParam.FastMode        = ENABLE;
00972     hAudioInDfsdmFilter[mic_num].Init.RegularParam.DmaMode         = ENABLE;
00973     hAudioInDfsdmFilter[mic_num].Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
00974     hAudioInDfsdmFilter[mic_num].Init.InjectedParam.ScanMode       = DISABLE;
00975     hAudioInDfsdmFilter[mic_num].Init.InjectedParam.DmaMode        = DISABLE;
00976     hAudioInDfsdmFilter[mic_num].Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO;
00977     hAudioInDfsdmFilter[mic_num].Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES;
00978     hAudioInDfsdmFilter[mic_num].Init.FilterParam.SincOrder        = DFSDM_FILTER_ORDER(hAudioIn.Frequency);
00979     hAudioInDfsdmFilter[mic_num].Init.FilterParam.Oversampling     = DFSDM_OVER_SAMPLING(hAudioIn.Frequency);   
00980     hAudioInDfsdmFilter[mic_num].Init.FilterParam.IntOversampling  = 1;
00981     
00982     if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInDfsdmFilter[mic_num]))
00983     {
00984       return AUDIO_ERROR;
00985     }
00986 
00987     /* Channel **********************************************************************************************************/
00988     if(hAudioInDfsdmChannel[mic_num].Instance != NULL)
00989     {
00990       if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInDfsdmChannel[mic_num]))
00991       {
00992         return AUDIO_ERROR;
00993       }
00994       
00995       /* MIC channels initialization */
00996       __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInDfsdmChannel[mic_num]);   
00997     }
00998     
00999     /* MIC channels initialization */
01000     __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInDfsdmChannel[mic_num]);   
01001     hAudioInDfsdmChannel[mic_num].Init.OutputClock.Activation   = ENABLE;
01002     hAudioInDfsdmChannel[mic_num].Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 
01003     hAudioInDfsdmChannel[mic_num].Init.OutputClock.Divider      = DFSDM_CLOCK_DIVIDER(hAudioIn.Frequency); 
01004     hAudioInDfsdmChannel[mic_num].Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;  
01005     hAudioInDfsdmChannel[mic_num].Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
01006     hAudioInDfsdmChannel[mic_num].Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 
01007     hAudioInDfsdmChannel[mic_num].Init.Awd.FilterOrder          = DFSDM_CHANNEL_SINC1_ORDER;
01008     hAudioInDfsdmChannel[mic_num].Init.Awd.Oversampling         = 10; 
01009     hAudioInDfsdmChannel[mic_num].Init.Offset                   = 0;
01010     hAudioInDfsdmChannel[mic_num].Init.RightBitShift            = DFSDM_MIC_BIT_SHIFT(hAudioIn.Frequency);
01011     hAudioInDfsdmChannel[mic_num].Instance                      = ChannelInstnace[mic_num];
01012     hAudioInDfsdmChannel[mic_num].Init.Input.Pins               = DigitalMicPins[mic_num]; 
01013     hAudioInDfsdmChannel[mic_num].Init.SerialInterface.Type     = DigitalMicType[mic_num];
01014     
01015     if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInDfsdmChannel[mic_num]))
01016     {
01017       return AUDIO_ERROR;
01018     }
01019     
01020     filter_ch = Channel4Filter[mic_num];      
01021     /* Configure injected channel */
01022     if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInDfsdmFilter[mic_num], filter_ch, DFSDM_CONTINUOUS_CONV_ON))
01023     {
01024       return AUDIO_ERROR;
01025     }  
01026   }
01027   return AUDIO_OK;
01028 } 
01029 
01030 /**
01031   * @brief  Initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01032   * @param  InputDevice: The microphone to be configured. Can be INPUT_DEVICE_DIGITAL_MIC1..INPUT_DEVICE_DIGITAL_MIC5
01033   * @param  Params : pointer on additional configuration parameters, can be NULL.  
01034   * @retval AUDIO_OK if correct communication, else wrong communication
01035   */
01036 __weak uint8_t BSP_AUDIO_IN_ConfigDigitalMic(uint32_t InputDevice, void *Params)
01037 {
01038   /* Prevent unused argument(s) compilation warning */
01039   UNUSED(Params);
01040   
01041   /* Default configuration of DFSDM filters and channels */
01042   return(BSP_AUDIO_IN_ConfigMicDefault(InputDevice));
01043   /* Note: This function can be called at application level and default configuration
01044            can be ovewritten to fit user's need */
01045 } 
01046 
01047 /**
01048   * @brief  Allocate channel buffer scratch 
01049   * @param  pScratch : pointer to scratch tables.
01050   * @param  size: size of scratch buffer
01051   */
01052 uint8_t BSP_AUDIO_IN_AllocScratch (int32_t *pScratch, uint32_t size)
01053 { 
01054   uint32_t idx;
01055   
01056   ScratchSize = size / DEFAULT_AUDIO_IN_CHANNEL_NBR;
01057   
01058   /* copy scratch pointers */
01059   for (idx = 0; idx < DEFAULT_AUDIO_IN_CHANNEL_NBR ; idx++)
01060   {
01061     pScratchBuff[idx] = (int32_t *)(pScratch + idx * ScratchSize);
01062   }
01063   /* Return AUDIO_OK */
01064   return AUDIO_OK;
01065 }
01066 
01067 /**
01068   * @brief  Starts audio recording.                    
01069   * @param  pBuf: Main buffer pointer for the recorded data storing
01070   * @param  size: Current size of the recorded buffer
01071   * @retval AUDIO_OK if correct communication, else wrong communication
01072   */
01073 uint8_t BSP_AUDIO_IN_Record(uint16_t *pBuf, uint32_t size)
01074 {  
01075   hAudioIn.pRecBuf = pBuf;
01076   hAudioIn.RecSize = size;
01077   /* Reset Application Buffer Trigger */
01078   AppBuffTrigger = 0;
01079   AppBuffHalf = 0;
01080   
01081   if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC)
01082   {    
01083     /* Call the Media layer start function for MIC1 channel */
01084     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], ScratchSize))
01085     {
01086       return AUDIO_ERROR;
01087     }
01088     
01089     /* Call the Media layer start function for MIC2 channel */
01090     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], ScratchSize))
01091     {
01092       return AUDIO_ERROR;
01093     }    
01094   }
01095   else
01096   {
01097     /* Start the process to receive the DMA */
01098     if (HAL_OK != HAL_I2SEx_TransmitReceive_DMA(&haudio_i2s, pBuf, pBuf, size))
01099     {
01100       return AUDIO_ERROR;
01101     }
01102   }
01103   /* Return AUDIO_OK when all operations are correctly done */
01104   return AUDIO_OK;
01105 }
01106   
01107 /**
01108   * @brief  Starts audio recording.                  
01109   * @param  pBuf: Main buffer pointer for the recorded data storing
01110   * @param  size: Current size of the recorded buffer
01111   * @retval AUDIO_OK if correct communication, else wrong communication
01112   */
01113 uint8_t BSP_AUDIO_IN_RecordEx(uint32_t *pBuf, uint32_t size)
01114 {
01115   uint8_t ret = AUDIO_ERROR;
01116   hAudioIn.RecSize = size;
01117   uint32_t i = 0;
01118   uint32_t mic_init[DFSDM_MIC_NUMBER] = {0};
01119   if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC)
01120   {
01121     return ret;
01122   }
01123   else
01124   {
01125     hAudioIn.MultiBuffMode = 1;
01126     for(i = 0; i < hAudioIn.ChannelNbr; i++)
01127     {
01128       if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] != 1))
01129       {
01130         /* Call the Media layer start function for MIC1 channel 1 */
01131         if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], (int32_t*)pBuf[i], size))
01132         {
01133           return AUDIO_ERROR;
01134         }
01135         MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = i; 
01136         mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 1;
01137       }
01138       else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] != 1))
01139       {
01140         /* Call the Media layer start function for MIC2 channel 1 */
01141         if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], (int32_t*)pBuf[i], size))
01142         {
01143           return AUDIO_ERROR;
01144         }
01145         MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = i; 
01146         mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = 1;
01147       }
01148       else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC3) == INPUT_DEVICE_DIGITAL_MIC3) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)] != 1))
01149       {
01150         /* Call the Media layer start function for MIC3 channel 0 */
01151         if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)], (int32_t*)pBuf[i], size))
01152         {
01153           return AUDIO_ERROR;
01154         }
01155         MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)] = i;
01156         mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)] = 1;
01157       }
01158       else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC4) == INPUT_DEVICE_DIGITAL_MIC4) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)] != 1))
01159       {
01160         /* Call the Media layer start function for MIC4 channel 7 */
01161         if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)], (int32_t*)pBuf[i], size))
01162         {
01163           return AUDIO_ERROR;
01164         }
01165         MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)] = i; 
01166         mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)] = 1;
01167       }
01168       else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC5) == INPUT_DEVICE_DIGITAL_MIC5) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)] != 1))
01169       {
01170         /* Call the Media layer start function for MIC5 channel 6 */
01171         if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)], (int32_t*)pBuf[i], size))
01172         {
01173           return AUDIO_ERROR;
01174         }
01175         MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)] = i; 
01176         mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)] = 1;
01177       }
01178     }
01179   }
01180   /* Return AUDIO_OK when all operations are correctly done */
01181   return AUDIO_OK;
01182 }
01183 
01184 /**
01185   * @brief  Initializes the I2S MSP.
01186   */
01187 static void I2Sx_In_MspInit(void)
01188 {
01189   static DMA_HandleTypeDef hdma_i2s_rx;
01190   GPIO_InitTypeDef  gpio_init_structure;  
01191 
01192   /* Enable I2S clock */
01193   AUDIO_IN_I2Sx_CLK_ENABLE();
01194 
01195   /* Enable MCK GPIO clock, needed by the codec */
01196   AUDIO_OUT_I2Sx_MCK_GPIO_CLK_ENABLE();
01197 
01198   /* CODEC_I2S pins configuration: MCK pins */
01199   gpio_init_structure.Pin = AUDIO_OUT_I2Sx_MCK_PIN;
01200   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
01201   gpio_init_structure.Pull = GPIO_NOPULL;
01202   gpio_init_structure.Speed = GPIO_SPEED_FAST;
01203   gpio_init_structure.Alternate = AUDIO_OUT_I2Sx_MCK_AF;
01204   HAL_GPIO_Init(AUDIO_OUT_I2Sx_MCK_GPIO_PORT, &gpio_init_structure);
01205   
01206   /* Enable SD GPIO clock */
01207   AUDIO_IN_I2Sx_EXT_SD_GPIO_CLK_ENABLE();
01208   /* CODEC_I2S pin configuration: SD pin */
01209   gpio_init_structure.Pin = AUDIO_IN_I2Sx_EXT_SD_PIN;
01210   gpio_init_structure.Alternate = AUDIO_IN_I2Sx_EXT_SD_AF;
01211   HAL_GPIO_Init(AUDIO_IN_I2Sx_EXT_SD_GPIO_PORT, &gpio_init_structure);
01212 
01213   /* Enable the DMA clock */
01214   AUDIO_IN_I2Sx_DMAx_CLK_ENABLE();
01215     
01216   if(haudio_i2s.Instance == AUDIO_IN_I2Sx)
01217   {
01218     /* Configure the hdma_i2s_rx handle parameters */
01219     hdma_i2s_rx.Init.Channel             = AUDIO_IN_I2Sx_DMAx_CHANNEL;
01220     hdma_i2s_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
01221     hdma_i2s_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
01222     hdma_i2s_rx.Init.MemInc              = DMA_MINC_ENABLE;
01223     hdma_i2s_rx.Init.PeriphDataAlignment = AUDIO_IN_I2Sx_DMAx_PERIPH_DATA_SIZE;
01224     hdma_i2s_rx.Init.MemDataAlignment    = AUDIO_IN_I2Sx_DMAx_MEM_DATA_SIZE;
01225     hdma_i2s_rx.Init.Mode                = DMA_CIRCULAR;
01226     hdma_i2s_rx.Init.Priority            = DMA_PRIORITY_HIGH;
01227     hdma_i2s_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
01228     hdma_i2s_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
01229     hdma_i2s_rx.Init.MemBurst            = DMA_MBURST_SINGLE;
01230     hdma_i2s_rx.Init.PeriphBurst         = DMA_MBURST_SINGLE;
01231     
01232     hdma_i2s_rx.Instance = AUDIO_IN_I2Sx_DMAx_STREAM;
01233     
01234     /* Associate the DMA handle */
01235     __HAL_LINKDMA(&haudio_i2s, hdmarx, hdma_i2s_rx);
01236     
01237     /* Deinitialize the Stream for new transfer */
01238     HAL_DMA_DeInit(&hdma_i2s_rx);
01239     
01240     /* Configure the DMA Stream */
01241     HAL_DMA_Init(&hdma_i2s_rx);
01242   }
01243   
01244   /* I2S DMA IRQ Channel configuration */
01245   HAL_NVIC_SetPriority(AUDIO_IN_I2Sx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
01246   HAL_NVIC_EnableIRQ(AUDIO_IN_I2Sx_DMAx_IRQ);   
01247 }
01248 
01249 /**
01250   * @brief  De-Initializes the I2S MSP.
01251   */
01252 static void I2Sx_In_MspDeInit(void)
01253 {
01254   GPIO_InitTypeDef  gpio_init_structure;
01255   
01256   /* I2S DMA IRQ Channel deactivation */
01257   HAL_NVIC_DisableIRQ(AUDIO_IN_I2Sx_DMAx_IRQ);
01258   
01259   if(haudio_i2s.Instance == AUDIO_IN_I2Sx)
01260   {
01261     /* Deinitialize the DMA stream */
01262     HAL_DMA_DeInit(haudio_i2s.hdmarx);
01263   }
01264   
01265   /* Disable I2S peripheral */
01266   __HAL_I2S_DISABLE(&haudio_i2s);
01267   
01268   /* Deactives CODEC_I2S pins MCK by putting them in input mode */
01269   gpio_init_structure.Pin = AUDIO_OUT_I2Sx_MCK_PIN;
01270   HAL_GPIO_DeInit(AUDIO_OUT_I2Sx_MCK_GPIO_PORT, gpio_init_structure.Pin);
01271   
01272   gpio_init_structure.Pin = AUDIO_IN_I2Sx_EXT_SD_PIN;
01273   HAL_GPIO_DeInit(AUDIO_IN_I2Sx_EXT_SD_GPIO_PORT, gpio_init_structure.Pin);
01274   
01275   /* Disable I2S clock */
01276   AUDIO_IN_I2Sx_CLK_DISABLE();  
01277 }
01278 
01279 /**
01280   * @brief  Initializes BSP_AUDIO_IN MSP.
01281   * @param  Params : pointer on additional configuration parameters, can be NULL.
01282   */
01283 __weak void BSP_AUDIO_IN_MspInit(void *Params)
01284 {
01285   /* Prevent unused argument(s) compilation warning */
01286   UNUSED(Params);
01287   
01288   if(hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC)
01289   {
01290     I2Sx_In_MspInit();
01291   }
01292   else
01293   {
01294     /* MSP channels initialization */
01295     DFSDMx_ChannelMspInit();
01296     
01297     /* MSP filters initialization */
01298     DFSDMx_FilterMspInit();  
01299   }
01300 }
01301 
01302 /**
01303   * @brief  De-Initializes BSP_AUDIO_IN MSP. 
01304   * @param  Params : pointer on additional configuration parameters, can be NULL.
01305   */
01306 __weak void BSP_AUDIO_IN_MspDeInit(void *Params)
01307 {
01308   /* Prevent unused argument(s) compilation warning */
01309   UNUSED(Params);
01310   
01311   if(hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC)
01312   {
01313     I2Sx_In_MspDeInit();
01314   }
01315   else
01316   {
01317     /* MSP channels initialization */
01318     DFSDMx_ChannelMspDeInit();
01319     
01320     /* MSP filters initialization */
01321     DFSDMx_FilterMspDeInit();  
01322   }
01323 }
01324 
01325 /**
01326   * @brief  Clock Config.
01327   * @param  AudioFreq: Audio frequency used to play the audio stream.
01328   * @param  Params : pointer on additional configuration parameters, can be NULL.
01329   * @note   This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency()
01330   *         Being __weak it can be overwritten by the application
01331   * @retval AUDIO_OK if correct communication, else wrong communication
01332   */
01333 __weak uint8_t BSP_AUDIO_IN_ClockConfig(uint32_t AudioFreq, void *Params)
01334 {
01335   RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct;
01336 
01337   /* Prevent unused argument(s) compilation warning */
01338   UNUSED(Params);
01339   
01340   HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct);
01341 
01342   /* Set the PLL configuration according to the audio frequency */
01343   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
01344   {
01345     /* Configure PLLI2S prescalers */
01346     rcc_ex_clk_init_struct.PeriphClockSelection = (RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_DFSDM | RCC_PERIPHCLK_DFSDM2);
01347     rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S;
01348     rcc_ex_clk_init_struct.Dfsdm1ClockSelection = RCC_DFSDM1CLKSOURCE_APB2;
01349     rcc_ex_clk_init_struct.Dfsdm2ClockSelection = RCC_DFSDM2CLKSOURCE_APB2;
01350     rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC;
01351     rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8;
01352     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 271;
01353     rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 2;
01354 
01355     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
01356   }
01357   else if(AudioFreq == AUDIO_FREQUENCY_96K)
01358   {
01359     /* I2S clock config */
01360     rcc_ex_clk_init_struct.PeriphClockSelection = (RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_DFSDM | RCC_PERIPHCLK_DFSDM2);
01361     rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S;
01362     rcc_ex_clk_init_struct.Dfsdm1ClockSelection = RCC_DFSDM1CLKSOURCE_APB2;
01363     rcc_ex_clk_init_struct.Dfsdm2ClockSelection = RCC_DFSDM2CLKSOURCE_APB2;
01364     rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC;
01365     rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8;
01366     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344;
01367     rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 2;
01368 
01369     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);    
01370   }
01371   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_32K, AUDIO_FREQUENCY_48K */
01372   {
01373     /* I2S clock config
01374     PLLI2S_VCO: VCO_344M
01375     I2S_CLK(first level) = PLLI2S_VCO/PLLI2SR = 344/7 = 49.142 Mhz
01376     I2S_CLK_x = I2S_CLK(first level)/PLLI2SDIVR = 49.142/1 = 49.142 Mhz */
01377     rcc_ex_clk_init_struct.PeriphClockSelection = (RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_DFSDM | RCC_PERIPHCLK_DFSDM2);
01378     rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S;
01379     rcc_ex_clk_init_struct.DfsdmClockSelection = RCC_DFSDM1CLKSOURCE_APB2|RCC_DFSDM2CLKSOURCE_APB2;
01380     rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC;
01381     rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8;
01382     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344;
01383     rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 7;
01384 
01385     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
01386   }
01387 
01388   if(hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
01389   {
01390     /* I2S_APB1 selected as DFSDM audio clock source */
01391     __HAL_RCC_DFSDM1AUDIO_CONFIG(RCC_DFSDM1AUDIOCLKSOURCE_I2SAPB1);
01392     /* I2S_APB1 selected as DFSDM audio clock source */
01393     __HAL_RCC_DFSDM2AUDIO_CONFIG(RCC_DFSDM2AUDIOCLKSOURCE_I2SAPB1);
01394   }
01395 
01396   return AUDIO_OK;
01397 }
01398 
01399 /**
01400   * @brief  Regular conversion complete callback.
01401   * @note   In interrupt mode, user has to read conversion value in this function
01402             using HAL_DFSDM_FilterGetRegularValue.
01403   * @param  hdfsdm_filter : DFSDM filter handle.
01404   */
01405 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01406 {
01407   uint32_t index, input_device = 0;
01408   
01409   if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC1_FILTER)
01410   {
01411     DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 1;
01412     input_device = INPUT_DEVICE_DIGITAL_MIC1;    
01413   }
01414   else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC2_FILTER)
01415   {
01416     DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = 1;
01417     input_device = INPUT_DEVICE_DIGITAL_MIC2; 
01418   }
01419   else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC3_FILTER)
01420   {
01421     input_device = INPUT_DEVICE_DIGITAL_MIC3; 
01422   }
01423   else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC4_FILTER)
01424   {
01425     input_device = INPUT_DEVICE_DIGITAL_MIC4; 
01426   }  
01427   else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC5_FILTER)
01428   {
01429     input_device = INPUT_DEVICE_DIGITAL_MIC5;    
01430   }
01431   
01432   if(hAudioIn.MultiBuffMode == 1)
01433   {
01434     BSP_AUDIO_IN_TransferComplete_CallBackEx(input_device);
01435   }
01436   else
01437   {
01438     if((DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] == 1) && (DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] == 1))
01439     {
01440       if(AppBuffTrigger >= hAudioIn.RecSize)
01441         AppBuffTrigger = 0;
01442       
01443       for(index = (ScratchSize/2) ; index < ScratchSize; index++)
01444       {
01445         hAudioIn.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)][index] >> 8), -32760, 32760));
01446         hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)][index] >> 8), -32760, 32760));
01447         AppBuffTrigger += 2;
01448       }
01449       DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 0;
01450     }
01451     
01452     /* Update Trigger with Remaining Byte before callback if necessary */
01453     if(AppBuffTrigger >= hAudioIn.RecSize)
01454     {
01455       /* Reset Application Buffer Trigger */
01456       AppBuffTrigger = 0;
01457       AppBuffHalf = 0;
01458       
01459       /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01460       BSP_AUDIO_IN_TransferComplete_CallBack();
01461     }
01462     else if((AppBuffTrigger >= hAudioIn.RecSize/2))
01463     {
01464       if(AppBuffHalf == 0)
01465       {
01466         AppBuffHalf = 1;
01467         /* Manage the remaining file size and new address offset: This function
01468         should be coded by user (its prototype is already declared in stm32l476g_eval_audio.h) */
01469         BSP_AUDIO_IN_HalfTransfer_CallBack();
01470       }
01471     }
01472   }
01473 }
01474 
01475 /**
01476   * @brief  Half regular conversion complete callback.
01477   * @param  hdfsdm_filter : DFSDM filter handle.
01478   */
01479 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01480 {
01481   uint32_t index, input_device = 0;
01482   
01483   if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC1_FILTER)
01484   {
01485     DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 1;
01486     input_device = INPUT_DEVICE_DIGITAL_MIC1;    
01487   }
01488   else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC2_FILTER)
01489   {
01490     DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = 1;
01491     input_device = INPUT_DEVICE_DIGITAL_MIC2; 
01492   }
01493   else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC3_FILTER)
01494   {
01495     input_device = INPUT_DEVICE_DIGITAL_MIC3; 
01496   }
01497   else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC4_FILTER)
01498   {
01499     input_device = INPUT_DEVICE_DIGITAL_MIC4; 
01500   }  
01501   else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC5_FILTER)
01502   {
01503     input_device = INPUT_DEVICE_DIGITAL_MIC5;    
01504   }
01505   
01506   if(hAudioIn.MultiBuffMode == 1)
01507   {
01508     BSP_AUDIO_IN_HalfTransfer_CallBackEx(input_device);
01509   }
01510   else
01511   { 
01512     if((DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] == 1) && (DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] == 1))
01513     {  
01514       if(AppBuffTrigger >= hAudioIn.RecSize)
01515         AppBuffTrigger = 0;
01516       
01517       for(index = 0; index < ScratchSize/2; index++)
01518       {
01519         hAudioIn.pRecBuf[AppBuffTrigger]     = (int16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)][index] >> 8), -32760, 32760));
01520         hAudioIn.pRecBuf[AppBuffTrigger + 1] = (int16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)][index] >> 8), -32760, 32760));
01521         AppBuffTrigger += 2;
01522       }
01523       DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 0;
01524     }
01525     
01526     
01527     /* Update Trigger with Remaining Byte before callback if necessary */
01528     if(AppBuffTrigger >= hAudioIn.RecSize)
01529     {
01530       /* Reset Application Buffer Trigger */
01531       AppBuffTrigger = 0;
01532       AppBuffHalf = 0;
01533       
01534       /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01535       BSP_AUDIO_IN_TransferComplete_CallBack();
01536     }
01537     else if((AppBuffTrigger >= hAudioIn.RecSize/2))
01538     {
01539       if(AppBuffHalf == 0)
01540       {
01541         AppBuffHalf = 1;
01542         /* Manage the remaining file size and new address offset: This function
01543         should be coded by user */
01544         BSP_AUDIO_IN_HalfTransfer_CallBack();
01545       }
01546     }
01547   }
01548 }
01549 
01550 /**
01551   * @brief  Half reception complete callback.
01552   * @param  hi2s : I2S handle.
01553   */
01554 void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
01555 {
01556   /* Manage the remaining file size and new address offset: This function 
01557      should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */
01558   BSP_AUDIO_IN_HalfTransfer_CallBack();
01559 }
01560 
01561 /**
01562   * @brief  Reception complete callback.
01563   * @param  hi2s : I2S handle.
01564   */
01565 void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
01566 {
01567   /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01568   BSP_AUDIO_IN_TransferComplete_CallBack();
01569 }
01570 
01571 /**
01572   * @brief  Stops audio recording.
01573   * @retval AUDIO_OK if correct communication, else wrong communication
01574   */
01575 uint8_t BSP_AUDIO_IN_Stop(void)
01576 {  
01577   AppBuffTrigger = 0;
01578   AppBuffHalf    = 0;
01579   
01580   if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC)
01581   {
01582     /* Call the Media layer stop function */
01583     if(HAL_OK != HAL_I2S_DMAStop(&haudio_i2s))
01584     {
01585       return AUDIO_ERROR;
01586     }
01587     /* Call Audio Codec Stop function */
01588     if(audio_drv->Stop(AUDIO_I2C_ADDRESS, CODEC_PDWN_HW) != 0)
01589     {
01590       return AUDIO_ERROR;
01591     }
01592     /* Wait at least 100us */
01593     HAL_Delay(1);
01594   }
01595   else /* InputDevice = Digital Mic */
01596   {   
01597     /* Call the Media layer stop function for MIC1 channel */
01598     if(AUDIO_OK != BSP_AUDIO_IN_PauseEx(INPUT_DEVICE_DIGITAL_MIC1))
01599     {
01600       return AUDIO_ERROR;
01601     }
01602     
01603     /* Call the Media layer stop function for MIC2 channel */
01604     if(AUDIO_OK != BSP_AUDIO_IN_PauseEx(INPUT_DEVICE_DIGITAL_MIC2))
01605     {
01606       return AUDIO_ERROR;
01607     } 
01608   }
01609   
01610   /* Return AUDIO_OK when all operations are correctly done */  
01611   return AUDIO_OK;
01612 }
01613 
01614 /**
01615   * @brief  Stops audio recording.                 
01616   * @param  InputDevice: Microphone to be stopped. Can be INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5. 
01617   * @retval AUDIO_OK if correct communication, else wrong communication
01618   */
01619 uint8_t BSP_AUDIO_IN_StopEx(uint32_t InputDevice)
01620 {
01621   if((InputDevice < INPUT_DEVICE_DIGITAL_MIC1) || (InputDevice > INPUT_DEVICE_DIGITAL_MIC5))
01622   {
01623     return AUDIO_ERROR;
01624   }
01625   else
01626   {
01627     BSP_AUDIO_IN_PauseEx(InputDevice);      
01628   }
01629   
01630   /* Return AUDIO_OK when all operations are correctly done */  
01631   return AUDIO_OK;
01632 }
01633 
01634 /**
01635   * @brief  Pauses the audio file stream.
01636   * @retval AUDIO_OK if correct communication, else wrong communication
01637   */
01638 uint8_t BSP_AUDIO_IN_Pause(void)
01639 {
01640   if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC)
01641   {
01642     return AUDIO_ERROR;
01643   }
01644   else
01645   {
01646     /* Call the Media layer stop function */
01647     if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)]))
01648     {
01649       return AUDIO_ERROR;
01650     }
01651     
01652     /* Call the Media layer stop function */
01653     if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)]))
01654     {
01655       return AUDIO_ERROR;
01656     }
01657   }
01658   /* Return AUDIO_OK when all operations are correctly done */
01659   return AUDIO_OK;
01660 }
01661 
01662 /**
01663   * @brief  Pauses the audio file stream.
01664   * @param  InputDevice: Microphone to be paused. Can be INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5.
01665   * @retval AUDIO_OK if correct communication, else wrong communication
01666   */
01667 uint8_t BSP_AUDIO_IN_PauseEx(uint32_t InputDevice)
01668 {
01669   if((InputDevice < INPUT_DEVICE_DIGITAL_MIC1) || (InputDevice > INPUT_DEVICE_DIGITAL_MIC5))
01670   {
01671     return AUDIO_ERROR;
01672   }
01673   else
01674   {
01675     /* Call the Media layer stop function */
01676     if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInDfsdmFilter[POS_VAL(InputDevice)]))
01677     {
01678       return AUDIO_ERROR;
01679     }    
01680   }
01681   /* Return AUDIO_OK when all operations are correctly done */
01682   return AUDIO_OK;
01683 }
01684 
01685 /**
01686   * @brief  Resumes the audio file stream.
01687   * @retval AUDIO_OK if correct communication, else wrong communication
01688   */
01689 uint8_t BSP_AUDIO_IN_Resume(void)
01690 { 
01691   if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC)
01692   {
01693     return AUDIO_ERROR;
01694   }
01695   else
01696   {  
01697     /* Call the Media layer start function for MIC2 channel */
01698     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], ScratchSize))
01699     {
01700       return AUDIO_ERROR;
01701     }
01702     
01703     /* Call the Media layer start function for MIC1 channel */
01704     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], ScratchSize))
01705     {
01706       return AUDIO_ERROR;
01707     }
01708   } 
01709   /* Return AUDIO_OK when all operations are correctly done */
01710   return AUDIO_OK;
01711 }
01712 
01713 /**
01714   * @brief  Resumes the audio file stream.
01715   * @param  pBuf: Main buffer pointer for the recorded data storing
01716   * @param  InputDevice: Microphone to be paused. Can be INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5.
01717   * @retval AUDIO_OK if correct communication, else wrong communication
01718   */
01719 uint8_t BSP_AUDIO_IN_ResumeEx(uint32_t *pBuf, uint32_t InputDevice)
01720 {
01721   if((InputDevice < INPUT_DEVICE_DIGITAL_MIC1) || (InputDevice > INPUT_DEVICE_DIGITAL_MIC5))
01722   {
01723     return AUDIO_ERROR;
01724   }
01725   else
01726   {  
01727     /* Call the Media layer stop function */
01728     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(InputDevice)], (int32_t*)pBuf[MicBuff[POS_VAL(InputDevice)]], hAudioIn.RecSize))
01729     {
01730       return AUDIO_ERROR;
01731     }
01732   }
01733   /* Return AUDIO_OK when all operations are correctly done */
01734   return AUDIO_OK;
01735 }
01736 
01737 /**
01738   * @brief  Controls the audio in volume level. 
01739   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for 
01740   *         Mute and 100 for Max volume level).
01741   * @retval AUDIO_OK if correct communication, else wrong communication
01742   */
01743 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume)
01744 {
01745   /* Set the Global variable AudioInVolume  */
01746   AudioInVolume = Volume; 
01747   
01748   /* Return AUDIO_OK when all operations are correctly done */
01749   return AUDIO_OK;
01750 }
01751 
01752 /**
01753   * @brief  User callback when record buffer is filled.
01754   */
01755 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void)
01756 {
01757   /* This function should be implemented by the user application.
01758      It is called into this driver when the current buffer is filled
01759      to prepare the next buffer pointer and its size. */
01760 }
01761 
01762 /**
01763   * @brief  Manages the DMA Half Transfer complete event.
01764   */
01765 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
01766 {
01767   /* This function should be implemented by the user application.
01768      It is called into this driver when the current buffer is filled
01769      to prepare the next buffer pointer and its size. */
01770 }
01771 
01772 /**
01773   * @brief  User callback when record buffer is filled.
01774   * @param InputDevice: INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5.
01775   */
01776 __weak void BSP_AUDIO_IN_TransferComplete_CallBackEx(uint32_t InputDevice)
01777 {
01778   /* This function should be implemented by the user application.
01779      It is called into this driver when the current buffer is filled
01780      to prepare the next buffer pointer and its size. */
01781 }
01782 
01783 /**
01784   * @brief  User callback when record buffer is filled.
01785   * @param InputDevice: INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5.
01786   */
01787 __weak void BSP_AUDIO_IN_HalfTransfer_CallBackEx(uint32_t InputDevice)
01788 {
01789   /* This function should be implemented by the user application.
01790      It is called into this driver when the current buffer is filled
01791      to prepare the next buffer pointer and its size. */
01792 }
01793 
01794 /**
01795   * @brief  Audio IN Error callback function.
01796   */
01797 __weak void BSP_AUDIO_IN_Error_Callback(void)
01798 {
01799   /* This function is called when an Interrupt due to transfer error on or peripheral
01800      error occurs. */
01801 }
01802 
01803 /**
01804   * @}
01805   */
01806 
01807 /*******************************************************************************
01808                             Static Functions
01809 *******************************************************************************/
01810 
01811 /**
01812   * @brief  De-initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01813   * @retval AUDIO_OK if correct communication, else wrong communication
01814   */
01815 static uint8_t DFSDMx_DeInit(void)
01816 {
01817   for(uint32_t i = 0; i < DFSDM_MIC_NUMBER; i++)
01818   {
01819     if(hAudioInDfsdmFilter[i].Instance != NULL)
01820     {
01821       if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInDfsdmFilter[i]))
01822       {
01823         return AUDIO_ERROR;
01824       }
01825       hAudioInDfsdmFilter[i].Instance = NULL;
01826     }
01827     if(hAudioInDfsdmChannel[i].Instance != NULL)
01828     {
01829       if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInDfsdmChannel[i]))
01830       {
01831         return AUDIO_ERROR;
01832       }
01833       hAudioInDfsdmChannel[i].Instance = NULL;
01834     }
01835   }
01836   return AUDIO_OK;
01837 }
01838 
01839 /**
01840   * @brief  Initializes the DFSDM channel MSP.
01841   */
01842 static void DFSDMx_ChannelMspInit(void)
01843 {
01844   GPIO_InitTypeDef  GPIO_InitStruct;
01845   
01846   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
01847   GPIO_InitStruct.Pull = GPIO_NOPULL;
01848   GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
01849   
01850   if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01851   {
01852     /* Enable DFSDM clock */
01853     AUDIO_DFSDMx_MIC1_CLK_ENABLE();
01854     /* Enable GPIO clock */
01855     AUDIO_DFSDMx_MIC1_CKOUT_DMIC_GPIO_CLK_ENABLE();
01856     
01857     /* DFSDM MIC1 pins configuration: DFSDM_CKOUT, DMIC_DATIN pins -------------*/
01858     GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC1_CKOUT_PIN;
01859     GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC1_CKOUT_DMIC_AF;
01860     HAL_GPIO_Init(AUDIO_DFSDMx_MIC1_CKOUT_DMIC_GPIO_PORT, &GPIO_InitStruct);
01861     
01862     AUDIO_DFSDMx_MIC1_DMIC_GPIO_CLK_ENABLE();
01863     GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC1_DMIC_PIN;
01864     GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC1_DMIC_AF;
01865     HAL_GPIO_Init(AUDIO_DFSDMx_MIC1_DMIC_GPIO_PORT, &GPIO_InitStruct); 
01866   }
01867   
01868   if(hAudioIn.InputDevice > INPUT_DEVICE_DIGITAL_MIC1)
01869   {
01870     /* Enable DFSDM clock */
01871     AUDIO_DFSDMx_MIC2_5_CLK_ENABLE(); 
01872     /* Enable GPIO clock */
01873     AUDIO_DFSDMx_MIC2_5_CKOUT_DMIC_GPIO_CLK_ENABLE(); 
01874     
01875     /* DFSDM MIC2 pins configuration: DFSDM_CKOUT, DMIC_DATIN pins -------------*/
01876     GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC2_5_CKOUT_PIN;
01877     GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC2_5_CKOUT_DMIC_AF;
01878     HAL_GPIO_Init(AUDIO_DFSDMx_MIC2_5_CKOUT_DMIC_GPIO_PORT, &GPIO_InitStruct);  
01879     
01880     if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) ||\
01881       ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC3) == INPUT_DEVICE_DIGITAL_MIC3))
01882     {  
01883       AUDIO_DFSDMx_MIC23_DMIC_GPIO_CLK_ENABLE();
01884       GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC23_DMIC_PIN;
01885       GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC23_DMIC_AF;
01886       HAL_GPIO_Init(AUDIO_DFSDMx_MIC23_DMIC_GPIO_PORT, &GPIO_InitStruct);
01887     }
01888     
01889     if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC4) == INPUT_DEVICE_DIGITAL_MIC4) ||\
01890       ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC5) == INPUT_DEVICE_DIGITAL_MIC5))
01891     {
01892       
01893       AUDIO_DFSDMx_MIC45_DMIC_GPIO_CLK_ENABLE();
01894       GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC45_DMIC_PIN;
01895       GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC45_DMIC_AF;
01896       HAL_GPIO_Init(AUDIO_DFSDMx_MIC45_DMIC_GPIO_PORT, &GPIO_InitStruct);  
01897     }
01898   }
01899 }
01900 
01901 /**
01902   * @brief  DeInitializes the DFSDM channel MSP.
01903   */
01904 static void DFSDMx_ChannelMspDeInit(void)
01905 {
01906   GPIO_InitTypeDef  GPIO_InitStruct;
01907   
01908   if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01909   {  
01910     /* DFSDM MIC1 pins configuration: DFSDM_CKOUT, DMIC_DATIN pins -------------*/
01911     GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC1_CKOUT_PIN;
01912     HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC1_CKOUT_DMIC_GPIO_PORT, GPIO_InitStruct.Pin);
01913     
01914     GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC1_DMIC_PIN;
01915     HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC1_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 
01916   }
01917   
01918   if(hAudioIn.InputDevice > INPUT_DEVICE_DIGITAL_MIC1)
01919   {
01920     /* DFSDM MIC2, MIC3, MIC4 and MIC5 pins configuration: DFSDM_CKOUT pin -----*/
01921     GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC2_5_CKOUT_PIN;
01922     HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC2_5_CKOUT_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 
01923     
01924     if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) ||\
01925       ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC3) == INPUT_DEVICE_DIGITAL_MIC3))
01926     {   
01927       /* DFSDM MIC2, MIC3 pins configuration:  DMIC_DATIN pin -----*/
01928       GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC23_DMIC_PIN;
01929       HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC23_DMIC_GPIO_PORT, GPIO_InitStruct.Pin);
01930     }
01931     
01932     if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC4) == INPUT_DEVICE_DIGITAL_MIC4) ||\
01933       ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC5) == INPUT_DEVICE_DIGITAL_MIC5))
01934     {
01935       /* DFSDM MIC4, MIC5 pins configuration: DMIC_DATIN pin -----*/   
01936       GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC45_DMIC_PIN;
01937       HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC45_DMIC_GPIO_PORT, GPIO_InitStruct.Pin);
01938     } 
01939   }
01940 }
01941 
01942 /**
01943   * @brief  Initializes the DFSDM filter MSP.
01944   */
01945 static void DFSDMx_FilterMspInit(void)
01946 {
01947   uint32_t i = 0, mic_num = 0, mic_init[DFSDM_MIC_NUMBER] = {0};
01948   IRQn_Type AUDIO_DFSDM_DMAx_MIC_IRQHandler[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_DMAx_MIC1_IRQ, AUDIO_DFSDMx_DMAx_MIC2_IRQ, AUDIO_DFSDMx_DMAx_MIC3_IRQ, AUDIO_DFSDMx_DMAx_MIC4_IRQ, AUDIO_DFSDMx_DMAx_MIC5_IRQ};
01949   DMA_Stream_TypeDef* AUDIO_DFSDMx_DMAx_MIC_STREAM[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_DMAx_MIC1_STREAM, AUDIO_DFSDMx_DMAx_MIC2_STREAM, AUDIO_DFSDMx_DMAx_MIC3_STREAM, AUDIO_DFSDMx_DMAx_MIC4_STREAM, AUDIO_DFSDMx_DMAx_MIC5_STREAM};
01950   uint32_t AUDIO_DFSDMx_DMAx_MIC_CHANNEL[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_DMAx_MIC1_CHANNEL, AUDIO_DFSDMx_DMAx_MIC2_CHANNEL, AUDIO_DFSDMx_DMAx_MIC3_CHANNEL, AUDIO_DFSDMx_DMAx_MIC4_CHANNEL, AUDIO_DFSDMx_DMAx_MIC5_CHANNEL};
01951   
01952   /* Enable the DMA clock */
01953   AUDIO_DFSDMx_DMAx_CLK_ENABLE();
01954   
01955   for(i = 0; i < hAudioIn.ChannelNbr; i++)
01956   {
01957     if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] != 1))
01958     {
01959       mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC1);
01960       mic_init[mic_num] = 1;
01961     }
01962     else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] != 1))
01963     {
01964       mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC2);
01965       mic_init[mic_num] = 1;
01966     }  
01967     else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC3) == INPUT_DEVICE_DIGITAL_MIC3) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)] != 1))
01968     {
01969       mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC3);
01970       mic_init[mic_num] = 1;
01971     }
01972     else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC4) == INPUT_DEVICE_DIGITAL_MIC4) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)] != 1))
01973     {
01974       mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC4);
01975       mic_init[mic_num] = 1;
01976     }
01977     else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC5) == INPUT_DEVICE_DIGITAL_MIC5) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)] != 1))
01978     {
01979       mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC5);
01980       mic_init[mic_num] = 1;
01981     } 
01982     
01983     /* Configure the hDmaDfsdm[i] handle parameters */    
01984     hDmaDfsdm[mic_num].Init.Channel             = AUDIO_DFSDMx_DMAx_MIC_CHANNEL[mic_num]; 
01985     hDmaDfsdm[mic_num].Instance                 = AUDIO_DFSDMx_DMAx_MIC_STREAM[mic_num];
01986     hDmaDfsdm[mic_num].Init.Direction           = DMA_PERIPH_TO_MEMORY;
01987     hDmaDfsdm[mic_num].Init.PeriphInc           = DMA_PINC_DISABLE;
01988     hDmaDfsdm[mic_num].Init.MemInc              = DMA_MINC_ENABLE;
01989     hDmaDfsdm[mic_num].Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
01990     hDmaDfsdm[mic_num].Init.MemDataAlignment    = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
01991     hDmaDfsdm[mic_num].Init.Mode                = DMA_CIRCULAR;
01992     hDmaDfsdm[mic_num].Init.Priority            = DMA_PRIORITY_HIGH;
01993     hDmaDfsdm[mic_num].Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
01994     hDmaDfsdm[mic_num].Init.MemBurst            = DMA_MBURST_SINGLE;
01995     hDmaDfsdm[mic_num].Init.PeriphBurst         = DMA_PBURST_SINGLE;
01996     hDmaDfsdm[mic_num].State                    = HAL_DMA_STATE_RESET;  
01997     
01998     /* Associate the DMA handle */
01999     __HAL_LINKDMA(&hAudioInDfsdmFilter[mic_num], hdmaReg, hDmaDfsdm[mic_num]);
02000     
02001     /* Reset DMA handle state */
02002     __HAL_DMA_RESET_HANDLE_STATE(&hDmaDfsdm[mic_num]);
02003     
02004     /* Configure the DMA Channel */
02005     HAL_DMA_Init(&hDmaDfsdm[mic_num]);
02006     
02007     /* DMA IRQ Channel configuration */
02008     HAL_NVIC_SetPriority(AUDIO_DFSDM_DMAx_MIC_IRQHandler[mic_num], AUDIO_IN_IRQ_PREPRIO, 0);
02009     HAL_NVIC_EnableIRQ(AUDIO_DFSDM_DMAx_MIC_IRQHandler[mic_num]);
02010   } 
02011 }
02012 
02013 /**
02014   * @brief  DeInitializes the DFSDM filter MSP.
02015   */
02016 static void DFSDMx_FilterMspDeInit(void)
02017 {
02018   /* Configure the DMA Channel */
02019   for(uint32_t i = 0; i < DFSDM_MIC_NUMBER; i++)
02020   {
02021     if(hDmaDfsdm[i].Instance != NULL)
02022     {
02023       HAL_DMA_DeInit(&hDmaDfsdm[i]); 
02024     }
02025   }  
02026 }
02027 
02028 /**
02029   * @brief  Initializes the Audio Codec audio interface (I2S)
02030   * @note   This function assumes that the I2S input clock
02031   *         is already configured and ready to be used.
02032   * @param  AudioFreq: Audio frequency to be configured for the I2S peripheral.
02033   */
02034 static void I2Sx_In_Init(uint32_t AudioFreq)
02035 {
02036   /* Initialize the hAudioInI2s and haudio_in_i2sext Instance parameters */
02037   haudio_i2s.Instance = AUDIO_IN_I2Sx;
02038   haudio_in_i2sext.Instance = I2S3ext;
02039 
02040  /* Disable I2S block */
02041   __HAL_I2S_DISABLE(&haudio_i2s);
02042   __HAL_I2S_DISABLE(&haudio_in_i2sext);
02043 
02044   /* I2S peripheral configuration */
02045   haudio_i2s.Init.AudioFreq = AudioFreq;
02046   haudio_i2s.Init.ClockSource = I2S_CLOCK_PLL;
02047   haudio_i2s.Init.CPOL = I2S_CPOL_LOW;
02048   haudio_i2s.Init.DataFormat = I2S_DATAFORMAT_16B;
02049   haudio_i2s.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
02050   haudio_i2s.Init.Mode = I2S_MODE_MASTER_TX;
02051   haudio_i2s.Init.Standard = I2S_STANDARD_PHILIPS;
02052   haudio_i2s.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_ENABLE;
02053   /* Init the I2S */
02054   HAL_I2S_Init(&haudio_i2s);
02055 
02056   /* I2Sext peripheral configuration */
02057   haudio_in_i2sext.Init.AudioFreq = AudioFreq;
02058   haudio_in_i2sext.Init.ClockSource = I2S_CLOCK_PLL;
02059   haudio_in_i2sext.Init.CPOL = I2S_CPOL_HIGH;
02060   haudio_in_i2sext.Init.DataFormat = I2S_DATAFORMAT_16B;
02061   haudio_in_i2sext.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
02062   haudio_in_i2sext.Init.Mode = I2S_MODE_SLAVE_RX;
02063   haudio_in_i2sext.Init.Standard = I2S_STANDARD_PHILIPS;
02064 
02065   /* Init the I2Sext */
02066   HAL_I2S_Init(&haudio_in_i2sext);
02067 
02068  /* Enable I2S block */
02069   __HAL_I2S_ENABLE(&haudio_i2s);
02070   __HAL_I2S_ENABLE(&haudio_in_i2sext);
02071 }
02072 
02073 /**
02074   * @brief  Deinitializes the Audio Codec audio interface (I2S).
02075   */
02076 static void I2Sx_In_DeInit(void)
02077 {
02078   /* Initialize the hAudioInI2s Instance parameter */
02079   haudio_i2s.Instance = AUDIO_IN_I2Sx;
02080 
02081  /* Disable I2S block */
02082   __HAL_I2S_DISABLE(&haudio_i2s);
02083 
02084   /* DeInit the I2S */
02085   HAL_I2S_DeInit(&haudio_i2s);
02086 
02087   /* Initialize the hAudioInI2s Instance parameter */
02088   haudio_in_i2sext.Instance = I2S3ext;
02089 
02090  /* Disable I2S block */
02091   __HAL_I2S_DISABLE(&haudio_in_i2sext);
02092 
02093   /* DeInit the I2S */
02094   HAL_I2S_DeInit(&haudio_in_i2sext);
02095 }
02096 
02097 /**
02098   * @brief  This function handles DFSDM MIC1 DMA interrupt request.
02099   * @param  None
02100   * @retval None
02101   */
02102 void AUDIO_DFSDM_DMAx_MIC1_IRQHandler(void)
02103 {
02104   HAL_DMA_IRQHandler(hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)].hdmaReg);
02105 
02106 }
02107 
02108 /**
02109   * @brief  This function handles DFSDM MIC2 DMA interrupt request.
02110   * @param  None
02111   * @retval None
02112   */
02113 void AUDIO_DFSDM_DMAx_MIC2_IRQHandler(void)
02114 {
02115   HAL_DMA_IRQHandler(hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)].hdmaReg);
02116 }
02117 
02118 /**
02119   * @brief  This function handles I2S DMA interrupt request.
02120   * @param  None
02121   * @retval None
02122   */
02123 void AUDIO_OUT_I2Sx_DMAx_IRQHandler(void)
02124 {
02125   HAL_DMA_IRQHandler(haudio_i2s.hdmatx);
02126 }
02127 
02128 /**
02129   * @}
02130   */ 
02131   
02132 /**
02133   * @}
02134   */
02135 
02136 /**
02137   * @}
02138   */
02139 
02140 /**
02141   * @}
02142   */ 
02143 
02144 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/