STM32Cube BSP FW for STM32F769I-Discovery
Dependents: mbed-os-example-blinky-5 DISCO-F769NI_TOUCHSCREEN_demo_custom_1 Datarecorder2 DISCO-F769NI_TOUCHSCREEN_demo ... more
stm32f769i_discovery_audio.c
00001 /** 00002 ****************************************************************************** 00003 * @file stm32f769i_discovery_audio.c 00004 * @author MCD Application Team 00005 * @brief This file provides the Audio driver for the STM32F769I-DISCOVERY 00006 * board. 00007 @verbatim 00008 How To use this driver: 00009 ----------------------- 00010 + This driver supports STM32F7xx devices on STM32F769I-DISCOVERY (MB1225) Evaluation boards. 00011 + Call the function BSP_AUDIO_OUT_Init( 00012 OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 00013 OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH) 00014 Volume : Initial volume to be set (0 is min (mute), 100 is max (100%) 00015 AudioFreq : Audio frequency in Hz (8000, 16000, 22500, 32000...) 00016 this parameter is relative to the audio file/stream type. 00017 ) 00018 This function configures all the hardware required for the audio application (codec, I2C, SAI, 00019 GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK. 00020 If the returned value is different from AUDIO_OK or the function is stuck then the communication with 00021 the codec has failed (try to un-plug the power or reset device in this case). 00022 - OUTPUT_DEVICE_SPEAKER : only speaker will be set as output for the audio stream. 00023 - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream. 00024 - OUTPUT_DEVICE_BOTH : both Speaker and Headphone are used as outputs for the audio stream 00025 at the same time. 00026 Note. On STM32F769I-DISCOVERY SAI_DMA is configured in CIRCULAR mode. Due to this the application 00027 does NOT need to call BSP_AUDIO_OUT_ChangeBuffer() to assure streaming. 00028 + Call the function BSP_AUDIO_OUT_Play( 00029 pBuffer: pointer to the audio data file address 00030 Size : size of the buffer to be sent in Bytes 00031 ) 00032 to start playing (for the first time) from the audio file/stream. 00033 + Call the function BSP_AUDIO_OUT_Pause() to pause playing 00034 + Call the function BSP_AUDIO_OUT_Resume() to resume playing. 00035 Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called 00036 for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case). 00037 Note. This function should be called only when the audio file is played or paused (not stopped). 00038 + For each mode, you may need to implement the relative callback functions into your code. 00039 The Callback functions are named BSP_AUDIO_OUT_XXX_CallBack() and only their prototypes are declared in 00040 the stm32f769i_discovery_audio.h file. (refer to the example for more details on the callbacks implementations) 00041 + To Stop playing, to modify the volume level, the frequency, the audio frame slot, 00042 the device output mode the mute or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(), 00043 AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetAudioFrameSlot(), BSP_AUDIO_OUT_SetOutputMode(), 00044 BSP_AUDIO_OUT_SetMute() and BSP_AUDIO_OUT_Stop(). 00045 00046 + Call the function BSP_AUDIO_IN_Init( 00047 AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000...) 00048 this parameter is relative to the audio file/stream type. 00049 BitRes: Bit resolution fixed to 16bit 00050 ChnlNbr: Number of channel to be configured for the DFSDM peripheral 00051 ) 00052 This function configures all the hardware required for the audio in application (DFSDM filters and channels, 00053 Clock source for DFSDM periphiral, GPIOs, DMA and interrupt if needed). 00054 This function returns AUDIO_OK if configuration is OK.If the returned value is different from AUDIO_OK then 00055 the configuration should be wrong. 00056 Note: On STM32F769I-DISCOVERY, four DFSDM Channel/Filters are configured and their DMA streams are configured 00057 in CIRCULAR mode. 00058 + Call the function BSP_AUDIO_IN_AllocScratch( 00059 pScratch: pointer to scratch tables 00060 size: size of scratch buffer) 00061 This function must be called before BSP_AUDIO_IN_RECORD() to allocate buffer scratch for each DFSDM channel 00062 and its size. 00063 Note: These buffers scratch are used as intermidiate buffers to collect data within final record buffer. 00064 size is the total size of the four buffers scratch; If size is 512 then the size of each is 128. 00065 This function must be called after BSP_AUDIO_IN_Init() 00066 + Call the function BSP_AUDIO_IN_RECORD( 00067 pBuf: pointer to the recorded audio data file address 00068 Size: size of the buffer to be written in Bytes 00069 ) 00070 to start recording from microphones. 00071 00072 + Call the function BSP_AUDIO_IN_Pause() to pause recording 00073 + Call the function BSP_AUDIO_IN_Resume() to recording playing. 00074 Note. After calling BSP_AUDIO_IN_Pause() function for pause, only BSP_AUDIO_IN_Resume() should be called 00075 for resume (it is not allowed to call BSP_AUDIO_IN_RECORD() in this case). 00076 + Call the function BSP_AUDIO_IN_Stop() to stop recording 00077 + For each mode, you may need to implement the relative callback functions into your code. 00078 The Callback functions are named BSP_AUDIO_IN_XXX_CallBack() and only their prototypes are declared in 00079 the stm32f769i_discovery_audio.h file. (refer to the example for more details on the callbacks implementations) 00080 00081 Driver architecture: 00082 -------------------- 00083 + This driver provides the High Audio Layer: consists of the function API exported in the stm32f769i_discovery_audio.h file 00084 (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...) 00085 + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/ 00086 providing the audio file/stream. These functions are also included as local functions into 00087 the stm32f769i_discovery_audio.c file (DFSDMx_Init(), DFSDMx_DeInit(), SAIx_Init() and SAIx_DeInit()) 00088 00089 Known Limitations: 00090 ------------------ 00091 1- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second 00092 Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams. 00093 2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 00094 File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file. 00095 3- Supports only Stereo audio streaming. 00096 4- Supports only 16-bits audio data size. 00097 @endverbatim 00098 ****************************************************************************** 00099 * @attention 00100 * 00101 * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> 00102 * 00103 * Redistribution and use in source and binary forms, with or without modification, 00104 * are permitted provided that the following conditions are met: 00105 * 1. Redistributions of source code must retain the above copyright notice, 00106 * this list of conditions and the following disclaimer. 00107 * 2. Redistributions in binary form must reproduce the above copyright notice, 00108 * this list of conditions and the following disclaimer in the documentation 00109 * and/or other materials provided with the distribution. 00110 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00111 * may be used to endorse or promote products derived from this software 00112 * without specific prior written permission. 00113 * 00114 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00115 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00116 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00117 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00118 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00119 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00120 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00121 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00122 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00123 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00124 * 00125 ****************************************************************************** 00126 */ 00127 00128 /* Dependencies 00129 - stm32f769i_discovery.c 00130 - stm32f7xx_hal_sai.c 00131 - stm32f7xx_hal_dfsdm.c 00132 - stm32f7xx_hal_dma.c 00133 - stm32f7xx_hal_gpio.c 00134 - stm32f7xx_hal_cortex.c 00135 - stm32f7xx_hal_rcc_ex.h 00136 - wm8994.c 00137 EndDependencies */ 00138 00139 /* Includes ------------------------------------------------------------------*/ 00140 #include "stm32f769i_discovery_audio.h" 00141 00142 /** @addtogroup BSP 00143 * @{ 00144 */ 00145 00146 /** @addtogroup STM32F769I_DISCOVERY 00147 * @{ 00148 */ 00149 00150 /** @defgroup STM32F769I_DISCOVERY_AUDIO STM32F769I_DISCOVERY AUDIO 00151 * @brief This file includes the low layer driver for wm8994 Audio Codec 00152 * available on STM32F769I-DISCOVERY discoveryuation board(MB1225). 00153 * @{ 00154 */ 00155 00156 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Types STM32F769I_DISCOVERY_AUDIO Private Types 00157 * @{ 00158 */ 00159 typedef struct 00160 { 00161 uint16_t *pRecBuf; /* Pointer to record user buffer */ 00162 uint32_t RecSize; /* Size to record in mono, double size to record in stereo */ 00163 }AUDIOIN_TypeDef; 00164 00165 /** 00166 * @} 00167 */ 00168 00169 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Defines STM32F769I_DISCOVERY_AUDIO Private Defines 00170 * @{ 00171 */ 00172 /** 00173 * @} 00174 */ 00175 00176 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Macros STM32F769I_DISCOVERY_AUDIO Private Macros 00177 * @{ 00178 */ 00179 /*### RECORD ###*/ 00180 #define DFSDM_OVER_SAMPLING(__FREQUENCY__) \ 00181 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 256 \ 00182 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \ 00183 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \ 00184 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \ 00185 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \ 00186 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64 \ 00187 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 40 : 20 \ 00188 00189 #define DFSDM_CLOCK_DIVIDER(__FREQUENCY__) \ 00190 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 24 \ 00191 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \ 00192 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \ 00193 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \ 00194 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \ 00195 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4 \ 00196 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 25 : 25 \ 00197 00198 #define DFSDM_FILTER_ORDER(__FREQUENCY__) \ 00199 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? DFSDM_FILTER_SINC3_ORDER \ 00200 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \ 00201 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \ 00202 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \ 00203 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \ 00204 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC3_ORDER \ 00205 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC3_ORDER : DFSDM_FILTER_SINC5_ORDER \ 00206 00207 #define DFSDM_RIGHT_BIT_SHIFT(__FREQUENCY__) \ 00208 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 8 \ 00209 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 8 \ 00210 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 3 \ 00211 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \ 00212 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 7 \ 00213 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 0 \ 00214 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 0 : 4 \ 00215 00216 /* Saturate the record PCM sample */ 00217 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N))) 00218 /** 00219 * @} 00220 */ 00221 00222 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Variables STM32F769I_DISCOVERY_AUDIO Private Variables 00223 * @{ 00224 */ 00225 /* PLAY */ 00226 AUDIO_DrvTypeDef *audio_drv; 00227 SAI_HandleTypeDef haudio_out_sai; 00228 SAI_HandleTypeDef haudio_in_sai; 00229 00230 /* RECORD */ 00231 AUDIOIN_TypeDef hAudioIn; 00232 00233 DFSDM_Channel_HandleTypeDef hAudioInTopLeftChannel; 00234 DFSDM_Channel_HandleTypeDef hAudioInTopRightChannel; 00235 DFSDM_Filter_HandleTypeDef hAudioInTopLeftFilter; 00236 DFSDM_Filter_HandleTypeDef hAudioInTopRightFilter; 00237 DMA_HandleTypeDef hDmaTopLeft; 00238 DMA_HandleTypeDef hDmaTopRight; 00239 00240 DFSDM_Channel_HandleTypeDef hAudioInButtomLeftChannel; 00241 DFSDM_Channel_HandleTypeDef hAudioInButtomRightChannel; 00242 DFSDM_Filter_HandleTypeDef hAudioInButtomLeftFilter; 00243 DFSDM_Filter_HandleTypeDef hAudioInButtomRightFilter; 00244 DMA_HandleTypeDef hDmaButtomLeft; 00245 DMA_HandleTypeDef hDmaButtomRight; 00246 00247 /* Buffers for right and left samples */ 00248 static int32_t *pScratchBuff[2*DEFAULT_AUDIO_IN_CHANNEL_NBR]; 00249 static __IO int32_t ScratchSize; 00250 /* Cannel number to be used: 2 channels by default */ 00251 static uint8_t AudioIn_ChannelNumber = DEFAULT_AUDIO_IN_CHANNEL_NBR; 00252 /* Input device to be used: digital microphones by default */ 00253 static uint16_t AudioIn_Device = INPUT_DEVICE_DIGITAL_MIC; 00254 00255 /* Buffers status flags */ 00256 static uint32_t DmaTopLeftRecHalfCplt = 0; 00257 static uint32_t DmaTopLeftRecCplt = 0; 00258 static uint32_t DmaTopRightRecHalfCplt = 0; 00259 static uint32_t DmaTopRightRecCplt = 0; 00260 static uint32_t DmaButtomLeftRecHalfCplt = 0; 00261 static uint32_t DmaButtomLeftRecCplt = 0; 00262 static uint32_t DmaButtomRightRecHalfCplt = 0; 00263 static uint32_t DmaButtomRightRecCplt = 0; 00264 00265 /* Application Buffer Trigger */ 00266 static __IO uint32_t AppBuffTrigger = 0; 00267 static __IO uint32_t AppBuffHalf = 0; 00268 00269 /** 00270 * @} 00271 */ 00272 00273 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Function_Prototypes STM32F769I_DISCOVERY_AUDIO Private Function Prototypes 00274 * @{ 00275 */ 00276 static void SAIx_Out_Init(uint32_t AudioFreq); 00277 static void SAIx_Out_DeInit(void); 00278 static void SAI_AUDIO_IN_MspInit(SAI_HandleTypeDef *hsai, void *Params); 00279 static void SAI_AUDIO_IN_MspDeInit(SAI_HandleTypeDef *hsai, void *Params); 00280 static void SAIx_In_Init(uint32_t AudioFreq); 00281 static void SAIx_In_DeInit(void); 00282 static void DFSDMx_ChannelMspInit(void); 00283 static void DFSDMx_FilterMspInit(void); 00284 static void DFSDMx_ChannelMspDeInit(void); 00285 static void DFSDMx_FilterMspDeInit(void); 00286 static uint8_t DFSDMx_Init(uint32_t AudioFreq); 00287 static uint8_t DFSDMx_DeInit(void); 00288 00289 /** 00290 * @} 00291 */ 00292 00293 /** @defgroup STM32F769I_DISCOVERY_AUDIO_out_Private_Functions STM32F769I_DISCOVERY_AUDIO_Out Private Functions 00294 * @{ 00295 */ 00296 00297 /** 00298 * @brief Configures the audio peripherals. 00299 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00300 * or OUTPUT_DEVICE_BOTH. 00301 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00302 * @param AudioFreq: Audio frequency used to play the audio stream. 00303 * @retval AUDIO_OK if correct communication, else wrong communication 00304 */ 00305 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00306 { 00307 uint8_t ret = AUDIO_ERROR; 00308 uint32_t deviceid = 0x00; 00309 00310 /* Disable SAI */ 00311 SAIx_Out_DeInit(); 00312 00313 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00314 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00315 00316 /* SAI data transfer preparation: 00317 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00318 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00319 if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET) 00320 { 00321 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00322 BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL); 00323 } 00324 SAIx_Out_Init(AudioFreq); 00325 00326 /* wm8994 codec initialization */ 00327 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00328 00329 if((deviceid) == WM8994_ID) 00330 { 00331 /* Reset the Codec Registers */ 00332 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00333 /* Initialize the audio driver structure */ 00334 audio_drv = &wm8994_drv; 00335 ret = AUDIO_OK; 00336 } 00337 else 00338 { 00339 ret = AUDIO_ERROR; 00340 } 00341 00342 if(ret == AUDIO_OK) 00343 { 00344 /* Initialize the codec internal registers */ 00345 audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq); 00346 } 00347 00348 return ret; 00349 } 00350 00351 /** 00352 * @brief Starts playing audio stream from a data buffer for a determined size. 00353 * @param pBuffer: Pointer to the buffer 00354 * @param Size: Number of audio data BYTES. 00355 * @retval AUDIO_OK if correct communication, else wrong communication 00356 */ 00357 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size) 00358 { 00359 /* Call the audio Codec Play function */ 00360 if(audio_drv->Play(AUDIO_I2C_ADDRESS, (uint16_t *)pBuffer, Size) != 0) 00361 { 00362 return AUDIO_ERROR; 00363 } 00364 else 00365 { 00366 /* Update the Media layer and enable it for play */ 00367 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE)); 00368 00369 return AUDIO_OK; 00370 } 00371 } 00372 00373 /** 00374 * @brief Sends n-Bytes on the SAI interface. 00375 * @param pData: pointer on data address 00376 * @param Size: number of data to be written 00377 * @retval None 00378 */ 00379 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size) 00380 { 00381 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size); 00382 } 00383 00384 /** 00385 * @brief This function Pauses the audio file stream. In case 00386 * of using DMA, the DMA Pause feature is used. 00387 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00388 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00389 * function for resume could lead to unexpected behaviour). 00390 * @retval AUDIO_OK if correct communication, else wrong communication 00391 */ 00392 uint8_t BSP_AUDIO_OUT_Pause(void) 00393 { 00394 /* Call the Audio Codec Pause/Resume function */ 00395 if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0) 00396 { 00397 return AUDIO_ERROR; 00398 } 00399 else 00400 { 00401 /* Call the Media layer pause function */ 00402 HAL_SAI_DMAPause(&haudio_out_sai); 00403 00404 /* Return AUDIO_OK when all operations are correctly done */ 00405 return AUDIO_OK; 00406 } 00407 } 00408 00409 /** 00410 * @brief Resumes the audio file stream. 00411 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00412 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00413 * function for resume could lead to unexpected behaviour). 00414 * @retval AUDIO_OK if correct communication, else wrong communication 00415 */ 00416 uint8_t BSP_AUDIO_OUT_Resume(void) 00417 { 00418 /* Call the Audio Codec Pause/Resume function */ 00419 if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0) 00420 { 00421 return AUDIO_ERROR; 00422 } 00423 else 00424 { 00425 /* Call the Media layer pause/resume function */ 00426 HAL_SAI_DMAResume(&haudio_out_sai); 00427 00428 /* Return AUDIO_OK when all operations are correctly done */ 00429 return AUDIO_OK; 00430 } 00431 } 00432 00433 /** 00434 * @brief Stops audio playing and Power down the Audio Codec. 00435 * @param Option: could be one of the following parameters 00436 * - CODEC_PDWN_SW: for software power off (by writing registers). 00437 * Then no need to reconfigure the Codec after power on. 00438 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00439 * Then need to reconfigure the Codec after power on. 00440 * @retval AUDIO_OK if correct communication, else wrong communication 00441 */ 00442 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option) 00443 { 00444 /* Call the Media layer stop function */ 00445 HAL_SAI_DMAStop(&haudio_out_sai); 00446 00447 /* Call Audio Codec Stop function */ 00448 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 00449 { 00450 return AUDIO_ERROR; 00451 } 00452 else 00453 { 00454 if(Option == CODEC_PDWN_HW) 00455 { 00456 /* Wait at least 100us */ 00457 HAL_Delay(1); 00458 } 00459 /* Return AUDIO_OK when all operations are correctly done */ 00460 return AUDIO_OK; 00461 } 00462 } 00463 00464 /** 00465 * @brief Controls the current audio volume level. 00466 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00467 * Mute and 100 for Max volume level). 00468 * @retval AUDIO_OK if correct communication, else wrong communication 00469 */ 00470 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume) 00471 { 00472 /* Call the codec volume control function with converted volume value */ 00473 if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 00474 { 00475 return AUDIO_ERROR; 00476 } 00477 else 00478 { 00479 /* Return AUDIO_OK when all operations are correctly done */ 00480 return AUDIO_OK; 00481 } 00482 } 00483 00484 /** 00485 * @brief Enables or disables the MUTE mode by software 00486 * @param Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 00487 * unmute the codec and restore previous volume level. 00488 * @retval AUDIO_OK if correct communication, else wrong communication 00489 */ 00490 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd) 00491 { 00492 /* Call the Codec Mute function */ 00493 if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0) 00494 { 00495 return AUDIO_ERROR; 00496 } 00497 else 00498 { 00499 /* Return AUDIO_OK when all operations are correctly done */ 00500 return AUDIO_OK; 00501 } 00502 } 00503 00504 /** 00505 * @brief Switch dynamically (while audio file is played) the output target 00506 * (speaker or headphone). 00507 * @param Output: The audio output target: OUTPUT_DEVICE_SPEAKER, 00508 * OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH 00509 * @retval AUDIO_OK if correct communication, else wrong communication 00510 */ 00511 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output) 00512 { 00513 /* Call the Codec output device function */ 00514 if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0) 00515 { 00516 return AUDIO_ERROR; 00517 } 00518 else 00519 { 00520 /* Return AUDIO_OK when all operations are correctly done */ 00521 return AUDIO_OK; 00522 } 00523 } 00524 00525 /** 00526 * @brief Updates the audio frequency. 00527 * @param AudioFreq: Audio frequency used to play the audio stream. 00528 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00529 * audio frequency. 00530 * @retval None 00531 */ 00532 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq) 00533 { 00534 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00535 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00536 00537 /* Disable SAI peripheral to allow access to SAI internal registers */ 00538 __HAL_SAI_DISABLE(&haudio_out_sai); 00539 00540 /* Update the SAI audio frequency configuration */ 00541 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00542 HAL_SAI_Init(&haudio_out_sai); 00543 00544 /* Enable SAI peripheral to generate MCLK */ 00545 __HAL_SAI_ENABLE(&haudio_out_sai); 00546 } 00547 00548 /** 00549 * @brief Updates the Audio frame slot configuration. 00550 * @param AudioFrameSlot: specifies the audio Frame slot 00551 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00552 * audio frame slot. 00553 * @retval None 00554 */ 00555 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot) 00556 { 00557 /* Disable SAI peripheral to allow access to SAI internal registers */ 00558 __HAL_SAI_DISABLE(&haudio_out_sai); 00559 00560 /* Update the SAI audio frame slot configuration */ 00561 haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot; 00562 HAL_SAI_Init(&haudio_out_sai); 00563 00564 /* Enable SAI peripheral to generate MCLK */ 00565 __HAL_SAI_ENABLE(&haudio_out_sai); 00566 } 00567 00568 /** 00569 * @brief De-initializes the audio out peripheral. 00570 * @retval None 00571 */ 00572 void BSP_AUDIO_OUT_DeInit(void) 00573 { 00574 SAIx_Out_DeInit(); 00575 /* DeInit the SAI MSP : this __weak function can be rewritten by the application */ 00576 BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL); 00577 } 00578 00579 /** 00580 * @brief Tx Transfer completed callbacks. 00581 * @param hsai: SAI handle 00582 * @retval None 00583 */ 00584 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) 00585 { 00586 /* Manage the remaining file size and new address offset: This function 00587 should be coded by user (its prototype is already declared in stm32f769i_discovery_audio.h) */ 00588 BSP_AUDIO_OUT_TransferComplete_CallBack(); 00589 } 00590 00591 /** 00592 * @brief Tx Half Transfer completed callbacks. 00593 * @param hsai: SAI handle 00594 * @retval None 00595 */ 00596 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 00597 { 00598 /* Manage the remaining file size and new address offset: This function 00599 should be coded by user (its prototype is already declared in stm32f769i_discovery_audio.h) */ 00600 BSP_AUDIO_OUT_HalfTransfer_CallBack(); 00601 } 00602 00603 /** 00604 * @brief SAI error callbacks. 00605 * @param hsai: SAI handle 00606 * @retval None 00607 */ 00608 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 00609 { 00610 if(hsai->Instance == AUDIO_OUT_SAIx) 00611 { 00612 BSP_AUDIO_OUT_Error_CallBack(); 00613 } 00614 else 00615 { 00616 BSP_AUDIO_IN_Error_CallBack(); 00617 } 00618 } 00619 00620 /** 00621 * @brief Manages the DMA full Transfer complete event. 00622 * @retval None 00623 */ 00624 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void) 00625 { 00626 } 00627 00628 /** 00629 * @brief Manages the DMA Half Transfer complete event. 00630 * @retval None 00631 */ 00632 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) 00633 { 00634 } 00635 00636 /** 00637 * @brief Manages the DMA FIFO error event. 00638 * @retval None 00639 */ 00640 __weak void BSP_AUDIO_OUT_Error_CallBack(void) 00641 { 00642 } 00643 00644 /** 00645 * @brief Initializes BSP_AUDIO_OUT MSP. 00646 * @param hsai: SAI handle 00647 * @param Params 00648 * @retval None 00649 */ 00650 __weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params) 00651 { 00652 static DMA_HandleTypeDef hdma_sai_tx; 00653 GPIO_InitTypeDef gpio_init_structure; 00654 00655 /* Enable SAI clock */ 00656 AUDIO_OUT_SAIx_CLK_ENABLE(); 00657 00658 00659 /* Enable GPIO clock */ 00660 AUDIO_OUT_SAIx_MCLK_ENABLE(); 00661 AUDIO_OUT_SAIx_SD_FS_CLK_ENABLE(); 00662 00663 /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/ 00664 gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SD_PIN; 00665 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00666 gpio_init_structure.Pull = GPIO_NOPULL; 00667 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00668 gpio_init_structure.Alternate = AUDIO_OUT_SAIx_AF; 00669 HAL_GPIO_Init(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, &gpio_init_structure); 00670 00671 gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN; 00672 HAL_GPIO_Init(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, &gpio_init_structure); 00673 00674 /* Enable the DMA clock */ 00675 AUDIO_OUT_SAIx_DMAx_CLK_ENABLE(); 00676 00677 if(hsai->Instance == AUDIO_OUT_SAIx) 00678 { 00679 /* Configure the hdma_saiTx handle parameters */ 00680 hdma_sai_tx.Init.Channel = AUDIO_OUT_SAIx_DMAx_CHANNEL; 00681 hdma_sai_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; 00682 hdma_sai_tx.Init.PeriphInc = DMA_PINC_DISABLE; 00683 hdma_sai_tx.Init.MemInc = DMA_MINC_ENABLE; 00684 hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_OUT_SAIx_DMAx_PERIPH_DATA_SIZE; 00685 hdma_sai_tx.Init.MemDataAlignment = AUDIO_OUT_SAIx_DMAx_MEM_DATA_SIZE; 00686 hdma_sai_tx.Init.Mode = DMA_CIRCULAR; 00687 hdma_sai_tx.Init.Priority = DMA_PRIORITY_HIGH; 00688 hdma_sai_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; 00689 hdma_sai_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 00690 hdma_sai_tx.Init.MemBurst = DMA_MBURST_SINGLE; 00691 hdma_sai_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; 00692 00693 hdma_sai_tx.Instance = AUDIO_OUT_SAIx_DMAx_STREAM; 00694 00695 /* Associate the DMA handle */ 00696 __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx); 00697 00698 /* Deinitialize the Stream for new transfer */ 00699 HAL_DMA_DeInit(&hdma_sai_tx); 00700 00701 /* Configure the DMA Stream */ 00702 HAL_DMA_Init(&hdma_sai_tx); 00703 } 00704 00705 /* SAI DMA IRQ Channel configuration */ 00706 HAL_NVIC_SetPriority(AUDIO_OUT_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 00707 HAL_NVIC_EnableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ); 00708 } 00709 00710 /** 00711 * @brief Initializes SAI Audio IN MSP. 00712 * @param hsai: SAI handle 00713 * @param Params 00714 * @retval None 00715 */ 00716 static void SAI_AUDIO_IN_MspInit(SAI_HandleTypeDef *hsai, void *Params) 00717 { 00718 static DMA_HandleTypeDef hdma_sai_rx; 00719 GPIO_InitTypeDef gpio_init_structure; 00720 00721 /* Enable SAI clock */ 00722 AUDIO_IN_SAIx_CLK_ENABLE(); 00723 00724 /* Enable SD GPIO clock */ 00725 AUDIO_IN_SAIx_SD_ENABLE(); 00726 /* CODEC_SAI pin configuration: SD pin */ 00727 gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN; 00728 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00729 gpio_init_structure.Pull = GPIO_NOPULL; 00730 gpio_init_structure.Speed = GPIO_SPEED_FAST; 00731 gpio_init_structure.Alternate = AUDIO_IN_SAIx_AF; 00732 HAL_GPIO_Init(AUDIO_IN_SAIx_SD_GPIO_PORT, &gpio_init_structure); 00733 00734 /* Enable Audio INT GPIO clock */ 00735 AUDIO_IN_INT_GPIO_ENABLE(); 00736 /* Audio INT pin configuration: input */ 00737 gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN; 00738 gpio_init_structure.Mode = GPIO_MODE_INPUT; 00739 gpio_init_structure.Pull = GPIO_NOPULL; 00740 gpio_init_structure.Speed = GPIO_SPEED_FAST; 00741 HAL_GPIO_Init(AUDIO_IN_INT_GPIO_PORT, &gpio_init_structure); 00742 00743 /* Enable the DMA clock */ 00744 AUDIO_IN_SAIx_DMAx_CLK_ENABLE(); 00745 00746 if(hsai->Instance == AUDIO_IN_SAIx) 00747 { 00748 /* Configure the hdma_sai_rx handle parameters */ 00749 hdma_sai_rx.Init.Channel = AUDIO_IN_SAIx_DMAx_CHANNEL; 00750 hdma_sai_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; 00751 hdma_sai_rx.Init.PeriphInc = DMA_PINC_DISABLE; 00752 hdma_sai_rx.Init.MemInc = DMA_MINC_ENABLE; 00753 hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAIx_DMAx_PERIPH_DATA_SIZE; 00754 hdma_sai_rx.Init.MemDataAlignment = AUDIO_IN_SAIx_DMAx_MEM_DATA_SIZE; 00755 hdma_sai_rx.Init.Mode = DMA_CIRCULAR; 00756 hdma_sai_rx.Init.Priority = DMA_PRIORITY_HIGH; 00757 hdma_sai_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 00758 hdma_sai_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 00759 hdma_sai_rx.Init.MemBurst = DMA_MBURST_SINGLE; 00760 hdma_sai_rx.Init.PeriphBurst = DMA_MBURST_SINGLE; 00761 00762 hdma_sai_rx.Instance = AUDIO_IN_SAIx_DMAx_STREAM; 00763 00764 /* Associate the DMA handle */ 00765 __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx); 00766 00767 /* Deinitialize the Stream for new transfer */ 00768 HAL_DMA_DeInit(&hdma_sai_rx); 00769 00770 /* Configure the DMA Stream */ 00771 HAL_DMA_Init(&hdma_sai_rx); 00772 } 00773 00774 /* SAI DMA IRQ Channel configuration */ 00775 HAL_NVIC_SetPriority(AUDIO_IN_SAIx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 00776 HAL_NVIC_EnableIRQ(AUDIO_IN_SAIx_DMAx_IRQ); 00777 00778 /* Audio INT IRQ Channel configuration */ 00779 HAL_NVIC_SetPriority(AUDIO_IN_INT_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 00780 HAL_NVIC_EnableIRQ(AUDIO_IN_INT_IRQ); 00781 } 00782 00783 /** 00784 * @brief De-Initializes SAI Audio IN MSP. 00785 * @param hsai: SAI handle 00786 * @param Params 00787 * @retval None 00788 */ 00789 static void SAI_AUDIO_IN_MspDeInit(SAI_HandleTypeDef *hsai, void *Params) 00790 { 00791 GPIO_InitTypeDef gpio_init_structure; 00792 00793 /* SAI DMA IRQ Channel deactivation */ 00794 HAL_NVIC_DisableIRQ(AUDIO_IN_SAIx_DMAx_IRQ); 00795 00796 if(hsai->Instance == AUDIO_IN_SAIx) 00797 { 00798 /* Deinitialize the DMA stream */ 00799 HAL_DMA_DeInit(hsai->hdmatx); 00800 } 00801 00802 /* Disable SAI peripheral */ 00803 __HAL_SAI_DISABLE(hsai); 00804 00805 /* Deactivates CODEC_SAI pin SD by putting them in input mode */ 00806 gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN; 00807 HAL_GPIO_DeInit(AUDIO_IN_SAIx_SD_GPIO_PORT, gpio_init_structure.Pin); 00808 00809 gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN; 00810 HAL_GPIO_DeInit(AUDIO_IN_INT_GPIO_PORT, gpio_init_structure.Pin); 00811 00812 /* Disable SAI clock */ 00813 AUDIO_IN_SAIx_CLK_DISABLE(); 00814 } 00815 00816 /** 00817 * @brief Deinitializes SAI MSP. 00818 * @param hsai: SAI handle 00819 * @param Params 00820 * @retval None 00821 */ 00822 __weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params) 00823 { 00824 GPIO_InitTypeDef gpio_init_structure; 00825 00826 /* SAI DMA IRQ Channel deactivation */ 00827 HAL_NVIC_DisableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ); 00828 00829 if(hsai->Instance == AUDIO_OUT_SAIx) 00830 { 00831 /* Deinitialize the DMA stream */ 00832 HAL_DMA_DeInit(hsai->hdmatx); 00833 } 00834 00835 /* Disable SAI peripheral */ 00836 __HAL_SAI_DISABLE(hsai); 00837 00838 /* Deactivates CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */ 00839 gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SD_PIN; 00840 HAL_GPIO_DeInit(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, gpio_init_structure.Pin); 00841 00842 gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN; 00843 HAL_GPIO_DeInit(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin); 00844 00845 /* Disable SAI clock */ 00846 AUDIO_OUT_SAIx_CLK_DISABLE(); 00847 00848 /* GPIO pins clock and DMA clock can be shut down in the applic 00849 by surcharging this __weak function */ 00850 } 00851 00852 /** 00853 * @brief Clock Config. 00854 * @param hsai: might be required to set audio peripheral predivider if any. 00855 * @param AudioFreq: Audio frequency used to play the audio stream. 00856 * @param Params 00857 * @note This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency() 00858 * Being __weak it can be overwritten by the application 00859 * @retval None 00860 */ 00861 __weak void BSP_AUDIO_OUT_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params) 00862 { 00863 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 00864 00865 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 00866 00867 /* Set the PLL configuration according to the audio frequency */ 00868 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 00869 { 00870 /* Configure PLLSAI prescalers */ 00871 /* PLLSAI_VCO: VCO_429M 00872 SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 429/2 = 214.5 Mhz 00873 SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 214.5/19 = 11.289 Mhz */ 00874 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 00875 rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLI2S; 00876 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429; 00877 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2; 00878 rcc_ex_clk_init_struct.PLLI2SDivQ = 19; 00879 00880 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00881 00882 } 00883 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 00884 { 00885 /* SAI clock config 00886 PLLSAI_VCO: VCO_344M 00887 SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 344/7 = 49.142 Mhz 00888 SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 49.142/1 = 49.142 Mhz */ 00889 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 00890 rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLI2S; 00891 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 00892 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 00893 rcc_ex_clk_init_struct.PLLI2SDivQ = 1; 00894 00895 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00896 } 00897 } 00898 00899 /******************************************************************************* 00900 Static Functions 00901 *******************************************************************************/ 00902 00903 /** 00904 * @brief Initializes the Audio Codec audio interface (SAI). 00905 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00906 * @note The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 00907 * and user can update this configuration using 00908 * @retval None 00909 */ 00910 static void SAIx_Out_Init(uint32_t AudioFreq) 00911 { 00912 /* Initialize the haudio_out_sai Instance parameter */ 00913 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00914 00915 /* Disable SAI peripheral to allow access to SAI internal registers */ 00916 __HAL_SAI_DISABLE(&haudio_out_sai); 00917 00918 /* Configure SAI_Block_x 00919 LSBFirst: Disabled 00920 DataSize: 16 */ 00921 haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE; 00922 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00923 haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX; 00924 haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED; 00925 haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL; 00926 haudio_out_sai.Init.DataSize = SAI_DATASIZE_16; 00927 haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 00928 haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 00929 haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS; 00930 haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLED; 00931 haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 00932 haudio_out_sai.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 00933 haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING; 00934 haudio_out_sai.Init.TriState = SAI_OUTPUT_NOTRELEASED; 00935 haudio_out_sai.Init.Mckdiv = 0; 00936 00937 /* Configure SAI_Block_x Frame 00938 Frame Length: 64 00939 Frame active Length: 32 00940 FS Definition: Start frame + Channel Side identification 00941 FS Polarity: FS active Low 00942 FS Offset: FS asserted one bit before the first bit of slot 0 */ 00943 haudio_out_sai.FrameInit.FrameLength = 128; 00944 haudio_out_sai.FrameInit.ActiveFrameLength = 64; 00945 haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 00946 haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 00947 haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 00948 00949 /* Configure SAI Block_x Slot 00950 Slot First Bit Offset: 0 00951 Slot Size : 16 00952 Slot Number: 4 00953 Slot Active: All slot actives */ 00954 haudio_out_sai.SlotInit.FirstBitOffset = 0; 00955 haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 00956 haudio_out_sai.SlotInit.SlotNumber = 4; 00957 haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123; 00958 00959 HAL_SAI_Init(&haudio_out_sai); 00960 00961 /* Enable SAI peripheral to generate MCLK */ 00962 __HAL_SAI_ENABLE(&haudio_out_sai); 00963 } 00964 00965 /** 00966 * @brief Deinitializes the Audio Codec audio interface (SAI). 00967 * @retval None 00968 */ 00969 static void SAIx_Out_DeInit(void) 00970 { 00971 /* Initialize the haudio_out_sai Instance parameter */ 00972 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00973 00974 /* Disable SAI peripheral */ 00975 __HAL_SAI_DISABLE(&haudio_out_sai); 00976 00977 HAL_SAI_DeInit(&haudio_out_sai); 00978 } 00979 00980 /** 00981 * @brief Initializes the Audio Codec audio interface (SAI). 00982 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00983 * @note The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 00984 * and user can update this configuration using 00985 * @retval None 00986 */ 00987 static void SAIx_In_Init(uint32_t AudioFreq) 00988 { 00989 /* Initialize SAI1 block A in MASTER TX */ 00990 /* Initialize the haudio_out_sai Instance parameter */ 00991 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00992 00993 /* Disable SAI peripheral to allow access to SAI internal registers */ 00994 __HAL_SAI_DISABLE(&haudio_out_sai); 00995 00996 /* Configure SAI_Block_x 00997 LSBFirst: Disabled 00998 DataSize: 16 */ 00999 haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE; 01000 haudio_out_sai.Init.AudioFrequency = AudioFreq; 01001 haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_RX; 01002 haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; 01003 haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL; 01004 haudio_out_sai.Init.DataSize = SAI_DATASIZE_16; 01005 haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 01006 haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; 01007 haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS; 01008 haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE; 01009 haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 01010 haudio_out_sai.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 01011 haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING; 01012 haudio_out_sai.Init.TriState = SAI_OUTPUT_NOTRELEASED; 01013 haudio_out_sai.Init.Mckdiv = 0; 01014 01015 /* Configure SAI_Block_x Frame 01016 Frame Length: 64 01017 Frame active Length: 32 01018 FS Definition: Start frame + Channel Side identification 01019 FS Polarity: FS active Low 01020 FS Offset: FS asserted one bit before the first bit of slot 0 */ 01021 haudio_out_sai.FrameInit.FrameLength = 64; 01022 haudio_out_sai.FrameInit.ActiveFrameLength = 32; 01023 haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 01024 haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 01025 haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 01026 01027 /* Configure SAI Block_x Slot 01028 Slot First Bit Offset: 0 01029 Slot Size : 16 01030 Slot Number: 4 01031 Slot Active: All slot actives */ 01032 haudio_out_sai.SlotInit.FirstBitOffset = 0; 01033 haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 01034 haudio_out_sai.SlotInit.SlotNumber = 4; 01035 haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_02; 01036 01037 HAL_SAI_Init(&haudio_out_sai); 01038 01039 /* Initialize SAI1 block B in SLAVE RX synchronous from SAI1 block A */ 01040 /* Initialize the haudio_in_sai Instance parameter */ 01041 haudio_in_sai.Instance = AUDIO_IN_SAIx; 01042 01043 /* Disable SAI peripheral to allow access to SAI internal registers */ 01044 __HAL_SAI_DISABLE(&haudio_in_sai); 01045 01046 /* Configure SAI_Block_x 01047 LSBFirst: Disabled 01048 DataSize: 16 */ 01049 haudio_in_sai.Init.MonoStereoMode = SAI_STEREOMODE; 01050 haudio_in_sai.Init.AudioFrequency = AudioFreq; 01051 haudio_in_sai.Init.AudioMode = SAI_MODESLAVE_RX; 01052 haudio_in_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; 01053 haudio_in_sai.Init.Protocol = SAI_FREE_PROTOCOL; 01054 haudio_in_sai.Init.DataSize = SAI_DATASIZE_16; 01055 haudio_in_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 01056 haudio_in_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 01057 haudio_in_sai.Init.Synchro = SAI_SYNCHRONOUS; 01058 haudio_in_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE; 01059 haudio_in_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 01060 haudio_in_sai.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 01061 haudio_in_sai.Init.CompandingMode = SAI_NOCOMPANDING; 01062 haudio_in_sai.Init.TriState = SAI_OUTPUT_RELEASED; 01063 haudio_in_sai.Init.Mckdiv = 0; 01064 01065 /* Configure SAI_Block_x Frame 01066 Frame Length: 64 01067 Frame active Length: 32 01068 FS Definition: Start frame + Channel Side identification 01069 FS Polarity: FS active Low 01070 FS Offset: FS asserted one bit before the first bit of slot 0 */ 01071 haudio_in_sai.FrameInit.FrameLength = 64; 01072 haudio_in_sai.FrameInit.ActiveFrameLength = 32; 01073 haudio_in_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 01074 haudio_in_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 01075 haudio_in_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 01076 01077 /* Configure SAI Block_x Slot 01078 Slot First Bit Offset: 0 01079 Slot Size : 16 01080 Slot Number: 4 01081 Slot Active: All slot active */ 01082 haudio_in_sai.SlotInit.FirstBitOffset = 0; 01083 haudio_in_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 01084 haudio_in_sai.SlotInit.SlotNumber = 4; 01085 haudio_in_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_02; 01086 01087 HAL_SAI_Init(&haudio_in_sai); 01088 01089 /* Enable SAI peripheral */ 01090 __HAL_SAI_ENABLE(&haudio_in_sai); 01091 01092 /* Enable SAI peripheral to generate MCLK */ 01093 __HAL_SAI_ENABLE(&haudio_out_sai); 01094 } 01095 01096 /** 01097 * @brief Deinitializes the output Audio Codec audio interface (SAI). 01098 * @retval None 01099 */ 01100 static void SAIx_In_DeInit(void) 01101 { 01102 /* Initialize the haudio_in_sai Instance parameter */ 01103 haudio_in_sai.Instance = AUDIO_IN_SAIx; 01104 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 01105 /* Disable SAI peripheral */ 01106 __HAL_SAI_DISABLE(&haudio_in_sai); 01107 01108 HAL_SAI_DeInit(&haudio_in_sai); 01109 HAL_SAI_DeInit(&haudio_out_sai); 01110 } 01111 01112 /** 01113 * @} 01114 */ 01115 01116 /** @defgroup STM32F769I_DISCOVERY_AUDIO_In_Private_Functions STM32F769I_DISCOVERY_AUDIO_In Private Functions 01117 * @{ 01118 */ 01119 01120 /** 01121 * @brief Initialize wave recording. 01122 * @param AudioFreq: Audio frequency to be configured for the DFSDM peripheral. 01123 * @param BitRes: Audio frequency to be configured for the DFSDM peripheral. 01124 * @param ChnlNbr: Audio frequency to be configured for the DFSDM peripheral. 01125 * @retval AUDIO_OK if correct communication, else wrong communication 01126 */ 01127 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 01128 { 01129 return BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC, AudioFreq, BitRes, ChnlNbr); 01130 } 01131 01132 /** 01133 * @brief Initialize wave recording. 01134 * @param InputDevice: INPUT_DEVICE_DIGITAL_MIC or INPUT_DEVICE_ANALOG_MIC. 01135 * @param AudioFreq: Audio frequency to be configured. 01136 * @param BitRes: Audio bit resolution to be configured.. 01137 * @param ChnlNbr: Number of channel to be configured. 01138 * @retval AUDIO_OK if correct communication, else wrong communication 01139 */ 01140 uint8_t BSP_AUDIO_IN_InitEx(uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 01141 { 01142 uint8_t ret = AUDIO_ERROR; 01143 AudioIn_Device = InputDevice; 01144 01145 if(InputDevice == INPUT_DEVICE_DIGITAL_MIC) 01146 { 01147 AudioIn_ChannelNumber = ChnlNbr; 01148 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 01149 BSP_AUDIO_IN_ClockConfig(&hAudioInTopLeftFilter, AudioFreq, NULL); 01150 01151 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 01152 BSP_AUDIO_IN_MspInit(); 01153 01154 /* Initializes DFSDM peripheral */ 01155 DFSDMx_Init(AudioFreq); 01156 ret = AUDIO_OK; 01157 } 01158 else 01159 { 01160 /* Disable SAI */ 01161 SAIx_In_DeInit(); 01162 01163 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 01164 BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL); 01165 01166 haudio_in_sai.Instance = AUDIO_IN_SAIx; 01167 if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET) 01168 { 01169 BSP_AUDIO_OUT_MspInit(&haudio_in_sai, NULL); 01170 BSP_AUDIO_IN_MspInit(); 01171 } 01172 01173 SAIx_In_Init(AudioFreq); 01174 01175 if((wm8994_drv.ReadID(AUDIO_I2C_ADDRESS)) == WM8994_ID) 01176 { 01177 /* Reset the Codec Registers */ 01178 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 01179 /* Initialize the audio driver structure */ 01180 audio_drv = &wm8994_drv; 01181 ret = AUDIO_OK; 01182 } 01183 else 01184 { 01185 ret = AUDIO_ERROR; 01186 } 01187 01188 if(ret == AUDIO_OK) 01189 { 01190 /* Initialize the codec internal registers */ 01191 audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice, 100, AudioFreq); 01192 } 01193 } 01194 01195 /* Return AUDIO_OK when all operations are correctly done */ 01196 return ret; 01197 } 01198 01199 /** 01200 * @brief Allocate channel buffer scratch 01201 * @param pScratch : pointer to scratch tables. 01202 * @param size of scratch buffer 01203 */ 01204 uint8_t BSP_AUDIO_IN_AllocScratch (int32_t *pScratch, uint32_t size) 01205 { 01206 uint32_t idx; 01207 01208 ScratchSize = (size / AudioIn_ChannelNumber); 01209 01210 /* copy scratch pointers */ 01211 for (idx = 0; idx < AudioIn_ChannelNumber; idx++) 01212 { 01213 pScratchBuff[idx] = (int32_t *)(pScratch + (idx * ScratchSize)); 01214 } 01215 /* Return AUDIO_OK */ 01216 return AUDIO_OK; 01217 } 01218 01219 /** 01220 * @brief Return audio in channel number 01221 * @retval Number of channel 01222 */ 01223 uint8_t BSP_AUDIO_IN_GetChannelNumber(void) 01224 { 01225 return AudioIn_ChannelNumber; 01226 } 01227 01228 /** 01229 * @brief Start audio recording. 01230 * @param pbuf: Main buffer pointer for the recorded data storing 01231 * @param size: Current size of the recorded buffer 01232 * @retval AUDIO_OK if correct communication, else wrong communication 01233 */ 01234 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size) 01235 { 01236 if (AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC) 01237 { 01238 hAudioIn.pRecBuf = pbuf; 01239 hAudioIn.RecSize = size; 01240 /* Reset Application Buffer Trigger */ 01241 AppBuffTrigger = 0; 01242 AppBuffHalf = 0; 01243 01244 if(AudioIn_ChannelNumber > 2) 01245 { 01246 /* Call the Media layer start function for buttom right channel */ 01247 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInButtomRightFilter, pScratchBuff[2], ScratchSize)) 01248 { 01249 return AUDIO_ERROR; 01250 } 01251 01252 /* Call the Media layer start function for buttom left channel */ 01253 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInButtomLeftFilter, pScratchBuff[3], ScratchSize)) 01254 { 01255 return AUDIO_ERROR; 01256 } 01257 } 01258 01259 /* Call the Media layer start function for top right channel */ 01260 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInTopRightFilter, pScratchBuff[0], ScratchSize)) 01261 { 01262 return AUDIO_ERROR; 01263 } 01264 01265 /* Call the Media layer start function for top left channel */ 01266 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInTopLeftFilter, pScratchBuff[1], ScratchSize)) 01267 { 01268 return AUDIO_ERROR; 01269 } 01270 } 01271 else 01272 { 01273 /* Start the process receive DMA */ 01274 if(HAL_OK !=HAL_SAI_Receive_DMA(&haudio_in_sai, (uint8_t*)pbuf, size)) 01275 { 01276 return AUDIO_ERROR; 01277 } 01278 } 01279 /* Return AUDIO_OK when all operations are correctly done */ 01280 return AUDIO_OK; 01281 } 01282 01283 /** 01284 * @brief Stop audio recording. 01285 * @retval AUDIO_OK if correct communication, else wrong communication 01286 */ 01287 uint8_t BSP_AUDIO_IN_Stop(void) 01288 { 01289 if (AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC) 01290 { 01291 AppBuffTrigger = 0; 01292 AppBuffHalf = 0; 01293 01294 if(AudioIn_ChannelNumber > 2) 01295 { 01296 /* Call the Media layer stop function for buttom right channel */ 01297 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInButtomRightFilter)) 01298 { 01299 return AUDIO_ERROR; 01300 } 01301 01302 /* Call the Media layer stop function for buttom left channel */ 01303 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInButtomLeftFilter)) 01304 { 01305 return AUDIO_ERROR; 01306 } 01307 } 01308 01309 /* Call the Media layer stop function for top right channel */ 01310 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInTopRightFilter)) 01311 { 01312 return AUDIO_ERROR; 01313 } 01314 01315 /* Call the Media layer stop function for top left channel */ 01316 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInTopLeftFilter)) 01317 { 01318 return AUDIO_ERROR; 01319 } 01320 } 01321 else 01322 { 01323 /* Call the Media layer stop function */ 01324 HAL_SAI_DMAStop(&haudio_in_sai); 01325 01326 /* Call Audio Codec Stop function */ 01327 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, CODEC_PDWN_HW) != 0) 01328 { 01329 return AUDIO_ERROR; 01330 } 01331 else 01332 { 01333 /* Wait at least 100us */ 01334 HAL_Delay(1); 01335 01336 /* Return AUDIO_OK when all operations are correctly done */ 01337 return AUDIO_OK; 01338 } 01339 } 01340 /* Return AUDIO_OK when all operations are correctly done */ 01341 return AUDIO_OK; 01342 } 01343 01344 /** 01345 * @brief Pause the audio file stream. 01346 * @retval AUDIO_OK if correct communication, else wrong communication 01347 */ 01348 uint8_t BSP_AUDIO_IN_Pause(void) 01349 { 01350 if(AudioIn_ChannelNumber > 2) 01351 { 01352 /* Call the Media layer stop function */ 01353 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInButtomRightFilter)) 01354 { 01355 return AUDIO_ERROR; 01356 } 01357 01358 /* Call the Media layer stop function */ 01359 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInButtomLeftFilter)) 01360 { 01361 return AUDIO_ERROR; 01362 } 01363 } 01364 /* Call the Media layer stop function */ 01365 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInTopRightFilter)) 01366 { 01367 return AUDIO_ERROR; 01368 } 01369 01370 /* Call the Media layer stop function */ 01371 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInTopLeftFilter)) 01372 { 01373 return AUDIO_ERROR; 01374 } 01375 01376 /* Return AUDIO_OK when all operations are correctly done */ 01377 return AUDIO_OK; 01378 } 01379 01380 /** 01381 * @brief Resume the audio file stream. 01382 * @retval AUDIO_OK if correct communication, else wrong communication 01383 */ 01384 uint8_t BSP_AUDIO_IN_Resume(void) 01385 { 01386 if(AudioIn_ChannelNumber > 2) 01387 { 01388 /* Call the Media layer start function for buttom right channel */ 01389 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInButtomRightFilter, pScratchBuff[2], ScratchSize)) 01390 { 01391 return AUDIO_ERROR; 01392 } 01393 01394 /* Call the Media layer start function for buttom left channel */ 01395 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInButtomLeftFilter, pScratchBuff[3], ScratchSize)) 01396 { 01397 return AUDIO_ERROR; 01398 } 01399 } 01400 /* Call the Media layer start function for top right channel */ 01401 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInTopRightFilter, pScratchBuff[0], ScratchSize)) 01402 { 01403 return AUDIO_ERROR; 01404 } 01405 01406 /* Call the Media layer start function for top left channel */ 01407 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInTopLeftFilter, pScratchBuff[1], ScratchSize)) 01408 { 01409 return AUDIO_ERROR; 01410 } 01411 01412 /* Return AUDIO_OK when all operations are correctly done */ 01413 return AUDIO_OK; 01414 } 01415 01416 /** 01417 * @brief Deinit the audio IN peripherals. 01418 * @retval None 01419 */ 01420 void BSP_AUDIO_IN_DeInit(void) 01421 { 01422 BSP_AUDIO_IN_MspDeInit(); 01423 01424 if(AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC) 01425 { 01426 DFSDMx_DeInit(); 01427 } 01428 else 01429 { 01430 SAIx_In_DeInit(); 01431 } 01432 } 01433 01434 /** 01435 * @brief Regular conversion complete callback. 01436 * @note In interrupt mode, user has to read conversion value in this function 01437 using HAL_DFSDM_FilterGetRegularValue. 01438 * @param hdfsdm_filter : DFSDM filter handle. 01439 * @retval None 01440 */ 01441 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01442 { 01443 int32_t index = 0; 01444 01445 if(hdfsdm_filter == &hAudioInTopLeftFilter) 01446 { 01447 DmaTopLeftRecCplt = 1; 01448 } 01449 else if(hdfsdm_filter == &hAudioInTopRightFilter) 01450 { 01451 DmaTopRightRecCplt = 1; 01452 } 01453 else if(hdfsdm_filter == &hAudioInButtomLeftFilter) 01454 { 01455 DmaButtomLeftRecCplt = 1; 01456 } 01457 else 01458 { 01459 DmaButtomRightRecCplt = 1; 01460 } 01461 01462 if(AudioIn_ChannelNumber > 2) 01463 { 01464 if((DmaTopLeftRecCplt == 1) && (DmaTopRightRecCplt == 1) && (DmaButtomLeftRecCplt == 1) && (DmaButtomRightRecCplt == 1)) 01465 { 01466 for(index = (ScratchSize/2) ; index < ScratchSize; index++) 01467 { 01468 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760)); 01469 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760)); 01470 hAudioIn.pRecBuf[AppBuffTrigger + 2] = (uint16_t)(SaturaLH((pScratchBuff[3][index] >> 8), -32760, 32760)); 01471 hAudioIn.pRecBuf[AppBuffTrigger + 3] = (uint16_t)(SaturaLH((pScratchBuff[2][index] >> 8), -32760, 32760)); 01472 AppBuffTrigger +=4; 01473 } 01474 DmaTopLeftRecCplt = 0; 01475 DmaTopRightRecCplt = 0; 01476 DmaButtomLeftRecCplt = 0; 01477 DmaButtomRightRecCplt = 0; 01478 } 01479 } 01480 else 01481 { 01482 if((DmaTopLeftRecCplt == 1) && (DmaTopRightRecCplt == 1)) 01483 { 01484 for(index = (ScratchSize/2) ; index < ScratchSize; index++) 01485 { 01486 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760)); 01487 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760)); 01488 AppBuffTrigger +=2; 01489 } 01490 DmaTopLeftRecCplt = 0; 01491 DmaTopRightRecCplt = 0; 01492 } 01493 } 01494 01495 /* Call Half Transfer Complete callback */ 01496 if((AppBuffTrigger == hAudioIn.RecSize/2) && (AppBuffHalf == 0)) 01497 { 01498 AppBuffHalf = 1; 01499 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01500 } 01501 /* Call Transfer Complete callback */ 01502 if(AppBuffTrigger == hAudioIn.RecSize) 01503 { 01504 /* Reset Application Buffer Trigger */ 01505 AppBuffTrigger = 0; 01506 AppBuffHalf = 0; 01507 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01508 BSP_AUDIO_IN_TransferComplete_CallBack(); 01509 } 01510 } 01511 01512 /** 01513 * @brief Half regular conversion complete callback. 01514 * @param hdfsdm_filter : DFSDM filter handle. 01515 * @retval None 01516 */ 01517 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01518 { 01519 int32_t index = 0; 01520 01521 if(hdfsdm_filter == &hAudioInTopLeftFilter) 01522 { 01523 DmaTopLeftRecHalfCplt = 1; 01524 } 01525 else if(hdfsdm_filter == &hAudioInTopRightFilter) 01526 { 01527 DmaTopRightRecHalfCplt = 1; 01528 } 01529 else if(hdfsdm_filter == &hAudioInButtomLeftFilter) 01530 { 01531 DmaButtomLeftRecHalfCplt = 1; 01532 } 01533 else 01534 { 01535 DmaButtomRightRecHalfCplt = 1; 01536 } 01537 01538 if(AudioIn_ChannelNumber > 2) 01539 { 01540 if((DmaTopLeftRecHalfCplt == 1) && (DmaTopRightRecHalfCplt == 1) && (DmaButtomLeftRecHalfCplt == 1) && (DmaButtomRightRecHalfCplt == 1)) 01541 { 01542 for(index = 0 ; index < ScratchSize/2; index++) 01543 { 01544 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760)); 01545 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760)); 01546 hAudioIn.pRecBuf[AppBuffTrigger + 2] = (uint16_t)(SaturaLH((pScratchBuff[3][index] >> 8), -32760, 32760)); 01547 hAudioIn.pRecBuf[AppBuffTrigger + 3] = (uint16_t)(SaturaLH((pScratchBuff[2][index] >> 8), -32760, 32760)); 01548 AppBuffTrigger +=4; 01549 } 01550 DmaTopLeftRecHalfCplt = 0; 01551 DmaTopRightRecHalfCplt = 0; 01552 DmaButtomLeftRecHalfCplt = 0; 01553 DmaButtomRightRecHalfCplt = 0; 01554 } 01555 } 01556 else 01557 { 01558 if((DmaTopLeftRecHalfCplt == 1) && (DmaTopRightRecHalfCplt == 1)) 01559 { 01560 for(index = 0 ; index < ScratchSize/2; index++) 01561 { 01562 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760)); 01563 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760)); 01564 AppBuffTrigger +=2; 01565 } 01566 DmaTopLeftRecHalfCplt = 0; 01567 DmaTopRightRecHalfCplt = 0; 01568 } 01569 } 01570 01571 /* Call Half Transfer Complete callback */ 01572 if((AppBuffTrigger == hAudioIn.RecSize/2) && (AppBuffHalf == 0)) 01573 { 01574 AppBuffHalf = 1; 01575 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01576 } 01577 /* Call Transfer Complete callback */ 01578 if(AppBuffTrigger == hAudioIn.RecSize) 01579 { 01580 /* Reset Application Buffer Trigger */ 01581 AppBuffTrigger = 0; 01582 AppBuffHalf = 0; 01583 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01584 BSP_AUDIO_IN_TransferComplete_CallBack(); 01585 } 01586 } 01587 01588 /** 01589 * @brief Half reception complete callback. 01590 * @param hsai : SAI handle. 01591 * @retval None 01592 */ 01593 void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai) 01594 { 01595 /* Manage the remaining file size and new address offset: This function 01596 should be coded by user (its prototype is already declared in stm32769i_discovery_audio.h) */ 01597 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01598 } 01599 01600 /** 01601 * @brief Reception complete callback. 01602 * @param hsai : SAI handle. 01603 * @retval None 01604 */ 01605 void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai) 01606 { 01607 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01608 BSP_AUDIO_IN_TransferComplete_CallBack(); 01609 } 01610 01611 /** 01612 * @brief User callback when record buffer is filled. 01613 * @retval None 01614 */ 01615 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void) 01616 { 01617 /* This function should be implemented by the user application. 01618 It is called into this driver when the current buffer is filled 01619 to prepare the next buffer pointer and its size. */ 01620 } 01621 01622 /** 01623 * @brief Manages the DMA Half Transfer complete event. 01624 * @retval None 01625 */ 01626 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 01627 { 01628 /* This function should be implemented by the user application. 01629 It is called into this driver when the current buffer is filled 01630 to prepare the next buffer pointer and its size. */ 01631 } 01632 01633 /** 01634 * @brief Audio IN Error callback function. 01635 * @retval None 01636 */ 01637 __weak void BSP_AUDIO_IN_Error_CallBack(void) 01638 { 01639 /* This function is called when an Interrupt due to transfer error on or peripheral 01640 error occurs. */ 01641 } 01642 01643 /** 01644 * @brief Initialize BSP_AUDIO_IN MSP. 01645 * @retval None 01646 */ 01647 __weak void BSP_AUDIO_IN_MspInit(void) 01648 { 01649 if (AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC) 01650 { 01651 /* MSP channels initialization */ 01652 DFSDMx_ChannelMspInit(); 01653 /* MSP filters initialization */ 01654 DFSDMx_FilterMspInit(); 01655 } 01656 else 01657 { 01658 SAI_AUDIO_IN_MspInit(&haudio_in_sai, NULL); 01659 } 01660 } 01661 01662 /** 01663 * @brief DeInitialize BSP_AUDIO_IN MSP. 01664 * @retval None 01665 */ 01666 __weak void BSP_AUDIO_IN_MspDeInit(void) 01667 { 01668 if (AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC) 01669 { 01670 /* MSP channels initialization */ 01671 DFSDMx_ChannelMspDeInit(); 01672 /* MSP filters initialization */ 01673 DFSDMx_FilterMspDeInit(); 01674 } 01675 else 01676 { 01677 SAI_AUDIO_IN_MspDeInit(&haudio_in_sai, NULL); 01678 } 01679 } 01680 01681 /** 01682 * @brief Clock Config. 01683 * @param hdfsdm_filter: might be required to set audio peripheral predivider if any. 01684 * @param AudioFreq: Audio frequency used to play the audio stream. 01685 * @param Params 01686 * @note This API is called by BSP_AUDIO_IN_Init() 01687 * Being __weak it can be overwritten by the application 01688 * @retval None 01689 */ 01690 __weak void BSP_AUDIO_IN_ClockConfig(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, uint32_t AudioFreq, void *Params) 01691 { 01692 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 01693 01694 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 01695 01696 /* Set the PLL configuration according to the audio frequency */ 01697 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 01698 { 01699 /* Configure PLLSAI prescalers */ 01700 /* PLLI2S_VCO: VCO_429M 01701 SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 429/2 = 214.5 Mhz 01702 SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 214.5/19 = 11.289 Mhz */ 01703 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 01704 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S; 01705 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429; 01706 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2; 01707 rcc_ex_clk_init_struct.PLLI2SDivQ = 19; 01708 01709 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01710 01711 } 01712 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_32K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 01713 { 01714 /* SAI clock config 01715 PLLI2S_VCO: VCO_344M 01716 SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 344/7 = 49.142 Mhz 01717 SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 49.142/1 = 49.142 Mhz */ 01718 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 01719 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S; 01720 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 01721 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 01722 rcc_ex_clk_init_struct.PLLI2SDivQ = 1; 01723 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01724 } 01725 01726 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_DFSDM1_AUDIO; 01727 rcc_ex_clk_init_struct.Dfsdm1AudioClockSelection = RCC_DFSDM1AUDIOCLKSOURCE_SAI2; 01728 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01729 } 01730 01731 /******************************************************************************* 01732 Static Functions 01733 *******************************************************************************/ 01734 /** 01735 * @brief Initialize the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01736 * @param AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral. 01737 * @note Channel output Clock Divider and Filter Oversampling are calculated as follow: 01738 * - Clock_Divider = CLK(input DFSDM)/CLK(micro) with 01739 * 1MHZ < CLK(micro) < 3.2MHZ (TYP 2.4MHZ for MP34DT01TR) 01740 * - Oversampling = CLK(input DFSDM)/(Clock_Divider * AudioFreq) 01741 * @retval AUDIO_OK if correct communication, else wrong communication 01742 */ 01743 static uint8_t DFSDMx_Init(uint32_t AudioFreq) 01744 { 01745 /****************************************************************************/ 01746 /********************** Channels configuration *****************************/ 01747 /****************************************************************************/ 01748 /* CHANNEL 1 configuration */ 01749 __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInTopLeftChannel); 01750 hAudioInTopLeftChannel.Instance = DFSDM1_Channel1; 01751 hAudioInTopLeftChannel.Init.OutputClock.Activation = ENABLE; 01752 hAudioInTopLeftChannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01753 /* Set the DFSDM clock OUT audio frequency configuration */ 01754 hAudioInTopLeftChannel.Init.OutputClock.Divider = DFSDM_CLOCK_DIVIDER(AudioFreq); 01755 hAudioInTopLeftChannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01756 hAudioInTopLeftChannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01757 hAudioInTopLeftChannel.Init.Input.Pins = DFSDM_CHANNEL_SAME_CHANNEL_PINS; 01758 /* Request to sample stable data for LEFT micro on Rising edge */ 01759 hAudioInTopLeftChannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_RISING; 01760 hAudioInTopLeftChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01761 hAudioInTopLeftChannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER; 01762 hAudioInTopLeftChannel.Init.Awd.Oversampling = 10; 01763 hAudioInTopLeftChannel.Init.Offset = 0; 01764 hAudioInTopLeftChannel.Init.RightBitShift = DFSDM_RIGHT_BIT_SHIFT(AudioFreq); 01765 if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInTopLeftChannel)) 01766 { 01767 return AUDIO_ERROR; 01768 } 01769 01770 /* CHANNEL 0 configuration */ 01771 __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInTopRightChannel); 01772 hAudioInTopRightChannel.Instance = DFSDM1_Channel0; 01773 hAudioInTopRightChannel.Init.OutputClock.Activation = ENABLE; 01774 hAudioInTopRightChannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01775 /* Set the DFSDM clock OUT audio frequency configuration */ 01776 hAudioInTopRightChannel.Init.OutputClock.Divider = DFSDM_CLOCK_DIVIDER(AudioFreq); 01777 hAudioInTopRightChannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01778 hAudioInTopRightChannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01779 hAudioInTopRightChannel.Init.Input.Pins = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS; 01780 /* Request to sample stable data for RIGHT micro on Falling edge */ 01781 hAudioInTopRightChannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_FALLING; 01782 hAudioInTopRightChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01783 hAudioInTopRightChannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER; 01784 hAudioInTopRightChannel.Init.Awd.Oversampling = 10; 01785 hAudioInTopRightChannel.Init.Offset = 0; 01786 hAudioInTopRightChannel.Init.RightBitShift = DFSDM_RIGHT_BIT_SHIFT(AudioFreq); 01787 if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInTopRightChannel)) 01788 { 01789 return AUDIO_ERROR; 01790 } 01791 01792 if(AudioIn_ChannelNumber > 2) 01793 { 01794 /* CHANNEL 5 configuration */ 01795 __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInButtomLeftChannel); 01796 hAudioInButtomLeftChannel.Instance = DFSDM1_Channel5; 01797 hAudioInButtomLeftChannel.Init.OutputClock.Activation = ENABLE; 01798 hAudioInButtomLeftChannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01799 /* Set the DFSDM clock OUT audio frequency configuration */ 01800 hAudioInButtomLeftChannel.Init.OutputClock.Divider = DFSDM_CLOCK_DIVIDER(AudioFreq); 01801 hAudioInButtomLeftChannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01802 hAudioInButtomLeftChannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01803 hAudioInButtomLeftChannel.Init.Input.Pins = DFSDM_CHANNEL_SAME_CHANNEL_PINS; 01804 /* Request to sample stable data for LEFT micro on Rising edge */ 01805 hAudioInButtomLeftChannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_RISING; 01806 hAudioInButtomLeftChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01807 hAudioInButtomLeftChannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER; 01808 hAudioInButtomLeftChannel.Init.Awd.Oversampling = 10; 01809 hAudioInButtomLeftChannel.Init.Offset = 0; 01810 hAudioInButtomLeftChannel.Init.RightBitShift = DFSDM_RIGHT_BIT_SHIFT(AudioFreq); 01811 if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInButtomLeftChannel)) 01812 { 01813 return AUDIO_ERROR; 01814 } 01815 01816 /* CHANNEL 4 configuration */ 01817 __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInButtomRightChannel); 01818 hAudioInButtomRightChannel.Instance = DFSDM1_Channel4; 01819 hAudioInButtomRightChannel.Init.OutputClock.Activation = ENABLE; 01820 hAudioInButtomRightChannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01821 /* Set the DFSDM clock OUT audio frequency configuration */ 01822 hAudioInButtomRightChannel.Init.OutputClock.Divider = DFSDM_CLOCK_DIVIDER(AudioFreq); 01823 hAudioInButtomRightChannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01824 hAudioInButtomRightChannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01825 hAudioInButtomRightChannel.Init.Input.Pins = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS; 01826 /* Request to sample stable data for RIGHT micro on Falling edge */ 01827 hAudioInButtomRightChannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_FALLING; 01828 hAudioInButtomRightChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01829 hAudioInButtomRightChannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER; 01830 hAudioInButtomRightChannel.Init.Awd.Oversampling = 10; 01831 hAudioInButtomRightChannel.Init.Offset = 0; 01832 hAudioInButtomRightChannel.Init.RightBitShift = DFSDM_RIGHT_BIT_SHIFT(AudioFreq); 01833 if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInButtomRightChannel)) 01834 { 01835 return AUDIO_ERROR; 01836 } 01837 } 01838 /****************************************************************************/ 01839 /********************** Filters configuration ******************************/ 01840 /****************************************************************************/ 01841 01842 /* FILTER 0 configuration */ 01843 __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInTopLeftFilter); 01844 hAudioInTopLeftFilter.Instance = AUDIO_DFSDMx_TOP_LEFT_FILTER; 01845 hAudioInTopLeftFilter.Init.RegularParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01846 hAudioInTopLeftFilter.Init.RegularParam.FastMode = ENABLE; 01847 hAudioInTopLeftFilter.Init.RegularParam.DmaMode = ENABLE; 01848 hAudioInTopLeftFilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01849 hAudioInTopLeftFilter.Init.InjectedParam.ScanMode = ENABLE; 01850 hAudioInTopLeftFilter.Init.InjectedParam.DmaMode = DISABLE; 01851 hAudioInTopLeftFilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO; 01852 hAudioInTopLeftFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE; 01853 hAudioInTopLeftFilter.Init.FilterParam.SincOrder = DFSDM_FILTER_ORDER(AudioFreq); 01854 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01855 hAudioInTopLeftFilter.Init.FilterParam.Oversampling = DFSDM_OVER_SAMPLING(AudioFreq); 01856 hAudioInTopLeftFilter.Init.FilterParam.IntOversampling = 1; 01857 if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInTopLeftFilter)) 01858 { 01859 return AUDIO_ERROR; 01860 } 01861 01862 /* Configure injected channel */ 01863 if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInTopLeftFilter, AUDIO_DFSDMx_TOP_LEFT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON)) 01864 { 01865 return AUDIO_ERROR; 01866 } 01867 01868 /* FILTER 1 configuration */ 01869 __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInTopRightFilter); 01870 hAudioInTopRightFilter.Instance = AUDIO_DFSDMx_TOP_RIGHT_FILTER; 01871 hAudioInTopRightFilter.Init.RegularParam.Trigger = DFSDM_FILTER_SYNC_TRIGGER; 01872 hAudioInTopRightFilter.Init.RegularParam.FastMode = ENABLE; 01873 hAudioInTopRightFilter.Init.RegularParam.DmaMode = ENABLE; 01874 hAudioInTopRightFilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01875 hAudioInTopRightFilter.Init.InjectedParam.ScanMode = DISABLE; 01876 hAudioInTopRightFilter.Init.InjectedParam.DmaMode = DISABLE; 01877 hAudioInTopRightFilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO; 01878 hAudioInTopRightFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE; 01879 hAudioInTopRightFilter.Init.FilterParam.SincOrder = DFSDM_FILTER_ORDER(AudioFreq); 01880 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01881 hAudioInTopRightFilter.Init.FilterParam.Oversampling = DFSDM_OVER_SAMPLING(AudioFreq); 01882 hAudioInTopRightFilter.Init.FilterParam.IntOversampling = 1; 01883 if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInTopRightFilter)) 01884 { 01885 return AUDIO_ERROR; 01886 } 01887 /* Configure injected channel */ 01888 if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInTopRightFilter, AUDIO_DFSDMx_TOP_RIGHT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON)) 01889 { 01890 return AUDIO_ERROR; 01891 } 01892 01893 if(AudioIn_ChannelNumber > 2) 01894 { 01895 /* FILTER 2 configuration */ 01896 __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInButtomLeftFilter); 01897 hAudioInButtomLeftFilter.Instance = AUDIO_DFSDMx_BUTTOM_LEFT_FILTER; 01898 hAudioInButtomLeftFilter.Init.RegularParam.Trigger = DFSDM_FILTER_SYNC_TRIGGER; 01899 hAudioInButtomLeftFilter.Init.RegularParam.FastMode = ENABLE; 01900 hAudioInButtomLeftFilter.Init.RegularParam.DmaMode = ENABLE; 01901 hAudioInButtomLeftFilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01902 hAudioInButtomLeftFilter.Init.InjectedParam.ScanMode = ENABLE; 01903 hAudioInButtomLeftFilter.Init.InjectedParam.DmaMode = DISABLE; 01904 hAudioInButtomLeftFilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO; 01905 hAudioInButtomLeftFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE; 01906 hAudioInButtomLeftFilter.Init.FilterParam.SincOrder = DFSDM_FILTER_ORDER(AudioFreq); 01907 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01908 hAudioInButtomLeftFilter.Init.FilterParam.Oversampling = DFSDM_OVER_SAMPLING(AudioFreq); 01909 hAudioInButtomLeftFilter.Init.FilterParam.IntOversampling = 1; 01910 if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInButtomLeftFilter)) 01911 { 01912 return AUDIO_ERROR; 01913 } 01914 01915 /* Configure injected channel */ 01916 if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInButtomLeftFilter, AUDIO_DFSDMx_BUTTOM_LEFT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON)) 01917 { 01918 return AUDIO_ERROR; 01919 } 01920 01921 /* FILTER 3 configuration */ 01922 __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInButtomRightFilter); 01923 hAudioInButtomRightFilter.Instance = AUDIO_DFSDMx_BUTTOM_RIGHT_FILTER; 01924 hAudioInButtomRightFilter.Init.RegularParam.Trigger = DFSDM_FILTER_SYNC_TRIGGER; 01925 hAudioInButtomRightFilter.Init.RegularParam.FastMode = ENABLE; 01926 hAudioInButtomRightFilter.Init.RegularParam.DmaMode = ENABLE; 01927 hAudioInButtomRightFilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01928 hAudioInButtomRightFilter.Init.InjectedParam.ScanMode = DISABLE; 01929 hAudioInButtomRightFilter.Init.InjectedParam.DmaMode = DISABLE; 01930 hAudioInButtomRightFilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO; 01931 hAudioInButtomRightFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE; 01932 hAudioInButtomRightFilter.Init.FilterParam.SincOrder = DFSDM_FILTER_ORDER(AudioFreq); 01933 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01934 hAudioInButtomRightFilter.Init.FilterParam.Oversampling = DFSDM_OVER_SAMPLING(AudioFreq); 01935 hAudioInButtomRightFilter.Init.FilterParam.IntOversampling = 1; 01936 if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInButtomRightFilter)) 01937 { 01938 return AUDIO_ERROR; 01939 } 01940 /* Configure injected channel */ 01941 if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInButtomRightFilter, AUDIO_DFSDMx_BUTTOM_RIGHT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON)) 01942 { 01943 return AUDIO_ERROR; 01944 } 01945 } 01946 return AUDIO_OK; 01947 } 01948 01949 /** 01950 * @brief De-initialize the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01951 * @retval AUDIO_OK if correct communication, else wrong communication 01952 */ 01953 static uint8_t DFSDMx_DeInit(void) 01954 { 01955 /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */ 01956 if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInTopLeftFilter)) 01957 { 01958 return AUDIO_ERROR; 01959 } 01960 01961 if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInTopRightFilter)) 01962 { 01963 return AUDIO_ERROR; 01964 } 01965 01966 /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */ 01967 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInTopLeftChannel)) 01968 { 01969 return AUDIO_ERROR; 01970 } 01971 01972 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInTopRightChannel)) 01973 { 01974 return AUDIO_ERROR; 01975 } 01976 01977 if(AudioIn_ChannelNumber > 2) 01978 { 01979 /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */ 01980 if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInButtomLeftFilter)) 01981 { 01982 return AUDIO_ERROR; 01983 } 01984 01985 if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInButtomRightFilter)) 01986 { 01987 return AUDIO_ERROR; 01988 } 01989 01990 /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */ 01991 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInButtomLeftChannel)) 01992 { 01993 return AUDIO_ERROR; 01994 } 01995 01996 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInButtomRightChannel)) 01997 { 01998 return AUDIO_ERROR; 01999 } 02000 } 02001 02002 return AUDIO_OK; 02003 } 02004 02005 /** 02006 * @brief Initialize the DFSDM channel MSP. 02007 * @retval None 02008 */ 02009 static void DFSDMx_ChannelMspInit(void) 02010 { 02011 GPIO_InitTypeDef GPIO_InitStruct; 02012 02013 /* Enable DFSDM clock */ 02014 AUDIO_DFSDMx_CLK_ENABLE(); 02015 02016 /* Enable GPIO clock */ 02017 AUDIO_DFSDMx_DMIC_DATIN_GPIO_CLK_ENABLE(); 02018 AUDIO_DFSDMx_CKOUT_DMIC_GPIO_CLK_ENABLE(); 02019 02020 /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN1 pins ------------------*/ 02021 GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN; 02022 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 02023 GPIO_InitStruct.Pull = GPIO_NOPULL; 02024 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 02025 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_CKOUT_AF; 02026 HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT, &GPIO_InitStruct); 02027 02028 /* DFSDM pin configuration: DMIC_DATIN1 pin --------------------------------*/ 02029 GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_DATIN1_PIN; 02030 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_DMIC_DATIN_AF; 02031 HAL_GPIO_Init(AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct); 02032 02033 if(AudioIn_ChannelNumber > 2) 02034 { 02035 /* DFSDM pin configuration: DMIC_DATIN5 pin --------------------------------*/ 02036 GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_DATIN5_PIN; 02037 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_DMIC_DATIN_AF; 02038 HAL_GPIO_Init(AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct); 02039 } 02040 } 02041 02042 /** 02043 * @brief DeInitialize the DFSDM channel MSP. 02044 * @retval None 02045 */ 02046 static void DFSDMx_ChannelMspDeInit(void) 02047 { 02048 GPIO_InitTypeDef GPIO_InitStruct; 02049 02050 /* DFSDM pin configuration: DMIC_DATIN1 pin --------------------------------*/ 02051 GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN; 02052 HAL_GPIO_DeInit(AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 02053 GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_DATIN1_PIN; 02054 HAL_GPIO_DeInit(AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, GPIO_InitStruct.Pin); 02055 02056 if(AudioIn_ChannelNumber > 2) 02057 { 02058 /* DFSDM pin configuration: DMIC_DATIN5 pin ------------------------------*/ 02059 GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN; 02060 HAL_GPIO_DeInit(AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 02061 GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_DATIN5_PIN; 02062 HAL_GPIO_DeInit(AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, GPIO_InitStruct.Pin); 02063 } 02064 } 02065 02066 /** 02067 * @brief Initialize the DFSDM filter MSP. 02068 * @retval None 02069 */ 02070 static void DFSDMx_FilterMspInit(void) 02071 { 02072 /* Enable DFSDM clock */ 02073 AUDIO_DFSDMx_CLK_ENABLE(); 02074 02075 /* Enable the DMA clock */ 02076 AUDIO_DFSDMx_DMAx_CLK_ENABLE(); 02077 02078 /*********** Configure DMA stream for TOP LEFT microphone *******************/ 02079 hDmaTopLeft.Init.Direction = DMA_PERIPH_TO_MEMORY; 02080 hDmaTopLeft.Init.PeriphInc = DMA_PINC_DISABLE; 02081 hDmaTopLeft.Init.MemInc = DMA_MINC_ENABLE; 02082 hDmaTopLeft.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE; 02083 hDmaTopLeft.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE; 02084 hDmaTopLeft.Init.Mode = DMA_CIRCULAR; 02085 hDmaTopLeft.Init.Priority = DMA_PRIORITY_HIGH; 02086 hDmaTopLeft.Instance = AUDIO_DFSDMx_DMAx_TOP_LEFT_STREAM; 02087 hDmaTopLeft.Init.Channel = AUDIO_DFSDMx_DMAx_CHANNEL; 02088 02089 /* Associate the DMA handle */ 02090 __HAL_LINKDMA(&hAudioInTopLeftFilter, hdmaReg, hDmaTopLeft); 02091 02092 /* Reset DMA handle state */ 02093 __HAL_DMA_RESET_HANDLE_STATE(&hDmaTopLeft); 02094 02095 /* Configure the DMA Channel */ 02096 HAL_DMA_Init(&hDmaTopLeft); 02097 02098 /* DMA IRQ Channel configuration */ 02099 HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_TOP_LEFT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 02100 HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_TOP_LEFT_IRQ); 02101 02102 02103 /*********** Configure DMA stream for TOP RIGHT microphone ******************/ 02104 hDmaTopRight.Init.Direction = DMA_PERIPH_TO_MEMORY; 02105 hDmaTopRight.Init.PeriphInc = DMA_PINC_DISABLE; 02106 hDmaTopRight.Init.MemInc = DMA_MINC_ENABLE; 02107 hDmaTopRight.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE; 02108 hDmaTopRight.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE; 02109 hDmaTopRight.Init.Mode = DMA_CIRCULAR; 02110 hDmaTopRight.Init.Priority = DMA_PRIORITY_HIGH; 02111 hDmaTopRight.Instance = AUDIO_DFSDMx_DMAx_TOP_RIGHT_STREAM; 02112 hDmaTopRight.Init.Channel = AUDIO_DFSDMx_DMAx_CHANNEL; 02113 02114 /* Associate the DMA handle */ 02115 __HAL_LINKDMA(&hAudioInTopRightFilter, hdmaReg, hDmaTopRight); 02116 02117 /* Reset DMA handle state */ 02118 __HAL_DMA_RESET_HANDLE_STATE(&hDmaTopRight); 02119 02120 /* Configure the DMA Channel */ 02121 HAL_DMA_Init(&hDmaTopRight); 02122 02123 /* DMA IRQ Channel configuration */ 02124 HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_TOP_RIGHT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 02125 HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_TOP_RIGHT_IRQ); 02126 02127 if(AudioIn_ChannelNumber > 2) 02128 { 02129 /*********** Configure DMA stream for BUTTOM LEFT microphone ****************/ 02130 hDmaButtomLeft.Init.Direction = DMA_PERIPH_TO_MEMORY; 02131 hDmaButtomLeft.Init.PeriphInc = DMA_PINC_DISABLE; 02132 hDmaButtomLeft.Init.MemInc = DMA_MINC_ENABLE; 02133 hDmaButtomLeft.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE; 02134 hDmaButtomLeft.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE; 02135 hDmaButtomLeft.Init.Mode = DMA_CIRCULAR; 02136 hDmaButtomLeft.Init.Priority = DMA_PRIORITY_HIGH; 02137 hDmaButtomLeft.Instance = AUDIO_DFSDMx_DMAx_BUTTOM_LEFT_STREAM; 02138 hDmaButtomLeft.Init.Channel = AUDIO_DFSDMx_DMAx_CHANNEL; 02139 02140 /* Associate the DMA handle */ 02141 __HAL_LINKDMA(&hAudioInButtomLeftFilter, hdmaReg, hDmaButtomLeft); 02142 02143 /* Reset DMA handle state */ 02144 __HAL_DMA_RESET_HANDLE_STATE(&hDmaButtomLeft); 02145 02146 /* Configure the DMA Channel */ 02147 HAL_DMA_Init(&hDmaButtomLeft); 02148 02149 /* DMA IRQ Channel configuration */ 02150 HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_BUTTOM_LEFT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 02151 HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_BUTTOM_LEFT_IRQ); 02152 02153 02154 /*********** Configure DMA stream for BUTTOM RIGHT microphone ***************/ 02155 hDmaButtomRight.Init.Direction = DMA_PERIPH_TO_MEMORY; 02156 hDmaButtomRight.Init.PeriphInc = DMA_PINC_DISABLE; 02157 hDmaButtomRight.Init.MemInc = DMA_MINC_ENABLE; 02158 hDmaButtomRight.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE; 02159 hDmaButtomRight.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE; 02160 hDmaButtomRight.Init.Mode = DMA_CIRCULAR; 02161 hDmaButtomRight.Init.Priority = DMA_PRIORITY_HIGH; 02162 hDmaButtomRight.Instance = AUDIO_DFSDMx_DMAx_BUTTOM_RIGHT_STREAM; 02163 hDmaButtomRight.Init.Channel = AUDIO_DFSDMx_DMAx_CHANNEL; 02164 02165 /* Associate the DMA handle */ 02166 __HAL_LINKDMA(&hAudioInButtomRightFilter, hdmaReg, hDmaButtomRight); 02167 02168 /* Reset DMA handle state */ 02169 __HAL_DMA_RESET_HANDLE_STATE(&hDmaButtomRight); 02170 02171 /* Configure the DMA Channel */ 02172 HAL_DMA_Init(&hDmaButtomRight); 02173 02174 /* DMA IRQ Channel configuration */ 02175 HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_BUTTOM_RIGHT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 02176 HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_BUTTOM_RIGHT_IRQ); 02177 } 02178 } 02179 02180 /** 02181 * @brief DeInitialize the DFSDM filter MSP. 02182 * @retval None 02183 */ 02184 static void DFSDMx_FilterMspDeInit(void) 02185 { 02186 /* Configure the DMA Channel */ 02187 HAL_DMA_DeInit(&hDmaTopLeft); 02188 HAL_DMA_DeInit(&hDmaTopRight); 02189 if(AudioIn_ChannelNumber > 2) 02190 { 02191 HAL_DMA_DeInit(&hDmaButtomLeft); 02192 HAL_DMA_DeInit(&hDmaButtomRight); 02193 } 02194 } 02195 02196 /** 02197 * @brief This function handles DMA2 Stream 0 interrupt request. 02198 * @param None 02199 * @retval None 02200 */ 02201 void AUDIO_DFSDMx_DMAx_TOP_LEFT_IRQHandler(void) // DMA2_Stream0_IRQHandler 02202 { 02203 HAL_DMA_IRQHandler(hAudioInTopLeftFilter.hdmaReg); 02204 } 02205 02206 /** 02207 * @brief This function handles DMA2 Stream 5 interrupt request. 02208 * @param None 02209 * @retval None 02210 */ 02211 void AUDIO_DFSDMx_DMAx_TOP_RIGHT_IRQHandler(void) // DMA2_Stream5_IRQHandler 02212 { 02213 HAL_DMA_IRQHandler(hAudioInTopRightFilter.hdmaReg); 02214 } 02215 02216 /** 02217 * @brief This function handles DMA2 Stream 1 interrupt request. 02218 * @param None 02219 * @retval None 02220 */ 02221 void AUDIO_OUT_SAIx_DMAx_IRQHandler(void) // DMA2_Stream1_IRQHandler 02222 { 02223 HAL_DMA_IRQHandler(haudio_out_sai.hdmatx); 02224 } 02225 02226 /** 02227 * @brief This function handles DMA2 Stream 6 interrupt request. 02228 * @param None 02229 * @retval None 02230 */ 02231 void AUDIO_DFSDMx_DMAx_BUTTOM_LEFT_IRQHandler(void) // DMA2_Stream6_IRQHandler 02232 { 02233 HAL_DMA_IRQHandler(hAudioInButtomLeftFilter.hdmaReg); 02234 } 02235 02236 /** 02237 * @brief This function handles DMA2 Stream 7 interrupt request. 02238 * @param None 02239 * @retval None 02240 */ 02241 void AUDIO_DFSDMx_DMAx_BUTTOM_RIGHT_IRQHandler(void) // DMA2_Stream7_IRQHandler 02242 { 02243 HAL_DMA_IRQHandler(hAudioInButtomRightFilter.hdmaReg); 02244 } 02245 02246 02247 /** 02248 * @} 02249 */ 02250 02251 /** 02252 * @} 02253 */ 02254 02255 /** 02256 * @} 02257 */ 02258 02259 /** 02260 * @} 02261 */ 02262 02263 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 17:55:04 by 1.7.2