STM32F723E-Discovery BSP User Manual
|
stm32f723e_discovery_audio.c
Go to the documentation of this file.
00001 /** 00002 ****************************************************************************** 00003 * @file stm32f723e_discovery_audio.c 00004 * @author MCD Application Team 00005 * @brief This file provides the Audio driver for the STM32F723E-DISCOVERY 00006 * board. 00007 @verbatim 00008 How To use this driver: 00009 ----------------------- 00010 + This driver supports STM32F7xx devices on STM32F723E-DISCOVERY (MB1260) Evaluation boards. 00011 + Call the function BSP_AUDIO_OUT_Init( 00012 OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 00013 OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH) 00014 Volume : Initial volume to be set (0 is min (mute), 100 is max (100%) 00015 AudioFreq : Audio frequency in Hz (8000, 16000, 22500, 32000...) 00016 this parameter is relative to the audio file/stream type. 00017 ) 00018 This function configures all the hardware required for the audio application (codec, I2C, SAI, 00019 GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK. 00020 If the returned value is different from AUDIO_OK or the function is stuck then the communication with 00021 the codec has failed (try to un-plug the power or reset device in this case). 00022 - OUTPUT_DEVICE_SPEAKER : only speaker will be set as output for the audio stream. 00023 - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream. 00024 - OUTPUT_DEVICE_BOTH : both Speaker and Headphone are used as outputs for the audio stream 00025 at the same time. 00026 + Call the function BSP_DISCOVERY_AUDIO_OUT_Play( 00027 pBuffer: pointer to the audio data file address 00028 Size : size of the buffer to be sent in Bytes 00029 ) 00030 to start playing (for the first time) from the audio file/stream. 00031 + Call the function BSP_AUDIO_OUT_Pause() to pause playing 00032 + Call the function BSP_AUDIO_OUT_Resume() to resume playing. 00033 Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called 00034 for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case). 00035 Note. This function should be called only when the audio file is played or paused (not stopped). 00036 + For each mode, you may need to implement the relative callback functions into your code. 00037 The Callback functions are named AUDIO_OUT_XXX_CallBack() and only their prototypes are declared in 00038 the stm32f723e_discovery_audio.h file. (refer to the example for more details on the callbacks implementations) 00039 + To Stop playing, to modify the volume level, the frequency, the audio frame slot, 00040 the device output mode the mute or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(), 00041 AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetAudioFrameSlot(), BSP_AUDIO_OUT_SetOutputMode(), 00042 BSP_AUDIO_OUT_SetMute() and BSP_AUDIO_OUT_Stop(). 00043 + The driver API and the callback functions are at the end of the stm32f723e_discovery_audio.h file. 00044 00045 + Call the function BSP_AUDIO_IN_Init( 00046 InputDevice: physical input mode (INPUT_DEVICE_DIGITAL_MICROPHONE_1, 00047 INPUT_DEVICE_DIGITAL_MICROPHONE_2, INPUT_DEVICE_DIGITAL_MIC1_MIC2 00048 or INPUT_DEVICE_INPUT_LINE_1) 00049 Volume : Initial volume to be set (0 is min (mute), 100 is max (100%) 00050 AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000...) 00051 this parameter is relative to the audio file/stream type. 00052 ) 00053 This function configures all the hardware required for the AUDIO IN application (SAI blocks, 00054 SAI clock source, GPIOs, DMA and interrupt if needed). 00055 This function returns AUDIO_OK if configuration is OK.If the returned value is different from AUDIO_OK then 00056 the configuration should be wrong. 00057 Note: On STM32F723E-DISCOVERY, two SAI blocks are configured and their DMA streams are configured 00058 in CIRCULAR mode. 00059 + Call the function BSP_AUDIO_IN_RECORD( 00060 pBuf: pointer to the recorded audio data file address 00061 Size: size of the buffer to be written in Bytes 00062 ) 00063 to start recording from microphones. 00064 00065 + Call the function BSP_AUDIO_IN_Pause() to pause recording 00066 + Call the function BSP_AUDIO_IN_Resume() to recording playing. 00067 Note. After calling BSP_AUDIO_IN_Pause() function for pause, only BSP_AUDIO_IN_Resume() should be called 00068 for resume (it is not allowed to call BSP_AUDIO_IN_RECORD() in this case). 00069 + Call the function BSP_AUDIO_IN_Stop() to stop recording 00070 + For each mode, you may need to implement the relative callback functions into your code. 00071 The Callback functions are named BSP_AUDIO_IN_XXX_CallBack() and only their prototypes are declared in 00072 the stm32f723e_discovery_audio.h file. (refer to the example for more details on the callbacks implementations) 00073 00074 + Call the function BSP_AUDIO_IN_OUT_Init( 00075 InputDevice : physical input mode (INPUT_DEVICE_DIGITAL_MICROPHONE_1, 00076 INPUT_DEVICE_DIGITAL_MICROPHONE_2, INPUT_DEVICE_DIGITAL_MIC1_MIC2 00077 or INPUT_DEVICE_INPUT_LINE_1) 00078 OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 00079 OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH) 00080 Volume : Initial volume to be set (0 is min (mute), 100 is max (100%) 00081 AudioFreq : Audio frequency in Hz (8000, 16000, 22500, 32000...) 00082 this parameter is relative to the audio file/stream type. 00083 ) 00084 This function configures all the hardware required for the AUDIO IN(record) and AUDIO OUT(play) 00085 application (SAI blocks, SAI clock source, GPIOs, DMA and interrupt if needed). 00086 00087 Driver architecture: 00088 -------------------- 00089 + This driver provides the High Audio Layer: consists of the function API exported in the stm32f723e_discovery_audio.h file 00090 (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...) 00091 + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/ 00092 providing the audio file/stream. These functions are also included as local functions into 00093 the stm32f723e_discovery_audio.c file (SAIx_Out_Init() and SAIx_Out_DeInit(), SAIx_In_Init() and SAIx_In_DeInit()) 00094 00095 Known Limitations: 00096 ------------------ 00097 1- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second 00098 Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams. 00099 2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 00100 File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file. 00101 3- Supports only Stereo audio streaming. 00102 4- Supports only 16-bits audio data size. 00103 @endverbatim 00104 ****************************************************************************** 00105 * @attention 00106 * 00107 * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> 00108 * 00109 * Redistribution and use in source and binary forms, with or without modification, 00110 * are permitted provided that the following conditions are met: 00111 * 1. Redistributions of source code must retain the above copyright notice, 00112 * this list of conditions and the following disclaimer. 00113 * 2. Redistributions in binary form must reproduce the above copyright notice, 00114 * this list of conditions and the following disclaimer in the documentation 00115 * and/or other materials provided with the distribution. 00116 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00117 * may be used to endorse or promote products derived from this software 00118 * without specific prior written permission. 00119 * 00120 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00121 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00122 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00123 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00124 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00125 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00126 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00127 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00128 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00129 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00130 * 00131 ****************************************************************************** 00132 */ 00133 00134 /* Dependencies 00135 - stm32f723e_discovery.c 00136 - stm32f7xx_hal_sai.c 00137 - stm32f7xx_hal_dma.c 00138 - stm32f7xx_hal_gpio.c 00139 - stm32f7xx_hal_cortex.c 00140 - stm32f7xx_hal_rcc_ex.h 00141 - wm8994.c 00142 EndDependencies */ 00143 00144 /* Includes ------------------------------------------------------------------*/ 00145 #include "stm32f723e_discovery_audio.h" 00146 00147 /** @addtogroup BSP 00148 * @{ 00149 */ 00150 00151 /** @addtogroup STM32F723E_DISCOVERY 00152 * @{ 00153 */ 00154 00155 /** @defgroup STM32F723E_DISCOVERY_AUDIO STM32F723E_DISCOVERY_AUDIO 00156 * @brief This file includes the low layer driver for wm8994 Audio Codec 00157 * available on STM32F723E-DISCOVERY discoveryuation board(MB1260). 00158 * @{ 00159 */ 00160 00161 /** @defgroup STM32F723E_DISCOVERY_AUDIO_Private_Types STM32F723E_DISCOVERY_AUDIO Private Types 00162 * @{ 00163 */ 00164 /** 00165 * @} 00166 */ 00167 00168 /** @defgroup STM32F723E_DISCOVERY_AUDIO_Private_Defines STM32F723E_DISCOVERY_AUDIO Private Defines 00169 * @{ 00170 */ 00171 /** 00172 * @} 00173 */ 00174 00175 /** @defgroup STM32F723E_DISCOVERY_AUDIO_Private_Macros STM32F723E_DISCOVERY_AUDIO Private Macros 00176 * @{ 00177 */ 00178 00179 /** 00180 * @} 00181 */ 00182 00183 /** @defgroup STM32F723E_DISCOVERY_AUDIO_Private_Variables STM32F723E_DISCOVERY_AUDIO Private Variables 00184 * @{ 00185 */ 00186 AUDIO_DrvTypeDef *audio_drv; 00187 SAI_HandleTypeDef haudio_out_sai; 00188 SAI_HandleTypeDef haudio_in_sai; 00189 00190 uint16_t __IO AudioInVolume = DEFAULT_AUDIO_IN_VOLUME; 00191 /** 00192 * @} 00193 */ 00194 00195 /** @defgroup STM32F723E_DISCOVERY_AUDIO_Private_Function_Prototypes STM32F723E_DISCOVERY_AUDIO Private Function Prototypes 00196 * @{ 00197 */ 00198 static void SAIx_Out_Init(uint32_t AudioFreq); 00199 static void SAIx_Out_DeInit(void); 00200 static void SAIx_In_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq); 00201 static void SAIx_In_DeInit(void); 00202 00203 /** 00204 * @} 00205 */ 00206 00207 /** @defgroup STM32F723E_DISCOVERY_AUDIO_out_Private_Functions STM32F723E_DISCOVERY_AUDIO_Out Private Functions 00208 * @{ 00209 */ 00210 00211 /** 00212 * @brief Configures the audio out peripheral(SAI2 BlockA). 00213 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00214 * or OUTPUT_DEVICE_BOTH. 00215 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00216 * @param AudioFreq: Audio frequency used to play the audio stream. 00217 * @retval AUDIO_OK if correct communication, else wrong communication 00218 */ 00219 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00220 { 00221 uint8_t ret = AUDIO_ERROR; 00222 uint32_t deviceid = 0x00; 00223 00224 /* Disable SAI */ 00225 SAIx_Out_DeInit(); 00226 00227 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00228 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00229 00230 /* SAI data transfer preparation: 00231 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00232 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00233 if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET) 00234 { 00235 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00236 BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL); 00237 } 00238 SAIx_Out_Init(AudioFreq); 00239 00240 /* wm8994 codec initialization */ 00241 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00242 00243 if((deviceid) == WM8994_ID) 00244 { 00245 /* Reset the Codec Registers */ 00246 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00247 /* Initialize the audio driver structure */ 00248 audio_drv = &wm8994_drv; 00249 ret = AUDIO_OK; 00250 } 00251 else 00252 { 00253 ret = AUDIO_ERROR; 00254 } 00255 00256 if(ret == AUDIO_OK) 00257 { 00258 /* Initialize the codec internal registers */ 00259 audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq); 00260 } 00261 00262 return ret; 00263 } 00264 00265 /** 00266 * @brief Starts playing audio stream from a data buffer for a determined size. 00267 * @param pBuffer: Pointer to the buffer 00268 * @param Size: Number of audio data BYTES. 00269 * @retval AUDIO_OK if correct communication, else wrong communication 00270 */ 00271 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size) 00272 { 00273 /* Call the audio Codec Play function */ 00274 if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0) 00275 { 00276 return AUDIO_ERROR; 00277 } 00278 else 00279 { 00280 /* Update the Media layer and enable it for play */ 00281 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE)); 00282 00283 return AUDIO_OK; 00284 } 00285 } 00286 00287 /** 00288 * @brief This function Pauses the audio file stream. In case 00289 * of using DMA, the DMA Pause feature is used. 00290 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00291 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00292 * function for resume could lead to unexpected behaviour). 00293 * @retval AUDIO_OK if correct communication, else wrong communication 00294 */ 00295 uint8_t BSP_AUDIO_OUT_Pause(void) 00296 { 00297 /* Call the Audio Codec Pause/Resume function */ 00298 if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0) 00299 { 00300 return AUDIO_ERROR; 00301 } 00302 else 00303 { 00304 /* Call the Media layer pause function */ 00305 HAL_SAI_DMAPause(&haudio_out_sai); 00306 00307 /* Return AUDIO_OK when all operations are correctly done */ 00308 return AUDIO_OK; 00309 } 00310 } 00311 00312 /** 00313 * @brief This function Resumes the audio file stream. 00314 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00315 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00316 * function for resume could lead to unexpected behaviour). 00317 * @retval AUDIO_OK if correct communication, else wrong communication 00318 */ 00319 uint8_t BSP_AUDIO_OUT_Resume(void) 00320 { 00321 /* Call the Audio Codec Pause/Resume function */ 00322 if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0) 00323 { 00324 return AUDIO_ERROR; 00325 } 00326 else 00327 { 00328 /* Call the Media layer pause/resume function */ 00329 HAL_SAI_DMAResume(&haudio_out_sai); 00330 00331 /* Return AUDIO_OK when all operations are correctly done */ 00332 return AUDIO_OK; 00333 } 00334 } 00335 00336 /** 00337 * @brief Stops audio playing and Power down the Audio Codec. 00338 * @param Option: could be one of the following parameters 00339 * - CODEC_PDWN_SW: for software power off (by writing registers). 00340 * Then no need to reconfigure the Codec after power on. 00341 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00342 * Then need to reconfigure the Codec after power on. 00343 * @retval AUDIO_OK if correct communication, else wrong communication 00344 */ 00345 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option) 00346 { 00347 /* Call the Media layer stop function */ 00348 HAL_SAI_DMAStop(&haudio_out_sai); 00349 00350 /* Call Audio Codec Stop function */ 00351 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 00352 { 00353 return AUDIO_ERROR; 00354 } 00355 else 00356 { 00357 if(Option == CODEC_PDWN_HW) 00358 { 00359 /* Wait at least 100us */ 00360 HAL_Delay(1); 00361 } 00362 /* Return AUDIO_OK when all operations are correctly done */ 00363 return AUDIO_OK; 00364 } 00365 } 00366 00367 /** 00368 * @brief Controls the current audio volume level. 00369 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00370 * Mute and 100 for Max volume level). 00371 * @retval AUDIO_OK if correct communication, else wrong communication 00372 */ 00373 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume) 00374 { 00375 /* Call the codec volume control function with converted volume value */ 00376 if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 00377 { 00378 return AUDIO_ERROR; 00379 } 00380 else 00381 { 00382 /* Return AUDIO_OK when all operations are correctly done */ 00383 return AUDIO_OK; 00384 } 00385 } 00386 00387 /** 00388 * @brief Enables or disables the MUTE mode by software 00389 * @param Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 00390 * unmute the codec and restore previous volume level. 00391 * @retval AUDIO_OK if correct communication, else wrong communication 00392 */ 00393 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd) 00394 { 00395 /* Call the Codec Mute function */ 00396 if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0) 00397 { 00398 return AUDIO_ERROR; 00399 } 00400 else 00401 { 00402 /* Return AUDIO_OK when all operations are correctly done */ 00403 return AUDIO_OK; 00404 } 00405 } 00406 00407 /** 00408 * @brief Switch dynamically (while audio file is played) the output target 00409 * (speaker or headphone). 00410 * @param Output: The audio output target: OUTPUT_DEVICE_SPEAKER, 00411 * OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH 00412 * @retval AUDIO_OK if correct communication, else wrong communication 00413 */ 00414 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output) 00415 { 00416 /* Call the Codec output device function */ 00417 if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0) 00418 { 00419 return AUDIO_ERROR; 00420 } 00421 else 00422 { 00423 /* Return AUDIO_OK when all operations are correctly done */ 00424 return AUDIO_OK; 00425 } 00426 } 00427 00428 /** 00429 * @brief Updates the audio frequency. 00430 * @param AudioFreq: Audio frequency used to play the audio stream. 00431 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00432 * audio frequency. 00433 * @retval None 00434 */ 00435 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq) 00436 { 00437 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00438 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00439 00440 /* Disable SAI peripheral to allow access to SAI internal registers */ 00441 __HAL_SAI_DISABLE(&haudio_out_sai); 00442 00443 /* Update the SAI audio frequency configuration */ 00444 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00445 HAL_SAI_Init(&haudio_out_sai); 00446 00447 /* Enable SAI peripheral to generate MCLK */ 00448 __HAL_SAI_ENABLE(&haudio_out_sai); 00449 } 00450 00451 /** 00452 * @brief Updates the Audio frame slot configuration. 00453 * @param AudioFrameSlot: specifies the audio Frame slot 00454 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00455 * audio frame slot. 00456 * @retval None 00457 */ 00458 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot) 00459 { 00460 /* Disable SAI peripheral to allow access to SAI internal registers */ 00461 __HAL_SAI_DISABLE(&haudio_out_sai); 00462 00463 /* Update the SAI audio frame slot configuration */ 00464 haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot; 00465 HAL_SAI_Init(&haudio_out_sai); 00466 00467 /* Enable SAI peripheral to generate MCLK */ 00468 __HAL_SAI_ENABLE(&haudio_out_sai); 00469 } 00470 00471 /** 00472 * @brief Send n-Bytes on the SAI interface. 00473 * @param pData: pointer on data address 00474 * @param Size: number of data to be written 00475 * @retval None 00476 */ 00477 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size) 00478 { 00479 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size); 00480 } 00481 00482 /** 00483 * @brief Deinit the audio peripherals. 00484 * @retval None 00485 */ 00486 void BSP_AUDIO_OUT_DeInit(void) 00487 { 00488 SAIx_Out_DeInit(); 00489 /* DeInit the SAI MSP : this __weak function can be rewritten by the application */ 00490 BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL); 00491 } 00492 00493 /** 00494 * @brief Tx Transfer completed callbacks. 00495 * @param hsai: SAI handle 00496 * @retval None 00497 */ 00498 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) 00499 { 00500 /* Manage the remaining file size and new address offset: This function 00501 should be coded by user (its prototype is already declared in stm32f723e_discovery_audio.h) */ 00502 BSP_AUDIO_OUT_TransferComplete_CallBack(); 00503 } 00504 00505 /** 00506 * @brief Tx Half Transfer completed callbacks. 00507 * @param hsai: SAI handle 00508 * @retval None 00509 */ 00510 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 00511 { 00512 /* Manage the remaining file size and new address offset: This function 00513 should be coded by user (its prototype is already declared in stm32f723e_discovery_audio.h) */ 00514 BSP_AUDIO_OUT_HalfTransfer_CallBack(); 00515 } 00516 00517 /** 00518 * @brief SAI error callbacks. 00519 * @param hsai: SAI handle 00520 * @retval None 00521 */ 00522 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 00523 { 00524 BSP_AUDIO_OUT_Error_CallBack(); 00525 } 00526 00527 /** 00528 * @brief Manages the DMA full Transfer complete event. 00529 * @retval None 00530 */ 00531 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void) 00532 { 00533 } 00534 00535 /** 00536 * @brief Manages the DMA Half Transfer complete event. 00537 * @retval None 00538 */ 00539 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) 00540 { 00541 } 00542 00543 /** 00544 * @brief Manages the DMA FIFO error event. 00545 * @retval None 00546 */ 00547 __weak void BSP_AUDIO_OUT_Error_CallBack(void) 00548 { 00549 } 00550 00551 /** 00552 * @brief Initializes BSP_AUDIO_OUT MSP. 00553 * @param hsai: SAI handle 00554 * @param Params 00555 * @retval None 00556 */ 00557 __weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params) 00558 { 00559 static DMA_HandleTypeDef hdma_sai_tx; 00560 GPIO_InitTypeDef gpio_init_structure; 00561 00562 /* Enable SAI clock */ 00563 AUDIO_OUT_SAIx_CLK_ENABLE(); 00564 00565 /* Enable GPIO clock */ 00566 AUDIO_OUT_SAIx_MCLK_ENABLE(); 00567 AUDIO_OUT_SAIx_SD_FS_CLK_ENABLE(); 00568 00569 /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/ 00570 gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SD_PIN; 00571 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00572 gpio_init_structure.Pull = GPIO_NOPULL; 00573 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00574 gpio_init_structure.Alternate = AUDIO_OUT_SAIx_AF; 00575 HAL_GPIO_Init(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, &gpio_init_structure); 00576 00577 gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN; 00578 HAL_GPIO_Init(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, &gpio_init_structure); 00579 00580 /* Enable the DMA clock */ 00581 AUDIO_OUT_SAIx_DMAx_CLK_ENABLE(); 00582 00583 if(hsai->Instance == AUDIO_OUT_SAIx) 00584 { 00585 /* Configure the hdma_saiTx handle parameters */ 00586 hdma_sai_tx.Init.Channel = AUDIO_OUT_SAIx_DMAx_CHANNEL; 00587 hdma_sai_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; 00588 hdma_sai_tx.Init.PeriphInc = DMA_PINC_DISABLE; 00589 hdma_sai_tx.Init.MemInc = DMA_MINC_ENABLE; 00590 hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_OUT_SAIx_DMAx_PERIPH_DATA_SIZE; 00591 hdma_sai_tx.Init.MemDataAlignment = AUDIO_OUT_SAIx_DMAx_MEM_DATA_SIZE; 00592 hdma_sai_tx.Init.Mode = DMA_CIRCULAR; 00593 hdma_sai_tx.Init.Priority = DMA_PRIORITY_HIGH; 00594 hdma_sai_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; 00595 hdma_sai_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 00596 hdma_sai_tx.Init.MemBurst = DMA_MBURST_SINGLE; 00597 hdma_sai_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; 00598 00599 hdma_sai_tx.Instance = AUDIO_OUT_SAIx_DMAx_STREAM; 00600 00601 /* Associate the DMA handle */ 00602 __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx); 00603 00604 /* Deinitialize the Stream for new transfer */ 00605 HAL_DMA_DeInit(&hdma_sai_tx); 00606 00607 /* Configure the DMA Stream */ 00608 HAL_DMA_Init(&hdma_sai_tx); 00609 } 00610 00611 /* SAI DMA IRQ Channel configuration */ 00612 HAL_NVIC_SetPriority(AUDIO_OUT_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 00613 HAL_NVIC_EnableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ); 00614 } 00615 00616 /** 00617 * @brief Deinitializes SAI MSP. 00618 * @param hsai: SAI handle 00619 * @param Params 00620 * @retval None 00621 */ 00622 __weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params) 00623 { 00624 GPIO_InitTypeDef gpio_init_structure; 00625 00626 /* SAI DMA IRQ Channel deactivation */ 00627 HAL_NVIC_DisableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ); 00628 00629 if(hsai->Instance == AUDIO_OUT_SAIx) 00630 { 00631 /* Deinitialize the DMA stream */ 00632 HAL_DMA_DeInit(hsai->hdmatx); 00633 } 00634 00635 /* Disable SAI peripheral */ 00636 __HAL_SAI_DISABLE(hsai); 00637 00638 /* Deactivates CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */ 00639 gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SCK_PIN; 00640 HAL_GPIO_DeInit(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, gpio_init_structure.Pin); 00641 00642 gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN; 00643 HAL_GPIO_DeInit(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin); 00644 00645 /* Disable SAI clock */ 00646 AUDIO_OUT_SAIx_CLK_DISABLE(); 00647 00648 /* GPIO pins clock and DMA clock can be shut down in the applic 00649 by surcharging this __weak function */ 00650 } 00651 00652 /** 00653 * @brief Clock Config. 00654 * @param hsai: might be required to set audio peripheral predivider if any. 00655 * @param AudioFreq: Audio frequency used to play the audio stream. 00656 * @param Params 00657 * @note This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency() 00658 * Being __weak it can be overwritten by the application 00659 * @retval None 00660 */ 00661 __weak void BSP_AUDIO_OUT_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params) 00662 { 00663 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 00664 00665 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 00666 00667 /* Set the PLL configuration according to the audio frequency */ 00668 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 00669 { 00670 /* Configure PLLSAI prescalers */ 00671 /* PLLSAI_VCO: VCO_429M 00672 SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 429/2 = 214.5 Mhz 00673 SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 214.5/19 = 11.289 Mhz */ 00674 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 00675 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S; 00676 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429; 00677 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2; 00678 rcc_ex_clk_init_struct.PLLI2SDivQ = 19; 00679 00680 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00681 00682 } 00683 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 00684 { 00685 /* SAI clock config 00686 PLLSAI_VCO: VCO_344M 00687 SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 344/7 = 49.142 Mhz 00688 SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 49.142/1 = 49.142 Mhz */ 00689 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 00690 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S; 00691 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 00692 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 00693 rcc_ex_clk_init_struct.PLLI2SDivQ = 1; 00694 00695 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00696 } 00697 } 00698 00699 /******************************************************************************* 00700 Static Functions 00701 *******************************************************************************/ 00702 00703 /** 00704 * @brief Initializes the Audio Codec audio interface (SAI). 00705 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00706 * @note The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 00707 * and user can update this configuration using 00708 * @retval None 00709 */ 00710 static void SAIx_Out_Init(uint32_t AudioFreq) 00711 { 00712 /* Initialize the haudio_out_sai Instance parameter */ 00713 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00714 00715 /* Disable SAI peripheral to allow access to SAI internal registers */ 00716 __HAL_SAI_DISABLE(&haudio_out_sai); 00717 00718 /* Configure SAI_Block_x 00719 LSBFirst: Disabled 00720 DataSize: 16 */ 00721 haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE; 00722 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00723 haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX; 00724 haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED; 00725 haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL; 00726 haudio_out_sai.Init.DataSize = SAI_DATASIZE_16; 00727 haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 00728 haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; 00729 haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS; 00730 haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE; 00731 haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 00732 haudio_out_sai.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 00733 haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING; 00734 haudio_out_sai.Init.TriState = SAI_OUTPUT_NOTRELEASED; 00735 haudio_out_sai.Init.Mckdiv = 0; 00736 00737 /* Configure SAI_Block_x Frame 00738 Frame Length: 64 00739 Frame active Length: 32 00740 FS Definition: Start frame + Channel Side identification 00741 FS Polarity: FS active Low 00742 FS Offset: FS asserted one bit before the first bit of slot 0 */ 00743 haudio_out_sai.FrameInit.FrameLength = 64; 00744 haudio_out_sai.FrameInit.ActiveFrameLength = 32; 00745 haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 00746 haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 00747 haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 00748 00749 /* Configure SAI Block_x Slot 00750 Slot First Bit Offset: 0 00751 Slot Size : 16 00752 Slot Number: 4 00753 Slot Active: All slot actives */ 00754 haudio_out_sai.SlotInit.FirstBitOffset = 0; 00755 haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 00756 haudio_out_sai.SlotInit.SlotNumber = 4; 00757 haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123; 00758 00759 HAL_SAI_Init(&haudio_out_sai); 00760 00761 /* Enable SAI peripheral to generate MCLK */ 00762 __HAL_SAI_ENABLE(&haudio_out_sai); 00763 } 00764 00765 /** 00766 * @brief Deinitializes the Audio Codec audio interface (SAI). 00767 * @retval None 00768 */ 00769 static void SAIx_Out_DeInit(void) 00770 { 00771 /* Initialize the haudio_out_sai Instance parameter */ 00772 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00773 00774 /* Disable SAI peripheral */ 00775 __HAL_SAI_DISABLE(&haudio_out_sai); 00776 00777 HAL_SAI_DeInit(&haudio_out_sai); 00778 } 00779 00780 00781 /** 00782 * @} 00783 */ 00784 00785 /** @defgroup STM32F723E_DISCOVERY_AUDIO_In_Private_Functions STM32F723E_DISCOVERY_AUDIO_In Private Functions 00786 * @{ 00787 */ 00788 00789 /** 00790 * @brief Initializes wave recording. 00791 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00792 * @param BitRes: Audio frequency to be configured. 00793 * @param ChnlNbr: Channel number. 00794 * @retval AUDIO_OK if correct communication, else wrong communication 00795 */ 00796 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00797 { 00798 return BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC1_MIC2, AudioFreq, BitRes, ChnlNbr); 00799 } 00800 00801 /** 00802 * @brief Initializes wave recording. 00803 * @param InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_1, INPUT_DEVICE_DIGITAL_MICROPHONE_2 00804 * INPUT_DEVICE_INPUT_LINE_1 or INPUT_DEVICE_DIGITAL_MIC1_MIC2 00805 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00806 * @param BitRes: Audio frequency to be configured. 00807 * @param ChnlNbr: Channel number. 00808 * @retval AUDIO_OK if correct communication, else wrong communication 00809 */ 00810 uint8_t BSP_AUDIO_IN_InitEx(uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00811 { 00812 uint8_t ret = AUDIO_ERROR; 00813 uint32_t deviceid = 0x00; 00814 uint32_t slot_active; 00815 00816 /* Only INPUT_LINE_1, MICROPHONE_1, MICROPHONE_2 and MIC1&MIC2 inputs supported */ 00817 if ((InputDevice != INPUT_DEVICE_INPUT_LINE_1) && 00818 (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_1) && 00819 (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2) && 00820 (InputDevice != INPUT_DEVICE_DIGITAL_MIC1_MIC2)) 00821 { 00822 ret = AUDIO_ERROR; 00823 } 00824 else 00825 { 00826 /* Disable SAI */ 00827 SAIx_In_DeInit(); 00828 00829 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */ 00830 BSP_AUDIO_IN_ClockConfig(&haudio_in_sai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */ 00831 00832 /* SAI data transfer preparation: 00833 Prepare the Media to be used for the audio transfer from SAI peripheral to memory */ 00834 haudio_in_sai.Instance = AUDIO_IN_SAIx; 00835 if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET) 00836 { 00837 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00838 BSP_AUDIO_OUT_MspInit(&haudio_in_sai, NULL); /* Initialize GPIOs for SAI2 block A Master signals */ 00839 BSP_AUDIO_IN_MspInit(&haudio_in_sai, NULL); 00840 } 00841 00842 /* Configure SAI in master RX mode : 00843 * - SAI2_block_A in master RX mode 00844 * - SAI2_block_B in slave RX mode synchronous from SAI2_block_A 00845 */ 00846 if (InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2) 00847 { 00848 slot_active = CODEC_AUDIOFRAME_SLOT_13; 00849 } 00850 else if (InputDevice == INPUT_DEVICE_DIGITAL_MIC1_MIC2) 00851 { 00852 slot_active = CODEC_AUDIOFRAME_SLOT_0123; 00853 } 00854 else 00855 { 00856 slot_active = CODEC_AUDIOFRAME_SLOT_02; 00857 } 00858 SAIx_In_Init(SAI_MODEMASTER_RX, slot_active, AudioFreq); 00859 00860 /* wm8994 codec initialization */ 00861 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00862 00863 if((deviceid) == WM8994_ID) 00864 { 00865 /* Reset the Codec Registers */ 00866 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00867 /* Initialize the audio driver structure */ 00868 audio_drv = &wm8994_drv; 00869 ret = AUDIO_OK; 00870 } 00871 else 00872 { 00873 ret = AUDIO_ERROR; 00874 } 00875 00876 if(ret == AUDIO_OK) 00877 { 00878 /* Initialize the codec internal registers */ 00879 audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice, 100, AudioFreq); 00880 } 00881 } 00882 return ret; 00883 } 00884 00885 /** 00886 * @brief Initializes wave recording and playback in parallel. 00887 * @param InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_1, INPUT_DEVICE_DIGITAL_MICROPHONE_2 00888 * or INPUT_DEVICE_DIGITAL_MIC1_MIC2 00889 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00890 * or OUTPUT_DEVICE_BOTH. 00891 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00892 * @param BitRes: Audio frequency to be configured. 00893 * @param ChnlNbr: Channel number. 00894 * @retval AUDIO_OK if correct communication, else wrong communication 00895 */ 00896 uint8_t BSP_AUDIO_IN_OUT_Init(uint16_t InputDevice, uint16_t OutputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00897 { 00898 uint8_t ret = AUDIO_ERROR; 00899 uint32_t deviceid = 0x00; 00900 uint32_t slot_active; 00901 00902 if ((InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_1) && 00903 (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2) && 00904 (InputDevice != INPUT_DEVICE_DIGITAL_MIC1_MIC2)) 00905 { 00906 ret = AUDIO_ERROR; 00907 } 00908 else 00909 { 00910 /* Disable SAI */ 00911 SAIx_In_DeInit(); 00912 SAIx_Out_DeInit(); 00913 00914 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */ 00915 BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */ 00916 00917 /* SAI data transfer preparation: 00918 Prepare the Media to be used for the audio transfer from SAI peripheral to memory */ 00919 haudio_in_sai.Instance = AUDIO_IN_SAIx; 00920 if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET) 00921 { 00922 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00923 BSP_AUDIO_IN_MspInit(&haudio_in_sai, NULL); 00924 } 00925 00926 /* SAI data transfer preparation: 00927 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00928 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00929 if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET) 00930 { 00931 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00932 BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL); 00933 } 00934 00935 /* Configure SAI in master mode : 00936 * - SAI2_block_A in master TX mode 00937 * - SAI2_block_B in slave RX mode synchronous from SAI2_block_A 00938 */ 00939 if (InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2) 00940 { 00941 slot_active = CODEC_AUDIOFRAME_SLOT_13; 00942 } 00943 else if (InputDevice == INPUT_DEVICE_DIGITAL_MIC1_MIC2) 00944 { 00945 slot_active = CODEC_AUDIOFRAME_SLOT_0123; 00946 } 00947 else 00948 { 00949 slot_active = CODEC_AUDIOFRAME_SLOT_02; 00950 } 00951 SAIx_In_Init(SAI_MODEMASTER_TX, slot_active, AudioFreq); 00952 00953 /* wm8994 codec initialization */ 00954 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00955 00956 if((deviceid) == WM8994_ID) 00957 { 00958 /* Reset the Codec Registers */ 00959 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00960 /* Initialize the audio driver structure */ 00961 audio_drv = &wm8994_drv; 00962 ret = AUDIO_OK; 00963 } 00964 else 00965 { 00966 ret = AUDIO_ERROR; 00967 } 00968 00969 if(ret == AUDIO_OK) 00970 { 00971 /* Initialize the codec internal registers */ 00972 audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice | OutputDevice, 100, AudioFreq); 00973 } 00974 } 00975 return ret; 00976 } 00977 00978 /** 00979 * @brief Starts audio recording. 00980 * @param pbuf: Main buffer pointer for the recorded data storing 00981 * @param size: size of the recorded buffer in number of elements (typically number of half-words) 00982 * Be careful that it is not the same unit than BSP_AUDIO_OUT_Play function 00983 * @retval AUDIO_OK if correct communication, else wrong communication 00984 */ 00985 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size) 00986 { 00987 uint32_t ret = AUDIO_ERROR; 00988 00989 /* Start the process receive DMA */ 00990 if(HAL_SAI_Receive_DMA(&haudio_in_sai, (uint8_t*)pbuf, size) == HAL_OK) 00991 { 00992 /* Return AUDIO_OK when all operations are correctly done */ 00993 ret = AUDIO_OK; 00994 } 00995 00996 return ret; 00997 } 00998 00999 /** 01000 * @brief Stops audio recording. 01001 * @param Option: could be one of the following parameters 01002 * - CODEC_PDWN_SW: for software power off (by writing registers). 01003 * Then no need to reconfigure the Codec after power on. 01004 * - CODEC_PDWN_HW: completely shut down the codec (physically). 01005 * Then need to reconfigure the Codec after power on. 01006 * @retval AUDIO_OK if correct communication, else wrong communication 01007 */ 01008 uint8_t BSP_AUDIO_IN_Stop(uint32_t Option) 01009 { 01010 /* Call the Media layer stop function */ 01011 HAL_SAI_DMAStop(&haudio_in_sai); 01012 01013 /* Call Audio Codec Stop function */ 01014 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 01015 { 01016 return AUDIO_ERROR; 01017 } 01018 else 01019 { 01020 if(Option == CODEC_PDWN_HW) 01021 { 01022 /* Wait at least 100us */ 01023 HAL_Delay(1); 01024 } 01025 /* Return AUDIO_OK when all operations are correctly done */ 01026 return AUDIO_OK; 01027 } 01028 } 01029 01030 /** 01031 * @brief Pauses the audio file stream. 01032 * @retval AUDIO_OK if correct communication, else wrong communication 01033 */ 01034 uint8_t BSP_AUDIO_IN_Pause(void) 01035 { 01036 /* Call the Media layer pause function */ 01037 HAL_SAI_DMAPause(&haudio_in_sai); 01038 /* Return AUDIO_OK when all operations are correctly done */ 01039 return AUDIO_OK; 01040 } 01041 01042 /** 01043 * @brief Resumes the audio file stream. 01044 * @retval AUDIO_OK if correct communication, else wrong communication 01045 */ 01046 uint8_t BSP_AUDIO_IN_Resume(void) 01047 { 01048 /* Call the Media layer pause/resume function */ 01049 HAL_SAI_DMAResume(&haudio_in_sai); 01050 /* Return AUDIO_OK when all operations are correctly done */ 01051 return AUDIO_OK; 01052 } 01053 01054 /** 01055 * @brief Controls the audio in volume level. 01056 * @param Volume: Volume level in range 0(Mute)..80(+0dB)..100(+17.625dB) 01057 * @retval AUDIO_OK if correct communication, else wrong communication 01058 */ 01059 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume) 01060 { 01061 /* Call the codec volume control function with converted volume value */ 01062 if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 01063 { 01064 return AUDIO_ERROR; 01065 } 01066 else 01067 { 01068 /* Set the Global variable AudioInVolume */ 01069 AudioInVolume = Volume; 01070 /* Return AUDIO_OK when all operations are correctly done */ 01071 return AUDIO_OK; 01072 } 01073 } 01074 01075 /** 01076 * @brief Deinit the audio IN peripherals. 01077 * @retval None 01078 */ 01079 void BSP_AUDIO_IN_DeInit(void) 01080 { 01081 SAIx_In_DeInit(); 01082 /* DeInit the SAI MSP : this __weak function can be rewritten by the application */ 01083 BSP_AUDIO_IN_MspDeInit(&haudio_in_sai, NULL); 01084 } 01085 01086 /** 01087 * @brief Rx Transfer completed callbacks. 01088 * @param hsai: SAI handle 01089 * @retval None 01090 */ 01091 void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai) 01092 { 01093 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01094 BSP_AUDIO_IN_TransferComplete_CallBack(); 01095 } 01096 01097 /** 01098 * @brief Rx Half Transfer completed callbacks. 01099 * @param hsai: SAI handle 01100 * @retval None 01101 */ 01102 void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai) 01103 { 01104 /* Manage the remaining file size and new address offset: This function 01105 should be coded by user (its prototype is already declared in stm32f723e_discovery_audio.h) */ 01106 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01107 } 01108 01109 /** 01110 * @brief User callback when record buffer is filled. 01111 * @retval None 01112 */ 01113 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void) 01114 { 01115 /* This function should be implemented by the user application. 01116 It is called into this driver when the current buffer is filled 01117 to prepare the next buffer pointer and its size. */ 01118 } 01119 01120 /** 01121 * @brief Manages the DMA Half Transfer complete event. 01122 * @retval None 01123 */ 01124 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 01125 { 01126 /* This function should be implemented by the user application. 01127 It is called into this driver when the current buffer is filled 01128 to prepare the next buffer pointer and its size. */ 01129 } 01130 01131 /** 01132 * @brief Audio IN Error callback function. 01133 * @retval None 01134 */ 01135 __weak void BSP_AUDIO_IN_Error_CallBack(void) 01136 { 01137 /* This function is called when an Interrupt due to transfer error on or peripheral 01138 error occurs. */ 01139 } 01140 01141 /** 01142 * @brief Initializes BSP_AUDIO_IN MSP. 01143 * @param hsai: SAI handle 01144 * @param Params 01145 * @retval None 01146 */ 01147 __weak void BSP_AUDIO_IN_MspInit(SAI_HandleTypeDef *hsai, void *Params) 01148 { 01149 static DMA_HandleTypeDef hdma_sai_rx; 01150 GPIO_InitTypeDef gpio_init_structure; 01151 01152 /* Enable SAI clock */ 01153 AUDIO_IN_SAIx_CLK_ENABLE(); 01154 01155 /* Enable SD GPIO clock */ 01156 AUDIO_IN_SAIx_SD_ENABLE(); 01157 /* CODEC_SAI pin configuration: SD pin */ 01158 gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN; 01159 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 01160 gpio_init_structure.Pull = GPIO_NOPULL; 01161 gpio_init_structure.Speed = GPIO_SPEED_FAST; 01162 gpio_init_structure.Alternate = AUDIO_IN_SAIx_SD_AF; 01163 HAL_GPIO_Init(AUDIO_IN_SAIx_SD_GPIO_PORT, &gpio_init_structure); 01164 01165 /* Enable Audio INT GPIO clock */ 01166 AUDIO_IN_INT_GPIO_ENABLE(); 01167 /* Audio INT pin configuration: input */ 01168 gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN; 01169 gpio_init_structure.Mode = GPIO_MODE_INPUT; 01170 gpio_init_structure.Pull = GPIO_NOPULL; 01171 gpio_init_structure.Speed = GPIO_SPEED_FAST; 01172 HAL_GPIO_Init(AUDIO_IN_INT_GPIO_PORT, &gpio_init_structure); 01173 01174 /* Enable the DMA clock */ 01175 AUDIO_IN_SAIx_DMAx_CLK_ENABLE(); 01176 01177 if(hsai->Instance == AUDIO_IN_SAIx) 01178 { 01179 /* Configure the hdma_sai_rx handle parameters */ 01180 hdma_sai_rx.Init.Channel = AUDIO_IN_SAIx_DMAx_CHANNEL; 01181 hdma_sai_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; 01182 hdma_sai_rx.Init.PeriphInc = DMA_PINC_DISABLE; 01183 hdma_sai_rx.Init.MemInc = DMA_MINC_ENABLE; 01184 hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAIx_DMAx_PERIPH_DATA_SIZE; 01185 hdma_sai_rx.Init.MemDataAlignment = AUDIO_IN_SAIx_DMAx_MEM_DATA_SIZE; 01186 hdma_sai_rx.Init.Mode = DMA_CIRCULAR; 01187 hdma_sai_rx.Init.Priority = DMA_PRIORITY_HIGH; 01188 hdma_sai_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 01189 hdma_sai_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 01190 hdma_sai_rx.Init.MemBurst = DMA_MBURST_SINGLE; 01191 hdma_sai_rx.Init.PeriphBurst = DMA_MBURST_SINGLE; 01192 01193 hdma_sai_rx.Instance = AUDIO_IN_SAIx_DMAx_STREAM; 01194 01195 /* Associate the DMA handle */ 01196 __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx); 01197 01198 /* Deinitialize the Stream for new transfer */ 01199 HAL_DMA_DeInit(&hdma_sai_rx); 01200 01201 /* Configure the DMA Stream */ 01202 HAL_DMA_Init(&hdma_sai_rx); 01203 } 01204 01205 /* SAI DMA IRQ Channel configuration */ 01206 HAL_NVIC_SetPriority(AUDIO_IN_SAIx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 01207 HAL_NVIC_EnableIRQ(AUDIO_IN_SAIx_DMAx_IRQ); 01208 01209 /* Audio INT IRQ Channel configuration */ 01210 HAL_NVIC_SetPriority(AUDIO_IN_INT_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 01211 HAL_NVIC_EnableIRQ(AUDIO_IN_INT_IRQ); 01212 } 01213 01214 /** 01215 * @brief DeInitializes BSP_AUDIO_IN MSP. 01216 * @param hsai: SAI handle 01217 * @param Params 01218 * @retval None 01219 */ 01220 __weak void BSP_AUDIO_IN_MspDeInit(SAI_HandleTypeDef *hsai, void *Params) 01221 { 01222 GPIO_InitTypeDef gpio_init_structure; 01223 01224 /* SAI IN DMA IRQ Channel deactivation */ 01225 HAL_NVIC_DisableIRQ(AUDIO_IN_SAIx_DMAx_IRQ); 01226 01227 if(hsai->Instance == AUDIO_IN_SAIx) 01228 { 01229 /* Deinitialize the Stream for new transfer */ 01230 HAL_DMA_DeInit(haudio_in_sai.hdmarx); 01231 } 01232 01233 /* Disable SAI block */ 01234 __HAL_SAI_DISABLE(hsai); 01235 01236 /* Disable pin: SD pin */ 01237 gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN; 01238 HAL_GPIO_DeInit(AUDIO_IN_SAIx_SD_GPIO_PORT, gpio_init_structure.Pin); 01239 01240 /* Disable SAI clock */ 01241 AUDIO_IN_SAIx_CLK_DISABLE(); 01242 01243 /* GPIO pins clock and DMA clock can be shut down in the application 01244 by surcharging this __weak function */ 01245 } 01246 01247 /** 01248 * @brief Clock Config. 01249 * @param hsai: might be required to set audio peripheral predivider if any. 01250 * @param AudioFreq: Audio frequency used to play the audio stream. 01251 * @param Params 01252 * @note This API is called by BSP_AUDIO_IN_Init() 01253 * Being __weak it can be overwritten by the application 01254 * @retval None 01255 */ 01256 __weak void BSP_AUDIO_IN_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params) 01257 { 01258 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 01259 01260 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 01261 01262 /* Set the PLL configuration according to the audio frequency */ 01263 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 01264 { 01265 /* Configure PLLSAI prescalers */ 01266 /* PLLSAI_VCO: VCO_429M 01267 SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 429/2 = 214.5 Mhz 01268 SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 214.5/19 = 11.289 Mhz */ 01269 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 01270 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S; 01271 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429; 01272 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2; 01273 rcc_ex_clk_init_struct.PLLI2SDivQ = 19; 01274 01275 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01276 01277 } 01278 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K), AUDIO_FREQUENCY_96K */ 01279 { 01280 /* SAI clock config 01281 PLLSAI_VCO: VCO_344M 01282 SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 344/7 = 49.142 Mhz 01283 SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 49.142/1 = 49.142 Mhz */ 01284 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 01285 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S; 01286 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 01287 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 01288 rcc_ex_clk_init_struct.PLLI2SDivQ = 1; 01289 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01290 } 01291 } 01292 01293 /******************************************************************************* 01294 Static Functions 01295 *******************************************************************************/ 01296 /** 01297 * @brief Initializes the input Audio Codec audio interface (SAI). 01298 * @param SaiOutMode: SAI_MODEMASTER_TX (for record and playback in parallel) 01299 * or SAI_MODEMASTER_RX (for record only). 01300 * @param SlotActive: CODEC_AUDIOFRAME_SLOT_02, CODEC_AUDIOFRAME_SLOT_13 or 01301 * CODEC_AUDIOFRAME_SLOT_0123 01302 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 01303 * @retval None 01304 */ 01305 static void SAIx_In_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq) 01306 { 01307 /* Initialize the haudio_out_sai instance parameters */ 01308 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 01309 01310 /* Disable SAI peripheral to allow access to SAI internal registers */ 01311 __HAL_SAI_DISABLE(&haudio_out_sai); 01312 01313 /* Configure SAI_Block_x 01314 LSBFirst: Disabled 01315 DataSize: 16 */ 01316 haudio_out_sai.Init.AudioFrequency = AudioFreq; 01317 haudio_out_sai.Init.AudioMode = SaiOutMode; 01318 haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; 01319 haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL; 01320 haudio_out_sai.Init.DataSize = SAI_DATASIZE_16; 01321 haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 01322 haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; 01323 haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS; 01324 haudio_out_sai.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 01325 haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE; 01326 haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 01327 haudio_out_sai.Init.Mckdiv = 0; 01328 haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE; 01329 haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING; 01330 haudio_out_sai.Init.TriState = SAI_OUTPUT_NOTRELEASED; 01331 01332 /* Configure SAI_Block_x Frame 01333 Frame Length: 64 01334 Frame active Length: 32 01335 FS Definition: Start frame + Channel Side identification 01336 FS Polarity: FS active Low 01337 FS Offset: FS asserted one bit before the first bit of slot 0 */ 01338 haudio_out_sai.FrameInit.FrameLength = 64; 01339 haudio_out_sai.FrameInit.ActiveFrameLength = 32; 01340 haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 01341 haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 01342 haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 01343 01344 /* Configure SAI Block_x Slot 01345 Slot First Bit Offset: 0 01346 Slot Size : 16 01347 Slot Number: 4 01348 Slot Active: All slot actives */ 01349 haudio_out_sai.SlotInit.FirstBitOffset = 0; 01350 haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 01351 haudio_out_sai.SlotInit.SlotNumber = 4; 01352 haudio_out_sai.SlotInit.SlotActive = SlotActive; 01353 01354 HAL_SAI_Init(&haudio_out_sai); 01355 01356 /* Initialize SAI2 block B in SLAVE RX synchronous from SAI2 block A */ 01357 /* Initialize the haudio_in_sai instance parameters */ 01358 haudio_in_sai.Instance = AUDIO_IN_SAIx; 01359 01360 /* Disable SAI peripheral to allow access to SAI internal registers */ 01361 __HAL_SAI_DISABLE(&haudio_in_sai); 01362 01363 /* Configure SAI_Block_x 01364 LSBFirst: Disabled 01365 DataSize: 16 */ 01366 haudio_in_sai.Init.AudioFrequency = AudioFreq; 01367 haudio_in_sai.Init.AudioMode = SAI_MODESLAVE_RX; 01368 haudio_in_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; 01369 haudio_in_sai.Init.Protocol = SAI_FREE_PROTOCOL; 01370 haudio_in_sai.Init.DataSize = SAI_DATASIZE_16; 01371 haudio_in_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 01372 haudio_in_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 01373 haudio_in_sai.Init.Synchro = SAI_SYNCHRONOUS; 01374 haudio_in_sai.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 01375 haudio_in_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE; 01376 haudio_in_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 01377 haudio_in_sai.Init.Mckdiv = 0; 01378 haudio_in_sai.Init.MonoStereoMode = SAI_STEREOMODE; 01379 haudio_in_sai.Init.CompandingMode = SAI_NOCOMPANDING; 01380 haudio_in_sai.Init.TriState = SAI_OUTPUT_NOTRELEASED; 01381 01382 /* Configure SAI_Block_x Frame 01383 Frame Length: 64 01384 Frame active Length: 32 01385 FS Definition: Start frame + Channel Side identification 01386 FS Polarity: FS active Low 01387 FS Offset: FS asserted one bit before the first bit of slot 0 */ 01388 haudio_in_sai.FrameInit.FrameLength = 64; 01389 haudio_in_sai.FrameInit.ActiveFrameLength = 32; 01390 haudio_in_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 01391 haudio_in_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 01392 haudio_in_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 01393 01394 /* Configure SAI Block_x Slot 01395 Slot First Bit Offset: 0 01396 Slot Size : 16 01397 Slot Number: 4 01398 Slot Active: All slot active */ 01399 haudio_in_sai.SlotInit.FirstBitOffset = 0; 01400 haudio_in_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 01401 haudio_in_sai.SlotInit.SlotNumber = 4; 01402 haudio_in_sai.SlotInit.SlotActive = SlotActive; 01403 01404 HAL_SAI_Init(&haudio_in_sai); 01405 01406 /* Enable SAI peripheral */ 01407 __HAL_SAI_ENABLE(&haudio_in_sai); 01408 01409 /* Enable SAI peripheral to generate MCLK */ 01410 __HAL_SAI_ENABLE(&haudio_out_sai); 01411 } 01412 01413 01414 01415 /** 01416 * @brief Deinitializes the output Audio Codec audio interface (SAI). 01417 * @retval None 01418 */ 01419 static void SAIx_In_DeInit(void) 01420 { 01421 /* Initialize the haudio_in_sai Instance parameter */ 01422 haudio_in_sai.Instance = AUDIO_IN_SAIx; 01423 01424 /* Disable SAI peripheral */ 01425 __HAL_SAI_DISABLE(&haudio_in_sai); 01426 01427 HAL_SAI_DeInit(&haudio_in_sai); 01428 } 01429 01430 /** 01431 * @} 01432 */ 01433 01434 /** 01435 * @} 01436 */ 01437 01438 /** 01439 * @} 01440 */ 01441 01442 /** 01443 * @} 01444 */ 01445 01446 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue May 30 2017 13:59:12 for STM32F723E-Discovery BSP User Manual by 1.7.6.1