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