Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: DISCO_H747I_LCD_demo DISCO_H747I_AUDIO_demo
stm32h747i_discovery_audio.c
00001 /** 00002 ****************************************************************************** 00003 * @file stm32h747i_discovery_audio.c 00004 * @author MCD Application Team 00005 * @brief This file provides the Audio driver for the STM32H747I-DISCOVERY 00006 * board. 00007 @verbatim 00008 How To use this driver: 00009 ----------------------- 00010 + This driver supports STM32H7xx devices on STM32H747I-DISCOVERY (MB1248) Discovery boards. 00011 + Call the function BSP_AUDIO_OUT_Init( 00012 OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 00013 OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH) 00014 Volume : Initial volume to be set (0 is min (mute), 100 is max (100%) 00015 AudioFreq : Audio frequency in Hz (8000, 16000, 22500, 32000...) 00016 this parameter is relative to the audio file/stream type. 00017 ) 00018 This function configures all the hardware required for the audio application (codec, I2C, SAI, 00019 GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK. 00020 If the returned value is different from AUDIO_OK or the function is stuck then the communication with 00021 the codec has failed (try to un-plug the power or reset device in this case). 00022 - OUTPUT_DEVICE_SPEAKER : only speaker will be set as output for the audio stream. 00023 - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream. 00024 - OUTPUT_DEVICE_BOTH : both Speaker and Headphone are used as outputs for the audio stream 00025 at the same time. 00026 Note. On STM32H747I-DISCOVERY SAI_DMA is configured in CIRCULAR mode. Due to this the application 00027 does NOT need to call BSP_AUDIO_OUT_ChangeBuffer() to assure streaming. 00028 + Call the function BSP_AUDIO_OUT_Play( 00029 pBuffer: pointer to the audio data file address 00030 Size : size of the buffer to be sent in Bytes 00031 ) 00032 to start playing (for the first time) from the audio file/stream. 00033 + Call the function BSP_AUDIO_OUT_Pause() to pause playing 00034 + Call the function BSP_AUDIO_OUT_Resume() to resume playing. 00035 Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called 00036 for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case). 00037 Note. This function should be called only when the audio file is played or paused (not stopped). 00038 + For each mode, you may need to implement the relative callback functions into your code. 00039 The Callback functions are named BSP_AUDIO_OUT_XXX_CallBack() and only their prototypes are declared in 00040 the stm32h747i_discovery_audio.h file. (refer to the example for more details on the callbacks implementations) 00041 + To Stop playing, to modify the volume level, the frequency, the audio frame slot, 00042 the device output mode the mute or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(), 00043 AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetAudioFrameSlot(), BSP_AUDIO_OUT_SetOutputMode(), 00044 BSP_AUDIO_OUT_SetMute() and BSP_AUDIO_OUT_Stop(). 00045 00046 + Call the function BSP_AUDIO_IN_Init( 00047 AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000...) 00048 this parameter is relative to the audio file/stream type. 00049 BitRes: Bit resolution fixed to 16bit 00050 ChnlNbr: Number of channel to be configured for the DFSDM peripheral 00051 ) 00052 This function configures all the hardware required for the audio in application (channels, 00053 Clock source for SAI PDM periphiral, GPIOs, DMA and interrupt if needed). 00054 This function returns AUDIO_OK if configuration is OK.If the returned value is different from AUDIO_OK then 00055 the configuration should be wrong. 00056 + Call the function BSP_AUDIO_IN_AllocScratch( 00057 pScratch: pointer to scratch tables 00058 size: size of scratch buffer) 00059 This function must be called before BSP_AUDIO_IN_RECORD() to allocate buffer scratch for each DFSDM channel 00060 and its size. 00061 Note: These buffers scratch are used as intermidiate buffers to collect data within final record buffer. 00062 size is the total size of the four buffers scratch; If size is 512 then the size of each is 128. 00063 This function must be called after BSP_AUDIO_IN_Init() 00064 + Call the function BSP_AUDIO_IN_RECORD( 00065 pBuf: pointer to the recorded audio data file address 00066 Size: size of the buffer to be written in Bytes 00067 ) 00068 to start recording from microphones. 00069 00070 + Call the function BSP_AUDIO_IN_Pause() to pause recording 00071 + Call the function BSP_AUDIO_IN_Resume() to recording playing. 00072 Note. After calling BSP_AUDIO_IN_Pause() function for pause, only BSP_AUDIO_IN_Resume() should be called 00073 for resume (it is not allowed to call BSP_AUDIO_IN_RECORD() in this case). 00074 + Call the function BSP_AUDIO_IN_Stop() to stop recording 00075 + For each mode, you may need to implement the relative callback functions into your code. 00076 The Callback functions are named BSP_AUDIO_IN_XXX_CallBack() and only their prototypes are declared in 00077 the stm32h747i_discovery_audio.h file. (refer to the example for more details on the callbacks implementations) 00078 + Call the function BSP_AUDIO_IN_SelectInterface(uint32_t Interface) to select one of the two interfaces 00079 available on the STM32H747I-Discovery board: SAI or PDM. This function is to be called before BSP_AUDIO_IN_InitEx(). 00080 + Call the function BSP_AUDIO_IN_GetInterface() to get the current used interface. 00081 + Call the function BSP_AUDIO_IN_PDMToPCM_Init(uint32_t AudioFreq, uint32_t ChnlNbrIn, uint32_t ChnlNbrOut) 00082 to init PDM filters if the libPDMFilter is used for audio data filtering. 00083 + Call the function BSP_AUDIO_IN_PDMToPCM(uint16_t* PDMBuf, uint16_t* PCMBuf) to filter PDM data to PCM format 00084 if the libPDMFilter library is used for audio data filtering. 00085 00086 Driver architecture: 00087 -------------------- 00088 + This driver provides the High Audio Layer: consists of the function API exported in the stm32h747i_discovery_audio.h file 00089 (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...) 00090 + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/ 00091 providing the audio file/stream. These functions are also included as local functions into 00092 the stm32h747i_discovery_audio.c file (DFSDMx_Init(), DFSDMx_DeInit(), SAIx_Init() and SAIx_DeInit()) 00093 00094 Known Limitations: 00095 ------------------ 00096 1- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second 00097 Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams. 00098 2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 00099 File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file. 00100 3- Supports only Stereo audio streaming. 00101 4- Supports only 16-bits audio data size. 00102 @endverbatim 00103 ****************************************************************************** 00104 * @attention 00105 * 00106 * <h2><center>© Copyright (c) 2019 STMicroelectronics. 00107 * All rights reserved.</center></h2> 00108 * 00109 * This software component is licensed by ST under BSD 3-Clause license, 00110 * the "License"; You may not use this file except in compliance with the 00111 * License. You may obtain a copy of the License at: 00112 * opensource.org/licenses/BSD-3-Clause 00113 * 00114 ****************************************************************************** 00115 */ 00116 /* Includes ------------------------------------------------------------------*/ 00117 #include "stm32h747i_discovery_audio.h" 00118 00119 /** @addtogroup BSP 00120 * @{ 00121 */ 00122 00123 /** @addtogroup STM32H747I_DISCOVERY 00124 * @{ 00125 */ 00126 00127 /** @defgroup STM32H747I_DISCOVERY_AUDIO STM32H747I_DISCOVERY_AUDIO 00128 * @brief This file includes the low layer driver for wm8994 Audio Codec 00129 * available on STM32H747I-DISCOVERY discovery board(MB1248). 00130 * @{ 00131 */ 00132 00133 /** @defgroup STM32H747I_DISCOVERY_AUDIO_Private_Variables Private Variables 00134 * @{ 00135 */ 00136 /* PLAY */ 00137 AUDIO_DrvTypeDef *audio_drv; 00138 SAI_HandleTypeDef haudio_out_sai; 00139 SAI_HandleTypeDef haudio_in_sai; 00140 00141 /* RECORD */ 00142 AUDIOIN_ContextTypeDef hAudioIn; 00143 00144 00145 00146 /* Audio in Volume value */ 00147 __IO uint16_t AudioInVolume = DEFAULT_AUDIO_IN_VOLUME; 00148 00149 /* PDM filters params */ 00150 PDM_Filter_Handler_t PDM_FilterHandler[2]; 00151 PDM_Filter_Config_t PDM_FilterConfig[2]; 00152 00153 /** 00154 * @} 00155 */ 00156 00157 /** @defgroup STM32H747I_DISCOVERY_AUDIO_Private_Function_Prototypes Private FunctionPrototypes 00158 * @{ 00159 */ 00160 static void SAIx_Out_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq); 00161 static void SAIx_Out_DeInit(SAI_HandleTypeDef *hsai); 00162 static void SAIx_In_MspInit(SAI_HandleTypeDef *hsai, void *Params); 00163 static void SAIx_In_MspDeInit(SAI_HandleTypeDef *hsai, void *Params); 00164 static void SAIx_In_Init(uint32_t SaiInMode, uint32_t SlotActive, uint32_t AudioFreq); 00165 static void SAIx_In_DeInit(SAI_HandleTypeDef *hsai); 00166 00167 /** 00168 * @} 00169 */ 00170 00171 /** @defgroup STM32H747I_DISCOVERY_AUDIO_OUT_Exported_Functions OUT Exported Functions 00172 * @{ 00173 */ 00174 00175 /** 00176 * @brief Configures the audio Out peripheral. 00177 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00178 * or OUTPUT_DEVICE_BOTH. 00179 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00180 * @param AudioFreq: Audio frequency used to play the audio stream. 00181 * @retval AUDIO_OK if correct communication, else wrong communication 00182 */ 00183 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00184 { 00185 uint8_t ret = AUDIO_ERROR; 00186 uint32_t deviceid = 0x00; 00187 uint32_t slot_active; 00188 00189 /* Initialize SAI1 sub_block A as MASTER TX */ 00190 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00191 00192 /* Disable SAI */ 00193 SAIx_Out_DeInit(&haudio_out_sai); 00194 00195 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00196 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00197 00198 /* SAI data transfer preparation: 00199 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00200 00201 if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET) 00202 { 00203 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00204 BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL); 00205 } 00206 00207 /* Init SAI as master RX output */ 00208 slot_active = CODEC_AUDIOFRAME_SLOT_0123; 00209 SAIx_Out_Init(SAI_MODEMASTER_TX, slot_active, AudioFreq); 00210 00211 /* wm8994 codec initialization */ 00212 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00213 00214 if((deviceid) == WM8994_ID) 00215 { 00216 /* Reset the Codec Registers */ 00217 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00218 /* Initialize the audio driver structure */ 00219 audio_drv = &wm8994_drv; 00220 ret = AUDIO_OK; 00221 } 00222 else 00223 { 00224 ret = AUDIO_ERROR; 00225 } 00226 00227 if(ret == AUDIO_OK) 00228 { 00229 /* Initialize the codec internal registers */ 00230 audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq); 00231 } 00232 00233 return ret; 00234 } 00235 00236 /** 00237 * @brief Starts playing audio stream from a data buffer for a determined size. 00238 * @param pBuffer: Pointer to the buffer 00239 * @param Size: Number of audio data BYTES. 00240 * @retval AUDIO_OK if correct communication, else wrong communication 00241 */ 00242 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size) 00243 { 00244 /* Call the audio Codec Play function */ 00245 if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0) 00246 { 00247 return AUDIO_ERROR; 00248 } 00249 else 00250 { 00251 /* Update the Media layer and enable it for play */ 00252 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE)); 00253 00254 return AUDIO_OK; 00255 } 00256 } 00257 00258 /** 00259 * @brief Sends n-Bytes on the SAI interface. 00260 * @param pData: pointer on data address 00261 * @param Size: number of data to be written 00262 * @retval None 00263 */ 00264 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size) 00265 { 00266 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size); 00267 } 00268 00269 /** 00270 * @brief This function Pauses the audio file stream. In case 00271 * of using DMA, the DMA Pause feature is used. 00272 * @warning When calling BSP_AUDIO_OUT_Pause() function for pause, only 00273 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00274 * function for resume could lead to unexpected behaviour). 00275 * @retval AUDIO_OK if correct communication, else wrong communication 00276 */ 00277 uint8_t BSP_AUDIO_OUT_Pause(void) 00278 { 00279 /* Call the Audio Codec Pause/Resume function */ 00280 if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0) 00281 { 00282 return AUDIO_ERROR; 00283 } 00284 else 00285 { 00286 /* Call the Media layer pause function */ 00287 HAL_SAI_DMAPause(&haudio_out_sai); 00288 00289 /* Return AUDIO_OK when all operations are correctly done */ 00290 return AUDIO_OK; 00291 } 00292 } 00293 00294 /** 00295 * @brief Resumes the audio file stream. 00296 * @warning When calling BSP_AUDIO_OUT_Pause() function for pause, only 00297 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00298 * function for resume could lead to unexpected behaviour). 00299 * @retval AUDIO_OK if correct communication, else wrong communication 00300 */ 00301 uint8_t BSP_AUDIO_OUT_Resume(void) 00302 { 00303 /* Call the Audio Codec Pause/Resume function */ 00304 if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0) 00305 { 00306 return AUDIO_ERROR; 00307 } 00308 else 00309 { 00310 /* Call the Media layer pause/resume function */ 00311 HAL_SAI_DMAResume(&haudio_out_sai); 00312 00313 /* Return AUDIO_OK when all operations are correctly done */ 00314 return AUDIO_OK; 00315 } 00316 } 00317 00318 /** 00319 * @brief Stops audio playing and Power down the Audio Codec. 00320 * @param Option: could be one of the following parameters 00321 * - CODEC_PDWN_SW: for software power off (by writing registers). 00322 * Then no need to reconfigure the Codec after power on. 00323 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00324 * Then need to reconfigure the Codec after power on. 00325 * @retval AUDIO_OK if correct communication, else wrong communication 00326 */ 00327 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option) 00328 { 00329 /* Call the Media layer stop function */ 00330 HAL_SAI_DMAStop(&haudio_out_sai); 00331 00332 /* Call Audio Codec Stop function */ 00333 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 00334 { 00335 return AUDIO_ERROR; 00336 } 00337 else 00338 { 00339 if(Option == CODEC_PDWN_HW) 00340 { 00341 /* Wait at least 100us */ 00342 HAL_Delay(1); 00343 } 00344 /* Return AUDIO_OK when all operations are correctly done */ 00345 return AUDIO_OK; 00346 } 00347 } 00348 00349 /** 00350 * @brief Controls the current audio volume level. 00351 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00352 * Mute and 100 for Max volume level). 00353 * @retval AUDIO_OK if correct communication, else wrong communication 00354 */ 00355 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume) 00356 { 00357 /* Call the codec volume control function with converted volume value */ 00358 if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 00359 { 00360 return AUDIO_ERROR; 00361 } 00362 else 00363 { 00364 /* Return AUDIO_OK when all operations are correctly done */ 00365 return AUDIO_OK; 00366 } 00367 } 00368 00369 /** 00370 * @brief Enables or disables the MUTE mode by software 00371 * @param Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 00372 * unmute the codec and restore previous volume level. 00373 * @retval AUDIO_OK if correct communication, else wrong communication 00374 */ 00375 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd) 00376 { 00377 /* Call the Codec Mute function */ 00378 if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0) 00379 { 00380 return AUDIO_ERROR; 00381 } 00382 else 00383 { 00384 /* Return AUDIO_OK when all operations are correctly done */ 00385 return AUDIO_OK; 00386 } 00387 } 00388 00389 /** 00390 * @brief Switch dynamically (while audio file is played) the output target 00391 * (speaker or headphone). 00392 * @param Output: The audio output target: OUTPUT_DEVICE_SPEAKER, 00393 * OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH 00394 * @retval AUDIO_OK if correct communication, else wrong communication 00395 */ 00396 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output) 00397 { 00398 /* Call the Codec output device function */ 00399 if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0) 00400 { 00401 return AUDIO_ERROR; 00402 } 00403 else 00404 { 00405 /* Return AUDIO_OK when all operations are correctly done */ 00406 return AUDIO_OK; 00407 } 00408 } 00409 00410 /** 00411 * @brief Updates the audio frequency. 00412 * @param AudioFreq: Audio frequency used to play the audio stream. 00413 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00414 * audio frequency. 00415 * @retval None 00416 */ 00417 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq) 00418 { 00419 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00420 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00421 00422 /* Disable SAI peripheral to allow access to SAI internal registers */ 00423 __HAL_SAI_DISABLE(&haudio_out_sai); 00424 00425 /* Update the SAI audio frequency configuration */ 00426 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00427 HAL_SAI_Init(&haudio_out_sai); 00428 00429 /* Enable SAI peripheral to generate MCLK */ 00430 __HAL_SAI_ENABLE(&haudio_out_sai); 00431 } 00432 00433 /** 00434 * @brief Updates the Audio frame slot configuration. 00435 * @param AudioFrameSlot: specifies the audio Frame slot 00436 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00437 * audio frame slot. 00438 * @retval None 00439 */ 00440 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot) 00441 { 00442 /* Disable SAI peripheral to allow access to SAI internal registers */ 00443 __HAL_SAI_DISABLE(&haudio_out_sai); 00444 00445 /* Update the SAI audio frame slot configuration */ 00446 haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot; 00447 HAL_SAI_Init(&haudio_out_sai); 00448 00449 /* Enable SAI peripheral to generate MCLK */ 00450 __HAL_SAI_ENABLE(&haudio_out_sai); 00451 } 00452 00453 /** 00454 * @brief De-initializes the audio out peripheral. 00455 * @retval None 00456 */ 00457 void BSP_AUDIO_OUT_DeInit(void) 00458 { 00459 SAIx_Out_DeInit(&haudio_out_sai); 00460 /* DeInit the SAI MSP : this __weak function can be rewritten by the application */ 00461 BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL); 00462 } 00463 00464 /** 00465 * @brief Manages the DMA full Transfer complete event. 00466 * @retval None 00467 */ 00468 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void) 00469 { 00470 } 00471 00472 /** 00473 * @brief Manages the DMA Half Transfer complete event. 00474 * @retval None 00475 */ 00476 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) 00477 { 00478 } 00479 00480 /** 00481 * @brief Manages the DMA FIFO error event. 00482 * @retval None 00483 */ 00484 __weak void BSP_AUDIO_OUT_Error_CallBack(void) 00485 { 00486 } 00487 00488 /** 00489 * @brief Initializes BSP_AUDIO_OUT MSP. 00490 * @param hsai: SAI handle 00491 * @param Params: pointer on additional configuration parameters, can be NULL. 00492 * @retval None 00493 */ 00494 __weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params) 00495 { 00496 static DMA_HandleTypeDef hdma_sai_tx; 00497 GPIO_InitTypeDef gpio_init_structure; 00498 00499 /* Enable SAI clock */ 00500 AUDIO_OUT_SAIx_CLK_ENABLE(); 00501 00502 /* CODEC_SAI pins configuration: FS, SCK and SD pins */ 00503 /* Enable FS, SCK and SD clocks */ 00504 AUDIO_OUT_SAIx_SD_FS_CLK_ENABLE(); 00505 /* Enable FS, SCK and SD pins */ 00506 gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SD_PIN; 00507 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00508 gpio_init_structure.Pull = GPIO_NOPULL; 00509 gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 00510 gpio_init_structure.Alternate = AUDIO_OUT_SAIx_AF; 00511 HAL_GPIO_Init(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, &gpio_init_structure); 00512 00513 /* Enable MCLK clock */ 00514 AUDIO_OUT_SAIx_MCLK_ENABLE(); 00515 /* Enable MCLK pin */ 00516 gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN; 00517 HAL_GPIO_Init(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, &gpio_init_structure); 00518 00519 /* Enable the DMA clock */ 00520 AUDIO_OUT_SAIx_DMAx_CLK_ENABLE(); 00521 00522 if(hsai->Instance == AUDIO_OUT_SAIx) 00523 { 00524 /* Configure the hdma_saiTx handle parameters */ 00525 hdma_sai_tx.Init.Request = AUDIO_OUT_SAIx_DMAx_REQUEST; 00526 hdma_sai_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; 00527 hdma_sai_tx.Init.PeriphInc = DMA_PINC_DISABLE; 00528 hdma_sai_tx.Init.MemInc = DMA_MINC_ENABLE; 00529 hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_OUT_SAIx_DMAx_PERIPH_DATA_SIZE; 00530 hdma_sai_tx.Init.MemDataAlignment = AUDIO_OUT_SAIx_DMAx_MEM_DATA_SIZE; 00531 hdma_sai_tx.Init.Mode = DMA_CIRCULAR; 00532 hdma_sai_tx.Init.Priority = DMA_PRIORITY_HIGH; 00533 hdma_sai_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; 00534 hdma_sai_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 00535 hdma_sai_tx.Init.MemBurst = DMA_MBURST_SINGLE; 00536 hdma_sai_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; 00537 00538 hdma_sai_tx.Instance = AUDIO_OUT_SAIx_DMAx_STREAM; 00539 00540 /* Associate the DMA handle */ 00541 __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx); 00542 00543 /* Deinitialize the Stream for new transfer */ 00544 HAL_DMA_DeInit(&hdma_sai_tx); 00545 00546 /* Configure the DMA Stream */ 00547 HAL_DMA_Init(&hdma_sai_tx); 00548 } 00549 00550 /* SAI DMA IRQ Channel configuration */ 00551 HAL_NVIC_SetPriority(AUDIO_OUT_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 00552 HAL_NVIC_EnableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ); 00553 } 00554 00555 /** 00556 * @brief Deinitializes SAI MSP. 00557 * @param hsai: SAI handle 00558 * @param Params: pointer on additional configuration parameters, can be NULL. 00559 * @retval None 00560 */ 00561 __weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params) 00562 { 00563 GPIO_InitTypeDef gpio_init_structure; 00564 00565 /* SAI DMA IRQ Channel deactivation */ 00566 HAL_NVIC_DisableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ); 00567 00568 if(hsai->Instance == AUDIO_OUT_SAIx) 00569 { 00570 /* Deinitialize the DMA stream */ 00571 HAL_DMA_DeInit(hsai->hdmatx); 00572 } 00573 00574 /* Disable SAI peripheral */ 00575 __HAL_SAI_DISABLE(hsai); 00576 00577 /* Deactivates CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */ 00578 gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SD_PIN; 00579 HAL_GPIO_DeInit(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, gpio_init_structure.Pin); 00580 00581 gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN; 00582 HAL_GPIO_DeInit(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin); 00583 00584 /* Disable SAI clock */ 00585 AUDIO_OUT_SAIx_CLK_DISABLE(); 00586 00587 /* GPIO pins clock and DMA clock can be shut down in the applic 00588 by surcharging this __weak function */ 00589 } 00590 00591 /** 00592 * @brief Clock Config. 00593 * @param hsai: might be required to set audio peripheral predivider if any. 00594 * @param AudioFreq: Audio frequency used to play the audio stream. 00595 * @param Params: pointer on additional configuration parameters, can be NULL. 00596 * @note This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency() 00597 * Being __weak it can be overwritten by the application 00598 * @retval None 00599 */ 00600 __weak void BSP_AUDIO_OUT_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params) 00601 { 00602 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 00603 00604 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 00605 00606 /* Set the PLL configuration according to the audio frequency */ 00607 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 00608 { 00609 /* SAI clock config: 00610 PLL2_VCO Input = HSE_VALUE/PLL2M = 1 Mhz 00611 PLL2_VCO Output = PLL2_VCO Input * PLL2N = 429 Mhz 00612 SAI_CLK_x = PLL2_VCO Output/PLL2P = 429/38 = 11.289 Mhz */ 00613 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 00614 rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2; 00615 rcc_ex_clk_init_struct.PLL2.PLL2P = 38; 00616 rcc_ex_clk_init_struct.PLL2.PLL2Q = 1; 00617 rcc_ex_clk_init_struct.PLL2.PLL2R = 1; 00618 rcc_ex_clk_init_struct.PLL2.PLL2N = 429; 00619 rcc_ex_clk_init_struct.PLL2.PLL2M = 25; 00620 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00621 } 00622 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 00623 { 00624 /* SAI clock config: 00625 PLL2_VCO Input = HSE_VALUE/PLL2M = 1 Mhz 00626 PLL2_VCO Output = PLL2_VCO Input * PLL2N = 344 Mhz 00627 SAI_CLK_x = PLL2_VCO Output/PLL2P = 344/7 = 49.142 Mhz */ 00628 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 00629 rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2; 00630 rcc_ex_clk_init_struct.PLL2.PLL2P = 7; 00631 rcc_ex_clk_init_struct.PLL2.PLL2Q = 1; 00632 rcc_ex_clk_init_struct.PLL2.PLL2R = 1; 00633 rcc_ex_clk_init_struct.PLL2.PLL2N = 344; 00634 rcc_ex_clk_init_struct.PLL2.PLL2M = 25; 00635 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00636 } 00637 } 00638 /** 00639 * @} 00640 */ 00641 00642 /** @defgroup STM32H747I_DISCOVERY_AUDIO_OUT_Private_Functions OUT Private Functions 00643 * @{ 00644 */ 00645 00646 /******************************************************************************* 00647 HAL Callbacks 00648 *******************************************************************************/ 00649 /** 00650 * @brief Tx Transfer completed callbacks. 00651 * @param hsai: SAI handle 00652 * @retval None 00653 */ 00654 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) 00655 { 00656 /* Manage the remaining file size and new address offset: This function 00657 should be coded by user (its prototype is already declared in stm32h747i_discovery_audio.h) */ 00658 BSP_AUDIO_OUT_TransferComplete_CallBack(); 00659 } 00660 00661 /** 00662 * @brief Tx Half Transfer completed callbacks. 00663 * @param hsai: SAI handle 00664 * @retval None 00665 */ 00666 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 00667 { 00668 /* Manage the remaining file size and new address offset: This function 00669 should be coded by user (its prototype is already declared in stm32h747i_discovery_audio.h) */ 00670 BSP_AUDIO_OUT_HalfTransfer_CallBack(); 00671 } 00672 00673 /** 00674 * @brief SAI error callbacks. 00675 * @param hsai: SAI handle 00676 * @retval None 00677 */ 00678 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 00679 { 00680 if(hsai->Instance == AUDIO_OUT_SAIx) 00681 { 00682 BSP_AUDIO_OUT_Error_CallBack(); 00683 } 00684 else 00685 { 00686 BSP_AUDIO_IN_Error_CallBack(); 00687 } 00688 } 00689 00690 /******************************************************************************* 00691 Static Functions 00692 *******************************************************************************/ 00693 00694 /** 00695 * @brief Initializes the Audio Codec audio interface (SAI). 00696 * @param SaiOutMode: Audio mode to be configured for the SAI peripheral. 00697 * @param SlotActive: Audio active slot to be configured for the SAI peripheral. 00698 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00699 * @note The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 00700 * and user can update this configuration using 00701 * @retval None 00702 */ 00703 static void SAIx_Out_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq) 00704 { 00705 /* Disable SAI peripheral to allow access to SAI internal registers */ 00706 __HAL_SAI_DISABLE(&haudio_out_sai); 00707 00708 /* Configure SAI_Block_x 00709 LSBFirst: Disabled 00710 DataSize: 16 */ 00711 haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE; 00712 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00713 haudio_out_sai.Init.AudioMode = SaiOutMode; 00714 haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; 00715 haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL; 00716 haudio_out_sai.Init.DataSize = SAI_DATASIZE_16; 00717 haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 00718 haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 00719 haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS; 00720 haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE; 00721 haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 00722 haudio_out_sai.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 00723 haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING; 00724 haudio_out_sai.Init.TriState = SAI_OUTPUT_NOTRELEASED; 00725 haudio_out_sai.Init.Mckdiv = 0; 00726 haudio_out_sai.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE; 00727 haudio_out_sai.Init.PdmInit.Activation = DISABLE; 00728 haudio_out_sai.Init.PdmInit.ClockEnable = 0; 00729 haudio_out_sai.Init.PdmInit.MicPairsNbr = 0; 00730 00731 /* Configure SAI_Block_x Frame 00732 Frame Length: 64 00733 Frame active Length: 32 00734 FS Definition: Start frame + Channel Side identification 00735 FS Polarity: FS active Low 00736 FS Offset: FS asserted one bit before the first bit of slot 0 */ 00737 haudio_out_sai.FrameInit.FrameLength = 128; 00738 haudio_out_sai.FrameInit.ActiveFrameLength = 64; 00739 haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 00740 haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 00741 haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 00742 00743 /* Configure SAI Block_x Slot 00744 Slot First Bit Offset: 0 00745 Slot Size : 16 00746 Slot Number: 4 00747 Slot Active: All slot actives */ 00748 haudio_out_sai.SlotInit.FirstBitOffset = 0; 00749 haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 00750 haudio_out_sai.SlotInit.SlotNumber = 4; 00751 haudio_out_sai.SlotInit.SlotActive = SlotActive; 00752 HAL_SAI_Init(&haudio_out_sai); 00753 00754 /* Enable SAI peripheral to generate MCLK */ 00755 __HAL_SAI_ENABLE(&haudio_out_sai); 00756 } 00757 00758 /** 00759 * @brief Deinitializes the Audio Codec audio interface (SAI). 00760 * @retval None 00761 */ 00762 static void SAIx_Out_DeInit(SAI_HandleTypeDef *hsai) 00763 { 00764 /* Disable SAI peripheral */ 00765 __HAL_SAI_DISABLE(hsai); 00766 00767 HAL_SAI_DeInit(hsai); 00768 } 00769 00770 /** 00771 * @} 00772 */ 00773 00774 /** @defgroup STM32H747I_DISCOVERY_AUDIO_IN_Exported_Functions IN Exported Functions 00775 * @{ 00776 */ 00777 00778 /** 00779 * @brief Initialize wave recording. 00780 * @param AudioFreq: Audio frequency to be configured for the DFSDM peripheral. 00781 * @param BitRes: Audio frequency to be configured for the DFSDM peripheral. 00782 * @param ChnlNbr: Audio frequency to be configured for the DFSDM peripheral. 00783 * @retval AUDIO_OK if correct communication, else wrong communication 00784 */ 00785 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00786 { 00787 /* Set audio in interface to default one */ 00788 BSP_AUDIO_IN_SelectInterface(AUDIO_IN_INTERFACE_PDM); 00789 return BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC, AudioFreq, BitRes, ChnlNbr); 00790 } 00791 00792 /** 00793 * @brief Initialize wave recording. 00794 * @param InputDevice: INPUT_DEVICE_DIGITAL_MIC or INPUT_DEVICE_ANALOG_MIC. 00795 * @param AudioFreq: Audio frequency to be configured. 00796 * @param BitRes: Audio bit resolution to be configured.. 00797 * @param ChnlNbr: Number of channel to be configured. 00798 * @retval AUDIO_OK if correct communication, else wrong communication 00799 */ 00800 uint8_t BSP_AUDIO_IN_InitEx(uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00801 { 00802 uint8_t ret = AUDIO_OK; 00803 uint32_t slot_active; 00804 00805 /* Store the audio record context */ 00806 hAudioIn.Frequency = AudioFreq; 00807 hAudioIn.BitResolution = BitRes; 00808 hAudioIn.InputDevice = InputDevice; 00809 hAudioIn.ChannelNbr = ChnlNbr; 00810 00811 if(hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC) 00812 { 00813 if(hAudioIn.Interface == AUDIO_IN_INTERFACE_SAI) 00814 { 00815 /* Initialize SAI1 block B as SLAVE RX synchrounous with SAI1 block A */ 00816 haudio_in_sai.Instance = AUDIO_IN_SAIx; 00817 00818 /* Disable SAI */ 00819 SAIx_In_DeInit(&haudio_in_sai); 00820 00821 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */ 00822 BSP_AUDIO_IN_ClockConfig(AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */ 00823 00824 /* SAI data transfer preparation: 00825 Prepare the Media to be used for the audio transfer from SAI peripheral to memory */ 00826 if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET) 00827 { 00828 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00829 BSP_AUDIO_IN_MspInit(); 00830 } 00831 00832 /* Configure SAI in master mode : 00833 * - SAI1_block_B in slave RX mode synchronous from SAI1_block_A 00834 */ 00835 slot_active = CODEC_AUDIOFRAME_SLOT_13; 00836 SAIx_In_Init(SAI_MODESLAVE_RX, slot_active, AudioFreq); 00837 } 00838 else if(hAudioIn.Interface == AUDIO_IN_INTERFACE_PDM) 00839 { 00840 /* Initialize SAI1 block A as MASTER RX */ 00841 haudio_in_sai.Instance = AUDIO_IN_SAI_PDMx; 00842 00843 /* Disable SAI */ 00844 SAIx_In_DeInit(&haudio_in_sai); 00845 00846 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */ 00847 BSP_AUDIO_IN_ClockConfig(AudioFreq, NULL); 00848 00849 /* SAI data transfer preparation: 00850 Prepare the Media to be used for the audio transfer from SAI peripheral to memory */ 00851 /* Initialize the haudio_in_sai Instance parameter */ 00852 00853 if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET) 00854 { 00855 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00856 BSP_AUDIO_IN_MspInit(); 00857 } 00858 00859 /* Configure SAI in master mode : 00860 * - SAI1_block_A in master RX mode 00861 */ 00862 slot_active = CODEC_AUDIOFRAME_SLOT_0; 00863 SAIx_In_Init(SAI_MODEMASTER_RX, slot_active, AudioFreq); 00864 00865 if(BSP_AUDIO_IN_PDMToPCM_Init(AudioFreq, hAudioIn.ChannelNbr, hAudioIn.ChannelNbr) != AUDIO_OK) 00866 { 00867 ret = AUDIO_ERROR; 00868 } 00869 } 00870 else 00871 { 00872 ret = AUDIO_ERROR; 00873 } 00874 } 00875 else 00876 { 00877 /* Analog Input */ 00878 ret = AUDIO_ERROR; 00879 } 00880 00881 /* Return AUDIO_OK when all operations are correctly done */ 00882 return ret; 00883 } 00884 00885 00886 /** 00887 * @brief Initializes wave recording and playback in parallel. 00888 * @param InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_2 00889 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00890 * or OUTPUT_DEVICE_BOTH. 00891 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00892 * @param BitRes: Audio frequency to be configured. 00893 * @param ChnlNbr: Channel number. 00894 * @retval AUDIO_OK if correct communication, else wrong communication 00895 */ 00896 uint8_t BSP_AUDIO_IN_OUT_Init(uint32_t InputDevice, uint32_t OutputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00897 { 00898 uint32_t slot_active; 00899 uint32_t deviceid = 0, ret = AUDIO_OK; 00900 00901 /* Store the audio record context */ 00902 hAudioIn.Frequency = AudioFreq; 00903 hAudioIn.BitResolution = BitRes; 00904 hAudioIn.InputDevice = InputDevice; 00905 hAudioIn.ChannelNbr = ChnlNbr; 00906 00907 /* Input device is Digital MIC2 and Codec interface is SAI */ 00908 if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2) 00909 { 00910 haudio_in_sai.Instance = AUDIO_IN_SAIx; 00911 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00912 00913 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */ 00914 BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL); 00915 /* SAI data transfer preparation: 00916 Prepare the Media to be used for the audio transfer from SAI peripheral to memory */ 00917 if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET) 00918 { 00919 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00920 BSP_AUDIO_IN_MspInit(); 00921 } 00922 00923 /* SAI data transfer preparation: 00924 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 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 TX mode : 00932 * - SAI1_block_A in master TX mode 00933 * - SAI1_block_B in slave RX mode synchronous from SAI1_block_A 00934 */ 00935 slot_active = CODEC_AUDIOFRAME_SLOT_13; 00936 SAIx_In_Init(SAI_MODESLAVE_RX, slot_active, AudioFreq); 00937 00938 slot_active = CODEC_AUDIOFRAME_SLOT_02; 00939 SAIx_Out_Init(SAI_MODEMASTER_TX, slot_active, AudioFreq); 00940 00941 /* wm8994 codec initialization */ 00942 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00943 00944 if((deviceid) == WM8994_ID) 00945 { 00946 /* Reset the Codec Registers */ 00947 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00948 /* Initialize the audio driver structure */ 00949 audio_drv = &wm8994_drv; 00950 ret = AUDIO_OK; 00951 } 00952 else 00953 { 00954 ret = AUDIO_ERROR; 00955 } 00956 00957 if(ret == AUDIO_OK) 00958 { 00959 /* Initialize the codec internal registers */ 00960 audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice|OutputDevice, 90, AudioFreq); 00961 } 00962 } 00963 else 00964 { 00965 ret = AUDIO_ERROR; 00966 } 00967 00968 /* Return AUDIO_OK when all operations are correctly done */ 00969 return ret; 00970 } 00971 00972 /** 00973 * @brief Link digital mic to specified source 00974 * @param Interface : Audio In interface for Digital mic. It can be: 00975 * AUDIO_IN_INTERFACE_SAI 00976 * AUDIO_IN_INTERFACE_PDM 00977 * @retval None 00978 */ 00979 void BSP_AUDIO_IN_SelectInterface(uint32_t Interface) 00980 { 00981 hAudioIn.Interface = Interface; 00982 } 00983 00984 /** 00985 * @brief Get digital mic interface 00986 * @retval Digital mic interface. 00987 */ 00988 uint32_t BSP_AUDIO_IN_GetInterface(void) 00989 { 00990 return (hAudioIn.Interface); 00991 } 00992 00993 /** 00994 * @brief Return audio in channel number 00995 * @retval Number of channel 00996 */ 00997 uint8_t BSP_AUDIO_IN_GetChannelNumber(void) 00998 { 00999 return hAudioIn.ChannelNbr; 01000 } 01001 01002 /** 01003 * @brief Start audio recording. 01004 * @param pBuf: Main buffer pointer for the recorded data storing 01005 * @param size: Current size of the recorded buffer 01006 * @retval AUDIO_OK if correct communication, else wrong communication 01007 */ 01008 uint8_t BSP_AUDIO_IN_Record(uint16_t *pBuf, uint32_t size) 01009 { 01010 /* Start the process receive DMA */ 01011 if(HAL_OK != HAL_SAI_Receive_DMA(&haudio_in_sai, (uint8_t*)pBuf, size)) 01012 { 01013 return AUDIO_ERROR; 01014 } 01015 01016 /* Return AUDIO_OK when all operations are correctly done */ 01017 return AUDIO_OK; 01018 } 01019 01020 /** 01021 * @brief Stop audio recording. 01022 * @retval AUDIO_OK if correct communication, else wrong communication 01023 */ 01024 uint8_t BSP_AUDIO_IN_Stop(void) 01025 { 01026 /* Call the Media layer stop function */ 01027 HAL_SAI_DMAStop(&haudio_in_sai); 01028 01029 /* Return AUDIO_OK when all operations are correctly done */ 01030 return AUDIO_OK; 01031 } 01032 01033 /** 01034 * @brief Pause the audio file stream. 01035 * @retval AUDIO_OK if correct communication, else wrong communication 01036 */ 01037 uint8_t BSP_AUDIO_IN_Pause(void) 01038 { 01039 if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 01040 { 01041 return AUDIO_ERROR; 01042 } 01043 else 01044 { 01045 /* Call the Media layer pause function */ 01046 HAL_SAI_DMAPause(&haudio_in_sai); 01047 } 01048 01049 /* Return AUDIO_OK when all operations are correctly done */ 01050 return AUDIO_OK; 01051 } 01052 01053 /** 01054 * @brief Resume the audio file stream. 01055 * @retval AUDIO_OK if correct communication, else wrong communication 01056 */ 01057 uint8_t BSP_AUDIO_IN_Resume(void) 01058 { 01059 if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 01060 { 01061 return AUDIO_ERROR; 01062 } 01063 else 01064 { 01065 /* Call the Media layer resume function */ 01066 HAL_SAI_DMAResume(&haudio_in_sai); 01067 } 01068 01069 /* Return AUDIO_OK when all operations are correctly done */ 01070 return AUDIO_OK; 01071 } 01072 01073 /** 01074 * @brief Controls the audio in volume level. 01075 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 01076 * Mute and 100 for Max volume level). 01077 * @retval AUDIO_OK if correct communication, else wrong communication 01078 */ 01079 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume) 01080 { 01081 /* Set the Global variable AudioInVolume */ 01082 AudioInVolume = Volume; 01083 01084 /* Return AUDIO_OK when all operations are correctly done */ 01085 return AUDIO_OK; 01086 } 01087 01088 /** 01089 * @brief Deinit the audio IN peripherals. 01090 * @retval None 01091 */ 01092 void BSP_AUDIO_IN_DeInit(void) 01093 { 01094 SAIx_In_DeInit(&haudio_in_sai); 01095 01096 BSP_AUDIO_IN_MspDeInit(); 01097 } 01098 01099 /** 01100 * @brief Initialize the PDM library. 01101 * @param AudioFreq: Audio sampling frequency 01102 * @param ChnlNbrIn: Number of input audio channels in the PDM buffer 01103 * @param ChnlNbrOut: Number of desired output audio channels in the resulting PCM buffer 01104 * @retval None 01105 */ 01106 uint8_t BSP_AUDIO_IN_PDMToPCM_Init(uint32_t AudioFreq, uint32_t ChnlNbrIn, uint32_t ChnlNbrOut) 01107 { 01108 uint32_t index = 0; 01109 01110 /* Enable CRC peripheral to unlock the PDM library */ 01111 __HAL_RCC_CRC_CLK_ENABLE(); 01112 01113 for(index = 0; index < ChnlNbrIn; index++) 01114 { 01115 /* Init PDM filters */ 01116 PDM_FilterHandler[index].bit_order = PDM_FILTER_BIT_ORDER_MSB; 01117 PDM_FilterHandler[index].endianness = PDM_FILTER_ENDIANNESS_LE; 01118 PDM_FilterHandler[index].high_pass_tap = 2122358088; 01119 PDM_FilterHandler[index].out_ptr_channels = ChnlNbrOut; 01120 PDM_FilterHandler[index].in_ptr_channels = ChnlNbrIn; 01121 PDM_Filter_Init((PDM_Filter_Handler_t *)(&PDM_FilterHandler[index])); 01122 01123 /* PDM lib config phase */ 01124 PDM_FilterConfig[index].output_samples_number = AudioFreq/1000; 01125 PDM_FilterConfig[index].mic_gain = 24; 01126 PDM_FilterConfig[index].decimation_factor = PDM_FILTER_DEC_FACTOR_64; 01127 PDM_Filter_setConfig((PDM_Filter_Handler_t *)&PDM_FilterHandler[index], &PDM_FilterConfig[index]); 01128 } 01129 01130 return AUDIO_OK; 01131 } 01132 01133 01134 /** 01135 * @brief Converts audio format from PDM to PCM. 01136 01137 * @param PDMBuf: Pointer to PDM buffer data 01138 * @param PCMBuf: Pointer to PCM buffer data 01139 * @retval AUDIO_OK in case of success, AUDIO_ERROR otherwise 01140 */ 01141 uint8_t BSP_AUDIO_IN_PDMToPCM(uint16_t *PDMBuf, uint16_t *PCMBuf) 01142 { 01143 uint32_t index = 0; 01144 01145 for(index = 0; index < hAudioIn.ChannelNbr; index++) 01146 { 01147 PDM_Filter(&((uint8_t*)(PDMBuf))[index], (uint16_t*)&(PCMBuf[index]), &PDM_FilterHandler[index]); 01148 } 01149 01150 return AUDIO_OK; 01151 } 01152 01153 /** 01154 * @brief User callback when record buffer is filled. 01155 * @retval None 01156 */ 01157 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void) 01158 { 01159 /* This function should be implemented by the user application. 01160 It is called into this driver when the current buffer is filled 01161 to prepare the next buffer pointer and its size. */ 01162 } 01163 01164 /** 01165 * @brief Manages the DMA Half Transfer complete event. 01166 * @retval None 01167 */ 01168 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 01169 { 01170 /* This function should be implemented by the user application. 01171 It is called into this driver when the current buffer is filled 01172 to prepare the next buffer pointer and its size. */ 01173 } 01174 01175 /** 01176 * @brief User callback when record buffer is filled. 01177 * @param InputDevice: INPUT_DEVICE_DIGITAL_MIC1 or INPUT_DEVICE_DIGITAL_MIC2 01178 */ 01179 __weak void BSP_AUDIO_IN_TransferComplete_CallBackEx(uint32_t InputDevice) 01180 { 01181 /* This function should be implemented by the user application. 01182 It is called into this driver when the current buffer is filled 01183 to prepare the next buffer pointer and its size. */ 01184 } 01185 01186 /** 01187 * @brief User callback when record buffer is filled. 01188 * @param InputDevice: INPUT_DEVICE_DIGITAL_MIC1 or INPUT_DEVICE_DIGITAL_MIC2 01189 */ 01190 __weak void BSP_AUDIO_IN_HalfTransfer_CallBackEx(uint32_t InputDevice) 01191 { 01192 /* This function should be implemented by the user application. 01193 It is called into this driver when the current buffer is filled 01194 to prepare the next buffer pointer and its size. */ 01195 } 01196 01197 /** 01198 * @brief Audio IN Error callback function. 01199 * @retval None 01200 */ 01201 __weak void BSP_AUDIO_IN_Error_CallBack(void) 01202 { 01203 /* This function is called when an Interrupt due to transfer error on or peripheral 01204 error occurs. */ 01205 } 01206 01207 /** 01208 * @brief Initialize BSP_AUDIO_IN MSP. 01209 * @retval None 01210 */ 01211 __weak void BSP_AUDIO_IN_MspInit(void) 01212 { 01213 SAIx_In_MspInit(&haudio_in_sai, NULL); 01214 } 01215 01216 /** 01217 * @brief DeInitialize BSP_AUDIO_IN MSP. 01218 * @retval None 01219 */ 01220 __weak void BSP_AUDIO_IN_MspDeInit(void) 01221 { 01222 SAIx_In_MspDeInit(&haudio_in_sai, NULL); 01223 } 01224 01225 /** 01226 * @brief Clock Config. 01227 * @param AudioFreq: Audio frequency used to play the audio stream. 01228 * @param Params: pointer on additional configuration parameters, can be NULL. 01229 * @note This API is called by BSP_AUDIO_IN_Init() 01230 * Being __weak it can be overwritten by the application 01231 * @retval None 01232 */ 01233 __weak void BSP_AUDIO_IN_ClockConfig(uint32_t AudioFreq, void *Params) 01234 { 01235 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 01236 01237 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 01238 01239 /* Set the PLL configuration according to the audio frequency */ 01240 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 01241 { 01242 /* SAI clock config: 01243 PLL2_VCO Input = HSE_VALUE/PLL2M = 1 Mhz 01244 PLL2_VCO Output = PLL2_VCO Input * PLL2N = 429 Mhz 01245 SAI_CLK_x = PLL2_VCO Output/PLL2P = 429/38 = 11.289 Mhz */ 01246 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 01247 rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2; 01248 rcc_ex_clk_init_struct.PLL2.PLL2P = 38; 01249 rcc_ex_clk_init_struct.PLL2.PLL2Q = 1; 01250 rcc_ex_clk_init_struct.PLL2.PLL2R = 1; 01251 rcc_ex_clk_init_struct.PLL2.PLL2N = 429; 01252 rcc_ex_clk_init_struct.PLL2.PLL2M = 25; 01253 if (hAudioIn.Interface == AUDIO_IN_INTERFACE_PDM) 01254 { 01255 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI4A; 01256 rcc_ex_clk_init_struct.Sai4AClockSelection = RCC_SAI4ACLKSOURCE_PLL2; 01257 } 01258 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01259 01260 } 01261 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_32K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 01262 { 01263 /* SAI clock config: 01264 PLL2_VCO Input = HSE_VALUE/PLL2M = 1 Mhz 01265 PLL2_VCO Output = PLL2_VCO Input * PLL2N = 344 Mhz 01266 SAI_CLK_x = PLL2_VCO Output/PLL2P = 344/7 = 49.142 Mhz */ 01267 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 01268 rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2; 01269 rcc_ex_clk_init_struct.PLL2.PLL2P = 7; 01270 rcc_ex_clk_init_struct.PLL2.PLL2Q = 1; 01271 rcc_ex_clk_init_struct.PLL2.PLL2R = 1; 01272 rcc_ex_clk_init_struct.PLL2.PLL2N = 344; 01273 rcc_ex_clk_init_struct.PLL2.PLL2M = 25; 01274 if (hAudioIn.Interface == AUDIO_IN_INTERFACE_PDM) 01275 { 01276 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI4A; 01277 rcc_ex_clk_init_struct.Sai4AClockSelection = RCC_SAI4ACLKSOURCE_PLL2; 01278 } 01279 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01280 } 01281 } 01282 /** 01283 * @} 01284 */ 01285 01286 01287 /** @defgroup STM32H747I_DISCOVERY_AUDIO_IN_Private_Functions IN Private Functions 01288 * @{ 01289 */ 01290 01291 /******************************************************************************* 01292 HAL Callbacks 01293 *******************************************************************************/ 01294 01295 /** 01296 * @brief Half reception complete callback. 01297 * @param hsai: SAI handle. 01298 * @retval None 01299 */ 01300 void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai) 01301 { 01302 /* Manage the remaining file size and new address offset: This function should be coded by user */ 01303 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01304 } 01305 01306 /** 01307 * @brief Reception complete callback. 01308 * @param hsai: SAI handle. 01309 * @retval None 01310 */ 01311 void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai) 01312 { 01313 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01314 BSP_AUDIO_IN_TransferComplete_CallBack(); 01315 } 01316 01317 /******************************************************************************* 01318 Static Functions 01319 *******************************************************************************/ 01320 /** 01321 * @brief Initializes SAI Audio IN MSP. 01322 * @param hsai: SAI handle 01323 * @param Params: pointer on additional configuration parameters, can be NULL. 01324 * @retval None 01325 */ 01326 static void SAIx_In_MspInit(SAI_HandleTypeDef *hsai, void *Params) 01327 { 01328 static DMA_HandleTypeDef hdma_sai_rx; 01329 GPIO_InitTypeDef gpio_init_structure; 01330 01331 if(hsai->Instance == AUDIO_IN_SAI_PDMx) 01332 { 01333 /* Enable SAI clock */ 01334 AUDIO_IN_SAI_PDMx_CLK_ENABLE(); 01335 01336 AUDIO_IN_SAI_PDMx_CLK_IN_ENABLE(); 01337 AUDIO_IN_SAI_PDMx_DATA_IN_ENABLE(); 01338 01339 gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_CLK_IN_PIN; 01340 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 01341 gpio_init_structure.Pull = GPIO_NOPULL; 01342 gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH; 01343 gpio_init_structure.Alternate = AUDIO_IN_SAI_PDMx_DATA_CLK_AF; 01344 HAL_GPIO_Init(AUDIO_IN_SAI_PDMx_CLK_IN_PORT, &gpio_init_structure); 01345 01346 gpio_init_structure.Pull = GPIO_PULLUP; 01347 gpio_init_structure.Speed = GPIO_SPEED_FREQ_MEDIUM; 01348 gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_DATA_IN_PIN; 01349 HAL_GPIO_Init(AUDIO_IN_SAI_PDMx_DATA_IN_PORT, &gpio_init_structure); 01350 01351 AUDIO_IN_SAI_PDMx_FS_SCK_ENABLE(); 01352 01353 /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/ 01354 gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_FS_PIN | AUDIO_IN_SAI_PDMx_SCK_PIN; 01355 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 01356 gpio_init_structure.Pull = GPIO_NOPULL; 01357 gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH; 01358 gpio_init_structure.Alternate = AUDIO_IN_SAI_PDMx_FS_SCK_AF; 01359 HAL_GPIO_Init(AUDIO_IN_SAI_PDMx_FS_SCK_GPIO_PORT, &gpio_init_structure); 01360 01361 /* Enable the DMA clock */ 01362 AUDIO_IN_SAI_PDMx_DMAx_CLK_ENABLE(); 01363 01364 /* Configure the hdma_sai_rx handle parameters */ 01365 hdma_sai_rx.Init.Request = AUDIO_IN_SAI_PDMx_DMAx_REQUEST; 01366 hdma_sai_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; 01367 hdma_sai_rx.Init.PeriphInc = DMA_PINC_DISABLE; 01368 hdma_sai_rx.Init.MemInc = DMA_MINC_ENABLE; 01369 hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAI_PDMx_DMAx_PERIPH_DATA_SIZE; 01370 hdma_sai_rx.Init.MemDataAlignment = AUDIO_IN_SAI_PDMx_DMAx_MEM_DATA_SIZE; 01371 hdma_sai_rx.Init.Mode = DMA_CIRCULAR; 01372 hdma_sai_rx.Init.Priority = DMA_PRIORITY_HIGH; 01373 hdma_sai_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 01374 hdma_sai_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 01375 hdma_sai_rx.Init.MemBurst = DMA_MBURST_SINGLE; 01376 hdma_sai_rx.Init.PeriphBurst = DMA_MBURST_SINGLE; 01377 01378 hdma_sai_rx.Instance = AUDIO_IN_SAI_PDMx_DMAx_STREAM; 01379 01380 /* Associate the DMA handle */ 01381 __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx); 01382 01383 /* Deinitialize the Stream for new transfer */ 01384 HAL_DMA_DeInit(&hdma_sai_rx); 01385 01386 /* Configure the DMA Stream */ 01387 HAL_DMA_Init(&hdma_sai_rx); 01388 01389 /* SAI DMA IRQ Channel configuration */ 01390 HAL_NVIC_SetPriority(AUDIO_IN_SAI_PDMx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 01391 HAL_NVIC_EnableIRQ(AUDIO_IN_SAI_PDMx_DMAx_IRQ); 01392 } 01393 else 01394 { 01395 /* Enable SAI clock */ 01396 AUDIO_IN_SAIx_CLK_ENABLE(); 01397 01398 /* Enable SD GPIO clock */ 01399 AUDIO_IN_SAIx_SD_ENABLE(); 01400 /* CODEC_SAI pin configuration: SD pin */ 01401 gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN; 01402 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 01403 gpio_init_structure.Pull = GPIO_NOPULL; 01404 gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH; 01405 gpio_init_structure.Alternate = AUDIO_IN_SAIx_AF; 01406 HAL_GPIO_Init(AUDIO_IN_SAIx_SD_GPIO_PORT, &gpio_init_structure); 01407 01408 /* Enable Audio INT GPIO clock */ 01409 AUDIO_IN_INT_GPIO_ENABLE(); 01410 /* Audio INT pin configuration: input */ 01411 gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN; 01412 gpio_init_structure.Mode = GPIO_MODE_INPUT; 01413 gpio_init_structure.Pull = GPIO_NOPULL; 01414 gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH; 01415 HAL_GPIO_Init(AUDIO_IN_INT_GPIO_PORT, &gpio_init_structure); 01416 01417 /* Enable the DMA clock */ 01418 AUDIO_IN_SAIx_DMAx_CLK_ENABLE(); 01419 01420 /* Configure the hdma_sai_rx handle parameters */ 01421 hdma_sai_rx.Init.Request = AUDIO_IN_SAIx_DMAx_REQUEST; 01422 hdma_sai_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; 01423 hdma_sai_rx.Init.PeriphInc = DMA_PINC_DISABLE; 01424 hdma_sai_rx.Init.MemInc = DMA_MINC_ENABLE; 01425 hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAIx_DMAx_PERIPH_DATA_SIZE; 01426 hdma_sai_rx.Init.MemDataAlignment = AUDIO_IN_SAIx_DMAx_MEM_DATA_SIZE; 01427 hdma_sai_rx.Init.Mode = DMA_CIRCULAR; 01428 hdma_sai_rx.Init.Priority = DMA_PRIORITY_HIGH; 01429 hdma_sai_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 01430 hdma_sai_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 01431 hdma_sai_rx.Init.MemBurst = DMA_MBURST_SINGLE; 01432 hdma_sai_rx.Init.PeriphBurst = DMA_MBURST_SINGLE; 01433 01434 hdma_sai_rx.Instance = AUDIO_IN_SAIx_DMAx_STREAM; 01435 01436 /* Associate the DMA handle */ 01437 __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx); 01438 01439 /* Deinitialize the Stream for new transfer */ 01440 HAL_DMA_DeInit(&hdma_sai_rx); 01441 01442 /* Configure the DMA Stream */ 01443 HAL_DMA_Init(&hdma_sai_rx); 01444 01445 /* SAI DMA IRQ Channel configuration */ 01446 HAL_NVIC_SetPriority(AUDIO_IN_SAIx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 01447 HAL_NVIC_EnableIRQ(AUDIO_IN_SAIx_DMAx_IRQ); 01448 01449 /* Audio INT IRQ Channel configuration */ 01450 HAL_NVIC_SetPriority(AUDIO_IN_INT_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 01451 HAL_NVIC_EnableIRQ(AUDIO_IN_INT_IRQ); 01452 } 01453 } 01454 01455 /** 01456 * @brief De-Initializes SAI Audio IN MSP. 01457 * @param hsai: SAI handle 01458 * @param Params: pointer on additional configuration parameters, can be NULL. 01459 * @retval None 01460 */ 01461 static void SAIx_In_MspDeInit(SAI_HandleTypeDef *hsai, void *Params) 01462 { 01463 GPIO_InitTypeDef gpio_init_structure; 01464 01465 if(hsai->Instance == AUDIO_IN_SAI_PDMx) 01466 { 01467 /* Deinitialize the DMA stream */ 01468 HAL_DMA_Abort(hsai->hdmarx); 01469 01470 HAL_SAI_DeInit(hsai); 01471 /* Disable SAI peripheral */ 01472 __HAL_SAI_DISABLE(hsai); 01473 01474 /* Deinitialize the DMA stream */ 01475 HAL_DMA_DeInit(hsai->hdmarx); 01476 01477 gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_CLK_IN_PIN; 01478 HAL_GPIO_DeInit(AUDIO_IN_SAI_PDMx_CLK_IN_PORT, gpio_init_structure.Pin); 01479 01480 gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_DATA_IN_PIN; 01481 HAL_GPIO_DeInit(AUDIO_IN_SAI_PDMx_DATA_IN_PORT, gpio_init_structure.Pin); 01482 01483 /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/ 01484 gpio_init_structure.Pin = AUDIO_IN_SAI_PDMx_FS_PIN | AUDIO_IN_SAI_PDMx_SCK_PIN; 01485 HAL_GPIO_DeInit(AUDIO_IN_SAI_PDMx_FS_SCK_GPIO_PORT, gpio_init_structure.Pin); 01486 01487 /* Disable SAI clock */ 01488 AUDIO_IN_SAI_PDMx_CLK_DISABLE(); 01489 } 01490 else 01491 { 01492 /* SAI DMA IRQ Channel deactivation */ 01493 HAL_NVIC_DisableIRQ(AUDIO_IN_SAIx_DMAx_IRQ); 01494 01495 if(hsai->Instance == AUDIO_IN_SAIx) 01496 { 01497 /* Deinitialize the DMA stream */ 01498 HAL_DMA_DeInit(hsai->hdmatx); 01499 } 01500 01501 /* Disable SAI peripheral */ 01502 __HAL_SAI_DISABLE(hsai); 01503 01504 /* Deactivates CODEC_SAI pin SD by putting them in input mode */ 01505 gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN; 01506 HAL_GPIO_DeInit(AUDIO_IN_SAIx_SD_GPIO_PORT, gpio_init_structure.Pin); 01507 01508 gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN; 01509 HAL_GPIO_DeInit(AUDIO_IN_INT_GPIO_PORT, gpio_init_structure.Pin); 01510 01511 /* Disable SAI clock */ 01512 AUDIO_IN_SAIx_CLK_DISABLE(); 01513 } 01514 } 01515 01516 /** 01517 * @brief Initializes the Audio Codec audio interface (SAI). 01518 * @param SaiInMode: Audio mode to be configured for the SAI peripheral. 01519 * @param SlotActive: Audio active slot to be configured for the SAI peripheral. 01520 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 01521 * @retval None 01522 */ 01523 static void SAIx_In_Init(uint32_t SaiInMode, uint32_t SlotActive, uint32_t AudioFreq) 01524 { 01525 /* Disable SAI peripheral to allow access to SAI internal registers */ 01526 __HAL_SAI_DISABLE(&haudio_in_sai); 01527 01528 /* Configure SAI_Block_x 01529 LSBFirst: Disabled 01530 DataSize: 16 */ 01531 haudio_in_sai.Init.MonoStereoMode = SAI_STEREOMODE; 01532 haudio_in_sai.Init.AudioFrequency = AudioFreq; 01533 haudio_in_sai.Init.AudioMode = SaiInMode; 01534 haudio_in_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; 01535 haudio_in_sai.Init.Protocol = SAI_FREE_PROTOCOL; 01536 haudio_in_sai.Init.DataSize = SAI_DATASIZE_16; 01537 haudio_in_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 01538 haudio_in_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 01539 haudio_in_sai.Init.Synchro = SAI_SYNCHRONOUS; 01540 haudio_in_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE; 01541 haudio_in_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 01542 haudio_in_sai.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 01543 haudio_in_sai.Init.CompandingMode = SAI_NOCOMPANDING; 01544 haudio_in_sai.Init.TriState = SAI_OUTPUT_RELEASED; 01545 haudio_in_sai.Init.Mckdiv = 0; 01546 haudio_in_sai.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE; 01547 haudio_in_sai.Init.PdmInit.Activation = DISABLE; 01548 01549 /* Configure SAI_Block_x Frame 01550 Frame Length: 64 01551 Frame active Length: 32 01552 FS Definition: Start frame + Channel Side identification 01553 FS Polarity: FS active Low 01554 FS Offset: FS asserted one bit before the first bit of slot 0 */ 01555 haudio_in_sai.FrameInit.FrameLength = 128; 01556 haudio_in_sai.FrameInit.ActiveFrameLength = 64; 01557 haudio_in_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 01558 haudio_in_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 01559 haudio_in_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 01560 01561 /* Configure SAI Block_x Slot 01562 Slot First Bit Offset: 0 01563 Slot Size : 16 01564 Slot Number: 4 01565 Slot Active: All slot active */ 01566 haudio_in_sai.SlotInit.FirstBitOffset = 0; 01567 haudio_in_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 01568 haudio_in_sai.SlotInit.SlotNumber = 4; 01569 haudio_in_sai.SlotInit.SlotActive = SlotActive; 01570 01571 if(hAudioIn.Interface == AUDIO_IN_INTERFACE_PDM) 01572 { 01573 haudio_in_sai.Init.AudioFrequency = AudioFreq * 8; 01574 haudio_in_sai.Init.Synchro = SAI_ASYNCHRONOUS; 01575 haudio_in_sai.Init.NoDivider = SAI_MASTERDIVIDER_DISABLE; 01576 01577 haudio_in_sai.Init.PdmInit.Activation = ENABLE; 01578 haudio_in_sai.Init.PdmInit.MicPairsNbr = 1; 01579 haudio_in_sai.Init.PdmInit.ClockEnable = SAI_PDM_CLOCK1_ENABLE; 01580 haudio_in_sai.Init.FirstBit = SAI_FIRSTBIT_LSB; 01581 haudio_in_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; 01582 01583 haudio_in_sai.FrameInit.FrameLength = 16; 01584 haudio_in_sai.FrameInit.ActiveFrameLength = 1; 01585 haudio_in_sai.FrameInit.FSDefinition = SAI_FS_STARTFRAME; 01586 haudio_in_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH; 01587 haudio_in_sai.FrameInit.FSOffset = SAI_FS_FIRSTBIT; 01588 01589 haudio_in_sai.SlotInit.SlotNumber = 1; 01590 haudio_in_sai.SlotInit.SlotActive = SlotActive; 01591 } 01592 01593 HAL_SAI_Init(&haudio_in_sai); 01594 01595 /* Enable SAI peripheral */ 01596 __HAL_SAI_ENABLE(&haudio_in_sai); 01597 } 01598 01599 /** 01600 * @brief De-initializes the output Audio Codec audio interface (SAI). 01601 * @retval None 01602 */ 01603 static void SAIx_In_DeInit(SAI_HandleTypeDef *hsai) 01604 { 01605 /* Disable SAI peripheral */ 01606 __HAL_SAI_DISABLE(hsai); 01607 01608 HAL_SAI_DeInit(hsai); 01609 } 01610 01611 /** 01612 * @} 01613 */ 01614 01615 /** 01616 * @} 01617 */ 01618 01619 /** 01620 * @} 01621 */ 01622 01623 /** 01624 * @} 01625 */ 01626 01627 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 18:45:41 by
