STM32412G-Discovery BSP User Manual: stm32412g_discovery_audio.c Source File

STM32412G-Discovery BSP Drivers

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