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