STM32746G-Discovery board drivers V1.0.0
Dependents: F746_SD_GraphicEqualizer_ren0620
Fork of BSP_DISCO_F746NG 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 AUDIO_IN_INT_IRQHandler(void); 00151 static void AUDIO_IN_SAIx_DMAx_IRQHandler(void); 00152 static void AUDIO_OUT_SAIx_DMAx_IRQHandler(void); 00153 static void SAIx_Out_Init(uint32_t AudioFreq); 00154 static void SAIx_Out_DeInit(void); 00155 static void SAIx_In_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq); 00156 static void SAIx_In_DeInit(void); 00157 /** 00158 * @} 00159 */ 00160 00161 /** @defgroup STM32746G_DISCOVERY_AUDIO_OUT_Exported_Functions STM32746G_DISCOVERY AUDIO Out Exported Functions 00162 * @{ 00163 */ 00164 00165 /** 00166 * @brief Configures the audio peripherals. 00167 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00168 * or OUTPUT_DEVICE_BOTH. 00169 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00170 * @param AudioFreq: Audio frequency used to play the audio stream. 00171 * @note The I2S PLL input clock must be done in the user application. 00172 * @retval AUDIO_OK if correct communication, else wrong communication 00173 */ 00174 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00175 { 00176 uint8_t ret = AUDIO_ERROR; 00177 uint32_t deviceid = 0x00; 00178 00179 /* Disable SAI */ 00180 SAIx_Out_DeInit(); 00181 00182 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */ 00183 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00184 00185 /* SAI data transfer preparation: 00186 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00187 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00188 if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET) 00189 { 00190 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00191 BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL); 00192 } 00193 SAIx_Out_Init(AudioFreq); 00194 00195 /* wm8994 codec initialization */ 00196 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00197 00198 if((deviceid) == WM8994_ID) 00199 { 00200 /* Reset the Codec Registers */ 00201 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00202 /* Initialize the audio driver structure */ 00203 audio_drv = &wm8994_drv; 00204 ret = AUDIO_OK; 00205 } 00206 else 00207 { 00208 ret = AUDIO_ERROR; 00209 } 00210 00211 if(ret == AUDIO_OK) 00212 { 00213 /* Initialize the codec internal registers */ 00214 audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq); 00215 } 00216 00217 return ret; 00218 } 00219 00220 /** 00221 * @brief Starts playing audio stream from a data buffer for a determined size. 00222 * @param pBuffer: Pointer to the buffer 00223 * @param Size: Number of audio data in BYTES unit. 00224 * In memory, first element is for left channel, second element is for right channel 00225 * @retval AUDIO_OK if correct communication, else wrong communication 00226 */ 00227 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size) 00228 { 00229 /* Call the audio Codec Play function */ 00230 if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0) 00231 { 00232 return AUDIO_ERROR; 00233 } 00234 else 00235 { 00236 /* Update the Media layer and enable it for play */ 00237 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE)); 00238 00239 return AUDIO_OK; 00240 } 00241 } 00242 00243 /** 00244 * @brief Sends n-Bytes on the SAI interface. 00245 * @param pData: pointer on data address 00246 * @param Size: number of data to be written 00247 * @retval None 00248 */ 00249 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size) 00250 { 00251 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size); 00252 } 00253 00254 /** 00255 * @brief This function Pauses the audio file stream. In case 00256 * of using DMA, the DMA Pause feature is used. 00257 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00258 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00259 * function for resume could lead to unexpected behaviour). 00260 * @retval AUDIO_OK if correct communication, else wrong communication 00261 */ 00262 uint8_t BSP_AUDIO_OUT_Pause(void) 00263 { 00264 /* Call the Audio Codec Pause/Resume function */ 00265 if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0) 00266 { 00267 return AUDIO_ERROR; 00268 } 00269 else 00270 { 00271 /* Call the Media layer pause function */ 00272 HAL_SAI_DMAPause(&haudio_out_sai); 00273 00274 /* Return AUDIO_OK when all operations are correctly done */ 00275 return AUDIO_OK; 00276 } 00277 } 00278 00279 /** 00280 * @brief This function Resumes the audio file stream. 00281 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00282 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00283 * function for resume could lead to unexpected behaviour). 00284 * @retval AUDIO_OK if correct communication, else wrong communication 00285 */ 00286 uint8_t BSP_AUDIO_OUT_Resume(void) 00287 { 00288 /* Call the Audio Codec Pause/Resume function */ 00289 if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0) 00290 { 00291 return AUDIO_ERROR; 00292 } 00293 else 00294 { 00295 /* Call the Media layer pause/resume function */ 00296 HAL_SAI_DMAResume(&haudio_out_sai); 00297 00298 /* Return AUDIO_OK when all operations are correctly done */ 00299 return AUDIO_OK; 00300 } 00301 } 00302 00303 /** 00304 * @brief Stops audio playing and Power down the Audio Codec. 00305 * @param Option: could be one of the following parameters 00306 * - CODEC_PDWN_SW: for software power off (by writing registers). 00307 * Then no need to reconfigure the Codec after power on. 00308 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00309 * Then need to reconfigure the Codec after power on. 00310 * @retval AUDIO_OK if correct communication, else wrong communication 00311 */ 00312 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option) 00313 { 00314 /* Call the Media layer stop function */ 00315 HAL_SAI_DMAStop(&haudio_out_sai); 00316 00317 /* Call Audio Codec Stop function */ 00318 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 00319 { 00320 return AUDIO_ERROR; 00321 } 00322 else 00323 { 00324 if(Option == CODEC_PDWN_HW) 00325 { 00326 /* Wait at least 100us */ 00327 HAL_Delay(1); 00328 } 00329 /* Return AUDIO_OK when all operations are correctly done */ 00330 return AUDIO_OK; 00331 } 00332 } 00333 00334 /** 00335 * @brief Controls the current audio volume level. 00336 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00337 * Mute and 100 for Max volume level). 00338 * @retval AUDIO_OK if correct communication, else wrong communication 00339 */ 00340 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume) 00341 { 00342 /* Call the codec volume control function with converted volume value */ 00343 if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 00344 { 00345 return AUDIO_ERROR; 00346 } 00347 else 00348 { 00349 /* Return AUDIO_OK when all operations are correctly done */ 00350 return AUDIO_OK; 00351 } 00352 } 00353 00354 /** 00355 * @brief Enables or disables the MUTE mode by software 00356 * @param Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 00357 * unmute the codec and restore previous volume level. 00358 * @retval AUDIO_OK if correct communication, else wrong communication 00359 */ 00360 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd) 00361 { 00362 /* Call the Codec Mute function */ 00363 if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0) 00364 { 00365 return AUDIO_ERROR; 00366 } 00367 else 00368 { 00369 /* Return AUDIO_OK when all operations are correctly done */ 00370 return AUDIO_OK; 00371 } 00372 } 00373 00374 /** 00375 * @brief Switch dynamically (while audio file is played) the output target 00376 * (speaker or headphone). 00377 * @param Output: The audio output target: OUTPUT_DEVICE_SPEAKER, 00378 * OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH 00379 * @retval AUDIO_OK if correct communication, else wrong communication 00380 */ 00381 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output) 00382 { 00383 /* Call the Codec output device function */ 00384 if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0) 00385 { 00386 return AUDIO_ERROR; 00387 } 00388 else 00389 { 00390 /* Return AUDIO_OK when all operations are correctly done */ 00391 return AUDIO_OK; 00392 } 00393 } 00394 00395 /** 00396 * @brief Updates the audio frequency. 00397 * @param AudioFreq: Audio frequency used to play the audio stream. 00398 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00399 * audio frequency. 00400 * @retval None 00401 */ 00402 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq) 00403 { 00404 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00405 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00406 00407 /* Disable SAI peripheral to allow access to SAI internal registers */ 00408 __HAL_SAI_DISABLE(&haudio_out_sai); 00409 00410 /* Update the SAI audio frequency configuration */ 00411 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00412 HAL_SAI_Init(&haudio_out_sai); 00413 00414 /* Enable SAI peripheral to generate MCLK */ 00415 __HAL_SAI_ENABLE(&haudio_out_sai); 00416 } 00417 00418 /** 00419 * @brief Updates the Audio frame slot configuration. 00420 * @param AudioFrameSlot: specifies the audio Frame slot 00421 * This parameter can be one of the following values 00422 * @arg CODEC_AUDIOFRAME_SLOT_0123 00423 * @arg CODEC_AUDIOFRAME_SLOT_02 00424 * @arg CODEC_AUDIOFRAME_SLOT_13 00425 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00426 * audio frame slot. 00427 * @retval None 00428 */ 00429 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot) 00430 { 00431 /* Disable SAI peripheral to allow access to SAI internal registers */ 00432 __HAL_SAI_DISABLE(&haudio_out_sai); 00433 00434 /* Update the SAI audio frame slot configuration */ 00435 haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot; 00436 HAL_SAI_Init(&haudio_out_sai); 00437 00438 /* Enable SAI peripheral to generate MCLK */ 00439 __HAL_SAI_ENABLE(&haudio_out_sai); 00440 } 00441 00442 /** 00443 * @brief Deinit the audio peripherals. 00444 * @retval None 00445 */ 00446 void BSP_AUDIO_OUT_DeInit(void) 00447 { 00448 SAIx_Out_DeInit(); 00449 /* DeInit the SAI MSP : this __weak function can be rewritten by the application */ 00450 BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL); 00451 } 00452 00453 /** 00454 * @brief Tx Transfer completed callbacks. 00455 * @param hsai: SAI handle 00456 * @retval None 00457 */ 00458 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) 00459 { 00460 /* Manage the remaining file size and new address offset: This function 00461 should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */ 00462 BSP_AUDIO_OUT_TransferComplete_CallBack(); 00463 } 00464 00465 /** 00466 * @brief Tx Half Transfer completed callbacks. 00467 * @param hsai: SAI handle 00468 * @retval None 00469 */ 00470 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 00471 { 00472 /* Manage the remaining file size and new address offset: This function 00473 should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */ 00474 BSP_AUDIO_OUT_HalfTransfer_CallBack(); 00475 } 00476 00477 /** 00478 * @brief SAI error callbacks. 00479 * @param hsai: SAI handle 00480 * @retval None 00481 */ 00482 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 00483 { 00484 HAL_SAI_StateTypeDef audio_out_state; 00485 HAL_SAI_StateTypeDef audio_in_state; 00486 00487 audio_out_state = HAL_SAI_GetState(&haudio_out_sai); 00488 audio_in_state = HAL_SAI_GetState(&haudio_in_sai); 00489 00490 /* Determines if it is an audio out or audio in error */ 00491 if ((audio_out_state == HAL_SAI_STATE_BUSY) || (audio_out_state == HAL_SAI_STATE_BUSY_TX) 00492 || (audio_out_state == HAL_SAI_STATE_TIMEOUT) || (audio_out_state == HAL_SAI_STATE_ERROR)) 00493 { 00494 BSP_AUDIO_OUT_Error_CallBack(); 00495 } 00496 00497 if ((audio_in_state == HAL_SAI_STATE_BUSY) || (audio_in_state == HAL_SAI_STATE_BUSY_RX) 00498 || (audio_in_state == HAL_SAI_STATE_TIMEOUT) || (audio_in_state == HAL_SAI_STATE_ERROR)) 00499 { 00500 BSP_AUDIO_IN_Error_CallBack(); 00501 } 00502 } 00503 00504 /** 00505 * @brief Manages the DMA full Transfer complete event. 00506 * @retval None 00507 */ 00508 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void) 00509 { 00510 } 00511 00512 /** 00513 * @brief Manages the DMA Half Transfer complete event. 00514 * @retval None 00515 */ 00516 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) 00517 { 00518 } 00519 00520 /** 00521 * @brief Manages the DMA FIFO error event. 00522 * @retval None 00523 */ 00524 __weak void BSP_AUDIO_OUT_Error_CallBack(void) 00525 { 00526 } 00527 00528 /** 00529 * @brief Initializes BSP_AUDIO_OUT MSP. 00530 * @param hsai: SAI handle 00531 * @param Params 00532 * @retval None 00533 */ 00534 __weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params) 00535 { 00536 static DMA_HandleTypeDef hdma_sai_tx; 00537 GPIO_InitTypeDef gpio_init_structure; 00538 00539 /* Enable SAI clock */ 00540 AUDIO_OUT_SAIx_CLK_ENABLE(); 00541 00542 /* Enable GPIO clock */ 00543 AUDIO_OUT_SAIx_MCLK_ENABLE(); 00544 AUDIO_OUT_SAIx_SCK_SD_ENABLE(); 00545 AUDIO_OUT_SAIx_FS_ENABLE(); 00546 /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/ 00547 gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN; 00548 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00549 gpio_init_structure.Pull = GPIO_NOPULL; 00550 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00551 gpio_init_structure.Alternate = AUDIO_OUT_SAIx_FS_SD_MCLK_AF; 00552 HAL_GPIO_Init(AUDIO_OUT_SAIx_FS_GPIO_PORT, &gpio_init_structure); 00553 00554 gpio_init_structure.Pin = AUDIO_OUT_SAIx_SCK_PIN; 00555 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00556 gpio_init_structure.Pull = GPIO_NOPULL; 00557 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00558 gpio_init_structure.Alternate = AUDIO_OUT_SAIx_SCK_AF; 00559 HAL_GPIO_Init(AUDIO_OUT_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure); 00560 00561 gpio_init_structure.Pin = AUDIO_OUT_SAIx_SD_PIN; 00562 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00563 gpio_init_structure.Pull = GPIO_NOPULL; 00564 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00565 gpio_init_structure.Alternate = AUDIO_OUT_SAIx_FS_SD_MCLK_AF; 00566 HAL_GPIO_Init(AUDIO_OUT_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure); 00567 00568 gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN; 00569 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00570 gpio_init_structure.Pull = GPIO_NOPULL; 00571 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00572 gpio_init_structure.Alternate = AUDIO_OUT_SAIx_FS_SD_MCLK_AF; 00573 HAL_GPIO_Init(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, &gpio_init_structure); 00574 00575 /* Enable the DMA clock */ 00576 AUDIO_OUT_SAIx_DMAx_CLK_ENABLE(); 00577 00578 if(hsai->Instance == AUDIO_OUT_SAIx) 00579 { 00580 /* Configure the hdma_saiTx handle parameters */ 00581 hdma_sai_tx.Init.Channel = AUDIO_OUT_SAIx_DMAx_CHANNEL; 00582 hdma_sai_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; 00583 hdma_sai_tx.Init.PeriphInc = DMA_PINC_DISABLE; 00584 hdma_sai_tx.Init.MemInc = DMA_MINC_ENABLE; 00585 hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_OUT_SAIx_DMAx_PERIPH_DATA_SIZE; 00586 hdma_sai_tx.Init.MemDataAlignment = AUDIO_OUT_SAIx_DMAx_MEM_DATA_SIZE; 00587 hdma_sai_tx.Init.Mode = DMA_CIRCULAR; 00588 hdma_sai_tx.Init.Priority = DMA_PRIORITY_HIGH; 00589 hdma_sai_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; 00590 hdma_sai_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 00591 hdma_sai_tx.Init.MemBurst = DMA_MBURST_SINGLE; 00592 hdma_sai_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; 00593 00594 hdma_sai_tx.Instance = AUDIO_OUT_SAIx_DMAx_STREAM; 00595 00596 /* Associate the DMA handle */ 00597 __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx); 00598 00599 /* Deinitialize the Stream for new transfer */ 00600 HAL_DMA_DeInit(&hdma_sai_tx); 00601 00602 /* Configure the DMA Stream */ 00603 HAL_DMA_Init(&hdma_sai_tx); 00604 } 00605 #if ( __MBED__ == 1) 00606 // Enable interrupt 00607 IRQn_Type irqn = (IRQn_Type)(AUDIO_OUT_SAIx_DMAx_IRQ); 00608 NVIC_ClearPendingIRQ(irqn); 00609 NVIC_DisableIRQ(irqn); 00610 NVIC_SetPriority(irqn, AUDIO_OUT_IRQ_PREPRIO); 00611 NVIC_SetVector(irqn, (uint32_t)AUDIO_OUT_SAIx_DMAx_IRQHandler); 00612 NVIC_EnableIRQ(irqn); 00613 00614 #else 00615 /* SAI DMA IRQ Channel configuration */ 00616 HAL_NVIC_SetPriority(AUDIO_OUT_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 00617 HAL_NVIC_EnableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ); 00618 #endif 00619 } 00620 00621 /** 00622 * @brief Deinitializes SAI MSP. 00623 * @param hsai: SAI handle 00624 * @param Params 00625 * @retval None 00626 */ 00627 __weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params) 00628 { 00629 GPIO_InitTypeDef gpio_init_structure; 00630 00631 /* SAI DMA IRQ Channel deactivation */ 00632 HAL_NVIC_DisableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ); 00633 00634 if(hsai->Instance == AUDIO_OUT_SAIx) 00635 { 00636 /* Deinitialize the DMA stream */ 00637 HAL_DMA_DeInit(hsai->hdmatx); 00638 } 00639 00640 /* Disable SAI peripheral */ 00641 __HAL_SAI_DISABLE(hsai); 00642 00643 /* Deactives CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */ 00644 gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN; 00645 HAL_GPIO_DeInit(AUDIO_OUT_SAIx_FS_GPIO_PORT, gpio_init_structure.Pin); 00646 00647 gpio_init_structure.Pin = AUDIO_OUT_SAIx_SCK_PIN; 00648 HAL_GPIO_DeInit(AUDIO_OUT_SAIx_SCK_SD_GPIO_PORT, gpio_init_structure.Pin); 00649 00650 gpio_init_structure.Pin = AUDIO_OUT_SAIx_SD_PIN; 00651 HAL_GPIO_DeInit(AUDIO_OUT_SAIx_SCK_SD_GPIO_PORT, gpio_init_structure.Pin); 00652 00653 gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN; 00654 HAL_GPIO_DeInit(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin); 00655 00656 /* Disable SAI clock */ 00657 AUDIO_OUT_SAIx_CLK_DISABLE(); 00658 00659 /* GPIO pins clock and DMA clock can be shut down in the application 00660 by surcharging this __weak function */ 00661 } 00662 00663 /** 00664 * @brief Clock Config. 00665 * @param hsai: might be required to set audio peripheral predivider if any. 00666 * @param AudioFreq: Audio frequency used to play the audio stream. 00667 * @param Params 00668 * @note This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency() 00669 * Being __weak it can be overwritten by the application 00670 * @retval None 00671 */ 00672 __weak void BSP_AUDIO_OUT_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params) 00673 { 00674 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 00675 00676 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 00677 00678 /* Set the PLL configuration according to the audio frequency */ 00679 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 00680 { 00681 /* Configure PLLI2S prescalers */ 00682 /* PLLI2S_VCO: VCO_429M 00683 I2S_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 429/2 = 214.5 Mhz 00684 I2S_CLK_x = I2S_CLK(first level)/PLLI2SDIVQ = 214.5/19 = 11.289 Mhz */ 00685 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 00686 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S; 00687 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429; 00688 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2; 00689 rcc_ex_clk_init_struct.PLLI2SDivQ = 19; 00690 00691 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00692 00693 } 00694 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K), AUDIO_FREQUENCY_96K */ 00695 { 00696 /* I2S clock config 00697 PLLI2S_VCO: VCO_344M 00698 I2S_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 344/7 = 49.142 Mhz 00699 I2S_CLK_x = I2S_CLK(first level)/PLLI2SDIVQ = 49.142/1 = 49.142 Mhz */ 00700 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 00701 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S; 00702 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 00703 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 00704 rcc_ex_clk_init_struct.PLLI2SDivQ = 1; 00705 00706 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00707 } 00708 } 00709 00710 /******************************************************************************* 00711 Static Functions 00712 *******************************************************************************/ 00713 00714 /** 00715 * @brief Initializes the output Audio Codec audio interface (SAI). 00716 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00717 * @note The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 00718 * and user can update this configuration using 00719 * @retval None 00720 */ 00721 static void SAIx_Out_Init(uint32_t AudioFreq) 00722 { 00723 /* Initialize the haudio_out_sai Instance parameter */ 00724 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00725 00726 /* Disable SAI peripheral to allow access to SAI internal registers */ 00727 __HAL_SAI_DISABLE(&haudio_out_sai); 00728 00729 /* Configure SAI_Block_x 00730 LSBFirst: Disabled 00731 DataSize: 16 */ 00732 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00733 haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX; 00734 haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED; 00735 haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL; 00736 haudio_out_sai.Init.DataSize = SAI_DATASIZE_16; 00737 haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 00738 haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 00739 haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS; 00740 haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLED; 00741 haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 00742 00743 /* Configure SAI_Block_x Frame 00744 Frame Length: 64 00745 Frame active Length: 32 00746 FS Definition: Start frame + Channel Side identification 00747 FS Polarity: FS active Low 00748 FS Offset: FS asserted one bit before the first bit of slot 0 */ 00749 haudio_out_sai.FrameInit.FrameLength = 64; 00750 haudio_out_sai.FrameInit.ActiveFrameLength = 32; 00751 haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 00752 haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 00753 haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 00754 00755 /* Configure SAI Block_x Slot 00756 Slot First Bit Offset: 0 00757 Slot Size : 16 00758 Slot Number: 4 00759 Slot Active: All slot actives */ 00760 haudio_out_sai.SlotInit.FirstBitOffset = 0; 00761 haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 00762 haudio_out_sai.SlotInit.SlotNumber = 4; 00763 haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123; 00764 00765 HAL_SAI_Init(&haudio_out_sai); 00766 00767 /* Enable SAI peripheral to generate MCLK */ 00768 __HAL_SAI_ENABLE(&haudio_out_sai); 00769 } 00770 00771 00772 00773 /** 00774 * @brief Deinitializes the output Audio Codec audio interface (SAI). 00775 * @retval None 00776 */ 00777 static void SAIx_Out_DeInit(void) 00778 { 00779 /* Initialize the haudio_out_sai Instance parameter */ 00780 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00781 00782 /* Disable SAI peripheral */ 00783 __HAL_SAI_DISABLE(&haudio_out_sai); 00784 00785 HAL_SAI_DeInit(&haudio_out_sai); 00786 } 00787 00788 /** 00789 * @} 00790 */ 00791 00792 /** @defgroup STM32746G_DISCOVERY_AUDIO_Out_Private_Functions STM32746G_DISCOVERY_AUDIO Out Private Functions 00793 * @{ 00794 */ 00795 00796 /** 00797 * @brief Initializes wave recording. 00798 * @param InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_2 or INPUT_DEVICE_INPUT_LINE_1 00799 * @param Volume: Initial volume level (in range 0(Mute)..80(+0dB)..100(+17.625dB)) 00800 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00801 * @retval AUDIO_OK if correct communication, else wrong communication 00802 */ 00803 uint8_t BSP_AUDIO_IN_Init(uint16_t InputDevice, uint8_t Volume, uint32_t AudioFreq) 00804 { 00805 uint8_t ret = AUDIO_ERROR; 00806 uint32_t deviceid = 0x00; 00807 uint32_t slot_active; 00808 00809 if ((InputDevice != INPUT_DEVICE_INPUT_LINE_1) && /* Only INPUT_LINE_1 and MICROPHONE_2 inputs supported */ 00810 (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2)) 00811 { 00812 ret = AUDIO_ERROR; 00813 } 00814 else 00815 { 00816 /* Disable SAI */ 00817 SAIx_In_DeInit(); 00818 00819 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */ 00820 BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */ 00821 00822 /* SAI data transfer preparation: 00823 Prepare the Media to be used for the audio transfer from SAI peripheral to memory */ 00824 haudio_in_sai.Instance = AUDIO_IN_SAIx; 00825 if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET) 00826 { 00827 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00828 BSP_AUDIO_OUT_MspInit(&haudio_in_sai, NULL); /* Initialize GPIOs for SAI2 block A Master signals */ 00829 BSP_AUDIO_IN_MspInit(&haudio_in_sai, NULL); 00830 } 00831 00832 /* Configure SAI in master RX mode : 00833 * - SAI2_block_A in master RX mode 00834 * - SAI2_block_B in slave RX mode synchronous from SAI2_block_A 00835 */ 00836 if (InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2) 00837 { 00838 slot_active = CODEC_AUDIOFRAME_SLOT_13; 00839 } 00840 else 00841 { 00842 slot_active = CODEC_AUDIOFRAME_SLOT_02; 00843 } 00844 SAIx_In_Init(SAI_MODEMASTER_RX, slot_active, AudioFreq); 00845 00846 /* wm8994 codec initialization */ 00847 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00848 00849 if((deviceid) == WM8994_ID) 00850 { 00851 /* Reset the Codec Registers */ 00852 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00853 /* Initialize the audio driver structure */ 00854 audio_drv = &wm8994_drv; 00855 ret = AUDIO_OK; 00856 } 00857 else 00858 { 00859 ret = AUDIO_ERROR; 00860 } 00861 00862 if(ret == AUDIO_OK) 00863 { 00864 /* Initialize the codec internal registers */ 00865 audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice, Volume, AudioFreq); 00866 } 00867 } 00868 return ret; 00869 } 00870 00871 /** 00872 * @brief Initializes wave recording and playback in parallel. 00873 * @param InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_2 00874 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00875 * or OUTPUT_DEVICE_BOTH. 00876 * @param Volume: Initial volume level (in range 0(Mute)..80(+0dB)..100(+17.625dB)) 00877 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00878 * @retval AUDIO_OK if correct communication, else wrong communication 00879 */ 00880 uint8_t BSP_AUDIO_IN_OUT_Init(uint16_t InputDevice, uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00881 { 00882 uint8_t ret = AUDIO_ERROR; 00883 uint32_t deviceid = 0x00; 00884 uint32_t slot_active; 00885 00886 if (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2) /* Only MICROPHONE_2 input supported */ 00887 { 00888 ret = AUDIO_ERROR; 00889 } 00890 else 00891 { 00892 /* Disable SAI */ 00893 SAIx_In_DeInit(); 00894 SAIx_Out_DeInit(); 00895 00896 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */ 00897 BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */ 00898 00899 /* SAI data transfer preparation: 00900 Prepare the Media to be used for the audio transfer from SAI peripheral to memory */ 00901 haudio_in_sai.Instance = AUDIO_IN_SAIx; 00902 if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET) 00903 { 00904 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00905 BSP_AUDIO_IN_MspInit(&haudio_in_sai, NULL); 00906 } 00907 00908 /* SAI data transfer preparation: 00909 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00910 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00911 if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET) 00912 { 00913 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00914 BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL); 00915 } 00916 00917 /* Configure SAI in master mode : 00918 * - SAI2_block_A in master TX mode 00919 * - SAI2_block_B in slave RX mode synchronous from SAI2_block_A 00920 */ 00921 if (InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2) 00922 { 00923 slot_active = CODEC_AUDIOFRAME_SLOT_13; 00924 } 00925 else 00926 { 00927 slot_active = CODEC_AUDIOFRAME_SLOT_02; 00928 } 00929 SAIx_In_Init(SAI_MODEMASTER_TX, slot_active, AudioFreq); 00930 00931 /* wm8994 codec initialization */ 00932 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00933 00934 if((deviceid) == WM8994_ID) 00935 { 00936 /* Reset the Codec Registers */ 00937 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00938 /* Initialize the audio driver structure */ 00939 audio_drv = &wm8994_drv; 00940 ret = AUDIO_OK; 00941 } 00942 else 00943 { 00944 ret = AUDIO_ERROR; 00945 } 00946 00947 if(ret == AUDIO_OK) 00948 { 00949 /* Initialize the codec internal registers */ 00950 audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice | OutputDevice, Volume, AudioFreq); 00951 } 00952 } 00953 return ret; 00954 } 00955 00956 00957 /** 00958 * @brief Starts audio recording. 00959 * @param pbuf: Main buffer pointer for the recorded data storing 00960 * @param size: size of the recorded buffer in number of elements (typically number of half-words) 00961 * Be careful that it is not the same unit than BSP_AUDIO_OUT_Play function 00962 * @retval AUDIO_OK if correct communication, else wrong communication 00963 */ 00964 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size) 00965 { 00966 uint32_t ret = AUDIO_ERROR; 00967 00968 /* Start the process receive DMA */ 00969 HAL_SAI_Receive_DMA(&haudio_in_sai, (uint8_t*)pbuf, size); 00970 00971 /* Return AUDIO_OK when all operations are correctly done */ 00972 ret = AUDIO_OK; 00973 00974 return ret; 00975 } 00976 00977 /** 00978 * @brief Stops audio recording. 00979 * @param Option: could be one of the following parameters 00980 * - CODEC_PDWN_SW: for software power off (by writing registers). 00981 * Then no need to reconfigure the Codec after power on. 00982 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00983 * Then need to reconfigure the Codec after power on. 00984 * @retval AUDIO_OK if correct communication, else wrong communication 00985 */ 00986 uint8_t BSP_AUDIO_IN_Stop(uint32_t Option) 00987 { 00988 /* Call the Media layer stop function */ 00989 HAL_SAI_DMAStop(&haudio_in_sai); 00990 00991 /* Call Audio Codec Stop function */ 00992 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 00993 { 00994 return AUDIO_ERROR; 00995 } 00996 else 00997 { 00998 if(Option == CODEC_PDWN_HW) 00999 { 01000 /* Wait at least 100us */ 01001 HAL_Delay(1); 01002 } 01003 /* Return AUDIO_OK when all operations are correctly done */ 01004 return AUDIO_OK; 01005 } 01006 } 01007 01008 /** 01009 * @brief Pauses the audio file stream. 01010 * @retval AUDIO_OK if correct communication, else wrong communication 01011 */ 01012 uint8_t BSP_AUDIO_IN_Pause(void) 01013 { 01014 /* Call the Media layer pause function */ 01015 HAL_SAI_DMAPause(&haudio_in_sai); 01016 /* Return AUDIO_OK when all operations are correctly done */ 01017 return AUDIO_OK; 01018 } 01019 01020 /** 01021 * @brief Resumes the audio file stream. 01022 * @retval AUDIO_OK if correct communication, else wrong communication 01023 */ 01024 uint8_t BSP_AUDIO_IN_Resume(void) 01025 { 01026 /* Call the Media layer pause/resume function */ 01027 HAL_SAI_DMAResume(&haudio_in_sai); 01028 /* Return AUDIO_OK when all operations are correctly done */ 01029 return AUDIO_OK; 01030 } 01031 01032 /** 01033 * @brief Controls the audio in volume level. 01034 * @param Volume: Volume level in range 0(Mute)..80(+0dB)..100(+17.625dB) 01035 * @retval AUDIO_OK if correct communication, else wrong communication 01036 */ 01037 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume) 01038 { 01039 /* Call the codec volume control function with converted volume value */ 01040 if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 01041 { 01042 return AUDIO_ERROR; 01043 } 01044 else 01045 { 01046 /* Set the Global variable AudioInVolume */ 01047 AudioInVolume = Volume; 01048 /* Return AUDIO_OK when all operations are correctly done */ 01049 return AUDIO_OK; 01050 } 01051 } 01052 01053 /** 01054 * @brief Deinit the audio IN peripherals. 01055 * @retval None 01056 */ 01057 void BSP_AUDIO_IN_DeInit(void) 01058 { 01059 SAIx_In_DeInit(); 01060 /* DeInit the SAI MSP : this __weak function can be rewritten by the application */ 01061 BSP_AUDIO_IN_MspDeInit(&haudio_in_sai, NULL); 01062 } 01063 01064 /** 01065 * @brief Rx Transfer completed callbacks. 01066 * @param hsai: SAI handle 01067 * @retval None 01068 */ 01069 void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai) 01070 { 01071 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01072 BSP_AUDIO_IN_TransferComplete_CallBack(); 01073 } 01074 01075 /** 01076 * @brief Rx Half Transfer completed callbacks. 01077 * @param hsai: SAI handle 01078 * @retval None 01079 */ 01080 void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai) 01081 { 01082 /* Manage the remaining file size and new address offset: This function 01083 should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */ 01084 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01085 } 01086 01087 /** 01088 * @brief User callback when record buffer is filled. 01089 * @retval None 01090 */ 01091 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void) 01092 { 01093 /* This function should be implemented by the user application. 01094 It is called into this driver when the current buffer is filled 01095 to prepare the next buffer pointer and its size. */ 01096 } 01097 01098 /** 01099 * @brief Manages the DMA Half Transfer complete event. 01100 * @retval None 01101 */ 01102 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 01103 { 01104 /* This function should be implemented by the user application. 01105 It is called into this driver when the current buffer is filled 01106 to prepare the next buffer pointer and its size. */ 01107 } 01108 01109 /** 01110 * @brief Audio IN Error callback function. 01111 * @retval None 01112 */ 01113 __weak void BSP_AUDIO_IN_Error_CallBack(void) 01114 { 01115 /* This function is called when an Interrupt due to transfer error on or peripheral 01116 error occurs. */ 01117 } 01118 01119 /** 01120 * @brief Initializes BSP_AUDIO_IN MSP. 01121 * @param hsai: SAI handle 01122 * @param Params 01123 * @retval None 01124 */ 01125 __weak void BSP_AUDIO_IN_MspInit(SAI_HandleTypeDef *hsai, void *Params) 01126 { 01127 static DMA_HandleTypeDef hdma_sai_rx; 01128 GPIO_InitTypeDef gpio_init_structure; 01129 01130 /* Enable SAI clock */ 01131 AUDIO_IN_SAIx_CLK_ENABLE(); 01132 01133 /* Enable SD GPIO clock */ 01134 AUDIO_IN_SAIx_SD_ENABLE(); 01135 /* CODEC_SAI pin configuration: SD pin */ 01136 gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN; 01137 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 01138 gpio_init_structure.Pull = GPIO_NOPULL; 01139 gpio_init_structure.Speed = GPIO_SPEED_FAST; 01140 gpio_init_structure.Alternate = AUDIO_IN_SAIx_SD_AF; 01141 HAL_GPIO_Init(AUDIO_IN_SAIx_SD_GPIO_PORT, &gpio_init_structure); 01142 01143 /* Enable Audio INT GPIO clock */ 01144 AUDIO_IN_INT_GPIO_ENABLE(); 01145 /* Audio INT pin configuration: input */ 01146 gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN; 01147 gpio_init_structure.Mode = GPIO_MODE_INPUT; 01148 gpio_init_structure.Pull = GPIO_NOPULL; 01149 gpio_init_structure.Speed = GPIO_SPEED_FAST; 01150 HAL_GPIO_Init(AUDIO_IN_INT_GPIO_PORT, &gpio_init_structure); 01151 01152 /* Enable the DMA clock */ 01153 AUDIO_IN_SAIx_DMAx_CLK_ENABLE(); 01154 01155 if(hsai->Instance == AUDIO_IN_SAIx) 01156 { 01157 /* Configure the hdma_sai_rx handle parameters */ 01158 hdma_sai_rx.Init.Channel = AUDIO_IN_SAIx_DMAx_CHANNEL; 01159 hdma_sai_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; 01160 hdma_sai_rx.Init.PeriphInc = DMA_PINC_DISABLE; 01161 hdma_sai_rx.Init.MemInc = DMA_MINC_ENABLE; 01162 hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAIx_DMAx_PERIPH_DATA_SIZE; 01163 hdma_sai_rx.Init.MemDataAlignment = AUDIO_IN_SAIx_DMAx_MEM_DATA_SIZE; 01164 hdma_sai_rx.Init.Mode = DMA_CIRCULAR; 01165 hdma_sai_rx.Init.Priority = DMA_PRIORITY_HIGH; 01166 hdma_sai_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 01167 hdma_sai_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 01168 hdma_sai_rx.Init.MemBurst = DMA_MBURST_SINGLE; 01169 hdma_sai_rx.Init.PeriphBurst = DMA_MBURST_SINGLE; 01170 01171 hdma_sai_rx.Instance = AUDIO_IN_SAIx_DMAx_STREAM; 01172 01173 /* Associate the DMA handle */ 01174 __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx); 01175 01176 /* Deinitialize the Stream for new transfer */ 01177 HAL_DMA_DeInit(&hdma_sai_rx); 01178 01179 /* Configure the DMA Stream */ 01180 HAL_DMA_Init(&hdma_sai_rx); 01181 } 01182 01183 /* SAI DMA IRQ Channel configuration */ 01184 #if ( __MBED__ == 1) 01185 IRQn_Type irqn = (IRQn_Type)(AUDIO_IN_SAIx_DMAx_IRQ); 01186 NVIC_ClearPendingIRQ(irqn); 01187 NVIC_DisableIRQ(irqn); 01188 NVIC_SetPriority(irqn, AUDIO_IN_IRQ_PREPRIO); 01189 NVIC_SetVector(irqn, (uint32_t)AUDIO_IN_SAIx_DMAx_IRQHandler); 01190 NVIC_EnableIRQ(irqn); 01191 #else 01192 HAL_NVIC_SetPriority(AUDIO_IN_SAIx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 01193 HAL_NVIC_EnableIRQ(AUDIO_IN_SAIx_DMAx_IRQ); 01194 #endif 01195 01196 /* Audio INT IRQ Channel configuration */ 01197 #if ( __MBED__ == 1) 01198 irqn = (IRQn_Type)(AUDIO_IN_INT_IRQ); 01199 NVIC_ClearPendingIRQ(irqn); 01200 NVIC_DisableIRQ(irqn); 01201 NVIC_SetPriority(irqn, AUDIO_IN_IRQ_PREPRIO); 01202 NVIC_SetVector(irqn, (uint32_t)AUDIO_IN_INT_IRQHandler); 01203 NVIC_EnableIRQ(irqn); 01204 #else 01205 HAL_NVIC_SetPriority(AUDIO_IN_INT_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 01206 HAL_NVIC_EnableIRQ(AUDIO_IN_INT_IRQ); 01207 #endif 01208 } 01209 01210 /** 01211 * @brief DeInitializes BSP_AUDIO_IN MSP. 01212 * @param hsai: SAI handle 01213 * @param Params 01214 * @retval None 01215 */ 01216 __weak void BSP_AUDIO_IN_MspDeInit(SAI_HandleTypeDef *hsai, void *Params) 01217 { 01218 GPIO_InitTypeDef gpio_init_structure; 01219 01220 static DMA_HandleTypeDef hdma_sai_rx; 01221 01222 /* SAI IN DMA IRQ Channel deactivation */ 01223 HAL_NVIC_DisableIRQ(AUDIO_IN_SAIx_DMAx_IRQ); 01224 01225 if(hsai->Instance == AUDIO_IN_SAIx) 01226 { 01227 /* Deinitialize the Stream for new transfer */ 01228 HAL_DMA_DeInit(&hdma_sai_rx); 01229 } 01230 01231 /* Disable SAI block */ 01232 __HAL_SAI_DISABLE(hsai); 01233 01234 /* Disable pin: SD pin */ 01235 gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN; 01236 HAL_GPIO_DeInit(AUDIO_IN_SAIx_SD_GPIO_PORT, gpio_init_structure.Pin); 01237 01238 /* Disable SAI clock */ 01239 AUDIO_IN_SAIx_CLK_DISABLE(); 01240 01241 /* GPIO pins clock and DMA clock can be shut down in the application 01242 by surcharging this __weak function */ 01243 } 01244 01245 01246 /******************************************************************************* 01247 Static Functions 01248 *******************************************************************************/ 01249 01250 /** 01251 * @brief Initializes the input Audio Codec audio interface (SAI). 01252 * @param SaiOutMode: SAI_MODEMASTER_TX (for record and playback in parallel) 01253 * or SAI_MODEMASTER_RX (for record only). 01254 * @param SlotActive: CODEC_AUDIOFRAME_SLOT_02 or CODEC_AUDIOFRAME_SLOT_13 01255 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 01256 * @retval None 01257 */ 01258 static void SAIx_In_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq) 01259 { 01260 /* Initialize SAI2 block A in MASTER RX */ 01261 /* Initialize the haudio_out_sai Instance parameter */ 01262 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 01263 01264 /* Disable SAI peripheral to allow access to SAI internal registers */ 01265 __HAL_SAI_DISABLE(&haudio_out_sai); 01266 01267 /* Configure SAI_Block_x 01268 LSBFirst: Disabled 01269 DataSize: 16 */ 01270 haudio_out_sai.Init.AudioFrequency = AudioFreq; 01271 haudio_out_sai.Init.AudioMode = SaiOutMode; 01272 haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED; 01273 haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL; 01274 haudio_out_sai.Init.DataSize = SAI_DATASIZE_16; 01275 haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 01276 haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 01277 haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS; 01278 haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLED; 01279 haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 01280 01281 /* Configure SAI_Block_x Frame 01282 Frame Length: 64 01283 Frame active Length: 32 01284 FS Definition: Start frame + Channel Side identification 01285 FS Polarity: FS active Low 01286 FS Offset: FS asserted one bit before the first bit of slot 0 */ 01287 haudio_out_sai.FrameInit.FrameLength = 64; 01288 haudio_out_sai.FrameInit.ActiveFrameLength = 32; 01289 haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 01290 haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 01291 haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 01292 01293 /* Configure SAI Block_x Slot 01294 Slot First Bit Offset: 0 01295 Slot Size : 16 01296 Slot Number: 4 01297 Slot Active: All slot actives */ 01298 haudio_out_sai.SlotInit.FirstBitOffset = 0; 01299 haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 01300 haudio_out_sai.SlotInit.SlotNumber = 4; 01301 haudio_out_sai.SlotInit.SlotActive = SlotActive; 01302 01303 HAL_SAI_Init(&haudio_out_sai); 01304 01305 /* Initialize SAI2 block B in SLAVE RX synchronous from SAI2 block A */ 01306 /* Initialize the haudio_in_sai Instance parameter */ 01307 haudio_in_sai.Instance = AUDIO_IN_SAIx; 01308 01309 /* Disable SAI peripheral to allow access to SAI internal registers */ 01310 __HAL_SAI_DISABLE(&haudio_in_sai); 01311 01312 /* Configure SAI_Block_x 01313 LSBFirst: Disabled 01314 DataSize: 16 */ 01315 haudio_in_sai.Init.AudioFrequency = AudioFreq; 01316 haudio_in_sai.Init.AudioMode = SAI_MODESLAVE_RX; 01317 haudio_in_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED; 01318 haudio_in_sai.Init.Protocol = SAI_FREE_PROTOCOL; 01319 haudio_in_sai.Init.DataSize = SAI_DATASIZE_16; 01320 haudio_in_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 01321 haudio_in_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 01322 haudio_in_sai.Init.Synchro = SAI_SYNCHRONOUS; 01323 haudio_in_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLED; 01324 haudio_in_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 01325 01326 /* Configure SAI_Block_x Frame 01327 Frame Length: 64 01328 Frame active Length: 32 01329 FS Definition: Start frame + Channel Side identification 01330 FS Polarity: FS active Low 01331 FS Offset: FS asserted one bit before the first bit of slot 0 */ 01332 haudio_in_sai.FrameInit.FrameLength = 64; 01333 haudio_in_sai.FrameInit.ActiveFrameLength = 32; 01334 haudio_in_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 01335 haudio_in_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 01336 haudio_in_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 01337 01338 /* Configure SAI Block_x Slot 01339 Slot First Bit Offset: 0 01340 Slot Size : 16 01341 Slot Number: 4 01342 Slot Active: All slot active */ 01343 haudio_in_sai.SlotInit.FirstBitOffset = 0; 01344 haudio_in_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 01345 haudio_in_sai.SlotInit.SlotNumber = 4; 01346 haudio_in_sai.SlotInit.SlotActive = SlotActive; 01347 01348 HAL_SAI_Init(&haudio_in_sai); 01349 01350 /* Enable SAI peripheral to generate MCLK */ 01351 __HAL_SAI_ENABLE(&haudio_out_sai); 01352 01353 /* Enable SAI peripheral */ 01354 __HAL_SAI_ENABLE(&haudio_in_sai); 01355 } 01356 01357 01358 01359 /** 01360 * @brief Deinitializes the output Audio Codec audio interface (SAI). 01361 * @retval None 01362 */ 01363 static void SAIx_In_DeInit(void) 01364 { 01365 /* Initialize the haudio_in_sai Instance parameter */ 01366 haudio_in_sai.Instance = AUDIO_IN_SAIx; 01367 01368 /* Disable SAI peripheral */ 01369 __HAL_SAI_DISABLE(&haudio_in_sai); 01370 01371 HAL_SAI_DeInit(&haudio_in_sai); 01372 } 01373 01374 /** 01375 * @brief This function handles External line 15_10 interrupt request. 01376 * @param None 01377 * @retval None 01378 */ 01379 static void AUDIO_IN_INT_IRQHandler(void) 01380 { 01381 /* Interrupt handler shared between SD_DETECT pin, USER_KEY button and touch screen interrupt */ 01382 if (__HAL_GPIO_EXTI_GET_IT(AUDIO_IN_INT_GPIO_PIN) != RESET) 01383 { 01384 HAL_GPIO_EXTI_IRQHandler(AUDIO_IN_INT_GPIO_PIN); /* Audio Interrupt */ 01385 } 01386 } 01387 01388 /** 01389 * @brief This function handles DMA2 Stream 7 interrupt request. 01390 * @param None 01391 * @retval None 01392 */ 01393 static void AUDIO_IN_SAIx_DMAx_IRQHandler(void) 01394 { 01395 HAL_DMA_IRQHandler(haudio_in_sai.hdmarx); 01396 } 01397 01398 /** 01399 * @brief This function handles DMA2 Stream 6 interrupt request. 01400 * @param None 01401 * @retval None 01402 */ 01403 static void AUDIO_OUT_SAIx_DMAx_IRQHandler(void) 01404 { 01405 HAL_DMA_IRQHandler(haudio_out_sai.hdmatx); 01406 } 01407 01408 /** 01409 * @} 01410 */ 01411 01412 /** 01413 * @} 01414 */ 01415 01416 /** 01417 * @} 01418 */ 01419 01420 /** 01421 * @} 01422 */ 01423 01424 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 18:43:04 by 1.7.2