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