1 /** 2 ****************************************************************************** 3 * @file stm32f4_discovery_audio.c 4 * @author MCD Application Team 5 * @version V2.1.2 6 * @date 27-January-2017 7 * @brief This file provides the Audio driver for the STM32F4-Discovery 8 * board. 9 ****************************************************************************** 10 * @attention 11 * 12 * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2> 13 * 14 * Redistribution and use in source and binary forms, with or without modification, 15 * are permitted provided that the following conditions are met: 16 * 1. Redistributions of source code must retain the above copyright notice, 17 * this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright notice, 19 * this list of conditions and the following disclaimer in the documentation 20 * and/or other materials provided with the distribution. 21 * 3. Neither the name of STMicroelectronics nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 * 36 ****************************************************************************** 37 */ 38 39 /*============================================================================== 40 User NOTES 41 1. How To use this driver: 42 -------------------------- 43 - This driver supports STM32F4xx devices on STM32F4-Discovery Kit: 44 a) to play an audio file (all functions names start by BSP_AUDIO_OUT_xxx) 45 b) to record an audio file through MP45DT02, ST MEMS (all functions names start by AUDIO_IN_xxx) 46 47 a) PLAY A FILE: 48 ============== 49 + Call the function BSP_AUDIO_OUT_Init( 50 OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 51 OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_AUTO or 52 OUTPUT_DEVICE_BOTH) 53 Volume: initial volume to be set (0 is min (mute), 100 is max (100%) 54 AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...) 55 this parameter is relative to the audio file/stream type. 56 ) 57 This function configures all the hardware required for the audio application (codec, I2C, I2S, 58 GPIOs, DMA and interrupt if needed). This function returns 0 if configuration is OK. 59 If the returned value is different from 0 or the function is stuck then the communication with 60 the codec (try to un-plug the power or reset device in this case). 61 - OUTPUT_DEVICE_SPEAKER: only speaker will be set as output for the audio stream. 62 - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream. 63 - OUTPUT_DEVICE_AUTO: Selection of output device is made through external switch (implemented 64 into the audio jack on the discovery board). When the Headphone is connected it is used 65 as output. When the headphone is disconnected from the audio jack, the output is 66 automatically switched to Speaker. 67 - OUTPUT_DEVICE_BOTH: both Speaker and Headphone are used as outputs for the audio stream 68 at the same time. 69 + Call the function BSP_AUDIO_OUT_Play( 70 pBuffer: pointer to the audio data file address 71 Size: size of the buffer to be sent in Bytes 72 ) 73 to start playing (for the first time) from the audio file/stream. 74 + Call the function BSP_AUDIO_OUT_Pause() to pause playing 75 + Call the function BSP_AUDIO_OUT_Resume() to resume playing. 76 Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called 77 for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case). 78 Note. This function should be called only when the audio file is played or paused (not stopped). 79 + For each mode, you may need to implement the relative callback functions into your code. 80 The Callback functions are named BSP_AUDIO_OUT_XXXCallBack() and only their prototypes are declared in 81 the stm32f4_discovery_audio.h file. (refer to the example for more details on the callbacks implementations) 82 + To Stop playing, to modify the volume level, the frequency or to mute, use the functions 83 BSP_AUDIO_OUT_Stop(), BSP_AUDIO_OUT_SetVolume(), AUDIO_OUT_SetFrequency() BSP_AUDIO_OUT_SetOutputMode and BSP_AUDIO_OUT_SetMute(). 84 + The driver API and the callback functions are at the end of the stm32f4_discovery_audio.h file. 85 86 Driver architecture: 87 -------------------- 88 + This driver provide the High Audio Layer: consists of the function API exported in the stm32f4_discovery_audio.h file 89 (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...) 90 + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/ 91 providing the audio file/stream. These functions are also included as local functions into 92 the stm32f4_discovery_audio.c file (I2S3_Init()...) 93 94 Known Limitations: 95 ------------------- 96 1- When using the Speaker, if the audio file quality is not high enough, the speaker output 97 may produce high and uncomfortable noise level. To avoid this issue, to use speaker 98 output properly, try to increase audio file sampling rate (typically higher than 48KHz). 99 This operation will lead to larger file size. 100 2- Communication with the audio codec (through I2C) may be corrupted if it is interrupted by some 101 user interrupt routines (in this case, interrupts could be disabled just before the start of 102 communication then re-enabled when it is over). Note that this communication is only done at 103 the configuration phase (BSP_AUDIO_OUT_Init() or BSP_AUDIO_OUT_Stop()) and when Volume control modification is 104 performed (BSP_AUDIO_OUT_SetVolume() or BSP_AUDIO_OUT_SetMute()or BSP_AUDIO_OUT_SetOutputMode()). 105 When the audio data is played, no communication is required with the audio codec. 106 3- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 107 File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file. 108 4- Supports only Stereo audio streaming. To play mono audio streams, each data should be sent twice 109 on the I2S or should be duplicated on the source buffer. Or convert the stream in stereo before playing. 110 5- Supports only 16-bits audio data size. 111 112 b) RECORD A FILE: 113 ================ 114 + Call the function BSP_AUDIO_IN_Init( 115 AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...) 116 ) 117 This function configures all the hardware required for the audio application (I2S, 118 GPIOs, DMA and interrupt if needed). This function returns 0 if configuration is OK. 119 120 + Call the function BSP_AUDIO_IN_Record( 121 pbuf Main buffer pointer for the recorded data storing 122 size Current size of the recorded buffer 123 ) 124 to start recording from the microphone. 125 126 + User needs to implement user callbacks to retrieve data saved in the record buffer 127 (AUDIO_IN_RxHalfCpltCallback/BSP_AUDIO_IN_ReceiveComplete_CallBack) 128 129 + Call the function AUDIO_IN_STOP() to stop recording 130 131 ==============================================================================*/ 132 133 /* Includes ------------------------------------------------------------------*/ 134 #include "stm32f4_discovery_audio.h" 135 #include "pdm_filter.h" 136 #include "btstack_config.h" 137 138 /** @addtogroup BSP 139 * @{ 140 */ 141 142 /** @addtogroup STM32F4_DISCOVERY 143 * @{ 144 */ 145 146 /** @defgroup STM32F4_DISCOVERY_AUDIO STM32F4 DISCOVERY AUDIO 147 * @brief This file includes the low layer audio driver available on STM32F4-Discovery 148 * discovery board. 149 * @{ 150 */ 151 152 /** @defgroup STM32F4_DISCOVERY_AUDIO_Private_Types STM32F4 DISCOVERY AUDIO Private Types 153 * @{ 154 */ 155 /** 156 * @} 157 */ 158 159 /** @defgroup STM32F4_DISCOVERY_AUDIO_Private_Defines STM32F4 DISCOVERY AUDIO Private Defines 160 * @{ 161 */ 162 /* These PLL parameters are valid when the f(VCO clock) = 1Mhz */ 163 static const uint32_t I2SFreq[8] = {8000, 11025, 16000, 22050, 32000, 44100, 48000, 96000}; 164 static const uint32_t I2SPLLN[8] = {256, 429, 213, 429, 426, 271, 258, 344}; 165 static const uint32_t I2SPLLR[8] = {5, 4, 4, 4, 4, 6, 3, 1}; 166 /** 167 * @} 168 */ 169 170 /** @defgroup STM32F4_DISCOVERY_AUDIO_Private_Macros STM32F4 DISCOVERY AUDIO Private Macros 171 * @{ 172 */ 173 /** 174 * @} 175 */ 176 177 /** @defgroup STM32F4_DISCOVERY_AUDIO_Private_Variables STM32F4 DISCOVERY AUDIO Private Variables 178 * @{ 179 */ 180 /*##### PLAY #####*/ 181 static AUDIO_DrvTypeDef *pAudioDrv; 182 I2S_HandleTypeDef hAudioOutI2s; 183 184 /*### RECORDER ###*/ 185 I2S_HandleTypeDef hAudioInI2s; 186 187 static PDMFilter_InitStruct Filter[DEFAULT_AUDIO_IN_CHANNEL_NBR]; 188 __IO uint16_t AudioInVolume = DEFAULT_AUDIO_IN_VOLUME; 189 /** 190 * @} 191 */ 192 193 /** @defgroup STM32F4_DISCOVERY_AUDIO_Private_Function_Prototypes STM32F4 DISCOVERY AUDIO Private Function Prototypes 194 * @{ 195 */ 196 static uint8_t I2S2_Init(uint32_t AudioFreq); 197 static uint8_t I2S3_Init(uint32_t AudioFreq); 198 static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr); 199 200 /** 201 * @} 202 */ 203 204 /** @defgroup STM32F4_DISCOVERY_AUDIO_OUT_Private_Functions STM32F4 DISCOVERY AUDIO OUT Private Functions 205 * @{ 206 */ 207 208 /** 209 * @brief Configures the audio peripherals. 210 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 211 * OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO . 212 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 213 * @param AudioFreq: Audio frequency used to play the audio stream. 214 * @retval AUDIO_OK if correct communication, else wrong communication 215 */ 216 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 217 { 218 uint8_t ret = AUDIO_OK; 219 220 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 221 BSP_AUDIO_OUT_ClockConfig(&hAudioOutI2s, AudioFreq, NULL); 222 223 /* I2S data transfer preparation: 224 Prepare the Media to be used for the audio transfer from memory to I2S peripheral */ 225 hAudioOutI2s.Instance = I2S3; 226 if(HAL_I2S_GetState(&hAudioOutI2s) == HAL_I2S_STATE_RESET) 227 { 228 /* Init the I2S MSP: this __weak function can be redefined by the application*/ 229 BSP_AUDIO_OUT_MspInit(&hAudioOutI2s, NULL); 230 } 231 232 /* I2S data transfer preparation: 233 Prepare the Media to be used for the audio transfer from memory to I2S peripheral */ 234 /* Configure the I2S peripheral */ 235 if(I2S3_Init(AudioFreq) != AUDIO_OK) 236 { 237 ret = AUDIO_ERROR; 238 } 239 240 if(ret == AUDIO_OK) 241 { 242 /* Retieve audio codec identifier */ 243 if(((cs43l22_drv.ReadID(AUDIO_I2C_ADDRESS)) & CS43L22_ID_MASK) == CS43L22_ID) 244 { 245 /* Initialize the audio driver structure */ 246 pAudioDrv = &cs43l22_drv; 247 } 248 else 249 { 250 ret = AUDIO_ERROR; 251 } 252 } 253 254 if(ret == AUDIO_OK) 255 { 256 pAudioDrv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq); 257 } 258 259 return ret; 260 } 261 262 /** 263 * @brief Starts playing audio stream from a data buffer for a determined size. 264 * @param pBuffer: Pointer to the buffer 265 * @param Size: Number of audio data BYTES. 266 * @retval AUDIO_OK if correct communication, else wrong communication 267 */ 268 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size) 269 { 270 /* Call the audio Codec Play function */ 271 if(pAudioDrv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0) 272 { 273 return AUDIO_ERROR; 274 } 275 else 276 { 277 /* Update the Media layer and enable it for play */ 278 HAL_I2S_Transmit_DMA(&hAudioOutI2s, pBuffer, DMA_MAX(Size/AUDIODATA_SIZE)); 279 280 /* Return AUDIO_OK when all operations are correctly done */ 281 return AUDIO_OK; 282 } 283 } 284 285 /** 286 * @brief Sends n-Bytes on the I2S interface. 287 * @param pData: Pointer to data address 288 * @param Size: Number of data to be written 289 */ 290 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size) 291 { 292 HAL_I2S_Transmit_DMA(&hAudioOutI2s, pData, Size); 293 } 294 295 /** 296 * @brief Pauses the audio file stream. In case of using DMA, the DMA Pause 297 * feature is used. 298 * WARNING: When calling BSP_AUDIO_OUT_Pause() function for pause, only the 299 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 300 * function for resume could lead to unexpected behavior). 301 * @retval AUDIO_OK if correct communication, else wrong communication 302 */ 303 uint8_t BSP_AUDIO_OUT_Pause(void) 304 { 305 /* Call the Audio Codec Pause/Resume function */ 306 if(pAudioDrv->Pause(AUDIO_I2C_ADDRESS) != 0) 307 { 308 return AUDIO_ERROR; 309 } 310 else 311 { 312 /* Call the Media layer pause function */ 313 HAL_I2S_DMAPause(&hAudioOutI2s); 314 315 /* Return AUDIO_OK when all operations are correctly done */ 316 return AUDIO_OK; 317 } 318 } 319 320 /** 321 * @brief Resumes the audio file streaming. 322 * WARNING: When calling BSP_AUDIO_OUT_Pause() function for pause, only 323 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 324 * function for resume could lead to unexpected behavior). 325 * @retval AUDIO_OK if correct communication, else wrong communication 326 */ 327 uint8_t BSP_AUDIO_OUT_Resume(void) 328 { 329 /* Call the Audio Codec Pause/Resume function */ 330 if(pAudioDrv->Resume(AUDIO_I2C_ADDRESS) != 0) 331 { 332 return AUDIO_ERROR; 333 } 334 else 335 { 336 /* Call the Media layer resume function */ 337 HAL_I2S_DMAResume(&hAudioOutI2s); 338 339 /* Return AUDIO_OK when all operations are correctly done */ 340 return AUDIO_OK; 341 } 342 } 343 344 /** 345 * @brief Stops audio playing and Power down the Audio Codec. 346 * @param Option: could be one of the following parameters 347 * - CODEC_PDWN_HW: completely shut down the codec (physically). 348 * Then need to reconfigure the Codec after power on. 349 * @retval AUDIO_OK if correct communication, else wrong communication 350 */ 351 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option) 352 { 353 /* Call DMA Stop to disable DMA stream before stopping codec */ 354 HAL_I2S_DMAStop(&hAudioOutI2s); 355 356 /* Call Audio Codec Stop function */ 357 if(pAudioDrv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 358 { 359 return AUDIO_ERROR; 360 } 361 else 362 { 363 if(Option == CODEC_PDWN_HW) 364 { 365 /* Wait at least 1ms */ 366 HAL_Delay(1); 367 368 /* Reset the pin */ 369 HAL_GPIO_WritePin(AUDIO_RESET_GPIO, AUDIO_RESET_PIN, GPIO_PIN_RESET); 370 } 371 372 /* Return AUDIO_OK when all operations are correctly done */ 373 return AUDIO_OK; 374 } 375 } 376 377 /** 378 * @brief Controls the current audio volume level. 379 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 380 * Mute and 100 for Max volume level). 381 * @retval AUDIO_OK if correct communication, else wrong communication 382 */ 383 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume) 384 { 385 /* Call the codec volume control function with converted volume value */ 386 if(pAudioDrv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 387 { 388 return AUDIO_ERROR; 389 } 390 else 391 { 392 /* Return AUDIO_OK when all operations are correctly done */ 393 return AUDIO_OK; 394 } 395 } 396 397 /** 398 * @brief Enables or disables the MUTE mode by software 399 * @param Cmd: could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 400 * unmute the codec and restore previous volume level. 401 * @retval AUDIO_OK if correct communication, else wrong communication 402 */ 403 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd) 404 { 405 /* Call the Codec Mute function */ 406 if(pAudioDrv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0) 407 { 408 return AUDIO_ERROR; 409 } 410 else 411 { 412 /* Return AUDIO_OK when all operations are correctly done */ 413 return AUDIO_OK; 414 } 415 } 416 417 /** 418 * @brief Switch dynamically (while audio file is played) the output target 419 * (speaker or headphone). 420 * @note This function modifies a global variable of the audio codec driver: OutputDev. 421 * @param Output: specifies the audio output target: OUTPUT_DEVICE_SPEAKER, 422 * OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO 423 * @retval AUDIO_OK if correct communication, else wrong communication 424 */ 425 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output) 426 { 427 /* Call the Codec output Device function */ 428 if(pAudioDrv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0) 429 { 430 return AUDIO_ERROR; 431 } 432 else 433 { 434 /* Return AUDIO_OK when all operations are correctly done */ 435 return AUDIO_OK; 436 } 437 } 438 439 /** 440 * @brief Update the audio frequency. 441 * @param AudioFreq: Audio frequency used to play the audio stream. 442 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 443 * audio frequency. 444 */ 445 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq) 446 { 447 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 448 BSP_AUDIO_OUT_ClockConfig(&hAudioOutI2s, AudioFreq, NULL); 449 450 /* Update the I2S audio frequency configuration */ 451 I2S3_Init(AudioFreq); 452 } 453 454 /** 455 * @brief Tx Transfer completed callbacks. 456 * @param hi2s: I2S handle 457 */ 458 void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s) 459 { 460 if(hi2s->Instance == I2S3) 461 { 462 /* Call the user function which will manage directly transfer complete */ 463 BSP_AUDIO_OUT_TransferComplete_CallBack(); 464 } 465 } 466 467 /** 468 * @brief Tx Half Transfer completed callbacks. 469 * @param hi2s: I2S handle 470 */ 471 void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s) 472 { 473 if(hi2s->Instance == I2S3) 474 { 475 /* Manage the remaining file size and new address offset: This function should 476 be coded by user (its prototype is already declared in stm32f4_discovery_audio.h) */ 477 BSP_AUDIO_OUT_HalfTransfer_CallBack(); 478 } 479 } 480 481 /** 482 * @brief Clock Config. 483 * @param hi2s: might be required to set audio peripheral predivider if any. 484 * @param AudioFreq: Audio frequency used to play the audio stream. 485 * @note This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency() 486 * Being __weak it can be overwritten by the application 487 * @param Params : pointer on additional configuration parameters, can be NULL. 488 */ 489 __weak void BSP_AUDIO_OUT_ClockConfig(I2S_HandleTypeDef *hi2s, uint32_t AudioFreq, void *Params) 490 { 491 RCC_PeriphCLKInitTypeDef rccclkinit; 492 uint8_t index = 0, freqindex = 0xFF; 493 494 for(index = 0; index < 8; index++) 495 { 496 if(I2SFreq[index] == AudioFreq) 497 { 498 freqindex = index; 499 } 500 } 501 /* Enable PLLI2S clock */ 502 HAL_RCCEx_GetPeriphCLKConfig(&rccclkinit); 503 /* PLLI2S_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */ 504 505 // BK use table if frequency found in table, otherwise use same settings as for 48 kHz 506 if (freqindex != 0xFF) 507 { 508 /* I2S clock config 509 PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) � (PLLI2SN/PLLM) 510 I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */ 511 rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S; 512 rccclkinit.PLLI2S.PLLI2SN = I2SPLLN[freqindex]; 513 rccclkinit.PLLI2S.PLLI2SR = I2SPLLR[freqindex]; 514 HAL_RCCEx_PeriphCLKConfig(&rccclkinit); 515 } 516 else 517 { 518 /* I2S clock config 519 PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) � (PLLI2SN/PLLM) 520 I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */ 521 rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S; 522 rccclkinit.PLLI2S.PLLI2SN = 258; 523 rccclkinit.PLLI2S.PLLI2SR = 3; 524 HAL_RCCEx_PeriphCLKConfig(&rccclkinit); 525 } 526 } 527 528 /** 529 * @brief AUDIO OUT I2S MSP Init. 530 * @param hi2s: might be required to set audio peripheral predivider if any. 531 * @param Params : pointer on additional configuration parameters, can be NULL. 532 */ 533 __weak void BSP_AUDIO_OUT_MspInit(I2S_HandleTypeDef *hi2s, void *Params) 534 { 535 static DMA_HandleTypeDef hdma_i2sTx; 536 GPIO_InitTypeDef GPIO_InitStruct; 537 538 /* Enable I2S3 clock */ 539 I2S3_CLK_ENABLE(); 540 541 /*** Configure the GPIOs ***/ 542 /* Enable I2S GPIO clocks */ 543 I2S3_SCK_SD_CLK_ENABLE(); 544 I2S3_WS_CLK_ENABLE(); 545 546 /* I2S3 pins configuration: WS, SCK and SD pins ----------------------------*/ 547 GPIO_InitStruct.Pin = I2S3_SCK_PIN | I2S3_SD_PIN; 548 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 549 GPIO_InitStruct.Pull = GPIO_NOPULL; 550 GPIO_InitStruct.Speed = GPIO_SPEED_FAST; 551 GPIO_InitStruct.Alternate = I2S3_SCK_SD_WS_AF; 552 HAL_GPIO_Init(I2S3_SCK_SD_GPIO_PORT, &GPIO_InitStruct); 553 554 GPIO_InitStruct.Pin = I2S3_WS_PIN ; 555 HAL_GPIO_Init(I2S3_WS_GPIO_PORT, &GPIO_InitStruct); 556 557 /* I2S3 pins configuration: MCK pin */ 558 I2S3_MCK_CLK_ENABLE(); 559 GPIO_InitStruct.Pin = I2S3_MCK_PIN; 560 HAL_GPIO_Init(I2S3_MCK_GPIO_PORT, &GPIO_InitStruct); 561 562 /* Enable the I2S DMA clock */ 563 I2S3_DMAx_CLK_ENABLE(); 564 565 if(hi2s->Instance == I2S3) 566 { 567 /* Configure the hdma_i2sTx handle parameters */ 568 hdma_i2sTx.Init.Channel = I2S3_DMAx_CHANNEL; 569 hdma_i2sTx.Init.Direction = DMA_MEMORY_TO_PERIPH; 570 hdma_i2sTx.Init.PeriphInc = DMA_PINC_DISABLE; 571 hdma_i2sTx.Init.MemInc = DMA_MINC_ENABLE; 572 hdma_i2sTx.Init.PeriphDataAlignment = I2S3_DMAx_PERIPH_DATA_SIZE; 573 hdma_i2sTx.Init.MemDataAlignment = I2S3_DMAx_MEM_DATA_SIZE; 574 hdma_i2sTx.Init.Mode = DMA_NORMAL; 575 576 // BK: use circular DMA for hal_audio.h 577 #ifdef HAVE_HAL_AUDIO 578 hdma_i2sTx.Init.Mode = DMA_CIRCULAR; 579 #endif 580 // BK: use circular DMA (end) 581 582 hdma_i2sTx.Init.Priority = DMA_PRIORITY_HIGH; 583 hdma_i2sTx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; 584 hdma_i2sTx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 585 hdma_i2sTx.Init.MemBurst = DMA_MBURST_SINGLE; 586 hdma_i2sTx.Init.PeriphBurst = DMA_PBURST_SINGLE; 587 588 hdma_i2sTx.Instance = I2S3_DMAx_STREAM; 589 590 /* Associate the DMA handle */ 591 __HAL_LINKDMA(hi2s, hdmatx, hdma_i2sTx); 592 593 /* Deinitialize the Stream for new transfer */ 594 HAL_DMA_DeInit(&hdma_i2sTx); 595 596 /* Configure the DMA Stream */ 597 HAL_DMA_Init(&hdma_i2sTx); 598 } 599 600 /* I2S DMA IRQ Channel configuration */ 601 HAL_NVIC_SetPriority(I2S3_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 602 HAL_NVIC_EnableIRQ(I2S3_DMAx_IRQ); 603 } 604 605 /** 606 * @brief De-Initializes BSP_AUDIO_OUT MSP. 607 * @param hi2s: might be required to set audio peripheral predivider if any. 608 * @param Params : pointer on additional configuration parameters, can be NULL. 609 */ 610 __weak void BSP_AUDIO_OUT_MspDeInit(I2S_HandleTypeDef *hi2s, void *Params) 611 { 612 GPIO_InitTypeDef GPIO_InitStruct; 613 614 /* I2S DMA IRQ Channel deactivation */ 615 HAL_NVIC_DisableIRQ(I2S3_DMAx_IRQ); 616 617 if(hi2s->Instance == I2S3) 618 { 619 /* Deinitialize the Stream for new transfer */ 620 HAL_DMA_DeInit(hi2s->hdmatx); 621 } 622 623 /* Disable I2S block */ 624 __HAL_I2S_DISABLE(hi2s); 625 626 /* CODEC_I2S pins configuration: SCK and SD pins */ 627 GPIO_InitStruct.Pin = I2S3_SCK_PIN | I2S3_SD_PIN; 628 HAL_GPIO_DeInit(I2S3_SCK_SD_GPIO_PORT, GPIO_InitStruct.Pin); 629 630 /* CODEC_I2S pins configuration: WS pin */ 631 GPIO_InitStruct.Pin = I2S3_WS_PIN; 632 HAL_GPIO_DeInit(I2S3_WS_GPIO_PORT, GPIO_InitStruct.Pin); 633 634 /* CODEC_I2S pins configuration: MCK pin */ 635 GPIO_InitStruct.Pin = I2S3_MCK_PIN; 636 HAL_GPIO_DeInit(I2S3_MCK_GPIO_PORT, GPIO_InitStruct.Pin); 637 638 /* Disable I2S clock */ 639 I2S3_CLK_DISABLE(); 640 641 /* GPIO pins clock and DMA clock can be shut down in the applic 642 by surcgarging this __weak function */ 643 } 644 645 /** 646 * @brief Manages the DMA full Transfer complete event. 647 */ 648 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void) 649 { 650 } 651 652 /** 653 * @brief Manages the DMA Half Transfer complete event. 654 */ 655 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) 656 { 657 } 658 659 /** 660 * @brief Manages the DMA FIFO error event. 661 */ 662 __weak void BSP_AUDIO_OUT_Error_CallBack(void) 663 { 664 } 665 666 /******************************************************************************* 667 Static Functions 668 *******************************************************************************/ 669 670 /** 671 * @brief Initializes the Audio Codec audio interface (I2S). 672 * @param AudioFreq: Audio frequency to be configured for the I2S peripheral. 673 */ 674 static uint8_t I2S3_Init(uint32_t AudioFreq) 675 { 676 /* Initialize the hAudioOutI2s Instance parameter */ 677 hAudioOutI2s.Instance = I2S3; 678 679 /* Disable I2S block */ 680 __HAL_I2S_DISABLE(&hAudioOutI2s); 681 682 /* I2S3 peripheral configuration */ 683 hAudioOutI2s.Init.AudioFreq = AudioFreq; 684 hAudioOutI2s.Init.ClockSource = I2S_CLOCK_PLL; 685 hAudioOutI2s.Init.CPOL = I2S_CPOL_LOW; 686 hAudioOutI2s.Init.DataFormat = I2S_DATAFORMAT_16B; 687 hAudioOutI2s.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE; 688 hAudioOutI2s.Init.Mode = I2S_MODE_MASTER_TX; 689 hAudioOutI2s.Init.Standard = I2S_STANDARD; 690 /* Initialize the I2S peripheral with the structure above */ 691 if(HAL_I2S_Init(&hAudioOutI2s) != HAL_OK) 692 { 693 return AUDIO_ERROR; 694 } 695 else 696 { 697 return AUDIO_OK; 698 } 699 } 700 701 /** 702 * @} 703 */ 704 705 /** @defgroup STM32F4_DISCOVERY_AUDIO_IN_Private_Functions STM32F4 DISCOVERY AUDIO IN Private Functions 706 * @{ 707 */ 708 709 /** 710 * @brief Initializes wave recording. 711 * @param AudioFreq: Audio frequency to be configured for the I2S peripheral. 712 * @param BitRes: Audio frequency to be configured for the I2S peripheral. 713 * @param ChnlNbr: Audio frequency to be configured for the I2S peripheral. 714 * @retval AUDIO_OK if correct communication, else wrong communication 715 */ 716 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 717 { 718 719 #if 0 720 // BK: only do PLL clock configuration in sink 721 /* Configure PLL clock */ 722 BSP_AUDIO_IN_ClockConfig(&hAudioInI2s, AudioFreq, NULL); 723 #endif 724 725 /* Configure the PDM library */ 726 PDMDecoder_Init(AudioFreq, ChnlNbr); 727 728 /* Configure the I2S peripheral */ 729 hAudioInI2s.Instance = I2S2; 730 if(HAL_I2S_GetState(&hAudioInI2s) == HAL_I2S_STATE_RESET) 731 { 732 /* Initialize the I2S Msp: this __weak function can be rewritten by the application */ 733 BSP_AUDIO_IN_MspInit(&hAudioInI2s, NULL); 734 } 735 736 /* Configure the I2S2 */ 737 I2S2_Init(AudioFreq); 738 739 /* Return AUDIO_OK when all operations are correctly done */ 740 return AUDIO_OK; 741 } 742 743 /** 744 * @brief Starts audio recording. 745 * @param pbuf: Main buffer pointer for the recorded data storing 746 * @param size: Current size of the recorded buffer 747 * @retval AUDIO_OK if correct communication, else wrong communication 748 */ 749 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size) 750 { 751 uint32_t ret = AUDIO_ERROR; 752 753 /* Start the process receive DMA */ 754 HAL_I2S_Receive_DMA(&hAudioInI2s, pbuf, size); 755 756 /* Return AUDIO_OK when all operations are correctly done */ 757 ret = AUDIO_OK; 758 759 return ret; 760 } 761 762 /** 763 * @brief Stops audio recording. 764 * @retval AUDIO_OK if correct communication, else wrong communication 765 */ 766 uint8_t BSP_AUDIO_IN_Stop(void) 767 { 768 uint32_t ret = AUDIO_ERROR; 769 770 /* Call the Media layer pause function */ 771 HAL_I2S_DMAStop(&hAudioInI2s); 772 773 /* Return AUDIO_OK when all operations are correctly done */ 774 ret = AUDIO_OK; 775 776 return ret; 777 } 778 779 /** 780 * @brief Pauses the audio file stream. 781 * @retval AUDIO_OK if correct communication, else wrong communication 782 */ 783 uint8_t BSP_AUDIO_IN_Pause(void) 784 { 785 /* Call the Media layer pause function */ 786 HAL_I2S_DMAPause(&hAudioInI2s); 787 788 /* Return AUDIO_OK when all operations are correctly done */ 789 return AUDIO_OK; 790 } 791 792 /** 793 * @brief Resumes the audio file stream. 794 * @retval AUDIO_OK if correct communication, else wrong communication 795 */ 796 uint8_t BSP_AUDIO_IN_Resume(void) 797 { 798 /* Call the Media layer pause/resume function */ 799 HAL_I2S_DMAResume(&hAudioInI2s); 800 801 /* Return AUDIO_OK when all operations are correctly done */ 802 return AUDIO_OK; 803 } 804 805 /** 806 * @brief Controls the audio in volume level. 807 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 808 * Mute and 100 for Max volume level). 809 * @retval AUDIO_OK if correct communication, else wrong communication 810 */ 811 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume) 812 { 813 /* Set the Global variable AudioInVolume */ 814 AudioInVolume = Volume; 815 816 /* Return AUDIO_OK when all operations are correctly done */ 817 return AUDIO_OK; 818 } 819 820 /** 821 * @brief Converts audio format from PDM to PCM. 822 * @param PDMBuf: Pointer to data PDM buffer 823 * @param PCMBuf: Pointer to data PCM buffer 824 * @retval AUDIO_OK if correct communication, else wrong communication 825 */ 826 uint8_t BSP_AUDIO_IN_PDMToPCM(uint16_t *PDMBuf, uint16_t *PCMBuf) 827 { 828 uint16_t AppPDM[INTERNAL_BUFF_SIZE/2]; 829 uint32_t index = 0; 830 831 /* PDM Demux */ 832 for(index = 0; index<INTERNAL_BUFF_SIZE/2; index++) 833 { 834 AppPDM[index] = HTONS(PDMBuf[index]); 835 } 836 837 for(index = 0; index < DEFAULT_AUDIO_IN_CHANNEL_NBR; index++) 838 { 839 /* PDM to PCM filter */ 840 PDM_Filter_64_LSB((uint8_t*)&AppPDM[index], (uint16_t*)&(PCMBuf[index]), AudioInVolume , (PDMFilter_InitStruct *)&Filter[index]); 841 } 842 #if 0 843 // BK - generate mono output 844 845 /* Duplicate samples since a single microphone in mounted on STM32F4-Discovery */ 846 for(index = 0; index < PCM_OUT_SIZE; index++) 847 { 848 PCMBuf[(index<<1)+1] = PCMBuf[index<<1]; 849 } 850 #endif 851 852 /* Return AUDIO_OK when all operations are correctly done */ 853 return AUDIO_OK; 854 } 855 856 /** 857 * @brief Rx Transfer completed callbacks 858 * @param hi2s: I2S handle 859 */ 860 void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) 861 { 862 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 863 BSP_AUDIO_IN_TransferComplete_CallBack(); 864 } 865 866 /** 867 * @brief Rx Half Transfer completed callbacks. 868 * @param hi2s: I2S handle 869 */ 870 void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s) 871 { 872 /* Manage the remaining file size and new address offset: This function 873 should be coded by user (its prototype is already declared in stm32f4_discovery_audio.h) */ 874 BSP_AUDIO_IN_HalfTransfer_CallBack(); 875 } 876 877 /** 878 * @brief Audio In Clock Config. 879 * @param hi2s: I2S handle 880 * @param AudioFreq: Audio frequency used to record the audio stream. 881 * @param Params : pointer on additional configuration parameters, can be NULL. 882 * @note This API is called by BSP_AUDIO_IN_Init() 883 * Being __weak it can be overwritten by the application 884 */ 885 __weak void BSP_AUDIO_IN_ClockConfig(I2S_HandleTypeDef *hi2s, uint32_t AudioFreq, void *Params) 886 { 887 RCC_PeriphCLKInitTypeDef rccclkinit; 888 889 /*Enable PLLI2S clock*/ 890 HAL_RCCEx_GetPeriphCLKConfig(&rccclkinit); 891 /* PLLI2S_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */ 892 if ((AudioFreq & 0x7) == 0) 893 { 894 /* Audio frequency multiple of 8 (8/16/32/48/96/192)*/ 895 /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN = 192 Mhz */ 896 /* I2SCLK = PLLI2S_VCO Output/PLLI2SR = 192/6 = 32 Mhz */ 897 rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S; 898 rccclkinit.PLLI2S.PLLI2SN = 192; 899 rccclkinit.PLLI2S.PLLI2SR = 6; 900 HAL_RCCEx_PeriphCLKConfig(&rccclkinit); 901 } 902 else 903 { 904 /* Other Frequency (11.025/22.500/44.100) */ 905 /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN = 290 Mhz */ 906 /* I2SCLK = PLLI2S_VCO Output/PLLI2SR = 290/2 = 145 Mhz */ 907 rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S; 908 rccclkinit.PLLI2S.PLLI2SN = 290; 909 rccclkinit.PLLI2S.PLLI2SR = 2; 910 HAL_RCCEx_PeriphCLKConfig(&rccclkinit); 911 } 912 } 913 914 /** 915 * @brief BSP AUDIO IN MSP Init. 916 * @param hi2s: I2S handle 917 * @param Params : pointer on additional configuration parameters, can be NULL. 918 */ 919 __weak void BSP_AUDIO_IN_MspInit(I2S_HandleTypeDef *hi2s, void *Params) 920 { 921 static DMA_HandleTypeDef hdma_i2sRx; 922 GPIO_InitTypeDef GPIO_InitStruct; 923 924 /* Enable the I2S2 peripheral clock */ 925 I2S2_CLK_ENABLE(); 926 927 /* Enable I2S GPIO clocks */ 928 I2S2_SCK_GPIO_CLK_ENABLE(); 929 I2S2_MOSI_GPIO_CLK_ENABLE(); 930 931 /* I2S2 pins configuration: SCK and MOSI pins ------------------------------*/ 932 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 933 GPIO_InitStruct.Pull = GPIO_NOPULL; 934 GPIO_InitStruct.Speed = GPIO_SPEED_FAST; 935 936 GPIO_InitStruct.Pin = I2S2_SCK_PIN; 937 GPIO_InitStruct.Alternate = I2S2_SCK_AF; 938 HAL_GPIO_Init(I2S2_SCK_GPIO_PORT, &GPIO_InitStruct); 939 940 GPIO_InitStruct.Pin = I2S2_MOSI_PIN ; 941 GPIO_InitStruct.Alternate = I2S2_MOSI_AF; 942 HAL_GPIO_Init(I2S2_MOSI_GPIO_PORT, &GPIO_InitStruct); 943 944 /* Enable the DMA clock */ 945 I2S2_DMAx_CLK_ENABLE(); 946 947 if(hi2s->Instance == I2S2) 948 { 949 /* Configure the hdma_i2sRx handle parameters */ 950 hdma_i2sRx.Init.Channel = I2S2_DMAx_CHANNEL; 951 hdma_i2sRx.Init.Direction = DMA_PERIPH_TO_MEMORY; 952 hdma_i2sRx.Init.PeriphInc = DMA_PINC_DISABLE; 953 hdma_i2sRx.Init.MemInc = DMA_MINC_ENABLE; 954 hdma_i2sRx.Init.PeriphDataAlignment = I2S2_DMAx_PERIPH_DATA_SIZE; 955 hdma_i2sRx.Init.MemDataAlignment = I2S2_DMAx_MEM_DATA_SIZE; 956 hdma_i2sRx.Init.Mode = DMA_CIRCULAR; 957 hdma_i2sRx.Init.Priority = DMA_PRIORITY_HIGH; 958 hdma_i2sRx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 959 hdma_i2sRx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 960 hdma_i2sRx.Init.MemBurst = DMA_MBURST_SINGLE; 961 hdma_i2sRx.Init.PeriphBurst = DMA_MBURST_SINGLE; 962 963 hdma_i2sRx.Instance = I2S2_DMAx_STREAM; 964 965 /* Associate the DMA handle */ 966 __HAL_LINKDMA(hi2s, hdmarx, hdma_i2sRx); 967 968 /* Deinitialize the Stream for new transfer */ 969 HAL_DMA_DeInit(&hdma_i2sRx); 970 971 /* Configure the DMA Stream */ 972 HAL_DMA_Init(&hdma_i2sRx); 973 } 974 975 /* I2S DMA IRQ Channel configuration */ 976 HAL_NVIC_SetPriority(I2S2_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 977 HAL_NVIC_EnableIRQ(I2S2_DMAx_IRQ); 978 } 979 980 /** 981 * @brief DeInitializes BSP_AUDIO_IN MSP. 982 * @param hi2s: I2S handle 983 * @param Params : pointer on additional configuration parameters, can be NULL. 984 */ 985 __weak void BSP_AUDIO_IN_MspDeInit(I2S_HandleTypeDef *hi2s, void *Params) 986 { 987 GPIO_InitTypeDef gpio_init_structure; 988 989 /* I2S DMA IRQ Channel deactivation */ 990 HAL_NVIC_DisableIRQ(I2S2_DMAx_IRQ); 991 992 if(hi2s->Instance == I2S2) 993 { 994 /* Deinitialize the Stream for new transfer */ 995 HAL_DMA_DeInit(hi2s->hdmarx); 996 } 997 998 /* Disable I2S block */ 999 __HAL_I2S_DISABLE(hi2s); 1000 1001 /* Disable pins: SCK and SD pins */ 1002 gpio_init_structure.Pin = I2S2_SCK_PIN; 1003 HAL_GPIO_DeInit(I2S2_SCK_GPIO_PORT, gpio_init_structure.Pin); 1004 gpio_init_structure.Pin = I2S2_MOSI_PIN; 1005 HAL_GPIO_DeInit(I2S2_MOSI_GPIO_PORT, gpio_init_structure.Pin); 1006 1007 /* Disable I2S clock */ 1008 I2S2_CLK_DISABLE(); 1009 1010 /* GPIO pins clock and DMA clock can be shut down in the applic 1011 by surcgarging this __weak function */ 1012 } 1013 1014 /** 1015 * @brief User callback when record buffer is filled. 1016 */ 1017 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void) 1018 { 1019 /* This function should be implemented by the user application. 1020 It is called into this driver when the current buffer is filled 1021 to prepare the next buffer pointer and its size. */ 1022 } 1023 1024 /** 1025 * @brief Manages the DMA Half Transfer complete event. 1026 */ 1027 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 1028 { 1029 /* This function should be implemented by the user application. 1030 It is called into this driver when the current buffer is filled 1031 to prepare the next buffer pointer and its size. */ 1032 } 1033 1034 /** 1035 * @brief Audio IN Error callback function. 1036 */ 1037 __weak void BSP_AUDIO_IN_Error_Callback(void) 1038 { 1039 /* This function is called when an Interrupt due to transfer error on or peripheral 1040 error occurs. */ 1041 } 1042 1043 /******************************************************************************* 1044 Static Functions 1045 *******************************************************************************/ 1046 1047 /** 1048 * @brief Initialize the PDM library. 1049 * @param AudioFreq: Audio sampling frequency 1050 * @param ChnlNbr: Number of audio channels (1: mono; 2: stereo) 1051 */ 1052 static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr) 1053 { 1054 #if 1 1055 uint32_t i = 0; 1056 1057 /* Enable CRC peripheral to unlock the PDM library */ 1058 __CRC_CLK_ENABLE(); 1059 1060 for(i = 0; i < ChnlNbr; i++) 1061 { 1062 /* Filter LP and HP Init */ 1063 Filter[i].LP_HZ = AudioFreq / 2; 1064 Filter[i].HP_HZ = 10; 1065 Filter[i].Fs = AudioFreq; 1066 /* On STM32F4-Discovery a single microphone is mounted, samples are duplicated 1067 to make stereo audio streams */ 1068 // BK - generate mono output 1069 // Filter[i].Out_MicChannels = 2; 1070 Filter[i].Out_MicChannels = 1; 1071 Filter[i].In_MicChannels = ChnlNbr; 1072 PDM_Filter_Init((PDMFilter_InitStruct *)&Filter[i]); 1073 } 1074 #endif 1075 } 1076 1077 /** 1078 * @brief Initializes the Audio Codec audio interface (I2S) 1079 * @note This function assumes that the I2S input clock (through PLL_R in 1080 * Devices RevA/Z and through dedicated PLLI2S_R in Devices RevB/Y) 1081 * is already configured and ready to be used. 1082 * @param AudioFreq: Audio frequency to be configured for the I2S peripheral. 1083 */ 1084 static uint8_t I2S2_Init(uint32_t AudioFreq) 1085 { 1086 /* Initialize the hAudioInI2s Instance parameter */ 1087 hAudioInI2s.Instance = I2S2; 1088 1089 /* Disable I2S block */ 1090 __HAL_I2S_DISABLE(&hAudioInI2s); 1091 1092 /* I2S2 peripheral configuration */ 1093 hAudioInI2s.Init.AudioFreq = 2 * AudioFreq; 1094 hAudioInI2s.Init.ClockSource = I2S_CLOCK_PLL; 1095 hAudioInI2s.Init.CPOL = I2S_CPOL_HIGH; 1096 hAudioInI2s.Init.DataFormat = I2S_DATAFORMAT_16B; 1097 hAudioInI2s.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE; 1098 hAudioInI2s.Init.Mode = I2S_MODE_MASTER_RX; 1099 hAudioInI2s.Init.Standard = I2S_STANDARD_LSB; 1100 1101 /* Initialize the I2S peripheral with the structure above */ 1102 if(HAL_I2S_Init(&hAudioInI2s) != HAL_OK) 1103 { 1104 return AUDIO_ERROR; 1105 } 1106 else 1107 { 1108 return AUDIO_OK; 1109 } 1110 } 1111 1112 /** 1113 * @} 1114 */ 1115 1116 /** @defgroup STM32F4_DISCOVERY_AUDIO_IN_OUT_Private_Functions STM32F4 DISCOVERY AUDIO IN OUT Private Functions 1117 * @{ 1118 */ 1119 1120 /** 1121 * @brief I2S error callbacks. 1122 * @param hi2s: I2S handle 1123 */ 1124 void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s) 1125 { 1126 /* Manage the error generated on DMA FIFO: This function 1127 should be coded by user (its prototype is already declared in stm32f4_discovery_audio.h) */ 1128 if(hi2s->Instance == I2S3) 1129 { 1130 BSP_AUDIO_OUT_Error_CallBack(); 1131 } 1132 if(hi2s->Instance == I2S2) 1133 { 1134 BSP_AUDIO_IN_Error_Callback(); 1135 } 1136 } 1137 1138 /** 1139 * @} 1140 */ 1141 1142 /** 1143 * @} 1144 */ 1145 1146 /** 1147 * @} 1148 */ 1149 1150 /** 1151 * @} 1152 */ 1153 1154 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 1155