STM32L476G-Discovery board drivers V1.0.0
Dependents: DiscoLogger DISCO_L476VG_GlassLCD DISCO_L476VG_MicrophoneRecorder DISCO_L476VG_UART ... more
stm32l476g_discovery_audio.c
00001 /** 00002 ****************************************************************************** 00003 * @file stm32l476g_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 STM32L476G-Discovery board. 00007 ****************************************************************************** 00008 * @attention 00009 * 00010 * <h2><center>© Copyright (c) 2016 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 STM32L476G-Discovery (MB1184) Discovery boards. 00027 a) to play an audio file (all functions names start by BSP_AUDIO_OUT_xxx) 00028 b) to record an audio file through MP34DT01TR, ST MEMS (all functions names start by BSP_AUDIO_IN_xxx) 00029 00030 a) PLAY A FILE: 00031 ============== 00032 + Call the function BSP_AUDIO_OUT_Init( 00033 OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 00034 OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH) 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_SPEAKER : only speaker will be set as output for the audio stream. 00044 - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream. 00045 - OUTPUT_DEVICE_BOTH : both Speaker and Headphone are used as outputs for the audio stream 00046 at the same time. 00047 00048 + Call the function BSP_AUDIO_OUT_RegisterCallbacks to register user callbacks 00049 required to manage audio data streaming towards the audio codec (ErrorCallback(), 00050 HalfTransfer_CallBack() and TransferComplete_CallBack()). 00051 00052 + Call the function BSP_AUDIO_OUT_Play() to start audio playback (for the first time). 00053 + Call the function BSP_AUDIO_OUT_Pause() to pause audio playabck 00054 + Call the function BSP_AUDIO_OUT_Resume() to resume audio playback. 00055 Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called 00056 for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case). 00057 Note. This function should be called only when the audio file is played or paused (not stopped). 00058 + Call the function BSP_AUDIO_OUT_Stop() to stop audio playback. 00059 + To modify the volume level, the sampling frequency, the device output mode, 00060 the mute status or the audio configuration or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(), 00061 AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetOutputMode(), BSP_AUDIO_OUT_SetMute()and 00062 BSP_AUDIO_OUT_ChangeAudioConfig(). 00063 00064 Driver architecture: 00065 -------------------- 00066 + This driver provides the audio layer high level API: it consists in functions 00067 exported in the stm32l476g_discovery_audio.h file (e.g. BSP_AUDIO_OUT_Init(), 00068 BSP_AUDIO_OUT_Play(), ...). 00069 + This driver also includes the Media Access Layer (MAL): it consists in 00070 functions allowing to access setup the audio devices. These functions 00071 are included as local functions into the stm32l476g_discovery_audio.c file 00072 (e.g. AUDIO_SAIx_Init()). 00073 00074 Known Limitations: 00075 ------------------ 00076 1- Communication with the audio codec (through I2C) may be corrupted if it is interrupted by some 00077 user interrupt routines (in this case, interrupts could be disabled just before the start of 00078 communication then re-enabled when it is over). Note that this communication is only done at 00079 the configuration phase (BSP_AUDIO_OUT_Init() or BSP_AUDIO_OUT_Stop()) and when Volume control modification is 00080 performed (BSP_AUDIO_OUT_SetVolume() or BSP_AUDIO_OUT_SetMute()or BSP_AUDIO_OUT_SetOutputMode()). 00081 When the audio data is played, no communication is required with the audio codec. 00082 2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 00083 File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file. 00084 3- Supports only 16-bits audio data size. 00085 00086 b) RECORD A FILE: 00087 ================ 00088 + Call the function BSP_AUDIO_IN_Init( 00089 AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...) 00090 ) 00091 This function configures all the hardware required for the audio application (DFSDM, 00092 GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if the 00093 configuration completes successfully. 00094 00095 + Call the function BSP_AUDIO_IN_RegisterCallbacks to register user callbacks 00096 used to stream audio data toward the record buffer (ErrorCallback(), 00097 HalfTransfer_CallBack() and TransferComplete_CallBack()). 00098 00099 + Call the function BSP_AUDIO_IN_Record( 00100 pbuf Main buffer pointer for the recorded data storing 00101 size Current size of the recorded buffer 00102 ) 00103 to start recording from the microphone. 00104 00105 + Call the function AUDIO_IN_STOP() to stop recording 00106 ==============================================================================*/ 00107 00108 /* Includes ------------------------------------------------------------------*/ 00109 #include <string.h> 00110 #include "stm32l476g_discovery_audio.h" 00111 00112 /** @addtogroup BSP 00113 * @{ 00114 */ 00115 00116 /** @addtogroup STM32L476G_DISCOVERY 00117 * @{ 00118 */ 00119 00120 /** @defgroup STM32L476G_DISCOVERY_AUDIO STM32L476G-DISCOVERY AUDIO 00121 * @brief This file includes the low layer driver for cs43l22 Audio Codec 00122 * available on STM32L476G-Discovery board(MB1184). 00123 * @{ 00124 */ 00125 00126 /* Private typedef -----------------------------------------------------------*/ 00127 /** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Types Private Types 00128 * @{ 00129 */ 00130 typedef struct 00131 { 00132 AUDIO_DrvTypeDef *AudioDrv; /* Audio codec driver */ 00133 Audio_CallbackTypeDef CbError; /* pointer to the callback function invoked when ... */ 00134 Audio_CallbackTypeDef CbHalfTransfer; /* pointer to the callback function invoked when ... */ 00135 Audio_CallbackTypeDef CbTransferComplete; /* pointer to the callback function invoked when ... */ 00136 } AUDIO_OUT_TypeDef; 00137 00138 typedef struct 00139 { 00140 DFSDM_Channel_HandleTypeDef hDfsdmLeftChannel; /* DFSDM channel handle used for left channel */ 00141 DMA_HandleTypeDef hDmaDfsdmLeft; /* DMA handle used for DFSDM regular conversions on left channel */ 00142 int32_t *LeftRecBuff; /* Buffers for left samples */ 00143 uint32_t Frequency; /* Record Frequency */ 00144 uint32_t BitResolution; /* Record bit resolution */ 00145 uint32_t ChannelNbr; /* Record Channel Number */ 00146 uint16_t *pRecBuf; /* Pointer to record user buffer */ 00147 uint32_t RecSize; /* Size to record in mono, double size to record in stereo */ 00148 Audio_CallbackTypeDef CbError; /* pointer to the callback function invoked when a DMA transfer fails */ 00149 Audio_CallbackTypeDef CbHalfTransfer; /* pointer to the callback function invoked when half of the DMA transfer is completed */ 00150 Audio_CallbackTypeDef CbTransferComplete; /* pointer to the callback function invoked when the DMA transfer is completed */ 00151 } AUDIO_IN_TypeDef; 00152 00153 /** 00154 * @} 00155 */ 00156 00157 /* Private defines ------------------------------------------------------------*/ 00158 /** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Constants Private Constants 00159 * @{ 00160 */ 00161 /** 00162 * @} 00163 */ 00164 00165 /* Private macros ------------------------------------------------------------*/ 00166 /** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Macros Private Macros 00167 * @{ 00168 */ 00169 /*### PLAY ###*/ 00170 /* SCK(kHz) = SAI_CK_x/(SAIClockDivider*2*256) */ 00171 #define SAIClockDivider(__FREQUENCY__) \ 00172 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 12 \ 00173 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 2 \ 00174 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 6 \ 00175 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 1 \ 00176 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 3 \ 00177 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 0 \ 00178 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 2 : 1 \ 00179 00180 /*### RECORD ###*/ 00181 #define DFSDMOverSampling(__FREQUENCY__) \ 00182 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 256 \ 00183 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \ 00184 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \ 00185 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \ 00186 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \ 00187 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64 \ 00188 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 16 \ 00189 00190 #define DFSDMClockDivider(__FREQUENCY__) \ 00191 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 24 \ 00192 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \ 00193 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \ 00194 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \ 00195 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \ 00196 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4 \ 00197 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 32 \ 00198 00199 #define DFSDMFilterOrder(__FREQUENCY__) \ 00200 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? DFSDM_FILTER_SINC3_ORDER \ 00201 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \ 00202 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \ 00203 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \ 00204 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \ 00205 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC3_ORDER \ 00206 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC4_ORDER : DFSDM_FILTER_SINC5_ORDER \ 00207 00208 #define DFSDMRightBitShift(__FREQUENCY__) \ 00209 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 6 \ 00210 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 6 \ 00211 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 3 \ 00212 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 3 \ 00213 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 6 \ 00214 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 0 \ 00215 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 2 : 0 \ 00216 00217 /* Saturate the record PCM sample */ 00218 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N))) 00219 00220 /** 00221 * @} 00222 */ 00223 00224 /* Private variables ---------------------------------------------------------*/ 00225 /** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Variables Private Variables 00226 * @{ 00227 */ 00228 /* Audio output context information */ 00229 static AUDIO_OUT_TypeDef hAudioOut; 00230 00231 /* Audio input context information */ 00232 static AUDIO_IN_TypeDef hAudioIn; 00233 00234 /* SAI DMA handle */ 00235 static DMA_HandleTypeDef hDmaSai; 00236 /** 00237 * @} 00238 */ 00239 00240 /* Exported variables ---------------------------------------------------------*/ 00241 /** @defgroup STM32L476G_DISCOVERY_AUDIO_Exported_Variables Exported Variables 00242 * @{ 00243 */ 00244 /* SAIx handle */ 00245 SAI_HandleTypeDef BSP_AUDIO_hSai; 00246 00247 /* DFSDM filter handle */ 00248 DFSDM_Filter_HandleTypeDef BSP_AUDIO_hDfsdmLeftFilter; 00249 /** 00250 * @} 00251 */ 00252 00253 /* Private function prototypes -----------------------------------------------*/ 00254 /** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Functions Private Functions 00255 * @{ 00256 */ 00257 static void AUDIO_CODEC_Reset(void); 00258 static uint8_t AUDIO_SAIx_Init(uint32_t AudioFreq); 00259 static uint8_t AUDIO_SAIx_DeInit(void); 00260 static uint8_t AUDIO_DFSDMx_Init(uint32_t AudioFreq); 00261 static uint8_t AUDIO_DFSDMx_DeInit(void); 00262 static uint8_t AUDIO_SAIPLLConfig(uint32_t AudioFreq); 00263 /** 00264 * @} 00265 */ 00266 00267 /* Exported functions --------------------------------------------------------*/ 00268 /** @addtogroup STM32L476G_DISCOVERY_AUDIO_Exported_Functions 00269 * @{ 00270 */ 00271 00272 /** 00273 * @brief Configures the audio codec related peripherals. 00274 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00275 * or OUTPUT_DEVICE_BOTH. 00276 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00277 * @param AudioFreq: Audio frequency used to play the audio stream.ion. 00278 * @retval BSP AUDIO status 00279 * @note The SAI PLL input clock must be configure in the user application. 00280 * The SAI PLL configuration done within this function assumes that 00281 * the SAI PLL input clock runs at 8 MHz. 00282 */ 00283 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, 00284 uint8_t Volume, 00285 uint32_t AudioFreq) 00286 { 00287 /* Initialize the audio output context */ 00288 hAudioOut.AudioDrv = &cs43l22_drv; 00289 hAudioOut.CbError = (Audio_CallbackTypeDef)NULL; 00290 hAudioOut.CbHalfTransfer = (Audio_CallbackTypeDef)NULL; 00291 hAudioOut.CbTransferComplete = (Audio_CallbackTypeDef)NULL; 00292 00293 /* Configure the SAI PLL according to the requested audio frequency */ 00294 if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK) 00295 { 00296 return AUDIO_ERROR; 00297 } 00298 00299 /* SAI data transfer preparation: prepare the Media to be used for the audio 00300 transfer from memory to SAI peripheral. */ 00301 if (AUDIO_SAIx_Init(AudioFreq) != AUDIO_OK) 00302 { 00303 return AUDIO_ERROR; 00304 } 00305 00306 /* Retieve audio codec identifier */ 00307 if (cs43l22_drv.ReadID(AUDIO_I2C_ADDRESS) != CS43L22_ID) 00308 { 00309 return AUDIO_ERROR; 00310 } 00311 00312 /* Reset the audio codec Registers */ 00313 AUDIO_CODEC_Reset(); 00314 00315 /* Initialize the audio codec internal registers */ 00316 if (hAudioOut.AudioDrv->Init(AUDIO_I2C_ADDRESS, 00317 OutputDevice, 00318 Volume, 00319 AudioFreq) != 0) 00320 { 00321 return AUDIO_ERROR; 00322 } 00323 00324 /* Set the requested volume */ 00325 BSP_AUDIO_OUT_SetVolume(Volume); 00326 00327 return AUDIO_OK; 00328 } 00329 00330 /** 00331 * @brief De-Initializes audio codec related peripherals 00332 * @retval BSP AUDIO status 00333 00334 */ 00335 uint8_t BSP_AUDIO_OUT_DeInit(void) 00336 { 00337 /* De-initializes the Audio Codec audio interface */ 00338 if (AUDIO_SAIx_DeInit() != AUDIO_OK) 00339 { 00340 return AUDIO_ERROR; 00341 } 00342 00343 /* DeInit Audio component interface */ 00344 hAudioOut.AudioDrv->DeInit(); 00345 00346 return AUDIO_OK; 00347 } 00348 00349 /** 00350 * @brief Starts playing audio stream from a data buffer for a determined size. 00351 * @param pData: pointer on PCM samples buffer 00352 * @param Size: Number of audio data BYTES. 00353 * @retval BSP AUDIO status 00354 */ 00355 uint8_t BSP_AUDIO_OUT_Play(uint16_t *pData, uint32_t Size) 00356 { 00357 /* Initiate a DMA transfer of PCM samples towards the serial audio interface */ 00358 if (HAL_SAI_Transmit_DMA(&BSP_AUDIO_hSai, (uint8_t *)pData, DMA_MAX(Size)) != HAL_OK) 00359 { 00360 return AUDIO_ERROR; 00361 } 00362 00363 /* Call the audio Codec Play function */ 00364 if (hAudioOut.AudioDrv->Play(AUDIO_I2C_ADDRESS, pData, Size) != 0) 00365 { 00366 return AUDIO_ERROR; 00367 } 00368 00369 return AUDIO_OK; 00370 } 00371 00372 /** 00373 * @brief Sends n-Bytes on the SAI interface. 00374 * @param pData: pointer on PCM samples buffer 00375 * @param Size: number of data to be written 00376 * @retval BSP AUDIO status 00377 */ 00378 uint8_t BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size) 00379 { 00380 /* Initiate a DMA transfer of PCM samples towards the serial audio interface */ 00381 if (HAL_SAI_Transmit_DMA(&BSP_AUDIO_hSai, (uint8_t *)pData, Size) != HAL_OK) 00382 { 00383 return AUDIO_ERROR; 00384 } 00385 00386 return AUDIO_OK; 00387 } 00388 00389 /** 00390 * @brief This function Pauses the audio file stream. In case 00391 * of using DMA, the DMA Pause feature is used. 00392 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00393 * BSP_AUDIO_OUT_Resume() function should be called for resume 00394 * (use of BSP_AUDIO_OUT_Play() function for resume could lead 00395 * to unexpected behavior). 00396 * @retval BSP AUDIO status 00397 */ 00398 uint8_t BSP_AUDIO_OUT_Pause(void) 00399 { 00400 /* Call the Audio Codec Pause function */ 00401 if (hAudioOut.AudioDrv->Pause(AUDIO_I2C_ADDRESS) != 0) 00402 { 00403 return AUDIO_ERROR; 00404 } 00405 00406 /* Pause DMA transfer of PCM samples towards the serial audio interface */ 00407 if (HAL_SAI_DMAPause(&BSP_AUDIO_hSai) != HAL_OK) 00408 { 00409 return AUDIO_ERROR; 00410 } 00411 00412 return AUDIO_OK; 00413 } 00414 00415 /** 00416 * @brief This function Resumes the audio file stream. 00417 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00418 * BSP_AUDIO_OUT_Resume() function should be called for resume 00419 * (use of BSP_AUDIO_OUT_Play() function for resume could lead to 00420 * unexpected behavior). 00421 * @retval BSP AUDIO status 00422 */ 00423 uint8_t BSP_AUDIO_OUT_Resume(void) 00424 { 00425 /* Call the Audio Codec Resume function */ 00426 if (hAudioOut.AudioDrv->Resume(AUDIO_I2C_ADDRESS) != 0) 00427 { 00428 return AUDIO_ERROR; 00429 } 00430 00431 /* Resume DMA transfer of PCM samples towards the serial audio interface */ 00432 if (HAL_SAI_DMAResume(&BSP_AUDIO_hSai) != HAL_OK) 00433 { 00434 return AUDIO_ERROR; 00435 } 00436 00437 return AUDIO_OK; 00438 } 00439 00440 /** 00441 * @brief Stops audio playing and Power down the Audio Codec. 00442 * @param Option: could be one of the following parameters 00443 * - CODEC_PDWN_SW: for software power off (by writing registers). 00444 * Then no need to reconfigure the Codec after power on. 00445 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00446 * Then need to reconfigure the Codec after power on. 00447 * @retval BSP AUDIO status 00448 */ 00449 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option) 00450 { 00451 /* Call Audio Codec Stop function */ 00452 if (hAudioOut.AudioDrv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 00453 { 00454 return AUDIO_ERROR; 00455 } 00456 00457 if (Option == CODEC_PDWN_HW) 00458 { 00459 /* Wait at least 100us */ 00460 HAL_Delay(1); 00461 } 00462 00463 /* Stop DMA transfer of PCM samples towards the serial audio interface */ 00464 if (HAL_SAI_DMAStop(&BSP_AUDIO_hSai) != HAL_OK) 00465 { 00466 return AUDIO_ERROR; 00467 } 00468 00469 return AUDIO_OK; 00470 } 00471 00472 /** 00473 * @brief Controls the current audio volume level. 00474 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00475 * Mute and 100 for Max volume level). 00476 * @retval BSP AUDIO status 00477 */ 00478 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume) 00479 { 00480 /* Call the codec volume control function with converted volume value */ 00481 if (hAudioOut.AudioDrv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 00482 { 00483 return AUDIO_ERROR; 00484 } 00485 00486 return AUDIO_OK; 00487 } 00488 00489 /** 00490 * @brief Enables or disables the MUTE mode by software 00491 * @param Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 00492 * unmute the codec and restore previous volume level. 00493 * @retval BSP AUDIO status 00494 */ 00495 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd) 00496 { 00497 /* Call the Codec Mute function */ 00498 if (hAudioOut.AudioDrv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0) 00499 { 00500 return AUDIO_ERROR; 00501 } 00502 00503 return AUDIO_OK; 00504 } 00505 00506 /** 00507 * @brief Switch dynamically (while audio file is being played) the output 00508 * target (speaker or headphone). 00509 * @param Output: The audio output target: OUTPUT_DEVICE_SPEAKER, 00510 * OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH 00511 * @retval BSP AUDIO status 00512 */ 00513 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output) 00514 { 00515 /* Call the Codec output device function */ 00516 if (hAudioOut.AudioDrv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0) 00517 { 00518 return AUDIO_ERROR; 00519 } 00520 00521 return AUDIO_OK; 00522 } 00523 00524 /** 00525 * @brief Updates the audio frequency. 00526 * @param AudioFreq: Audio frequency used to play the audio stream. 00527 * @note The SAI PLL input clock must be configure in the user application. 00528 * The SAI PLL configuration done within this function assumes that 00529 * the SAI PLL input clock runs at 8 MHz. 00530 * @retval BSP AUDIO status 00531 */ 00532 uint8_t BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq) 00533 { 00534 /* Configure the SAI PLL according to the requested audio frequency */ 00535 if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK) 00536 { 00537 return AUDIO_ERROR; 00538 } 00539 00540 /* Disable SAI peripheral to allow access to SAI internal registers */ 00541 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai); 00542 00543 /* Update the SAI audio frequency configuration */ 00544 BSP_AUDIO_hSai.Init.Mckdiv = SAIClockDivider(AudioFreq); 00545 HAL_SAI_Init(&BSP_AUDIO_hSai); 00546 00547 /* Enable SAI peripheral to generate MCLK */ 00548 __HAL_SAI_ENABLE(&BSP_AUDIO_hSai); 00549 00550 return AUDIO_OK; 00551 } 00552 00553 /** 00554 * @brief Changes the Audio Out Configuration. 00555 * @param AudioOutOption: specifies the audio out new configuration 00556 * This parameter can be any value of @ref BSP_Audio_Out_Option 00557 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00558 * audio out configuration. 00559 * @retval None 00560 */ 00561 void BSP_AUDIO_OUT_ChangeAudioConfig(uint32_t AudioOutOption) 00562 { 00563 /********** Playback Buffer circular/normal mode **********/ 00564 if (AudioOutOption & BSP_AUDIO_OUT_CIRCULARMODE) 00565 { 00566 /* Deinitialize the Stream to update DMA mode */ 00567 HAL_DMA_DeInit(BSP_AUDIO_hSai.hdmatx); 00568 00569 /* Update the SAI audio Transfer DMA mode */ 00570 BSP_AUDIO_hSai.hdmatx->Init.Mode = DMA_CIRCULAR; 00571 00572 /* Configure the DMA Stream with new Transfer DMA mode */ 00573 HAL_DMA_Init(BSP_AUDIO_hSai.hdmatx); 00574 } 00575 else /* BSP_AUDIO_OUT_NORMALMODE */ 00576 { 00577 /* Deinitialize the Stream to update DMA mode */ 00578 HAL_DMA_DeInit(BSP_AUDIO_hSai.hdmatx); 00579 00580 /* Update the SAI audio Transfer DMA mode */ 00581 BSP_AUDIO_hSai.hdmatx->Init.Mode = DMA_NORMAL; 00582 00583 /* Configure the DMA Stream with new Transfer DMA mode */ 00584 HAL_DMA_Init(BSP_AUDIO_hSai.hdmatx); 00585 } 00586 00587 /********** Playback Buffer stereo/mono mode **********/ 00588 if (AudioOutOption & BSP_AUDIO_OUT_STEREOMODE) 00589 { 00590 /* Disable SAI peripheral to allow access to SAI internal registers */ 00591 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai); 00592 00593 /* Update the SAI audio frame slot configuration */ 00594 BSP_AUDIO_hSai.Init.MonoStereoMode = SAI_STEREOMODE; 00595 HAL_SAI_Init(&BSP_AUDIO_hSai); 00596 00597 /* Enable SAI peripheral to generate MCLK */ 00598 __HAL_SAI_ENABLE(&BSP_AUDIO_hSai); 00599 } 00600 else /* BSP_AUDIO_OUT_MONOMODE */ 00601 { 00602 /* Disable SAI peripheral to allow access to SAI internal registers */ 00603 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai); 00604 00605 /* Update the SAI audio frame slot configuration */ 00606 BSP_AUDIO_hSai.Init.MonoStereoMode = SAI_MONOMODE; 00607 HAL_SAI_Init(&BSP_AUDIO_hSai); 00608 00609 /* Enable SAI peripheral to generate MCLK */ 00610 __HAL_SAI_ENABLE(&BSP_AUDIO_hSai); 00611 } 00612 } 00613 00614 /** 00615 * @brief register user callback functions 00616 * @param ErrorCallback: pointer to the error callback function 00617 * @param HalfTransferCallback: pointer to the half transfer callback function 00618 * @param TransferCompleteCallback: pointer to the transfer complete callback function 00619 * @retval None 00620 */ 00621 void BSP_AUDIO_OUT_RegisterCallbacks(Audio_CallbackTypeDef ErrorCallback, 00622 Audio_CallbackTypeDef HalfTransferCallback, 00623 Audio_CallbackTypeDef TransferCompleteCallback) 00624 { 00625 hAudioOut.CbError = ErrorCallback; 00626 hAudioOut.CbHalfTransfer = HalfTransferCallback; 00627 hAudioOut.CbTransferComplete = TransferCompleteCallback; 00628 } 00629 00630 /** 00631 * @brief Tx Transfer completed callbacks. 00632 * @param hsai: SAI handle 00633 * @retval None 00634 */ 00635 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) 00636 { 00637 /* Invoke the registered 'TransferComplete' function (if any) */ 00638 if (hAudioOut.CbTransferComplete != (Audio_CallbackTypeDef)NULL) 00639 { 00640 hAudioOut.CbTransferComplete(); 00641 } 00642 } 00643 00644 /** 00645 * @brief Tx Half Transfer completed callbacks. 00646 * @param hsai: SAI handle 00647 * @retval None 00648 */ 00649 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 00650 { 00651 /* Invoke the registered 'HalfTransfer' callback function (if any) */ 00652 if (hAudioOut.CbHalfTransfer != (Audio_CallbackTypeDef)NULL) 00653 { 00654 hAudioOut.CbHalfTransfer(); 00655 } 00656 } 00657 00658 /** 00659 * @brief SAI error callbacks. 00660 * @param hsai: SAI handle 00661 * @retval None 00662 */ 00663 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 00664 { 00665 /* Invoke the registered 'ErrorCallback' callback function (if any) */ 00666 if (hAudioOut.CbError != (Audio_CallbackTypeDef)NULL) 00667 { 00668 hAudioOut.CbError(); 00669 } 00670 } 00671 00672 /** 00673 * @} 00674 */ 00675 00676 /** @addtogroup STM32L476G_EVAL_AUDIO_Exported_Functions 00677 * @{ 00678 */ 00679 00680 /** 00681 * @brief Initializes micropone related peripherals. 00682 * @note This function assumes that the SAI input clock (through PLL_M) 00683 * is already configured and ready to be used. 00684 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00685 * @param BitRes: Audio frequency to be configured for the SAI peripheral. 00686 * @param ChnlNbr: Audio frequency to be configured for the SAI peripheral. 00687 * @retval BSP AUDIO status 00688 */ 00689 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00690 { 00691 /* Update the audio input context */ 00692 hAudioIn.Frequency = AudioFreq; 00693 hAudioIn.BitResolution = BitRes; 00694 hAudioIn.ChannelNbr = ChnlNbr; 00695 hAudioIn.CbError = (Audio_CallbackTypeDef)NULL; 00696 hAudioIn.CbHalfTransfer = (Audio_CallbackTypeDef)NULL; 00697 hAudioIn.CbTransferComplete = (Audio_CallbackTypeDef)NULL; 00698 00699 /* Configure the SAI PLL according to the requested audio frequency */ 00700 if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK) 00701 { 00702 return AUDIO_ERROR; 00703 } 00704 00705 /* Initializes the Digital Filter for Sigma-Delta Modulators interface */ 00706 if (AUDIO_DFSDMx_Init(AudioFreq) != AUDIO_OK) 00707 { 00708 return AUDIO_ERROR; 00709 } 00710 00711 return AUDIO_OK; 00712 } 00713 00714 /** 00715 * @brief De-Initializes microphone related peripherals. 00716 * @retval BSP AUDIO status 00717 00718 */ 00719 uint8_t BSP_AUDIO_IN_DeInit(void) 00720 { 00721 /* De-initializes the Digital Filter for Sigma-Delta Modulators interface */ 00722 if (AUDIO_DFSDMx_DeInit() != AUDIO_OK) 00723 { 00724 return AUDIO_ERROR; 00725 } 00726 00727 /* Reset the audio input context */ 00728 memset(&hAudioIn, 0, sizeof(hAudioIn)); 00729 00730 return AUDIO_OK; 00731 } 00732 00733 /** 00734 * @brief Starts audio recording. 00735 * @param pbuf: Main buffer pointer for the recorded data storing 00736 * @param size: Current size of the recorded buffer 00737 * @note The Right channel is start at first with synchro on start of Left channel 00738 * @retval BSP AUDIO status 00739 */ 00740 uint8_t BSP_AUDIO_IN_Record(uint16_t *pbuf, uint32_t size) 00741 { 00742 hAudioIn.pRecBuf = pbuf; 00743 hAudioIn.RecSize = size; 00744 00745 /* Allocate hAudioIn.LeftRecBuff buffer */ 00746 #if defined(BSP_AUDIO_USE_RTOS) 00747 hAudioIn.LeftRecBuff = (int32_t *)k_malloc(size * sizeof(int32_t)); 00748 #else 00749 hAudioIn.LeftRecBuff = (int32_t *)malloc(size * sizeof(int32_t)); 00750 #endif 00751 if (hAudioIn.LeftRecBuff == NULL) 00752 { 00753 return AUDIO_ERROR; 00754 } 00755 00756 /* Call the Media layer start function for left channel */ 00757 if (HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmLeftFilter, 00758 (int32_t *)hAudioIn.LeftRecBuff, 00759 (hAudioIn.RecSize / DEFAULT_AUDIO_IN_CHANNEL_NBR)) != HAL_OK) 00760 { 00761 return AUDIO_ERROR; 00762 } 00763 00764 return AUDIO_OK; 00765 } 00766 00767 /** 00768 * @brief Updates the audio frequency. 00769 * @param AudioFreq: Audio frequency used to record the audio stream. 00770 * @note This API should be called after the BSP_AUDIO_IN_Init() to adjust the 00771 * audio frequency. 00772 * @retval BSP AUDIO status 00773 */ 00774 uint8_t BSP_AUDIO_IN_SetFrequency(uint32_t AudioFreq) 00775 { 00776 /* Configure the SAI PLL according to the requested audio frequency */ 00777 if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK) 00778 { 00779 return AUDIO_ERROR; 00780 } 00781 00782 /* De-initializes the Digital Filter for Sigma-Delta Modulators interface */ 00783 if (AUDIO_DFSDMx_DeInit() != AUDIO_OK) 00784 { 00785 return AUDIO_ERROR; 00786 } 00787 00788 /* Initializes the Digital Filter for Sigma-Delta Modulators interface */ 00789 if (AUDIO_DFSDMx_Init(AudioFreq) != AUDIO_OK) 00790 { 00791 return AUDIO_ERROR; 00792 } 00793 00794 return AUDIO_OK; 00795 } 00796 00797 /** 00798 * @brief Regular conversion complete callback. 00799 * @note In interrupt mode, user has to read conversion value in this function 00800 using HAL_DFSDM_FilterGetRegularValue. 00801 * @param hdfsdm_filter : DFSDM filter handle. 00802 * @retval None 00803 */ 00804 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 00805 { 00806 uint32_t index; 00807 uint32_t recbufsize = (hAudioIn.RecSize / DEFAULT_AUDIO_IN_CHANNEL_NBR); 00808 00809 for (index = (recbufsize / 2); index < recbufsize; index++) 00810 { 00811 hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32768, 32767)); 00812 } 00813 00814 /* Invoke the registered 'TransferComplete' function (if any) */ 00815 if (hAudioIn.CbTransferComplete != (Audio_CallbackTypeDef)NULL) 00816 { 00817 hAudioIn.CbTransferComplete(); 00818 } 00819 } 00820 00821 /** 00822 * @brief Half regular conversion complete callback. 00823 * @param hdfsdm_filter : DFSDM filter handle. 00824 * @retval None 00825 */ 00826 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 00827 { 00828 uint32_t index; 00829 uint32_t recbufsize = (hAudioIn.RecSize / DEFAULT_AUDIO_IN_CHANNEL_NBR); 00830 00831 00832 for (index = 0; index < (recbufsize / 2); index++) 00833 { 00834 hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32768, 32767)); 00835 } 00836 00837 /* Invoke the registered 'HalfTransfer' callback function (if any) */ 00838 if (hAudioIn.CbHalfTransfer != (Audio_CallbackTypeDef)NULL) 00839 { 00840 hAudioIn.CbHalfTransfer(); 00841 } 00842 } 00843 00844 /** 00845 * @brief Error callback. 00846 * @param hdfsdm_filter : DFSDM filter handle. 00847 * @retval None 00848 */ 00849 void HAL_DFSDM_FilterErrorCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 00850 { 00851 /* Invoke the registered 'ErrorCallback' callback function (if any) */ 00852 if (hAudioIn.CbError != (Audio_CallbackTypeDef)NULL) 00853 { 00854 hAudioIn.CbError(); 00855 } 00856 } 00857 00858 /** 00859 * @brief Stops audio recording. 00860 * @retval BSP AUDIO status 00861 */ 00862 uint8_t BSP_AUDIO_IN_Stop(void) 00863 { 00864 /* Call the Media layer stop function for left channel */ 00865 if (HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK) 00866 { 00867 return AUDIO_ERROR; 00868 } 00869 00870 /* Free hAudioIn.LeftRecBuff buffer */ 00871 #if defined(BSP_AUDIO_USE_RTOS) 00872 k_free((void *)hAudioIn.LeftRecBuff); 00873 #else 00874 free((void *)hAudioIn.LeftRecBuff); 00875 #endif 00876 00877 return AUDIO_OK; 00878 } 00879 00880 /** 00881 * @brief Pauses the audio file stream. 00882 * @retval BSP AUDIO status 00883 */ 00884 uint8_t BSP_AUDIO_IN_Pause(void) 00885 { 00886 /* Call the Media layer stop function */ 00887 if (HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK) 00888 { 00889 return AUDIO_ERROR; 00890 } 00891 00892 return AUDIO_OK; 00893 } 00894 00895 /** 00896 * @brief Resumes the audio file stream. 00897 * @retval BSP AUDIO status 00898 */ 00899 uint8_t BSP_AUDIO_IN_Resume(void) 00900 { 00901 /* Call the Media layer start function for left channel */ 00902 if (HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmLeftFilter, 00903 (int32_t *)hAudioIn.LeftRecBuff, 00904 (hAudioIn.RecSize / DEFAULT_AUDIO_IN_CHANNEL_NBR)) != HAL_OK) 00905 { 00906 return AUDIO_ERROR; 00907 } 00908 00909 return AUDIO_OK; 00910 } 00911 00912 /** 00913 * @brief register user callback functions 00914 * @param ErrorCallback: pointer to the error callback function 00915 * @param HalfTransferCallback: pointer to the half transfer callback function 00916 * @param TransferCompleteCallback: pointer to the transfer complete callback function 00917 * @retval None 00918 */ 00919 void BSP_AUDIO_IN_RegisterCallbacks(Audio_CallbackTypeDef ErrorCallback, 00920 Audio_CallbackTypeDef HalfTransferCallback, 00921 Audio_CallbackTypeDef TransferCompleteCallback) 00922 { 00923 hAudioIn.CbError = ErrorCallback; 00924 hAudioIn.CbHalfTransfer = HalfTransferCallback; 00925 hAudioIn.CbTransferComplete = TransferCompleteCallback; 00926 } 00927 /** 00928 * @} 00929 */ 00930 00931 /* private functions --------------------------------------------------------*/ 00932 /** @addtogroup STM32L476G_DISCOVERY_AUDIO_Private_Functions 00933 * @{ 00934 */ 00935 /** 00936 * @brief Initializes the Audio Codec audio interface (SAI). 00937 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00938 * @note The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 00939 * and user can update this configuration using 00940 * @retval BSP AUDIO status 00941 */ 00942 static uint8_t AUDIO_SAIx_Init(uint32_t AudioFreq) 00943 { 00944 /* Disable SAI peripheral to allow access to SAI internal registers */ 00945 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai); 00946 00947 /* Initialize the BSP_AUDIO_hSai Instance parameter */ 00948 BSP_AUDIO_hSai.Instance = AUDIO_SAIx; 00949 00950 /* Configure SAI_Block_x 00951 LSBFirst: Disabled 00952 DataSize: 16 */ 00953 BSP_AUDIO_hSai.Init.AudioMode = SAI_MODEMASTER_TX; 00954 BSP_AUDIO_hSai.Init.Synchro = SAI_ASYNCHRONOUS; 00955 BSP_AUDIO_hSai.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 00956 BSP_AUDIO_hSai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE; 00957 BSP_AUDIO_hSai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; 00958 BSP_AUDIO_hSai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 00959 BSP_AUDIO_hSai.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV; 00960 BSP_AUDIO_hSai.Init.Mckdiv = SAIClockDivider(AudioFreq); 00961 BSP_AUDIO_hSai.Init.MonoStereoMode = SAI_STEREOMODE; 00962 BSP_AUDIO_hSai.Init.CompandingMode = SAI_NOCOMPANDING; 00963 BSP_AUDIO_hSai.Init.TriState = SAI_OUTPUT_NOTRELEASED; 00964 BSP_AUDIO_hSai.Init.Protocol = SAI_FREE_PROTOCOL; 00965 BSP_AUDIO_hSai.Init.DataSize = SAI_DATASIZE_16; 00966 BSP_AUDIO_hSai.Init.FirstBit = SAI_FIRSTBIT_MSB; 00967 BSP_AUDIO_hSai.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; 00968 00969 /* Configure SAI_Block_x Frame 00970 Frame Length: 32 00971 Frame active Length: 16 00972 FS Definition: Start frame + Channel Side identification 00973 FS Polarity: FS active Low 00974 FS Offset: FS asserted one bit before the first bit of slot 0 */ 00975 BSP_AUDIO_hSai.FrameInit.FrameLength = 32; 00976 BSP_AUDIO_hSai.FrameInit.ActiveFrameLength = 16; 00977 BSP_AUDIO_hSai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 00978 BSP_AUDIO_hSai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 00979 BSP_AUDIO_hSai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 00980 00981 /* Configure SAI Block_x Slot 00982 Slot First Bit Offset: 0 00983 Slot Size : 16 00984 Slot Number: 2 00985 Slot Active: Slots 0 and 1 actives */ 00986 BSP_AUDIO_hSai.SlotInit.FirstBitOffset = 0; 00987 BSP_AUDIO_hSai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 00988 BSP_AUDIO_hSai.SlotInit.SlotNumber = 2; 00989 BSP_AUDIO_hSai.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1; 00990 00991 /* Initializes the SAI peripheral*/ 00992 if (HAL_SAI_Init(&BSP_AUDIO_hSai) != HAL_OK) 00993 { 00994 return AUDIO_ERROR; 00995 } 00996 00997 /* Enable SAI peripheral to generate MCLK */ 00998 __HAL_SAI_ENABLE(&BSP_AUDIO_hSai); 00999 01000 return AUDIO_OK; 01001 01002 } 01003 01004 /** 01005 * @brief De-initializes the Audio Codec audio interface (SAI). 01006 * @retval BSP AUDIO status 01007 */ 01008 static uint8_t AUDIO_SAIx_DeInit(void) 01009 { 01010 /* Disable the SAI audio block */ 01011 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai); 01012 01013 /* De-initializes the SAI peripheral */ 01014 if (HAL_SAI_DeInit(&BSP_AUDIO_hSai) != HAL_OK) 01015 { 01016 return AUDIO_ERROR; 01017 } 01018 01019 /* Disable SAIx PLL */ 01020 if (AUDIO_SAIx_PLL_DISABLE() != AUDIO_OK) 01021 { 01022 return AUDIO_ERROR; 01023 } 01024 01025 return AUDIO_OK; 01026 } 01027 01028 /** 01029 * @brief SAI MSP Init 01030 * @param hsai : pointer to a SAI_HandleTypeDef structure 01031 * @retval None 01032 */ 01033 void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai) 01034 { 01035 GPIO_InitTypeDef GPIO_InitStruct; 01036 01037 /* Enable SAI clock */ 01038 AUDIO_SAIx_CLK_ENABLE(); 01039 01040 /* Enable GPIO clock */ 01041 AUDIO_SAIx_MCK_SCK_SD_FS_ENABLE(); 01042 01043 /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/ 01044 GPIO_InitStruct.Pin = AUDIO_SAIx_FS_PIN | AUDIO_SAIx_SCK_PIN | AUDIO_SAIx_SD_PIN | AUDIO_SAIx_MCK_PIN; 01045 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 01046 GPIO_InitStruct.Pull = GPIO_NOPULL; 01047 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 01048 GPIO_InitStruct.Alternate = AUDIO_SAIx_MCK_SCK_SD_FS_AF; 01049 HAL_GPIO_Init(AUDIO_SAIx_MCK_SCK_SD_FS_GPIO_PORT, &GPIO_InitStruct); 01050 01051 /* Enable the DMA clock */ 01052 AUDIO_SAIx_DMAx_CLK_ENABLE(); 01053 01054 if (hsai->Instance == AUDIO_SAIx) 01055 { 01056 /* Configure the hDmaSai handle parameters */ 01057 hDmaSai.Init.Request = DMA_REQUEST_1; 01058 hDmaSai.Init.Direction = DMA_MEMORY_TO_PERIPH; 01059 hDmaSai.Init.PeriphInc = DMA_PINC_DISABLE; 01060 hDmaSai.Init.MemInc = DMA_MINC_ENABLE; 01061 hDmaSai.Init.PeriphDataAlignment = AUDIO_SAIx_DMAx_PERIPH_DATA_SIZE; 01062 hDmaSai.Init.MemDataAlignment = AUDIO_SAIx_DMAx_MEM_DATA_SIZE; 01063 hDmaSai.Init.Mode = DMA_NORMAL; 01064 hDmaSai.Init.Priority = DMA_PRIORITY_HIGH; 01065 01066 hDmaSai.Instance = AUDIO_SAIx_DMAx_CHANNEL; 01067 01068 /* Associate the DMA handle */ 01069 __HAL_LINKDMA(hsai, hdmatx, hDmaSai); 01070 01071 /* Deinitialize the Stream for new transfer */ 01072 HAL_DMA_DeInit(&hDmaSai); 01073 01074 /* Configure the DMA Stream */ 01075 HAL_DMA_Init(&hDmaSai); 01076 } 01077 01078 /* SAI DMA IRQ Channel configuration */ 01079 HAL_NVIC_SetPriority(AUDIO_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 01080 HAL_NVIC_EnableIRQ(AUDIO_SAIx_DMAx_IRQ); 01081 } 01082 01083 /** 01084 * @brief SAI MSP De-init 01085 * @param hsai : pointer to a SAI_HandleTypeDef structure 01086 * @retval None 01087 */ 01088 void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai) 01089 { 01090 /* Disable SAI DMA Channel IRQ */ 01091 HAL_NVIC_DisableIRQ(AUDIO_SAIx_DMAx_IRQ); 01092 01093 /* Reset the DMA Stream configuration*/ 01094 HAL_DMA_DeInit(&hDmaSai); 01095 01096 /* Disable the DMA clock */ 01097 AUDIO_SAIx_DMAx_CLK_DISABLE(); 01098 01099 /* De-initialize FS, SCK, MCK and SD pins*/ 01100 HAL_GPIO_DeInit(AUDIO_SAIx_MCK_SCK_SD_FS_GPIO_PORT, 01101 AUDIO_SAIx_FS_PIN | AUDIO_SAIx_SCK_PIN | AUDIO_SAIx_SD_PIN | AUDIO_SAIx_MCK_PIN); 01102 01103 /* Disable GPIO clock */ 01104 AUDIO_SAIx_MCK_SCK_SD_FS_DISABLE(); 01105 01106 /* Disable SAI clock */ 01107 AUDIO_SAIx_CLK_DISABLE(); 01108 } 01109 01110 /** 01111 * @brief Resets the audio codec. It restores the default configuration of the 01112 * codec (this function shall be called before initializing the codec). 01113 * @retval None 01114 */ 01115 static void AUDIO_CODEC_Reset(void) 01116 { 01117 /* Initialize the audio driver structure */ 01118 hAudioOut.AudioDrv = &cs43l22_drv; 01119 01120 hAudioOut.AudioDrv->Reset(AUDIO_I2C_ADDRESS); 01121 } 01122 01123 /** 01124 * @} 01125 */ 01126 01127 /** @addtogroup STM32L476G_DISCOVERY_AUDIO_Private_Functions 01128 * @{ 01129 */ 01130 01131 /** 01132 * @brief Initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01133 * @param AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral. 01134 * @retval BSP AUDIO status 01135 */ 01136 static uint8_t AUDIO_DFSDMx_Init(uint32_t AudioFreq) 01137 { 01138 /*####CHANNEL 2####*/ 01139 hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Activation = ENABLE; 01140 hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01141 /* Set the DFSDM clock OUT audio frequency configuration */ 01142 hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Divider = DFSDMClockDivider(AudioFreq); 01143 hAudioIn.hDfsdmLeftChannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01144 hAudioIn.hDfsdmLeftChannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01145 hAudioIn.hDfsdmLeftChannel.Init.Input.Pins = DFSDM_CHANNEL_SAME_CHANNEL_PINS; 01146 /* Request to sample stable data for LEFT micro on Rising edge */ 01147 hAudioIn.hDfsdmLeftChannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_RISING; 01148 hAudioIn.hDfsdmLeftChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01149 hAudioIn.hDfsdmLeftChannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_SINC1_ORDER; 01150 hAudioIn.hDfsdmLeftChannel.Init.Awd.Oversampling = 10; 01151 hAudioIn.hDfsdmLeftChannel.Init.Offset = 0; 01152 hAudioIn.hDfsdmLeftChannel.Init.RightBitShift = DFSDMRightBitShift(AudioFreq); 01153 01154 hAudioIn.hDfsdmLeftChannel.Instance = DFSDM1_Channel2; 01155 01156 /* Init the DFSDM Channel */ 01157 if (HAL_DFSDM_ChannelInit(&hAudioIn.hDfsdmLeftChannel) != HAL_OK) 01158 { 01159 return AUDIO_ERROR; 01160 } 01161 01162 /*####FILTER 0####*/ 01163 BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01164 BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.FastMode = ENABLE; 01165 BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.DmaMode = ENABLE; 01166 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01167 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ScanMode = DISABLE; 01168 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.DmaMode = DISABLE; 01169 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO; 01170 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES; 01171 BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.SincOrder = DFSDMFilterOrder(AudioFreq); 01172 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01173 BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.Oversampling = DFSDMOverSampling(AudioFreq); 01174 BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.IntOversampling = 1; 01175 01176 BSP_AUDIO_hDfsdmLeftFilter.Instance = AUDIO_DFSDMx_LEFT_FILTER; 01177 01178 /* Init the DFSDM Filter */ 01179 if (HAL_DFSDM_FilterInit(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK) 01180 { 01181 return AUDIO_ERROR; 01182 } 01183 01184 /* Configure regular channel */ 01185 if (HAL_DFSDM_FilterConfigRegChannel(&BSP_AUDIO_hDfsdmLeftFilter, 01186 DFSDM_CHANNEL_2, 01187 DFSDM_CONTINUOUS_CONV_ON) != HAL_OK) 01188 { 01189 return AUDIO_ERROR; 01190 } 01191 01192 return AUDIO_OK; 01193 } 01194 01195 /** 01196 * @brief De-initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01197 * @retval BSP AUDIO status 01198 */ 01199 static uint8_t AUDIO_DFSDMx_DeInit(void) 01200 { 01201 /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */ 01202 if (HAL_DFSDM_FilterDeInit(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK) 01203 { 01204 return AUDIO_ERROR; 01205 } 01206 01207 /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */ 01208 if (HAL_DFSDM_ChannelDeInit(&hAudioIn.hDfsdmLeftChannel) != HAL_OK) 01209 { 01210 return AUDIO_ERROR; 01211 } 01212 01213 /* Disable DFSDM clock */ 01214 AUDIO_DFSDMx_CLK_DISABLE(); 01215 01216 /* Disable SAIx PLL */ 01217 if (AUDIO_SAIx_PLL_DISABLE() != AUDIO_OK) 01218 { 01219 return AUDIO_ERROR; 01220 } 01221 01222 /* DFSDM reset */ 01223 __HAL_RCC_DFSDM1_FORCE_RESET(); 01224 __HAL_RCC_DFSDM1_RELEASE_RESET(); 01225 01226 return AUDIO_OK; 01227 } 01228 01229 /** 01230 * @brief Initializes the DFSDM channel MSP. 01231 * @param hdfsdm_channel : DFSDM channel handle. 01232 * @retval None 01233 */ 01234 void HAL_DFSDM_ChannelMspInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) 01235 { 01236 GPIO_InitTypeDef GPIO_InitStruct; 01237 01238 /* Enable DFSDM clock */ 01239 AUDIO_DFSDMx_CLK_ENABLE(); 01240 01241 /* Enable GPIO clock */ 01242 AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_CLK_ENABLE(); 01243 01244 /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN pins ------------------*/ 01245 GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN | AUDIO_DFSDMx_DMIC_DATIN_PIN; 01246 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 01247 GPIO_InitStruct.Pull = GPIO_NOPULL; 01248 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 01249 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_CKOUT_DMIC_DATIN_AF; 01250 HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct); 01251 } 01252 01253 /** 01254 * @brief De-initializes the DFSDM channel MSP. 01255 * @param hdfsdm_channel : DFSDM channel handle. 01256 * @retval None 01257 */ 01258 void HAL_DFSDM_ChannelMspDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) 01259 { 01260 GPIO_InitTypeDef GPIO_InitStruct; 01261 01262 /* Enable GPIO clock */ 01263 AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_CLK_ENABLE(); 01264 01265 /* DFSDM pins configuration: DFSDM_CKOUT */ 01266 GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN; 01267 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 01268 GPIO_InitStruct.Pull = GPIO_NOPULL; 01269 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 01270 HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct); 01271 HAL_GPIO_WritePin(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, AUDIO_DFSDMx_CKOUT_PIN, GPIO_PIN_RESET); 01272 01273 01274 /* De-initialize DMIC_DATIN pin */ 01275 HAL_GPIO_DeInit(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, AUDIO_DFSDMx_DMIC_DATIN_PIN); 01276 } 01277 01278 /** 01279 * @brief Initializes the DFSDM filter MSP. 01280 * @param hdfsdm_filter : DFSDM filter handle. 01281 * @retval None 01282 */ 01283 void HAL_DFSDM_FilterMspInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01284 { 01285 /* Enable DFSDM clock */ 01286 AUDIO_DFSDMx_CLK_ENABLE(); 01287 01288 /* Enable the DMA clock */ 01289 AUDIO_DFSDMx_DMAx_CLK_ENABLE(); 01290 01291 /* Configure the hAudioIn.hDmaDfsdmLeft handle parameters */ 01292 hAudioIn.hDmaDfsdmLeft.Init.Request = DMA_REQUEST_0; 01293 hAudioIn.hDmaDfsdmLeft.Init.Direction = DMA_PERIPH_TO_MEMORY; 01294 hAudioIn.hDmaDfsdmLeft.Init.PeriphInc = DMA_PINC_DISABLE; 01295 hAudioIn.hDmaDfsdmLeft.Init.MemInc = DMA_MINC_ENABLE; 01296 hAudioIn.hDmaDfsdmLeft.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE; 01297 hAudioIn.hDmaDfsdmLeft.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE; 01298 hAudioIn.hDmaDfsdmLeft.Init.Mode = DMA_CIRCULAR; 01299 hAudioIn.hDmaDfsdmLeft.Init.Priority = DMA_PRIORITY_HIGH; 01300 01301 hAudioIn.hDmaDfsdmLeft.Instance = AUDIO_DFSDMx_DMAx_LEFT_CHANNEL; 01302 01303 /* Associate the DMA handle */ 01304 __HAL_LINKDMA(hdfsdm_filter, hdmaReg, hAudioIn.hDmaDfsdmLeft); 01305 01306 /* Reset DMA handle state */ 01307 __HAL_DMA_RESET_HANDLE_STATE(&hAudioIn.hDmaDfsdmLeft); 01308 01309 /* Configure the DMA Channel */ 01310 HAL_DMA_Init(&hAudioIn.hDmaDfsdmLeft); 01311 01312 /* DMA IRQ Channel configuration */ 01313 HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_LEFT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 01314 HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_LEFT_IRQ); 01315 } 01316 01317 /** 01318 * @brief De-initializes the DFSDM filter MSP. 01319 * @param hdfsdm_filter : DFSDM filter handle. 01320 * @retval None 01321 */ 01322 void HAL_DFSDM_FilterMspDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01323 { 01324 /* Disable DMA Channel IRQ */ 01325 HAL_NVIC_DisableIRQ(AUDIO_DFSDMx_DMAx_LEFT_IRQ); 01326 01327 /* De-initialize the DMA Channel */ 01328 HAL_DMA_DeInit(&hAudioIn.hDmaDfsdmLeft); 01329 01330 /* Disable the DMA clock */ 01331 AUDIO_DFSDMx_DMAx_CLK_DISABLE(); 01332 } 01333 01334 /** 01335 * @brief Configures the SAI PLL clock according to the required audio frequency. 01336 * @param Frequency: Audio frequency. 01337 * @retval BSP AUDIO status 01338 * @note The SAI PLL input clock must be configured in the user application. 01339 * The SAI PLL configuration done within this function assumes that 01340 * the SAI PLL input clock runs at 8 MHz. 01341 */ 01342 static uint8_t AUDIO_SAIPLLConfig(uint32_t Frequency) 01343 { 01344 RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct; 01345 01346 /* Retrieve actual RCC configuration */ 01347 HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct); 01348 01349 if ((Frequency == AUDIO_FREQUENCY_11K) 01350 || (Frequency == AUDIO_FREQUENCY_22K) 01351 || (Frequency == AUDIO_FREQUENCY_44K)) 01352 { 01353 /* Configure PLLSAI prescalers */ 01354 /* SAI clock config 01355 PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 24 = VCO_192M 01356 SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 192/17 = 11.294 Mhz */ 01357 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 01358 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 24; 01359 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = 17; 01360 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK; 01361 RCC_ExCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; 01362 } 01363 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 01364 { 01365 /* SAI clock config 01366 PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 43 = VCO_344M 01367 SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 344/7 = 49.142 Mhz */ 01368 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 01369 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 43; 01370 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = 7; 01371 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK; 01372 RCC_ExCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; 01373 } 01374 01375 if (HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct) != HAL_OK) 01376 { 01377 return AUDIO_ERROR; 01378 } 01379 01380 return AUDIO_OK; 01381 } 01382 01383 /** 01384 * @} 01385 */ 01386 01387 /** 01388 * @} 01389 */ 01390 01391 /** 01392 * @} 01393 */ 01394 01395 /** 01396 * @} 01397 */ 01398 01399 /** 01400 * @} 01401 */ 01402 01403 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 18:37:21 by 1.7.2