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