STM32769I_EVAL BSP User Manual
|
stm32f769i_eval_audio.c
Go to the documentation of this file.
00001 /** 00002 ****************************************************************************** 00003 * @file stm32f769i_eval_audio.c 00004 * @author MCD Application Team 00005 * @version V2.0.1 00006 * @date 06-April-2017 00007 * @brief This file provides the Audio driver for the STM32F769I-EVAL 00008 * evaluation board. 00009 @verbatim 00010 How To use this driver: 00011 ----------------------- 00012 + This driver supports STM32F7xx devices on STM32F769I-EVAL (MB1219) Evaluation boards. 00013 + Call the function BSP_AUDIO_OUT_Init( 00014 OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 00015 OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH) 00016 Volume : Initial volume to be set (0 is min (mute), 100 is max (100%) 00017 AudioFreq : Audio frequency in Hz (8000, 16000, 22500, 32000...) 00018 this parameter is relative to the audio file/stream type. 00019 ) 00020 This function configures all the hardware required for the audio application (codec, I2C, SAI, 00021 GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK. 00022 If the returned value is different from AUDIO_OK or the function is stuck then the communication with 00023 the codec or the MFX has failed (try to un-plug the power or reset device in this case). 00024 - OUTPUT_DEVICE_SPEAKER : only speaker will be set as output for the audio stream. 00025 - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream. 00026 - OUTPUT_DEVICE_BOTH : both Speaker and Headphone are used as outputs for the audio stream 00027 at the same time. 00028 Note. On STM32F769I-EVAL SAI_DMA is configured in CIRCULAR mode. Due to this the application 00029 does NOT need to call BSP_AUDIO_OUT_ChangeBuffer() to assure streaming. 00030 + Call the function BSP_EVAL_AUDIO_OUT_Play( 00031 pBuffer: pointer to the audio data file address 00032 Size : size of the buffer to be sent in Bytes 00033 ) 00034 to start playing (for the first time) from the audio file/stream. 00035 + Call the function BSP_AUDIO_OUT_Pause() to pause playing 00036 + Call the function BSP_AUDIO_OUT_Resume() to resume playing. 00037 Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called 00038 for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case). 00039 Note. This function should be called only when the audio file is played or paused (not stopped). 00040 + For each mode, you may need to implement the relative callback functions into your code. 00041 The Callback functions are named AUDIO_OUT_XXX_CallBack() and only their prototypes are declared in 00042 the stm32f769i_eval_audio.h file. (refer to the example for more details on the callbacks implementations) 00043 + To Stop playing, to modify the volume level, the frequency, the audio frame slot, 00044 the device output mode the mute or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(), 00045 AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetAudioFrameSlot(), BSP_AUDIO_OUT_SetOutputMode(), 00046 BSP_AUDIO_OUT_SetMute() and BSP_AUDIO_OUT_Stop(). 00047 + The driver API and the callback functions are at the end of the stm32f769i_eval_audio.h file. 00048 00049 Driver architecture: 00050 -------------------- 00051 + This driver provides the High Audio Layer: consists of the function API exported in the stm32f769i_eval_audio.h file 00052 (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...) 00053 + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/ 00054 providing the audio file/stream. These functions are also included as local functions into 00055 the stm32f769i_eval_audio_codec.c file (DFSDMx_Init(), DFSDMx_DeInit(), SAIx_Init() and SAIx_DeInit()) 00056 00057 Known Limitations: 00058 ------------------ 00059 1- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second 00060 Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams. 00061 2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 00062 File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file. 00063 3- Supports only Stereo audio streaming. 00064 4- Supports only 16-bits audio data size. 00065 @endverbatim 00066 ****************************************************************************** 00067 * @attention 00068 * 00069 * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2> 00070 * 00071 * Redistribution and use in source and binary forms, with or without modification, 00072 * are permitted provided that the following conditions are met: 00073 * 1. Redistributions of source code must retain the above copyright notice, 00074 * this list of conditions and the following disclaimer. 00075 * 2. Redistributions in binary form must reproduce the above copyright notice, 00076 * this list of conditions and the following disclaimer in the documentation 00077 * and/or other materials provided with the distribution. 00078 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00079 * may be used to endorse or promote products derived from this software 00080 * without specific prior written permission. 00081 * 00082 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00083 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00084 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00085 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00086 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00087 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00088 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00089 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00090 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00091 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00092 * 00093 ****************************************************************************** 00094 */ 00095 00096 /* Dependencies 00097 - stm32f769i_eval.c 00098 - stm32f7xx_hal_sai.c 00099 - stm32f7xx_hal_dfsdm.c 00100 - stm32f7xx_hal_dma.c 00101 - stm32f7xx_hal_gpio.c 00102 - stm32f7xx_hal_cortex.c 00103 - stm32f7xx_hal_rcc_ex.h 00104 - wm8994.c 00105 - adv7533.c 00106 EndDependencies */ 00107 00108 /* Includes ------------------------------------------------------------------*/ 00109 #include "stm32f769i_eval_audio.h" 00110 00111 /** @addtogroup BSP 00112 * @{ 00113 */ 00114 00115 /** @addtogroup STM32F769I_EVAL 00116 * @{ 00117 */ 00118 00119 /** @defgroup STM32F769I_EVAL_AUDIO STM32F769I_EVAL AUDIO 00120 * @brief This file includes the low layer driver for wm8994 Audio Codec 00121 * available on STM32F769I-EVAL evaluation board(MB1219). 00122 * @{ 00123 */ 00124 00125 /** @defgroup STM32F769I_EVAL_AUDIO_Private_Types STM32F769I_EVAL_AUDIO Private Types 00126 * @{ 00127 */ 00128 typedef struct 00129 { 00130 uint16_t *pRecBuf; /* Pointer to record user buffer */ 00131 uint32_t RecSize; /* Size to record in mono, double size to record in stereo */ 00132 }AUDIOIN_TypeDef; 00133 00134 /** 00135 * @} 00136 */ 00137 00138 /** @defgroup STM32F769I_EVAL_AUDIO_Private_Defines STM32F769I_EVAL_AUDIO Private Defines 00139 * @{ 00140 */ 00141 /** 00142 * @} 00143 */ 00144 00145 /** @defgroup STM32F769I_EVAL_AUDIO_Private_Macros STM32F769I_EVAL_AUDIO Private Macros 00146 * @{ 00147 */ 00148 /*### RECORD ###*/ 00149 #define DFSDM_OVER_SAMPLING(__FREQUENCY__) \ 00150 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 256 \ 00151 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \ 00152 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \ 00153 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \ 00154 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \ 00155 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64 \ 00156 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 40 : 20 \ 00157 00158 #define DFSDM_CLOCK_DIVIDER(__FREQUENCY__) \ 00159 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 24 \ 00160 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \ 00161 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \ 00162 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \ 00163 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \ 00164 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4 \ 00165 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 25 : 25 \ 00166 00167 #define DFSDM_FILTER_ORDER(__FREQUENCY__) \ 00168 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? DFSDM_FILTER_SINC3_ORDER \ 00169 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \ 00170 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \ 00171 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \ 00172 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \ 00173 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC3_ORDER \ 00174 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC3_ORDER : DFSDM_FILTER_SINC5_ORDER \ 00175 00176 #define DFSDM_RIGHT_BIT_SHIFT(__FREQUENCY__) \ 00177 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 8 \ 00178 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 8 \ 00179 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 3 \ 00180 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \ 00181 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 7 \ 00182 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 0 \ 00183 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 0 : 4 \ 00184 00185 /* Saturate the record PCM sample */ 00186 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N))) 00187 /** 00188 * @} 00189 */ 00190 00191 /** @defgroup STM32F769I_EVAL_AUDIO_Private_Variables STM32F769I_EVAL_AUDIO Private Variables 00192 * @{ 00193 */ 00194 /*### PLAY ###*/ 00195 AUDIO_DrvTypeDef *audio_drv; 00196 SAI_HandleTypeDef haudio_out_sai; 00197 00198 /*### RECORD ###*/ 00199 AUDIOIN_TypeDef hAudioIn; 00200 00201 DFSDM_Channel_HandleTypeDef haudio_in_dfsdm_leftchannel; 00202 DFSDM_Channel_HandleTypeDef haudio_in_dfsdm_rightchannel; 00203 DFSDM_Filter_HandleTypeDef haudio_in_dfsdm_leftfilter; 00204 DFSDM_Filter_HandleTypeDef haudio_in_dfsdm_rightfilter; 00205 DMA_HandleTypeDef hdma_dfsdm_left; 00206 DMA_HandleTypeDef hdma_dfsdm_right; 00207 00208 /* Buffers for right and left samples */ 00209 int32_t *pScratchBuff[DEFAULT_AUDIO_IN_CHANNEL_NBR]; 00210 int32_t ScratchSize; 00211 00212 /* Output device to be used: headphone by default */ 00213 static uint16_t AudioOut_Device = OUTPUT_DEVICE_HEADPHONE1; 00214 00215 /* Buffers status flags */ 00216 uint32_t DmaLeftRecHalfBuffCplt = 0; 00217 uint32_t DmaLeftRecBuffCplt = 0; 00218 uint32_t DmaRightRecHalfBuffCplt = 0; 00219 uint32_t DmaRightRecBuffCplt = 0; 00220 00221 /* Application Buffer Trigger */ 00222 __IO uint32_t AppBuffTrigger = 0; 00223 __IO uint32_t AppBuffHalf = 0; 00224 00225 #if defined(USE_LCD_HDMI) 00226 AUDIO_DrvTypeDef *hdmi_drv; 00227 /* Audio device ID */ 00228 static uint32_t DeviceId = 0x00; 00229 #endif /* USE_LCD_HDMI */ 00230 00231 /** 00232 * @} 00233 */ 00234 00235 /** @defgroup STM32F769I_EVAL_AUDIO_Private_Function_Prototypes STM32F769I_EVAL_AUDIO Private Function Prototypes 00236 * @{ 00237 */ 00238 static void SAIx_Init(uint32_t AudioFreq); 00239 static void SAIx_DeInit(void); 00240 static void DFSDMx_ChannelMspInit(void); 00241 static void DFSDMx_FilterMspInit(void); 00242 static void DFSDMx_ChannelMspDeInit(void); 00243 static void DFSDMx_FilterMspDeInit(void); 00244 static uint8_t DFSDMx_Init(uint32_t AudioFreq); 00245 static uint8_t DFSDMx_DeInit(void); 00246 /** 00247 * @} 00248 */ 00249 00250 /** @defgroup STM32F769I_EVAL_AUDIO_OUT_Private_Functions STM32F769I_EVAL_AUDIO_OUT Private Functions 00251 * @{ 00252 */ 00253 00254 /** 00255 * @brief Configure the audio peripherals. 00256 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00257 * or OUTPUT_DEVICE_BOTH. 00258 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00259 * @param AudioFreq: Audio frequency used to play the audio stream. 00260 * @retval AUDIO_OK if correct communication, else wrong communication 00261 */ 00262 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00263 { 00264 uint8_t ret = AUDIO_ERROR; 00265 AudioOut_Device = OutputDevice; 00266 00267 /* Disable SAI */ 00268 SAIx_DeInit(); 00269 00270 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00271 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00272 00273 /* SAI data transfer preparation: 00274 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00275 haudio_out_sai.Instance = AUDIO_SAIx; 00276 if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET) 00277 { 00278 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00279 BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL); 00280 } 00281 SAIx_Init(AudioFreq); 00282 00283 #if defined(USE_LCD_HDMI) 00284 if((OutputDevice & OUTPUT_DEVICE_HDMI) == OUTPUT_DEVICE_HDMI) 00285 { 00286 /* adv7533 audio driver initialization */ 00287 DeviceId = adv7533_drv.ReadID(ADV7533_CEC_DSI_I2C_ADDR); 00288 00289 if(DeviceId == ADV7533_ID) 00290 { 00291 /* Initialize the audio driver structure */ 00292 hdmi_drv = &adv7533_drv; 00293 ret = AUDIO_OK; 00294 } 00295 else 00296 { 00297 ret = AUDIO_ERROR; 00298 } 00299 00300 if(ret == AUDIO_OK) 00301 { 00302 /* Initialize the codec internal registers */ 00303 hdmi_drv->Init(ADV7533_MAIN_I2C_ADDR, OutputDevice, Volume, AudioFreq); 00304 } 00305 } 00306 #endif /* USE_LCD_HDMI */ 00307 00308 if((((OutputDevice & OUTPUT_DEVICE_BOTH) > 0) && 00309 ((OutputDevice & OUTPUT_DEVICE_BOTH) <= OUTPUT_DEVICE_BOTH)) || 00310 ((OutputDevice & OUTPUT_DEVICE_AUTO) == OUTPUT_DEVICE_AUTO)) 00311 { 00312 /* wm8994 codec initialization */ 00313 if((wm8994_drv.ReadID(AUDIO_I2C_ADDRESS)) == WM8994_ID) 00314 { 00315 /* Reset the Codec Registers */ 00316 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00317 /* Initialize the audio driver structure */ 00318 audio_drv = &wm8994_drv; 00319 ret = AUDIO_OK; 00320 } 00321 else 00322 { 00323 ret = AUDIO_ERROR; 00324 } 00325 00326 if(ret == AUDIO_OK) 00327 { 00328 /* Initialize the codec internal registers */ 00329 audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq); 00330 } 00331 } 00332 00333 return ret; 00334 } 00335 00336 /** 00337 * @brief Start playing audio stream from a data buffer for a determined size. 00338 * @param pBuffer: Pointer to the buffer 00339 * @param Size: Number of audio data BYTES. 00340 * @retval AUDIO_OK if correct communication, else wrong communication 00341 */ 00342 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size) 00343 { 00344 uint8_t ret = 0; 00345 #if defined(USE_LCD_HDMI) 00346 /* ADV7533 used */ 00347 if((AudioOut_Device & OUTPUT_DEVICE_HDMI) == OUTPUT_DEVICE_HDMI) 00348 { 00349 if(DeviceId == ADV7533_ID) 00350 { 00351 /* Call the audio Codec Play function */ 00352 if(hdmi_drv->Play(ADV7533_MAIN_I2C_ADDR, (uint16_t *)pBuffer, Size) != 0) 00353 { 00354 ret = AUDIO_ERROR; 00355 } 00356 } 00357 } 00358 #endif /* USE_LCD_HDMI */ 00359 00360 /* WM8994 used */ 00361 if((((AudioOut_Device & OUTPUT_DEVICE_BOTH) > 0) && 00362 ((AudioOut_Device & OUTPUT_DEVICE_BOTH) <= OUTPUT_DEVICE_BOTH)) || 00363 ((AudioOut_Device & OUTPUT_DEVICE_AUTO) == OUTPUT_DEVICE_AUTO)) 00364 { 00365 /* Call the audio Codec Play function */ 00366 if(audio_drv->Play(AUDIO_I2C_ADDRESS, (uint16_t *)pBuffer, Size) != 0) 00367 { 00368 ret = AUDIO_ERROR; 00369 } 00370 } 00371 00372 if(ret == AUDIO_ERROR) 00373 { 00374 return AUDIO_ERROR; 00375 } 00376 else 00377 { 00378 /* Update the Media layer and enable it for play */ 00379 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE)); 00380 00381 return AUDIO_OK; 00382 } 00383 } 00384 00385 /** 00386 * @brief Send n-Bytes on the SAI interface. 00387 * @param pData: pointer on data address 00388 * @param Size: number of data to be written 00389 * @retval None 00390 */ 00391 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size) 00392 { 00393 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size); 00394 } 00395 00396 /** 00397 * @brief Pause the audio file stream. In case 00398 * of using DMA, the DMA Pause feature is used. 00399 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00400 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00401 * function for resume could lead to unexpected behaviour). 00402 * @retval AUDIO_OK if correct communication, else wrong communication 00403 */ 00404 uint8_t BSP_AUDIO_OUT_Pause(void) 00405 { 00406 uint8_t ret = 0; 00407 #if defined(USE_LCD_HDMI) 00408 /* ADV7533 used */ 00409 if((AudioOut_Device & OUTPUT_DEVICE_HDMI) == OUTPUT_DEVICE_HDMI) 00410 { 00411 if(DeviceId == ADV7533_ID) 00412 { 00413 /* Call the audio Codec Pause function */ 00414 if(hdmi_drv->Pause(ADV7533_MAIN_I2C_ADDR) != 0) 00415 { 00416 ret = AUDIO_ERROR; 00417 } 00418 } 00419 } 00420 #endif /* USE_LCD_HDMI */ 00421 00422 /* WM8994 used */ 00423 if((((AudioOut_Device & OUTPUT_DEVICE_BOTH) > 0) && 00424 ((AudioOut_Device & OUTPUT_DEVICE_BOTH) <= OUTPUT_DEVICE_BOTH)) || 00425 ((AudioOut_Device & OUTPUT_DEVICE_AUTO) == OUTPUT_DEVICE_AUTO)) 00426 { 00427 /* Call the audio Codec Pause function */ 00428 if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0) 00429 { 00430 ret = AUDIO_ERROR; 00431 } 00432 } 00433 00434 if(ret == AUDIO_ERROR) 00435 { 00436 return AUDIO_ERROR; 00437 } 00438 else 00439 { 00440 /* Call the Media layer pause function */ 00441 HAL_SAI_DMAPause(&haudio_out_sai); 00442 00443 /* Return AUDIO_OK when all operations are correctly done */ 00444 return AUDIO_OK; 00445 } 00446 } 00447 00448 /** 00449 * @brief Resume the audio file stream. 00450 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00451 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00452 * function for resume could lead to unexpected behaviour). 00453 * @retval AUDIO_OK if correct communication, else wrong communication 00454 */ 00455 uint8_t BSP_AUDIO_OUT_Resume(void) 00456 { 00457 uint8_t ret = 0; 00458 #if defined(USE_LCD_HDMI) 00459 /* ADV7533 used */ 00460 if((AudioOut_Device & OUTPUT_DEVICE_HDMI) == OUTPUT_DEVICE_HDMI) 00461 { 00462 if(DeviceId == ADV7533_ID) 00463 { 00464 /* Call the audio Codec Resume function */ 00465 if(hdmi_drv->Resume(ADV7533_MAIN_I2C_ADDR) != 0) 00466 { 00467 ret = AUDIO_ERROR; 00468 } 00469 } 00470 } 00471 #endif /* USE_LCD_HDMI */ 00472 00473 /* WM8994 used */ 00474 if((((AudioOut_Device & OUTPUT_DEVICE_BOTH) > 0) && 00475 ((AudioOut_Device & OUTPUT_DEVICE_BOTH) <= OUTPUT_DEVICE_BOTH)) || 00476 ((AudioOut_Device & OUTPUT_DEVICE_AUTO) == OUTPUT_DEVICE_AUTO)) 00477 { 00478 /* Call the audio Codec Resume function */ 00479 if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0) 00480 { 00481 ret = AUDIO_ERROR; 00482 } 00483 } 00484 00485 if(ret == AUDIO_ERROR) 00486 { 00487 return AUDIO_ERROR; 00488 } 00489 else 00490 { 00491 /* Call the Media layer pause/resume function */ 00492 HAL_SAI_DMAResume(&haudio_out_sai); 00493 00494 /* Return AUDIO_OK when all operations are correctly done */ 00495 return AUDIO_OK; 00496 } 00497 } 00498 00499 /** 00500 * @brief Stop audio playing and Power down the Audio Codec. 00501 * @param Option: could be one of the following parameters 00502 * - CODEC_PDWN_SW: for software power off (by writing registers). 00503 * Then no need to reconfigure the Codec after power on. 00504 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00505 * Then need to reconfigure the Codec after power on. 00506 * @retval AUDIO_OK if correct communication, else wrong communication 00507 */ 00508 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option) 00509 { 00510 uint8_t ret = 0; 00511 00512 /* Call the Media layer stop function */ 00513 HAL_SAI_DMAStop(&haudio_out_sai); 00514 00515 #if defined(USE_LCD_HDMI) 00516 /* ADV7533 used */ 00517 if((AudioOut_Device & OUTPUT_DEVICE_HDMI) == OUTPUT_DEVICE_HDMI) 00518 { 00519 if(DeviceId == ADV7533_ID) 00520 { 00521 /* Call the audio Codec Stop function */ 00522 if(hdmi_drv->Stop(ADV7533_MAIN_I2C_ADDR, Option) != 0) 00523 { 00524 ret = AUDIO_ERROR; 00525 } 00526 } 00527 } 00528 #endif /* USE_LCD_HDMI */ 00529 00530 /* WM8994 used */ 00531 if((((AudioOut_Device & OUTPUT_DEVICE_BOTH) > 0) && 00532 ((AudioOut_Device & OUTPUT_DEVICE_BOTH) <= OUTPUT_DEVICE_BOTH)) || 00533 ((AudioOut_Device & OUTPUT_DEVICE_AUTO) == OUTPUT_DEVICE_AUTO)) 00534 { 00535 /* Call the audio Codec Stop function */ 00536 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 00537 { 00538 ret = AUDIO_ERROR; 00539 } 00540 } 00541 00542 if(ret == AUDIO_ERROR) 00543 { 00544 return AUDIO_ERROR; 00545 } 00546 else 00547 { 00548 if(Option == CODEC_PDWN_HW) 00549 { 00550 /* Wait at least 100us */ 00551 HAL_Delay(1); 00552 } 00553 /* Return AUDIO_OK when all operations are correctly done */ 00554 return AUDIO_OK; 00555 } 00556 } 00557 00558 /** 00559 * @brief Control the current audio volume level. 00560 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00561 * Mute and 100 for Max volume level). 00562 * @retval AUDIO_OK if correct communication, else wrong communication 00563 */ 00564 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume) 00565 { 00566 /* Call the codec volume control function with converted volume value */ 00567 if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 00568 { 00569 return AUDIO_ERROR; 00570 } 00571 else 00572 { 00573 /* Return AUDIO_OK when all operations are correctly done */ 00574 return AUDIO_OK; 00575 } 00576 } 00577 00578 /** 00579 * @brief Enable or disable the MUTE mode by software 00580 * @param Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 00581 * unmute the codec and restore previous volume level. 00582 * @retval AUDIO_OK if correct communication, else wrong communication 00583 */ 00584 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd) 00585 { 00586 uint8_t ret = 0; 00587 #if defined(USE_LCD_HDMI) 00588 /* ADV7533 used */ 00589 if((AudioOut_Device & OUTPUT_DEVICE_HDMI) == OUTPUT_DEVICE_HDMI) 00590 { 00591 if(DeviceId == ADV7533_ID) 00592 { 00593 /* Call the audio Codec SetMute function */ 00594 if(hdmi_drv->SetMute(ADV7533_MAIN_I2C_ADDR, Cmd) != 0) 00595 { 00596 ret = AUDIO_ERROR; 00597 } 00598 } 00599 } 00600 #endif /* USE_LCD_HDMI */ 00601 00602 /* WM8994 used */ 00603 if((((AudioOut_Device & OUTPUT_DEVICE_BOTH) > 0) && 00604 ((AudioOut_Device & OUTPUT_DEVICE_BOTH) <= OUTPUT_DEVICE_BOTH)) || 00605 ((AudioOut_Device & OUTPUT_DEVICE_AUTO) == OUTPUT_DEVICE_AUTO)) 00606 { 00607 /* Call the audio Codec SetMute function */ 00608 if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0) 00609 { 00610 ret = AUDIO_ERROR; 00611 } 00612 } 00613 00614 if(ret == AUDIO_ERROR) 00615 { 00616 return AUDIO_ERROR; 00617 } 00618 else 00619 { 00620 /* Return AUDIO_OK when all operations are correctly done */ 00621 return AUDIO_OK; 00622 } 00623 } 00624 00625 /** 00626 * @brief Switch dynamically (while audio file is played) the output target 00627 * (speaker or headphone). 00628 * @param Output: The audio output target: OUTPUT_DEVICE_SPEAKER, 00629 * OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH 00630 * @retval AUDIO_OK if correct communication, else wrong communication 00631 */ 00632 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output) 00633 { 00634 /* Call the Codec output device function */ 00635 if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0) 00636 { 00637 return AUDIO_ERROR; 00638 } 00639 else 00640 { 00641 /* Return AUDIO_OK when all operations are correctly done */ 00642 return AUDIO_OK; 00643 } 00644 } 00645 00646 /** 00647 * @brief Update the audio frequency. 00648 * @param AudioFreq: Audio frequency used to play the audio stream. 00649 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00650 * audio frequency. 00651 * @retval None 00652 */ 00653 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq) 00654 { 00655 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00656 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00657 00658 /* Disable SAI peripheral to allow access to SAI internal registers */ 00659 __HAL_SAI_DISABLE(&haudio_out_sai); 00660 00661 /* Update the SAI audio frequency configuration */ 00662 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00663 HAL_SAI_Init(&haudio_out_sai); 00664 00665 /* Enable SAI peripheral to generate MCLK */ 00666 __HAL_SAI_ENABLE(&haudio_out_sai); 00667 } 00668 00669 /** 00670 * @brief Update the Audio frame slot configuration. 00671 * @param AudioFrameSlot: specifies the audio Frame slot 00672 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00673 * audio frame slot. 00674 * @retval None 00675 */ 00676 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot) 00677 { 00678 /* Disable SAI peripheral to allow access to SAI internal registers */ 00679 __HAL_SAI_DISABLE(&haudio_out_sai); 00680 00681 /* Update the SAI audio frame slot configuration */ 00682 haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot; 00683 HAL_SAI_Init(&haudio_out_sai); 00684 00685 /* Enable SAI peripheral to generate MCLK */ 00686 __HAL_SAI_ENABLE(&haudio_out_sai); 00687 } 00688 00689 00690 /** 00691 * @brief De-initialize the audio peripherals. 00692 * @retval None 00693 */ 00694 void BSP_AUDIO_OUT_DeInit(void) 00695 { 00696 SAIx_DeInit(); 00697 /* DeInit the SAI MSP : this __weak function can be rewritten by the application */ 00698 BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL); 00699 } 00700 00701 /** 00702 * @brief Tx Transfer completed callbacks. 00703 * @param hsai: SAI handle 00704 * @retval None 00705 */ 00706 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) 00707 { 00708 /* Manage the remaining file size and new address offset: This function 00709 should be coded by user (its prototype is already declared in stm32f769i_eval_audio.h) */ 00710 BSP_AUDIO_OUT_TransferComplete_CallBack(); 00711 } 00712 00713 /** 00714 * @brief Tx Half Transfer completed callbacks. 00715 * @param hsai: SAI handle 00716 * @retval None 00717 */ 00718 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 00719 { 00720 /* Manage the remaining file size and new address offset: This function 00721 should be coded by user (its prototype is already declared in stm32f769i_eval_audio.h) */ 00722 BSP_AUDIO_OUT_HalfTransfer_CallBack(); 00723 } 00724 00725 /** 00726 * @brief SAI error callbacks. 00727 * @param hsai: SAI handle 00728 * @retval None 00729 */ 00730 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 00731 { 00732 BSP_AUDIO_OUT_Error_CallBack(); 00733 } 00734 00735 /** 00736 * @brief Manages the DMA full Transfer complete event. 00737 * @retval None 00738 */ 00739 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void) 00740 { 00741 } 00742 00743 /** 00744 * @brief Manages the DMA Half Transfer complete event. 00745 * @retval None 00746 */ 00747 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) 00748 { 00749 } 00750 00751 /** 00752 * @brief Manages the DMA FIFO error event. 00753 * @retval None 00754 */ 00755 __weak void BSP_AUDIO_OUT_Error_CallBack(void) 00756 { 00757 } 00758 00759 /** 00760 * @brief Initialize BSP_AUDIO_OUT MSP. 00761 * @param hsai: SAI handle 00762 * @param Params 00763 * @retval None 00764 */ 00765 __weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params) 00766 { 00767 static DMA_HandleTypeDef hdma_sai_tx; 00768 GPIO_InitTypeDef gpio_init_structure; 00769 00770 /* Enable SAI clock */ 00771 AUDIO_SAIx_CLK_ENABLE(); 00772 00773 /* Enable GPIO clock */ 00774 AUDIO_SAIx_MCLK_ENABLE(); 00775 AUDIO_SAIx_SCK_SD_ENABLE(); 00776 AUDIO_SAIx_FS_ENABLE(); 00777 /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/ 00778 gpio_init_structure.Pin = AUDIO_SAIx_FS_PIN; 00779 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00780 gpio_init_structure.Pull = GPIO_NOPULL; 00781 gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 00782 gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF; 00783 HAL_GPIO_Init(AUDIO_SAIx_FS_GPIO_PORT, &gpio_init_structure); 00784 00785 gpio_init_structure.Pin = AUDIO_SAIx_SCK_PIN; 00786 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00787 gpio_init_structure.Pull = GPIO_NOPULL; 00788 gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 00789 gpio_init_structure.Alternate = AUDIO_SAIx_SCK_AF; 00790 HAL_GPIO_Init(AUDIO_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure); 00791 00792 gpio_init_structure.Pin = AUDIO_SAIx_SD_PIN; 00793 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00794 gpio_init_structure.Pull = GPIO_NOPULL; 00795 gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 00796 gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF; 00797 HAL_GPIO_Init(AUDIO_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure); 00798 00799 gpio_init_structure.Pin = AUDIO_SAIx_MCLK_PIN; 00800 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00801 gpio_init_structure.Pull = GPIO_NOPULL; 00802 gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 00803 gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF; 00804 HAL_GPIO_Init(AUDIO_SAIx_MCLK_GPIO_PORT, &gpio_init_structure); 00805 00806 /* Enable the DMA clock */ 00807 AUDIO_SAIx_DMAx_CLK_ENABLE(); 00808 00809 if(hsai->Instance == AUDIO_SAIx) 00810 { 00811 /* Configure the hdma_saiTx handle parameters */ 00812 hdma_sai_tx.Init.Channel = AUDIO_SAIx_DMAx_CHANNEL; 00813 hdma_sai_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; 00814 hdma_sai_tx.Init.PeriphInc = DMA_PINC_DISABLE; 00815 hdma_sai_tx.Init.MemInc = DMA_MINC_ENABLE; 00816 hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_SAIx_DMAx_PERIPH_DATA_SIZE; 00817 hdma_sai_tx.Init.MemDataAlignment = AUDIO_SAIx_DMAx_MEM_DATA_SIZE; 00818 hdma_sai_tx.Init.Mode = DMA_CIRCULAR; 00819 hdma_sai_tx.Init.Priority = DMA_PRIORITY_HIGH; 00820 hdma_sai_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; 00821 hdma_sai_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 00822 hdma_sai_tx.Init.MemBurst = DMA_MBURST_SINGLE; 00823 hdma_sai_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; 00824 00825 hdma_sai_tx.Instance = AUDIO_SAIx_DMAx_STREAM; 00826 00827 /* Associate the DMA handle */ 00828 __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx); 00829 00830 /* Deinitialize the Stream for new transfer */ 00831 HAL_DMA_DeInit(&hdma_sai_tx); 00832 00833 /* Configure the DMA Stream */ 00834 HAL_DMA_Init(&hdma_sai_tx); 00835 } 00836 00837 /* SAI DMA IRQ Channel configuration */ 00838 HAL_NVIC_SetPriority(AUDIO_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 00839 HAL_NVIC_EnableIRQ(AUDIO_SAIx_DMAx_IRQ); 00840 } 00841 00842 /** 00843 * @brief Deinitialize SAI MSP. 00844 * @param hsai: SAI handle 00845 * @param Params 00846 * @retval None 00847 */ 00848 __weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params) 00849 { 00850 GPIO_InitTypeDef gpio_init_structure; 00851 00852 /* SAI DMA IRQ Channel deactivation */ 00853 HAL_NVIC_DisableIRQ(AUDIO_SAIx_DMAx_IRQ); 00854 00855 if(hsai->Instance == AUDIO_SAIx) 00856 { 00857 /* Deinitialize the DMA stream */ 00858 HAL_DMA_DeInit(hsai->hdmatx); 00859 } 00860 00861 /* Disable SAI peripheral */ 00862 __HAL_SAI_DISABLE(hsai); 00863 00864 /* Deactivates CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */ 00865 gpio_init_structure.Pin = AUDIO_SAIx_FS_PIN; 00866 HAL_GPIO_DeInit(AUDIO_SAIx_FS_GPIO_PORT, gpio_init_structure.Pin); 00867 00868 gpio_init_structure.Pin = AUDIO_SAIx_SCK_PIN; 00869 HAL_GPIO_DeInit(AUDIO_SAIx_SCK_SD_GPIO_PORT, gpio_init_structure.Pin); 00870 00871 gpio_init_structure.Pin = AUDIO_SAIx_SD_PIN; 00872 HAL_GPIO_DeInit(AUDIO_SAIx_SCK_SD_GPIO_PORT, gpio_init_structure.Pin); 00873 00874 gpio_init_structure.Pin = AUDIO_SAIx_MCLK_PIN; 00875 HAL_GPIO_DeInit(AUDIO_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin); 00876 00877 /* Disable SAI clock */ 00878 AUDIO_SAIx_CLK_DISABLE(); 00879 00880 /* GPIO pins clock and DMA clock can be shut down in the applic 00881 by surcharging this __weak function */ 00882 } 00883 00884 /** 00885 * @brief Clock Config. 00886 * @param hsai: might be required to set audio peripheral predivider if any. 00887 * @param AudioFreq: Audio frequency used to play the audio stream. 00888 * @param Params 00889 * @note This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency() 00890 * Being __weak it can be overwritten by the application 00891 * @retval None 00892 */ 00893 __weak void BSP_AUDIO_OUT_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params) 00894 { 00895 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 00896 00897 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 00898 00899 /* Set the PLL configuration according to the audio frequency */ 00900 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 00901 { 00902 /* Configure PLLSAI prescalers */ 00903 /* PLLSAI_VCO: VCO_429M 00904 SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 429/2 = 214.5 Mhz 00905 SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 214.5/19 = 11.289 Mhz */ 00906 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 00907 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S; 00908 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429; 00909 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2; 00910 rcc_ex_clk_init_struct.PLLI2SDivQ = 19; 00911 00912 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00913 00914 } 00915 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_32K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 00916 { 00917 /* SAI clock config 00918 PLLSAI_VCO: VCO_344M 00919 SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 344/7 = 49.142 Mhz 00920 SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 49.142/1 = 49.142 Mhz */ 00921 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 00922 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S; 00923 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 00924 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 00925 rcc_ex_clk_init_struct.PLLI2SDivQ = 1; 00926 00927 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00928 } 00929 } 00930 00931 /******************************************************************************* 00932 Static Functions 00933 *******************************************************************************/ 00934 00935 /** 00936 * @brief Initialize the Audio Codec audio interface (SAI). 00937 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00938 * @note The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 00939 * and user can update this configuration using 00940 * @retval None 00941 */ 00942 static void SAIx_Init(uint32_t AudioFreq) 00943 { 00944 /* Initialize the haudio_out_sai Instance parameter */ 00945 haudio_out_sai.Instance = AUDIO_SAIx; 00946 00947 /* Disable SAI peripheral to allow access to SAI internal registers */ 00948 __HAL_SAI_DISABLE(&haudio_out_sai); 00949 00950 /* Configure SAI_Block_x 00951 LSBFirst: Disabled 00952 DataSize: 16 */ 00953 haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE; 00954 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00955 haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX; 00956 haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; 00957 haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL; 00958 haudio_out_sai.Init.DataSize = SAI_DATASIZE_16; 00959 haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 00960 haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; 00961 haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS; 00962 haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE; 00963 haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 00964 haudio_out_sai.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 00965 haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING; 00966 haudio_out_sai.Init.TriState = SAI_OUTPUT_NOTRELEASED; 00967 haudio_out_sai.Init.Mckdiv = 0; 00968 00969 /* Configure SAI_Block_x Frame 00970 Frame Length: 64 00971 Frame active Length: 32 00972 FS Definition: Start frame + Channel Side identification 00973 FS Polarity: FS active Low 00974 FS Offset: FS asserted one bit before the first bit of slot 0 */ 00975 haudio_out_sai.FrameInit.FrameLength = 64; 00976 haudio_out_sai.FrameInit.ActiveFrameLength = 32; 00977 haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 00978 haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 00979 haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 00980 00981 /* Configure SAI Block_x Slot 00982 Slot First Bit Offset: 0 00983 Slot Size : 16 00984 Slot Number: 4 00985 Slot Active: All slot actives */ 00986 haudio_out_sai.SlotInit.FirstBitOffset = 0; 00987 haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 00988 haudio_out_sai.SlotInit.SlotNumber = 4; 00989 haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123; 00990 00991 HAL_SAI_Init(&haudio_out_sai); 00992 00993 /* Enable SAI peripheral to generate MCLK */ 00994 __HAL_SAI_ENABLE(&haudio_out_sai); 00995 } 00996 00997 /** 00998 * @brief Deinitialize the Audio Codec audio interface (SAI). 00999 * @retval None 01000 */ 01001 static void SAIx_DeInit(void) 01002 { 01003 /* Initialize the haudio_out_sai Instance parameter */ 01004 haudio_out_sai.Instance = AUDIO_SAIx; 01005 01006 /* Disable SAI peripheral */ 01007 __HAL_SAI_DISABLE(&haudio_out_sai); 01008 01009 HAL_SAI_DeInit(&haudio_out_sai); 01010 } 01011 01012 /** 01013 * @} 01014 */ 01015 01016 /** @defgroup STM32F769I_EVAL_AUDIO_out_Private_Functions STM32F769I_EVAL_AUDIO_Out Private Functions 01017 * @{ 01018 */ 01019 01020 /** 01021 * @brief Initialize wave recording. 01022 * @param AudioFreq: Audio frequency to be configured for the DFSDM peripheral. 01023 * @param BitRes: Audio frequency to be configured for the DFSDM peripheral. 01024 * @param ChnlNbr: Audio frequency to be configured for the DFSDM peripheral. 01025 * @retval AUDIO_OK if correct communication, else wrong communication 01026 */ 01027 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 01028 { 01029 01030 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 01031 BSP_AUDIO_IN_ClockConfig(&haudio_in_dfsdm_leftfilter, AudioFreq, NULL); 01032 01033 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 01034 BSP_AUDIO_IN_MspInit(); 01035 01036 /* Initializes DFSDM peripheral */ 01037 DFSDMx_Init(AudioFreq); 01038 01039 /* Return AUDIO_OK when all operations are correctly done */ 01040 return AUDIO_OK; 01041 } 01042 01043 /** 01044 * @brief Allocate channel buffer scratch 01045 * @param pScratch : pointer to scratch tables. 01046 * @param size of scratch buffer 01047 */ 01048 uint8_t BSP_AUDIO_IN_AllocScratch (int32_t *pScratch, uint32_t size) 01049 { 01050 uint32_t idx; 01051 01052 ScratchSize = size / DEFAULT_AUDIO_IN_CHANNEL_NBR; 01053 01054 /* copy scratch pointers */ 01055 for (idx = 0; idx < DEFAULT_AUDIO_IN_CHANNEL_NBR ; idx++) 01056 { 01057 pScratchBuff[idx] = (int32_t *)(pScratch + idx * ScratchSize); 01058 } 01059 /* Return AUDIO_OK */ 01060 return AUDIO_OK; 01061 } 01062 01063 /** 01064 * @brief Start audio recording. 01065 * @param pbuf: Main buffer pointer for the recorded data storing 01066 * @param size: Current size of the recorded buffer 01067 * @retval AUDIO_OK if correct communication, else wrong communication 01068 */ 01069 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size) 01070 { 01071 hAudioIn.pRecBuf = pbuf; 01072 hAudioIn.RecSize = size; 01073 /* Reset Application Buffer Trigger */ 01074 AppBuffTrigger = 0; 01075 AppBuffHalf = 0; 01076 01077 /* Call the Media layer start function for right channel */ 01078 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_rightfilter, pScratchBuff[0], ScratchSize)) 01079 { 01080 return AUDIO_ERROR; 01081 } 01082 01083 /* Call the Media layer start function for left channel */ 01084 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_leftfilter, pScratchBuff[1], ScratchSize)) 01085 { 01086 return AUDIO_ERROR; 01087 } 01088 01089 /* Return AUDIO_OK when all operations are correctly done */ 01090 return AUDIO_OK; 01091 } 01092 01093 /** 01094 * @brief Stop audio recording. 01095 * @retval AUDIO_OK if correct communication, else wrong communication 01096 */ 01097 uint8_t BSP_AUDIO_IN_Stop(void) 01098 { 01099 AppBuffTrigger = 0; 01100 AppBuffHalf = 0; 01101 01102 /* Call the Media layer stop function for right channel */ 01103 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_rightfilter)) 01104 { 01105 return AUDIO_ERROR; 01106 } 01107 01108 /* Call the Media layer stop function for left channel */ 01109 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_leftfilter)) 01110 { 01111 return AUDIO_ERROR; 01112 } 01113 01114 /* Return AUDIO_OK when all operations are correctly done */ 01115 return AUDIO_OK; 01116 } 01117 01118 /** 01119 * @brief Pause the audio file stream. 01120 * @retval AUDIO_OK if correct communication, else wrong communication 01121 */ 01122 uint8_t BSP_AUDIO_IN_Pause(void) 01123 { 01124 /* Call the Media layer stop function */ 01125 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_rightfilter)) 01126 { 01127 return AUDIO_ERROR; 01128 } 01129 01130 /* Call the Media layer stop function */ 01131 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_leftfilter)) 01132 { 01133 return AUDIO_ERROR; 01134 } 01135 01136 /* Return AUDIO_OK when all operations are correctly done */ 01137 return AUDIO_OK; 01138 } 01139 01140 /** 01141 * @brief Resume the audio file stream. 01142 * @retval AUDIO_OK if correct communication, else wrong communication 01143 */ 01144 uint8_t BSP_AUDIO_IN_Resume(void) 01145 { 01146 /* Call the Media layer start function for right channel */ 01147 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_rightfilter, pScratchBuff[0], ScratchSize)) 01148 { 01149 return AUDIO_ERROR; 01150 } 01151 01152 /* Call the Media layer start function for left channel */ 01153 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_leftfilter, pScratchBuff[1], ScratchSize)) 01154 { 01155 return AUDIO_ERROR; 01156 } 01157 01158 /* Return AUDIO_OK when all operations are correctly done */ 01159 return AUDIO_OK; 01160 } 01161 01162 /** 01163 * @brief Deinit the audio IN peripherals. 01164 * @retval None 01165 */ 01166 void BSP_AUDIO_IN_DeInit(void) 01167 { 01168 BSP_AUDIO_IN_MspDeInit(); 01169 DFSDMx_DeInit(); 01170 } 01171 01172 01173 /** 01174 * @brief Regular conversion complete callback. 01175 * @note In interrupt mode, user has to read conversion value in this function 01176 using HAL_DFSDM_FilterGetRegularValue. 01177 * @param hdfsdm_filter : DFSDM filter handle. 01178 * @retval None 01179 */ 01180 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01181 { 01182 uint32_t index = 0; 01183 01184 if(hdfsdm_filter == &haudio_in_dfsdm_leftfilter) 01185 { 01186 DmaLeftRecBuffCplt = 1; 01187 } 01188 else 01189 { 01190 DmaRightRecBuffCplt = 1; 01191 } 01192 if((DmaLeftRecBuffCplt == 1) && (DmaRightRecBuffCplt == 1)) 01193 { 01194 for(index = (ScratchSize/2) ; index < ScratchSize; index++) 01195 { 01196 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760)); 01197 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760)); 01198 AppBuffTrigger +=2; 01199 } 01200 DmaLeftRecBuffCplt = 0; 01201 DmaRightRecBuffCplt = 0; 01202 } 01203 01204 /* Call Half Transfer Complete callback */ 01205 if((AppBuffTrigger == hAudioIn.RecSize/2) && (AppBuffHalf == 0)) 01206 { 01207 AppBuffHalf = 1; 01208 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01209 } 01210 /* Call Transfer Complete callback */ 01211 if(AppBuffTrigger == hAudioIn.RecSize) 01212 { 01213 /* Reset Application Buffer Trigger */ 01214 AppBuffTrigger = 0; 01215 AppBuffHalf = 0; 01216 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01217 BSP_AUDIO_IN_TransferComplete_CallBack(); 01218 } 01219 } 01220 01221 /** 01222 * @brief Half regular conversion complete callback. 01223 * @param hdfsdm_filter : DFSDM filter handle. 01224 * @retval None 01225 */ 01226 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01227 { 01228 uint32_t index = 0; 01229 01230 if(hdfsdm_filter == &haudio_in_dfsdm_leftfilter) 01231 { 01232 DmaLeftRecHalfBuffCplt = 1; 01233 } 01234 else 01235 { 01236 DmaRightRecHalfBuffCplt = 1; 01237 } 01238 if((DmaLeftRecHalfBuffCplt == 1) && (DmaRightRecHalfBuffCplt == 1)) 01239 { 01240 for(index = 0; index < ScratchSize/2; index++) 01241 { 01242 hAudioIn.pRecBuf[AppBuffTrigger] = (int16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760)); 01243 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (int16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760)); 01244 AppBuffTrigger +=2; 01245 } 01246 DmaLeftRecHalfBuffCplt = 0; 01247 DmaRightRecHalfBuffCplt = 0; 01248 } 01249 01250 /* Call Half Transfer Complete callback */ 01251 if((AppBuffTrigger == hAudioIn.RecSize/2) && (AppBuffHalf == 0)) 01252 { 01253 AppBuffHalf = 1; 01254 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01255 } 01256 /* Call Transfer Complete callback */ 01257 if(AppBuffTrigger == hAudioIn.RecSize) 01258 { 01259 /* Reset Application Buffer Trigger */ 01260 AppBuffTrigger = 0; 01261 AppBuffHalf = 0; 01262 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01263 BSP_AUDIO_IN_TransferComplete_CallBack(); 01264 } 01265 } 01266 01267 /** 01268 * @brief User callback when record buffer is filled. 01269 * @retval None 01270 */ 01271 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void) 01272 { 01273 /* This function should be implemented by the user application. 01274 It is called into this driver when the current buffer is filled 01275 to prepare the next buffer pointer and its size. */ 01276 } 01277 01278 /** 01279 * @brief Manages the DMA Half Transfer complete event. 01280 * @retval None 01281 */ 01282 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 01283 { 01284 /* This function should be implemented by the user application. 01285 It is called into this driver when the current buffer is filled 01286 to prepare the next buffer pointer and its size. */ 01287 } 01288 01289 /** 01290 * @brief Audio IN Error callback function. 01291 * @retval None 01292 */ 01293 __weak void BSP_AUDIO_IN_Error_Callback(void) 01294 { 01295 /* This function is called when an Interrupt due to transfer error on or peripheral 01296 error occurs. */ 01297 } 01298 01299 /** 01300 * @brief Initialize BSP_AUDIO_IN MSP. 01301 * @retval None 01302 */ 01303 __weak void BSP_AUDIO_IN_MspInit(void) 01304 { 01305 /* MSP channels initialization */ 01306 DFSDMx_ChannelMspInit(); 01307 /* MSP filters initialization */ 01308 DFSDMx_FilterMspInit(); 01309 } 01310 01311 /** 01312 * @brief DeInitialize BSP_AUDIO_IN MSP. 01313 * @retval None 01314 */ 01315 __weak void BSP_AUDIO_IN_MspDeInit(void) 01316 { 01317 /* MSP channels initialization */ 01318 DFSDMx_ChannelMspDeInit(); 01319 /* MSP filters initialization */ 01320 DFSDMx_FilterMspDeInit(); 01321 } 01322 01323 /** 01324 * @brief Clock Config. 01325 * @param hdfsdm_filter: might be required to set audio peripheral predivider if any. 01326 * @param AudioFreq: Audio frequency used to play the audio stream. 01327 * @param Params 01328 * @note This API is called by BSP_AUDIO_IN_Init() 01329 * Being __weak it can be overwritten by the application 01330 * @retval None 01331 */ 01332 __weak void BSP_AUDIO_IN_ClockConfig(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, uint32_t AudioFreq, void *Params) 01333 { 01334 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 01335 01336 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 01337 01338 /* Set the PLL configuration according to the audio frequency */ 01339 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 01340 { 01341 /* Configure PLLSAI prescalers */ 01342 /* PLLI2S_VCO: VCO_429M 01343 SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 429/2 = 214.5 Mhz 01344 SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 214.5/19 = 11.289 Mhz */ 01345 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 01346 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S; 01347 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429; 01348 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2; 01349 rcc_ex_clk_init_struct.PLLI2SDivQ = 19; 01350 01351 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01352 01353 } 01354 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_32K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 01355 { 01356 /* SAI clock config 01357 PLLI2S_VCO: VCO_344M 01358 SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 344/7 = 49.142 Mhz 01359 SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 49.142/1 = 49.142 Mhz */ 01360 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 01361 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S; 01362 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 01363 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 01364 rcc_ex_clk_init_struct.PLLI2SDivQ = 1; 01365 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01366 } 01367 01368 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_DFSDM1_AUDIO; 01369 rcc_ex_clk_init_struct.Dfsdm1AudioClockSelection = RCC_DFSDM1AUDIOCLKSOURCE_SAI2; 01370 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01371 } 01372 01373 /******************************************************************************* 01374 Static Functions 01375 *******************************************************************************/ 01376 /** 01377 * @brief Initialize the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01378 * @param AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral. 01379 * @note Channel output Clock Divider and Filter Oversampling are calculated as follow: 01380 * - Clock_Divider = CLK(input DFSDM)/CLK(micro) with 01381 * 1MHZ < CLK(micro) < 3.2MHZ (TYP 2.4MHZ for MP34DT01TR) 01382 * - Oversampling = CLK(input DFSDM)/(Clock_Divider * AudioFreq) 01383 * @retval AUDIO_OK if correct communication, else wrong communication 01384 */ 01385 static uint8_t DFSDMx_Init(uint32_t AudioFreq) 01386 { 01387 /*####CHANNEL 1####*/ 01388 __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&haudio_in_dfsdm_leftchannel); 01389 haudio_in_dfsdm_leftchannel.Instance = DFSDM1_Channel1; 01390 haudio_in_dfsdm_leftchannel.Init.OutputClock.Activation = ENABLE; 01391 haudio_in_dfsdm_leftchannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01392 /* Set the DFSDM clock OUT audio frequency configuration */ 01393 haudio_in_dfsdm_leftchannel.Init.OutputClock.Divider = DFSDM_CLOCK_DIVIDER(AudioFreq); 01394 haudio_in_dfsdm_leftchannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01395 haudio_in_dfsdm_leftchannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01396 haudio_in_dfsdm_leftchannel.Init.Input.Pins = DFSDM_CHANNEL_SAME_CHANNEL_PINS; 01397 /* Request to sample stable data for LEFT micro on Rising edge */ 01398 haudio_in_dfsdm_leftchannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_RISING; 01399 haudio_in_dfsdm_leftchannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01400 haudio_in_dfsdm_leftchannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER; 01401 haudio_in_dfsdm_leftchannel.Init.Awd.Oversampling = 10; 01402 haudio_in_dfsdm_leftchannel.Init.Offset = 0; 01403 haudio_in_dfsdm_leftchannel.Init.RightBitShift = DFSDM_RIGHT_BIT_SHIFT(AudioFreq); 01404 if(HAL_OK != HAL_DFSDM_ChannelInit(&haudio_in_dfsdm_leftchannel)) 01405 { 01406 return AUDIO_ERROR; 01407 } 01408 01409 /*####FILTER 0####*/ 01410 __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&haudio_in_dfsdm_leftfilter); 01411 haudio_in_dfsdm_leftfilter.Instance = AUDIO_DFSDMx_LEFT_FILTER; 01412 haudio_in_dfsdm_leftfilter.Init.RegularParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01413 haudio_in_dfsdm_leftfilter.Init.RegularParam.FastMode = ENABLE; 01414 haudio_in_dfsdm_leftfilter.Init.RegularParam.DmaMode = ENABLE; 01415 haudio_in_dfsdm_leftfilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01416 haudio_in_dfsdm_leftfilter.Init.InjectedParam.ScanMode = ENABLE; 01417 haudio_in_dfsdm_leftfilter.Init.InjectedParam.DmaMode = DISABLE; 01418 haudio_in_dfsdm_leftfilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO; 01419 haudio_in_dfsdm_leftfilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE; 01420 haudio_in_dfsdm_leftfilter.Init.FilterParam.SincOrder = DFSDM_FILTER_ORDER(AudioFreq); 01421 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01422 haudio_in_dfsdm_leftfilter.Init.FilterParam.Oversampling = DFSDM_OVER_SAMPLING(AudioFreq); 01423 haudio_in_dfsdm_leftfilter.Init.FilterParam.IntOversampling = 1; 01424 if(HAL_OK != HAL_DFSDM_FilterInit(&haudio_in_dfsdm_leftfilter)) 01425 { 01426 return AUDIO_ERROR; 01427 } 01428 01429 /* Configure injected channel */ 01430 if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&haudio_in_dfsdm_leftfilter, DFSDM_CHANNEL_1, DFSDM_CONTINUOUS_CONV_ON)) 01431 { 01432 return AUDIO_ERROR; 01433 } 01434 01435 /*####CHANNEL 0####*/ 01436 __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&haudio_in_dfsdm_rightchannel); 01437 haudio_in_dfsdm_rightchannel.Instance = DFSDM1_Channel0; 01438 haudio_in_dfsdm_rightchannel.Init.OutputClock.Activation = ENABLE; 01439 haudio_in_dfsdm_rightchannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01440 /* Set the DFSDM clock OUT audio frequency configuration */ 01441 haudio_in_dfsdm_rightchannel.Init.OutputClock.Divider = DFSDM_CLOCK_DIVIDER(AudioFreq); 01442 haudio_in_dfsdm_rightchannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01443 haudio_in_dfsdm_rightchannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01444 haudio_in_dfsdm_rightchannel.Init.Input.Pins = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS; 01445 /* Request to sample stable data for RIGHT micro on Falling edge */ 01446 haudio_in_dfsdm_rightchannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_FALLING; 01447 haudio_in_dfsdm_rightchannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01448 haudio_in_dfsdm_rightchannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER; 01449 haudio_in_dfsdm_rightchannel.Init.Awd.Oversampling = 10; 01450 haudio_in_dfsdm_rightchannel.Init.Offset = 0; 01451 haudio_in_dfsdm_rightchannel.Init.RightBitShift = DFSDM_RIGHT_BIT_SHIFT(AudioFreq); 01452 if(HAL_OK != HAL_DFSDM_ChannelInit(&haudio_in_dfsdm_rightchannel)) 01453 { 01454 return AUDIO_ERROR; 01455 } 01456 01457 /*####FILTER 1####*/ 01458 __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&haudio_in_dfsdm_rightfilter); 01459 haudio_in_dfsdm_rightfilter.Instance = AUDIO_DFSDMx_RIGHT_FILTER; 01460 haudio_in_dfsdm_rightfilter.Init.RegularParam.Trigger = DFSDM_FILTER_SYNC_TRIGGER; 01461 haudio_in_dfsdm_rightfilter.Init.RegularParam.FastMode = ENABLE; 01462 haudio_in_dfsdm_rightfilter.Init.RegularParam.DmaMode = ENABLE; 01463 haudio_in_dfsdm_rightfilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01464 haudio_in_dfsdm_rightfilter.Init.InjectedParam.ScanMode = DISABLE; 01465 haudio_in_dfsdm_rightfilter.Init.InjectedParam.DmaMode = DISABLE; 01466 haudio_in_dfsdm_rightfilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO; 01467 haudio_in_dfsdm_rightfilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE; 01468 haudio_in_dfsdm_rightfilter.Init.FilterParam.SincOrder = DFSDM_FILTER_ORDER(AudioFreq); 01469 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01470 haudio_in_dfsdm_rightfilter.Init.FilterParam.Oversampling = DFSDM_OVER_SAMPLING(AudioFreq); 01471 haudio_in_dfsdm_rightfilter.Init.FilterParam.IntOversampling = 1; 01472 if(HAL_OK != HAL_DFSDM_FilterInit(&haudio_in_dfsdm_rightfilter)) 01473 { 01474 return AUDIO_ERROR; 01475 } 01476 /* Configure injected channel */ 01477 if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&haudio_in_dfsdm_rightfilter, DFSDM_CHANNEL_0, DFSDM_CONTINUOUS_CONV_ON)) 01478 { 01479 return AUDIO_ERROR; 01480 } 01481 01482 return AUDIO_OK; 01483 } 01484 01485 /** 01486 * @brief De-initialize the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01487 * @retval AUDIO_OK if correct communication, else wrong communication 01488 */ 01489 static uint8_t DFSDMx_DeInit(void) 01490 { 01491 /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */ 01492 if(HAL_OK != HAL_DFSDM_FilterDeInit(&haudio_in_dfsdm_leftfilter)) 01493 { 01494 return AUDIO_ERROR; 01495 } 01496 01497 if(HAL_OK != HAL_DFSDM_FilterDeInit(&haudio_in_dfsdm_rightfilter)) 01498 { 01499 return AUDIO_ERROR; 01500 } 01501 01502 /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */ 01503 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&haudio_in_dfsdm_leftchannel)) 01504 { 01505 return AUDIO_ERROR; 01506 } 01507 01508 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&haudio_in_dfsdm_rightchannel)) 01509 { 01510 return AUDIO_ERROR; 01511 } 01512 01513 return AUDIO_OK; 01514 } 01515 01516 /** 01517 * @brief Initialize the DFSDM channel MSP. 01518 * @retval None 01519 */ 01520 static void DFSDMx_ChannelMspInit(void) 01521 { 01522 GPIO_InitTypeDef GPIO_InitStruct; 01523 01524 /* Enable DFSDM clock */ 01525 AUDIO_DFSDMx_CLK_ENABLE(); 01526 01527 /* Enable GPIO clock */ 01528 AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_CLK_ENABLE(); 01529 01530 /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN pins ------------------*/ 01531 GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN; 01532 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 01533 GPIO_InitStruct.Pull = GPIO_NOPULL; 01534 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 01535 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_CKOUT_AF; 01536 HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct); 01537 01538 GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_DATIN_PIN; 01539 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_DMIC_DATIN_AF; 01540 HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct); 01541 } 01542 01543 /** 01544 * @brief DeInitialize the DFSDM channel MSP. 01545 * @retval None 01546 */ 01547 static void DFSDMx_ChannelMspDeInit(void) 01548 { 01549 GPIO_InitTypeDef GPIO_InitStruct; 01550 01551 /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN pins ------------------*/ 01552 GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN | AUDIO_DFSDMx_DMIC_DATIN_PIN; 01553 HAL_GPIO_DeInit(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, GPIO_InitStruct.Pin); 01554 } 01555 01556 /** 01557 * @brief Initialize the DFSDM filter MSP. 01558 * @retval None 01559 */ 01560 static void DFSDMx_FilterMspInit(void) 01561 { 01562 /* Enable DFSDM clock */ 01563 AUDIO_DFSDMx_CLK_ENABLE(); 01564 01565 /* Enable the DMA clock */ 01566 AUDIO_DFSDMx_DMAx_CLK_ENABLE(); 01567 01568 hdma_dfsdm_left.Init.Direction = DMA_PERIPH_TO_MEMORY; 01569 hdma_dfsdm_left.Init.PeriphInc = DMA_PINC_DISABLE; 01570 hdma_dfsdm_left.Init.MemInc = DMA_MINC_ENABLE; 01571 hdma_dfsdm_left.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE; 01572 hdma_dfsdm_left.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE; 01573 hdma_dfsdm_left.Init.Mode = DMA_CIRCULAR; 01574 hdma_dfsdm_left.Init.Priority = DMA_PRIORITY_HIGH; 01575 hdma_dfsdm_left.Instance = DMA2_Stream0; 01576 hdma_dfsdm_left.Init.Channel = AUDIO_DFSDMx_DMAx_LEFT_CHANNEL; 01577 01578 /* Associate the DMA handle */ 01579 __HAL_LINKDMA(&haudio_in_dfsdm_leftfilter, hdmaReg, hdma_dfsdm_left); 01580 01581 /* Reset DMA handle state */ 01582 __HAL_DMA_RESET_HANDLE_STATE(&hdma_dfsdm_left); 01583 01584 /* Configure the DMA Channel */ 01585 HAL_DMA_Init(&hdma_dfsdm_left); 01586 01587 /* DMA IRQ Channel configuration */ 01588 HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_LEFT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 01589 HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_LEFT_IRQ); 01590 01591 01592 /* Configure the hdma_dfsdmReg handle parameters */ 01593 hdma_dfsdm_right.Init.Direction = DMA_PERIPH_TO_MEMORY; 01594 hdma_dfsdm_right.Init.PeriphInc = DMA_PINC_DISABLE; 01595 hdma_dfsdm_right.Init.MemInc = DMA_MINC_ENABLE; 01596 hdma_dfsdm_right.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE; 01597 hdma_dfsdm_right.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE; 01598 hdma_dfsdm_right.Init.Mode = DMA_CIRCULAR; 01599 hdma_dfsdm_right.Init.Priority = DMA_PRIORITY_HIGH; 01600 hdma_dfsdm_right.Instance = DMA2_Stream5; 01601 hdma_dfsdm_right.Init.Channel = AUDIO_DFSDMx_DMAx_RIGHT_CHANNEL; 01602 01603 /* Associate the DMA handle */ 01604 __HAL_LINKDMA(&haudio_in_dfsdm_rightfilter, hdmaReg, hdma_dfsdm_right); 01605 01606 /* Reset DMA handle state */ 01607 __HAL_DMA_RESET_HANDLE_STATE(&hdma_dfsdm_right); 01608 01609 /* Configure the DMA Channel */ 01610 HAL_DMA_Init(&hdma_dfsdm_right); 01611 01612 /* DMA IRQ Channel configuration */ 01613 HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_RIGHT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 01614 HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_RIGHT_IRQ); 01615 } 01616 01617 /** 01618 * @brief DeInitialize the DFSDM filter MSP. 01619 * @retval None 01620 */ 01621 static void DFSDMx_FilterMspDeInit(void) 01622 { 01623 /* Configure the DMA Channel */ 01624 HAL_DMA_DeInit(&hdma_dfsdm_left); 01625 HAL_DMA_DeInit(&hdma_dfsdm_right); 01626 } 01627 01628 /** 01629 * @} 01630 */ 01631 01632 /** 01633 * @} 01634 */ 01635 01636 /** 01637 * @} 01638 */ 01639 01640 /** 01641 * @} 01642 */ 01643 01644 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Thu May 25 2017 11:03:11 for STM32769I_EVAL BSP User Manual by
