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