STM32F411E-Discovery BSP User Manual: stm32f411e_discovery_audio.c Source File

STM32F411E-Discovery BSP Drivers

stm32f411e_discovery_audio.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32f411e_discovery_audio.c
00004   * @author  MCD Application Team
00005   * @version V1.0.2
00006   * @date    31-January-2017
00007   * @brief   This file provides the Audio driver for the STM32F411E-Discovery 
00008   *          board.  
00009   ******************************************************************************
00010   * @attention
00011   *
00012   * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
00013   *
00014   * Redistribution and use in source and binary forms, with or without modification,
00015   * are permitted provided that the following conditions are met:
00016   *   1. Redistributions of source code must retain the above copyright notice,
00017   *      this list of conditions and the following disclaimer.
00018   *   2. Redistributions in binary form must reproduce the above copyright notice,
00019   *      this list of conditions and the following disclaimer in the documentation
00020   *      and/or other materials provided with the distribution.
00021   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00022   *      may be used to endorse or promote products derived from this software
00023   *      without specific prior written permission.
00024   *
00025   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00026   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00028   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00029   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00030   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00031   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00032   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00033   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035   *
00036   ******************************************************************************
00037   */ 
00038 
00039 /*==============================================================================
00040                                              User NOTES
00041 1. How To use this driver:
00042 --------------------------
00043    - This driver supports STM32F411xx devices on STM32F411E-Discovery Kit:
00044         a) to play an audio file (all functions names start by BSP_AUDIO_OUT_xxx)
00045         b) to record an audio file through MP45DT02, ST MEMS (all functions names start by AUDIO_IN_xxx)
00046 
00047 a) PLAY A FILE:
00048 ==============
00049    + Call the function BSP_AUDIO_OUT_Init(
00050                                     OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 
00051                                                  OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_AUTO or 
00052                                                  OUTPUT_DEVICE_BOTH)
00053                                     Volume: initial volume to be set (0 is min (mute), 100 is max (100%)
00054                                     AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...)
00055                                     this parameter is relative to the audio file/stream type.
00056                                    )
00057       This function configures all the hardware required for the audio application (codec, I2C, I2S, 
00058       GPIOs, DMA and interrupt if needed). This function returns 0 if configuration is OK.
00059       If the returned value is different from 0 or the function is stuck then the communication with
00060       the codec (try to un-plug the power or reset device in this case).
00061       - OUTPUT_DEVICE_SPEAKER: only speaker will be set as output for the audio stream.
00062       - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream.
00063       - OUTPUT_DEVICE_AUTO: Selection of output device is made through external switch (implemented 
00064          into the audio jack on the discovery board). When the Headphone is connected it is used
00065          as output. When the headphone is disconnected from the audio jack, the output is
00066          automatically switched to Speaker.
00067       - OUTPUT_DEVICE_BOTH: both Speaker and Headphone are used as outputs for the audio stream
00068          at the same time.
00069    + Call the function BSP_AUDIO_OUT_Play(
00070                                   pBuffer: pointer to the audio data file address
00071                                   Size: size of the buffer to be sent in Bytes
00072                                  )
00073       to start playing (for the first time) from the audio file/stream.
00074    + Call the function BSP_AUDIO_OUT_Pause() to pause playing 
00075    + Call the function BSP_AUDIO_OUT_Resume() to resume playing.
00076        Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called
00077           for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case).
00078        Note. This function should be called only when the audio file is played or paused (not stopped).
00079    + For each mode, you may need to implement the relative callback functions into your code.
00080       The Callback functions are named BSP_AUDIO_OUT_XXXCallBack() and only their prototypes are declared in 
00081       the stm32f411e_discovery_audio.h file. (refer to the example for more details on the callbacks implementations)
00082    + To Stop playing, to modify the volume level, the frequency or to mute, use the functions
00083        BSP_AUDIO_OUT_Stop(), BSP_AUDIO_OUT_SetVolume(), AUDIO_OUT_SetFrequency() BSP_AUDIO_OUT_SetOutputMode and BSP_AUDIO_OUT_SetMute().
00084    + The driver API and the callback functions are at the end of the stm32f411e_discovery_audio.h file.
00085    
00086 Driver architecture:
00087 --------------------
00088    + This driver provide the High Audio Layer: consists of the function API exported in the stm32f411e_discovery_audio.h file
00089        (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...)
00090    + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/
00091        providing the audio file/stream. These functions are also included as local functions into
00092        the stm32f411e_discovery_audio.c file (I2S3_Init()...)
00093 
00094 Known Limitations:
00095 -------------------
00096    1- When using the Speaker, if the audio file quality is not high enough, the speaker output
00097       may produce high and uncomfortable noise level. To avoid this issue, to use speaker
00098       output properly, try to increase audio file sampling rate (typically higher than 48KHz).
00099       This operation will lead to larger file size.
00100    2- Communication with the audio codec (through I2C) may be corrupted if it is interrupted by some
00101       user interrupt routines (in this case, interrupts could be disabled just before the start of 
00102       communication then re-enabled when it is over). Note that this communication is only done at
00103       the configuration phase (BSP_AUDIO_OUT_Init() or BSP_AUDIO_OUT_Stop()) and when Volume control modification is 
00104       performed (BSP_AUDIO_OUT_SetVolume() or BSP_AUDIO_OUT_SetMute()or BSP_AUDIO_OUT_SetOutputMode()). 
00105       When the audio data is played, no communication is required with the audio codec.
00106    3- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 
00107       File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file.
00108    4- Supports only Stereo audio streaming. To play mono audio streams, each data should be sent twice 
00109       on the I2S or should be duplicated on the source buffer. Or convert the stream in stereo before playing.
00110    5- Supports only 16-bits audio data size.
00111 
00112 b) RECORD A FILE:
00113 ================
00114    + Call the function BSP_AUDIO_IN_Init(
00115                                     AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...)
00116                                     )
00117       This function configures all the hardware required for the audio application (I2S, 
00118       GPIOs, DMA and interrupt if needed). This function returns 0 if configuration is OK.
00119 
00120    + Call the function BSP_AUDIO_IN_Record(
00121                             pbuf Main buffer pointer for the recorded data storing  
00122                             size Current size of the recorded buffer
00123                             )
00124       to start recording from the microphone.
00125 
00126    + User needs to implement user callbacks to retrieve data saved in the record buffer
00127       (AUDIO_IN_RxHalfCpltCallback/BSP_AUDIO_IN_ReceiveComplete_CallBack)
00128 
00129    + Call the function AUDIO_IN_STOP() to stop recording 
00130 
00131 ==============================================================================*/
00132 
00133 /* Includes ------------------------------------------------------------------*/
00134 #include "stm32f411e_discovery_audio.h"
00135 
00136 /** @addtogroup BSP
00137   * @{
00138   */
00139   
00140 /** @addtogroup STM32F411E_DISCOVERY
00141   * @{
00142   */
00143 
00144 /** @defgroup STM32F411E_DISCOVERY_AUDIO STM32F411E DISCOVERY AUDIO
00145   * @brief This file includes the low layer audio driver available on STM32F411E-Discovery
00146   *        discovery board.
00147   * @{
00148   */ 
00149 
00150 /** @defgroup STM32F411E_DISCOVERY_AUDIO_Private_Types STM32F411E DISCOVERY AUDIO Private Types
00151   * @{
00152   */ 
00153 /**
00154   * @}
00155   */ 
00156   
00157 /** @defgroup STM32F411E_DISCOVERY_AUDIO_Private_Defines STM32F411E DISCOVERY AUDIO Private Defines
00158   * @{
00159   */ 
00160 /* These PLL parameters are valid when the f(VCO clock) = 1Mhz */
00161 const uint32_t I2SFreq[8] = {8000, 11025, 16000, 22050, 32000, 44100, 48000, 96000};
00162 const uint32_t I2SPLLN[8] = {256, 429, 213, 429, 426, 271, 258, 344};
00163 const uint32_t I2SPLLR[8] = {5, 4, 4, 4, 4, 6, 3, 1};
00164 /**
00165   * @}
00166   */ 
00167 
00168 /** @defgroup STM32F411E_DISCOVERY_AUDIO_Private_Macros STM32F411E DISCOVERY AUDIO Private Macros
00169   * @{
00170   */
00171 /**
00172   * @}
00173   */ 
00174   
00175 /** @defgroup STM32F411E_DISCOVERY_AUDIO_Private_Variables STM32F411E DISCOVERY AUDIO Private Variables
00176   * @{
00177   */
00178 /*##### PLAY #####*/
00179 static AUDIO_DrvTypeDef           *pAudioDrv;
00180 I2S_HandleTypeDef                 hAudioOutI2s;
00181 
00182 /*### RECORDER ###*/
00183 I2S_HandleTypeDef                 hAudioInI2s;
00184 
00185 PDMFilter_InitStruct Filter[DEFAULT_AUDIO_IN_CHANNEL_NBR];
00186 __IO uint16_t AudioInVolume = DEFAULT_AUDIO_IN_VOLUME;
00187 /**
00188   * @}
00189   */ 
00190 
00191 /** @defgroup STM32F411E_DISCOVERY_AUDIO_Private_Function_Prototypes STM32F411E DISCOVERY AUDIO Private Function Prototypes
00192   * @{
00193   */ 
00194 static uint8_t I2S3_Init(uint32_t AudioFreq);
00195 static uint8_t I2S2_Init(uint32_t AudioFreq);
00196 static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr);
00197 /**
00198   * @}
00199   */ 
00200 
00201 /** @defgroup STM32F411E_DISCOVERY_AUDIO_OUT_Private_Functions STM32F411E DISCOVERY AUDIO OUT Private Functions
00202   * @{
00203   */ 
00204 
00205 /**
00206   * @brief  Configures the audio peripherals.
00207   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
00208   *                       OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO .
00209   * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
00210   * @param  AudioFreq: Audio frequency used to play the audio stream.
00211   * @retval AUDIO_OK if correct communication, else wrong communication
00212   */
00213 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
00214 {    
00215   uint8_t ret = AUDIO_OK;
00216   
00217   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
00218   BSP_AUDIO_OUT_ClockConfig(&hAudioOutI2s, AudioFreq, NULL);
00219   
00220   /* I2S data transfer preparation:
00221   Prepare the Media to be used for the audio transfer from memory to I2S peripheral */
00222   hAudioOutI2s.Instance = I2S3;
00223   if(HAL_I2S_GetState(&hAudioOutI2s) == HAL_I2S_STATE_RESET)
00224   {
00225     /* Init the I2S MSP: this __weak function can be redefined by the application*/
00226     BSP_AUDIO_OUT_MspInit(&hAudioOutI2s, NULL);
00227   }
00228   
00229   /* I2S data transfer preparation:
00230   Prepare the Media to be used for the audio transfer from memory to I2S peripheral */
00231   /* Configure the I2S peripheral */
00232   if(I2S3_Init(AudioFreq) != AUDIO_OK)
00233   {
00234     ret = AUDIO_ERROR;
00235   }
00236   
00237   if(ret == AUDIO_OK)
00238   {
00239     /* Retieve audio codec identifier */
00240     if(((cs43l22_drv.ReadID(AUDIO_I2C_ADDRESS)) & CS43L22_ID_MASK) == CS43L22_ID)
00241     {  
00242       /* Initialize the audio driver structure */
00243       pAudioDrv = &cs43l22_drv; 
00244     }
00245     else
00246     {
00247       ret = AUDIO_ERROR;
00248     }
00249   }
00250   
00251   if(ret == AUDIO_OK)
00252   {
00253     pAudioDrv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq);
00254   }
00255   
00256   return ret;
00257 }
00258 
00259 /**
00260   * @brief  Starts playing audio stream from a data buffer for a determined size. 
00261   * @param  pBuffer: Pointer to the buffer 
00262   * @param  Size: Number of audio data BYTES.
00263   * @retval AUDIO_OK if correct communication, else wrong communication
00264   */
00265 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size)
00266 {
00267   /* Call the audio Codec Play function */
00268   if(pAudioDrv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0)
00269   {
00270     return AUDIO_ERROR;
00271   }
00272   else 
00273   {
00274     /* Update the Media layer and enable it for play */  
00275     HAL_I2S_Transmit_DMA(&hAudioOutI2s, pBuffer, DMA_MAX(Size/AUDIODATA_SIZE)); 
00276     
00277     /* Return AUDIO_OK when all operations are correctly done */
00278     return AUDIO_OK;
00279   }
00280 }
00281 
00282 /**
00283   * @brief  Sends n-Bytes on the I2S interface.
00284   * @param  pData: Pointer to data address 
00285   * @param  Size: Number of data to be written
00286   */
00287 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size)
00288 {
00289   HAL_I2S_Transmit_DMA(&hAudioOutI2s, pData, Size); 
00290 }
00291 
00292 /**
00293   * @brief   Pauses the audio file stream. In case of using DMA, the DMA Pause
00294   *          feature is used.
00295   * WARNING: When calling BSP_AUDIO_OUT_Pause() function for pause, only the
00296   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00297   *          function for resume could lead to unexpected behavior).
00298   * @retval  AUDIO_OK if correct communication, else wrong communication
00299   */
00300 uint8_t BSP_AUDIO_OUT_Pause(void)
00301 {    
00302   /* Call the Audio Codec Pause/Resume function */
00303   if(pAudioDrv->Pause(AUDIO_I2C_ADDRESS) != 0)
00304   {
00305     return AUDIO_ERROR;
00306   }
00307   else
00308   {
00309     /* Call the Media layer pause function */
00310     HAL_I2S_DMAPause(&hAudioOutI2s);
00311     
00312     /* Return AUDIO_OK when all operations are correctly done */
00313     return AUDIO_OK;
00314   }
00315 }
00316 
00317 /**
00318   * @brief   Resumes the audio file streaming.  
00319   * WARNING: When calling BSP_AUDIO_OUT_Pause() function for pause, only
00320   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00321   *          function for resume could lead to unexpected behavior).
00322   * @retval  AUDIO_OK if correct communication, else wrong communication
00323   */
00324 uint8_t BSP_AUDIO_OUT_Resume(void)
00325 {    
00326   /* Call the Audio Codec Pause/Resume function */
00327   if(pAudioDrv->Resume(AUDIO_I2C_ADDRESS) != 0)
00328   {
00329     return AUDIO_ERROR;
00330   }
00331   else
00332   {
00333     /* Call the Media layer resume function */
00334     HAL_I2S_DMAResume(&hAudioOutI2s);
00335     
00336     /* Return AUDIO_OK when all operations are correctly done */
00337     return AUDIO_OK;
00338   }
00339 }
00340 
00341 /**
00342   * @brief  Stops audio playing and Power down the Audio Codec. 
00343   * @param  Option: could be one of the following parameters 
00344   *           - CODEC_PDWN_HW: completely shut down the codec (physically). 
00345   *                            Then need to reconfigure the Codec after power on.  
00346   * @retval AUDIO_OK if correct communication, else wrong communication
00347   */
00348 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
00349 {
00350   /* Call DMA Stop to disable DMA stream before stopping codec */
00351   HAL_I2S_DMAStop(&hAudioOutI2s);
00352   
00353   /* Call Audio Codec Stop function */
00354   if(pAudioDrv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
00355   {
00356     return AUDIO_ERROR;
00357   }
00358   else
00359   {
00360     if(Option == CODEC_PDWN_HW)
00361     { 
00362       /* Wait at least 1ms */
00363       HAL_Delay(1);
00364       
00365       /* Reset the pin */
00366       HAL_GPIO_WritePin(AUDIO_RESET_GPIO, AUDIO_RESET_PIN, GPIO_PIN_RESET);
00367     }
00368     
00369     /* Return AUDIO_OK when all operations are correctly done */
00370     return AUDIO_OK;
00371   }
00372 }
00373 
00374 /**
00375   * @brief  Controls the current audio volume level. 
00376   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for 
00377   *         Mute and 100 for Max volume level).
00378   * @retval AUDIO_OK if correct communication, else wrong communication
00379   */
00380 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume)
00381 {
00382   /* Call the codec volume control function with converted volume value */
00383   if(pAudioDrv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
00384   {
00385     return AUDIO_ERROR;
00386   }
00387   else
00388   {
00389     /* Return AUDIO_OK when all operations are correctly done */
00390     return AUDIO_OK;
00391   }
00392 }
00393 
00394 /**
00395   * @brief  Enables or disables the MUTE mode by software 
00396   * @param  Cmd: could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 
00397   *         unmute the codec and restore previous volume level.
00398   * @retval AUDIO_OK if correct communication, else wrong communication
00399   */
00400 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd)
00401 { 
00402   /* Call the Codec Mute function */
00403   if(pAudioDrv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0)
00404   {
00405     return AUDIO_ERROR;
00406   }
00407   else
00408   {
00409     /* Return AUDIO_OK when all operations are correctly done */
00410     return AUDIO_OK;
00411   }
00412 }
00413 
00414 /**
00415   * @brief  Switch dynamically (while audio file is played) the output target 
00416   *         (speaker or headphone).
00417   * @note   This function modifies a global variable of the audio codec driver: OutputDev.
00418   * @param  Output: specifies the audio output target: OUTPUT_DEVICE_SPEAKER,
00419   *         OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO 
00420   * @retval AUDIO_OK if correct communication, else wrong communication
00421   */
00422 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)
00423 {
00424   /* Call the Codec output Device function */
00425   if(pAudioDrv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0)
00426   {
00427     return AUDIO_ERROR;
00428   }
00429   else
00430   {
00431     /* Return AUDIO_OK when all operations are correctly done */
00432     return AUDIO_OK;
00433   }
00434 }
00435 
00436 /**
00437   * @brief  Update the audio frequency.
00438   * @param  AudioFreq: Audio frequency used to play the audio stream.
00439   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00440   *         audio frequency. 
00441   */
00442 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)
00443 { 
00444   RCC_PeriphCLKInitTypeDef rccclkinit;
00445   
00446   /* Enable PLLI2S clock */
00447   HAL_RCCEx_GetPeriphCLKConfig(&rccclkinit);
00448   /* PLLI2S_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
00449   if ((AudioFreq & 0x7) == 0)
00450   {
00451     /* Audio frequency multiple of 8 (8/16/32/48/96/192) */
00452     /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN = 192 Mhz */
00453     /* I2SCLK = PLLI2S_VCO Output/PLLI2SR = 192/6 = 32 Mhz */
00454     rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S;
00455     rccclkinit.PLLI2S.PLLI2SN = 192;
00456     rccclkinit.PLLI2S.PLLI2SR = 6;
00457     HAL_RCCEx_PeriphCLKConfig(&rccclkinit);
00458   }
00459   else
00460   {
00461     /* Other Frequency (11.025/22.500/44.100) */
00462     /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN = 290 Mhz */
00463     /* I2SCLK = PLLI2S_VCO Output/PLLI2SR = 290/2 = 145 Mhz */
00464     rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S;
00465     rccclkinit.PLLI2S.PLLI2SN = 290;
00466     rccclkinit.PLLI2S.PLLI2SR = 2;
00467     HAL_RCCEx_PeriphCLKConfig(&rccclkinit);
00468   }
00469   
00470   /* Update the I2S audio frequency configuration */
00471   I2S3_Init(AudioFreq);
00472 }
00473 
00474 /**
00475   * @brief  Tx Transfer completed callbacks.
00476   * @param  hi2s: I2S handle
00477   */
00478 void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
00479 {
00480   if(hi2s->Instance == I2S3)
00481   {
00482     /* Call the user function which will manage directly transfer complete */  
00483     BSP_AUDIO_OUT_TransferComplete_CallBack();       
00484   }
00485 }
00486 
00487 /**
00488   * @brief  Tx Half Transfer completed callbacks.
00489   * @param  hi2s: I2S handle
00490   */
00491 void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
00492 {
00493   if(hi2s->Instance == I2S3)
00494   {
00495     /* Manage the remaining file size and new address offset: This function should
00496        be coded by user (its prototype is already declared in stm32f4_discovery_audio.h) */  
00497     BSP_AUDIO_OUT_HalfTransfer_CallBack();
00498   }
00499 }
00500 
00501 /**
00502   * @brief  Clock Config.
00503   * @param  hi2s: might be required to set audio peripheral predivider if any.
00504   * @param  AudioFreq: Audio frequency used to play the audio stream.
00505   * @note   This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency()
00506   *         Being __weak it can be overwritten by the application     
00507   * @param  Params : pointer on additional configuration parameters, can be NULL.
00508   */
00509 __weak void BSP_AUDIO_OUT_ClockConfig(I2S_HandleTypeDef *hi2s, uint32_t AudioFreq, void *Params)
00510 { 
00511   RCC_PeriphCLKInitTypeDef rccclkinit;
00512   uint8_t index = 0, freqindex = 0xFF;
00513   
00514   for(index = 0; index < 8; index++)
00515   {
00516     if(I2SFreq[index] == AudioFreq)
00517     {
00518       freqindex = index;
00519     }
00520   }
00521   /* Enable PLLI2S clock */
00522   HAL_RCCEx_GetPeriphCLKConfig(&rccclkinit);
00523   /* PLLI2S_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
00524   if ((freqindex & 0x7) == 0)
00525   {
00526     /* I2S clock config 
00527     PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) � (PLLI2SN/PLLM)
00528     I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
00529     rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S;
00530     rccclkinit.PLLI2S.PLLI2SM = 8;
00531     rccclkinit.PLLI2S.PLLI2SN = I2SPLLN[freqindex];
00532     rccclkinit.PLLI2S.PLLI2SR = I2SPLLR[freqindex];
00533     HAL_RCCEx_PeriphCLKConfig(&rccclkinit);
00534   }
00535   else 
00536   {
00537     /* I2S clock config 
00538     PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) � (PLLI2SN/PLLM)
00539     I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
00540     rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S;
00541     rccclkinit.PLLI2S.PLLI2SM = 8;
00542     rccclkinit.PLLI2S.PLLI2SN = 258;
00543     rccclkinit.PLLI2S.PLLI2SR = 3;
00544     HAL_RCCEx_PeriphCLKConfig(&rccclkinit);
00545   }
00546 }
00547 
00548 /**
00549   * @brief  AUDIO OUT I2S MSP Init.
00550   * @param  hi2s: might be required to set audio peripheral predivider if any.
00551   * @param  Params : pointer on additional configuration parameters, can be NULL.
00552   */
00553 __weak void BSP_AUDIO_OUT_MspInit(I2S_HandleTypeDef *hi2s, void *Params)
00554 {
00555   static DMA_HandleTypeDef hdma_i2sTx;
00556   GPIO_InitTypeDef  GPIO_InitStruct;
00557 
00558   /* Enable I2S3 clock */
00559   I2S3_CLK_ENABLE();
00560 
00561   /*** Configure the GPIOs ***/  
00562   /* Enable I2S GPIO clocks */
00563   I2S3_SCK_SD_CLK_ENABLE();
00564   I2S3_WS_CLK_ENABLE();
00565 
00566   /* I2S3 pins configuration: WS, SCK and SD pins ----------------------------*/
00567   GPIO_InitStruct.Pin         = I2S3_SCK_PIN | I2S3_SD_PIN; 
00568   GPIO_InitStruct.Mode        = GPIO_MODE_AF_PP;
00569   GPIO_InitStruct.Pull        = GPIO_NOPULL;
00570   GPIO_InitStruct.Speed       = GPIO_SPEED_FAST;
00571   GPIO_InitStruct.Alternate   = I2S3_SCK_SD_WS_AF;
00572   HAL_GPIO_Init(I2S3_SCK_SD_GPIO_PORT, &GPIO_InitStruct);
00573   
00574   GPIO_InitStruct.Pin         = I2S3_WS_PIN ;
00575   HAL_GPIO_Init(I2S3_WS_GPIO_PORT, &GPIO_InitStruct); 
00576 
00577   /* I2S3 pins configuration: MCK pin */
00578   I2S3_MCK_CLK_ENABLE();
00579   GPIO_InitStruct.Pin         = I2S3_MCK_PIN; 
00580   HAL_GPIO_Init(I2S3_MCK_GPIO_PORT, &GPIO_InitStruct);   
00581 
00582   /* Enable the I2S DMA clock */
00583   I2S3_DMAx_CLK_ENABLE(); 
00584   
00585   if(hi2s->Instance == I2S3)
00586   {
00587     /* Configure the hdma_i2sTx handle parameters */   
00588     hdma_i2sTx.Init.Channel             = I2S3_DMAx_CHANNEL;  
00589     hdma_i2sTx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
00590     hdma_i2sTx.Init.PeriphInc           = DMA_PINC_DISABLE;
00591     hdma_i2sTx.Init.MemInc              = DMA_MINC_ENABLE;
00592     hdma_i2sTx.Init.PeriphDataAlignment = I2S3_DMAx_PERIPH_DATA_SIZE;
00593     hdma_i2sTx.Init.MemDataAlignment    = I2S3_DMAx_MEM_DATA_SIZE;
00594     hdma_i2sTx.Init.Mode                = DMA_NORMAL;
00595     hdma_i2sTx.Init.Priority            = DMA_PRIORITY_HIGH;
00596     hdma_i2sTx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;         
00597     hdma_i2sTx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
00598     hdma_i2sTx.Init.MemBurst            = DMA_MBURST_SINGLE;
00599     hdma_i2sTx.Init.PeriphBurst         = DMA_PBURST_SINGLE; 
00600 
00601     hdma_i2sTx.Instance                 = I2S3_DMAx_STREAM;
00602 
00603     /* Associate the DMA handle */
00604     __HAL_LINKDMA(hi2s, hdmatx, hdma_i2sTx);
00605     
00606     /* Deinitialize the Stream for new transfer */
00607     HAL_DMA_DeInit(&hdma_i2sTx);
00608     
00609     /* Configure the DMA Stream */
00610     HAL_DMA_Init(&hdma_i2sTx);
00611   }
00612   
00613   /* I2S DMA IRQ Channel configuration */
00614   HAL_NVIC_SetPriority(I2S3_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
00615   HAL_NVIC_EnableIRQ(I2S3_DMAx_IRQ);  
00616 }
00617 
00618 /**
00619   * @brief  De-Initializes BSP_AUDIO_OUT MSP.
00620   * @param  hi2s: might be required to set audio peripheral predivider if any.
00621   * @param  Params : pointer on additional configuration parameters, can be NULL.
00622   */
00623 __weak void BSP_AUDIO_OUT_MspDeInit(I2S_HandleTypeDef *hi2s, void *Params)
00624 {  
00625   GPIO_InitTypeDef  GPIO_InitStruct;
00626 
00627   /* I2S DMA IRQ Channel deactivation */
00628   HAL_NVIC_DisableIRQ(I2S3_DMAx_IRQ); 
00629   
00630   if(hi2s->Instance == I2S3)
00631   {
00632     /* Deinitialize the Stream for new transfer */
00633     HAL_DMA_DeInit(hi2s->hdmatx);
00634   }
00635 
00636  /* Disable I2S block */
00637   __HAL_I2S_DISABLE(hi2s);
00638 
00639   /* CODEC_I2S pins configuration: SCK and SD pins */
00640   GPIO_InitStruct.Pin = I2S3_SCK_PIN | I2S3_SD_PIN;
00641   HAL_GPIO_DeInit(I2S3_SCK_SD_GPIO_PORT, GPIO_InitStruct.Pin);
00642   
00643   /* CODEC_I2S pins configuration: WS pin */
00644   GPIO_InitStruct.Pin = I2S3_WS_PIN;
00645   HAL_GPIO_DeInit(I2S3_WS_GPIO_PORT, GPIO_InitStruct.Pin);
00646   
00647   /* CODEC_I2S pins configuration: MCK pin */
00648   GPIO_InitStruct.Pin = I2S3_MCK_PIN;
00649   HAL_GPIO_DeInit(I2S3_MCK_GPIO_PORT, GPIO_InitStruct.Pin); 
00650 
00651   /* Disable I2S clock */
00652   I2S3_CLK_DISABLE();
00653 
00654   /* GPIO pins clock and DMA clock can be shut down in the applic 
00655      by surcgarging this __weak function */   
00656 }
00657 
00658 /**
00659   * @brief  Manages the DMA full Transfer complete event.
00660   */
00661 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
00662 {
00663 }
00664 
00665 /**
00666   * @brief  Manages the DMA Half Transfer complete event.
00667   */
00668 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void)
00669 {
00670 }
00671 
00672 /**
00673   * @brief  Manages the DMA FIFO error event.
00674   */
00675 __weak void BSP_AUDIO_OUT_Error_CallBack(void)
00676 {
00677 }
00678 
00679 /*******************************************************************************
00680                             Static Functions
00681 *******************************************************************************/
00682 
00683 /**
00684   * @brief  Initializes the Audio Codec audio interface (I2S).
00685   * @param  AudioFreq: Audio frequency to be configured for the I2S peripheral. 
00686   */
00687 static uint8_t I2S3_Init(uint32_t AudioFreq)
00688 {
00689   /* Initialize the hAudioOutI2s Instance parameter */
00690   hAudioOutI2s.Instance         = I2S3;
00691   
00692   /* Disable I2S block */
00693   __HAL_I2S_DISABLE(&hAudioOutI2s);
00694   
00695   /* I2S3 peripheral configuration */
00696   hAudioOutI2s.Init.AudioFreq   = AudioFreq;
00697   hAudioOutI2s.Init.ClockSource = I2S_CLOCK_PLL;
00698   hAudioOutI2s.Init.CPOL        = I2S_CPOL_LOW;
00699   hAudioOutI2s.Init.DataFormat  = I2S_DATAFORMAT_16B;
00700   hAudioOutI2s.Init.MCLKOutput  = I2S_MCLKOUTPUT_ENABLE;
00701   hAudioOutI2s.Init.Mode        = I2S_MODE_MASTER_TX;
00702   hAudioOutI2s.Init.Standard    = I2S_STANDARD;
00703 
00704   /* Initialize the I2S peripheral with the structure above */
00705   if(HAL_I2S_Init(&hAudioOutI2s) != HAL_OK)
00706   {
00707     return AUDIO_ERROR;
00708   }
00709   else
00710   {
00711     return AUDIO_OK;
00712   }
00713 }
00714   
00715 /**
00716   * @}
00717   */ 
00718   
00719 /** @defgroup STM32F411E_DISCOVERY_AUDIO_IN_Private_Functions STM32F411EDISCOVERY AUDIO IN Private Functions
00720   * @{
00721   */ 
00722   
00723 /**
00724   * @brief  Initializes wave recording.
00725   * @param  AudioFreq: Audio frequency to be configured for the I2S peripheral. 
00726   * @param  BitRes: Audio Bit resolution.
00727   * @param  ChnlNbr: Audio Channel number.
00728   * @retval AUDIO_OK if correct communication, else wrong communication
00729   */
00730 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00731 {  
00732   /* Configure PLL clock */ 
00733   BSP_AUDIO_IN_ClockConfig(&hAudioInI2s, AudioFreq, NULL);
00734   
00735   /* Configure the PDM library */
00736   PDMDecoder_Init(AudioFreq, ChnlNbr);
00737 
00738   /* Configure the I2S peripheral */
00739   hAudioInI2s.Instance = I2S2;
00740   if(HAL_I2S_GetState(&hAudioInI2s) == HAL_I2S_STATE_RESET)
00741   { 
00742     /* Initialize the I2S Msp: this __weak function can be rewritten by the application */
00743     BSP_AUDIO_IN_MspInit(&hAudioInI2s, NULL);
00744   }
00745   
00746   /* Configure the I2S2 */
00747   I2S2_Init(AudioFreq);
00748   
00749   /* Return AUDIO_OK when all operations are correctly done */
00750   return AUDIO_OK;
00751 }
00752 
00753 /**
00754   * @brief  Starts audio recording.
00755   * @param  pbuf: Main buffer pointer for the recorded data storing  
00756   * @param  size: Current size of the recorded buffer
00757   * @retval AUDIO_OK if correct communication, else wrong communication
00758   */
00759 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size)
00760 {
00761   uint32_t ret = AUDIO_ERROR;
00762   
00763   /* Start the process receive DMA */
00764   HAL_I2S_Receive_DMA(&hAudioInI2s, pbuf, size);
00765   
00766   /* Return AUDIO_OK when all operations are correctly done */
00767   ret = AUDIO_OK;
00768   
00769   return ret;
00770 }
00771 
00772 /**
00773   * @brief  Stops audio recording.
00774   */
00775 uint8_t BSP_AUDIO_IN_Stop(void)
00776 {
00777   uint32_t ret = AUDIO_ERROR;
00778   
00779   /* Call the Media layer pause function */
00780   HAL_I2S_DMAStop(&hAudioInI2s);  
00781   
00782   /* Return AUDIO_OK when all operations are correctly done */
00783   ret = AUDIO_OK;
00784   
00785   return ret;
00786 }
00787 
00788 /**
00789   * @brief  Pauses the audio file stream.
00790   * @retval AUDIO_OK if correct communication, else wrong communication
00791   */
00792 uint8_t BSP_AUDIO_IN_Pause(void)
00793 {    
00794   /* Call the Media layer pause function */
00795   HAL_I2S_DMAPause(&hAudioInI2s);
00796   
00797   /* Return AUDIO_OK when all operations are correctly done */
00798   return AUDIO_OK;
00799 }
00800 
00801 /**
00802   * @brief  Resumes the audio file stream.
00803   * @retval AUDIO_OK if correct communication, else wrong communication
00804   */
00805 uint8_t BSP_AUDIO_IN_Resume(void)
00806 {    
00807   /* Call the Media layer pause/resume function */
00808   HAL_I2S_DMAResume(&hAudioInI2s);
00809   
00810   /* Return AUDIO_OK when all operations are correctly done */
00811   return AUDIO_OK;
00812 }
00813 
00814 /**
00815   * @brief  Controls the audio in volume level. 
00816   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for 
00817   *         Mute and 100 for Max volume level).
00818   * @retval AUDIO_OK if correct communication, else wrong communication
00819   */
00820 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume)
00821 {
00822   /* Set the Global variable AudioInVolume */
00823   AudioInVolume = Volume; 
00824   
00825   /* Return AUDIO_OK when all operations are correctly done */
00826   return AUDIO_OK;
00827 }
00828 
00829 /**
00830   * @brief  Converts audio format from PDM to PCM. 
00831   * @param  PDMBuf: Pointer to data PDM buffer
00832   * @param  PCMBuf: Pointer to data PCM buffer
00833   * @retval AUDIO_OK if correct communication, else wrong communication
00834   */
00835 uint8_t BSP_AUDIO_IN_PDMToPCM(uint16_t *PDMBuf, uint16_t *PCMBuf)
00836 {
00837   uint16_t AppPDM[INTERNAL_BUFF_SIZE/2];
00838   uint32_t index = 0; 
00839   
00840   /* PDM Demux */
00841   for(index = 0; index<INTERNAL_BUFF_SIZE/2; index++)
00842   {
00843     AppPDM[index] = HTONS(PDMBuf[index]);
00844   }
00845   
00846   for(index = 0; index < DEFAULT_AUDIO_IN_CHANNEL_NBR; index++)
00847   {
00848     /* PDM to PCM filter */
00849     PDM_Filter_64_LSB((uint8_t*)&AppPDM[index], (uint16_t*)&(PCMBuf[index]), AudioInVolume , (PDMFilter_InitStruct *)&Filter[index]);
00850   }
00851   
00852   /* Duplicate samples since a single microphone in mounted on STM32F4-Discovery */
00853   for(index = 0; index < PCM_OUT_SIZE; index++)
00854   {
00855     PCMBuf[(index<<1)+1] = PCMBuf[index<<1];
00856   }
00857         
00858   /* Return AUDIO_OK when all operations are correctly done */
00859   return AUDIO_OK; 
00860 }
00861 
00862 /**
00863   * @brief  Rx Transfer completed callbacks
00864   * @param  hi2s: I2S handle
00865   */
00866 void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
00867 {
00868   /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
00869   BSP_AUDIO_IN_TransferComplete_CallBack();
00870 }
00871 
00872 /**
00873   * @brief  Rx Half Transfer completed callbacks.
00874   * @param  hi2s: I2S handle
00875   */
00876 void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
00877 {
00878   /* Manage the remaining file size and new address offset: This function 
00879      should be coded by user (its prototype is already declared in stm32f4_discovery_audio.h) */
00880   BSP_AUDIO_IN_HalfTransfer_CallBack();
00881 }
00882 
00883 /**
00884   * @brief  Audio In Clock Config.
00885   * @param  hi2s: I2S handle
00886   * @param  AudioFreq: Audio frequency used to record the audio stream.  
00887   * @param  Params : pointer on additional configuration parameters, can be NULL.   
00888   * @note   This API is called by BSP_AUDIO_IN_Init()
00889   *         Being __weak it can be overwritten by the application
00890   */
00891 __weak void BSP_AUDIO_IN_ClockConfig(I2S_HandleTypeDef *hi2s, uint32_t AudioFreq, void *Params)
00892 {
00893   RCC_PeriphCLKInitTypeDef rccclkinit;
00894   
00895   /* Enable PLLI2S clock */
00896   HAL_RCCEx_GetPeriphCLKConfig(&rccclkinit);
00897   /* PLLI2S_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
00898   if ((AudioFreq & 0x7) == 0)
00899   {
00900     /* Audio frequency multiple of 8 (8/16/32/48/96/192)*/
00901     /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN = 192 Mhz */
00902     /* I2SCLK = PLLI2S_VCO Output/PLLI2SR = 192/6 = 32 Mhz */
00903     rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S;
00904     rccclkinit.PLLI2S.PLLI2SM = 8;
00905     rccclkinit.PLLI2S.PLLI2SN = 192;
00906     rccclkinit.PLLI2S.PLLI2SR = 6;
00907     HAL_RCCEx_PeriphCLKConfig(&rccclkinit);
00908   }
00909   else
00910   {
00911     /* Other Frequency (11.025/22.500/44.100) */
00912     /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN = 290 Mhz */
00913     /* I2SCLK = PLLI2S_VCO Output/PLLI2SR = 290/2 = 145 Mhz */
00914     rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S;
00915     rccclkinit.PLLI2S.PLLI2SM = 8;
00916     rccclkinit.PLLI2S.PLLI2SN = 290;
00917     rccclkinit.PLLI2S.PLLI2SR = 2;
00918     HAL_RCCEx_PeriphCLKConfig(&rccclkinit);
00919   }
00920 }
00921 
00922 /**
00923   * @brief  BSP AUDIO IN MSP Init.
00924   * @param  hi2s: I2S handle
00925   * @param  Params : pointer on additional configuration parameters, can be NULL.
00926   */
00927 __weak void BSP_AUDIO_IN_MspInit(I2S_HandleTypeDef *hi2s, void *Params)
00928 {
00929   static DMA_HandleTypeDef hdma_i2sRx;
00930   GPIO_InitTypeDef  GPIO_InitStruct;
00931 
00932   /* Enable the I2S2 peripheral clock */
00933   I2S2_CLK_ENABLE();
00934 
00935   /* Enable I2S GPIO clocks */
00936   I2S2_SCK_GPIO_CLK_ENABLE();
00937   I2S2_MOSI_GPIO_CLK_ENABLE();
00938   
00939   /* I2S2 pins configuration: SCK and MOSI pins ------------------------------*/
00940   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
00941   GPIO_InitStruct.Pull = GPIO_NOPULL;
00942   GPIO_InitStruct.Speed     = GPIO_SPEED_FAST;
00943 
00944   GPIO_InitStruct.Pin = I2S2_SCK_PIN; 
00945   GPIO_InitStruct.Alternate  = I2S2_SCK_AF;
00946   HAL_GPIO_Init(I2S2_SCK_GPIO_PORT, &GPIO_InitStruct);
00947   
00948   GPIO_InitStruct.Pin = I2S2_MOSI_PIN ;
00949   GPIO_InitStruct.Alternate  = I2S2_MOSI_AF;
00950   HAL_GPIO_Init(I2S2_MOSI_GPIO_PORT, &GPIO_InitStruct); 
00951 
00952   /* Enable the DMA clock */
00953   I2S2_DMAx_CLK_ENABLE();
00954     
00955   if(hi2s->Instance == I2S2)
00956   {
00957     /* Configure the hdma_i2sRx handle parameters */   
00958     hdma_i2sRx.Init.Channel             = I2S2_DMAx_CHANNEL;
00959     hdma_i2sRx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
00960     hdma_i2sRx.Init.PeriphInc           = DMA_PINC_DISABLE;
00961     hdma_i2sRx.Init.MemInc              = DMA_MINC_ENABLE;
00962     hdma_i2sRx.Init.PeriphDataAlignment = I2S2_DMAx_PERIPH_DATA_SIZE;
00963     hdma_i2sRx.Init.MemDataAlignment    = I2S2_DMAx_MEM_DATA_SIZE;
00964     hdma_i2sRx.Init.Mode                = DMA_CIRCULAR;
00965     hdma_i2sRx.Init.Priority            = DMA_PRIORITY_HIGH;
00966     hdma_i2sRx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;         
00967     hdma_i2sRx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
00968     hdma_i2sRx.Init.MemBurst            = DMA_MBURST_SINGLE;
00969     hdma_i2sRx.Init.PeriphBurst         = DMA_MBURST_SINGLE; 
00970     
00971     hdma_i2sRx.Instance = I2S2_DMAx_STREAM;
00972     
00973     /* Associate the DMA handle */
00974     __HAL_LINKDMA(hi2s, hdmarx, hdma_i2sRx);
00975     
00976     /* Deinitialize the Stream for new transfer */
00977     HAL_DMA_DeInit(&hdma_i2sRx);
00978     
00979     /* Configure the DMA Stream */
00980     HAL_DMA_Init(&hdma_i2sRx);      
00981   }
00982   
00983   /* I2S DMA IRQ Channel configuration */
00984   HAL_NVIC_SetPriority(I2S2_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
00985   HAL_NVIC_EnableIRQ(I2S2_DMAx_IRQ); 
00986 }
00987 
00988 /**
00989   * @brief  DeInitializes BSP_AUDIO_IN MSP.
00990   * @param  hi2s: I2S handle
00991   * @param  Params : pointer on additional configuration parameters, can be NULL.
00992   */
00993 __weak void BSP_AUDIO_IN_MspDeInit(I2S_HandleTypeDef *hi2s, void *Params)
00994 {
00995   GPIO_InitTypeDef  gpio_init_structure;
00996 
00997   /* I2S DMA IRQ Channel deactivation */
00998   HAL_NVIC_DisableIRQ(I2S2_DMAx_IRQ); 
00999   
01000   if(hi2s->Instance == I2S2)
01001   {
01002     /* Deinitialize the Stream for new transfer */
01003     HAL_DMA_DeInit(hi2s->hdmarx);
01004   }
01005 
01006  /* Disable I2S block */
01007   __HAL_I2S_DISABLE(hi2s);
01008 
01009   /* Disable pins: SCK and SD pins */
01010   gpio_init_structure.Pin = I2S2_SCK_PIN;
01011   HAL_GPIO_DeInit(I2S2_SCK_GPIO_PORT, gpio_init_structure.Pin);
01012   gpio_init_structure.Pin = I2S2_MOSI_PIN;
01013   HAL_GPIO_DeInit(I2S2_MOSI_GPIO_PORT, gpio_init_structure.Pin); 
01014 
01015   /* Disable I2S clock */
01016   I2S2_CLK_DISABLE();
01017 
01018   /* GPIO pins clock and DMA clock can be shut down in the applic 
01019      by surcgarging this __weak function */ 
01020 }
01021 
01022 /**
01023   * @brief  User callback when record buffer is filled.
01024   */
01025 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void)
01026 {
01027   /* This function should be implemented by the user application.
01028      It is called into this driver when the current buffer is filled
01029      to prepare the next buffer pointer and its size. */
01030 }
01031 
01032 /**
01033   * @brief  Manages the DMA Half Transfer complete event.
01034   */
01035 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
01036 {
01037   /* This function should be implemented by the user application.
01038      It is called into this driver when the current buffer is filled
01039      to prepare the next buffer pointer and its size. */
01040 }
01041 
01042 /**
01043   * @brief  Audio IN Error callback function.
01044   */
01045 __weak void BSP_AUDIO_IN_Error_Callback(void)
01046 {   
01047   /* This function is called when an Interrupt due to transfer error on or peripheral
01048      error occurs. */
01049 }
01050 
01051 /*******************************************************************************
01052                             Static Functions
01053 *******************************************************************************/
01054 
01055 /**
01056   * @brief  Initialize the PDM library.
01057   * @param  AudioFreq: Audio sampling frequency
01058   * @param  ChnlNbr: Number of audio channels (1: mono; 2: stereo)
01059   */
01060 static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr)
01061 { 
01062   uint32_t i = 0;
01063   
01064   /* Enable CRC peripheral to unlock the PDM library */
01065   __CRC_CLK_ENABLE();
01066   
01067   for(i = 0; i < ChnlNbr; i++)
01068   {
01069     /* Filter LP and HP Init */
01070     Filter[i].LP_HZ = AudioFreq / 2;
01071     Filter[i].HP_HZ = 10;
01072     Filter[i].Fs = AudioFreq;
01073         /* On STM32F411E-Discovery a single microphone is mounted, samples are duplicated
01074        to make stereo audio streams */
01075     Filter[i].Out_MicChannels = 2;
01076     Filter[i].In_MicChannels = ChnlNbr; 
01077     PDM_Filter_Init((PDMFilter_InitStruct *)&Filter[i]);
01078   }  
01079 }
01080 
01081 /**
01082   * @brief  Initializes the Audio Codec audio interface (I2S)
01083   * @note   This function assumes that the I2S input clock (through PLL_R in 
01084   *         Devices RevA/Z and through dedicated PLLI2S_R in Devices RevB/Y)
01085   *         is already configured and ready to be used.    
01086   * @param  AudioFreq: Audio frequency to be configured for the I2S peripheral. 
01087   */
01088 static uint8_t I2S2_Init(uint32_t AudioFreq)
01089 {
01090   /* Initialize the hAudioInI2s Instance parameter */
01091   hAudioInI2s.Instance          = I2S2;
01092   
01093   /* Disable I2S block */
01094   __HAL_I2S_DISABLE(&hAudioInI2s);
01095   
01096   /* I2S2 peripheral configuration */
01097   hAudioInI2s.Init.AudioFreq    = 2 * AudioFreq;
01098   hAudioInI2s.Init.ClockSource  = I2S_CLOCK_PLL;
01099   hAudioInI2s.Init.CPOL         = I2S_CPOL_HIGH;
01100   hAudioInI2s.Init.DataFormat   = I2S_DATAFORMAT_16B;
01101   hAudioInI2s.Init.MCLKOutput   = I2S_MCLKOUTPUT_DISABLE;
01102   hAudioInI2s.Init.Mode         = I2S_MODE_MASTER_RX;
01103   hAudioInI2s.Init.Standard     = I2S_STANDARD_LSB;
01104   
01105   /* Initialize the I2S peripheral with the structure above */  
01106   if(HAL_I2S_Init(&hAudioInI2s) != HAL_OK)
01107   {
01108     return AUDIO_ERROR;
01109   }
01110   else
01111   {
01112     return AUDIO_OK; 
01113   }
01114 }
01115 /**
01116   * @}
01117   */
01118 
01119 /** @defgroup STM32F411E_DISCOVERY_AUDIO_IN_OUT_Private_Functions STM32F411E DISCOVERY AUDIO IN OUT Private Functions
01120   * @{
01121   */ 
01122   
01123 /**
01124   * @brief  I2S error callbacks.
01125   * @param  hi2s: I2S handle
01126   */
01127 void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s)
01128 {
01129   /* Manage the error generated on DMA FIFO: This function 
01130      should be coded by user (its prototype is already declared in stm32f411e_discovery_audio.h) */ 
01131   if(hi2s->Instance == I2S3)
01132   {
01133     BSP_AUDIO_OUT_Error_CallBack();
01134   }
01135   if(hi2s->Instance == I2S2)
01136   {
01137     BSP_AUDIO_IN_Error_Callback();
01138   }
01139 }
01140 
01141 /**
01142   * @}
01143   */ 
01144   
01145 /**
01146   * @}
01147   */
01148 
01149 /**
01150   * @}
01151   */
01152 
01153 /**
01154   * @}
01155   */
01156 
01157 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Fri Jan 20 2017 11:38:17 for STM32F411E-Discovery BSP User Manual by   doxygen 1.7.6.1