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