Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: DISCO_L4R9I-LCD-demo
stm32l4r9i_discovery_audio.c
00001 /** 00002 ****************************************************************************** 00003 * @file stm32l4r9i_discovery_audio.c 00004 * @author MCD Application Team 00005 * @brief This file provides a set of functions needed to manage the 00006 * Audio driver for the STM32L4R9I_DISCOVERY board. 00007 ****************************************************************************** 00008 * @attention 00009 * 00010 * <h2><center>© Copyright (c) 2017 STMicroelectronics. 00011 * All rights reserved.</center></h2> 00012 * 00013 * This software component is licensed by ST under BSD 3-Clause license, 00014 * the "License"; You may not use this file except in compliance with the 00015 * License. You may obtain a copy of the License at: 00016 * opensource.org/licenses/BSD-3-Clause 00017 * 00018 ****************************************************************************** 00019 */ 00020 00021 /*============================================================================== 00022 User NOTES 00023 00024 1. How To use this driver: 00025 -------------------------- 00026 + This driver supports STM32L4xx devices on STM32L4R9I_DISCOVERY (MB1311) Discovery boards. 00027 a) to play an audio file through headset. All functions names start by BSP_AUDIO_OUT_xxx. 00028 b) to record an audio file through digital microphones (MP34DT01TR ST mems) 00029 or analog microphone (headset microphone). All functions names start by BSP_AUDIO_IN_xxx. 00030 00031 a) PLAY A FILE: 00032 ============== 00033 + Call the function BSP_AUDIO_OUT_Init( 00034 OutputDevice: physical output mode (only OUTPUT_DEVICE_HEADPHONE). 00035 Volume : Initial volume to be set (0 is min (mute), 100 is max (100%) 00036 AudioFreq : Audio frequency in Hz (8000, 16000, 22500, 32000...) 00037 this parameter is relative to the audio file/stream type. 00038 ) 00039 This function configures all the hardware required for the audio application (codec, I2C, SAI, 00040 GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK. 00041 If the returned value is different from AUDIO_OK or the function is stuck then the communication with 00042 the audio codec has failed. 00043 - OUTPUT_DEVICE_HEADPHONE: only Headphone output is available on this board. 00044 00045 + Call the function BSP_AUDIO_OUT_RegisterCallbacks to register user callbacks 00046 required to manage audio data streaming towards the audio codec (ErrorCallback(), 00047 HalfTransfer_CallBack() and TransferComplete_CallBack()). 00048 00049 + Call the function BSP_AUDIO_OUT_Play() to start audio playback (for the first time). 00050 + Call the function BSP_AUDIO_OUT_Pause() to pause audio playback. 00051 + Call the function BSP_AUDIO_OUT_Resume() to resume audio playback. 00052 Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called 00053 for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case). 00054 Note. This function should be called only when the audio file is played or paused (not stopped). 00055 + Call the function BSP_AUDIO_OUT_Stop() to stop audio playback. 00056 + To modify the volume level, the sampling frequency, the device output mode, 00057 the mute status or the audio configuration or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(), 00058 AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetOutputMode(), BSP_AUDIO_OUT_SetMute()and 00059 BSP_AUDIO_OUT_ChangeAudioConfig(). 00060 00061 Driver architecture: 00062 -------------------- 00063 + This driver provides the audio layer high level API: it consists in functions 00064 exported in the stm32l4r9i_discovery_audio.h file (e.g. BSP_AUDIO_OUT_Init(), 00065 BSP_AUDIO_OUT_Play(), ...). 00066 + This driver also includes the Media Access Layer (MAL): it consists in 00067 functions allowing to access setup the audio devices. These functions 00068 are included as local functions into the stm32l4r9i_discovery_audio.c file 00069 (e.g. AUDIO_SAIx_Init()). 00070 00071 Known Limitations: 00072 ------------------ 00073 1- Communication with the audio codec (through I2C) may be corrupted if it is interrupted by some 00074 user interrupt routines (in this case, interrupts could be disabled just before the start of 00075 communication then re-enabled when it is over). Note that this communication is only done at 00076 the configuration phase (BSP_AUDIO_OUT_Init() or BSP_AUDIO_OUT_Stop()) and when Volume control modification is 00077 performed (BSP_AUDIO_OUT_SetVolume() or BSP_AUDIO_OUT_SetMute()or BSP_AUDIO_OUT_SetOutputMode()). 00078 When the audio data is played, no communication is required with the audio codec. 00079 2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 00080 File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file. 00081 3- Supports only 16-bits audio data size. 00082 00083 b) RECORD A FILE: 00084 ================ 00085 + Call the function BSP_AUDIO_IN_InitEx( 00086 InputDevice: physical input mode (INPUT_DEVICE_DIGITAL_MIC 00087 INPUT_DEVICE_DIGITAL_MIC1, INPUT_DEVICE_DIGITAL_MIC2 00088 or INPUT_DEVICE_ANALOG_MIC) 00089 AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...) 00090 ) 00091 This function configures all the hardware required for the audio application (DFSDM or SAI, 00092 GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if the 00093 configuration completes successfully. 00094 - INPUT_DEVICE_DIGITAL_MIC: Record from digital microphones mounted on board. 00095 - INPUT_DEVICE_DIGITAL_MIC1: Record from digital microphone 1 mounted on board (left microphone). 00096 - INPUT_DEVICE_DIGITAL_MIC2: Record from digital microphone 2 mounted on board (right microphone). 00097 - INPUT_DEVICE_ANALOG_MIC: Record from headset microphone. 00098 00099 + Call the function BSP_AUDIO_IN_RegisterCallbacks to register user callbacks 00100 used to stream audio data toward the record buffer (ErrorCallback(), 00101 HalfTransfer_CallBack() and TransferComplete_CallBack()). 00102 00103 + Call the function BSP_AUDIO_IN_Record( 00104 pbuf Main buffer pointer for the recorded data storing 00105 size Current size of the recorded buffer 00106 ) 00107 to start recording from the microphone. 00108 00109 + Call the function BSP_AUDIO_IN_Stop() to stop recording. 00110 ==============================================================================*/ 00111 00112 /* Includes ------------------------------------------------------------------*/ 00113 #include <string.h> 00114 #include "stm32l4r9i_discovery_audio.h" 00115 00116 /** @addtogroup BSP 00117 * @{ 00118 */ 00119 00120 /** @addtogroup STM32L4R9I_DISCOVERY 00121 * @{ 00122 */ 00123 00124 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO STM32L4R9I_DISCOVERY AUDIO 00125 * @brief This file includes the low layer driver for cs42l51 Audio Codec 00126 * available on STM32L4R9I_DISCOVERY board (MB1311). 00127 * @{ 00128 */ 00129 00130 /* Private typedef -----------------------------------------------------------*/ 00131 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Private_Types Private Types 00132 * @{ 00133 */ 00134 typedef struct 00135 { 00136 AUDIO_DrvTypeDef * AudioDrv; /* Audio codec driver */ 00137 uint32_t OutputDevice; /* Output device */ 00138 uint32_t Frequency; /* Playback frequency */ 00139 uint32_t Volume; /* Playback volume */ 00140 Audio_CallbackTypeDef CbError; /* pointer to the callback function invoked when error occurs */ 00141 Audio_CallbackTypeDef CbHalfTransfer; /* pointer to the callback function invoked when half transfer occurs */ 00142 Audio_CallbackTypeDef CbTransferComplete; /* pointer to the callback function invoked when transfer complete occurs */ 00143 } AUDIO_OUT_TypeDef; 00144 00145 typedef struct 00146 { 00147 AUDIO_DrvTypeDef * AudioDrv; /* Audio codec driver */ 00148 DFSDM_Channel_HandleTypeDef hDfsdmLeftChannel; /* DFSDM channel handle used for left channel */ 00149 DFSDM_Channel_HandleTypeDef hDfsdmRightChannel; /* DFSDM channel handle used for right channel */ 00150 DMA_HandleTypeDef hDmaDfsdmLeft; /* DMA handle used for DFSDM regular conversions on left channel */ 00151 DMA_HandleTypeDef hDmaDfsdmRight; /* DMA handle used for DFSDM regular conversions on right channel */ 00152 int32_t * LeftRecBuff; /* Buffers for left samples */ 00153 int32_t * RightRecBuff; /* Buffers for right samples */ 00154 uint32_t InputDevice; /* Input device */ 00155 uint32_t Frequency; /* Record Frequency */ 00156 uint32_t BitResolution; /* Record bit resolution */ 00157 uint32_t ChannelNbr; /* Record Channel Number */ 00158 uint16_t * pRecBuf; /* Pointer to record user buffer */ 00159 uint32_t RecSize; /* Size to record in mono, double size to record in stereo */ 00160 Audio_CallbackTypeDef CbError; /* pointer to the callback function invoked when a DMA transfer fails */ 00161 Audio_CallbackTypeDef CbHalfTransfer; /* pointer to the callback function invoked when half of the DMA transfer is completed */ 00162 Audio_CallbackTypeDef CbTransferComplete; /* pointer to the callback function invoked when the DMA transfer is completed */ 00163 } AUDIO_IN_TypeDef; 00164 00165 /** 00166 * @} 00167 */ 00168 00169 /* Private macros ------------------------------------------------------------*/ 00170 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Private_Macros Private Macros 00171 * @{ 00172 */ 00173 /*### PLAY ###*/ 00174 /* SCK(kHz) = SAI_CK_x/(SAIClockDivider*2*256) */ 00175 #define SAIClockDivider(__FREQUENCY__) \ 00176 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 24 \ 00177 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \ 00178 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 12 \ 00179 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 2 \ 00180 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 6 \ 00181 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 1 \ 00182 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 4 : 2 \ 00183 00184 /*### RECORD ###*/ 00185 #define DFSDMOverSampling(__FREQUENCY__) \ 00186 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 256 \ 00187 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \ 00188 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \ 00189 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \ 00190 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \ 00191 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64 \ 00192 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 16 \ 00193 00194 #define DFSDMClockDivider(__FREQUENCY__) \ 00195 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 24 \ 00196 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \ 00197 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \ 00198 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \ 00199 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \ 00200 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4 \ 00201 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 32 \ 00202 00203 #define DFSDMFilterOrder(__FREQUENCY__) \ 00204 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? DFSDM_FILTER_SINC3_ORDER \ 00205 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \ 00206 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \ 00207 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \ 00208 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \ 00209 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC4_ORDER \ 00210 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC4_ORDER : DFSDM_FILTER_SINC5_ORDER \ 00211 00212 #define DFSDMRightBitShift(__FREQUENCY__) \ 00213 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 7 \ 00214 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 7 \ 00215 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 4 \ 00216 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \ 00217 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 7 \ 00218 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 7 \ 00219 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 3 : 4 \ 00220 00221 /* Saturate the record PCM sample */ 00222 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N))) 00223 00224 /** 00225 * @} 00226 */ 00227 00228 /* Private variables ---------------------------------------------------------*/ 00229 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Private_Variables Private Variables 00230 * @{ 00231 */ 00232 /* Audio output context information */ 00233 static AUDIO_OUT_TypeDef hAudioOut = {0}; 00234 00235 /* Audio input context information */ 00236 static AUDIO_IN_TypeDef hAudioIn = {0}; 00237 00238 /* SAI DMA handle */ 00239 static DMA_HandleTypeDef hDmaSaiTx; 00240 static DMA_HandleTypeDef hDmaSaiRx; 00241 00242 static uint32_t DmaLeftRecHalfBuffCplt; 00243 static uint32_t DmaLeftRecBuffCplt; 00244 static uint32_t DmaRightRecHalfBuffCplt; 00245 static uint32_t DmaRightRecBuffCplt; 00246 00247 /** 00248 * @} 00249 */ 00250 00251 /* Exported variables ---------------------------------------------------------*/ 00252 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Exported_Variables Exported Variables 00253 * @{ 00254 */ 00255 /* SAIx handle */ 00256 SAI_HandleTypeDef BSP_AUDIO_hSai_Tx; 00257 SAI_HandleTypeDef BSP_AUDIO_hSai_Rx; 00258 00259 /* DFSDM filter handle */ 00260 DFSDM_Filter_HandleTypeDef BSP_AUDIO_hDfsdmLeftFilter; 00261 DFSDM_Filter_HandleTypeDef BSP_AUDIO_hDfsdmRightFilter; 00262 /** 00263 * @} 00264 */ 00265 00266 /* Private function prototypes -----------------------------------------------*/ 00267 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Private_Functions Private Functions 00268 * @{ 00269 */ 00270 static uint8_t AUDIO_SAIx_Init(uint32_t AudioFreq); 00271 static uint8_t AUDIO_SAIx_DeInit(void); 00272 static uint8_t AUDIO_DFSDMx_Init(uint32_t AudioFreq); 00273 static uint8_t AUDIO_DFSDMx_DeInit(void); 00274 static uint8_t AUDIO_SAIPLLConfig(uint32_t AudioFreq); 00275 /** 00276 * @} 00277 */ 00278 00279 /* Exported functions --------------------------------------------------------*/ 00280 /** @addtogroup STM32L4R9I_DISCOVERY_AUDIO_Exported_Functions 00281 * @{ 00282 */ 00283 00284 /** 00285 * @brief Configures the audio codec related peripherals. 00286 * @param OutputDevice: OUTPUT_DEVICE_HEADPHONE. 00287 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00288 * @param AudioFreq: Audio frequency used to play the audio stream. 00289 * @retval BSP AUDIO status 00290 * @note The SAI PLL input clock must be configure in the user application. 00291 * The SAI PLL configuration done within this function assumes that 00292 * the SAI PLL input clock runs at 8 MHz. 00293 */ 00294 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, 00295 uint8_t Volume, 00296 uint32_t AudioFreq) 00297 { 00298 /* Initialize the audio output context */ 00299 hAudioOut.AudioDrv = &cs42l51_drv; 00300 hAudioOut.OutputDevice = OutputDevice; 00301 hAudioOut.Frequency = AudioFreq; 00302 hAudioOut.Volume = Volume; 00303 hAudioOut.CbError = (Audio_CallbackTypeDef)NULL; 00304 hAudioOut.CbHalfTransfer = (Audio_CallbackTypeDef)NULL; 00305 hAudioOut.CbTransferComplete = (Audio_CallbackTypeDef)NULL; 00306 00307 /* Check if input device is currently used */ 00308 if(hAudioIn.InputDevice != 0) 00309 { 00310 /* If input device is currently used, SAI PLL is already initialized */ 00311 /* Check that AudioFreq for record and playback is the same */ 00312 if(hAudioIn.Frequency != hAudioOut.Frequency) 00313 { 00314 return AUDIO_ERROR; 00315 } 00316 } 00317 else 00318 { 00319 /* Configure the SAI PLL according to the requested audio frequency */ 00320 if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK) 00321 { 00322 return AUDIO_ERROR; 00323 } 00324 } 00325 00326 /* If input device is analogic mic, SAI is already initialized */ 00327 if(hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC) 00328 { 00329 /* SAI data transfer preparation: prepare the Media to be used for the audio 00330 transfer from memory to SAI peripheral. */ 00331 if (AUDIO_SAIx_Init(AudioFreq) != AUDIO_OK) 00332 { 00333 return AUDIO_ERROR; 00334 } 00335 } 00336 00337 /* Initialize the audio codec internal registers */ 00338 if (hAudioOut.AudioDrv->Init(AUDIO_I2C_ADDRESS, 00339 (hAudioOut.OutputDevice | hAudioIn.InputDevice), 00340 Volume, 00341 AudioFreq) != 0) 00342 { 00343 return AUDIO_ERROR; 00344 } 00345 00346 return AUDIO_OK; 00347 } 00348 00349 /** 00350 * @brief De-Initializes audio codec related peripherals 00351 * @retval BSP AUDIO status 00352 00353 */ 00354 uint8_t BSP_AUDIO_OUT_DeInit(void) 00355 { 00356 if(hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 00357 { 00358 /* Reset playback path on audio codec */ 00359 if(hAudioIn.AudioDrv->Init(AUDIO_I2C_ADDRESS, 00360 hAudioIn.InputDevice, 00361 (uint8_t) hAudioOut.Volume, 00362 hAudioIn.Frequency) != 0) 00363 { 00364 return AUDIO_ERROR; 00365 } 00366 } 00367 else 00368 { 00369 /* De-initializes SAI interface */ 00370 if(AUDIO_SAIx_DeInit() != AUDIO_OK) 00371 { 00372 return AUDIO_ERROR; 00373 } 00374 00375 /* DeInit audio codec */ 00376 hAudioOut.AudioDrv->DeInit(); 00377 } 00378 00379 /* Disable SAI PLL if no more device is used */ 00380 if(hAudioIn.InputDevice == 0) 00381 { 00382 if (AUDIO_SAIx_PLL_DISABLE() != AUDIO_OK) 00383 { 00384 return AUDIO_ERROR; 00385 } 00386 } 00387 00388 /* Reset the audio output context */ 00389 memset(&hAudioOut, 0, sizeof(hAudioOut)); 00390 00391 return AUDIO_OK; 00392 } 00393 00394 /** 00395 * @brief Starts playing audio stream from a data buffer for a determined size. 00396 * @param pData: pointer on PCM samples buffer 00397 * @param Size: Number of audio data HALF WORD. 00398 * @retval BSP AUDIO status 00399 */ 00400 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pData, uint32_t Size) 00401 { 00402 /* Initiate a DMA transfer of PCM samples towards the serial audio interface */ 00403 if (HAL_SAI_Transmit_DMA(&BSP_AUDIO_hSai_Tx, (uint8_t *)pData, DMA_MAX(Size))!= HAL_OK) 00404 { 00405 return AUDIO_ERROR; 00406 } 00407 00408 /* Call the audio Codec Play function */ 00409 if (hAudioOut.AudioDrv->Play(AUDIO_I2C_ADDRESS, pData, Size) != 0) 00410 { 00411 return AUDIO_ERROR; 00412 } 00413 00414 return AUDIO_OK; 00415 } 00416 00417 /** 00418 * @brief Sends n-Bytes on the SAI interface. 00419 * @param pData: pointer on PCM samples buffer 00420 * @param Size: number of data to be written 00421 * @retval BSP AUDIO status 00422 */ 00423 uint8_t BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size) 00424 { 00425 /* Initiate a DMA transfer of PCM samples towards the serial audio interface */ 00426 if (HAL_SAI_Transmit_DMA(&BSP_AUDIO_hSai_Tx, (uint8_t *)pData, Size)!= HAL_OK) 00427 { 00428 return AUDIO_ERROR; 00429 } 00430 00431 return AUDIO_OK; 00432 } 00433 00434 /** 00435 * @brief This function Pauses the audio file stream. In case 00436 * of using DMA, the DMA Pause feature is used. 00437 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00438 * BSP_AUDIO_OUT_Resume() function should be called for resume 00439 * (use of BSP_AUDIO_OUT_Play() function for resume could lead 00440 * to unexpected behavior). 00441 * @retval BSP AUDIO status 00442 */ 00443 uint8_t BSP_AUDIO_OUT_Pause(void) 00444 { 00445 /* Call the Audio Codec Pause function */ 00446 if (hAudioOut.AudioDrv->Pause(AUDIO_I2C_ADDRESS) != 0) 00447 { 00448 return AUDIO_ERROR; 00449 } 00450 00451 /* Pause DMA transfer of PCM samples towards the serial audio interface */ 00452 if (HAL_SAI_DMAPause(&BSP_AUDIO_hSai_Tx)!= HAL_OK) 00453 { 00454 return AUDIO_ERROR; 00455 } 00456 00457 return AUDIO_OK; 00458 } 00459 00460 /** 00461 * @brief This function Resumes the audio file stream. 00462 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00463 * BSP_AUDIO_OUT_Resume() function should be called for resume 00464 * (use of BSP_AUDIO_OUT_Play() function for resume could lead to 00465 * unexpected behavior). 00466 * @retval BSP AUDIO status 00467 */ 00468 uint8_t BSP_AUDIO_OUT_Resume(void) 00469 { 00470 /* Call the Audio Codec Resume function */ 00471 if (hAudioOut.AudioDrv->Resume(AUDIO_I2C_ADDRESS) != 0) 00472 { 00473 return AUDIO_ERROR; 00474 } 00475 00476 /* Resume DMA transfer of PCM samples towards the serial audio interface */ 00477 if (HAL_SAI_DMAResume(&BSP_AUDIO_hSai_Tx)!= HAL_OK) 00478 { 00479 return AUDIO_ERROR; 00480 } 00481 00482 return AUDIO_OK; 00483 } 00484 00485 /** 00486 * @brief Stops audio playing and Power down the Audio Codec. 00487 * @param Option: could be one of the following parameters 00488 * - CODEC_PDWN_SW: for software power off (by writing registers). 00489 * Then no need to reconfigure the Codec after power on. 00490 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00491 * Then need to reconfigure the Codec after power on. 00492 * @retval BSP AUDIO status 00493 */ 00494 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option) 00495 { 00496 /* Prevent unused argument(s) compilation warning */ 00497 UNUSED(Option); 00498 00499 /* Call Audio Codec Stop function */ 00500 if (hAudioOut.AudioDrv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 00501 { 00502 return AUDIO_ERROR; 00503 } 00504 00505 /* Wait at least 100ms */ 00506 HAL_Delay(100); 00507 00508 /* Stop DMA transfer of PCM samples towards the serial audio interface */ 00509 if (HAL_SAI_DMAStop(&BSP_AUDIO_hSai_Tx)!= HAL_OK) 00510 { 00511 return AUDIO_ERROR; 00512 } 00513 00514 return AUDIO_OK; 00515 } 00516 00517 /** 00518 * @brief Controls the current audio volume level. 00519 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00520 * Mute and 100 for Max volume level). 00521 * @retval BSP AUDIO status 00522 */ 00523 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume) 00524 { 00525 /* Call the codec volume control function with converted volume value */ 00526 if (hAudioOut.AudioDrv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 00527 { 00528 return AUDIO_ERROR; 00529 } 00530 00531 hAudioOut.Volume = Volume; 00532 00533 return AUDIO_OK; 00534 } 00535 00536 /** 00537 * @brief Enables or disables the MUTE mode by software 00538 * @param Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 00539 * unmute the codec and restore previous volume level. 00540 * @retval BSP AUDIO status 00541 */ 00542 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd) 00543 { 00544 /* Call the Codec Mute function */ 00545 if (hAudioOut.AudioDrv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0) 00546 { 00547 return AUDIO_ERROR; 00548 } 00549 00550 return AUDIO_OK; 00551 } 00552 00553 /** 00554 * @brief Switch dynamically (while audio file is being played) the output 00555 * target (speaker or headphone). 00556 * @param Output: The audio output target: OUTPUT_DEVICE_SPEAKER, 00557 * OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH 00558 * @retval BSP AUDIO status 00559 */ 00560 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output) 00561 { 00562 /* Call the Codec output device function */ 00563 if (hAudioOut.AudioDrv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0) 00564 { 00565 return AUDIO_ERROR; 00566 } 00567 00568 return AUDIO_OK; 00569 } 00570 00571 /** 00572 * @brief Updates the audio frequency. 00573 * @param AudioFreq: Audio frequency used to play the audio stream. 00574 * @note The SAI PLL input clock must be configure in the user application. 00575 * The SAI PLL configuration done within this function assumes that 00576 * the SAI PLL input clock runs at 8 MHz. 00577 * @retval BSP AUDIO status 00578 */ 00579 uint8_t BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq) 00580 { 00581 uint8_t TxData[2] = {0x00, 0x00}; 00582 00583 /* Configure the SAI PLL according to the requested audio frequency */ 00584 if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK) 00585 { 00586 return AUDIO_ERROR; 00587 } 00588 00589 /* Disable SAI peripheral to allow access to SAI internal registers */ 00590 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx); 00591 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Rx); 00592 00593 /* Update the SAI audio frequency configuration */ 00594 BSP_AUDIO_hSai_Tx.Init.Mckdiv = SAIClockDivider(AudioFreq); 00595 HAL_SAI_Init(&BSP_AUDIO_hSai_Tx); 00596 BSP_AUDIO_hSai_Rx.Init.Mckdiv = SAIClockDivider(AudioFreq); 00597 HAL_SAI_Init(&BSP_AUDIO_hSai_Rx); 00598 00599 /* Enable SAI peripheral to generate MCLK */ 00600 __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx); 00601 /* Transmit one byte to start FS generation */ 00602 if(HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000) != HAL_OK) 00603 { 00604 return AUDIO_ERROR; 00605 } 00606 00607 hAudioOut.Frequency = AudioFreq; 00608 00609 return AUDIO_OK; 00610 } 00611 00612 /** 00613 * @brief Changes the Audio Out Configuration. 00614 * @param AudioOutOption: specifies the audio out new configuration 00615 * This parameter can be any value of @ref BSP_Audio_Out_Option 00616 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00617 * audio out configuration. 00618 * @retval None 00619 */ 00620 void BSP_AUDIO_OUT_ChangeAudioConfig(uint32_t AudioOutOption) 00621 { 00622 uint8_t TxData[2] = {0x00, 0x00}; 00623 00624 /********** Playback Buffer circular/normal mode **********/ 00625 if(AudioOutOption & BSP_AUDIO_OUT_CIRCULARMODE) 00626 { 00627 /* Deinitialize the Stream to update DMA mode */ 00628 HAL_DMA_DeInit(BSP_AUDIO_hSai_Tx.hdmatx); 00629 00630 /* Update the SAI audio Transfer DMA mode */ 00631 BSP_AUDIO_hSai_Tx.hdmatx->Init.Mode = DMA_CIRCULAR; 00632 00633 /* Configure the DMA Stream with new Transfer DMA mode */ 00634 HAL_DMA_Init(BSP_AUDIO_hSai_Tx.hdmatx); 00635 } 00636 else /* BSP_AUDIO_OUT_NORMALMODE */ 00637 { 00638 /* Deinitialize the Stream to update DMA mode */ 00639 HAL_DMA_DeInit(BSP_AUDIO_hSai_Tx.hdmatx); 00640 00641 /* Update the SAI audio Transfer DMA mode */ 00642 BSP_AUDIO_hSai_Tx.hdmatx->Init.Mode = DMA_NORMAL; 00643 00644 /* Configure the DMA Stream with new Transfer DMA mode */ 00645 HAL_DMA_Init(BSP_AUDIO_hSai_Tx.hdmatx); 00646 } 00647 00648 /********** Playback Buffer stereo/mono mode **********/ 00649 if(AudioOutOption & BSP_AUDIO_OUT_STEREOMODE) 00650 { 00651 /* Disable SAI peripheral to allow access to SAI internal registers */ 00652 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx); 00653 00654 /* Update the SAI audio frame slot configuration */ 00655 BSP_AUDIO_hSai_Tx.Init.MonoStereoMode = SAI_STEREOMODE; 00656 HAL_SAI_Init(&BSP_AUDIO_hSai_Tx); 00657 00658 /* Enable SAI peripheral to generate MCLK */ 00659 __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx); 00660 /* Transmit one byte to start FS generation */ 00661 HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000); 00662 } 00663 else /* BSP_AUDIO_OUT_MONOMODE */ 00664 { 00665 /* Disable SAI peripheral to allow access to SAI internal registers */ 00666 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx); 00667 00668 /* Update the SAI audio frame slot configuration */ 00669 BSP_AUDIO_hSai_Tx.Init.MonoStereoMode = SAI_MONOMODE; 00670 HAL_SAI_Init(&BSP_AUDIO_hSai_Tx); 00671 00672 /* Enable SAI peripheral to generate MCLK */ 00673 __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx); 00674 /* Transmit one byte to start FS generation */ 00675 HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000); 00676 } 00677 } 00678 00679 /** 00680 * @brief register user callback functions 00681 * @param ErrorCallback: pointer to the error callback function 00682 * @param HalfTransferCallback: pointer to the half transfer callback function 00683 * @param TransferCompleteCallback: pointer to the transfer complete callback function 00684 * @retval None 00685 */ 00686 void BSP_AUDIO_OUT_RegisterCallbacks(Audio_CallbackTypeDef ErrorCallback, 00687 Audio_CallbackTypeDef HalfTransferCallback, 00688 Audio_CallbackTypeDef TransferCompleteCallback) 00689 { 00690 hAudioOut.CbError = ErrorCallback; 00691 hAudioOut.CbHalfTransfer = HalfTransferCallback; 00692 hAudioOut.CbTransferComplete = TransferCompleteCallback; 00693 } 00694 00695 /** 00696 * @brief Tx Transfer completed callbacks. 00697 * @param hsai: SAI handle 00698 * @retval None 00699 */ 00700 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) 00701 { 00702 /* Invoke the registered 'TransferComplete' function (if any) */ 00703 if (hAudioOut.CbTransferComplete != (Audio_CallbackTypeDef)NULL) 00704 { 00705 hAudioOut.CbTransferComplete(); 00706 } 00707 } 00708 00709 /** 00710 * @brief Tx Half Transfer completed callbacks. 00711 * @param hsai: SAI handle 00712 * @retval None 00713 */ 00714 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 00715 { 00716 /* Invoke the registered 'HalfTransfer' callback function (if any) */ 00717 if (hAudioOut.CbHalfTransfer != (Audio_CallbackTypeDef)NULL) 00718 { 00719 hAudioOut.CbHalfTransfer(); 00720 } 00721 } 00722 00723 /** 00724 * @brief SAI error callbacks. 00725 * @param hsai: SAI handle 00726 * @retval None 00727 */ 00728 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 00729 { 00730 /* Invoke the registered 'ErrorCallback' callback function (if any) */ 00731 if (hAudioOut.CbError != (Audio_CallbackTypeDef)NULL) 00732 { 00733 hAudioOut.CbError(); 00734 } 00735 /* Invoke the registered 'ErrorCallback' callback function (if any) */ 00736 if (hAudioIn.CbError != (Audio_CallbackTypeDef)NULL) 00737 { 00738 hAudioIn.CbError(); 00739 } 00740 } 00741 00742 /** 00743 * @} 00744 */ 00745 00746 /** @addtogroup STM32L4R9I_DISCOVERY_AUDIO_Exported_Functions 00747 * @{ 00748 */ 00749 00750 /** 00751 * @brief Initializes micropone related peripherals. 00752 * @note This function assumes that the SAI input clock (through PLL_M) 00753 * is already configured and ready to be used. 00754 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00755 * @param BitRes: Audio frequency to be configured for the SAI peripheral. 00756 * @param ChnlNbr: Audio frequency to be configured for the SAI peripheral. 00757 * @retval BSP AUDIO status 00758 */ 00759 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00760 { 00761 return BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC, AudioFreq, BitRes, ChnlNbr); 00762 } 00763 00764 /** 00765 * @brief Initialize wave recording. 00766 * @param InputDevice: INPUT_DEVICE_DIGITAL_MIC, INPUT_DEVICE_DIGITAL_MIC1, 00767 * INPUT_DEVICE_DIGITAL_MIC2 or INPUT_DEVICE_ANALOG_MIC. 00768 * @param AudioFreq: Audio frequency to be configured. 00769 * @param BitRes: Audio bit resolution to be configured.. 00770 * @param ChnlNbr: Number of channel to be configured. 00771 * @retval AUDIO_OK if correct communication, else wrong communication 00772 */ 00773 uint8_t BSP_AUDIO_IN_InitEx(uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00774 { 00775 /* Update the audio input context */ 00776 hAudioIn.AudioDrv = &cs42l51_drv; 00777 hAudioIn.InputDevice = InputDevice; 00778 hAudioIn.Frequency = AudioFreq; 00779 hAudioIn.BitResolution = BitRes; 00780 hAudioIn.ChannelNbr = ChnlNbr; 00781 hAudioIn.CbError = (Audio_CallbackTypeDef)NULL; 00782 hAudioIn.CbHalfTransfer = (Audio_CallbackTypeDef)NULL; 00783 hAudioIn.CbTransferComplete = (Audio_CallbackTypeDef)NULL; 00784 00785 /* Check channel number according device : only record mono with analog mic and stereo with digital mic are allowed */ 00786 if(((InputDevice == INPUT_DEVICE_DIGITAL_MIC) && (ChnlNbr == 1)) || 00787 ((InputDevice == INPUT_DEVICE_DIGITAL_MIC1) && (ChnlNbr == 2)) || 00788 ((InputDevice == INPUT_DEVICE_DIGITAL_MIC2) && (ChnlNbr == 2)) || 00789 ((InputDevice == INPUT_DEVICE_ANALOG_MIC) && (ChnlNbr == 2))) 00790 { 00791 return AUDIO_ERROR; 00792 } 00793 00794 /* Check if output device is currently used */ 00795 if(hAudioOut.OutputDevice != 0) 00796 { 00797 /* If output device is currently used, SAI PLL is already initialized */ 00798 /* Check that AudioFreq for record and playback is the same */ 00799 if(hAudioIn.Frequency != hAudioOut.Frequency) 00800 { 00801 return AUDIO_ERROR; 00802 } 00803 } 00804 else 00805 { 00806 /* Configure the SAI PLL according to the requested audio frequency */ 00807 if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK) 00808 { 00809 return AUDIO_ERROR; 00810 } 00811 } 00812 00813 if(InputDevice != INPUT_DEVICE_ANALOG_MIC) 00814 { 00815 /* Initializes the Digital Filter for Sigma-Delta Modulators interface */ 00816 if(AUDIO_DFSDMx_Init(AudioFreq) != AUDIO_OK) 00817 { 00818 return AUDIO_ERROR; 00819 } 00820 } 00821 else 00822 { /* INPUT_DEVICE_ANALOG_MIC */ 00823 /* If output device is currently used, SAI is already initialized */ 00824 if(hAudioOut.OutputDevice == 0) 00825 { 00826 /* SAI data transfer preparation: prepare the Media to be used for the audio 00827 transfer from SAI peripheral to memory. */ 00828 if(AUDIO_SAIx_Init(AudioFreq) != AUDIO_OK) 00829 { 00830 return AUDIO_ERROR; 00831 } 00832 } 00833 00834 /* Initialize the audio codec internal registers */ 00835 if(hAudioIn.AudioDrv->Init(AUDIO_I2C_ADDRESS, 00836 (hAudioOut.OutputDevice | hAudioIn.InputDevice), 00837 hAudioOut.Volume, 00838 AudioFreq) != 0) 00839 { 00840 return AUDIO_ERROR; 00841 } 00842 } 00843 00844 /* Initialise transfer control flag */ 00845 DmaLeftRecHalfBuffCplt = 0; 00846 DmaLeftRecBuffCplt = 0; 00847 DmaRightRecHalfBuffCplt = 0; 00848 DmaRightRecBuffCplt = 0; 00849 00850 return AUDIO_OK; 00851 } 00852 00853 /** 00854 * @brief De-Initializes microphone related peripherals. 00855 * @retval BSP AUDIO status 00856 00857 */ 00858 uint8_t BSP_AUDIO_IN_DeInit(void) 00859 { 00860 if(hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC) 00861 { 00862 /* De-initializes the Digital Filter for Sigma-Delta Modulators interface */ 00863 if (AUDIO_DFSDMx_DeInit() != AUDIO_OK) 00864 { 00865 return AUDIO_ERROR; 00866 } 00867 } 00868 else 00869 { /* INPUT_DEVICE_ANALOG_MIC */ 00870 /* Check if output device is currently used */ 00871 if(hAudioOut.OutputDevice != 0) 00872 { 00873 /* Reset record path on audio codec */ 00874 if(hAudioOut.AudioDrv->Init(AUDIO_I2C_ADDRESS, 00875 hAudioOut.OutputDevice, 00876 (uint8_t) hAudioOut.Volume, 00877 hAudioOut.Frequency) != 0) 00878 { 00879 return AUDIO_ERROR; 00880 } 00881 } 00882 else 00883 { 00884 /* De-initializes SAI interface */ 00885 if(AUDIO_SAIx_DeInit() != AUDIO_OK) 00886 { 00887 return AUDIO_ERROR; 00888 } 00889 00890 /* DeInit audio codec */ 00891 hAudioIn.AudioDrv->DeInit(); 00892 } 00893 } 00894 00895 /* Disable SAI PLL if no more device is used */ 00896 if(hAudioOut.OutputDevice == 0) 00897 { 00898 if (AUDIO_SAIx_PLL_DISABLE() != AUDIO_OK) 00899 { 00900 return AUDIO_ERROR; 00901 } 00902 } 00903 00904 /* Reset the audio input context */ 00905 memset(&hAudioIn, 0, sizeof(hAudioIn)); 00906 00907 return AUDIO_OK; 00908 } 00909 00910 /** 00911 * @brief Starts audio recording. 00912 * @param pbuf: Main buffer pointer for the recorded data storing 00913 * @param size: Current size of the recorded buffer 00914 * @note The Right channel is start at first with synchro on start of Left channel 00915 * @retval BSP AUDIO status 00916 */ 00917 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size) 00918 { 00919 hAudioIn.pRecBuf = pbuf; 00920 hAudioIn.RecSize = size; 00921 00922 00923 if(hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC) 00924 { 00925 if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 00926 { 00927 /* Allocate hAudioIn.LeftRecBuff buffer */ 00928 #if defined(BSP_AUDIO_USE_RTOS) 00929 hAudioIn.LeftRecBuff = (int32_t *)k_malloc((size / hAudioIn.ChannelNbr) * sizeof(int32_t)); 00930 #else 00931 hAudioIn.LeftRecBuff = (int32_t *)malloc((size / hAudioIn.ChannelNbr) * sizeof(int32_t)); 00932 #endif 00933 if(hAudioIn.LeftRecBuff == NULL) 00934 { 00935 return AUDIO_ERROR; 00936 } 00937 } 00938 00939 if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) 00940 { 00941 /* Allocate hAudioIn.RightRecBuff buffer */ 00942 #if defined(BSP_AUDIO_USE_RTOS) 00943 hAudioIn.RightRecBuff = (int32_t *)k_malloc((size / hAudioIn.ChannelNbr) * sizeof(int32_t)); 00944 #else 00945 hAudioIn.RightRecBuff = (int32_t *)malloc((size / hAudioIn.ChannelNbr) * sizeof(int32_t)); 00946 #endif 00947 if(hAudioIn.RightRecBuff == NULL) 00948 { 00949 return AUDIO_ERROR; 00950 } 00951 } 00952 00953 if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) 00954 { 00955 /* Call the Media layer start function for right channel */ 00956 if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmRightFilter, 00957 (int32_t*)hAudioIn.RightRecBuff, 00958 (hAudioIn.RecSize/hAudioIn.ChannelNbr)) != HAL_OK) 00959 { 00960 return AUDIO_ERROR; 00961 } 00962 } 00963 00964 if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 00965 { 00966 /* Call the Media layer start function for left channel */ 00967 if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmLeftFilter, 00968 (int32_t*)hAudioIn.LeftRecBuff, 00969 (hAudioIn.RecSize/hAudioIn.ChannelNbr)) != HAL_OK) 00970 { 00971 return AUDIO_ERROR; 00972 } 00973 } 00974 } 00975 else 00976 { /* INPUT_DEVICE_ANALOG_MIC */ 00977 /* Call the audio Codec Play function */ 00978 if (hAudioIn.AudioDrv->Play(AUDIO_I2C_ADDRESS, pbuf, size) != 0) 00979 { 00980 return AUDIO_ERROR; 00981 } 00982 00983 /* Start the process receive DMA */ 00984 if(HAL_OK != HAL_SAI_Receive_DMA(&BSP_AUDIO_hSai_Rx, (uint8_t*)pbuf, size)) 00985 { 00986 return AUDIO_ERROR; 00987 } 00988 } 00989 00990 return AUDIO_OK; 00991 } 00992 00993 /** 00994 * @brief Updates the audio frequency. 00995 * @param AudioFreq: Audio frequency used to record the audio stream. 00996 * @note This API should be called after the BSP_AUDIO_IN_Init() to adjust the 00997 * audio frequency. 00998 * @retval BSP AUDIO status 00999 */ 01000 uint8_t BSP_AUDIO_IN_SetFrequency(uint32_t AudioFreq) 01001 { 01002 uint8_t TxData[2] = {0x00, 0x00}; 01003 01004 /* Configure the SAI PLL according to the requested audio frequency */ 01005 if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK) 01006 { 01007 return AUDIO_ERROR; 01008 } 01009 01010 if (hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC) 01011 { 01012 /* De-initializes the Digital Filter for Sigma-Delta Modulators interface */ 01013 if(AUDIO_DFSDMx_DeInit() != AUDIO_OK) 01014 { 01015 return AUDIO_ERROR; 01016 } 01017 01018 /* Initializes the Digital Filter for Sigma-Delta Modulators interface */ 01019 if(AUDIO_DFSDMx_Init(AudioFreq) != AUDIO_OK) 01020 { 01021 return AUDIO_ERROR; 01022 } 01023 } 01024 else 01025 { /* INPUT_DEVICE_ANALOG_MIC */ 01026 /* Disable SAI peripheral to allow access to SAI internal registers */ 01027 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx); 01028 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Rx); 01029 01030 /* Update the SAI audio frequency configuration */ 01031 BSP_AUDIO_hSai_Tx.Init.Mckdiv = SAIClockDivider(AudioFreq); 01032 HAL_SAI_Init(&BSP_AUDIO_hSai_Tx); 01033 BSP_AUDIO_hSai_Rx.Init.Mckdiv = SAIClockDivider(AudioFreq); 01034 HAL_SAI_Init(&BSP_AUDIO_hSai_Rx); 01035 01036 /* Enable SAI peripheral to generate MCLK */ 01037 __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx); 01038 /* Transmit one byte to start FS generation */ 01039 if(HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000) != HAL_OK) 01040 { 01041 return AUDIO_ERROR; 01042 } 01043 } 01044 01045 hAudioIn.Frequency = AudioFreq; 01046 01047 return AUDIO_OK; 01048 } 01049 01050 /** 01051 * @brief Regular conversion complete callback. 01052 * @note In interrupt mode, user has to read conversion value in this function 01053 using HAL_DFSDM_FilterGetRegularValue. 01054 * @param hdfsdm_filter : DFSDM filter handle. 01055 * @retval None 01056 */ 01057 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01058 { 01059 uint32_t index; 01060 uint32_t recbufsize = (hAudioIn.RecSize/hAudioIn.ChannelNbr); 01061 01062 if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC) 01063 { 01064 for (index = (recbufsize / 2); index < recbufsize; index++) 01065 { 01066 hAudioIn.pRecBuf[2 * index] = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32768, 32767)); 01067 hAudioIn.pRecBuf[(2 * index) + 1] = (uint16_t)(SaturaLH((hAudioIn.RightRecBuff[index] >> 8), -32768, 32767)); 01068 } 01069 } 01070 else if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC1) 01071 { 01072 for (index = (recbufsize / 2); index < recbufsize; index++) 01073 { 01074 hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32768, 32767)); 01075 } 01076 } 01077 else if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2) 01078 { 01079 for (index = (recbufsize / 2); index < recbufsize; index++) 01080 { 01081 hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.RightRecBuff[index] >> 8), -32768, 32767)); 01082 } 01083 } 01084 01085 /* Invoke the registered 'TransferCompete' callback function (if any) */ 01086 if (hAudioIn.CbTransferComplete != (Audio_CallbackTypeDef)NULL) 01087 { 01088 if(hdfsdm_filter == &BSP_AUDIO_hDfsdmLeftFilter) 01089 { 01090 if (DmaLeftRecBuffCplt) BSP_ErrorHandler(); 01091 01092 DmaLeftRecBuffCplt = 1; 01093 } 01094 else 01095 { 01096 if (DmaRightRecBuffCplt) BSP_ErrorHandler(); 01097 01098 DmaRightRecBuffCplt = 1; 01099 } 01100 01101 if (((DmaLeftRecBuffCplt != 0) && (DmaRightRecBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC)) || 01102 ((DmaLeftRecBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC1)) || 01103 ((DmaRightRecBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2))) 01104 { 01105 hAudioIn.CbTransferComplete(); 01106 DmaLeftRecBuffCplt = 0; 01107 DmaRightRecBuffCplt = 0; 01108 } 01109 } 01110 } 01111 01112 /** 01113 * @brief Half regular conversion complete callback. 01114 * @param hdfsdm_filter : DFSDM filter handle. 01115 * @retval None 01116 */ 01117 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01118 { 01119 uint32_t index; 01120 uint32_t recbufsize = (hAudioIn.RecSize/hAudioIn.ChannelNbr); 01121 01122 if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC) 01123 { 01124 for (index = 0; index < (recbufsize / 2); index++) 01125 { 01126 hAudioIn.pRecBuf[2 * index] = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32768, 32767)); 01127 hAudioIn.pRecBuf[(2 * index) + 1] = (uint16_t)(SaturaLH((hAudioIn.RightRecBuff[index] >> 8), -32768, 32767)); 01128 } 01129 } 01130 else if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC1) 01131 { 01132 for (index = 0; index < (recbufsize / 2); index++) 01133 { 01134 hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32768, 32767)); 01135 } 01136 } 01137 else if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2) 01138 { 01139 for (index = 0; index < (recbufsize / 2); index++) 01140 { 01141 hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.RightRecBuff[index] >> 8), -32768, 32767)); 01142 } 01143 } 01144 01145 /* Invoke the registered 'HalfTransfer' callback function (if any) */ 01146 if (hAudioIn.CbHalfTransfer != (Audio_CallbackTypeDef)NULL) 01147 { 01148 if(hdfsdm_filter == &BSP_AUDIO_hDfsdmLeftFilter) 01149 { 01150 if (DmaLeftRecHalfBuffCplt) BSP_ErrorHandler(); 01151 01152 DmaLeftRecHalfBuffCplt = 1; 01153 } 01154 else 01155 { 01156 if (DmaRightRecHalfBuffCplt) BSP_ErrorHandler(); 01157 01158 DmaRightRecHalfBuffCplt = 1; 01159 } 01160 01161 01162 if (((DmaLeftRecHalfBuffCplt != 0) && (DmaRightRecHalfBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC)) || 01163 ((DmaLeftRecHalfBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC1)) || 01164 ((DmaRightRecHalfBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2))) 01165 { 01166 hAudioIn.CbHalfTransfer(); 01167 DmaLeftRecHalfBuffCplt = 0; 01168 DmaRightRecHalfBuffCplt = 0; 01169 } 01170 } 01171 } 01172 01173 /** 01174 * @brief Error callback. 01175 * @param hdfsdm_filter : DFSDM filter handle. 01176 * @retval None 01177 */ 01178 void HAL_DFSDM_FilterErrorCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01179 { 01180 /* Invoke the registered 'ErrorCallback' callback function (if any) */ 01181 if (hAudioIn.CbError != (Audio_CallbackTypeDef)NULL) 01182 { 01183 hAudioIn.CbError(); 01184 } 01185 } 01186 01187 /** 01188 * @brief SAI Rx Transfer completed callbacks. 01189 * @param hsai: SAI handle 01190 * @retval None 01191 */ 01192 void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai) 01193 { 01194 /* Invoke the registered 'TransferComplete' function (if any) */ 01195 if (hAudioIn.CbTransferComplete != (Audio_CallbackTypeDef)NULL) 01196 { 01197 hAudioIn.CbTransferComplete(); 01198 } 01199 } 01200 01201 /** 01202 * @brief SAI Rx Half Transfer completed callbacks. 01203 * @param hsai: SAI handle 01204 * @retval None 01205 */ 01206 void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai) 01207 { 01208 /* Invoke the registered 'HalfTransfer' callback function (if any) */ 01209 if (hAudioIn.CbHalfTransfer != (Audio_CallbackTypeDef)NULL) 01210 { 01211 hAudioIn.CbHalfTransfer(); 01212 } 01213 } 01214 01215 /** 01216 * @brief Stops audio recording. 01217 * @retval BSP AUDIO status 01218 */ 01219 uint8_t BSP_AUDIO_IN_Stop(void) 01220 { 01221 if (hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC) 01222 { 01223 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) 01224 { 01225 /* Call the Media layer stop function for right channel */ 01226 if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmRightFilter) != HAL_OK ) 01227 { 01228 return AUDIO_ERROR; 01229 } 01230 } 01231 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 01232 { 01233 /* Call the Media layer stop function for left channel */ 01234 if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK ) 01235 { 01236 return AUDIO_ERROR; 01237 } 01238 } 01239 01240 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 01241 { 01242 /* Free hAudioIn.LeftRecBuff buffer */ 01243 #if defined(BSP_AUDIO_USE_RTOS) 01244 k_free((void *)hAudioIn.LeftRecBuff); 01245 #else 01246 free((void *)hAudioIn.LeftRecBuff); 01247 #endif 01248 } 01249 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) 01250 { 01251 /* Free hAudioIn.RightRecBuff buffer */ 01252 #if defined(BSP_AUDIO_USE_RTOS) 01253 k_free((void *)hAudioIn.RightRecBuff); 01254 #else 01255 free((void *)hAudioIn.RightRecBuff); 01256 #endif 01257 } 01258 } 01259 else 01260 { /* INPUT_DEVICE_ANALOG_MIC */ 01261 /* Call Audio Codec Stop function */ 01262 if (hAudioIn.AudioDrv->Stop(AUDIO_I2C_ADDRESS, CODEC_PDWN_HW) != 0) 01263 { 01264 return AUDIO_ERROR; 01265 } 01266 01267 /* Wait at least 100ms */ 01268 HAL_Delay(100); 01269 01270 /* Stop DMA transfer of PCM samples towards the serial audio interface */ 01271 if (HAL_SAI_DMAStop(&BSP_AUDIO_hSai_Rx)!= HAL_OK) 01272 { 01273 return AUDIO_ERROR; 01274 } 01275 } 01276 01277 return AUDIO_OK; 01278 } 01279 01280 /** 01281 * @brief Pauses the audio file stream. 01282 * @retval BSP AUDIO status 01283 */ 01284 uint8_t BSP_AUDIO_IN_Pause(void) 01285 { 01286 if (hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC) 01287 { 01288 /* Call the Media layer stop function */ 01289 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) 01290 { 01291 if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmRightFilter) != HAL_OK) 01292 { 01293 return AUDIO_ERROR; 01294 } 01295 } 01296 01297 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 01298 { 01299 if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK) 01300 { 01301 return AUDIO_ERROR; 01302 } 01303 } 01304 } 01305 else 01306 { /* INPUT_DEVICE_ANALOG_MIC */ 01307 /* Pause DMA transfer of PCM samples towards the serial audio interface */ 01308 if (HAL_SAI_DMAPause(&BSP_AUDIO_hSai_Rx)!= HAL_OK) 01309 { 01310 return AUDIO_ERROR; 01311 } 01312 } 01313 01314 return AUDIO_OK; 01315 } 01316 01317 /** 01318 * @brief Resumes the audio file stream. 01319 * @retval BSP AUDIO status 01320 */ 01321 uint8_t BSP_AUDIO_IN_Resume(void) 01322 { 01323 if (hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC) 01324 { 01325 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) 01326 { 01327 /* Call the Media layer start function for right channel */ 01328 if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmRightFilter, 01329 (int32_t*)hAudioIn.RightRecBuff, 01330 (hAudioIn.RecSize/hAudioIn.ChannelNbr)) != HAL_OK) 01331 { 01332 return AUDIO_ERROR; 01333 } 01334 } 01335 01336 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 01337 { 01338 /* Call the Media layer start function for left channel */ 01339 if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmLeftFilter, 01340 (int32_t*)hAudioIn.LeftRecBuff, 01341 (hAudioIn.RecSize/hAudioIn.ChannelNbr)) != HAL_OK) 01342 { 01343 return AUDIO_ERROR; 01344 } 01345 } 01346 } 01347 else 01348 { /* INPUT_DEVICE_ANALOG_MIC */ 01349 /* Resume DMA transfer of PCM samples towards the serial audio interface */ 01350 if (HAL_SAI_DMAResume(&BSP_AUDIO_hSai_Rx) != HAL_OK) 01351 { 01352 return AUDIO_ERROR; 01353 } 01354 } 01355 01356 return AUDIO_OK; 01357 } 01358 01359 /** 01360 * @brief register user callback functions 01361 * @param ErrorCallback: pointer to the error callback function 01362 * @param HalfTransferCallback: pointer to the half transfer callback function 01363 * @param TransferCompleteCallback: pointer to the transfer complete callback function 01364 * @retval None 01365 */ 01366 void BSP_AUDIO_IN_RegisterCallbacks(Audio_CallbackTypeDef ErrorCallback, 01367 Audio_CallbackTypeDef HalfTransferCallback, 01368 Audio_CallbackTypeDef TransferCompleteCallback) 01369 { 01370 hAudioIn.CbError = ErrorCallback; 01371 hAudioIn.CbHalfTransfer = HalfTransferCallback; 01372 hAudioIn.CbTransferComplete = TransferCompleteCallback; 01373 } 01374 01375 /** 01376 * @} 01377 */ 01378 01379 /* Private functions --------------------------------------------------------*/ 01380 /** @addtogroup STM32L4R9I_DISCOVERY_AUDIO_Private_Functions 01381 * @{ 01382 */ 01383 /** 01384 * @brief Initializes the Audio Codec audio interface (SAI). 01385 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 01386 * @retval BSP AUDIO status 01387 */ 01388 static uint8_t AUDIO_SAIx_Init(uint32_t AudioFreq) 01389 { 01390 uint8_t TxData[2] = {0x00, 0x00}; 01391 01392 /* Initialize the BSP_AUDIO_hSai_Xx instances parameter */ 01393 BSP_AUDIO_hSai_Tx.Instance = SAI1_Block_A; 01394 BSP_AUDIO_hSai_Rx.Instance = SAI1_Block_B; 01395 01396 /* Disable SAI peripheral to allow access to SAI internal registers */ 01397 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx); 01398 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Rx); 01399 01400 /*******************************/ 01401 /* SAI block used for playback */ 01402 /*******************************/ 01403 /* Configure SAI_Block_x used for transmit 01404 LSBFirst: Disabled 01405 DataSize: 16 */ 01406 BSP_AUDIO_hSai_Tx.Init.AudioMode = SAI_MODEMASTER_TX; 01407 BSP_AUDIO_hSai_Tx.Init.Synchro = SAI_ASYNCHRONOUS; 01408 BSP_AUDIO_hSai_Tx.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 01409 BSP_AUDIO_hSai_Tx.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE; 01410 BSP_AUDIO_hSai_Tx.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; 01411 BSP_AUDIO_hSai_Tx.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 01412 BSP_AUDIO_hSai_Tx.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV; 01413 BSP_AUDIO_hSai_Tx.Init.Mckdiv = SAIClockDivider(AudioFreq); 01414 BSP_AUDIO_hSai_Tx.Init.MonoStereoMode = SAI_STEREOMODE; 01415 BSP_AUDIO_hSai_Tx.Init.CompandingMode = SAI_NOCOMPANDING; 01416 BSP_AUDIO_hSai_Tx.Init.TriState = SAI_OUTPUT_NOTRELEASED; 01417 BSP_AUDIO_hSai_Tx.Init.Protocol = SAI_FREE_PROTOCOL; 01418 BSP_AUDIO_hSai_Tx.Init.DataSize = SAI_DATASIZE_16; 01419 BSP_AUDIO_hSai_Tx.Init.FirstBit = SAI_FIRSTBIT_MSB; 01420 BSP_AUDIO_hSai_Tx.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; 01421 01422 /* Configure SAI_Block_x Frame 01423 Frame Length: 32 01424 Frame active Length: 16 01425 FS Definition: Start frame + Channel Side identification 01426 FS Polarity: FS active Low 01427 FS Offset: FS asserted one bit before the first bit of slot 0 */ 01428 BSP_AUDIO_hSai_Tx.FrameInit.FrameLength = 32; 01429 BSP_AUDIO_hSai_Tx.FrameInit.ActiveFrameLength = 16; 01430 BSP_AUDIO_hSai_Tx.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 01431 BSP_AUDIO_hSai_Tx.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 01432 BSP_AUDIO_hSai_Tx.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 01433 01434 /* Configure SAI Block_x Slot 01435 Slot First Bit Offset: 0 01436 Slot Size : 16 01437 Slot Number: 2 01438 Slot Active: Slots 0 and 1 actives */ 01439 BSP_AUDIO_hSai_Tx.SlotInit.FirstBitOffset = 0; 01440 BSP_AUDIO_hSai_Tx.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 01441 BSP_AUDIO_hSai_Tx.SlotInit.SlotNumber = 2; 01442 BSP_AUDIO_hSai_Tx.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1; 01443 01444 /*****************************/ 01445 /* SAI block used for record */ 01446 /*****************************/ 01447 /* Configure SAI_Block_x used for receive 01448 LSBFirst: Disabled 01449 DataSize: 16 */ 01450 BSP_AUDIO_hSai_Rx.Init.AudioMode = SAI_MODESLAVE_RX; 01451 BSP_AUDIO_hSai_Rx.Init.Synchro = SAI_SYNCHRONOUS; 01452 BSP_AUDIO_hSai_Rx.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 01453 BSP_AUDIO_hSai_Rx.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE; 01454 BSP_AUDIO_hSai_Rx.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; 01455 BSP_AUDIO_hSai_Rx.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 01456 BSP_AUDIO_hSai_Rx.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV; 01457 BSP_AUDIO_hSai_Rx.Init.Mckdiv = SAIClockDivider(AudioFreq); 01458 BSP_AUDIO_hSai_Rx.Init.MonoStereoMode = SAI_MONOMODE; 01459 BSP_AUDIO_hSai_Rx.Init.CompandingMode = SAI_NOCOMPANDING; 01460 BSP_AUDIO_hSai_Rx.Init.TriState = SAI_OUTPUT_NOTRELEASED; 01461 BSP_AUDIO_hSai_Rx.Init.Protocol = SAI_FREE_PROTOCOL; 01462 BSP_AUDIO_hSai_Rx.Init.DataSize = SAI_DATASIZE_16; 01463 BSP_AUDIO_hSai_Rx.Init.FirstBit = SAI_FIRSTBIT_MSB; 01464 BSP_AUDIO_hSai_Rx.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; 01465 01466 /* Configure SAI_Block_x Frame 01467 Frame Length: 32 01468 Frame active Length: 16 01469 FS Definition: Start frame + Channel Side identification 01470 FS Polarity: FS active Low 01471 FS Offset: FS asserted one bit before the first bit of slot 0 */ 01472 BSP_AUDIO_hSai_Rx.FrameInit.FrameLength = 32; 01473 BSP_AUDIO_hSai_Rx.FrameInit.ActiveFrameLength = 16; 01474 BSP_AUDIO_hSai_Rx.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 01475 BSP_AUDIO_hSai_Rx.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 01476 BSP_AUDIO_hSai_Rx.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 01477 01478 /* Configure SAI Block_x Slot 01479 Slot First Bit Offset: 0 01480 Slot Size : 16 01481 Slot Number: 2 01482 Slot Active: Slots 0 and 1 actives */ 01483 BSP_AUDIO_hSai_Rx.SlotInit.FirstBitOffset = 0; 01484 BSP_AUDIO_hSai_Rx.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 01485 BSP_AUDIO_hSai_Rx.SlotInit.SlotNumber = 2; 01486 BSP_AUDIO_hSai_Rx.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1; 01487 01488 /*********************************/ 01489 /* Initializes the SAI peripheral*/ 01490 /*********************************/ 01491 if (HAL_SAI_Init(&BSP_AUDIO_hSai_Tx) != HAL_OK) 01492 { 01493 return AUDIO_ERROR; 01494 } 01495 if (HAL_SAI_Init(&BSP_AUDIO_hSai_Rx) != HAL_OK) 01496 { 01497 return AUDIO_ERROR; 01498 } 01499 01500 /******************************************/ 01501 /* Enable SAI peripheral to generate MCLK */ 01502 /******************************************/ 01503 __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx); 01504 /* Transmit one byte to start FS generation */ 01505 if(HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000) != HAL_OK) 01506 { 01507 return AUDIO_ERROR; 01508 } 01509 01510 return AUDIO_OK; 01511 } 01512 01513 /** 01514 * @brief De-initializes the Audio Codec audio interface (SAI). 01515 * @retval BSP AUDIO status 01516 */ 01517 static uint8_t AUDIO_SAIx_DeInit(void) 01518 { 01519 /* Disable the SAI audio block */ 01520 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx); 01521 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Rx); 01522 01523 /* De-initializes the SAI peripheral */ 01524 if (HAL_SAI_DeInit(&BSP_AUDIO_hSai_Tx) != HAL_OK) 01525 { 01526 return AUDIO_ERROR; 01527 } 01528 if (HAL_SAI_DeInit(&BSP_AUDIO_hSai_Rx) != HAL_OK) 01529 { 01530 return AUDIO_ERROR; 01531 } 01532 01533 return AUDIO_OK; 01534 } 01535 01536 /** 01537 * @brief SAI MSP Init 01538 * @param hsai : pointer to a SAI_HandleTypeDef structure 01539 * @retval None 01540 */ 01541 void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai) 01542 { 01543 GPIO_InitTypeDef GPIO_InitStruct; 01544 01545 /* Enable SAI clock */ 01546 __HAL_RCC_SAI1_CLK_ENABLE(); 01547 01548 if(hsai->Instance == SAI1_Block_A) 01549 { 01550 /* SAI pins configuration: FS, SCK, MCLK and SD pins */ 01551 __HAL_RCC_GPIOB_CLK_ENABLE(); 01552 __HAL_RCC_GPIOE_CLK_ENABLE(); 01553 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 01554 GPIO_InitStruct.Pull = GPIO_NOPULL; 01555 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 01556 GPIO_InitStruct.Alternate = GPIO_AF13_SAI1; 01557 GPIO_InitStruct.Pin = GPIO_PIN_2; 01558 HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); /* SAI1_MCLK_A */ 01559 GPIO_InitStruct.Pin = GPIO_PIN_9; 01560 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* SAI1_FS_A */ 01561 GPIO_InitStruct.Pin = GPIO_PIN_5; 01562 HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); /* SAI1_SCK_A */ 01563 GPIO_InitStruct.Pin = GPIO_PIN_6; 01564 HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); /* SAI1_SD_A */ 01565 01566 /* Configure the hDmaSaiTx handle parameters */ 01567 __HAL_RCC_DMA2_CLK_ENABLE(); 01568 __HAL_RCC_DMAMUX1_CLK_ENABLE(); 01569 hDmaSaiTx.Init.Request = DMA_REQUEST_SAI1_A; 01570 hDmaSaiTx.Init.Direction = DMA_MEMORY_TO_PERIPH; 01571 hDmaSaiTx.Init.PeriphInc = DMA_PINC_DISABLE; 01572 hDmaSaiTx.Init.MemInc = DMA_MINC_ENABLE; 01573 hDmaSaiTx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; 01574 hDmaSaiTx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; 01575 hDmaSaiTx.Init.Mode = DMA_CIRCULAR; 01576 hDmaSaiTx.Init.Priority = DMA_PRIORITY_HIGH; 01577 hDmaSaiTx.Instance = DMA2_Channel1; 01578 /* Associate the DMA handle */ 01579 __HAL_LINKDMA(hsai, hdmatx, hDmaSaiTx); 01580 /* Deinitialize the Stream for new transfer */ 01581 HAL_DMA_DeInit(&hDmaSaiTx); 01582 /* Configure the DMA Stream */ 01583 HAL_DMA_Init(&hDmaSaiTx); 01584 /* SAI DMA IRQ Channel configuration */ 01585 HAL_NVIC_SetPriority(DMA2_Channel1_IRQn, 5, 0); 01586 HAL_NVIC_EnableIRQ(DMA2_Channel1_IRQn); 01587 } 01588 else /* SAI1_BlockB */ 01589 { 01590 /* SAI pins configuration: SD pin */ 01591 __HAL_RCC_GPIOB_CLK_ENABLE(); 01592 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 01593 GPIO_InitStruct.Pull = GPIO_NOPULL; 01594 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 01595 GPIO_InitStruct.Alternate = GPIO_AF13_SAI1; 01596 GPIO_InitStruct.Pin = GPIO_PIN_5; 01597 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* SAI1_SD_B */ 01598 01599 /* Configure the hDmaSaiRx handle parameters */ 01600 __HAL_RCC_DMA2_CLK_ENABLE(); 01601 __HAL_RCC_DMAMUX1_CLK_ENABLE(); 01602 hDmaSaiRx.Init.Request = DMA_REQUEST_SAI1_B; 01603 hDmaSaiRx.Init.Direction = DMA_PERIPH_TO_MEMORY; 01604 hDmaSaiRx.Init.PeriphInc = DMA_PINC_DISABLE; 01605 hDmaSaiRx.Init.MemInc = DMA_MINC_ENABLE; 01606 hDmaSaiRx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; 01607 hDmaSaiRx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; 01608 hDmaSaiRx.Init.Mode = DMA_CIRCULAR; 01609 hDmaSaiRx.Init.Priority = DMA_PRIORITY_HIGH; 01610 hDmaSaiRx.Instance = DMA2_Channel2; 01611 /* Associate the DMA handle */ 01612 __HAL_LINKDMA(hsai, hdmarx, hDmaSaiRx); 01613 /* Deinitialize the Stream for new transfer */ 01614 HAL_DMA_DeInit(&hDmaSaiRx); 01615 /* Configure the DMA Stream */ 01616 HAL_DMA_Init(&hDmaSaiRx); 01617 /* SAI DMA IRQ Channel configuration */ 01618 HAL_NVIC_SetPriority(DMA2_Channel2_IRQn, 5, 0); 01619 HAL_NVIC_EnableIRQ(DMA2_Channel2_IRQn); 01620 } 01621 } 01622 01623 /** 01624 * @brief SAI MSP De-init 01625 * @param hsai : pointer to a SAI_HandleTypeDef structure 01626 * @retval None 01627 */ 01628 void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai) 01629 { 01630 if(hsai->Instance == SAI1_Block_A) 01631 { 01632 /* Disable SAI DMA Channel IRQ */ 01633 HAL_NVIC_DisableIRQ(DMA2_Channel1_IRQn); 01634 01635 /* Reset the DMA Stream configuration*/ 01636 HAL_DMA_DeInit(&hDmaSaiTx); 01637 01638 /* Don't disable the DMA clock used for other SAI block */ 01639 /* __HAL_RCC_DMA2_CLK_DISABLE(); */ 01640 /* __HAL_RCC_DMAMUX1_CLK_DISABLE(); */ 01641 01642 /* De-initialize FS, SCK, MCK and SD pins*/ 01643 HAL_GPIO_DeInit(GPIOE, GPIO_PIN_2); /* SAI1_MCLK_A */ 01644 HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9); /* SAI1_FS_A */ 01645 HAL_GPIO_DeInit(GPIOE, GPIO_PIN_5); /* SAI1_SCK_A */ 01646 HAL_GPIO_DeInit(GPIOE, GPIO_PIN_6); /* SAI1_SD_A */ 01647 01648 /* Don't disable SAI clock used for other SAI block */ 01649 /*__HAL_RCC_SAI1_CLK_DISABLE(); */ 01650 } 01651 else /* SAI1_BlockB */ 01652 { 01653 /* Disable SAI DMA Channel IRQ */ 01654 HAL_NVIC_DisableIRQ(DMA2_Channel2_IRQn); 01655 01656 /* Reset the DMA Stream configuration*/ 01657 HAL_DMA_DeInit(&hDmaSaiRx); 01658 01659 /* De-initialize SD pin */ 01660 HAL_GPIO_DeInit(GPIOB, GPIO_PIN_5); /* SAI1_SD_B */ 01661 01662 /* Disable SAI clock */ 01663 __HAL_RCC_SAI1_CLK_DISABLE(); 01664 } 01665 } 01666 01667 /** 01668 * @} 01669 */ 01670 01671 /** @addtogroup STM32L4R9I_DISCOVERY_AUDIO_Private_Functions 01672 * @{ 01673 */ 01674 01675 /** 01676 * @brief Initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01677 * @param AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral. 01678 * @retval BSP AUDIO status 01679 */ 01680 static uint8_t AUDIO_DFSDMx_Init(uint32_t AudioFreq) 01681 { 01682 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 01683 { 01684 /*####CHANNEL 3####*/ 01685 hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Activation = ENABLE; 01686 hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01687 /* Set the DFSDM clock OUT audio frequency configuration */ 01688 hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Divider = DFSDMClockDivider(AudioFreq); 01689 hAudioIn.hDfsdmLeftChannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01690 hAudioIn.hDfsdmLeftChannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01691 hAudioIn.hDfsdmLeftChannel.Init.Input.Pins = DFSDM_CHANNEL_SAME_CHANNEL_PINS; 01692 /* Request to sample stable data for LEFT micro on Rising edge */ 01693 hAudioIn.hDfsdmLeftChannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_RISING; 01694 hAudioIn.hDfsdmLeftChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01695 hAudioIn.hDfsdmLeftChannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_SINC1_ORDER; 01696 hAudioIn.hDfsdmLeftChannel.Init.Awd.Oversampling = 10; 01697 hAudioIn.hDfsdmLeftChannel.Init.Offset = 0; 01698 hAudioIn.hDfsdmLeftChannel.Init.RightBitShift = DFSDMRightBitShift(AudioFreq); 01699 hAudioIn.hDfsdmLeftChannel.Instance = DFSDM1_Channel1; 01700 01701 /* Init the DFSDM Channel */ 01702 if (HAL_DFSDM_ChannelInit(&hAudioIn.hDfsdmLeftChannel) != HAL_OK) 01703 { 01704 return AUDIO_ERROR; 01705 } 01706 } 01707 01708 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) 01709 { 01710 /*####CHANNEL 2####*/ 01711 hAudioIn.hDfsdmRightChannel.Init.OutputClock.Activation = ENABLE; 01712 hAudioIn.hDfsdmRightChannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01713 /* Set the DFSDM clock OUT audio frequency configuration */ 01714 hAudioIn.hDfsdmRightChannel.Init.OutputClock.Divider = DFSDMClockDivider(AudioFreq); 01715 hAudioIn.hDfsdmRightChannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01716 hAudioIn.hDfsdmRightChannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01717 hAudioIn.hDfsdmRightChannel.Init.Input.Pins = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS; 01718 /* Request to sample stable data for LEFT micro on Rising edge */ 01719 hAudioIn.hDfsdmRightChannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_FALLING; 01720 hAudioIn.hDfsdmRightChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01721 hAudioIn.hDfsdmRightChannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_SINC1_ORDER; 01722 hAudioIn.hDfsdmRightChannel.Init.Awd.Oversampling = 10; 01723 hAudioIn.hDfsdmRightChannel.Init.Offset = 0; 01724 hAudioIn.hDfsdmRightChannel.Init.RightBitShift = DFSDMRightBitShift(AudioFreq); 01725 hAudioIn.hDfsdmRightChannel.Instance = DFSDM1_Channel0; 01726 01727 /* Init the DFSDM Channel */ 01728 if (HAL_DFSDM_ChannelInit(&hAudioIn.hDfsdmRightChannel) != HAL_OK) 01729 { 01730 return AUDIO_ERROR; 01731 } 01732 } 01733 01734 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 01735 { 01736 /*####FILTER 0####*/ 01737 BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01738 BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.FastMode = ENABLE; 01739 BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.DmaMode = ENABLE; 01740 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01741 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ScanMode = DISABLE; 01742 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.DmaMode = DISABLE; 01743 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO; 01744 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES; 01745 BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.SincOrder = DFSDMFilterOrder(AudioFreq); 01746 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01747 BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.Oversampling = DFSDMOverSampling(AudioFreq); 01748 BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.IntOversampling = 1; 01749 BSP_AUDIO_hDfsdmLeftFilter.Instance = DFSDM1_Filter0; 01750 01751 /* Init the DFSDM Filter */ 01752 if (HAL_DFSDM_FilterInit(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK) 01753 { 01754 return AUDIO_ERROR; 01755 } 01756 01757 /* Configure regular channel */ 01758 if (HAL_DFSDM_FilterConfigRegChannel(&BSP_AUDIO_hDfsdmLeftFilter, 01759 DFSDM_CHANNEL_1, 01760 DFSDM_CONTINUOUS_CONV_ON) != HAL_OK) 01761 { 01762 return AUDIO_ERROR; 01763 } 01764 } 01765 01766 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) 01767 { 01768 /*####FILTER 1####*/ 01769 if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2) 01770 { 01771 BSP_AUDIO_hDfsdmRightFilter.Init.RegularParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01772 } 01773 else 01774 { 01775 BSP_AUDIO_hDfsdmRightFilter.Init.RegularParam.Trigger = DFSDM_FILTER_SYNC_TRIGGER; 01776 } 01777 BSP_AUDIO_hDfsdmRightFilter.Init.RegularParam.FastMode = ENABLE; 01778 BSP_AUDIO_hDfsdmRightFilter.Init.RegularParam.DmaMode = ENABLE; 01779 BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01780 BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.ScanMode = DISABLE; 01781 BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.DmaMode = DISABLE; 01782 BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO; 01783 BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES; 01784 BSP_AUDIO_hDfsdmRightFilter.Init.FilterParam.SincOrder = DFSDMFilterOrder(AudioFreq); 01785 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01786 BSP_AUDIO_hDfsdmRightFilter.Init.FilterParam.Oversampling = DFSDMOverSampling(AudioFreq); 01787 BSP_AUDIO_hDfsdmRightFilter.Init.FilterParam.IntOversampling = 1; 01788 BSP_AUDIO_hDfsdmRightFilter.Instance = DFSDM1_Filter1; 01789 01790 /* Init the DFSDM Filter */ 01791 if (HAL_DFSDM_FilterInit(&BSP_AUDIO_hDfsdmRightFilter) != HAL_OK) 01792 { 01793 return AUDIO_ERROR; 01794 } 01795 01796 /* Configure regular channel */ 01797 if (HAL_DFSDM_FilterConfigRegChannel(&BSP_AUDIO_hDfsdmRightFilter, 01798 DFSDM_CHANNEL_0, 01799 DFSDM_CONTINUOUS_CONV_ON) != HAL_OK) 01800 { 01801 return AUDIO_ERROR; 01802 } 01803 } 01804 01805 return AUDIO_OK; 01806 } 01807 01808 /** 01809 * @brief De-initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01810 * @retval BSP AUDIO status 01811 */ 01812 static uint8_t AUDIO_DFSDMx_DeInit(void) 01813 { 01814 /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */ 01815 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) 01816 { 01817 if (HAL_DFSDM_FilterDeInit(&BSP_AUDIO_hDfsdmRightFilter) != HAL_OK) 01818 { 01819 return AUDIO_ERROR; 01820 } 01821 } 01822 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 01823 { 01824 if (HAL_DFSDM_FilterDeInit(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK) 01825 { 01826 return AUDIO_ERROR; 01827 } 01828 } 01829 01830 /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */ 01831 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) 01832 { 01833 if (HAL_DFSDM_ChannelDeInit(&hAudioIn.hDfsdmRightChannel) != HAL_OK) 01834 { 01835 return AUDIO_ERROR; 01836 } 01837 } 01838 if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 01839 { 01840 if (HAL_DFSDM_ChannelDeInit(&hAudioIn.hDfsdmLeftChannel) != HAL_OK) 01841 { 01842 return AUDIO_ERROR; 01843 } 01844 } 01845 01846 /* DFSDM reset */ 01847 __HAL_RCC_DFSDM1_FORCE_RESET(); 01848 __HAL_RCC_DFSDM1_RELEASE_RESET(); 01849 01850 return AUDIO_OK; 01851 } 01852 01853 /** 01854 * @brief Initializes the DFSDM channel MSP. 01855 * @param hdfsdm_channel : DFSDM channel handle. 01856 * @retval None 01857 */ 01858 void HAL_DFSDM_ChannelMspInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) 01859 { 01860 if (((hdfsdm_channel->Instance == DFSDM1_Channel1) && ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) != 0)) || \ 01861 ((hdfsdm_channel->Instance == DFSDM1_Channel0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2))) 01862 { 01863 GPIO_InitTypeDef GPIO_InitStruct; 01864 01865 /* Enable DFSDM clock */ 01866 __HAL_RCC_DFSDM1_CLK_ENABLE(); 01867 01868 /* DFSDM pins configuration: DFSDM1_CKOUT, DFSDM1_DATIN1 pins */ 01869 __HAL_RCC_GPIOB_CLK_ENABLE(); 01870 __HAL_RCC_GPIOC_CLK_ENABLE(); 01871 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 01872 GPIO_InitStruct.Pull = GPIO_NOPULL; 01873 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 01874 GPIO_InitStruct.Alternate = GPIO_AF6_DFSDM1; 01875 GPIO_InitStruct.Pin = GPIO_PIN_2; 01876 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /* DFSDM1_CKOUT */ 01877 GPIO_InitStruct.Pin = GPIO_PIN_12; 01878 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* DFSDM1_DATIN1 */ 01879 01880 /* Enable MIC_VDD (PH2) */ 01881 __HAL_RCC_GPIOH_CLK_ENABLE(); 01882 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 01883 GPIO_InitStruct.Pull = GPIO_NOPULL; 01884 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 01885 GPIO_InitStruct.Pin = GPIO_PIN_2; 01886 HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); 01887 HAL_GPIO_WritePin(GPIOH, GPIO_PIN_2, GPIO_PIN_SET); 01888 } 01889 } 01890 01891 /** 01892 * @brief De-initializes the DFSDM channel MSP. 01893 * @param hdfsdm_channel : DFSDM channel handle. 01894 * @retval None 01895 */ 01896 void HAL_DFSDM_ChannelMspDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) 01897 { 01898 if (((hdfsdm_channel->Instance == DFSDM1_Channel1) && ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) != 0)) || \ 01899 ((hdfsdm_channel->Instance == DFSDM1_Channel0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2))) 01900 { 01901 /* Disable MIC_VDD (PH2) */ 01902 HAL_GPIO_WritePin(GPIOH, GPIO_PIN_2, GPIO_PIN_RESET); 01903 HAL_GPIO_DeInit(GPIOH, GPIO_PIN_2); 01904 01905 /* De-initialize DFSDM1_CKOUT, DFSDM1_DATIN1 pins */ 01906 HAL_GPIO_DeInit(GPIOC, GPIO_PIN_2); /* DFSDM1_CKOUT */ 01907 HAL_GPIO_DeInit(GPIOB, GPIO_PIN_12); /* DFSDM1_DATIN1 */ 01908 01909 /* Disable DFSDM1 */ 01910 __HAL_RCC_DFSDM1_CLK_DISABLE(); 01911 } 01912 } 01913 01914 /** 01915 * @brief Initializes the DFSDM filter MSP. 01916 * @param hdfsdm_filter : DFSDM filter handle. 01917 * @retval None 01918 */ 01919 void HAL_DFSDM_FilterMspInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01920 { 01921 if(hdfsdm_filter->Instance == DFSDM1_Filter0) 01922 { 01923 /* Enable the DMA clock */ 01924 __HAL_RCC_DMA1_CLK_ENABLE(); 01925 __HAL_RCC_DMAMUX1_CLK_ENABLE(); 01926 01927 /* Configure the hAudioIn.hDmaDfsdmLeft handle parameters */ 01928 hAudioIn.hDmaDfsdmLeft.Init.Request = DMA_REQUEST_DFSDM1_FLT0; 01929 hAudioIn.hDmaDfsdmLeft.Init.Direction = DMA_PERIPH_TO_MEMORY; 01930 hAudioIn.hDmaDfsdmLeft.Init.PeriphInc = DMA_PINC_DISABLE; 01931 hAudioIn.hDmaDfsdmLeft.Init.MemInc = DMA_MINC_ENABLE; 01932 hAudioIn.hDmaDfsdmLeft.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; 01933 hAudioIn.hDmaDfsdmLeft.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; 01934 hAudioIn.hDmaDfsdmLeft.Init.Mode = DMA_CIRCULAR; 01935 hAudioIn.hDmaDfsdmLeft.Init.Priority = DMA_PRIORITY_HIGH; 01936 hAudioIn.hDmaDfsdmLeft.Instance = DMA1_Channel4; 01937 01938 /* Associate the DMA handle */ 01939 __HAL_LINKDMA(hdfsdm_filter, hdmaReg, hAudioIn.hDmaDfsdmLeft); 01940 01941 /* Reset DMA handle state */ 01942 __HAL_DMA_RESET_HANDLE_STATE(&hAudioIn.hDmaDfsdmLeft); 01943 01944 /* Configure the DMA Channel */ 01945 HAL_DMA_Init(&hAudioIn.hDmaDfsdmLeft); 01946 01947 /* DMA IRQ Channel configuration */ 01948 HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 5, 0); 01949 HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn); 01950 } 01951 else /* DFSDM1_Filter1 */ 01952 { 01953 if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2) 01954 { 01955 /* Enable the DMA clock needed if only MIC2 is used */ 01956 __HAL_RCC_DMA1_CLK_ENABLE(); 01957 __HAL_RCC_DMAMUX1_CLK_ENABLE(); 01958 } 01959 01960 /* Configure the hAudioIn.hDmaDfsdmRight handle parameters */ 01961 hAudioIn.hDmaDfsdmRight.Init.Request = DMA_REQUEST_DFSDM1_FLT1; 01962 hAudioIn.hDmaDfsdmRight.Init.Direction = DMA_PERIPH_TO_MEMORY; 01963 hAudioIn.hDmaDfsdmRight.Init.PeriphInc = DMA_PINC_DISABLE; 01964 hAudioIn.hDmaDfsdmRight.Init.MemInc = DMA_MINC_ENABLE; 01965 hAudioIn.hDmaDfsdmRight.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; 01966 hAudioIn.hDmaDfsdmRight.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; 01967 hAudioIn.hDmaDfsdmRight.Init.Mode = DMA_CIRCULAR; 01968 hAudioIn.hDmaDfsdmRight.Init.Priority = DMA_PRIORITY_HIGH; 01969 hAudioIn.hDmaDfsdmRight.Instance = DMA1_Channel5; 01970 01971 /* Associate the DMA handle */ 01972 __HAL_LINKDMA(hdfsdm_filter, hdmaReg, hAudioIn.hDmaDfsdmRight); 01973 01974 /* Reset DMA handle state */ 01975 __HAL_DMA_RESET_HANDLE_STATE(&hAudioIn.hDmaDfsdmRight); 01976 01977 /* Configure the DMA Channel */ 01978 HAL_DMA_Init(&hAudioIn.hDmaDfsdmRight); 01979 01980 /* DMA IRQ Channel configuration */ 01981 HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 5, 0); 01982 HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn); 01983 } 01984 } 01985 01986 /** 01987 * @brief De-initializes the DFSDM filter MSP. 01988 * @param hdfsdm_filter : DFSDM filter handle. 01989 * @retval None 01990 */ 01991 void HAL_DFSDM_FilterMspDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01992 { 01993 if(hdfsdm_filter->Instance == DFSDM1_Filter0) 01994 { 01995 /* Disable DMA Channel IRQ */ 01996 HAL_NVIC_DisableIRQ(DMA1_Channel4_IRQn); 01997 01998 /* De-initialize the DMA Channel */ 01999 HAL_DMA_DeInit(&hAudioIn.hDmaDfsdmLeft); 02000 } 02001 else /* DFSDM1_Filter1 */ 02002 { 02003 /* Disable DMA Channel IRQ */ 02004 HAL_NVIC_DisableIRQ(DMA1_Channel5_IRQn); 02005 02006 /* De-initialize the DMA Channel */ 02007 HAL_DMA_DeInit(&hAudioIn.hDmaDfsdmRight); 02008 } 02009 } 02010 02011 /** 02012 * @brief Configures the SAI PLL clock according to the required audio frequency. 02013 * @param Frequency: Audio frequency. 02014 * @retval BSP AUDIO status 02015 * @note The SAI PLL input clock must be configured in the user application. 02016 * The SAI PLL configuration done within this function assumes that 02017 * the SAI PLL input clock runs at 4 MHz. 02018 */ 02019 static uint8_t AUDIO_SAIPLLConfig(uint32_t Frequency) 02020 { 02021 RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct; 02022 02023 /* Retrieve actual RCC configuration */ 02024 HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct); 02025 02026 if ( (Frequency == AUDIO_FREQUENCY_11K) 02027 || (Frequency == AUDIO_FREQUENCY_22K) 02028 || (Frequency == AUDIO_FREQUENCY_44K) ) 02029 { 02030 /* Configure PLLSAI prescalers */ 02031 /* SAI clock config 02032 PLLSAI1_VCO= 4 Mhz * PLLSAI1N = 4 * 48 = VCO_192M 02033 SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 192/17 = 11.294 Mhz */ 02034 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 02035 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1M = 1; 02036 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 48; 02037 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = 17; 02038 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK; 02039 RCC_ExCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; 02040 } 02041 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 02042 { 02043 /* SAI clock config 02044 PLLSAI2_VCO= 4 Mhz * PLLSAI1N = 4 * 86 = VCO_344M 02045 SAI_CK_x = PLLSAI1_VCO/PLLSAI2P = 344/7 = 49.142 Mhz */ 02046 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 02047 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1M = 1; 02048 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 86; 02049 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = 7; 02050 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK; 02051 RCC_ExCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; 02052 } 02053 02054 if (HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct) != HAL_OK) 02055 { 02056 return AUDIO_ERROR; 02057 } 02058 02059 return AUDIO_OK; 02060 } 02061 02062 /** 02063 * @} 02064 */ 02065 02066 /** 02067 * @} 02068 */ 02069 02070 /** 02071 * @} 02072 */ 02073 02074 /** 02075 * @} 02076 */ 02077 02078 /** 02079 * @} 02080 */ 02081 02082 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Wed Jul 13 2022 19:15:17 by
