STM32F413H-Discovery BSP User Manual: stm32f413h_discovery_audio.c Source File

STM32F413H-Discovery BSP Drivers

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