STM32F4-Discovery BSP User Manual: stm32f4_discovery_audio.c Source File

STM32F4-Discovery BSP

stm32f4_discovery_audio.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32f4_discovery_audio.c
00004   * @author  MCD Application Team
00005   * @version V2.1.2
00006   * @date    31-January-2017
00007   * @brief   This file provides the Audio driver for the STM32F4-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 STM32F4xx devices on STM32F4-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 stm32f4_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 stm32f4_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 stm32f4_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 stm32f4_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 "stm32f4_discovery_audio.h"
00135 
00136 /** @addtogroup BSP
00137   * @{
00138   */
00139   
00140 /** @addtogroup STM32F4_DISCOVERY
00141   * @{
00142   */
00143 
00144 /** @defgroup STM32F4_DISCOVERY_AUDIO STM32F4 DISCOVERY AUDIO
00145   * @brief This file includes the low layer audio driver available on STM32F4-Discovery
00146   *        discovery board.
00147   * @{
00148   */ 
00149 
00150 /** @defgroup STM32F4_DISCOVERY_AUDIO_Private_Types STM32F4 DISCOVERY AUDIO Private Types
00151   * @{
00152   */ 
00153 /**
00154   * @}
00155   */ 
00156   
00157 /** @defgroup STM32F4_DISCOVERY_AUDIO_Private_Defines STM32F4 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 STM32F4_DISCOVERY_AUDIO_Private_Macros STM32F4 DISCOVERY AUDIO Private Macros
00169   * @{
00170   */
00171 /**
00172   * @}
00173   */ 
00174   
00175 /** @defgroup STM32F4_DISCOVERY_AUDIO_Private_Variables STM32F4 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 STM32F4_DISCOVERY_AUDIO_Private_Function_Prototypes STM32F4 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 STM32F4_DISCOVERY_AUDIO_OUT_Private_Functions STM32F4 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   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
00445   BSP_AUDIO_OUT_ClockConfig(&hAudioOutI2s, AudioFreq, NULL);
00446   
00447   /* Update the I2S audio frequency configuration */
00448   I2S3_Init(AudioFreq);
00449 }
00450 
00451 /**
00452   * @brief  Tx Transfer completed callbacks.
00453   * @param  hi2s: I2S handle
00454   */
00455 void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
00456 {
00457   if(hi2s->Instance == I2S3)
00458   {
00459     /* Call the user function which will manage directly transfer complete */  
00460     BSP_AUDIO_OUT_TransferComplete_CallBack();       
00461   }
00462 }
00463 
00464 /**
00465   * @brief  Tx Half Transfer completed callbacks.
00466   * @param  hi2s: I2S handle
00467   */
00468 void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
00469 {
00470   if(hi2s->Instance == I2S3)
00471   {
00472     /* Manage the remaining file size and new address offset: This function should
00473        be coded by user (its prototype is already declared in stm32f4_discovery_audio.h) */  
00474     BSP_AUDIO_OUT_HalfTransfer_CallBack();
00475   }
00476 }
00477 
00478 /**
00479   * @brief  Clock Config.
00480   * @param  hi2s: might be required to set audio peripheral predivider if any.
00481   * @param  AudioFreq: Audio frequency used to play the audio stream.
00482   * @note   This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency()
00483   *         Being __weak it can be overwritten by the application     
00484   * @param  Params : pointer on additional configuration parameters, can be NULL.
00485   */
00486 __weak void BSP_AUDIO_OUT_ClockConfig(I2S_HandleTypeDef *hi2s, uint32_t AudioFreq, void *Params)
00487 { 
00488   RCC_PeriphCLKInitTypeDef rccclkinit;
00489   uint8_t index = 0, freqindex = 0xFF;
00490   
00491   for(index = 0; index < 8; index++)
00492   {
00493     if(I2SFreq[index] == AudioFreq)
00494     {
00495       freqindex = index;
00496     }
00497   }
00498   /* Enable PLLI2S clock */
00499   HAL_RCCEx_GetPeriphCLKConfig(&rccclkinit);
00500   /* PLLI2S_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
00501   if ((freqindex & 0x7) == 0)
00502   {
00503     /* I2S clock config 
00504     PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) � (PLLI2SN/PLLM)
00505     I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
00506     rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S;
00507     rccclkinit.PLLI2S.PLLI2SN = I2SPLLN[freqindex];
00508     rccclkinit.PLLI2S.PLLI2SR = I2SPLLR[freqindex];
00509     HAL_RCCEx_PeriphCLKConfig(&rccclkinit);
00510   }
00511   else 
00512   {
00513     /* I2S clock config 
00514     PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) � (PLLI2SN/PLLM)
00515     I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
00516     rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S;
00517     rccclkinit.PLLI2S.PLLI2SN = 258;
00518     rccclkinit.PLLI2S.PLLI2SR = 3;
00519     HAL_RCCEx_PeriphCLKConfig(&rccclkinit);
00520   }
00521 }
00522 
00523 /**
00524   * @brief  AUDIO OUT I2S MSP Init.
00525   * @param  hi2s: might be required to set audio peripheral predivider if any.
00526   * @param  Params : pointer on additional configuration parameters, can be NULL.
00527   */
00528 __weak void BSP_AUDIO_OUT_MspInit(I2S_HandleTypeDef *hi2s, void *Params)
00529 {
00530   static DMA_HandleTypeDef hdma_i2sTx;
00531   GPIO_InitTypeDef  GPIO_InitStruct;
00532   
00533   /* Enable I2S3 clock */
00534   I2S3_CLK_ENABLE();
00535   
00536   /*** Configure the GPIOs ***/  
00537   /* Enable I2S GPIO clocks */
00538   I2S3_SCK_SD_CLK_ENABLE();
00539   I2S3_WS_CLK_ENABLE();
00540   
00541   /* I2S3 pins configuration: WS, SCK and SD pins ----------------------------*/
00542   GPIO_InitStruct.Pin         = I2S3_SCK_PIN | I2S3_SD_PIN; 
00543   GPIO_InitStruct.Mode        = GPIO_MODE_AF_PP;
00544   GPIO_InitStruct.Pull        = GPIO_NOPULL;
00545   GPIO_InitStruct.Speed       = GPIO_SPEED_FAST;
00546   GPIO_InitStruct.Alternate   = I2S3_SCK_SD_WS_AF;
00547   HAL_GPIO_Init(I2S3_SCK_SD_GPIO_PORT, &GPIO_InitStruct);
00548   
00549   GPIO_InitStruct.Pin         = I2S3_WS_PIN ;
00550   HAL_GPIO_Init(I2S3_WS_GPIO_PORT, &GPIO_InitStruct); 
00551   
00552   /* I2S3 pins configuration: MCK pin */
00553   I2S3_MCK_CLK_ENABLE();
00554   GPIO_InitStruct.Pin         = I2S3_MCK_PIN; 
00555   HAL_GPIO_Init(I2S3_MCK_GPIO_PORT, &GPIO_InitStruct);   
00556   
00557   /* Enable the I2S DMA clock */
00558   I2S3_DMAx_CLK_ENABLE(); 
00559   
00560   if(hi2s->Instance == I2S3)
00561   {
00562     /* Configure the hdma_i2sTx handle parameters */   
00563     hdma_i2sTx.Init.Channel             = I2S3_DMAx_CHANNEL;  
00564     hdma_i2sTx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
00565     hdma_i2sTx.Init.PeriphInc           = DMA_PINC_DISABLE;
00566     hdma_i2sTx.Init.MemInc              = DMA_MINC_ENABLE;
00567     hdma_i2sTx.Init.PeriphDataAlignment = I2S3_DMAx_PERIPH_DATA_SIZE;
00568     hdma_i2sTx.Init.MemDataAlignment    = I2S3_DMAx_MEM_DATA_SIZE;
00569     hdma_i2sTx.Init.Mode                = DMA_NORMAL;
00570     hdma_i2sTx.Init.Priority            = DMA_PRIORITY_HIGH;
00571     hdma_i2sTx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;         
00572     hdma_i2sTx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
00573     hdma_i2sTx.Init.MemBurst            = DMA_MBURST_SINGLE;
00574     hdma_i2sTx.Init.PeriphBurst         = DMA_PBURST_SINGLE; 
00575     
00576     hdma_i2sTx.Instance                 = I2S3_DMAx_STREAM;
00577     
00578     /* Associate the DMA handle */
00579     __HAL_LINKDMA(hi2s, hdmatx, hdma_i2sTx);
00580     
00581     /* Deinitialize the Stream for new transfer */
00582     HAL_DMA_DeInit(&hdma_i2sTx);
00583     
00584     /* Configure the DMA Stream */
00585     HAL_DMA_Init(&hdma_i2sTx);
00586   }
00587   
00588   /* I2S DMA IRQ Channel configuration */
00589   HAL_NVIC_SetPriority(I2S3_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
00590   HAL_NVIC_EnableIRQ(I2S3_DMAx_IRQ); 
00591 }
00592 
00593 /**
00594   * @brief  De-Initializes BSP_AUDIO_OUT MSP.
00595   * @param  hi2s: might be required to set audio peripheral predivider if any.
00596   * @param  Params : pointer on additional configuration parameters, can be NULL.
00597   */
00598 __weak void BSP_AUDIO_OUT_MspDeInit(I2S_HandleTypeDef *hi2s, void *Params)
00599 {  
00600   GPIO_InitTypeDef  GPIO_InitStruct;
00601 
00602   /* I2S DMA IRQ Channel deactivation */
00603   HAL_NVIC_DisableIRQ(I2S3_DMAx_IRQ); 
00604   
00605   if(hi2s->Instance == I2S3)
00606   {
00607     /* Deinitialize the Stream for new transfer */
00608     HAL_DMA_DeInit(hi2s->hdmatx);
00609   }
00610 
00611  /* Disable I2S block */
00612   __HAL_I2S_DISABLE(hi2s);
00613 
00614   /* CODEC_I2S pins configuration: SCK and SD pins */
00615   GPIO_InitStruct.Pin = I2S3_SCK_PIN | I2S3_SD_PIN;
00616   HAL_GPIO_DeInit(I2S3_SCK_SD_GPIO_PORT, GPIO_InitStruct.Pin);
00617   
00618   /* CODEC_I2S pins configuration: WS pin */
00619   GPIO_InitStruct.Pin = I2S3_WS_PIN;
00620   HAL_GPIO_DeInit(I2S3_WS_GPIO_PORT, GPIO_InitStruct.Pin);
00621   
00622   /* CODEC_I2S pins configuration: MCK pin */
00623   GPIO_InitStruct.Pin = I2S3_MCK_PIN;
00624   HAL_GPIO_DeInit(I2S3_MCK_GPIO_PORT, GPIO_InitStruct.Pin); 
00625 
00626   /* Disable I2S clock */
00627   I2S3_CLK_DISABLE();
00628 
00629   /* GPIO pins clock and DMA clock can be shut down in the applic 
00630      by surcgarging this __weak function */   
00631 }
00632 
00633 /**
00634   * @brief  Manages the DMA full Transfer complete event.
00635   */
00636 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
00637 {
00638 }
00639 
00640 /**
00641   * @brief  Manages the DMA Half Transfer complete event.
00642   */
00643 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void)
00644 {
00645 }
00646 
00647 /**
00648   * @brief  Manages the DMA FIFO error event.
00649   */
00650 __weak void BSP_AUDIO_OUT_Error_CallBack(void)
00651 {
00652 }
00653 
00654 /*******************************************************************************
00655                             Static Functions
00656 *******************************************************************************/
00657 
00658 /**
00659   * @brief  Initializes the Audio Codec audio interface (I2S).
00660   * @param  AudioFreq: Audio frequency to be configured for the I2S peripheral. 
00661   */
00662 static uint8_t I2S3_Init(uint32_t AudioFreq)
00663 {
00664   /* Initialize the hAudioOutI2s Instance parameter */
00665   hAudioOutI2s.Instance         = I2S3;
00666 
00667  /* Disable I2S block */
00668   __HAL_I2S_DISABLE(&hAudioOutI2s);
00669   
00670   /* I2S3 peripheral configuration */
00671   hAudioOutI2s.Init.AudioFreq   = AudioFreq;
00672   hAudioOutI2s.Init.ClockSource = I2S_CLOCK_PLL;
00673   hAudioOutI2s.Init.CPOL        = I2S_CPOL_LOW;
00674   hAudioOutI2s.Init.DataFormat  = I2S_DATAFORMAT_16B;
00675   hAudioOutI2s.Init.MCLKOutput  = I2S_MCLKOUTPUT_ENABLE;
00676   hAudioOutI2s.Init.Mode        = I2S_MODE_MASTER_TX;
00677   hAudioOutI2s.Init.Standard    = I2S_STANDARD;
00678   /* Initialize the I2S peripheral with the structure above */  
00679   if(HAL_I2S_Init(&hAudioOutI2s) != HAL_OK)
00680   {
00681     return AUDIO_ERROR;
00682   }
00683   else
00684   {
00685     return AUDIO_OK;
00686   }
00687 }
00688   
00689 /**
00690   * @}
00691   */ 
00692   
00693 /** @defgroup STM32F4_DISCOVERY_AUDIO_IN_Private_Functions STM32F4 DISCOVERY AUDIO IN Private Functions
00694   * @{
00695   */ 
00696   
00697 /**
00698   * @brief  Initializes wave recording.
00699   * @param  AudioFreq: Audio frequency to be configured for the I2S peripheral. 
00700   * @param  BitRes: Audio frequency to be configured for the I2S peripheral.
00701   * @param  ChnlNbr: Audio frequency to be configured for the I2S peripheral.
00702   * @retval AUDIO_OK if correct communication, else wrong communication
00703   */
00704 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00705 {
00706   
00707   /* Configure PLL clock */ 
00708   BSP_AUDIO_IN_ClockConfig(&hAudioInI2s, AudioFreq, NULL);
00709   
00710   /* Configure the PDM library */
00711   PDMDecoder_Init(AudioFreq, ChnlNbr);
00712 
00713   /* Configure the I2S peripheral */
00714   hAudioInI2s.Instance = I2S2;
00715   if(HAL_I2S_GetState(&hAudioInI2s) == HAL_I2S_STATE_RESET)
00716   { 
00717     /* Initialize the I2S Msp: this __weak function can be rewritten by the application */
00718     BSP_AUDIO_IN_MspInit(&hAudioInI2s, NULL);
00719   }
00720   
00721   /* Configure the I2S2 */
00722   I2S2_Init(AudioFreq);
00723   
00724   /* Return AUDIO_OK when all operations are correctly done */
00725   return AUDIO_OK;
00726 }
00727 
00728 /**
00729   * @brief  Starts audio recording.
00730   * @param  pbuf: Main buffer pointer for the recorded data storing  
00731   * @param  size: Current size of the recorded buffer
00732   * @retval AUDIO_OK if correct communication, else wrong communication
00733   */
00734 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size)
00735 {
00736   uint32_t ret = AUDIO_ERROR;
00737   
00738   /* Start the process receive DMA */
00739   HAL_I2S_Receive_DMA(&hAudioInI2s, pbuf, size);
00740   
00741   /* Return AUDIO_OK when all operations are correctly done */
00742   ret = AUDIO_OK;
00743   
00744   return ret;
00745 }
00746 
00747 /**
00748   * @brief  Stops audio recording.
00749   * @retval AUDIO_OK if correct communication, else wrong communication
00750   */
00751 uint8_t BSP_AUDIO_IN_Stop(void)
00752 {
00753   uint32_t ret = AUDIO_ERROR;
00754   
00755   /* Call the Media layer pause function */
00756   HAL_I2S_DMAStop(&hAudioInI2s);  
00757   
00758   /* Return AUDIO_OK when all operations are correctly done */
00759   ret = AUDIO_OK;
00760   
00761   return ret;
00762 }
00763 
00764 /**
00765   * @brief  Pauses the audio file stream.
00766   * @retval AUDIO_OK if correct communication, else wrong communication
00767   */
00768 uint8_t BSP_AUDIO_IN_Pause(void)
00769 {    
00770   /* Call the Media layer pause function */
00771   HAL_I2S_DMAPause(&hAudioInI2s);
00772   
00773   /* Return AUDIO_OK when all operations are correctly done */
00774   return AUDIO_OK;
00775 }
00776 
00777 /**
00778   * @brief  Resumes the audio file stream.    
00779   * @retval AUDIO_OK if correct communication, else wrong communication
00780   */
00781 uint8_t BSP_AUDIO_IN_Resume(void)
00782 {    
00783   /* Call the Media layer pause/resume function */
00784   HAL_I2S_DMAResume(&hAudioInI2s);
00785   
00786   /* Return AUDIO_OK when all operations are correctly done */
00787   return AUDIO_OK;
00788 }
00789 
00790 /**
00791   * @brief  Controls the audio in volume level. 
00792   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for 
00793   *         Mute and 100 for Max volume level).
00794   * @retval AUDIO_OK if correct communication, else wrong communication
00795   */
00796 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume)
00797 {
00798   /* Set the Global variable AudioInVolume */
00799   AudioInVolume = Volume; 
00800   
00801   /* Return AUDIO_OK when all operations are correctly done */
00802   return AUDIO_OK;
00803 }
00804 
00805 /**
00806   * @brief  Converts audio format from PDM to PCM.
00807   * @param  PDMBuf: Pointer to data PDM buffer
00808   * @param  PCMBuf: Pointer to data PCM buffer
00809   * @retval AUDIO_OK if correct communication, else wrong communication
00810   */
00811 uint8_t BSP_AUDIO_IN_PDMToPCM(uint16_t *PDMBuf, uint16_t *PCMBuf)
00812 {
00813   uint16_t AppPDM[INTERNAL_BUFF_SIZE/2];
00814   uint32_t index = 0; 
00815   
00816   /* PDM Demux */
00817   for(index = 0; index<INTERNAL_BUFF_SIZE/2; index++)
00818   {
00819     AppPDM[index] = HTONS(PDMBuf[index]);
00820   }
00821   
00822   for(index = 0; index < DEFAULT_AUDIO_IN_CHANNEL_NBR; index++)
00823   {
00824     /* PDM to PCM filter */
00825     PDM_Filter_64_LSB((uint8_t*)&AppPDM[index], (uint16_t*)&(PCMBuf[index]), AudioInVolume , (PDMFilter_InitStruct *)&Filter[index]);
00826   }
00827   /* Duplicate samples since a single microphone in mounted on STM32F4-Discovery */
00828   for(index = 0; index < PCM_OUT_SIZE; index++)
00829   {
00830     PCMBuf[(index<<1)+1] = PCMBuf[index<<1];
00831   }
00832   
00833   /* Return AUDIO_OK when all operations are correctly done */
00834   return AUDIO_OK; 
00835 }
00836 
00837 /**
00838   * @brief  Rx Transfer completed callbacks
00839   * @param  hi2s: I2S handle
00840   */
00841 void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
00842 {
00843   /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
00844   BSP_AUDIO_IN_TransferComplete_CallBack();
00845 }
00846 
00847 /**
00848   * @brief  Rx Half Transfer completed callbacks.
00849   * @param  hi2s: I2S handle
00850   */
00851 void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
00852 {
00853   /* Manage the remaining file size and new address offset: This function 
00854      should be coded by user (its prototype is already declared in stm32f4_discovery_audio.h) */
00855   BSP_AUDIO_IN_HalfTransfer_CallBack();
00856 }
00857 
00858 /**
00859   * @brief  Audio In Clock Config.
00860   * @param  hi2s: I2S handle
00861   * @param  AudioFreq: Audio frequency used to record the audio stream.  
00862   * @param  Params : pointer on additional configuration parameters, can be NULL.   
00863   * @note   This API is called by BSP_AUDIO_IN_Init()
00864   *         Being __weak it can be overwritten by the application
00865   */
00866 __weak void BSP_AUDIO_IN_ClockConfig(I2S_HandleTypeDef *hi2s, uint32_t AudioFreq, void *Params)
00867 {
00868   RCC_PeriphCLKInitTypeDef rccclkinit;
00869 
00870   /*Enable PLLI2S clock*/
00871   HAL_RCCEx_GetPeriphCLKConfig(&rccclkinit);
00872   /* PLLI2S_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
00873   if ((AudioFreq & 0x7) == 0)
00874   {
00875     /* Audio frequency multiple of 8 (8/16/32/48/96/192)*/
00876     /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN = 192 Mhz */
00877     /* I2SCLK = PLLI2S_VCO Output/PLLI2SR = 192/6 = 32 Mhz */
00878     rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S;
00879     rccclkinit.PLLI2S.PLLI2SN = 192;
00880     rccclkinit.PLLI2S.PLLI2SR = 6;
00881     HAL_RCCEx_PeriphCLKConfig(&rccclkinit);
00882   }
00883   else
00884   {
00885     /* Other Frequency (11.025/22.500/44.100) */
00886     /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN = 290 Mhz */
00887     /* I2SCLK = PLLI2S_VCO Output/PLLI2SR = 290/2 = 145 Mhz */
00888     rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S;
00889     rccclkinit.PLLI2S.PLLI2SN = 290;
00890     rccclkinit.PLLI2S.PLLI2SR = 2;
00891     HAL_RCCEx_PeriphCLKConfig(&rccclkinit);
00892   }
00893 }
00894 
00895 /**
00896   * @brief  BSP AUDIO IN MSP Init.
00897   * @param  hi2s: I2S handle
00898   * @param  Params : pointer on additional configuration parameters, can be NULL.
00899   */
00900 __weak void BSP_AUDIO_IN_MspInit(I2S_HandleTypeDef *hi2s, void *Params)
00901 {
00902   static DMA_HandleTypeDef hdma_i2sRx;
00903   GPIO_InitTypeDef  GPIO_InitStruct;
00904   
00905   /* Enable the I2S2 peripheral clock */
00906   I2S2_CLK_ENABLE();
00907 
00908   /* Enable I2S GPIO clocks */
00909   I2S2_SCK_GPIO_CLK_ENABLE();
00910   I2S2_MOSI_GPIO_CLK_ENABLE();
00911   
00912   /* I2S2 pins configuration: SCK and MOSI pins ------------------------------*/
00913   GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
00914   GPIO_InitStruct.Pull      = GPIO_NOPULL;
00915   GPIO_InitStruct.Speed     = GPIO_SPEED_FAST;
00916 
00917   GPIO_InitStruct.Pin       = I2S2_SCK_PIN; 
00918   GPIO_InitStruct.Alternate = I2S2_SCK_AF;
00919   HAL_GPIO_Init(I2S2_SCK_GPIO_PORT, &GPIO_InitStruct);
00920   
00921   GPIO_InitStruct.Pin       = I2S2_MOSI_PIN ;
00922   GPIO_InitStruct.Alternate = I2S2_MOSI_AF;
00923   HAL_GPIO_Init(I2S2_MOSI_GPIO_PORT, &GPIO_InitStruct); 
00924 
00925   /* Enable the DMA clock */
00926   I2S2_DMAx_CLK_ENABLE();
00927     
00928   if(hi2s->Instance == I2S2)
00929   {
00930     /* Configure the hdma_i2sRx handle parameters */   
00931     hdma_i2sRx.Init.Channel             = I2S2_DMAx_CHANNEL;
00932     hdma_i2sRx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
00933     hdma_i2sRx.Init.PeriphInc           = DMA_PINC_DISABLE;
00934     hdma_i2sRx.Init.MemInc              = DMA_MINC_ENABLE;
00935     hdma_i2sRx.Init.PeriphDataAlignment = I2S2_DMAx_PERIPH_DATA_SIZE;
00936     hdma_i2sRx.Init.MemDataAlignment    = I2S2_DMAx_MEM_DATA_SIZE;
00937     hdma_i2sRx.Init.Mode                = DMA_CIRCULAR;
00938     hdma_i2sRx.Init.Priority            = DMA_PRIORITY_HIGH;
00939     hdma_i2sRx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;         
00940     hdma_i2sRx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
00941     hdma_i2sRx.Init.MemBurst            = DMA_MBURST_SINGLE;
00942     hdma_i2sRx.Init.PeriphBurst         = DMA_MBURST_SINGLE; 
00943     
00944     hdma_i2sRx.Instance = I2S2_DMAx_STREAM;
00945     
00946     /* Associate the DMA handle */
00947     __HAL_LINKDMA(hi2s, hdmarx, hdma_i2sRx);
00948     
00949     /* Deinitialize the Stream for new transfer */
00950     HAL_DMA_DeInit(&hdma_i2sRx);
00951     
00952     /* Configure the DMA Stream */
00953     HAL_DMA_Init(&hdma_i2sRx);      
00954   }
00955   
00956   /* I2S DMA IRQ Channel configuration */
00957   HAL_NVIC_SetPriority(I2S2_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
00958   HAL_NVIC_EnableIRQ(I2S2_DMAx_IRQ); 
00959 }
00960 
00961 /**
00962   * @brief  DeInitializes BSP_AUDIO_IN MSP.
00963   * @param  hi2s: I2S handle
00964   * @param  Params : pointer on additional configuration parameters, can be NULL.
00965   */
00966 __weak void BSP_AUDIO_IN_MspDeInit(I2S_HandleTypeDef *hi2s, void *Params)
00967 {
00968   GPIO_InitTypeDef  gpio_init_structure;
00969 
00970   /* I2S DMA IRQ Channel deactivation */
00971   HAL_NVIC_DisableIRQ(I2S2_DMAx_IRQ); 
00972   
00973   if(hi2s->Instance == I2S2)
00974   {
00975     /* Deinitialize the Stream for new transfer */
00976     HAL_DMA_DeInit(hi2s->hdmarx);
00977   }
00978 
00979  /* Disable I2S block */
00980   __HAL_I2S_DISABLE(hi2s);
00981 
00982   /* Disable pins: SCK and SD pins */
00983   gpio_init_structure.Pin = I2S2_SCK_PIN;
00984   HAL_GPIO_DeInit(I2S2_SCK_GPIO_PORT, gpio_init_structure.Pin);
00985   gpio_init_structure.Pin = I2S2_MOSI_PIN;
00986   HAL_GPIO_DeInit(I2S2_MOSI_GPIO_PORT, gpio_init_structure.Pin); 
00987 
00988   /* Disable I2S clock */
00989   I2S2_CLK_DISABLE();
00990 
00991   /* GPIO pins clock and DMA clock can be shut down in the applic 
00992      by surcgarging this __weak function */ 
00993 }
00994 
00995 /**
00996   * @brief  User callback when record buffer is filled.
00997   */
00998 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void)
00999 {
01000   /* This function should be implemented by the user application.
01001      It is called into this driver when the current buffer is filled
01002      to prepare the next buffer pointer and its size. */
01003 }
01004 
01005 /**
01006   * @brief  Manages the DMA Half Transfer complete event.
01007   */
01008 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
01009 {
01010   /* This function should be implemented by the user application.
01011      It is called into this driver when the current buffer is filled
01012      to prepare the next buffer pointer and its size. */
01013 }
01014 
01015 /**
01016   * @brief  Audio IN Error callback function.
01017   */
01018 __weak void BSP_AUDIO_IN_Error_Callback(void)
01019 {   
01020   /* This function is called when an Interrupt due to transfer error on or peripheral
01021      error occurs. */
01022 }
01023 
01024 /*******************************************************************************
01025                             Static Functions
01026 *******************************************************************************/
01027 
01028 /**
01029   * @brief  Initialize the PDM library.
01030   * @param  AudioFreq: Audio sampling frequency
01031   * @param  ChnlNbr: Number of audio channels (1: mono; 2: stereo)
01032   */
01033 static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr)
01034 { 
01035   uint32_t i = 0;
01036   
01037   /* Enable CRC peripheral to unlock the PDM library */
01038   __CRC_CLK_ENABLE();
01039   
01040   for(i = 0; i < ChnlNbr; i++)
01041   {
01042     /* Filter LP and HP Init */
01043     Filter[i].LP_HZ = AudioFreq / 2;
01044     Filter[i].HP_HZ = 10;
01045     Filter[i].Fs = AudioFreq;
01046     /* On STM32F4-Discovery a single microphone is mounted, samples are duplicated
01047        to make stereo audio streams */
01048     Filter[i].Out_MicChannels = 2;
01049     Filter[i].In_MicChannels = ChnlNbr; 
01050     PDM_Filter_Init((PDMFilter_InitStruct *)&Filter[i]);
01051   }  
01052 }
01053 
01054 /**
01055   * @brief  Initializes the Audio Codec audio interface (I2S)
01056   * @note   This function assumes that the I2S input clock (through PLL_R in 
01057   *         Devices RevA/Z and through dedicated PLLI2S_R in Devices RevB/Y)
01058   *         is already configured and ready to be used.    
01059   * @param  AudioFreq: Audio frequency to be configured for the I2S peripheral. 
01060   */
01061 static uint8_t I2S2_Init(uint32_t AudioFreq)
01062 {
01063   /* Initialize the hAudioInI2s Instance parameter */
01064   hAudioInI2s.Instance          = I2S2;
01065   
01066   /* Disable I2S block */
01067   __HAL_I2S_DISABLE(&hAudioInI2s);
01068   
01069   /* I2S2 peripheral configuration */
01070   hAudioInI2s.Init.AudioFreq    = 2 * AudioFreq;
01071   hAudioInI2s.Init.ClockSource  = I2S_CLOCK_PLL;
01072   hAudioInI2s.Init.CPOL         = I2S_CPOL_HIGH;
01073   hAudioInI2s.Init.DataFormat   = I2S_DATAFORMAT_16B;
01074   hAudioInI2s.Init.MCLKOutput   = I2S_MCLKOUTPUT_DISABLE;
01075   hAudioInI2s.Init.Mode         = I2S_MODE_MASTER_RX;
01076   hAudioInI2s.Init.Standard     = I2S_STANDARD_LSB;
01077 
01078   /* Initialize the I2S peripheral with the structure above */  
01079   if(HAL_I2S_Init(&hAudioInI2s) != HAL_OK)
01080   {
01081     return AUDIO_ERROR;
01082   }
01083   else
01084   {
01085     return AUDIO_OK; 
01086   }
01087 }  
01088 
01089 /**
01090   * @}
01091   */
01092 
01093 /** @defgroup STM32F4_DISCOVERY_AUDIO_IN_OUT_Private_Functions STM32F4 DISCOVERY AUDIO IN OUT Private Functions
01094   * @{
01095   */ 
01096   
01097 /**
01098   * @brief  I2S error callbacks.
01099   * @param  hi2s: I2S handle
01100   */
01101 void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s)
01102 {
01103   /* Manage the error generated on DMA FIFO: This function 
01104      should be coded by user (its prototype is already declared in stm32f4_discovery_audio.h) */  
01105   if(hi2s->Instance == I2S3)
01106   {
01107     BSP_AUDIO_OUT_Error_CallBack();
01108   }
01109   if(hi2s->Instance == I2S2)
01110   {
01111     BSP_AUDIO_IN_Error_Callback();
01112   }
01113 }
01114 
01115 /**
01116   * @}
01117   */ 
01118   
01119 /**
01120   * @}
01121   */
01122 
01123 /**
01124   * @}
01125   */
01126 
01127 /**
01128   * @}
01129   */
01130 
01131 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Thu Jan 19 2017 15:34:14 for STM32F4-Discovery BSP User Manual by   doxygen 1.7.6.1