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