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