Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: DISCO_F413ZH-AUDIO-demo
stm32f413h_discovery_audio.c
00001 /** 00002 ****************************************************************************** 00003 * @file STM32f413h_discovery_audio.c 00004 * @author MCD Application Team 00005 * @brief This file provides the Audio driver for the STM32F413H-DISCOVERY board. 00006 ****************************************************************************** 00007 * @attention 00008 * 00009 * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2> 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 1. Redistributions of source code must retain the above copyright notice, 00014 * this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright notice, 00016 * this list of conditions and the following disclaimer in the documentation 00017 * and/or other materials provided with the distribution. 00018 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00019 * may be used to endorse or promote products derived from this software 00020 * without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00023 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00024 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00025 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00026 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00027 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00028 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00030 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00031 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 * 00033 ****************************************************************************** 00034 */ 00035 00036 /*============================================================================== 00037 User NOTES 00038 00039 How To use this driver: 00040 ----------------------- 00041 + This driver supports STM32F4xx devices on STM32F413H-DISCOVERY boards. 00042 + Call the function BSP_AUDIO_OUT_Init( 00043 OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 00044 OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH) 00045 Volume : Initial volume to be set (0 is min (mute), 100 is max (100%) 00046 AudioFreq : Audio frequency in Hz (8000, 16000, 22500, 32000...) 00047 this parameter is relative to the audio file/stream type. 00048 ) 00049 This function configures all the hardware required for the audio application (codec, I2C, I2S, 00050 GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK. 00051 If the returned value is different from AUDIO_OK or the function is stuck then the communication with 00052 the codec has failed (try to un-plug the power or reset device in this case). 00053 - OUTPUT_DEVICE_SPEAKER : only speaker will be set as output for the audio stream. 00054 - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream. 00055 - OUTPUT_DEVICE_BOTH : both Speaker and Headphone are used as outputs for the audio stream 00056 at the same time. 00057 + Call the function BSP_AUDIO_OUT_Play( 00058 pBuffer: pointer to the audio data file address 00059 Size : size of the buffer to be sent in Bytes 00060 ) 00061 to start playing (for the first time) from the audio file/stream. 00062 + Call the function BSP_AUDIO_OUT_Pause() to pause playing 00063 + Call the function BSP_AUDIO_OUT_Resume() to resume playing. 00064 Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called 00065 for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case). 00066 Note. This function should be called only when the audio file is played or paused (not stopped). 00067 + For each mode, you may need to implement the relative callback functions into your code. 00068 The Callback functions are named AUDIO_OUT_XXX_CallBack() and only their prototypes are declared in 00069 the STM32F413H_discovery_audio.h file. (refer to the example for more details on the callbacks implementations) 00070 + To Stop playing, to modify the volume level, the frequency, use the functions: BSP_AUDIO_OUT_SetVolume(), 00071 AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetOutputMode(), BSP_AUDIO_OUT_SetMute() and BSP_AUDIO_OUT_Stop(). 00072 + The driver API and the callback functions are at the end of the STM32F413H_discovery_audio.h file. 00073 00074 00075 Driver architecture: 00076 -------------------- 00077 + This driver provides the High Audio Layer: consists of the function API exported in the stm32f413h_discovery_audio.h file 00078 (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...) 00079 + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/ 00080 providing the audio file/stream. These functions are also included as local functions into 00081 the stm32f413h_discovery_audio_codec.c file (I2Sx_Out_Init(), I2Sx_Out_DeInit(), I2Sx_In_Init() and I2Sx_In_DeInit()) 00082 00083 Known Limitations: 00084 ------------------ 00085 1- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second 00086 Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams. 00087 2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 00088 File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file. 00089 3- Supports only Stereo audio streaming. 00090 4- Supports only 16-bits audio data size. 00091 ==============================================================================*/ 00092 00093 /* Includes ------------------------------------------------------------------*/ 00094 #include "stm32f413h_discovery_audio.h" 00095 00096 /** @addtogroup BSP 00097 * @{ 00098 */ 00099 00100 /** @addtogroup STM32F413H_DISCOVERY 00101 * @{ 00102 */ 00103 00104 /** @defgroup STM32F413H_DISCOVERY_AUDIO STM32F413H_DISCOVERY AUDIO 00105 * @brief This file includes the low layer driver for wm8994 Audio Codec 00106 * available on STM32F413H-DISCOVERY board(MB1209). 00107 * @{ 00108 */ 00109 00110 /** @defgroup STM32F413H_DISCOVERY_AUDIO_Private_Macros STM32F413H DISCOVERY Audio Private macros 00111 * @{ 00112 */ 00113 00114 #define DFSDM_OVER_SAMPLING(__FREQUENCY__) \ 00115 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 256 \ 00116 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \ 00117 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \ 00118 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \ 00119 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \ 00120 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64 \ 00121 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 25 \ 00122 00123 #define DFSDM_CLOCK_DIVIDER(__FREQUENCY__) \ 00124 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 24 \ 00125 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 48 \ 00126 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \ 00127 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 48 \ 00128 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \ 00129 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 48 \ 00130 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 72 \ 00131 00132 #define DFSDM_FILTER_ORDER(__FREQUENCY__) \ 00133 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? DFSDM_FILTER_SINC3_ORDER \ 00134 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \ 00135 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \ 00136 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \ 00137 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \ 00138 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC4_ORDER \ 00139 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC4_ORDER : DFSDM_FILTER_SINC4_ORDER \ 00140 00141 #define DFSDM_MIC_BIT_SHIFT(__FREQUENCY__) \ 00142 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 5 \ 00143 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \ 00144 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 2 \ 00145 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 2 \ 00146 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 5 \ 00147 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 6 \ 00148 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 2 : 0 \ 00149 00150 /* Saturate the record PCM sample */ 00151 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N))) 00152 /** 00153 * @} 00154 */ 00155 00156 /** @defgroup STM32F413H_DISCOVERY_AUDIO_Private_Variables STM32F413H DISCOVERY Audio Private Variables 00157 * @{ 00158 */ 00159 00160 AUDIO_DrvTypeDef *audio_drv; 00161 I2S_HandleTypeDef haudio_i2s; /* for Audio_OUT and Audio_IN_analog mic */ 00162 I2S_HandleTypeDef haudio_in_i2sext; /* for Analog mic with full duplex mode */ 00163 AUDIOIN_ContextTypeDef hAudioIn; 00164 00165 DFSDM_Channel_HandleTypeDef hAudioInDfsdmChannel[DFSDM_MIC_NUMBER]; /* 5 DFSDM channel handle used for all microphones */ 00166 DFSDM_Filter_HandleTypeDef hAudioInDfsdmFilter[DFSDM_MIC_NUMBER]; /* 5 DFSDM filter handle */ 00167 DMA_HandleTypeDef hDmaDfsdm[DFSDM_MIC_NUMBER]; /* 5 DMA handle used for DFSDM regular conversions */ 00168 00169 /* Buffers for right and left samples */ 00170 int32_t *pScratchBuff[DEFAULT_AUDIO_IN_CHANNEL_NBR]; 00171 uint32_t ScratchSize; 00172 00173 uint32_t DmaRecHalfBuffCplt[DFSDM_MIC_NUMBER] = {0}; 00174 uint32_t DmaRecBuffCplt[DFSDM_MIC_NUMBER] = {0}; 00175 00176 /* Application Buffer Trigger */ 00177 __IO uint32_t AppBuffTrigger = 0; 00178 __IO uint32_t AppBuffHalf = 0; 00179 __IO uint32_t MicBuff[DFSDM_MIC_NUMBER] = {0}; 00180 __IO uint16_t AudioInVolume = DEFAULT_AUDIO_IN_VOLUME; 00181 00182 /** 00183 * @} 00184 */ 00185 00186 /** @defgroup STM32F413H_DISCOVERY_AUDIO_Private_Function_Prototypes STM32F413H DISCOVERY Audio Private Prototypes 00187 * @{ 00188 */ 00189 static void I2Sx_In_Init(uint32_t AudioFreq); 00190 static void I2Sx_In_DeInit(void); 00191 static void I2Sx_In_MspInit(void); 00192 static void I2Sx_In_MspDeInit(void); 00193 00194 static void I2Sx_Out_Init(uint32_t AudioFreq); 00195 static void I2Sx_Out_DeInit(void); 00196 00197 static uint8_t DFSDMx_DeInit(void); 00198 static void DFSDMx_ChannelMspInit(void); 00199 static void DFSDMx_ChannelMspDeInit(void); 00200 static void DFSDMx_FilterMspInit(void); 00201 static void DFSDMx_FilterMspDeInit(void); 00202 00203 /** 00204 * @} 00205 */ 00206 00207 /** @defgroup STM32F413H_DISCOVERY_AUDIO_out_Private_Functions STM32F413H DISCOVERY AUDIO OUT Private Functions 00208 * @{ 00209 */ 00210 00211 /** 00212 * @brief Configures the audio peripherals. 00213 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00214 * or OUTPUT_DEVICE_BOTH. 00215 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00216 * @param AudioFreq: Audio frequency used to play the audio stream. 00217 * @note The I2S PLL input clock must be done in the user application. 00218 * @retval AUDIO_OK if correct communication, else wrong communication 00219 */ 00220 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00221 { 00222 uint8_t ret = AUDIO_ERROR; 00223 uint32_t deviceid = 0x00; 00224 uint16_t buffer_fake[16] = {0x00}; 00225 00226 I2Sx_Out_DeInit(); 00227 AUDIO_IO_DeInit(); 00228 00229 /* PLL clock is set depending on the AudioFreq (44.1 kHz vs 48kHz groups) */ 00230 BSP_AUDIO_OUT_ClockConfig(&haudio_i2s, AudioFreq, NULL); 00231 00232 /* Configure the I2S peripheral */ 00233 haudio_i2s.Instance = AUDIO_OUT_I2Sx; 00234 if(HAL_I2S_GetState(&haudio_i2s) == HAL_I2S_STATE_RESET) 00235 { 00236 /* Initialize the I2S Msp: this __weak function can be rewritten by the application */ 00237 BSP_AUDIO_OUT_MspInit(&haudio_i2s, NULL); 00238 } 00239 I2Sx_Out_Init(AudioFreq); 00240 00241 AUDIO_IO_Init(); 00242 00243 /* wm8994 codec initialization */ 00244 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00245 00246 if(deviceid == WM8994_ID) 00247 { 00248 /* Reset the Codec Registers */ 00249 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00250 /* Initialize the audio driver structure */ 00251 audio_drv = &wm8994_drv; 00252 ret = AUDIO_OK; 00253 } 00254 else 00255 { 00256 ret = AUDIO_ERROR; 00257 } 00258 00259 if(ret == AUDIO_OK) 00260 { 00261 /* Send fake I2S data in order to generate MCLK needed by WM8994 to set its registers 00262 * MCLK is generated only when a data stream is sent on I2S */ 00263 HAL_I2S_Transmit_DMA(&haudio_i2s, buffer_fake, 16); 00264 /* Initialize the codec internal registers */ 00265 audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq); 00266 /* Stop sending fake I2S data */ 00267 HAL_I2S_DMAStop(&haudio_i2s); 00268 } 00269 00270 return ret; 00271 } 00272 00273 /** 00274 * @brief Starts playing audio stream from a data buffer for a determined size. 00275 * @param pBuffer: Pointer to the buffer 00276 * @param Size: Number of audio data BYTES. 00277 * @retval AUDIO_OK if correct communication, else wrong communication 00278 */ 00279 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size) 00280 { 00281 /* Call the audio Codec Play function */ 00282 if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0) 00283 { 00284 return AUDIO_ERROR; 00285 } 00286 else 00287 { 00288 /* Update the Media layer and enable it for play */ 00289 HAL_I2S_Transmit_DMA(&haudio_i2s, pBuffer, DMA_MAX(Size / AUDIODATA_SIZE)); 00290 00291 return AUDIO_OK; 00292 } 00293 } 00294 00295 /** 00296 * @brief Sends n-Bytes on the I2S interface. 00297 * @param pData: pointer on data address 00298 * @param Size: number of data to be written 00299 */ 00300 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size) 00301 { 00302 HAL_I2S_Transmit_DMA(&haudio_i2s, pData, Size); 00303 } 00304 00305 /** 00306 * @brief This function Pauses the audio file stream. In case 00307 * of using DMA, the DMA Pause feature is used. 00308 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00309 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00310 * function for resume could lead to unexpected behavior). 00311 * @retval AUDIO_OK if correct communication, else wrong communication 00312 */ 00313 uint8_t BSP_AUDIO_OUT_Pause(void) 00314 { 00315 /* Call the Audio Codec Pause/Resume function */ 00316 if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0) 00317 { 00318 return AUDIO_ERROR; 00319 } 00320 else 00321 { 00322 /* Call the Media layer pause function */ 00323 HAL_I2S_DMAPause(&haudio_i2s); 00324 00325 /* Return AUDIO_OK when all operations are correctly done */ 00326 return AUDIO_OK; 00327 } 00328 } 00329 00330 /** 00331 * @brief This function Resumes the audio file stream. 00332 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00333 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00334 * function for resume could lead to unexpected behavior). 00335 * @retval AUDIO_OK if correct communication, else wrong communication 00336 */ 00337 uint8_t BSP_AUDIO_OUT_Resume(void) 00338 { 00339 /* Call the Media layer pause/resume function */ 00340 /* DMA stream resumed before accessing WM8994 register as WM8994 needs the MCLK to be generated to access its registers 00341 * MCLK is generated only when a data stream is sent on I2S */ 00342 HAL_I2S_DMAResume(&haudio_i2s); 00343 00344 /* Call the Audio Codec Pause/Resume function */ 00345 if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0) 00346 { 00347 return AUDIO_ERROR; 00348 } 00349 else 00350 { 00351 /* Return AUDIO_OK when all operations are correctly done */ 00352 return AUDIO_OK; 00353 } 00354 } 00355 00356 /** 00357 * @brief Stops audio playing and Power down the Audio Codec. 00358 * @param Option: could be one of the following parameters 00359 * - CODEC_PDWN_SW: for software power off (by writing registers). 00360 * Then no need to reconfigure the Codec after power on. 00361 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00362 * Then need to reconfigure the Codec after power on. 00363 * @retval AUDIO_OK if correct communication, else wrong communication 00364 */ 00365 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option) 00366 { 00367 /* Call the Media layer stop function */ 00368 HAL_I2S_DMAStop(&haudio_i2s); 00369 00370 /* Call Audio Codec Stop function */ 00371 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 00372 { 00373 return AUDIO_ERROR; 00374 } 00375 else 00376 { 00377 if(Option == CODEC_PDWN_HW) 00378 { 00379 /* Wait at least 100us */ 00380 HAL_Delay(1); 00381 } 00382 /* Return AUDIO_OK when all operations are correctly done */ 00383 return AUDIO_OK; 00384 } 00385 } 00386 00387 /** 00388 * @brief Controls the current audio volume level. 00389 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00390 * Mute and 100 for Max volume level). 00391 * @retval AUDIO_OK if correct communication, else wrong communication 00392 */ 00393 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume) 00394 { 00395 /* Call the codec volume control function with converted volume value */ 00396 if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 00397 { 00398 return AUDIO_ERROR; 00399 } 00400 else 00401 { 00402 /* Return AUDIO_OK when all operations are correctly done */ 00403 return AUDIO_OK; 00404 } 00405 } 00406 00407 /** 00408 * @brief Enables or disables the MUTE mode by software 00409 * @param Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 00410 * unmute the codec and restore previous volume level. 00411 * @retval AUDIO_OK if correct communication, else wrong communication 00412 */ 00413 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd) 00414 { 00415 /* Call the Codec Mute function */ 00416 if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0) 00417 { 00418 return AUDIO_ERROR; 00419 } 00420 else 00421 { 00422 /* Return AUDIO_OK when all operations are correctly done */ 00423 return AUDIO_OK; 00424 } 00425 } 00426 00427 /** 00428 * @brief Switch dynamically (while audio file is played) the output target 00429 * (speaker or headphone). 00430 * @param Output: The audio output target: OUTPUT_DEVICE_SPEAKER, 00431 * OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH 00432 * @retval AUDIO_OK if correct communication, else wrong communication 00433 */ 00434 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output) 00435 { 00436 /* Call the Codec output device function */ 00437 if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0) 00438 { 00439 return AUDIO_ERROR; 00440 } 00441 else 00442 { 00443 /* Return AUDIO_OK when all operations are correctly done */ 00444 return AUDIO_OK; 00445 } 00446 } 00447 00448 /** 00449 * @brief Updates the audio frequency. 00450 * @param AudioFreq: Audio frequency used to play the audio stream. 00451 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00452 * audio frequency. 00453 * @retval None 00454 */ 00455 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq) 00456 { 00457 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00458 BSP_AUDIO_OUT_ClockConfig(&haudio_i2s, AudioFreq, NULL); 00459 00460 /* Disable I2S peripheral to allow access to I2S internal registers */ 00461 __HAL_I2S_DISABLE(&haudio_i2s); 00462 00463 /* Update the I2S audio frequency configuration */ 00464 haudio_i2s.Init.AudioFreq = AudioFreq; 00465 HAL_I2S_Init(&haudio_i2s); 00466 00467 /* Enable I2S peripheral to generate MCLK */ 00468 __HAL_I2S_ENABLE(&haudio_i2s); 00469 } 00470 00471 /** 00472 * @brief Deinit the audio peripherals. 00473 */ 00474 void BSP_AUDIO_OUT_DeInit(void) 00475 { 00476 I2Sx_Out_DeInit(); 00477 /* DeInit the I2S MSP : this __weak function can be rewritten by the application */ 00478 BSP_AUDIO_OUT_MspDeInit(&haudio_i2s, NULL); 00479 } 00480 00481 /** 00482 * @brief Tx Transfer completed callbacks. 00483 * @param hi2s: I2S handle 00484 */ 00485 void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s) 00486 { 00487 /* Manage the remaining file size and new address offset: This function 00488 should be coded by user (its prototype is already declared in STM32F413H_discovery_audio.h) */ 00489 BSP_AUDIO_OUT_TransferComplete_CallBack(); 00490 } 00491 00492 /** 00493 * @brief Tx Half Transfer completed callbacks. 00494 * @param hi2s: I2S handle 00495 */ 00496 void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s) 00497 { 00498 /* Manage the remaining file size and new address offset: This function 00499 should be coded by user (its prototype is already declared in STM32F413H_discovery_audio.h) */ 00500 BSP_AUDIO_OUT_HalfTransfer_CallBack(); 00501 } 00502 00503 /** 00504 * @brief I2S error callbacks. 00505 * @param hi2s: I2S handle 00506 */ 00507 void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s) 00508 { 00509 BSP_AUDIO_OUT_Error_CallBack(); 00510 } 00511 00512 /** 00513 * @brief Manages the DMA full Transfer complete event. 00514 */ 00515 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void) 00516 { 00517 } 00518 00519 /** 00520 * @brief Manages the DMA Half Transfer complete event. 00521 */ 00522 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) 00523 { 00524 } 00525 00526 /** 00527 * @brief Manages the DMA FIFO error event. 00528 */ 00529 __weak void BSP_AUDIO_OUT_Error_CallBack(void) 00530 { 00531 } 00532 00533 /** 00534 * @brief Initializes BSP_AUDIO_OUT MSP. 00535 * @param hi2s: I2S handle 00536 * @param Params : pointer on additional configuration parameters, can be NULL. 00537 */ 00538 __weak void BSP_AUDIO_OUT_MspInit(I2S_HandleTypeDef *hi2s, void *Params) 00539 { 00540 static DMA_HandleTypeDef hdma_i2s_tx; 00541 GPIO_InitTypeDef gpio_init_structure; 00542 00543 /* Prevent unused argument(s) compilation warning */ 00544 UNUSED(Params); 00545 00546 /* Enable I2S clock */ 00547 AUDIO_OUT_I2Sx_CLK_ENABLE(); 00548 00549 /* Enable MCK, SCK, WS, SD and CODEC_INT GPIO clock */ 00550 AUDIO_OUT_I2Sx_MCK_GPIO_CLK_ENABLE(); 00551 AUDIO_OUT_I2Sx_SCK_GPIO_CLK_ENABLE(); 00552 AUDIO_OUT_I2Sx_SD_GPIO_CLK_ENABLE(); 00553 AUDIO_OUT_I2Sx_WS_GPIO_CLK_ENABLE(); 00554 00555 /* CODEC_I2S pins configuration: MCK, SCK, WS and SD pins */ 00556 gpio_init_structure.Pin = AUDIO_OUT_I2Sx_MCK_PIN; 00557 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00558 gpio_init_structure.Pull = GPIO_NOPULL; 00559 gpio_init_structure.Speed = GPIO_SPEED_FAST; 00560 gpio_init_structure.Alternate = AUDIO_OUT_I2Sx_MCK_AF; 00561 HAL_GPIO_Init(AUDIO_OUT_I2Sx_MCK_GPIO_PORT, &gpio_init_structure); 00562 00563 gpio_init_structure.Pin = AUDIO_OUT_I2Sx_SCK_PIN; 00564 gpio_init_structure.Alternate = AUDIO_OUT_I2Sx_SCK_AF; 00565 HAL_GPIO_Init(AUDIO_OUT_I2Sx_SCK_GPIO_PORT, &gpio_init_structure); 00566 00567 gpio_init_structure.Pin = AUDIO_OUT_I2Sx_WS_PIN; 00568 gpio_init_structure.Alternate = AUDIO_OUT_I2Sx_WS_AF; 00569 HAL_GPIO_Init(AUDIO_OUT_I2Sx_WS_GPIO_PORT, &gpio_init_structure); 00570 00571 gpio_init_structure.Pin = AUDIO_OUT_I2Sx_SD_PIN; 00572 gpio_init_structure.Alternate = AUDIO_OUT_I2Sx_SD_AF; 00573 HAL_GPIO_Init(AUDIO_OUT_I2Sx_SD_GPIO_PORT, &gpio_init_structure); 00574 00575 /* Enable the DMA clock */ 00576 AUDIO_OUT_I2Sx_DMAx_CLK_ENABLE(); 00577 00578 if(hi2s->Instance == AUDIO_OUT_I2Sx) 00579 { 00580 /* Configure the hdma_i2s_rx handle parameters */ 00581 hdma_i2s_tx.Init.Channel = AUDIO_OUT_I2Sx_DMAx_CHANNEL; 00582 hdma_i2s_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; 00583 hdma_i2s_tx.Init.PeriphInc = DMA_PINC_DISABLE; 00584 hdma_i2s_tx.Init.MemInc = DMA_MINC_ENABLE; 00585 hdma_i2s_tx.Init.PeriphDataAlignment = AUDIO_OUT_I2Sx_DMAx_PERIPH_DATA_SIZE; 00586 hdma_i2s_tx.Init.MemDataAlignment = AUDIO_OUT_I2Sx_DMAx_MEM_DATA_SIZE; 00587 hdma_i2s_tx.Init.Mode = DMA_CIRCULAR; 00588 hdma_i2s_tx.Init.Priority = DMA_PRIORITY_HIGH; 00589 hdma_i2s_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 00590 hdma_i2s_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 00591 hdma_i2s_tx.Init.MemBurst = DMA_MBURST_SINGLE; 00592 hdma_i2s_tx.Init.PeriphBurst = DMA_MBURST_SINGLE; 00593 00594 hdma_i2s_tx.Instance = AUDIO_OUT_I2Sx_DMAx_STREAM; 00595 00596 /* Associate the DMA handle */ 00597 __HAL_LINKDMA(hi2s, hdmatx, hdma_i2s_tx); 00598 00599 /* Deinitialize the Stream for new transfer */ 00600 HAL_DMA_DeInit(&hdma_i2s_tx); 00601 00602 /* Configure the DMA Stream */ 00603 HAL_DMA_Init(&hdma_i2s_tx); 00604 } 00605 00606 /* Enable and set I2Sx Interrupt to a lower priority */ 00607 HAL_NVIC_SetPriority(SPI3_IRQn, 0x0F, 0x00); 00608 HAL_NVIC_EnableIRQ(SPI3_IRQn); 00609 00610 /* I2S DMA IRQ Channel configuration */ 00611 HAL_NVIC_SetPriority(AUDIO_OUT_I2Sx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 00612 HAL_NVIC_EnableIRQ(AUDIO_OUT_I2Sx_DMAx_IRQ); 00613 } 00614 00615 /** 00616 * @brief Deinitializes I2S MSP. 00617 * @param hi2s: I2S handle 00618 * @param Params : pointer on additional configuration parameters, can be NULL. 00619 */ 00620 __weak void BSP_AUDIO_OUT_MspDeInit(I2S_HandleTypeDef *hi2s, void *Params) 00621 { 00622 GPIO_InitTypeDef gpio_init_structure; 00623 00624 /* Prevent unused argument(s) compilation warning */ 00625 UNUSED(Params); 00626 00627 /* I2S DMA IRQ Channel deactivation */ 00628 HAL_NVIC_DisableIRQ(AUDIO_OUT_I2Sx_DMAx_IRQ); 00629 00630 if(hi2s->Instance == AUDIO_OUT_I2Sx) 00631 { 00632 /* Deinitialize the DMA stream */ 00633 HAL_DMA_DeInit(hi2s->hdmatx); 00634 } 00635 00636 /* Disable I2S peripheral */ 00637 __HAL_I2S_DISABLE(hi2s); 00638 00639 /* Deactives CODEC_I2S pins MCK, SCK, WS and SD by putting them in input mode */ 00640 gpio_init_structure.Pin = AUDIO_OUT_I2Sx_MCK_PIN; 00641 HAL_GPIO_DeInit(AUDIO_OUT_I2Sx_MCK_GPIO_PORT, gpio_init_structure.Pin); 00642 00643 gpio_init_structure.Pin = AUDIO_OUT_I2Sx_SCK_PIN; 00644 HAL_GPIO_DeInit(AUDIO_OUT_I2Sx_SCK_GPIO_PORT, gpio_init_structure.Pin); 00645 00646 gpio_init_structure.Pin = AUDIO_OUT_I2Sx_WS_PIN; 00647 HAL_GPIO_DeInit(AUDIO_OUT_I2Sx_WS_GPIO_PORT, gpio_init_structure.Pin); 00648 00649 gpio_init_structure.Pin = AUDIO_OUT_I2Sx_SD_PIN; 00650 HAL_GPIO_DeInit(AUDIO_OUT_I2Sx_SD_GPIO_PORT, gpio_init_structure.Pin); 00651 00652 /* Disable I2S clock */ 00653 AUDIO_OUT_I2Sx_CLK_DISABLE(); 00654 00655 /* GPIO pins clock and DMA clock can be shut down in the application 00656 by surcharging this __weak function */ 00657 } 00658 00659 /** 00660 * @brief Clock Config. 00661 * @param hi2s: might be required to set audio peripheral predivider if any. 00662 * @param AudioFreq: Audio frequency used to play the audio stream. 00663 * @param Params : pointer on additional configuration parameters, can be NULL. 00664 * @note This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency() 00665 * Being __weak it can be overwritten by the application 00666 */ 00667 __weak void BSP_AUDIO_OUT_ClockConfig(I2S_HandleTypeDef *hi2s, uint32_t AudioFreq, void *Params) 00668 { 00669 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 00670 00671 /* Prevent unused argument(s) compilation warning */ 00672 UNUSED(Params); 00673 00674 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 00675 00676 /* Set the PLL configuration according to the audio frequency */ 00677 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 00678 { 00679 /* Configure PLLI2S prescalers */ 00680 rcc_ex_clk_init_struct.PeriphClockSelection = (RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_PLLI2S); 00681 rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S; 00682 rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC; 00683 rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8; 00684 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 271; 00685 rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 2; 00686 00687 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00688 } 00689 else if(AudioFreq == AUDIO_FREQUENCY_96K) /* AUDIO_FREQUENCY_96K */ 00690 { 00691 /* I2S clock config */ 00692 rcc_ex_clk_init_struct.PeriphClockSelection = (RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_PLLI2S); 00693 rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S; 00694 rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC; 00695 rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8; 00696 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 00697 rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 2; 00698 00699 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00700 } 00701 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K */ 00702 { 00703 /* I2S clock config 00704 PLLI2S_VCO: VCO_344M 00705 I2S_CLK(first level) = PLLI2S_VCO/PLLI2SR = 344/7 = 49.142 Mhz 00706 I2S_CLK_x = I2S_CLK(first level)/PLLI2SDIVR = 49.142/1 = 49.142 Mhz */ 00707 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_PLLI2S; 00708 rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S; 00709 rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC; 00710 rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8; 00711 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 00712 rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 7; 00713 00714 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00715 } 00716 } 00717 00718 /******************************************************************************* 00719 Static Functions 00720 *******************************************************************************/ 00721 00722 /** 00723 * @brief Initializes the Audio Codec audio interface (I2S) 00724 * @note This function assumes that the I2S input clock 00725 * is already configured and ready to be used. 00726 * @param AudioFreq: Audio frequency to be configured for the I2S peripheral. 00727 */ 00728 static void I2Sx_Out_Init(uint32_t AudioFreq) 00729 { 00730 /* Initialize the hAudioInI2s Instance parameter */ 00731 haudio_i2s.Instance = AUDIO_OUT_I2Sx; 00732 00733 /* Disable I2S block */ 00734 __HAL_I2S_DISABLE(&haudio_i2s); 00735 00736 /* I2S peripheral configuration */ 00737 haudio_i2s.Init.AudioFreq = AudioFreq; 00738 haudio_i2s.Init.ClockSource = I2S_CLOCK_PLL; 00739 haudio_i2s.Init.CPOL = I2S_CPOL_LOW; 00740 haudio_i2s.Init.DataFormat = I2S_DATAFORMAT_16B; 00741 haudio_i2s.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE; 00742 haudio_i2s.Init.Mode = I2S_MODE_MASTER_TX; 00743 haudio_i2s.Init.Standard = I2S_STANDARD_PHILIPS; 00744 haudio_i2s.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE; 00745 00746 /* Init the I2S */ 00747 HAL_I2S_Init(&haudio_i2s); 00748 00749 /* Enable I2S block */ 00750 __HAL_I2S_ENABLE(&haudio_i2s); 00751 } 00752 00753 /** 00754 * @brief Deinitializes the Audio Codec audio interface (I2S). 00755 */ 00756 static void I2Sx_Out_DeInit(void) 00757 { 00758 /* Initialize the hAudioInI2s Instance parameter */ 00759 haudio_i2s.Instance = AUDIO_OUT_I2Sx; 00760 00761 /* Disable I2S block */ 00762 __HAL_I2S_DISABLE(&haudio_i2s); 00763 00764 /* DeInit the I2S */ 00765 HAL_I2S_DeInit(&haudio_i2s); 00766 } 00767 00768 /** 00769 * @} 00770 */ 00771 00772 /** @defgroup STM32F413H_DISCOVERY_AUDIO_IN_Private_Functions STM32F413H DISCOVERY AUDIO IN Private functions 00773 * @{ 00774 */ 00775 00776 /** 00777 * @brief Initializes wave recording. 00778 * @param AudioFreq: Audio frequency to be configured for the audio in peripheral. 00779 * @param BitRes: Audio bit resolution. 00780 * @param ChnlNbr: Audio channel number. 00781 * @retval AUDIO_OK if correct communication, else wrong communication 00782 */ 00783 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00784 { 00785 return BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC, AudioFreq, BitRes, ChnlNbr); 00786 } 00787 00788 /** 00789 * @brief Initializes wave recording. 00790 * @param InputDevice: INPUT_DEVICE_DIGITAL_MICx or INPUT_DEVICE_ANALOG_MIC. 00791 * @param AudioFreq: Audio frequency to be configured for the audio in peripheral. 00792 * @param BitRes: Audio bit resolution. 00793 * @param ChnlNbr: Audio channel number. 00794 * @retval AUDIO_OK if correct communication, else wrong communication 00795 */ 00796 uint8_t BSP_AUDIO_IN_InitEx(uint32_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00797 { 00798 uint32_t ret = AUDIO_ERROR; 00799 uint32_t deviceid =0; 00800 uint32_t mic_enabled =0; 00801 uint16_t buffer_fake[16] = {0x00}; 00802 uint32_t i = 0; 00803 00804 /* Store the audio record context */ 00805 hAudioIn.Frequency = AudioFreq; 00806 hAudioIn.BitResolution = BitRes; 00807 hAudioIn.InputDevice = InputDevice; 00808 hAudioIn.ChannelNbr = ChnlNbr; 00809 00810 /* Store the total number of microphones enabled */ 00811 for(i = 0; i < DFSDM_MIC_NUMBER; i ++) 00812 { 00813 if(((hAudioIn.InputDevice >> i) & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 00814 { 00815 mic_enabled++; 00816 } 00817 } 00818 00819 if (InputDevice == INPUT_DEVICE_ANALOG_MIC) 00820 { 00821 InputDevice = INPUT_DEVICE_INPUT_LINE_1; 00822 /* INPUT_DEVICE_ANALOG_MIC */ 00823 /* Disable I2S */ 00824 I2Sx_In_DeInit(); 00825 00826 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */ 00827 BSP_AUDIO_IN_ClockConfig(AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT for analog mic */ 00828 00829 /* I2S data transfer preparation: 00830 Prepare the Media to be used for the audio transfer from I2S peripheral to memory */ 00831 haudio_i2s.Instance = AUDIO_IN_I2Sx; 00832 if(HAL_I2S_GetState(&haudio_i2s) == HAL_I2S_STATE_RESET) 00833 { 00834 BSP_AUDIO_OUT_MspInit(&haudio_i2s, NULL); /* Initialize GPIOs for SPI3 Master signals */ 00835 /* Init the I2S MSP: this __weak function can be redefined by the application*/ 00836 BSP_AUDIO_IN_MspInit(NULL); 00837 } 00838 00839 /* Configure I2S */ 00840 I2Sx_In_Init(AudioFreq); 00841 00842 AUDIO_IO_Init(); 00843 00844 /* wm8994 codec initialization */ 00845 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00846 00847 if((deviceid) == WM8994_ID) 00848 { 00849 /* Reset the Codec Registers */ 00850 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00851 /* Initialize the audio driver structure */ 00852 audio_drv = &wm8994_drv; 00853 ret = AUDIO_OK; 00854 } 00855 else 00856 { 00857 ret = AUDIO_ERROR; 00858 } 00859 00860 if(ret == AUDIO_OK) 00861 { 00862 /* Receive fake I2S data in order to generate MCLK needed by WM8994 to set its registers */ 00863 HAL_I2S_Receive_DMA(&haudio_i2s, buffer_fake, 16); 00864 /* Initialize the codec internal registers */ 00865 audio_drv->Init(AUDIO_I2C_ADDRESS, (OUTPUT_DEVICE_HEADPHONE|InputDevice), 100, AudioFreq); 00866 /* Stop receiving fake I2S data */ 00867 HAL_I2S_DMAStop(&haudio_i2s); 00868 } 00869 } 00870 else 00871 { 00872 if(hAudioIn.ChannelNbr != mic_enabled) 00873 { 00874 return AUDIO_ERROR; 00875 } 00876 else 00877 { 00878 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */ 00879 BSP_AUDIO_IN_ClockConfig(AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT for analog mic */ 00880 00881 /* Init the DFSDM MSP: this __weak function can be redefined by the application*/ 00882 BSP_AUDIO_IN_MspInit(NULL); 00883 00884 /* Default configuration of DFSDM filters and channels */ 00885 ret = BSP_AUDIO_IN_ConfigDigitalMic(hAudioIn.InputDevice, NULL); 00886 } 00887 } 00888 00889 /* Return AUDIO_OK when all operations are correctly done */ 00890 return ret; 00891 } 00892 00893 /** 00894 * @brief DeInitializes the audio peripheral. 00895 */ 00896 void BSP_AUDIO_IN_DeInit(void) 00897 { 00898 if(hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC) 00899 { 00900 /* MSP filters/channels initialization */ 00901 BSP_AUDIO_IN_MspDeInit(NULL); 00902 00903 DFSDMx_DeInit(); 00904 } 00905 else 00906 { 00907 I2Sx_In_DeInit(); 00908 } 00909 } 00910 00911 /** 00912 * @brief Initializes default configuration of the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 00913 * @param InputDevice: The microphone to be configured. Can be INPUT_DEVICE_DIGITAL_MIC1..INPUT_DEVICE_DIGITAL_MIC5 00914 * @note Channel output Clock Divider and Filter Oversampling are calculated as follow: 00915 * - Clock_Divider = CLK(input DFSDM)/CLK(micro) with 00916 * 1MHZ < CLK(micro) < 3.2MHZ (TYP 2.4MHZ for MP34DT01TR) 00917 * - Oversampling = CLK(input DFSDM)/(Clock_Divider * AudioFreq) 00918 * @retval AUDIO_OK if correct communication, else wrong communication 00919 */ 00920 uint8_t BSP_AUDIO_IN_ConfigMicDefault(uint32_t InputDevice) 00921 { 00922 uint32_t i = 0, mic_init[DFSDM_MIC_NUMBER] = {0}; 00923 uint32_t filter_ch = 0, mic_num = 0; 00924 00925 DFSDM_Filter_TypeDef* FilterInstnace[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_MIC1_FILTER, AUDIO_DFSDMx_MIC2_FILTER, AUDIO_DFSDMx_MIC3_FILTER, AUDIO_DFSDMx_MIC4_FILTER, AUDIO_DFSDMx_MIC5_FILTER}; 00926 DFSDM_Channel_TypeDef* ChannelInstnace[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_MIC1_CHANNEL, AUDIO_DFSDMx_MIC2_CHANNEL, AUDIO_DFSDMx_MIC3_CHANNEL, AUDIO_DFSDMx_MIC4_CHANNEL, AUDIO_DFSDMx_MIC5_CHANNEL}; 00927 uint32_t DigitalMicPins[DFSDM_MIC_NUMBER] = {DFSDM_CHANNEL_SAME_CHANNEL_PINS, DFSDM_CHANNEL_SAME_CHANNEL_PINS, DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS, DFSDM_CHANNEL_SAME_CHANNEL_PINS, DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS}; 00928 uint32_t DigitalMicType[DFSDM_MIC_NUMBER] = {DFSDM_CHANNEL_SPI_RISING, DFSDM_CHANNEL_SPI_RISING, DFSDM_CHANNEL_SPI_FALLING, DFSDM_CHANNEL_SPI_RISING, DFSDM_CHANNEL_SPI_FALLING}; 00929 uint32_t Channel4Filter[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_MIC1_CHANNEL_FOR_FILTER, AUDIO_DFSDMx_MIC2_CHANNEL_FOR_FILTER, AUDIO_DFSDMx_MIC3_CHANNEL_FOR_FILTER, AUDIO_DFSDMx_MIC4_CHANNEL_FOR_FILTER, AUDIO_DFSDMx_MIC5_CHANNEL_FOR_FILTER}; 00930 00931 for(i = 0; i < hAudioIn.ChannelNbr; i++) 00932 { 00933 if(((InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] != 1)) 00934 { 00935 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC1); 00936 } 00937 else if(((InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] != 1)) 00938 { 00939 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC2); 00940 } 00941 else if(((InputDevice & INPUT_DEVICE_DIGITAL_MIC3) == INPUT_DEVICE_DIGITAL_MIC3) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)] != 1)) 00942 { 00943 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC3); 00944 } 00945 else if(((InputDevice & INPUT_DEVICE_DIGITAL_MIC4) == INPUT_DEVICE_DIGITAL_MIC4) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)] != 1)) 00946 { 00947 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC4); 00948 } 00949 else if(((InputDevice & INPUT_DEVICE_DIGITAL_MIC5) == INPUT_DEVICE_DIGITAL_MIC5) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)] != 1)) 00950 { 00951 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC5); 00952 } 00953 00954 mic_init[mic_num] = 1; 00955 00956 /* Filter **********************************************************************************************************/ 00957 if(hAudioInDfsdmFilter[mic_num].Instance != NULL) 00958 { 00959 if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInDfsdmFilter[mic_num])) 00960 { 00961 return AUDIO_ERROR; 00962 } 00963 /* MIC filters initialization */ 00964 __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInDfsdmFilter[mic_num]); 00965 } 00966 00967 /* MIC filters initialization */ 00968 __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInDfsdmFilter[mic_num]); 00969 hAudioInDfsdmFilter[mic_num].Instance = FilterInstnace[mic_num]; 00970 hAudioInDfsdmFilter[mic_num].Init.RegularParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 00971 hAudioInDfsdmFilter[mic_num].Init.RegularParam.FastMode = ENABLE; 00972 hAudioInDfsdmFilter[mic_num].Init.RegularParam.DmaMode = ENABLE; 00973 hAudioInDfsdmFilter[mic_num].Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 00974 hAudioInDfsdmFilter[mic_num].Init.InjectedParam.ScanMode = DISABLE; 00975 hAudioInDfsdmFilter[mic_num].Init.InjectedParam.DmaMode = DISABLE; 00976 hAudioInDfsdmFilter[mic_num].Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO; 00977 hAudioInDfsdmFilter[mic_num].Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES; 00978 hAudioInDfsdmFilter[mic_num].Init.FilterParam.SincOrder = DFSDM_FILTER_ORDER(hAudioIn.Frequency); 00979 hAudioInDfsdmFilter[mic_num].Init.FilterParam.Oversampling = DFSDM_OVER_SAMPLING(hAudioIn.Frequency); 00980 hAudioInDfsdmFilter[mic_num].Init.FilterParam.IntOversampling = 1; 00981 00982 if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInDfsdmFilter[mic_num])) 00983 { 00984 return AUDIO_ERROR; 00985 } 00986 00987 /* Channel **********************************************************************************************************/ 00988 if(hAudioInDfsdmChannel[mic_num].Instance != NULL) 00989 { 00990 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInDfsdmChannel[mic_num])) 00991 { 00992 return AUDIO_ERROR; 00993 } 00994 00995 /* MIC channels initialization */ 00996 __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInDfsdmChannel[mic_num]); 00997 } 00998 00999 /* MIC channels initialization */ 01000 __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInDfsdmChannel[mic_num]); 01001 hAudioInDfsdmChannel[mic_num].Init.OutputClock.Activation = ENABLE; 01002 hAudioInDfsdmChannel[mic_num].Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01003 hAudioInDfsdmChannel[mic_num].Init.OutputClock.Divider = DFSDM_CLOCK_DIVIDER(hAudioIn.Frequency); 01004 hAudioInDfsdmChannel[mic_num].Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01005 hAudioInDfsdmChannel[mic_num].Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01006 hAudioInDfsdmChannel[mic_num].Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01007 hAudioInDfsdmChannel[mic_num].Init.Awd.FilterOrder = DFSDM_CHANNEL_SINC1_ORDER; 01008 hAudioInDfsdmChannel[mic_num].Init.Awd.Oversampling = 10; 01009 hAudioInDfsdmChannel[mic_num].Init.Offset = 0; 01010 hAudioInDfsdmChannel[mic_num].Init.RightBitShift = DFSDM_MIC_BIT_SHIFT(hAudioIn.Frequency); 01011 hAudioInDfsdmChannel[mic_num].Instance = ChannelInstnace[mic_num]; 01012 hAudioInDfsdmChannel[mic_num].Init.Input.Pins = DigitalMicPins[mic_num]; 01013 hAudioInDfsdmChannel[mic_num].Init.SerialInterface.Type = DigitalMicType[mic_num]; 01014 01015 if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInDfsdmChannel[mic_num])) 01016 { 01017 return AUDIO_ERROR; 01018 } 01019 01020 filter_ch = Channel4Filter[mic_num]; 01021 /* Configure injected channel */ 01022 if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInDfsdmFilter[mic_num], filter_ch, DFSDM_CONTINUOUS_CONV_ON)) 01023 { 01024 return AUDIO_ERROR; 01025 } 01026 } 01027 return AUDIO_OK; 01028 } 01029 01030 /** 01031 * @brief Initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01032 * @param InputDevice: The microphone to be configured. Can be INPUT_DEVICE_DIGITAL_MIC1..INPUT_DEVICE_DIGITAL_MIC5 01033 * @param Params : pointer on additional configuration parameters, can be NULL. 01034 * @retval AUDIO_OK if correct communication, else wrong communication 01035 */ 01036 __weak uint8_t BSP_AUDIO_IN_ConfigDigitalMic(uint32_t InputDevice, void *Params) 01037 { 01038 /* Prevent unused argument(s) compilation warning */ 01039 UNUSED(Params); 01040 01041 /* Default configuration of DFSDM filters and channels */ 01042 return(BSP_AUDIO_IN_ConfigMicDefault(InputDevice)); 01043 /* Note: This function can be called at application level and default configuration 01044 can be ovewritten to fit user's need */ 01045 } 01046 01047 /** 01048 * @brief Allocate channel buffer scratch 01049 * @param pScratch : pointer to scratch tables. 01050 * @param size: size of scratch buffer 01051 */ 01052 uint8_t BSP_AUDIO_IN_AllocScratch (int32_t *pScratch, uint32_t size) 01053 { 01054 uint32_t idx; 01055 01056 ScratchSize = size / DEFAULT_AUDIO_IN_CHANNEL_NBR; 01057 01058 /* copy scratch pointers */ 01059 for (idx = 0; idx < DEFAULT_AUDIO_IN_CHANNEL_NBR ; idx++) 01060 { 01061 pScratchBuff[idx] = (int32_t *)(pScratch + idx * ScratchSize); 01062 } 01063 /* Return AUDIO_OK */ 01064 return AUDIO_OK; 01065 } 01066 01067 /** 01068 * @brief Starts audio recording. 01069 * @param pBuf: Main buffer pointer for the recorded data storing 01070 * @param size: Current size of the recorded buffer 01071 * @retval AUDIO_OK if correct communication, else wrong communication 01072 */ 01073 uint8_t BSP_AUDIO_IN_Record(uint16_t *pBuf, uint32_t size) 01074 { 01075 hAudioIn.pRecBuf = pBuf; 01076 hAudioIn.RecSize = size; 01077 /* Reset Application Buffer Trigger */ 01078 AppBuffTrigger = 0; 01079 AppBuffHalf = 0; 01080 01081 if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC) 01082 { 01083 /* Call the Media layer start function for MIC1 channel */ 01084 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], ScratchSize)) 01085 { 01086 return AUDIO_ERROR; 01087 } 01088 01089 /* Call the Media layer start function for MIC2 channel */ 01090 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], ScratchSize)) 01091 { 01092 return AUDIO_ERROR; 01093 } 01094 } 01095 else 01096 { 01097 /* Start the process to receive the DMA */ 01098 if (HAL_OK != HAL_I2SEx_TransmitReceive_DMA(&haudio_i2s, pBuf, pBuf, size)) 01099 { 01100 return AUDIO_ERROR; 01101 } 01102 } 01103 /* Return AUDIO_OK when all operations are correctly done */ 01104 return AUDIO_OK; 01105 } 01106 01107 /** 01108 * @brief Starts audio recording. 01109 * @param pBuf: Main buffer pointer for the recorded data storing 01110 * @param size: Current size of the recorded buffer 01111 * @retval AUDIO_OK if correct communication, else wrong communication 01112 */ 01113 uint8_t BSP_AUDIO_IN_RecordEx(uint32_t *pBuf, uint32_t size) 01114 { 01115 uint8_t ret = AUDIO_ERROR; 01116 hAudioIn.RecSize = size; 01117 uint32_t i = 0; 01118 uint32_t mic_init[DFSDM_MIC_NUMBER] = {0}; 01119 if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 01120 { 01121 return ret; 01122 } 01123 else 01124 { 01125 hAudioIn.MultiBuffMode = 1; 01126 for(i = 0; i < hAudioIn.ChannelNbr; i++) 01127 { 01128 if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] != 1)) 01129 { 01130 /* Call the Media layer start function for MIC1 channel 1 */ 01131 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], (int32_t*)pBuf[i], size)) 01132 { 01133 return AUDIO_ERROR; 01134 } 01135 MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = i; 01136 mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 1; 01137 } 01138 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] != 1)) 01139 { 01140 /* Call the Media layer start function for MIC2 channel 1 */ 01141 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], (int32_t*)pBuf[i], size)) 01142 { 01143 return AUDIO_ERROR; 01144 } 01145 MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = i; 01146 mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = 1; 01147 } 01148 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC3) == INPUT_DEVICE_DIGITAL_MIC3) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)] != 1)) 01149 { 01150 /* Call the Media layer start function for MIC3 channel 0 */ 01151 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)], (int32_t*)pBuf[i], size)) 01152 { 01153 return AUDIO_ERROR; 01154 } 01155 MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)] = i; 01156 mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)] = 1; 01157 } 01158 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC4) == INPUT_DEVICE_DIGITAL_MIC4) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)] != 1)) 01159 { 01160 /* Call the Media layer start function for MIC4 channel 7 */ 01161 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)], (int32_t*)pBuf[i], size)) 01162 { 01163 return AUDIO_ERROR; 01164 } 01165 MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)] = i; 01166 mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)] = 1; 01167 } 01168 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC5) == INPUT_DEVICE_DIGITAL_MIC5) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)] != 1)) 01169 { 01170 /* Call the Media layer start function for MIC5 channel 6 */ 01171 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)], (int32_t*)pBuf[i], size)) 01172 { 01173 return AUDIO_ERROR; 01174 } 01175 MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)] = i; 01176 mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)] = 1; 01177 } 01178 } 01179 } 01180 /* Return AUDIO_OK when all operations are correctly done */ 01181 return AUDIO_OK; 01182 } 01183 01184 /** 01185 * @brief Initializes the I2S MSP. 01186 */ 01187 static void I2Sx_In_MspInit(void) 01188 { 01189 static DMA_HandleTypeDef hdma_i2s_rx; 01190 GPIO_InitTypeDef gpio_init_structure; 01191 01192 /* Enable I2S clock */ 01193 AUDIO_IN_I2Sx_CLK_ENABLE(); 01194 01195 /* Enable MCK GPIO clock, needed by the codec */ 01196 AUDIO_OUT_I2Sx_MCK_GPIO_CLK_ENABLE(); 01197 01198 /* CODEC_I2S pins configuration: MCK pins */ 01199 gpio_init_structure.Pin = AUDIO_OUT_I2Sx_MCK_PIN; 01200 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 01201 gpio_init_structure.Pull = GPIO_NOPULL; 01202 gpio_init_structure.Speed = GPIO_SPEED_FAST; 01203 gpio_init_structure.Alternate = AUDIO_OUT_I2Sx_MCK_AF; 01204 HAL_GPIO_Init(AUDIO_OUT_I2Sx_MCK_GPIO_PORT, &gpio_init_structure); 01205 01206 /* Enable SD GPIO clock */ 01207 AUDIO_IN_I2Sx_EXT_SD_GPIO_CLK_ENABLE(); 01208 /* CODEC_I2S pin configuration: SD pin */ 01209 gpio_init_structure.Pin = AUDIO_IN_I2Sx_EXT_SD_PIN; 01210 gpio_init_structure.Alternate = AUDIO_IN_I2Sx_EXT_SD_AF; 01211 HAL_GPIO_Init(AUDIO_IN_I2Sx_EXT_SD_GPIO_PORT, &gpio_init_structure); 01212 01213 /* Enable the DMA clock */ 01214 AUDIO_IN_I2Sx_DMAx_CLK_ENABLE(); 01215 01216 if(haudio_i2s.Instance == AUDIO_IN_I2Sx) 01217 { 01218 /* Configure the hdma_i2s_rx handle parameters */ 01219 hdma_i2s_rx.Init.Channel = AUDIO_IN_I2Sx_DMAx_CHANNEL; 01220 hdma_i2s_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; 01221 hdma_i2s_rx.Init.PeriphInc = DMA_PINC_DISABLE; 01222 hdma_i2s_rx.Init.MemInc = DMA_MINC_ENABLE; 01223 hdma_i2s_rx.Init.PeriphDataAlignment = AUDIO_IN_I2Sx_DMAx_PERIPH_DATA_SIZE; 01224 hdma_i2s_rx.Init.MemDataAlignment = AUDIO_IN_I2Sx_DMAx_MEM_DATA_SIZE; 01225 hdma_i2s_rx.Init.Mode = DMA_CIRCULAR; 01226 hdma_i2s_rx.Init.Priority = DMA_PRIORITY_HIGH; 01227 hdma_i2s_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 01228 hdma_i2s_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 01229 hdma_i2s_rx.Init.MemBurst = DMA_MBURST_SINGLE; 01230 hdma_i2s_rx.Init.PeriphBurst = DMA_MBURST_SINGLE; 01231 01232 hdma_i2s_rx.Instance = AUDIO_IN_I2Sx_DMAx_STREAM; 01233 01234 /* Associate the DMA handle */ 01235 __HAL_LINKDMA(&haudio_i2s, hdmarx, hdma_i2s_rx); 01236 01237 /* Deinitialize the Stream for new transfer */ 01238 HAL_DMA_DeInit(&hdma_i2s_rx); 01239 01240 /* Configure the DMA Stream */ 01241 HAL_DMA_Init(&hdma_i2s_rx); 01242 } 01243 01244 /* I2S DMA IRQ Channel configuration */ 01245 HAL_NVIC_SetPriority(AUDIO_IN_I2Sx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 01246 HAL_NVIC_EnableIRQ(AUDIO_IN_I2Sx_DMAx_IRQ); 01247 } 01248 01249 /** 01250 * @brief De-Initializes the I2S MSP. 01251 */ 01252 static void I2Sx_In_MspDeInit(void) 01253 { 01254 GPIO_InitTypeDef gpio_init_structure; 01255 01256 /* I2S DMA IRQ Channel deactivation */ 01257 HAL_NVIC_DisableIRQ(AUDIO_IN_I2Sx_DMAx_IRQ); 01258 01259 if(haudio_i2s.Instance == AUDIO_IN_I2Sx) 01260 { 01261 /* Deinitialize the DMA stream */ 01262 HAL_DMA_DeInit(haudio_i2s.hdmarx); 01263 } 01264 01265 /* Disable I2S peripheral */ 01266 __HAL_I2S_DISABLE(&haudio_i2s); 01267 01268 /* Deactives CODEC_I2S pins MCK by putting them in input mode */ 01269 gpio_init_structure.Pin = AUDIO_OUT_I2Sx_MCK_PIN; 01270 HAL_GPIO_DeInit(AUDIO_OUT_I2Sx_MCK_GPIO_PORT, gpio_init_structure.Pin); 01271 01272 gpio_init_structure.Pin = AUDIO_IN_I2Sx_EXT_SD_PIN; 01273 HAL_GPIO_DeInit(AUDIO_IN_I2Sx_EXT_SD_GPIO_PORT, gpio_init_structure.Pin); 01274 01275 /* Disable I2S clock */ 01276 AUDIO_IN_I2Sx_CLK_DISABLE(); 01277 } 01278 01279 /** 01280 * @brief Initializes BSP_AUDIO_IN MSP. 01281 * @param Params : pointer on additional configuration parameters, can be NULL. 01282 */ 01283 __weak void BSP_AUDIO_IN_MspInit(void *Params) 01284 { 01285 /* Prevent unused argument(s) compilation warning */ 01286 UNUSED(Params); 01287 01288 if(hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 01289 { 01290 I2Sx_In_MspInit(); 01291 } 01292 else 01293 { 01294 /* MSP channels initialization */ 01295 DFSDMx_ChannelMspInit(); 01296 01297 /* MSP filters initialization */ 01298 DFSDMx_FilterMspInit(); 01299 } 01300 } 01301 01302 /** 01303 * @brief De-Initializes BSP_AUDIO_IN MSP. 01304 * @param Params : pointer on additional configuration parameters, can be NULL. 01305 */ 01306 __weak void BSP_AUDIO_IN_MspDeInit(void *Params) 01307 { 01308 /* Prevent unused argument(s) compilation warning */ 01309 UNUSED(Params); 01310 01311 if(hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 01312 { 01313 I2Sx_In_MspDeInit(); 01314 } 01315 else 01316 { 01317 /* MSP channels initialization */ 01318 DFSDMx_ChannelMspDeInit(); 01319 01320 /* MSP filters initialization */ 01321 DFSDMx_FilterMspDeInit(); 01322 } 01323 } 01324 01325 /** 01326 * @brief Clock Config. 01327 * @param AudioFreq: Audio frequency used to play the audio stream. 01328 * @param Params : pointer on additional configuration parameters, can be NULL. 01329 * @note This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency() 01330 * Being __weak it can be overwritten by the application 01331 * @retval AUDIO_OK if correct communication, else wrong communication 01332 */ 01333 __weak uint8_t BSP_AUDIO_IN_ClockConfig(uint32_t AudioFreq, void *Params) 01334 { 01335 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 01336 01337 /* Prevent unused argument(s) compilation warning */ 01338 UNUSED(Params); 01339 01340 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 01341 01342 /* Set the PLL configuration according to the audio frequency */ 01343 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 01344 { 01345 /* Configure PLLI2S prescalers */ 01346 rcc_ex_clk_init_struct.PeriphClockSelection = (RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_DFSDM | RCC_PERIPHCLK_DFSDM2); 01347 rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S; 01348 rcc_ex_clk_init_struct.Dfsdm1ClockSelection = RCC_DFSDM1CLKSOURCE_APB2; 01349 rcc_ex_clk_init_struct.Dfsdm2ClockSelection = RCC_DFSDM2CLKSOURCE_APB2; 01350 rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC; 01351 rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8; 01352 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 271; 01353 rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 2; 01354 01355 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01356 } 01357 else if(AudioFreq == AUDIO_FREQUENCY_96K) 01358 { 01359 /* I2S clock config */ 01360 rcc_ex_clk_init_struct.PeriphClockSelection = (RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_DFSDM | RCC_PERIPHCLK_DFSDM2); 01361 rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S; 01362 rcc_ex_clk_init_struct.Dfsdm1ClockSelection = RCC_DFSDM1CLKSOURCE_APB2; 01363 rcc_ex_clk_init_struct.Dfsdm2ClockSelection = RCC_DFSDM2CLKSOURCE_APB2; 01364 rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC; 01365 rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8; 01366 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 01367 rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 2; 01368 01369 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01370 } 01371 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_32K, AUDIO_FREQUENCY_48K */ 01372 { 01373 /* I2S clock config 01374 PLLI2S_VCO: VCO_344M 01375 I2S_CLK(first level) = PLLI2S_VCO/PLLI2SR = 344/7 = 49.142 Mhz 01376 I2S_CLK_x = I2S_CLK(first level)/PLLI2SDIVR = 49.142/1 = 49.142 Mhz */ 01377 rcc_ex_clk_init_struct.PeriphClockSelection = (RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_DFSDM | RCC_PERIPHCLK_DFSDM2); 01378 rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S; 01379 rcc_ex_clk_init_struct.DfsdmClockSelection = RCC_DFSDM1CLKSOURCE_APB2|RCC_DFSDM2CLKSOURCE_APB2; 01380 rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC; 01381 rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8; 01382 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 01383 rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 7; 01384 01385 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01386 } 01387 01388 if(hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC) 01389 { 01390 /* I2S_APB1 selected as DFSDM audio clock source */ 01391 __HAL_RCC_DFSDM1AUDIO_CONFIG(RCC_DFSDM1AUDIOCLKSOURCE_I2SAPB1); 01392 /* I2S_APB1 selected as DFSDM audio clock source */ 01393 __HAL_RCC_DFSDM2AUDIO_CONFIG(RCC_DFSDM2AUDIOCLKSOURCE_I2SAPB1); 01394 } 01395 01396 return AUDIO_OK; 01397 } 01398 01399 /** 01400 * @brief Regular conversion complete callback. 01401 * @note In interrupt mode, user has to read conversion value in this function 01402 using HAL_DFSDM_FilterGetRegularValue. 01403 * @param hdfsdm_filter : DFSDM filter handle. 01404 */ 01405 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01406 { 01407 uint32_t index, input_device = 0; 01408 01409 if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC1_FILTER) 01410 { 01411 DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 1; 01412 input_device = INPUT_DEVICE_DIGITAL_MIC1; 01413 } 01414 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC2_FILTER) 01415 { 01416 DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = 1; 01417 input_device = INPUT_DEVICE_DIGITAL_MIC2; 01418 } 01419 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC3_FILTER) 01420 { 01421 input_device = INPUT_DEVICE_DIGITAL_MIC3; 01422 } 01423 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC4_FILTER) 01424 { 01425 input_device = INPUT_DEVICE_DIGITAL_MIC4; 01426 } 01427 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC5_FILTER) 01428 { 01429 input_device = INPUT_DEVICE_DIGITAL_MIC5; 01430 } 01431 01432 if(hAudioIn.MultiBuffMode == 1) 01433 { 01434 BSP_AUDIO_IN_TransferComplete_CallBackEx(input_device); 01435 } 01436 else 01437 { 01438 if((DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] == 1) && (DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] == 1)) 01439 { 01440 if(AppBuffTrigger >= hAudioIn.RecSize) 01441 AppBuffTrigger = 0; 01442 01443 for(index = (ScratchSize/2) ; index < ScratchSize; index++) 01444 { 01445 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)][index] >> 8), -32760, 32760)); 01446 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)][index] >> 8), -32760, 32760)); 01447 AppBuffTrigger += 2; 01448 } 01449 DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 0; 01450 } 01451 01452 /* Update Trigger with Remaining Byte before callback if necessary */ 01453 if(AppBuffTrigger >= hAudioIn.RecSize) 01454 { 01455 /* Reset Application Buffer Trigger */ 01456 AppBuffTrigger = 0; 01457 AppBuffHalf = 0; 01458 01459 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01460 BSP_AUDIO_IN_TransferComplete_CallBack(); 01461 } 01462 else if((AppBuffTrigger >= hAudioIn.RecSize/2)) 01463 { 01464 if(AppBuffHalf == 0) 01465 { 01466 AppBuffHalf = 1; 01467 /* Manage the remaining file size and new address offset: This function 01468 should be coded by user (its prototype is already declared in stm32l476g_eval_audio.h) */ 01469 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01470 } 01471 } 01472 } 01473 } 01474 01475 /** 01476 * @brief Half regular conversion complete callback. 01477 * @param hdfsdm_filter : DFSDM filter handle. 01478 */ 01479 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01480 { 01481 uint32_t index, input_device = 0; 01482 01483 if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC1_FILTER) 01484 { 01485 DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 1; 01486 input_device = INPUT_DEVICE_DIGITAL_MIC1; 01487 } 01488 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC2_FILTER) 01489 { 01490 DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = 1; 01491 input_device = INPUT_DEVICE_DIGITAL_MIC2; 01492 } 01493 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC3_FILTER) 01494 { 01495 input_device = INPUT_DEVICE_DIGITAL_MIC3; 01496 } 01497 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC4_FILTER) 01498 { 01499 input_device = INPUT_DEVICE_DIGITAL_MIC4; 01500 } 01501 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC5_FILTER) 01502 { 01503 input_device = INPUT_DEVICE_DIGITAL_MIC5; 01504 } 01505 01506 if(hAudioIn.MultiBuffMode == 1) 01507 { 01508 BSP_AUDIO_IN_HalfTransfer_CallBackEx(input_device); 01509 } 01510 else 01511 { 01512 if((DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] == 1) && (DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] == 1)) 01513 { 01514 if(AppBuffTrigger >= hAudioIn.RecSize) 01515 AppBuffTrigger = 0; 01516 01517 for(index = 0; index < ScratchSize/2; index++) 01518 { 01519 hAudioIn.pRecBuf[AppBuffTrigger] = (int16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)][index] >> 8), -32760, 32760)); 01520 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (int16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)][index] >> 8), -32760, 32760)); 01521 AppBuffTrigger += 2; 01522 } 01523 DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 0; 01524 } 01525 01526 01527 /* Update Trigger with Remaining Byte before callback if necessary */ 01528 if(AppBuffTrigger >= hAudioIn.RecSize) 01529 { 01530 /* Reset Application Buffer Trigger */ 01531 AppBuffTrigger = 0; 01532 AppBuffHalf = 0; 01533 01534 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01535 BSP_AUDIO_IN_TransferComplete_CallBack(); 01536 } 01537 else if((AppBuffTrigger >= hAudioIn.RecSize/2)) 01538 { 01539 if(AppBuffHalf == 0) 01540 { 01541 AppBuffHalf = 1; 01542 /* Manage the remaining file size and new address offset: This function 01543 should be coded by user */ 01544 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01545 } 01546 } 01547 } 01548 } 01549 01550 /** 01551 * @brief Half reception complete callback. 01552 * @param hi2s : I2S handle. 01553 */ 01554 void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s) 01555 { 01556 /* Manage the remaining file size and new address offset: This function 01557 should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */ 01558 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01559 } 01560 01561 /** 01562 * @brief Reception complete callback. 01563 * @param hi2s : I2S handle. 01564 */ 01565 void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) 01566 { 01567 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01568 BSP_AUDIO_IN_TransferComplete_CallBack(); 01569 } 01570 01571 /** 01572 * @brief Stops audio recording. 01573 * @retval AUDIO_OK if correct communication, else wrong communication 01574 */ 01575 uint8_t BSP_AUDIO_IN_Stop(void) 01576 { 01577 AppBuffTrigger = 0; 01578 AppBuffHalf = 0; 01579 01580 if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 01581 { 01582 /* Call the Media layer stop function */ 01583 if(HAL_OK != HAL_I2S_DMAStop(&haudio_i2s)) 01584 { 01585 return AUDIO_ERROR; 01586 } 01587 /* Call Audio Codec Stop function */ 01588 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, CODEC_PDWN_HW) != 0) 01589 { 01590 return AUDIO_ERROR; 01591 } 01592 /* Wait at least 100us */ 01593 HAL_Delay(1); 01594 } 01595 else /* InputDevice = Digital Mic */ 01596 { 01597 /* Call the Media layer stop function for MIC1 channel */ 01598 if(AUDIO_OK != BSP_AUDIO_IN_PauseEx(INPUT_DEVICE_DIGITAL_MIC1)) 01599 { 01600 return AUDIO_ERROR; 01601 } 01602 01603 /* Call the Media layer stop function for MIC2 channel */ 01604 if(AUDIO_OK != BSP_AUDIO_IN_PauseEx(INPUT_DEVICE_DIGITAL_MIC2)) 01605 { 01606 return AUDIO_ERROR; 01607 } 01608 } 01609 01610 /* Return AUDIO_OK when all operations are correctly done */ 01611 return AUDIO_OK; 01612 } 01613 01614 /** 01615 * @brief Stops audio recording. 01616 * @param InputDevice: Microphone to be stopped. Can be INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5. 01617 * @retval AUDIO_OK if correct communication, else wrong communication 01618 */ 01619 uint8_t BSP_AUDIO_IN_StopEx(uint32_t InputDevice) 01620 { 01621 if((InputDevice < INPUT_DEVICE_DIGITAL_MIC1) || (InputDevice > INPUT_DEVICE_DIGITAL_MIC5)) 01622 { 01623 return AUDIO_ERROR; 01624 } 01625 else 01626 { 01627 BSP_AUDIO_IN_PauseEx(InputDevice); 01628 } 01629 01630 /* Return AUDIO_OK when all operations are correctly done */ 01631 return AUDIO_OK; 01632 } 01633 01634 /** 01635 * @brief Pauses the audio file stream. 01636 * @retval AUDIO_OK if correct communication, else wrong communication 01637 */ 01638 uint8_t BSP_AUDIO_IN_Pause(void) 01639 { 01640 if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 01641 { 01642 return AUDIO_ERROR; 01643 } 01644 else 01645 { 01646 /* Call the Media layer stop function */ 01647 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)])) 01648 { 01649 return AUDIO_ERROR; 01650 } 01651 01652 /* Call the Media layer stop function */ 01653 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)])) 01654 { 01655 return AUDIO_ERROR; 01656 } 01657 } 01658 /* Return AUDIO_OK when all operations are correctly done */ 01659 return AUDIO_OK; 01660 } 01661 01662 /** 01663 * @brief Pauses the audio file stream. 01664 * @param InputDevice: Microphone to be paused. Can be INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5. 01665 * @retval AUDIO_OK if correct communication, else wrong communication 01666 */ 01667 uint8_t BSP_AUDIO_IN_PauseEx(uint32_t InputDevice) 01668 { 01669 if((InputDevice < INPUT_DEVICE_DIGITAL_MIC1) || (InputDevice > INPUT_DEVICE_DIGITAL_MIC5)) 01670 { 01671 return AUDIO_ERROR; 01672 } 01673 else 01674 { 01675 /* Call the Media layer stop function */ 01676 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInDfsdmFilter[POS_VAL(InputDevice)])) 01677 { 01678 return AUDIO_ERROR; 01679 } 01680 } 01681 /* Return AUDIO_OK when all operations are correctly done */ 01682 return AUDIO_OK; 01683 } 01684 01685 /** 01686 * @brief Resumes the audio file stream. 01687 * @retval AUDIO_OK if correct communication, else wrong communication 01688 */ 01689 uint8_t BSP_AUDIO_IN_Resume(void) 01690 { 01691 if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 01692 { 01693 return AUDIO_ERROR; 01694 } 01695 else 01696 { 01697 /* Call the Media layer start function for MIC2 channel */ 01698 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], ScratchSize)) 01699 { 01700 return AUDIO_ERROR; 01701 } 01702 01703 /* Call the Media layer start function for MIC1 channel */ 01704 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], ScratchSize)) 01705 { 01706 return AUDIO_ERROR; 01707 } 01708 } 01709 /* Return AUDIO_OK when all operations are correctly done */ 01710 return AUDIO_OK; 01711 } 01712 01713 /** 01714 * @brief Resumes the audio file stream. 01715 * @param pBuf: Main buffer pointer for the recorded data storing 01716 * @param InputDevice: Microphone to be paused. Can be INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5. 01717 * @retval AUDIO_OK if correct communication, else wrong communication 01718 */ 01719 uint8_t BSP_AUDIO_IN_ResumeEx(uint32_t *pBuf, uint32_t InputDevice) 01720 { 01721 if((InputDevice < INPUT_DEVICE_DIGITAL_MIC1) || (InputDevice > INPUT_DEVICE_DIGITAL_MIC5)) 01722 { 01723 return AUDIO_ERROR; 01724 } 01725 else 01726 { 01727 /* Call the Media layer stop function */ 01728 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(InputDevice)], (int32_t*)pBuf[MicBuff[POS_VAL(InputDevice)]], hAudioIn.RecSize)) 01729 { 01730 return AUDIO_ERROR; 01731 } 01732 } 01733 /* Return AUDIO_OK when all operations are correctly done */ 01734 return AUDIO_OK; 01735 } 01736 01737 /** 01738 * @brief Controls the audio in volume level. 01739 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 01740 * Mute and 100 for Max volume level). 01741 * @retval AUDIO_OK if correct communication, else wrong communication 01742 */ 01743 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume) 01744 { 01745 /* Set the Global variable AudioInVolume */ 01746 AudioInVolume = Volume; 01747 01748 /* Return AUDIO_OK when all operations are correctly done */ 01749 return AUDIO_OK; 01750 } 01751 01752 /** 01753 * @brief User callback when record buffer is filled. 01754 */ 01755 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void) 01756 { 01757 /* This function should be implemented by the user application. 01758 It is called into this driver when the current buffer is filled 01759 to prepare the next buffer pointer and its size. */ 01760 } 01761 01762 /** 01763 * @brief Manages the DMA Half Transfer complete event. 01764 */ 01765 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 01766 { 01767 /* This function should be implemented by the user application. 01768 It is called into this driver when the current buffer is filled 01769 to prepare the next buffer pointer and its size. */ 01770 } 01771 01772 /** 01773 * @brief User callback when record buffer is filled. 01774 * @param InputDevice: INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5. 01775 */ 01776 __weak void BSP_AUDIO_IN_TransferComplete_CallBackEx(uint32_t InputDevice) 01777 { 01778 /* This function should be implemented by the user application. 01779 It is called into this driver when the current buffer is filled 01780 to prepare the next buffer pointer and its size. */ 01781 } 01782 01783 /** 01784 * @brief User callback when record buffer is filled. 01785 * @param InputDevice: INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5. 01786 */ 01787 __weak void BSP_AUDIO_IN_HalfTransfer_CallBackEx(uint32_t InputDevice) 01788 { 01789 /* This function should be implemented by the user application. 01790 It is called into this driver when the current buffer is filled 01791 to prepare the next buffer pointer and its size. */ 01792 } 01793 01794 /** 01795 * @brief Audio IN Error callback function. 01796 */ 01797 __weak void BSP_AUDIO_IN_Error_Callback(void) 01798 { 01799 /* This function is called when an Interrupt due to transfer error on or peripheral 01800 error occurs. */ 01801 } 01802 01803 /** 01804 * @} 01805 */ 01806 01807 /******************************************************************************* 01808 Static Functions 01809 *******************************************************************************/ 01810 01811 /** 01812 * @brief De-initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01813 * @retval AUDIO_OK if correct communication, else wrong communication 01814 */ 01815 static uint8_t DFSDMx_DeInit(void) 01816 { 01817 for(uint32_t i = 0; i < DFSDM_MIC_NUMBER; i++) 01818 { 01819 if(hAudioInDfsdmFilter[i].Instance != NULL) 01820 { 01821 if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInDfsdmFilter[i])) 01822 { 01823 return AUDIO_ERROR; 01824 } 01825 hAudioInDfsdmFilter[i].Instance = NULL; 01826 } 01827 if(hAudioInDfsdmChannel[i].Instance != NULL) 01828 { 01829 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInDfsdmChannel[i])) 01830 { 01831 return AUDIO_ERROR; 01832 } 01833 hAudioInDfsdmChannel[i].Instance = NULL; 01834 } 01835 } 01836 return AUDIO_OK; 01837 } 01838 01839 /** 01840 * @brief Initializes the DFSDM channel MSP. 01841 */ 01842 static void DFSDMx_ChannelMspInit(void) 01843 { 01844 GPIO_InitTypeDef GPIO_InitStruct; 01845 01846 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 01847 GPIO_InitStruct.Pull = GPIO_NOPULL; 01848 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; 01849 01850 if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 01851 { 01852 /* Enable DFSDM clock */ 01853 AUDIO_DFSDMx_MIC1_CLK_ENABLE(); 01854 /* Enable GPIO clock */ 01855 AUDIO_DFSDMx_MIC1_CKOUT_DMIC_GPIO_CLK_ENABLE(); 01856 01857 /* DFSDM MIC1 pins configuration: DFSDM_CKOUT, DMIC_DATIN pins -------------*/ 01858 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC1_CKOUT_PIN; 01859 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC1_CKOUT_DMIC_AF; 01860 HAL_GPIO_Init(AUDIO_DFSDMx_MIC1_CKOUT_DMIC_GPIO_PORT, &GPIO_InitStruct); 01861 01862 AUDIO_DFSDMx_MIC1_DMIC_GPIO_CLK_ENABLE(); 01863 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC1_DMIC_PIN; 01864 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC1_DMIC_AF; 01865 HAL_GPIO_Init(AUDIO_DFSDMx_MIC1_DMIC_GPIO_PORT, &GPIO_InitStruct); 01866 } 01867 01868 if(hAudioIn.InputDevice > INPUT_DEVICE_DIGITAL_MIC1) 01869 { 01870 /* Enable DFSDM clock */ 01871 AUDIO_DFSDMx_MIC2_5_CLK_ENABLE(); 01872 /* Enable GPIO clock */ 01873 AUDIO_DFSDMx_MIC2_5_CKOUT_DMIC_GPIO_CLK_ENABLE(); 01874 01875 /* DFSDM MIC2 pins configuration: DFSDM_CKOUT, DMIC_DATIN pins -------------*/ 01876 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC2_5_CKOUT_PIN; 01877 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC2_5_CKOUT_DMIC_AF; 01878 HAL_GPIO_Init(AUDIO_DFSDMx_MIC2_5_CKOUT_DMIC_GPIO_PORT, &GPIO_InitStruct); 01879 01880 if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) ||\ 01881 ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC3) == INPUT_DEVICE_DIGITAL_MIC3)) 01882 { 01883 AUDIO_DFSDMx_MIC23_DMIC_GPIO_CLK_ENABLE(); 01884 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC23_DMIC_PIN; 01885 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC23_DMIC_AF; 01886 HAL_GPIO_Init(AUDIO_DFSDMx_MIC23_DMIC_GPIO_PORT, &GPIO_InitStruct); 01887 } 01888 01889 if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC4) == INPUT_DEVICE_DIGITAL_MIC4) ||\ 01890 ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC5) == INPUT_DEVICE_DIGITAL_MIC5)) 01891 { 01892 01893 AUDIO_DFSDMx_MIC45_DMIC_GPIO_CLK_ENABLE(); 01894 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC45_DMIC_PIN; 01895 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC45_DMIC_AF; 01896 HAL_GPIO_Init(AUDIO_DFSDMx_MIC45_DMIC_GPIO_PORT, &GPIO_InitStruct); 01897 } 01898 } 01899 } 01900 01901 /** 01902 * @brief DeInitializes the DFSDM channel MSP. 01903 */ 01904 static void DFSDMx_ChannelMspDeInit(void) 01905 { 01906 GPIO_InitTypeDef GPIO_InitStruct; 01907 01908 if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 01909 { 01910 /* DFSDM MIC1 pins configuration: DFSDM_CKOUT, DMIC_DATIN pins -------------*/ 01911 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC1_CKOUT_PIN; 01912 HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC1_CKOUT_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 01913 01914 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC1_DMIC_PIN; 01915 HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC1_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 01916 } 01917 01918 if(hAudioIn.InputDevice > INPUT_DEVICE_DIGITAL_MIC1) 01919 { 01920 /* DFSDM MIC2, MIC3, MIC4 and MIC5 pins configuration: DFSDM_CKOUT pin -----*/ 01921 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC2_5_CKOUT_PIN; 01922 HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC2_5_CKOUT_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 01923 01924 if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) ||\ 01925 ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC3) == INPUT_DEVICE_DIGITAL_MIC3)) 01926 { 01927 /* DFSDM MIC2, MIC3 pins configuration: DMIC_DATIN pin -----*/ 01928 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC23_DMIC_PIN; 01929 HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC23_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 01930 } 01931 01932 if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC4) == INPUT_DEVICE_DIGITAL_MIC4) ||\ 01933 ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC5) == INPUT_DEVICE_DIGITAL_MIC5)) 01934 { 01935 /* DFSDM MIC4, MIC5 pins configuration: DMIC_DATIN pin -----*/ 01936 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC45_DMIC_PIN; 01937 HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC45_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 01938 } 01939 } 01940 } 01941 01942 /** 01943 * @brief Initializes the DFSDM filter MSP. 01944 */ 01945 static void DFSDMx_FilterMspInit(void) 01946 { 01947 uint32_t i = 0, mic_num = 0, mic_init[DFSDM_MIC_NUMBER] = {0}; 01948 IRQn_Type AUDIO_DFSDM_DMAx_MIC_IRQHandler[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_DMAx_MIC1_IRQ, AUDIO_DFSDMx_DMAx_MIC2_IRQ, AUDIO_DFSDMx_DMAx_MIC3_IRQ, AUDIO_DFSDMx_DMAx_MIC4_IRQ, AUDIO_DFSDMx_DMAx_MIC5_IRQ}; 01949 DMA_Stream_TypeDef* AUDIO_DFSDMx_DMAx_MIC_STREAM[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_DMAx_MIC1_STREAM, AUDIO_DFSDMx_DMAx_MIC2_STREAM, AUDIO_DFSDMx_DMAx_MIC3_STREAM, AUDIO_DFSDMx_DMAx_MIC4_STREAM, AUDIO_DFSDMx_DMAx_MIC5_STREAM}; 01950 uint32_t AUDIO_DFSDMx_DMAx_MIC_CHANNEL[DFSDM_MIC_NUMBER] = {AUDIO_DFSDMx_DMAx_MIC1_CHANNEL, AUDIO_DFSDMx_DMAx_MIC2_CHANNEL, AUDIO_DFSDMx_DMAx_MIC3_CHANNEL, AUDIO_DFSDMx_DMAx_MIC4_CHANNEL, AUDIO_DFSDMx_DMAx_MIC5_CHANNEL}; 01951 01952 /* Enable the DMA clock */ 01953 AUDIO_DFSDMx_DMAx_CLK_ENABLE(); 01954 01955 for(i = 0; i < hAudioIn.ChannelNbr; i++) 01956 { 01957 if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] != 1)) 01958 { 01959 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC1); 01960 mic_init[mic_num] = 1; 01961 } 01962 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] != 1)) 01963 { 01964 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC2); 01965 mic_init[mic_num] = 1; 01966 } 01967 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC3) == INPUT_DEVICE_DIGITAL_MIC3) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)] != 1)) 01968 { 01969 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC3); 01970 mic_init[mic_num] = 1; 01971 } 01972 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC4) == INPUT_DEVICE_DIGITAL_MIC4) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)] != 1)) 01973 { 01974 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC4); 01975 mic_init[mic_num] = 1; 01976 } 01977 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC5) == INPUT_DEVICE_DIGITAL_MIC5) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)] != 1)) 01978 { 01979 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC5); 01980 mic_init[mic_num] = 1; 01981 } 01982 01983 /* Configure the hDmaDfsdm[i] handle parameters */ 01984 hDmaDfsdm[mic_num].Init.Channel = AUDIO_DFSDMx_DMAx_MIC_CHANNEL[mic_num]; 01985 hDmaDfsdm[mic_num].Instance = AUDIO_DFSDMx_DMAx_MIC_STREAM[mic_num]; 01986 hDmaDfsdm[mic_num].Init.Direction = DMA_PERIPH_TO_MEMORY; 01987 hDmaDfsdm[mic_num].Init.PeriphInc = DMA_PINC_DISABLE; 01988 hDmaDfsdm[mic_num].Init.MemInc = DMA_MINC_ENABLE; 01989 hDmaDfsdm[mic_num].Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE; 01990 hDmaDfsdm[mic_num].Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE; 01991 hDmaDfsdm[mic_num].Init.Mode = DMA_CIRCULAR; 01992 hDmaDfsdm[mic_num].Init.Priority = DMA_PRIORITY_HIGH; 01993 hDmaDfsdm[mic_num].Init.FIFOMode = DMA_FIFOMODE_DISABLE; 01994 hDmaDfsdm[mic_num].Init.MemBurst = DMA_MBURST_SINGLE; 01995 hDmaDfsdm[mic_num].Init.PeriphBurst = DMA_PBURST_SINGLE; 01996 hDmaDfsdm[mic_num].State = HAL_DMA_STATE_RESET; 01997 01998 /* Associate the DMA handle */ 01999 __HAL_LINKDMA(&hAudioInDfsdmFilter[mic_num], hdmaReg, hDmaDfsdm[mic_num]); 02000 02001 /* Reset DMA handle state */ 02002 __HAL_DMA_RESET_HANDLE_STATE(&hDmaDfsdm[mic_num]); 02003 02004 /* Configure the DMA Channel */ 02005 HAL_DMA_Init(&hDmaDfsdm[mic_num]); 02006 02007 /* DMA IRQ Channel configuration */ 02008 HAL_NVIC_SetPriority(AUDIO_DFSDM_DMAx_MIC_IRQHandler[mic_num], AUDIO_IN_IRQ_PREPRIO, 0); 02009 HAL_NVIC_EnableIRQ(AUDIO_DFSDM_DMAx_MIC_IRQHandler[mic_num]); 02010 } 02011 } 02012 02013 /** 02014 * @brief DeInitializes the DFSDM filter MSP. 02015 */ 02016 static void DFSDMx_FilterMspDeInit(void) 02017 { 02018 /* Configure the DMA Channel */ 02019 for(uint32_t i = 0; i < DFSDM_MIC_NUMBER; i++) 02020 { 02021 if(hDmaDfsdm[i].Instance != NULL) 02022 { 02023 HAL_DMA_DeInit(&hDmaDfsdm[i]); 02024 } 02025 } 02026 } 02027 02028 /** 02029 * @brief Initializes the Audio Codec audio interface (I2S) 02030 * @note This function assumes that the I2S input clock 02031 * is already configured and ready to be used. 02032 * @param AudioFreq: Audio frequency to be configured for the I2S peripheral. 02033 */ 02034 static void I2Sx_In_Init(uint32_t AudioFreq) 02035 { 02036 /* Initialize the hAudioInI2s and haudio_in_i2sext Instance parameters */ 02037 haudio_i2s.Instance = AUDIO_IN_I2Sx; 02038 haudio_in_i2sext.Instance = I2S3ext; 02039 02040 /* Disable I2S block */ 02041 __HAL_I2S_DISABLE(&haudio_i2s); 02042 __HAL_I2S_DISABLE(&haudio_in_i2sext); 02043 02044 /* I2S peripheral configuration */ 02045 haudio_i2s.Init.AudioFreq = AudioFreq; 02046 haudio_i2s.Init.ClockSource = I2S_CLOCK_PLL; 02047 haudio_i2s.Init.CPOL = I2S_CPOL_LOW; 02048 haudio_i2s.Init.DataFormat = I2S_DATAFORMAT_16B; 02049 haudio_i2s.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE; 02050 haudio_i2s.Init.Mode = I2S_MODE_MASTER_TX; 02051 haudio_i2s.Init.Standard = I2S_STANDARD_PHILIPS; 02052 haudio_i2s.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_ENABLE; 02053 /* Init the I2S */ 02054 HAL_I2S_Init(&haudio_i2s); 02055 02056 /* I2Sext peripheral configuration */ 02057 haudio_in_i2sext.Init.AudioFreq = AudioFreq; 02058 haudio_in_i2sext.Init.ClockSource = I2S_CLOCK_PLL; 02059 haudio_in_i2sext.Init.CPOL = I2S_CPOL_HIGH; 02060 haudio_in_i2sext.Init.DataFormat = I2S_DATAFORMAT_16B; 02061 haudio_in_i2sext.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE; 02062 haudio_in_i2sext.Init.Mode = I2S_MODE_SLAVE_RX; 02063 haudio_in_i2sext.Init.Standard = I2S_STANDARD_PHILIPS; 02064 02065 /* Init the I2Sext */ 02066 HAL_I2S_Init(&haudio_in_i2sext); 02067 02068 /* Enable I2S block */ 02069 __HAL_I2S_ENABLE(&haudio_i2s); 02070 __HAL_I2S_ENABLE(&haudio_in_i2sext); 02071 } 02072 02073 /** 02074 * @brief Deinitializes the Audio Codec audio interface (I2S). 02075 */ 02076 static void I2Sx_In_DeInit(void) 02077 { 02078 /* Initialize the hAudioInI2s Instance parameter */ 02079 haudio_i2s.Instance = AUDIO_IN_I2Sx; 02080 02081 /* Disable I2S block */ 02082 __HAL_I2S_DISABLE(&haudio_i2s); 02083 02084 /* DeInit the I2S */ 02085 HAL_I2S_DeInit(&haudio_i2s); 02086 02087 /* Initialize the hAudioInI2s Instance parameter */ 02088 haudio_in_i2sext.Instance = I2S3ext; 02089 02090 /* Disable I2S block */ 02091 __HAL_I2S_DISABLE(&haudio_in_i2sext); 02092 02093 /* DeInit the I2S */ 02094 HAL_I2S_DeInit(&haudio_in_i2sext); 02095 } 02096 02097 /** 02098 * @brief This function handles DFSDM MIC1 DMA interrupt request. 02099 * @param None 02100 * @retval None 02101 */ 02102 void AUDIO_DFSDM_DMAx_MIC1_IRQHandler(void) 02103 { 02104 HAL_DMA_IRQHandler(hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)].hdmaReg); 02105 02106 } 02107 02108 /** 02109 * @brief This function handles DFSDM MIC2 DMA interrupt request. 02110 * @param None 02111 * @retval None 02112 */ 02113 void AUDIO_DFSDM_DMAx_MIC2_IRQHandler(void) 02114 { 02115 HAL_DMA_IRQHandler(hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)].hdmaReg); 02116 } 02117 02118 /** 02119 * @brief This function handles I2S DMA interrupt request. 02120 * @param None 02121 * @retval None 02122 */ 02123 void AUDIO_OUT_I2Sx_DMAx_IRQHandler(void) 02124 { 02125 HAL_DMA_IRQHandler(haudio_i2s.hdmatx); 02126 } 02127 02128 /** 02129 * @} 02130 */ 02131 02132 /** 02133 * @} 02134 */ 02135 02136 /** 02137 * @} 02138 */ 02139 02140 /** 02141 * @} 02142 */ 02143 02144 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Thu Jul 14 2022 12:00:03 by
