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