STM32F401-Discovery BSP User Manual: stm32f401_discovery_audio.c Source File

STM32F401-Discovery BSP Drivers

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