Contains the BSP driver for the DISCO_F413ZH board.

Dependents:   DISCO_F413ZH-LCD-demo DISCO_F413ZH-touch-screen-demo DISCO_F413ZH-SD-demo DISCO_F413ZH-PSRAM-demo ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32f413h_discovery_audio.c Source File

stm32f413h_discovery_audio.c

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