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