Contains the BSP driver for the DISCO_F413ZH board.
Dependents: DISCO_F413ZH-LCD-demo DISCO_F413ZH-touch-screen-demo DISCO_F413ZH-SD-demo DISCO_F413ZH-PSRAM-demo ... more
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 HAL_DFSDM_FilterDeInit(&hAudioInDfsdmFilter[mic_num]); 00957 /* MIC filters initialization */ 00958 __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInDfsdmFilter[mic_num]); 00959 hAudioInDfsdmFilter[mic_num].Instance = FilterInstnace[mic_num]; 00960 hAudioInDfsdmFilter[mic_num].Init.RegularParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 00961 hAudioInDfsdmFilter[mic_num].Init.RegularParam.FastMode = ENABLE; 00962 hAudioInDfsdmFilter[mic_num].Init.RegularParam.DmaMode = ENABLE; 00963 hAudioInDfsdmFilter[mic_num].Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 00964 hAudioInDfsdmFilter[mic_num].Init.InjectedParam.ScanMode = DISABLE; 00965 hAudioInDfsdmFilter[mic_num].Init.InjectedParam.DmaMode = DISABLE; 00966 hAudioInDfsdmFilter[mic_num].Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO; 00967 hAudioInDfsdmFilter[mic_num].Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES; 00968 hAudioInDfsdmFilter[mic_num].Init.FilterParam.SincOrder = DFSDM_FILTER_ORDER(hAudioIn.Frequency); 00969 hAudioInDfsdmFilter[mic_num].Init.FilterParam.Oversampling = DFSDM_OVER_SAMPLING(hAudioIn.Frequency); 00970 hAudioInDfsdmFilter[mic_num].Init.FilterParam.IntOversampling = 1; 00971 00972 if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInDfsdmFilter[mic_num])) 00973 { 00974 return AUDIO_ERROR; 00975 } 00976 00977 HAL_DFSDM_ChannelDeInit(&hAudioInDfsdmChannel[mic_num]); 00978 /* MIC channels initialization */ 00979 __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInDfsdmChannel[mic_num]); 00980 hAudioInDfsdmChannel[mic_num].Init.OutputClock.Activation = ENABLE; 00981 hAudioInDfsdmChannel[mic_num].Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 00982 hAudioInDfsdmChannel[mic_num].Init.OutputClock.Divider = DFSDM_CLOCK_DIVIDER(hAudioIn.Frequency); 00983 hAudioInDfsdmChannel[mic_num].Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 00984 hAudioInDfsdmChannel[mic_num].Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 00985 hAudioInDfsdmChannel[mic_num].Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 00986 hAudioInDfsdmChannel[mic_num].Init.Awd.FilterOrder = DFSDM_CHANNEL_SINC1_ORDER; 00987 hAudioInDfsdmChannel[mic_num].Init.Awd.Oversampling = 10; 00988 hAudioInDfsdmChannel[mic_num].Init.Offset = 0; 00989 hAudioInDfsdmChannel[mic_num].Init.RightBitShift = DFSDM_MIC_BIT_SHIFT(hAudioIn.Frequency); 00990 hAudioInDfsdmChannel[mic_num].Instance = ChannelInstnace[mic_num]; 00991 hAudioInDfsdmChannel[mic_num].Init.Input.Pins = DigitalMicPins[mic_num]; 00992 hAudioInDfsdmChannel[mic_num].Init.SerialInterface.Type = DigitalMicType[mic_num]; 00993 00994 if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInDfsdmChannel[mic_num])) 00995 { 00996 return AUDIO_ERROR; 00997 } 00998 00999 filter_ch = Channel4Filter[mic_num]; 01000 /* Configure injected channel */ 01001 if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInDfsdmFilter[mic_num], filter_ch, DFSDM_CONTINUOUS_CONV_ON)) 01002 { 01003 return AUDIO_ERROR; 01004 } 01005 } 01006 return AUDIO_OK; 01007 } 01008 01009 /** 01010 * @brief Initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01011 * @param InputDevice: The microphone to be configured. Can be INPUT_DEVICE_DIGITAL_MIC1..INPUT_DEVICE_DIGITAL_MIC5 01012 * @param Params : pointer on additional configuration parameters, can be NULL. 01013 * @retval AUDIO_OK if correct communication, else wrong communication 01014 */ 01015 __weak uint8_t BSP_AUDIO_IN_ConfigDigitalMic(uint32_t InputDevice, void *Params) 01016 { 01017 /* Prevent unused argument(s) compilation warning */ 01018 UNUSED(Params); 01019 01020 /* Default configuration of DFSDM filters and channels */ 01021 return(BSP_AUDIO_IN_ConfigMicDefault(InputDevice)); 01022 /* Note: This function can be called at application level and default configuration 01023 can be ovewritten to fit user's need */ 01024 } 01025 01026 /** 01027 * @brief Allocate channel buffer scratch 01028 * @param pScratch : pointer to scratch tables. 01029 * @param size: size of scratch buffer 01030 */ 01031 uint8_t BSP_AUDIO_IN_AllocScratch (int32_t *pScratch, uint32_t size) 01032 { 01033 uint32_t idx; 01034 01035 ScratchSize = size / DEFAULT_AUDIO_IN_CHANNEL_NBR; 01036 01037 /* copy scratch pointers */ 01038 for (idx = 0; idx < DEFAULT_AUDIO_IN_CHANNEL_NBR ; idx++) 01039 { 01040 pScratchBuff[idx] = (int32_t *)(pScratch + idx * ScratchSize); 01041 } 01042 /* Return AUDIO_OK */ 01043 return AUDIO_OK; 01044 } 01045 01046 /** 01047 * @brief Starts audio recording. 01048 * @param pBuf: Main buffer pointer for the recorded data storing 01049 * @param size: Current size of the recorded buffer 01050 * @retval AUDIO_OK if correct communication, else wrong communication 01051 */ 01052 uint8_t BSP_AUDIO_IN_Record(uint16_t *pBuf, uint32_t size) 01053 { 01054 hAudioIn.pRecBuf = pBuf; 01055 hAudioIn.RecSize = size; 01056 /* Reset Application Buffer Trigger */ 01057 AppBuffTrigger = 0; 01058 AppBuffHalf = 0; 01059 01060 if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC) 01061 { 01062 /* Call the Media layer start function for MIC1 channel */ 01063 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], ScratchSize)) 01064 { 01065 return AUDIO_ERROR; 01066 } 01067 01068 /* Call the Media layer start function for MIC2 channel */ 01069 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], ScratchSize)) 01070 { 01071 return AUDIO_ERROR; 01072 } 01073 } 01074 else 01075 { 01076 /* Start the process to receive the DMA */ 01077 if (HAL_OK != HAL_I2SEx_TransmitReceive_DMA(&haudio_i2s, pBuf, pBuf, size)) 01078 { 01079 return AUDIO_ERROR; 01080 } 01081 } 01082 /* Return AUDIO_OK when all operations are correctly done */ 01083 return AUDIO_OK; 01084 } 01085 01086 /** 01087 * @brief Starts audio recording. 01088 * @param pBuf: Main buffer pointer for the recorded data storing 01089 * @param size: Current size of the recorded buffer 01090 * @retval AUDIO_OK if correct communication, else wrong communication 01091 */ 01092 uint8_t BSP_AUDIO_IN_RecordEx(uint32_t *pBuf, uint32_t size) 01093 { 01094 uint8_t ret = AUDIO_ERROR; 01095 hAudioIn.RecSize = size; 01096 uint32_t i = 0; 01097 uint32_t mic_init[DFSDM_MIC_NUMBER] = {0}; 01098 if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 01099 { 01100 return ret; 01101 } 01102 else 01103 { 01104 hAudioIn.MultiBuffMode = 1; 01105 for(i = 0; i < hAudioIn.ChannelNbr; i++) 01106 { 01107 if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] != 1)) 01108 { 01109 /* Call the Media layer start function for MIC1 channel 1 */ 01110 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], (int32_t*)pBuf[i], size)) 01111 { 01112 return AUDIO_ERROR; 01113 } 01114 MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = i; 01115 mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 1; 01116 } 01117 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] != 1)) 01118 { 01119 /* Call the Media layer start function for MIC2 channel 1 */ 01120 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], (int32_t*)pBuf[i], size)) 01121 { 01122 return AUDIO_ERROR; 01123 } 01124 MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = i; 01125 mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = 1; 01126 } 01127 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC3) == INPUT_DEVICE_DIGITAL_MIC3) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)] != 1)) 01128 { 01129 /* Call the Media layer start function for MIC3 channel 0 */ 01130 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)], (int32_t*)pBuf[i], size)) 01131 { 01132 return AUDIO_ERROR; 01133 } 01134 MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)] = i; 01135 mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)] = 1; 01136 } 01137 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC4) == INPUT_DEVICE_DIGITAL_MIC4) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)] != 1)) 01138 { 01139 /* Call the Media layer start function for MIC4 channel 7 */ 01140 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)], (int32_t*)pBuf[i], size)) 01141 { 01142 return AUDIO_ERROR; 01143 } 01144 MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)] = i; 01145 mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)] = 1; 01146 } 01147 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC5) == INPUT_DEVICE_DIGITAL_MIC5) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)] != 1)) 01148 { 01149 /* Call the Media layer start function for MIC5 channel 6 */ 01150 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)], (int32_t*)pBuf[i], size)) 01151 { 01152 return AUDIO_ERROR; 01153 } 01154 MicBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)] = i; 01155 mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)] = 1; 01156 } 01157 } 01158 } 01159 /* Return AUDIO_OK when all operations are correctly done */ 01160 return AUDIO_OK; 01161 } 01162 01163 /** 01164 * @brief Initializes the I2S MSP. 01165 */ 01166 static void I2Sx_In_MspInit(void) 01167 { 01168 static DMA_HandleTypeDef hdma_i2s_rx; 01169 GPIO_InitTypeDef gpio_init_structure; 01170 01171 /* Enable I2S clock */ 01172 AUDIO_IN_I2Sx_CLK_ENABLE(); 01173 01174 /* Enable MCK GPIO clock, needed by the codec */ 01175 AUDIO_OUT_I2Sx_MCK_GPIO_CLK_ENABLE(); 01176 01177 /* CODEC_I2S pins configuration: MCK pins */ 01178 gpio_init_structure.Pin = AUDIO_OUT_I2Sx_MCK_PIN; 01179 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 01180 gpio_init_structure.Pull = GPIO_NOPULL; 01181 gpio_init_structure.Speed = GPIO_SPEED_FAST; 01182 gpio_init_structure.Alternate = AUDIO_OUT_I2Sx_MCK_AF; 01183 HAL_GPIO_Init(AUDIO_OUT_I2Sx_MCK_GPIO_PORT, &gpio_init_structure); 01184 01185 /* Enable SD GPIO clock */ 01186 AUDIO_IN_I2Sx_EXT_SD_GPIO_CLK_ENABLE(); 01187 /* CODEC_I2S pin configuration: SD pin */ 01188 gpio_init_structure.Pin = AUDIO_IN_I2Sx_EXT_SD_PIN; 01189 gpio_init_structure.Alternate = AUDIO_IN_I2Sx_EXT_SD_AF; 01190 HAL_GPIO_Init(AUDIO_IN_I2Sx_EXT_SD_GPIO_PORT, &gpio_init_structure); 01191 01192 /* Enable the DMA clock */ 01193 AUDIO_IN_I2Sx_DMAx_CLK_ENABLE(); 01194 01195 if(haudio_i2s.Instance == AUDIO_IN_I2Sx) 01196 { 01197 /* Configure the hdma_i2s_rx handle parameters */ 01198 hdma_i2s_rx.Init.Channel = AUDIO_IN_I2Sx_DMAx_CHANNEL; 01199 hdma_i2s_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; 01200 hdma_i2s_rx.Init.PeriphInc = DMA_PINC_DISABLE; 01201 hdma_i2s_rx.Init.MemInc = DMA_MINC_ENABLE; 01202 hdma_i2s_rx.Init.PeriphDataAlignment = AUDIO_IN_I2Sx_DMAx_PERIPH_DATA_SIZE; 01203 hdma_i2s_rx.Init.MemDataAlignment = AUDIO_IN_I2Sx_DMAx_MEM_DATA_SIZE; 01204 hdma_i2s_rx.Init.Mode = DMA_CIRCULAR; 01205 hdma_i2s_rx.Init.Priority = DMA_PRIORITY_HIGH; 01206 hdma_i2s_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 01207 hdma_i2s_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 01208 hdma_i2s_rx.Init.MemBurst = DMA_MBURST_SINGLE; 01209 hdma_i2s_rx.Init.PeriphBurst = DMA_MBURST_SINGLE; 01210 01211 hdma_i2s_rx.Instance = AUDIO_IN_I2Sx_DMAx_STREAM; 01212 01213 /* Associate the DMA handle */ 01214 __HAL_LINKDMA(&haudio_i2s, hdmarx, hdma_i2s_rx); 01215 01216 /* Deinitialize the Stream for new transfer */ 01217 HAL_DMA_DeInit(&hdma_i2s_rx); 01218 01219 /* Configure the DMA Stream */ 01220 HAL_DMA_Init(&hdma_i2s_rx); 01221 } 01222 01223 /* I2S DMA IRQ Channel configuration */ 01224 HAL_NVIC_SetPriority(AUDIO_IN_I2Sx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 01225 HAL_NVIC_EnableIRQ(AUDIO_IN_I2Sx_DMAx_IRQ); 01226 } 01227 01228 /** 01229 * @brief De-Initializes the I2S MSP. 01230 */ 01231 static void I2Sx_In_MspDeInit(void) 01232 { 01233 GPIO_InitTypeDef gpio_init_structure; 01234 01235 /* I2S DMA IRQ Channel deactivation */ 01236 HAL_NVIC_DisableIRQ(AUDIO_IN_I2Sx_DMAx_IRQ); 01237 01238 if(haudio_i2s.Instance == AUDIO_IN_I2Sx) 01239 { 01240 /* Deinitialize the DMA stream */ 01241 HAL_DMA_DeInit(haudio_i2s.hdmarx); 01242 } 01243 01244 /* Disable I2S peripheral */ 01245 __HAL_I2S_DISABLE(&haudio_i2s); 01246 01247 /* Deactives CODEC_I2S pins MCK by putting them in input mode */ 01248 gpio_init_structure.Pin = AUDIO_OUT_I2Sx_MCK_PIN; 01249 HAL_GPIO_DeInit(AUDIO_OUT_I2Sx_MCK_GPIO_PORT, gpio_init_structure.Pin); 01250 01251 gpio_init_structure.Pin = AUDIO_IN_I2Sx_EXT_SD_PIN; 01252 HAL_GPIO_DeInit(AUDIO_IN_I2Sx_EXT_SD_GPIO_PORT, gpio_init_structure.Pin); 01253 01254 /* Disable I2S clock */ 01255 AUDIO_IN_I2Sx_CLK_DISABLE(); 01256 } 01257 01258 /** 01259 * @brief Initializes BSP_AUDIO_IN MSP. 01260 * @param Params : pointer on additional configuration parameters, can be NULL. 01261 */ 01262 __weak void BSP_AUDIO_IN_MspInit(void *Params) 01263 { 01264 /* Prevent unused argument(s) compilation warning */ 01265 UNUSED(Params); 01266 01267 if(hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 01268 { 01269 I2Sx_In_MspInit(); 01270 } 01271 else 01272 { 01273 /* MSP channels initialization */ 01274 DFSDMx_ChannelMspInit(); 01275 01276 /* MSP filters initialization */ 01277 DFSDMx_FilterMspInit(); 01278 } 01279 } 01280 01281 /** 01282 * @brief De-Initializes BSP_AUDIO_IN MSP. 01283 * @param Params : pointer on additional configuration parameters, can be NULL. 01284 */ 01285 __weak void BSP_AUDIO_IN_MspDeInit(void *Params) 01286 { 01287 /* Prevent unused argument(s) compilation warning */ 01288 UNUSED(Params); 01289 01290 if(hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 01291 { 01292 I2Sx_In_MspDeInit(); 01293 } 01294 else 01295 { 01296 /* MSP channels initialization */ 01297 DFSDMx_ChannelMspDeInit(); 01298 01299 /* MSP filters initialization */ 01300 DFSDMx_FilterMspDeInit(); 01301 } 01302 } 01303 01304 /** 01305 * @brief Clock Config. 01306 * @param AudioFreq: Audio frequency used to play the audio stream. 01307 * @param Params : pointer on additional configuration parameters, can be NULL. 01308 * @note This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency() 01309 * Being __weak it can be overwritten by the application 01310 * @retval AUDIO_OK if correct communication, else wrong communication 01311 */ 01312 __weak uint8_t BSP_AUDIO_IN_ClockConfig(uint32_t AudioFreq, void *Params) 01313 { 01314 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 01315 01316 /* Prevent unused argument(s) compilation warning */ 01317 UNUSED(Params); 01318 01319 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 01320 01321 /* Set the PLL configuration according to the audio frequency */ 01322 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 01323 { 01324 /* Configure PLLI2S prescalers */ 01325 rcc_ex_clk_init_struct.PeriphClockSelection = (RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_DFSDM | RCC_PERIPHCLK_DFSDM2); 01326 rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S; 01327 rcc_ex_clk_init_struct.Dfsdm1ClockSelection = RCC_DFSDM1CLKSOURCE_APB2; 01328 rcc_ex_clk_init_struct.Dfsdm2ClockSelection = RCC_DFSDM2CLKSOURCE_APB2; 01329 rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC; 01330 rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8; 01331 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 271; 01332 rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 2; 01333 01334 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01335 } 01336 else if(AudioFreq == AUDIO_FREQUENCY_96K) 01337 { 01338 /* I2S clock config */ 01339 rcc_ex_clk_init_struct.PeriphClockSelection = (RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_DFSDM | RCC_PERIPHCLK_DFSDM2); 01340 rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S; 01341 rcc_ex_clk_init_struct.Dfsdm1ClockSelection = RCC_DFSDM1CLKSOURCE_APB2; 01342 rcc_ex_clk_init_struct.Dfsdm2ClockSelection = RCC_DFSDM2CLKSOURCE_APB2; 01343 rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC; 01344 rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8; 01345 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 01346 rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 2; 01347 01348 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01349 } 01350 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_32K, AUDIO_FREQUENCY_48K */ 01351 { 01352 /* I2S clock config 01353 PLLI2S_VCO: VCO_344M 01354 I2S_CLK(first level) = PLLI2S_VCO/PLLI2SR = 344/7 = 49.142 Mhz 01355 I2S_CLK_x = I2S_CLK(first level)/PLLI2SDIVR = 49.142/1 = 49.142 Mhz */ 01356 rcc_ex_clk_init_struct.PeriphClockSelection = (RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_DFSDM | RCC_PERIPHCLK_DFSDM2); 01357 rcc_ex_clk_init_struct.I2sApb1ClockSelection = RCC_I2SAPB1CLKSOURCE_PLLI2S; 01358 rcc_ex_clk_init_struct.DfsdmClockSelection = RCC_DFSDM1CLKSOURCE_APB2|RCC_DFSDM2CLKSOURCE_APB2; 01359 rcc_ex_clk_init_struct.PLLI2SSelection = RCC_PLLI2SCLKSOURCE_PLLSRC; 01360 rcc_ex_clk_init_struct.PLLI2S.PLLI2SM = 8; 01361 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 01362 rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 7; 01363 01364 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01365 } 01366 01367 if(hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC) 01368 { 01369 /* I2S_APB1 selected as DFSDM audio clock source */ 01370 __HAL_RCC_DFSDM1AUDIO_CONFIG(RCC_DFSDM1AUDIOCLKSOURCE_I2SAPB1); 01371 /* I2S_APB1 selected as DFSDM audio clock source */ 01372 __HAL_RCC_DFSDM2AUDIO_CONFIG(RCC_DFSDM2AUDIOCLKSOURCE_I2SAPB1); 01373 } 01374 01375 return AUDIO_OK; 01376 } 01377 01378 /** 01379 * @brief Regular conversion complete callback. 01380 * @note In interrupt mode, user has to read conversion value in this function 01381 using HAL_DFSDM_FilterGetRegularValue. 01382 * @param hdfsdm_filter : DFSDM filter handle. 01383 */ 01384 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01385 { 01386 uint32_t index, input_device = 0; 01387 01388 if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC1_FILTER) 01389 { 01390 DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 1; 01391 input_device = INPUT_DEVICE_DIGITAL_MIC1; 01392 } 01393 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC2_FILTER) 01394 { 01395 DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = 1; 01396 input_device = INPUT_DEVICE_DIGITAL_MIC2; 01397 } 01398 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC3_FILTER) 01399 { 01400 input_device = INPUT_DEVICE_DIGITAL_MIC3; 01401 } 01402 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC4_FILTER) 01403 { 01404 input_device = INPUT_DEVICE_DIGITAL_MIC4; 01405 } 01406 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC5_FILTER) 01407 { 01408 input_device = INPUT_DEVICE_DIGITAL_MIC5; 01409 } 01410 01411 if(hAudioIn.MultiBuffMode == 1) 01412 { 01413 BSP_AUDIO_IN_TransferComplete_CallBackEx(input_device); 01414 } 01415 else 01416 { 01417 if((DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] == 1) && (DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] == 1)) 01418 { 01419 if(AppBuffTrigger >= hAudioIn.RecSize) 01420 AppBuffTrigger = 0; 01421 01422 for(index = (ScratchSize/2) ; index < ScratchSize; index++) 01423 { 01424 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)][index] >> 8), -32760, 32760)); 01425 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)][index] >> 8), -32760, 32760)); 01426 AppBuffTrigger += 2; 01427 } 01428 DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = DmaRecBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 0; 01429 } 01430 01431 /* Update Trigger with Remaining Byte before callback if necessary */ 01432 if(AppBuffTrigger >= hAudioIn.RecSize) 01433 { 01434 /* Reset Application Buffer Trigger */ 01435 AppBuffTrigger = 0; 01436 AppBuffHalf = 0; 01437 01438 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01439 BSP_AUDIO_IN_TransferComplete_CallBack(); 01440 } 01441 else if((AppBuffTrigger >= hAudioIn.RecSize/2)) 01442 { 01443 if(AppBuffHalf == 0) 01444 { 01445 AppBuffHalf = 1; 01446 /* Manage the remaining file size and new address offset: This function 01447 should be coded by user (its prototype is already declared in stm32l476g_eval_audio.h) */ 01448 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01449 } 01450 } 01451 } 01452 } 01453 01454 /** 01455 * @brief Half regular conversion complete callback. 01456 * @param hdfsdm_filter : DFSDM filter handle. 01457 */ 01458 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01459 { 01460 uint32_t index, input_device = 0; 01461 01462 if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC1_FILTER) 01463 { 01464 DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 1; 01465 input_device = INPUT_DEVICE_DIGITAL_MIC1; 01466 } 01467 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC2_FILTER) 01468 { 01469 DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = 1; 01470 input_device = INPUT_DEVICE_DIGITAL_MIC2; 01471 } 01472 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC3_FILTER) 01473 { 01474 input_device = INPUT_DEVICE_DIGITAL_MIC3; 01475 } 01476 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC4_FILTER) 01477 { 01478 input_device = INPUT_DEVICE_DIGITAL_MIC4; 01479 } 01480 else if(hdfsdm_filter->Instance == AUDIO_DFSDMx_MIC5_FILTER) 01481 { 01482 input_device = INPUT_DEVICE_DIGITAL_MIC5; 01483 } 01484 01485 if(hAudioIn.MultiBuffMode == 1) 01486 { 01487 BSP_AUDIO_IN_HalfTransfer_CallBackEx(input_device); 01488 } 01489 else 01490 { 01491 if((DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] == 1) && (DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] == 1)) 01492 { 01493 if(AppBuffTrigger >= hAudioIn.RecSize) 01494 AppBuffTrigger = 0; 01495 01496 for(index = 0; index < ScratchSize/2; index++) 01497 { 01498 hAudioIn.pRecBuf[AppBuffTrigger] = (int16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)][index] >> 8), -32760, 32760)); 01499 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (int16_t)(SaturaLH((pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)][index] >> 8), -32760, 32760)); 01500 AppBuffTrigger += 2; 01501 } 01502 DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] = DmaRecHalfBuffCplt[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] = 0; 01503 } 01504 01505 01506 /* Update Trigger with Remaining Byte before callback if necessary */ 01507 if(AppBuffTrigger >= hAudioIn.RecSize) 01508 { 01509 /* Reset Application Buffer Trigger */ 01510 AppBuffTrigger = 0; 01511 AppBuffHalf = 0; 01512 01513 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01514 BSP_AUDIO_IN_TransferComplete_CallBack(); 01515 } 01516 else if((AppBuffTrigger >= hAudioIn.RecSize/2)) 01517 { 01518 if(AppBuffHalf == 0) 01519 { 01520 AppBuffHalf = 1; 01521 /* Manage the remaining file size and new address offset: This function 01522 should be coded by user */ 01523 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01524 } 01525 } 01526 } 01527 } 01528 01529 /** 01530 * @brief Half reception complete callback. 01531 * @param hi2s : I2S handle. 01532 */ 01533 void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s) 01534 { 01535 /* Manage the remaining file size and new address offset: This function 01536 should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */ 01537 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01538 } 01539 01540 /** 01541 * @brief Reception complete callback. 01542 * @param hi2s : I2S handle. 01543 */ 01544 void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) 01545 { 01546 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01547 BSP_AUDIO_IN_TransferComplete_CallBack(); 01548 } 01549 01550 /** 01551 * @brief Stops audio recording. 01552 * @retval AUDIO_OK if correct communication, else wrong communication 01553 */ 01554 uint8_t BSP_AUDIO_IN_Stop(void) 01555 { 01556 AppBuffTrigger = 0; 01557 AppBuffHalf = 0; 01558 01559 if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 01560 { 01561 /* Call the Media layer stop function */ 01562 if(HAL_OK != HAL_I2S_DMAStop(&haudio_i2s)) 01563 { 01564 return AUDIO_ERROR; 01565 } 01566 /* Call Audio Codec Stop function */ 01567 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, CODEC_PDWN_HW) != 0) 01568 { 01569 return AUDIO_ERROR; 01570 } 01571 /* Wait at least 100us */ 01572 HAL_Delay(1); 01573 } 01574 else /* InputDevice = Digital Mic */ 01575 { 01576 /* Call the Media layer stop function for MIC1 channel */ 01577 if(AUDIO_OK != BSP_AUDIO_IN_PauseEx(INPUT_DEVICE_DIGITAL_MIC1)) 01578 { 01579 return AUDIO_ERROR; 01580 } 01581 01582 /* Call the Media layer stop function for MIC2 channel */ 01583 if(AUDIO_OK != BSP_AUDIO_IN_PauseEx(INPUT_DEVICE_DIGITAL_MIC2)) 01584 { 01585 return AUDIO_ERROR; 01586 } 01587 } 01588 01589 /* Return AUDIO_OK when all operations are correctly done */ 01590 return AUDIO_OK; 01591 } 01592 01593 /** 01594 * @brief Stops audio recording. 01595 * @param InputDevice: Microphone to be stopped. Can be INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5. 01596 * @retval AUDIO_OK if correct communication, else wrong communication 01597 */ 01598 uint8_t BSP_AUDIO_IN_StopEx(uint32_t InputDevice) 01599 { 01600 if((InputDevice < INPUT_DEVICE_DIGITAL_MIC1) || (InputDevice > INPUT_DEVICE_DIGITAL_MIC5)) 01601 { 01602 return AUDIO_ERROR; 01603 } 01604 else 01605 { 01606 BSP_AUDIO_IN_PauseEx(InputDevice); 01607 } 01608 01609 /* Return AUDIO_OK when all operations are correctly done */ 01610 return AUDIO_OK; 01611 } 01612 01613 /** 01614 * @brief Pauses the audio file stream. 01615 * @retval AUDIO_OK if correct communication, else wrong communication 01616 */ 01617 uint8_t BSP_AUDIO_IN_Pause(void) 01618 { 01619 if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 01620 { 01621 return AUDIO_ERROR; 01622 } 01623 else 01624 { 01625 /* Call the Media layer stop function */ 01626 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)])) 01627 { 01628 return AUDIO_ERROR; 01629 } 01630 01631 /* Call the Media layer stop function */ 01632 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)])) 01633 { 01634 return AUDIO_ERROR; 01635 } 01636 } 01637 /* Return AUDIO_OK when all operations are correctly done */ 01638 return AUDIO_OK; 01639 } 01640 01641 /** 01642 * @brief Pauses the audio file stream. 01643 * @param InputDevice: Microphone to be paused. Can be INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5. 01644 * @retval AUDIO_OK if correct communication, else wrong communication 01645 */ 01646 uint8_t BSP_AUDIO_IN_PauseEx(uint32_t InputDevice) 01647 { 01648 if((InputDevice < INPUT_DEVICE_DIGITAL_MIC1) || (InputDevice > INPUT_DEVICE_DIGITAL_MIC5)) 01649 { 01650 return AUDIO_ERROR; 01651 } 01652 else 01653 { 01654 /* Call the Media layer stop function */ 01655 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInDfsdmFilter[POS_VAL(InputDevice)])) 01656 { 01657 return AUDIO_ERROR; 01658 } 01659 } 01660 /* Return AUDIO_OK when all operations are correctly done */ 01661 return AUDIO_OK; 01662 } 01663 01664 /** 01665 * @brief Resumes the audio file stream. 01666 * @retval AUDIO_OK if correct communication, else wrong communication 01667 */ 01668 uint8_t BSP_AUDIO_IN_Resume(void) 01669 { 01670 if (hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC) 01671 { 01672 return AUDIO_ERROR; 01673 } 01674 else 01675 { 01676 /* Call the Media layer start function for MIC2 channel */ 01677 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)], ScratchSize)) 01678 { 01679 return AUDIO_ERROR; 01680 } 01681 01682 /* Call the Media layer start function for MIC1 channel */ 01683 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], pScratchBuff[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)], ScratchSize)) 01684 { 01685 return AUDIO_ERROR; 01686 } 01687 } 01688 /* Return AUDIO_OK when all operations are correctly done */ 01689 return AUDIO_OK; 01690 } 01691 01692 /** 01693 * @brief Resumes the audio file stream. 01694 * @param pBuf: Main buffer pointer for the recorded data storing 01695 * @param InputDevice: Microphone to be paused. Can be INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5. 01696 * @retval AUDIO_OK if correct communication, else wrong communication 01697 */ 01698 uint8_t BSP_AUDIO_IN_ResumeEx(uint32_t *pBuf, uint32_t InputDevice) 01699 { 01700 if((InputDevice < INPUT_DEVICE_DIGITAL_MIC1) || (InputDevice > INPUT_DEVICE_DIGITAL_MIC5)) 01701 { 01702 return AUDIO_ERROR; 01703 } 01704 else 01705 { 01706 /* Call the Media layer stop function */ 01707 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInDfsdmFilter[POS_VAL(InputDevice)], (int32_t*)pBuf[MicBuff[POS_VAL(InputDevice)]], hAudioIn.RecSize)) 01708 { 01709 return AUDIO_ERROR; 01710 } 01711 } 01712 /* Return AUDIO_OK when all operations are correctly done */ 01713 return AUDIO_OK; 01714 } 01715 01716 /** 01717 * @brief Controls the audio in volume level. 01718 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 01719 * Mute and 100 for Max volume level). 01720 * @retval AUDIO_OK if correct communication, else wrong communication 01721 */ 01722 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume) 01723 { 01724 /* Set the Global variable AudioInVolume */ 01725 AudioInVolume = Volume; 01726 01727 /* Return AUDIO_OK when all operations are correctly done */ 01728 return AUDIO_OK; 01729 } 01730 01731 /** 01732 * @brief User callback when record buffer is filled. 01733 */ 01734 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void) 01735 { 01736 /* This function should be implemented by the user application. 01737 It is called into this driver when the current buffer is filled 01738 to prepare the next buffer pointer and its size. */ 01739 } 01740 01741 /** 01742 * @brief Manages the DMA Half Transfer complete event. 01743 */ 01744 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 01745 { 01746 /* This function should be implemented by the user application. 01747 It is called into this driver when the current buffer is filled 01748 to prepare the next buffer pointer and its size. */ 01749 } 01750 01751 /** 01752 * @brief User callback when record buffer is filled. 01753 * @param InputDevice: INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5. 01754 */ 01755 __weak void BSP_AUDIO_IN_TransferComplete_CallBackEx(uint32_t InputDevice) 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 User callback when record buffer is filled. 01764 * @param InputDevice: INPUT_DEVICE_DIGITAL_MIC1 .. INPUT_DEVICE_DIGITAL_MIC5. 01765 */ 01766 __weak void BSP_AUDIO_IN_HalfTransfer_CallBackEx(uint32_t InputDevice) 01767 { 01768 /* This function should be implemented by the user application. 01769 It is called into this driver when the current buffer is filled 01770 to prepare the next buffer pointer and its size. */ 01771 } 01772 01773 /** 01774 * @brief Audio IN Error callback function. 01775 */ 01776 __weak void BSP_AUDIO_IN_Error_Callback(void) 01777 { 01778 /* This function is called when an Interrupt due to transfer error on or peripheral 01779 error occurs. */ 01780 } 01781 01782 /** 01783 * @} 01784 */ 01785 01786 /******************************************************************************* 01787 Static Functions 01788 *******************************************************************************/ 01789 01790 /** 01791 * @brief De-initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01792 * @retval AUDIO_OK if correct communication, else wrong communication 01793 */ 01794 static uint8_t DFSDMx_DeInit(void) 01795 { 01796 for(uint32_t i = 0; i < DFSDM_MIC_NUMBER; i++) 01797 { 01798 if(hAudioInDfsdmFilter[i].Instance != NULL) 01799 { 01800 if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInDfsdmFilter[i])) 01801 { 01802 return AUDIO_ERROR; 01803 } 01804 hAudioInDfsdmFilter[i].Instance = NULL; 01805 } 01806 if(hAudioInDfsdmChannel[i].Instance != NULL) 01807 { 01808 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInDfsdmChannel[i])) 01809 { 01810 return AUDIO_ERROR; 01811 } 01812 hAudioInDfsdmChannel[i].Instance = NULL; 01813 } 01814 } 01815 return AUDIO_OK; 01816 } 01817 01818 /** 01819 * @brief Initializes the DFSDM channel MSP. 01820 */ 01821 static void DFSDMx_ChannelMspInit(void) 01822 { 01823 GPIO_InitTypeDef GPIO_InitStruct; 01824 01825 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 01826 GPIO_InitStruct.Pull = GPIO_NOPULL; 01827 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; 01828 01829 if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 01830 { 01831 /* Enable DFSDM clock */ 01832 AUDIO_DFSDMx_MIC1_CLK_ENABLE(); 01833 /* Enable GPIO clock */ 01834 AUDIO_DFSDMx_MIC1_CKOUT_DMIC_GPIO_CLK_ENABLE(); 01835 01836 /* DFSDM MIC1 pins configuration: DFSDM_CKOUT, DMIC_DATIN pins -------------*/ 01837 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC1_CKOUT_PIN; 01838 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC1_CKOUT_DMIC_AF; 01839 HAL_GPIO_Init(AUDIO_DFSDMx_MIC1_CKOUT_DMIC_GPIO_PORT, &GPIO_InitStruct); 01840 01841 AUDIO_DFSDMx_MIC1_DMIC_GPIO_CLK_ENABLE(); 01842 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC1_DMIC_PIN; 01843 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC1_DMIC_AF; 01844 HAL_GPIO_Init(AUDIO_DFSDMx_MIC1_DMIC_GPIO_PORT, &GPIO_InitStruct); 01845 } 01846 01847 if(hAudioIn.InputDevice > INPUT_DEVICE_DIGITAL_MIC1) 01848 { 01849 /* Enable DFSDM clock */ 01850 AUDIO_DFSDMx_MIC2_5_CLK_ENABLE(); 01851 /* Enable GPIO clock */ 01852 AUDIO_DFSDMx_MIC2_5_CKOUT_DMIC_GPIO_CLK_ENABLE(); 01853 01854 /* DFSDM MIC2 pins configuration: DFSDM_CKOUT, DMIC_DATIN pins -------------*/ 01855 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC2_5_CKOUT_PIN; 01856 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC2_5_CKOUT_DMIC_AF; 01857 HAL_GPIO_Init(AUDIO_DFSDMx_MIC2_5_CKOUT_DMIC_GPIO_PORT, &GPIO_InitStruct); 01858 01859 if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) ||\ 01860 ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC3) == INPUT_DEVICE_DIGITAL_MIC3)) 01861 { 01862 AUDIO_DFSDMx_MIC23_DMIC_GPIO_CLK_ENABLE(); 01863 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC23_DMIC_PIN; 01864 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC23_DMIC_AF; 01865 HAL_GPIO_Init(AUDIO_DFSDMx_MIC23_DMIC_GPIO_PORT, &GPIO_InitStruct); 01866 } 01867 01868 if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC4) == INPUT_DEVICE_DIGITAL_MIC4) ||\ 01869 ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC5) == INPUT_DEVICE_DIGITAL_MIC5)) 01870 { 01871 01872 AUDIO_DFSDMx_MIC45_DMIC_GPIO_CLK_ENABLE(); 01873 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC45_DMIC_PIN; 01874 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_MIC45_DMIC_AF; 01875 HAL_GPIO_Init(AUDIO_DFSDMx_MIC45_DMIC_GPIO_PORT, &GPIO_InitStruct); 01876 } 01877 } 01878 } 01879 01880 /** 01881 * @brief DeInitializes the DFSDM channel MSP. 01882 */ 01883 static void DFSDMx_ChannelMspDeInit(void) 01884 { 01885 GPIO_InitTypeDef GPIO_InitStruct; 01886 01887 if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) 01888 { 01889 /* DFSDM MIC1 pins configuration: DFSDM_CKOUT, DMIC_DATIN pins -------------*/ 01890 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC1_CKOUT_PIN; 01891 HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC1_CKOUT_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 01892 01893 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC1_DMIC_PIN; 01894 HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC1_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 01895 } 01896 01897 if(hAudioIn.InputDevice > INPUT_DEVICE_DIGITAL_MIC1) 01898 { 01899 /* DFSDM MIC2, MIC3, MIC4 and MIC5 pins configuration: DFSDM_CKOUT pin -----*/ 01900 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC2_5_CKOUT_PIN; 01901 HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC2_5_CKOUT_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 01902 01903 if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) ||\ 01904 ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC3) == INPUT_DEVICE_DIGITAL_MIC3)) 01905 { 01906 /* DFSDM MIC2, MIC3 pins configuration: DMIC_DATIN pin -----*/ 01907 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC23_DMIC_PIN; 01908 HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC23_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 01909 } 01910 01911 if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC4) == INPUT_DEVICE_DIGITAL_MIC4) ||\ 01912 ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC5) == INPUT_DEVICE_DIGITAL_MIC5)) 01913 { 01914 /* DFSDM MIC4, MIC5 pins configuration: DMIC_DATIN pin -----*/ 01915 GPIO_InitStruct.Pin = AUDIO_DFSDMx_MIC45_DMIC_PIN; 01916 HAL_GPIO_DeInit(AUDIO_DFSDMx_MIC45_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 01917 } 01918 } 01919 } 01920 01921 /** 01922 * @brief Initializes the DFSDM filter MSP. 01923 */ 01924 static void DFSDMx_FilterMspInit(void) 01925 { 01926 uint32_t i = 0, mic_num = 0, mic_init[DFSDM_MIC_NUMBER] = {0}; 01927 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}; 01928 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}; 01929 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}; 01930 01931 /* Enable the DMA clock */ 01932 AUDIO_DFSDMx_DMAx_CLK_ENABLE(); 01933 01934 for(i = 0; i < hAudioIn.ChannelNbr; i++) 01935 { 01936 if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)] != 1)) 01937 { 01938 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC1); 01939 mic_init[mic_num] = 1; 01940 } 01941 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)] != 1)) 01942 { 01943 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC2); 01944 mic_init[mic_num] = 1; 01945 } 01946 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC3) == INPUT_DEVICE_DIGITAL_MIC3) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC3)] != 1)) 01947 { 01948 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC3); 01949 mic_init[mic_num] = 1; 01950 } 01951 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC4) == INPUT_DEVICE_DIGITAL_MIC4) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC4)] != 1)) 01952 { 01953 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC4); 01954 mic_init[mic_num] = 1; 01955 } 01956 else if(((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC5) == INPUT_DEVICE_DIGITAL_MIC5) && (mic_init[POS_VAL(INPUT_DEVICE_DIGITAL_MIC5)] != 1)) 01957 { 01958 mic_num = POS_VAL(INPUT_DEVICE_DIGITAL_MIC5); 01959 mic_init[mic_num] = 1; 01960 } 01961 01962 /* Configure the hDmaDfsdm[i] handle parameters */ 01963 hDmaDfsdm[mic_num].Init.Channel = AUDIO_DFSDMx_DMAx_MIC_CHANNEL[mic_num]; 01964 hDmaDfsdm[mic_num].Instance = AUDIO_DFSDMx_DMAx_MIC_STREAM[mic_num]; 01965 hDmaDfsdm[mic_num].Init.Direction = DMA_PERIPH_TO_MEMORY; 01966 hDmaDfsdm[mic_num].Init.PeriphInc = DMA_PINC_DISABLE; 01967 hDmaDfsdm[mic_num].Init.MemInc = DMA_MINC_ENABLE; 01968 hDmaDfsdm[mic_num].Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE; 01969 hDmaDfsdm[mic_num].Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE; 01970 hDmaDfsdm[mic_num].Init.Mode = DMA_CIRCULAR; 01971 hDmaDfsdm[mic_num].Init.Priority = DMA_PRIORITY_HIGH; 01972 hDmaDfsdm[mic_num].Init.FIFOMode = DMA_FIFOMODE_DISABLE; 01973 hDmaDfsdm[mic_num].Init.MemBurst = DMA_MBURST_SINGLE; 01974 hDmaDfsdm[mic_num].Init.PeriphBurst = DMA_PBURST_SINGLE; 01975 hDmaDfsdm[mic_num].State = HAL_DMA_STATE_RESET; 01976 01977 /* Associate the DMA handle */ 01978 __HAL_LINKDMA(&hAudioInDfsdmFilter[mic_num], hdmaReg, hDmaDfsdm[mic_num]); 01979 01980 /* Reset DMA handle state */ 01981 __HAL_DMA_RESET_HANDLE_STATE(&hDmaDfsdm[mic_num]); 01982 01983 /* Configure the DMA Channel */ 01984 HAL_DMA_Init(&hDmaDfsdm[mic_num]); 01985 01986 /* DMA IRQ Channel configuration */ 01987 HAL_NVIC_SetPriority(AUDIO_DFSDM_DMAx_MIC_IRQHandler[mic_num], AUDIO_IN_IRQ_PREPRIO, 0); 01988 HAL_NVIC_EnableIRQ(AUDIO_DFSDM_DMAx_MIC_IRQHandler[mic_num]); 01989 } 01990 } 01991 01992 /** 01993 * @brief DeInitializes the DFSDM filter MSP. 01994 */ 01995 static void DFSDMx_FilterMspDeInit(void) 01996 { 01997 /* Configure the DMA Channel */ 01998 for(uint32_t i = 0; i < DFSDM_MIC_NUMBER; i++) 01999 { 02000 if(hDmaDfsdm[i].Instance != NULL) 02001 { 02002 HAL_DMA_DeInit(&hDmaDfsdm[i]); 02003 } 02004 } 02005 } 02006 02007 /** 02008 * @brief Initializes the Audio Codec audio interface (I2S) 02009 * @note This function assumes that the I2S input clock 02010 * is already configured and ready to be used. 02011 * @param AudioFreq: Audio frequency to be configured for the I2S peripheral. 02012 */ 02013 static void I2Sx_In_Init(uint32_t AudioFreq) 02014 { 02015 /* Initialize the hAudioInI2s and haudio_in_i2sext Instance parameters */ 02016 haudio_i2s.Instance = AUDIO_IN_I2Sx; 02017 haudio_in_i2sext.Instance = I2S3ext; 02018 02019 /* Disable I2S block */ 02020 __HAL_I2S_DISABLE(&haudio_i2s); 02021 __HAL_I2S_DISABLE(&haudio_in_i2sext); 02022 02023 /* I2S peripheral configuration */ 02024 haudio_i2s.Init.AudioFreq = AudioFreq; 02025 haudio_i2s.Init.ClockSource = I2S_CLOCK_PLL; 02026 haudio_i2s.Init.CPOL = I2S_CPOL_LOW; 02027 haudio_i2s.Init.DataFormat = I2S_DATAFORMAT_16B; 02028 haudio_i2s.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE; 02029 haudio_i2s.Init.Mode = I2S_MODE_MASTER_TX; 02030 haudio_i2s.Init.Standard = I2S_STANDARD_PHILIPS; 02031 haudio_i2s.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_ENABLE; 02032 /* Init the I2S */ 02033 HAL_I2S_Init(&haudio_i2s); 02034 02035 /* I2Sext peripheral configuration */ 02036 haudio_in_i2sext.Init.AudioFreq = AudioFreq; 02037 haudio_in_i2sext.Init.ClockSource = I2S_CLOCK_PLL; 02038 haudio_in_i2sext.Init.CPOL = I2S_CPOL_HIGH; 02039 haudio_in_i2sext.Init.DataFormat = I2S_DATAFORMAT_16B; 02040 haudio_in_i2sext.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE; 02041 haudio_in_i2sext.Init.Mode = I2S_MODE_SLAVE_RX; 02042 haudio_in_i2sext.Init.Standard = I2S_STANDARD_PHILIPS; 02043 02044 /* Init the I2Sext */ 02045 HAL_I2S_Init(&haudio_in_i2sext); 02046 02047 /* Enable I2S block */ 02048 __HAL_I2S_ENABLE(&haudio_i2s); 02049 __HAL_I2S_ENABLE(&haudio_in_i2sext); 02050 } 02051 02052 /** 02053 * @brief Deinitializes the Audio Codec audio interface (I2S). 02054 */ 02055 static void I2Sx_In_DeInit(void) 02056 { 02057 /* Initialize the hAudioInI2s Instance parameter */ 02058 haudio_i2s.Instance = AUDIO_IN_I2Sx; 02059 02060 /* Disable I2S block */ 02061 __HAL_I2S_DISABLE(&haudio_i2s); 02062 02063 /* DeInit the I2S */ 02064 HAL_I2S_DeInit(&haudio_i2s); 02065 02066 /* Initialize the hAudioInI2s Instance parameter */ 02067 haudio_in_i2sext.Instance = I2S3ext; 02068 02069 /* Disable I2S block */ 02070 __HAL_I2S_DISABLE(&haudio_in_i2sext); 02071 02072 /* DeInit the I2S */ 02073 HAL_I2S_DeInit(&haudio_in_i2sext); 02074 } 02075 02076 /** 02077 * @brief This function handles DFSDM MIC1 DMA interrupt request. 02078 * @param None 02079 * @retval None 02080 */ 02081 void AUDIO_DFSDM_DMAx_MIC1_IRQHandler(void) 02082 { 02083 HAL_DMA_IRQHandler(hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC1)].hdmaReg); 02084 02085 } 02086 02087 /** 02088 * @brief This function handles DFSDM MIC2 DMA interrupt request. 02089 * @param None 02090 * @retval None 02091 */ 02092 void AUDIO_DFSDM_DMAx_MIC2_IRQHandler(void) 02093 { 02094 HAL_DMA_IRQHandler(hAudioInDfsdmFilter[POS_VAL(INPUT_DEVICE_DIGITAL_MIC2)].hdmaReg); 02095 } 02096 02097 /** 02098 * @brief This function handles I2S DMA interrupt request. 02099 * @param None 02100 * @retval None 02101 */ 02102 void AUDIO_OUT_I2Sx_DMAx_IRQHandler(void) 02103 { 02104 HAL_DMA_IRQHandler(haudio_i2s.hdmatx); 02105 } 02106 02107 /** 02108 * @} 02109 */ 02110 02111 /** 02112 * @} 02113 */ 02114 02115 /** 02116 * @} 02117 */ 02118 02119 /** 02120 * @} 02121 */ 02122 02123 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Tue Jul 12 2022 13:54:37 by 1.7.2