STM32F401-Discovery BSP User Manual
|
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>© 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 1.7.6.1