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