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