No changes made
Fork of BSP_DISCO_F746NG by
Embed:
(wiki syntax)
Show/hide line numbers
stm32746g_discovery_audio.c
Go to the documentation of this file.
00001 /** 00002 ****************************************************************************** 00003 * @file stm32746g_discovery_audio.c 00004 * @author MCD Application Team 00005 * @version V2.0.0 00006 * @date 30-December-2016 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) 2016 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 void wait_ms(int ms); // MBED to replace HAL_Delay function 00099 00100 /** @addtogroup BSP 00101 * @{ 00102 */ 00103 00104 /** @addtogroup STM32746G_DISCOVERY 00105 * @{ 00106 */ 00107 00108 /** @defgroup STM32746G_DISCOVERY_AUDIO STM32746G_DISCOVERY AUDIO 00109 * @brief This file includes the low layer driver for wm8994 Audio Codec 00110 * available on STM32746G-Discovery board(MB1191). 00111 * @{ 00112 */ 00113 00114 /** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Types STM32746G_DISCOVERY AUDIO Private Types 00115 * @{ 00116 */ 00117 /** 00118 * @} 00119 */ 00120 00121 /** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Defines STM32746G_DISCOVERY AUDIO Private Defines 00122 * @{ 00123 */ 00124 /** 00125 * @} 00126 */ 00127 00128 /** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Macros STM32746G_DISCOVERY AUDIO Private Macros 00129 * @{ 00130 */ 00131 /** 00132 * @} 00133 */ 00134 00135 /** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Variables STM32746G_DISCOVERY AUDIO Private Variables 00136 * @{ 00137 */ 00138 AUDIO_DrvTypeDef *audio_drv; 00139 SAI_HandleTypeDef haudio_out_sai={0}; 00140 SAI_HandleTypeDef haudio_in_sai={0}; 00141 TIM_HandleTypeDef haudio_tim; 00142 00143 uint16_t __IO AudioInVolume = DEFAULT_AUDIO_IN_VOLUME; 00144 00145 /** 00146 * @} 00147 */ 00148 00149 /** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Function_Prototypes STM32746G_DISCOVERY AUDIO Private Function Prototypes 00150 * @{ 00151 */ 00152 static void AUDIO_IN_INT_IRQHandler(void); // MBED 00153 static void AUDIO_IN_SAIx_DMAx_IRQHandler(void); // MBED 00154 static void AUDIO_OUT_SAIx_DMAx_IRQHandler(void); // MBED 00155 static void SAIx_Out_Init(uint32_t AudioFreq); 00156 static void SAIx_Out_DeInit(void); 00157 static void SAIx_In_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq); 00158 static void SAIx_In_DeInit(void); 00159 /** 00160 * @} 00161 */ 00162 00163 /** @defgroup STM32746G_DISCOVERY_AUDIO_OUT_Exported_Functions STM32746G_DISCOVERY AUDIO Out Exported Functions 00164 * @{ 00165 */ 00166 00167 /** 00168 * @brief Configures the audio peripherals. 00169 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00170 * or OUTPUT_DEVICE_BOTH. 00171 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00172 * @param AudioFreq: Audio frequency used to play the audio stream. 00173 * @note The I2S PLL input clock must be done in the user application. 00174 * @retval AUDIO_OK if correct communication, else wrong communication 00175 */ 00176 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00177 { 00178 uint8_t ret = AUDIO_ERROR; 00179 uint32_t deviceid = 0x00; 00180 00181 /* Disable SAI */ 00182 SAIx_Out_DeInit(); 00183 00184 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */ 00185 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00186 00187 /* SAI data transfer preparation: 00188 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00189 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00190 if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET) 00191 { 00192 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00193 BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL); 00194 } 00195 SAIx_Out_Init(AudioFreq); 00196 00197 /* wm8994 codec initialization */ 00198 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00199 00200 if((deviceid) == WM8994_ID) 00201 { 00202 /* Reset the Codec Registers */ 00203 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00204 /* Initialize the audio driver structure */ 00205 audio_drv = &wm8994_drv; 00206 ret = AUDIO_OK; 00207 } 00208 else 00209 { 00210 ret = AUDIO_ERROR; 00211 } 00212 00213 if(ret == AUDIO_OK) 00214 { 00215 /* Initialize the codec internal registers */ 00216 audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq); 00217 } 00218 00219 return ret; 00220 } 00221 00222 /** 00223 * @brief Starts playing audio stream from a data buffer for a determined size. 00224 * @param pBuffer: Pointer to the buffer 00225 * @param Size: Number of audio data in BYTES unit. 00226 * In memory, first element is for left channel, second element is for right channel 00227 * @retval AUDIO_OK if correct communication, else wrong communication 00228 */ 00229 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size) 00230 { 00231 /* Call the audio Codec Play function */ 00232 if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0) 00233 { 00234 return AUDIO_ERROR; 00235 } 00236 else 00237 { 00238 /* Update the Media layer and enable it for play */ 00239 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE)); 00240 00241 return AUDIO_OK; 00242 } 00243 } 00244 00245 /** 00246 * @brief Sends n-Bytes on the SAI interface. 00247 * @param pData: pointer on data address 00248 * @param Size: number of data to be written 00249 * @retval None 00250 */ 00251 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size) 00252 { 00253 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size); 00254 } 00255 00256 /** 00257 * @brief This function Pauses the audio file stream. In case 00258 * of using DMA, the DMA Pause feature is used. 00259 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00260 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00261 * function for resume could lead to unexpected behaviour). 00262 * @retval AUDIO_OK if correct communication, else wrong communication 00263 */ 00264 uint8_t BSP_AUDIO_OUT_Pause(void) 00265 { 00266 /* Call the Audio Codec Pause/Resume function */ 00267 if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0) 00268 { 00269 return AUDIO_ERROR; 00270 } 00271 else 00272 { 00273 /* Call the Media layer pause function */ 00274 HAL_SAI_DMAPause(&haudio_out_sai); 00275 00276 /* Return AUDIO_OK when all operations are correctly done */ 00277 return AUDIO_OK; 00278 } 00279 } 00280 00281 /** 00282 * @brief This function Resumes the audio file stream. 00283 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00284 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00285 * function for resume could lead to unexpected behaviour). 00286 * @retval AUDIO_OK if correct communication, else wrong communication 00287 */ 00288 uint8_t BSP_AUDIO_OUT_Resume(void) 00289 { 00290 /* Call the Audio Codec Pause/Resume function */ 00291 if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0) 00292 { 00293 return AUDIO_ERROR; 00294 } 00295 else 00296 { 00297 /* Call the Media layer pause/resume function */ 00298 HAL_SAI_DMAResume(&haudio_out_sai); 00299 00300 /* Return AUDIO_OK when all operations are correctly done */ 00301 return AUDIO_OK; 00302 } 00303 } 00304 00305 /** 00306 * @brief Stops audio playing and Power down the Audio Codec. 00307 * @param Option: could be one of the following parameters 00308 * - CODEC_PDWN_SW: for software power off (by writing registers). 00309 * Then no need to reconfigure the Codec after power on. 00310 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00311 * Then need to reconfigure the Codec after power on. 00312 * @retval AUDIO_OK if correct communication, else wrong communication 00313 */ 00314 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option) 00315 { 00316 /* Call the Media layer stop function */ 00317 HAL_SAI_DMAStop(&haudio_out_sai); 00318 00319 /* Call Audio Codec Stop function */ 00320 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 00321 { 00322 return AUDIO_ERROR; 00323 } 00324 else 00325 { 00326 if(Option == CODEC_PDWN_HW) 00327 { 00328 /* Wait at least 100us */ 00329 wait_ms(1); 00330 } 00331 /* Return AUDIO_OK when all operations are correctly done */ 00332 return AUDIO_OK; 00333 } 00334 } 00335 00336 /** 00337 * @brief Controls the current audio volume level. 00338 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00339 * Mute and 100 for Max volume level). 00340 * @retval AUDIO_OK if correct communication, else wrong communication 00341 */ 00342 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume) 00343 { 00344 /* Call the codec volume control function with converted volume value */ 00345 if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 00346 { 00347 return AUDIO_ERROR; 00348 } 00349 else 00350 { 00351 /* Return AUDIO_OK when all operations are correctly done */ 00352 return AUDIO_OK; 00353 } 00354 } 00355 00356 /** 00357 * @brief Enables or disables the MUTE mode by software 00358 * @param Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 00359 * unmute the codec and restore previous volume level. 00360 * @retval AUDIO_OK if correct communication, else wrong communication 00361 */ 00362 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd) 00363 { 00364 /* Call the Codec Mute function */ 00365 if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0) 00366 { 00367 return AUDIO_ERROR; 00368 } 00369 else 00370 { 00371 /* Return AUDIO_OK when all operations are correctly done */ 00372 return AUDIO_OK; 00373 } 00374 } 00375 00376 /** 00377 * @brief Switch dynamically (while audio file is played) the output target 00378 * (speaker or headphone). 00379 * @param Output: The audio output target: OUTPUT_DEVICE_SPEAKER, 00380 * OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH 00381 * @retval AUDIO_OK if correct communication, else wrong communication 00382 */ 00383 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output) 00384 { 00385 /* Call the Codec output device function */ 00386 if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0) 00387 { 00388 return AUDIO_ERROR; 00389 } 00390 else 00391 { 00392 /* Return AUDIO_OK when all operations are correctly done */ 00393 return AUDIO_OK; 00394 } 00395 } 00396 00397 /** 00398 * @brief Updates the audio frequency. 00399 * @param AudioFreq: Audio frequency used to play the audio stream. 00400 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00401 * audio frequency. 00402 * @retval None 00403 */ 00404 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq) 00405 { 00406 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00407 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00408 00409 /* Disable SAI peripheral to allow access to SAI internal registers */ 00410 __HAL_SAI_DISABLE(&haudio_out_sai); 00411 00412 /* Update the SAI audio frequency configuration */ 00413 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00414 HAL_SAI_Init(&haudio_out_sai); 00415 00416 /* Enable SAI peripheral to generate MCLK */ 00417 __HAL_SAI_ENABLE(&haudio_out_sai); 00418 } 00419 00420 /** 00421 * @brief Updates the Audio frame slot configuration. 00422 * @param AudioFrameSlot: specifies the audio Frame slot 00423 * This parameter can be one of the following values 00424 * @arg CODEC_AUDIOFRAME_SLOT_0123 00425 * @arg CODEC_AUDIOFRAME_SLOT_02 00426 * @arg CODEC_AUDIOFRAME_SLOT_13 00427 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00428 * audio frame slot. 00429 * @retval None 00430 */ 00431 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot) 00432 { 00433 /* Disable SAI peripheral to allow access to SAI internal registers */ 00434 __HAL_SAI_DISABLE(&haudio_out_sai); 00435 00436 /* Update the SAI audio frame slot configuration */ 00437 haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot; 00438 HAL_SAI_Init(&haudio_out_sai); 00439 00440 /* Enable SAI peripheral to generate MCLK */ 00441 __HAL_SAI_ENABLE(&haudio_out_sai); 00442 } 00443 00444 /** 00445 * @brief Deinit the audio peripherals. 00446 * @retval None 00447 */ 00448 void BSP_AUDIO_OUT_DeInit(void) 00449 { 00450 SAIx_Out_DeInit(); 00451 /* DeInit the SAI MSP : this __weak function can be rewritten by the application */ 00452 BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL); 00453 } 00454 00455 /** 00456 * @brief Tx Transfer completed callbacks. 00457 * @param hsai: SAI handle 00458 * @retval None 00459 */ 00460 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) 00461 { 00462 /* Manage the remaining file size and new address offset: This function 00463 should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */ 00464 BSP_AUDIO_OUT_TransferComplete_CallBack(); 00465 } 00466 00467 /** 00468 * @brief Tx Half Transfer completed callbacks. 00469 * @param hsai: SAI handle 00470 * @retval None 00471 */ 00472 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 00473 { 00474 /* Manage the remaining file size and new address offset: This function 00475 should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */ 00476 BSP_AUDIO_OUT_HalfTransfer_CallBack(); 00477 } 00478 00479 /** 00480 * @brief SAI error callbacks. 00481 * @param hsai: SAI handle 00482 * @retval None 00483 */ 00484 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 00485 { 00486 HAL_SAI_StateTypeDef audio_out_state; 00487 HAL_SAI_StateTypeDef audio_in_state; 00488 00489 audio_out_state = HAL_SAI_GetState(&haudio_out_sai); 00490 audio_in_state = HAL_SAI_GetState(&haudio_in_sai); 00491 00492 /* Determines if it is an audio out or audio in error */ 00493 if ((audio_out_state == HAL_SAI_STATE_BUSY) || (audio_out_state == HAL_SAI_STATE_BUSY_TX)) 00494 { 00495 BSP_AUDIO_OUT_Error_CallBack(); 00496 } 00497 00498 if ((audio_in_state == HAL_SAI_STATE_BUSY) || (audio_in_state == HAL_SAI_STATE_BUSY_RX)) 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 AudioFreq: Audio frequency to be configured for the SAI peripheral. 00799 * @param BitRes: Audio frequency to be configured. 00800 * @param ChnlNbr: Channel number. 00801 * @retval AUDIO_OK if correct communication, else wrong communication 00802 */ 00803 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00804 { 00805 return BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MICROPHONE_2, AudioFreq, BitRes, ChnlNbr); 00806 } 00807 00808 /** 00809 * @brief Initializes wave recording. 00810 * @param InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_2 or INPUT_DEVICE_INPUT_LINE_1 00811 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00812 * @param BitRes: Audio frequency to be configured. 00813 * @param ChnlNbr: Channel number. 00814 * @retval AUDIO_OK if correct communication, else wrong communication 00815 */ 00816 uint8_t BSP_AUDIO_IN_InitEx(uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00817 { 00818 uint8_t ret = AUDIO_ERROR; 00819 uint32_t deviceid = 0x00; 00820 uint32_t slot_active; 00821 00822 if ((InputDevice != INPUT_DEVICE_INPUT_LINE_1) && /* Only INPUT_LINE_1 and MICROPHONE_2 inputs supported */ 00823 (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2)) 00824 { 00825 ret = AUDIO_ERROR; 00826 } 00827 else 00828 { 00829 /* Disable SAI */ 00830 SAIx_In_DeInit(); 00831 00832 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */ 00833 BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */ 00834 00835 /* SAI data transfer preparation: 00836 Prepare the Media to be used for the audio transfer from SAI peripheral to memory */ 00837 haudio_in_sai.Instance = AUDIO_IN_SAIx; 00838 if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET) 00839 { 00840 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00841 BSP_AUDIO_OUT_MspInit(&haudio_in_sai, NULL); /* Initialize GPIOs for SAI2 block A Master signals */ 00842 BSP_AUDIO_IN_MspInit(&haudio_in_sai, NULL); 00843 } 00844 00845 /* Configure SAI in master RX mode : 00846 * - SAI2_block_A in master RX mode 00847 * - SAI2_block_B in slave RX mode synchronous from SAI2_block_A 00848 */ 00849 if (InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2) 00850 { 00851 slot_active = CODEC_AUDIOFRAME_SLOT_13; 00852 } 00853 else 00854 { 00855 slot_active = CODEC_AUDIOFRAME_SLOT_02; 00856 } 00857 SAIx_In_Init(SAI_MODEMASTER_RX, slot_active, AudioFreq); 00858 00859 /* wm8994 codec initialization */ 00860 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00861 00862 if((deviceid) == WM8994_ID) 00863 { 00864 /* Reset the Codec Registers */ 00865 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00866 /* Initialize the audio driver structure */ 00867 audio_drv = &wm8994_drv; 00868 ret = AUDIO_OK; 00869 } 00870 else 00871 { 00872 ret = AUDIO_ERROR; 00873 } 00874 00875 if(ret == AUDIO_OK) 00876 { 00877 /* Initialize the codec internal registers */ 00878 audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice, 100, AudioFreq); 00879 } 00880 } 00881 return ret; 00882 } 00883 00884 /** 00885 * @brief Initializes wave recording and playback in parallel. 00886 * @param InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_2 00887 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00888 * or OUTPUT_DEVICE_BOTH. 00889 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00890 * @param BitRes: Audio frequency to be configured. 00891 * @param ChnlNbr: Channel number. 00892 * @retval AUDIO_OK if correct communication, else wrong communication 00893 */ 00894 uint8_t BSP_AUDIO_IN_OUT_Init(uint16_t InputDevice, uint16_t OutputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00895 { 00896 uint8_t ret = AUDIO_ERROR; 00897 uint32_t deviceid = 0x00; 00898 uint32_t slot_active; 00899 00900 if (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2) /* Only MICROPHONE_2 input supported */ 00901 { 00902 ret = AUDIO_ERROR; 00903 } 00904 else 00905 { 00906 /* Disable SAI */ 00907 SAIx_In_DeInit(); 00908 SAIx_Out_DeInit(); 00909 00910 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */ 00911 BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */ 00912 00913 /* SAI data transfer preparation: 00914 Prepare the Media to be used for the audio transfer from SAI peripheral to memory */ 00915 haudio_in_sai.Instance = AUDIO_IN_SAIx; 00916 if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET) 00917 { 00918 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00919 BSP_AUDIO_IN_MspInit(&haudio_in_sai, NULL); 00920 } 00921 00922 /* SAI data transfer preparation: 00923 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00924 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00925 if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET) 00926 { 00927 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00928 BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL); 00929 } 00930 00931 /* Configure SAI in master mode : 00932 * - SAI2_block_A in master TX mode 00933 * - SAI2_block_B in slave RX mode synchronous from SAI2_block_A 00934 */ 00935 if (InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2) 00936 { 00937 slot_active = CODEC_AUDIOFRAME_SLOT_13; 00938 } 00939 else 00940 { 00941 slot_active = CODEC_AUDIOFRAME_SLOT_02; 00942 } 00943 SAIx_In_Init(SAI_MODEMASTER_TX, slot_active, AudioFreq); 00944 00945 /* wm8994 codec initialization */ 00946 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00947 00948 if((deviceid) == WM8994_ID) 00949 { 00950 /* Reset the Codec Registers */ 00951 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00952 /* Initialize the audio driver structure */ 00953 audio_drv = &wm8994_drv; 00954 ret = AUDIO_OK; 00955 } 00956 else 00957 { 00958 ret = AUDIO_ERROR; 00959 } 00960 00961 if(ret == AUDIO_OK) 00962 { 00963 /* Initialize the codec internal registers */ 00964 audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice | OutputDevice, 100, AudioFreq); 00965 } 00966 } 00967 return ret; 00968 } 00969 00970 00971 /** 00972 * @brief Starts audio recording. 00973 * @param pbuf: Main buffer pointer for the recorded data storing 00974 * @param size: size of the recorded buffer in number of elements (typically number of half-words) 00975 * Be careful that it is not the same unit than BSP_AUDIO_OUT_Play function 00976 * @retval AUDIO_OK if correct communication, else wrong communication 00977 */ 00978 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size) 00979 { 00980 uint32_t ret = AUDIO_ERROR; 00981 00982 /* Start the process receive DMA */ 00983 HAL_SAI_Receive_DMA(&haudio_in_sai, (uint8_t*)pbuf, size); 00984 00985 /* Return AUDIO_OK when all operations are correctly done */ 00986 ret = AUDIO_OK; 00987 00988 return ret; 00989 } 00990 00991 /** 00992 * @brief Stops audio recording. 00993 * @param Option: could be one of the following parameters 00994 * - CODEC_PDWN_SW: for software power off (by writing registers). 00995 * Then no need to reconfigure the Codec after power on. 00996 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00997 * Then need to reconfigure the Codec after power on. 00998 * @retval AUDIO_OK if correct communication, else wrong communication 00999 */ 01000 uint8_t BSP_AUDIO_IN_Stop(uint32_t Option) 01001 { 01002 /* Call the Media layer stop function */ 01003 HAL_SAI_DMAStop(&haudio_in_sai); 01004 01005 /* Call Audio Codec Stop function */ 01006 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 01007 { 01008 return AUDIO_ERROR; 01009 } 01010 else 01011 { 01012 if(Option == CODEC_PDWN_HW) 01013 { 01014 /* Wait at least 100us */ 01015 wait_ms(1); 01016 } 01017 /* Return AUDIO_OK when all operations are correctly done */ 01018 return AUDIO_OK; 01019 } 01020 } 01021 01022 /** 01023 * @brief Pauses the audio file stream. 01024 * @retval AUDIO_OK if correct communication, else wrong communication 01025 */ 01026 uint8_t BSP_AUDIO_IN_Pause(void) 01027 { 01028 /* Call the Media layer pause function */ 01029 HAL_SAI_DMAPause(&haudio_in_sai); 01030 /* Return AUDIO_OK when all operations are correctly done */ 01031 return AUDIO_OK; 01032 } 01033 01034 /** 01035 * @brief Resumes the audio file stream. 01036 * @retval AUDIO_OK if correct communication, else wrong communication 01037 */ 01038 uint8_t BSP_AUDIO_IN_Resume(void) 01039 { 01040 /* Call the Media layer pause/resume function */ 01041 HAL_SAI_DMAResume(&haudio_in_sai); 01042 /* Return AUDIO_OK when all operations are correctly done */ 01043 return AUDIO_OK; 01044 } 01045 01046 /** 01047 * @brief Controls the audio in volume level. 01048 * @param Volume: Volume level in range 0(Mute)..80(+0dB)..100(+17.625dB) 01049 * @retval AUDIO_OK if correct communication, else wrong communication 01050 */ 01051 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume) 01052 { 01053 /* Call the codec volume control function with converted volume value */ 01054 if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 01055 { 01056 return AUDIO_ERROR; 01057 } 01058 else 01059 { 01060 /* Set the Global variable AudioInVolume */ 01061 AudioInVolume = Volume; 01062 /* Return AUDIO_OK when all operations are correctly done */ 01063 return AUDIO_OK; 01064 } 01065 } 01066 01067 /** 01068 * @brief Deinit the audio IN peripherals. 01069 * @retval None 01070 */ 01071 void BSP_AUDIO_IN_DeInit(void) 01072 { 01073 SAIx_In_DeInit(); 01074 /* DeInit the SAI MSP : this __weak function can be rewritten by the application */ 01075 BSP_AUDIO_IN_MspDeInit(&haudio_in_sai, NULL); 01076 } 01077 01078 /** 01079 * @brief Rx Transfer completed callbacks. 01080 * @param hsai: SAI handle 01081 * @retval None 01082 */ 01083 void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai) 01084 { 01085 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01086 BSP_AUDIO_IN_TransferComplete_CallBack(); 01087 } 01088 01089 /** 01090 * @brief Rx Half Transfer completed callbacks. 01091 * @param hsai: SAI handle 01092 * @retval None 01093 */ 01094 void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai) 01095 { 01096 /* Manage the remaining file size and new address offset: This function 01097 should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */ 01098 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01099 } 01100 01101 /** 01102 * @brief User callback when record buffer is filled. 01103 * @retval None 01104 */ 01105 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void) 01106 { 01107 /* This function should be implemented by the user application. 01108 It is called into this driver when the current buffer is filled 01109 to prepare the next buffer pointer and its size. */ 01110 } 01111 01112 /** 01113 * @brief Manages the DMA Half Transfer complete event. 01114 * @retval None 01115 */ 01116 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 01117 { 01118 /* This function should be implemented by the user application. 01119 It is called into this driver when the current buffer is filled 01120 to prepare the next buffer pointer and its size. */ 01121 } 01122 01123 /** 01124 * @brief Audio IN Error callback function. 01125 * @retval None 01126 */ 01127 __weak void BSP_AUDIO_IN_Error_CallBack(void) 01128 { 01129 /* This function is called when an Interrupt due to transfer error on or peripheral 01130 error occurs. */ 01131 } 01132 01133 /** 01134 * @brief Initializes BSP_AUDIO_IN MSP. 01135 * @param hsai: SAI handle 01136 * @param Params 01137 * @retval None 01138 */ 01139 __weak void BSP_AUDIO_IN_MspInit(SAI_HandleTypeDef *hsai, void *Params) 01140 { 01141 static DMA_HandleTypeDef hdma_sai_rx; 01142 GPIO_InitTypeDef gpio_init_structure; 01143 01144 /* Enable SAI clock */ 01145 AUDIO_IN_SAIx_CLK_ENABLE(); 01146 01147 /* Enable SD GPIO clock */ 01148 AUDIO_IN_SAIx_SD_ENABLE(); 01149 /* CODEC_SAI pin configuration: SD pin */ 01150 gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN; 01151 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 01152 gpio_init_structure.Pull = GPIO_NOPULL; 01153 gpio_init_structure.Speed = GPIO_SPEED_FAST; 01154 gpio_init_structure.Alternate = AUDIO_IN_SAIx_SD_AF; 01155 HAL_GPIO_Init(AUDIO_IN_SAIx_SD_GPIO_PORT, &gpio_init_structure); 01156 01157 /* Enable Audio INT GPIO clock */ 01158 AUDIO_IN_INT_GPIO_ENABLE(); 01159 /* Audio INT pin configuration: input */ 01160 gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN; 01161 gpio_init_structure.Mode = GPIO_MODE_INPUT; 01162 gpio_init_structure.Pull = GPIO_NOPULL; 01163 gpio_init_structure.Speed = GPIO_SPEED_FAST; 01164 HAL_GPIO_Init(AUDIO_IN_INT_GPIO_PORT, &gpio_init_structure); 01165 01166 /* Enable the DMA clock */ 01167 AUDIO_IN_SAIx_DMAx_CLK_ENABLE(); 01168 01169 if(hsai->Instance == AUDIO_IN_SAIx) 01170 { 01171 /* Configure the hdma_sai_rx handle parameters */ 01172 hdma_sai_rx.Init.Channel = AUDIO_IN_SAIx_DMAx_CHANNEL; 01173 hdma_sai_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; 01174 hdma_sai_rx.Init.PeriphInc = DMA_PINC_DISABLE; 01175 hdma_sai_rx.Init.MemInc = DMA_MINC_ENABLE; 01176 hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAIx_DMAx_PERIPH_DATA_SIZE; 01177 hdma_sai_rx.Init.MemDataAlignment = AUDIO_IN_SAIx_DMAx_MEM_DATA_SIZE; 01178 hdma_sai_rx.Init.Mode = DMA_CIRCULAR; 01179 hdma_sai_rx.Init.Priority = DMA_PRIORITY_HIGH; 01180 hdma_sai_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 01181 hdma_sai_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 01182 hdma_sai_rx.Init.MemBurst = DMA_MBURST_SINGLE; 01183 hdma_sai_rx.Init.PeriphBurst = DMA_MBURST_SINGLE; 01184 01185 hdma_sai_rx.Instance = AUDIO_IN_SAIx_DMAx_STREAM; 01186 01187 /* Associate the DMA handle */ 01188 __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx); 01189 01190 /* Deinitialize the Stream for new transfer */ 01191 HAL_DMA_DeInit(&hdma_sai_rx); 01192 01193 /* Configure the DMA Stream */ 01194 HAL_DMA_Init(&hdma_sai_rx); 01195 } 01196 01197 /* SAI DMA IRQ Channel configuration */ 01198 #if ( __MBED__ == 1) 01199 IRQn_Type irqn = (IRQn_Type)(AUDIO_IN_SAIx_DMAx_IRQ); 01200 NVIC_ClearPendingIRQ(irqn); 01201 NVIC_DisableIRQ(irqn); 01202 NVIC_SetPriority(irqn, AUDIO_IN_IRQ_PREPRIO); 01203 NVIC_SetVector(irqn, (uint32_t)AUDIO_IN_SAIx_DMAx_IRQHandler); 01204 NVIC_EnableIRQ(irqn); 01205 #else 01206 HAL_NVIC_SetPriority(AUDIO_IN_SAIx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 01207 HAL_NVIC_EnableIRQ(AUDIO_IN_SAIx_DMAx_IRQ); 01208 #endif 01209 01210 /* Audio INT IRQ Channel configuration */ 01211 #if ( __MBED__ == 1) 01212 irqn = (IRQn_Type)(AUDIO_IN_INT_IRQ); 01213 NVIC_ClearPendingIRQ(irqn); 01214 NVIC_DisableIRQ(irqn); 01215 NVIC_SetPriority(irqn, AUDIO_IN_IRQ_PREPRIO); 01216 NVIC_SetVector(irqn, (uint32_t)AUDIO_IN_INT_IRQHandler); 01217 NVIC_EnableIRQ(irqn); 01218 #else 01219 HAL_NVIC_SetPriority(AUDIO_IN_INT_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 01220 HAL_NVIC_EnableIRQ(AUDIO_IN_INT_IRQ); 01221 #endif 01222 } 01223 01224 /** 01225 * @brief DeInitializes BSP_AUDIO_IN MSP. 01226 * @param hsai: SAI handle 01227 * @param Params 01228 * @retval None 01229 */ 01230 __weak void BSP_AUDIO_IN_MspDeInit(SAI_HandleTypeDef *hsai, void *Params) 01231 { 01232 GPIO_InitTypeDef gpio_init_structure; 01233 01234 static DMA_HandleTypeDef hdma_sai_rx; 01235 01236 /* SAI IN DMA IRQ Channel deactivation */ 01237 HAL_NVIC_DisableIRQ(AUDIO_IN_SAIx_DMAx_IRQ); 01238 01239 if(hsai->Instance == AUDIO_IN_SAIx) 01240 { 01241 /* Deinitialize the Stream for new transfer */ 01242 HAL_DMA_DeInit(&hdma_sai_rx); 01243 } 01244 01245 /* Disable SAI block */ 01246 __HAL_SAI_DISABLE(hsai); 01247 01248 /* Disable pin: SD pin */ 01249 gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN; 01250 HAL_GPIO_DeInit(AUDIO_IN_SAIx_SD_GPIO_PORT, gpio_init_structure.Pin); 01251 01252 /* Disable SAI clock */ 01253 AUDIO_IN_SAIx_CLK_DISABLE(); 01254 01255 /* GPIO pins clock and DMA clock can be shut down in the application 01256 by surcharging this __weak function */ 01257 } 01258 01259 01260 /******************************************************************************* 01261 Static Functions 01262 *******************************************************************************/ 01263 01264 /** 01265 * @brief Initializes the input Audio Codec audio interface (SAI). 01266 * @param SaiOutMode: SAI_MODEMASTER_TX (for record and playback in parallel) 01267 * or SAI_MODEMASTER_RX (for record only). 01268 * @param SlotActive: CODEC_AUDIOFRAME_SLOT_02 or CODEC_AUDIOFRAME_SLOT_13 01269 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 01270 * @retval None 01271 */ 01272 static void SAIx_In_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq) 01273 { 01274 /* Initialize SAI2 block A in MASTER RX */ 01275 /* Initialize the haudio_out_sai Instance parameter */ 01276 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 01277 01278 /* Disable SAI peripheral to allow access to SAI internal registers */ 01279 __HAL_SAI_DISABLE(&haudio_out_sai); 01280 01281 /* Configure SAI_Block_x 01282 LSBFirst: Disabled 01283 DataSize: 16 */ 01284 haudio_out_sai.Init.AudioFrequency = AudioFreq; 01285 haudio_out_sai.Init.AudioMode = SaiOutMode; 01286 haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED; 01287 haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL; 01288 haudio_out_sai.Init.DataSize = SAI_DATASIZE_16; 01289 haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 01290 haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 01291 haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS; 01292 haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLED; 01293 haudio_out_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_out_sai.FrameInit.FrameLength = 64; 01302 haudio_out_sai.FrameInit.ActiveFrameLength = 32; 01303 haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 01304 haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 01305 haudio_out_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 actives */ 01312 haudio_out_sai.SlotInit.FirstBitOffset = 0; 01313 haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 01314 haudio_out_sai.SlotInit.SlotNumber = 4; 01315 haudio_out_sai.SlotInit.SlotActive = SlotActive; 01316 01317 HAL_SAI_Init(&haudio_out_sai); 01318 01319 /* Initialize SAI2 block B in SLAVE RX synchronous from SAI2 block A */ 01320 /* Initialize the haudio_in_sai Instance parameter */ 01321 haudio_in_sai.Instance = AUDIO_IN_SAIx; 01322 01323 /* Disable SAI peripheral to allow access to SAI internal registers */ 01324 __HAL_SAI_DISABLE(&haudio_in_sai); 01325 01326 /* Configure SAI_Block_x 01327 LSBFirst: Disabled 01328 DataSize: 16 */ 01329 haudio_in_sai.Init.AudioFrequency = AudioFreq; 01330 haudio_in_sai.Init.AudioMode = SAI_MODESLAVE_RX; 01331 haudio_in_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED; 01332 haudio_in_sai.Init.Protocol = SAI_FREE_PROTOCOL; 01333 haudio_in_sai.Init.DataSize = SAI_DATASIZE_16; 01334 haudio_in_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 01335 haudio_in_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 01336 haudio_in_sai.Init.Synchro = SAI_SYNCHRONOUS; 01337 haudio_in_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLED; 01338 haudio_in_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 01339 01340 /* Configure SAI_Block_x Frame 01341 Frame Length: 64 01342 Frame active Length: 32 01343 FS Definition: Start frame + Channel Side identification 01344 FS Polarity: FS active Low 01345 FS Offset: FS asserted one bit before the first bit of slot 0 */ 01346 haudio_in_sai.FrameInit.FrameLength = 64; 01347 haudio_in_sai.FrameInit.ActiveFrameLength = 32; 01348 haudio_in_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 01349 haudio_in_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 01350 haudio_in_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 01351 01352 /* Configure SAI Block_x Slot 01353 Slot First Bit Offset: 0 01354 Slot Size : 16 01355 Slot Number: 4 01356 Slot Active: All slot active */ 01357 haudio_in_sai.SlotInit.FirstBitOffset = 0; 01358 haudio_in_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 01359 haudio_in_sai.SlotInit.SlotNumber = 4; 01360 haudio_in_sai.SlotInit.SlotActive = SlotActive; 01361 01362 HAL_SAI_Init(&haudio_in_sai); 01363 01364 /* Enable SAI peripheral to generate MCLK */ 01365 __HAL_SAI_ENABLE(&haudio_out_sai); 01366 01367 /* Enable SAI peripheral */ 01368 __HAL_SAI_ENABLE(&haudio_in_sai); 01369 } 01370 01371 01372 01373 /** 01374 * @brief Deinitializes the output Audio Codec audio interface (SAI). 01375 * @retval None 01376 */ 01377 static void SAIx_In_DeInit(void) 01378 { 01379 /* Initialize the haudio_in_sai Instance parameter */ 01380 haudio_in_sai.Instance = AUDIO_IN_SAIx; 01381 01382 /* Disable SAI peripheral */ 01383 __HAL_SAI_DISABLE(&haudio_in_sai); 01384 01385 HAL_SAI_DeInit(&haudio_in_sai); 01386 } 01387 01388 #if ( __MBED__ == 1) 01389 /** 01390 * @brief This function handles External line 15_10 interrupt request. 01391 * @param None 01392 * @retval None 01393 */ 01394 static void AUDIO_IN_INT_IRQHandler(void) 01395 { 01396 /* Interrupt handler shared between SD_DETECT pin, USER_KEY button and touch screen interrupt */ 01397 if (__HAL_GPIO_EXTI_GET_IT(AUDIO_IN_INT_GPIO_PIN) != RESET) 01398 { 01399 HAL_GPIO_EXTI_IRQHandler(AUDIO_IN_INT_GPIO_PIN); /* Audio Interrupt */ 01400 } 01401 } 01402 01403 /** 01404 * @brief This function handles DMA2 Stream 7 interrupt request. 01405 * @param None 01406 * @retval None 01407 */ 01408 static void AUDIO_IN_SAIx_DMAx_IRQHandler(void) 01409 { 01410 HAL_DMA_IRQHandler(haudio_in_sai.hdmarx); 01411 } 01412 01413 /** 01414 * @brief This function handles DMA2 Stream 6 interrupt request. 01415 * @param None 01416 * @retval None 01417 */ 01418 static void AUDIO_OUT_SAIx_DMAx_IRQHandler(void) 01419 { 01420 HAL_DMA_IRQHandler(haudio_out_sai.hdmatx); 01421 } 01422 #endif 01423 01424 /** 01425 * @} 01426 */ 01427 01428 /** 01429 * @} 01430 */ 01431 01432 /** 01433 * @} 01434 */ 01435 01436 /** 01437 * @} 01438 */ 01439 01440 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 19:15:26 by 1.7.2