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