STM32F769I-Discovery BSP User Manual
|
stm32f769i_discovery_audio.c
Go to the documentation of this file.
00001 /** 00002 ****************************************************************************** 00003 * @file stm32f769i_discovery_audio.c 00004 * @author MCD Application Team 00005 * @version V2.0.0 00006 * @date 30-December-2016 00007 * @brief This file provides the Audio driver for the STM32F769I-DISCOVERY 00008 * board. 00009 @verbatim 00010 How To use this driver: 00011 ----------------------- 00012 + This driver supports STM32F7xx devices on STM32F769I-DISCOVERY (MB1225) Evaluation boards. 00013 + Call the function BSP_AUDIO_OUT_Init( 00014 OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 00015 OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH) 00016 Volume : Initial volume to be set (0 is min (mute), 100 is max (100%) 00017 AudioFreq : Audio frequency in Hz (8000, 16000, 22500, 32000...) 00018 this parameter is relative to the audio file/stream type. 00019 ) 00020 This function configures all the hardware required for the audio application (codec, I2C, SAI, 00021 GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK. 00022 If the returned value is different from AUDIO_OK or the function is stuck then the communication with 00023 the codec has failed (try to un-plug the power or reset device in this case). 00024 - OUTPUT_DEVICE_SPEAKER : only speaker will be set as output for the audio stream. 00025 - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream. 00026 - OUTPUT_DEVICE_BOTH : both Speaker and Headphone are used as outputs for the audio stream 00027 at the same time. 00028 Note. On STM32F769I-DISCOVERY SAI_DMA is configured in CIRCULAR mode. Due to this the application 00029 does NOT need to call BSP_AUDIO_OUT_ChangeBuffer() to assure streaming. 00030 + Call the function BSP_AUDIO_OUT_Play( 00031 pBuffer: pointer to the audio data file address 00032 Size : size of the buffer to be sent in Bytes 00033 ) 00034 to start playing (for the first time) from the audio file/stream. 00035 + Call the function BSP_AUDIO_OUT_Pause() to pause playing 00036 + Call the function BSP_AUDIO_OUT_Resume() to resume playing. 00037 Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called 00038 for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case). 00039 Note. This function should be called only when the audio file is played or paused (not stopped). 00040 + For each mode, you may need to implement the relative callback functions into your code. 00041 The Callback functions are named BSP_AUDIO_OUT_XXX_CallBack() and only their prototypes are declared in 00042 the stm32f769i_discovery_audio.h file. (refer to the example for more details on the callbacks implementations) 00043 + To Stop playing, to modify the volume level, the frequency, the audio frame slot, 00044 the device output mode the mute or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(), 00045 AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetAudioFrameSlot(), BSP_AUDIO_OUT_SetOutputMode(), 00046 BSP_AUDIO_OUT_SetMute() and BSP_AUDIO_OUT_Stop(). 00047 00048 + Call the function BSP_AUDIO_IN_Init( 00049 AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000...) 00050 this parameter is relative to the audio file/stream type. 00051 BitRes: Bit resolution fixed to 16bit 00052 ChnlNbr: Number of channel to be configured for the DFSDM peripheral 00053 ) 00054 This function configures all the hardware required for the audio in application (DFSDM filters and channels, 00055 Clock source for DFSDM periphiral, GPIOs, DMA and interrupt if needed). 00056 This function returns AUDIO_OK if configuration is OK.If the returned value is different from AUDIO_OK then 00057 the configuration should be wrong. 00058 Note: On STM32F769I-DISCOVERY, four DFSDM Channel/Filters are configured and their DMA streams are configured 00059 in CIRCULAR mode. 00060 + Call the function BSP_AUDIO_IN_AllocScratch( 00061 pScratch: pointer to scratch tables 00062 size: size of scratch buffer) 00063 This function must be called before BSP_AUDIO_IN_RECORD() to allocate buffer scratch for each DFSDM channel 00064 and its size. 00065 Note: These buffers scratch are used as intermidiate buffers to collect data within final record buffer. 00066 size is the total size of the four buffers scratch; If size is 512 then the size of each is 128. 00067 This function must be called after BSP_AUDIO_IN_Init() 00068 + Call the function BSP_AUDIO_IN_RECORD( 00069 pBuf: pointer to the recorded audio data file address 00070 Size: size of the buffer to be written in Bytes 00071 ) 00072 to start recording from microphones. 00073 00074 + Call the function BSP_AUDIO_IN_Pause() to pause recording 00075 + Call the function BSP_AUDIO_IN_Resume() to recording playing. 00076 Note. After calling BSP_AUDIO_IN_Pause() function for pause, only BSP_AUDIO_IN_Resume() should be called 00077 for resume (it is not allowed to call BSP_AUDIO_IN_RECORD() in this case). 00078 + Call the function BSP_AUDIO_IN_Stop() to stop recording 00079 + For each mode, you may need to implement the relative callback functions into your code. 00080 The Callback functions are named BSP_AUDIO_IN_XXX_CallBack() and only their prototypes are declared in 00081 the stm32f769i_discovery_audio.h file. (refer to the example for more details on the callbacks implementations) 00082 00083 Driver architecture: 00084 -------------------- 00085 + This driver provides the High Audio Layer: consists of the function API exported in the stm32f769i_discovery_audio.h file 00086 (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...) 00087 + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/ 00088 providing the audio file/stream. These functions are also included as local functions into 00089 the stm32f769i_discovery_audio.c file (DFSDMx_Init(), DFSDMx_DeInit(), SAIx_Init() and SAIx_DeInit()) 00090 00091 Known Limitations: 00092 ------------------ 00093 1- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second 00094 Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams. 00095 2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 00096 File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file. 00097 3- Supports only Stereo audio streaming. 00098 4- Supports only 16-bits audio data size. 00099 @endverbatim 00100 ****************************************************************************** 00101 * @attention 00102 * 00103 * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> 00104 * 00105 * Redistribution and use in source and binary forms, with or without modification, 00106 * are permitted provided that the following conditions are met: 00107 * 1. Redistributions of source code must retain the above copyright notice, 00108 * this list of conditions and the following disclaimer. 00109 * 2. Redistributions in binary form must reproduce the above copyright notice, 00110 * this list of conditions and the following disclaimer in the documentation 00111 * and/or other materials provided with the distribution. 00112 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00113 * may be used to endorse or promote products derived from this software 00114 * without specific prior written permission. 00115 * 00116 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00117 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00118 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00119 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00120 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00121 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00122 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00123 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00124 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00125 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00126 * 00127 ****************************************************************************** 00128 */ 00129 /* Includes ------------------------------------------------------------------*/ 00130 #include "stm32f769i_discovery_audio.h" 00131 00132 /** @addtogroup BSP 00133 * @{ 00134 */ 00135 00136 /** @addtogroup STM32F769I_DISCOVERY 00137 * @{ 00138 */ 00139 00140 /** @defgroup STM32F769I_DISCOVERY_AUDIO STM32F769I_DISCOVERY AUDIO 00141 * @brief This file includes the low layer driver for wm8994 Audio Codec 00142 * available on STM32F769I-DISCOVERY discoveryuation board(MB1225). 00143 * @{ 00144 */ 00145 00146 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Types STM32F769I_DISCOVERY_AUDIO Private Types 00147 * @{ 00148 */ 00149 typedef struct 00150 { 00151 uint16_t *pRecBuf; /* Pointer to record user buffer */ 00152 uint32_t RecSize; /* Size to record in mono, double size to record in stereo */ 00153 }AUDIOIN_TypeDef; 00154 00155 /** 00156 * @} 00157 */ 00158 00159 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Defines STM32F769I_DISCOVERY_AUDIO Private Defines 00160 * @{ 00161 */ 00162 /** 00163 * @} 00164 */ 00165 00166 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Macros STM32F769I_DISCOVERY_AUDIO Private Macros 00167 * @{ 00168 */ 00169 /*### RECORD ###*/ 00170 #define DFSDM_OVER_SAMPLING(__FREQUENCY__) \ 00171 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 256 \ 00172 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \ 00173 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \ 00174 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \ 00175 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \ 00176 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64 \ 00177 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 40 : 20 \ 00178 00179 #define DFSDM_CLOCK_DIVIDER(__FREQUENCY__) \ 00180 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 24 \ 00181 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \ 00182 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \ 00183 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \ 00184 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \ 00185 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4 \ 00186 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 25 : 25 \ 00187 00188 #define DFSDM_FILTER_ORDER(__FREQUENCY__) \ 00189 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? DFSDM_FILTER_SINC3_ORDER \ 00190 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \ 00191 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \ 00192 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \ 00193 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \ 00194 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC3_ORDER \ 00195 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC3_ORDER : DFSDM_FILTER_SINC5_ORDER \ 00196 00197 #define DFSDM_RIGHT_BIT_SHIFT(__FREQUENCY__) \ 00198 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 8 \ 00199 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 8 \ 00200 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 3 \ 00201 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \ 00202 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 7 \ 00203 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 0 \ 00204 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 0 : 4 \ 00205 00206 /* Saturate the record PCM sample */ 00207 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N))) 00208 /** 00209 * @} 00210 */ 00211 00212 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Variables STM32F769I_DISCOVERY_AUDIO Private Variables 00213 * @{ 00214 */ 00215 /* PLAY */ 00216 AUDIO_DrvTypeDef *audio_drv; 00217 SAI_HandleTypeDef haudio_out_sai; 00218 SAI_HandleTypeDef haudio_in_sai; 00219 00220 /* RECORD */ 00221 AUDIOIN_TypeDef hAudioIn; 00222 00223 DFSDM_Channel_HandleTypeDef hAudioInTopLeftChannel; 00224 DFSDM_Channel_HandleTypeDef hAudioInTopRightChannel; 00225 DFSDM_Filter_HandleTypeDef hAudioInTopLeftFilter; 00226 DFSDM_Filter_HandleTypeDef hAudioInTopRightFilter; 00227 DMA_HandleTypeDef hDmaTopLeft; 00228 DMA_HandleTypeDef hDmaTopRight; 00229 00230 DFSDM_Channel_HandleTypeDef hAudioInButtomLeftChannel; 00231 DFSDM_Channel_HandleTypeDef hAudioInButtomRightChannel; 00232 DFSDM_Filter_HandleTypeDef hAudioInButtomLeftFilter; 00233 DFSDM_Filter_HandleTypeDef hAudioInButtomRightFilter; 00234 DMA_HandleTypeDef hDmaButtomLeft; 00235 DMA_HandleTypeDef hDmaButtomRight; 00236 00237 /* Buffers for right and left samples */ 00238 static int32_t *pScratchBuff[2*DEFAULT_AUDIO_IN_CHANNEL_NBR]; 00239 static __IO int32_t ScratchSize; 00240 /* Cannel number to be used: 2 channels by default */ 00241 static uint8_t AudioIn_ChannelNumber = DEFAULT_AUDIO_IN_CHANNEL_NBR; 00242 /* Input device to be used: digital microphones by default */ 00243 static uint16_t AudioIn_Device = INPUT_DEVICE_DIGITAL_MIC; 00244 00245 /* Buffers status flags */ 00246 static uint32_t DmaTopLeftRecHalfCplt = 0; 00247 static uint32_t DmaTopLeftRecCplt = 0; 00248 static uint32_t DmaTopRightRecHalfCplt = 0; 00249 static uint32_t DmaTopRightRecCplt = 0; 00250 static uint32_t DmaButtomLeftRecHalfCplt = 0; 00251 static uint32_t DmaButtomLeftRecCplt = 0; 00252 static uint32_t DmaButtomRightRecHalfCplt = 0; 00253 static uint32_t DmaButtomRightRecCplt = 0; 00254 00255 /* Application Buffer Trigger */ 00256 static __IO uint32_t AppBuffTrigger = 0; 00257 static __IO uint32_t AppBuffHalf = 0; 00258 00259 /** 00260 * @} 00261 */ 00262 00263 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Function_Prototypes STM32F769I_DISCOVERY_AUDIO Private Function Prototypes 00264 * @{ 00265 */ 00266 static void SAIx_Out_Init(uint32_t AudioFreq); 00267 static void SAIx_Out_DeInit(void); 00268 static void SAI_AUDIO_IN_MspInit(SAI_HandleTypeDef *hsai, void *Params); 00269 static void SAI_AUDIO_IN_MspDeInit(SAI_HandleTypeDef *hsai, void *Params); 00270 static void SAIx_In_Init(uint32_t AudioFreq); 00271 static void SAIx_In_DeInit(void); 00272 static void DFSDMx_ChannelMspInit(void); 00273 static void DFSDMx_FilterMspInit(void); 00274 static void DFSDMx_ChannelMspDeInit(void); 00275 static void DFSDMx_FilterMspDeInit(void); 00276 static uint8_t DFSDMx_Init(uint32_t AudioFreq); 00277 static uint8_t DFSDMx_DeInit(void); 00278 00279 /** 00280 * @} 00281 */ 00282 00283 /** @defgroup STM32F769I_DISCOVERY_AUDIO_out_Private_Functions STM32F769I_DISCOVERY_AUDIO_Out Private Functions 00284 * @{ 00285 */ 00286 00287 /** 00288 * @brief Configures the audio peripherals. 00289 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00290 * or OUTPUT_DEVICE_BOTH. 00291 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00292 * @param AudioFreq: Audio frequency used to play the audio stream. 00293 * @retval AUDIO_OK if correct communication, else wrong communication 00294 */ 00295 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00296 { 00297 uint8_t ret = AUDIO_ERROR; 00298 uint32_t deviceid = 0x00; 00299 00300 /* Disable SAI */ 00301 SAIx_Out_DeInit(); 00302 00303 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00304 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00305 00306 /* SAI data transfer preparation: 00307 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00308 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00309 if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET) 00310 { 00311 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00312 BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL); 00313 } 00314 SAIx_Out_Init(AudioFreq); 00315 00316 /* wm8994 codec initialization */ 00317 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00318 00319 if((deviceid) == WM8994_ID) 00320 { 00321 /* Reset the Codec Registers */ 00322 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00323 /* Initialize the audio driver structure */ 00324 audio_drv = &wm8994_drv; 00325 ret = AUDIO_OK; 00326 } 00327 else 00328 { 00329 ret = AUDIO_ERROR; 00330 } 00331 00332 if(ret == AUDIO_OK) 00333 { 00334 /* Initialize the codec internal registers */ 00335 audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq); 00336 } 00337 00338 return ret; 00339 } 00340 00341 /** 00342 * @brief Starts playing audio stream from a data buffer for a determined size. 00343 * @param pBuffer: Pointer to the buffer 00344 * @param Size: Number of audio data BYTES. 00345 * @retval AUDIO_OK if correct communication, else wrong communication 00346 */ 00347 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size) 00348 { 00349 /* Call the audio Codec Play function */ 00350 if(audio_drv->Play(AUDIO_I2C_ADDRESS, (uint16_t *)pBuffer, Size) != 0) 00351 { 00352 return AUDIO_ERROR; 00353 } 00354 else 00355 { 00356 /* Update the Media layer and enable it for play */ 00357 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE)); 00358 00359 return AUDIO_OK; 00360 } 00361 } 00362 00363 /** 00364 * @brief Sends n-Bytes on the SAI interface. 00365 * @param pData: pointer on data address 00366 * @param Size: number of data to be written 00367 * @retval None 00368 */ 00369 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size) 00370 { 00371 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size); 00372 } 00373 00374 /** 00375 * @brief This function Pauses the audio file stream. In case 00376 * of using DMA, the DMA Pause feature is used. 00377 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00378 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00379 * function for resume could lead to unexpected behaviour). 00380 * @retval AUDIO_OK if correct communication, else wrong communication 00381 */ 00382 uint8_t BSP_AUDIO_OUT_Pause(void) 00383 { 00384 /* Call the Audio Codec Pause/Resume function */ 00385 if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0) 00386 { 00387 return AUDIO_ERROR; 00388 } 00389 else 00390 { 00391 /* Call the Media layer pause function */ 00392 HAL_SAI_DMAPause(&haudio_out_sai); 00393 00394 /* Return AUDIO_OK when all operations are correctly done */ 00395 return AUDIO_OK; 00396 } 00397 } 00398 00399 /** 00400 * @brief Resumes the audio file stream. 00401 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00402 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00403 * function for resume could lead to unexpected behaviour). 00404 * @retval AUDIO_OK if correct communication, else wrong communication 00405 */ 00406 uint8_t BSP_AUDIO_OUT_Resume(void) 00407 { 00408 /* Call the Audio Codec Pause/Resume function */ 00409 if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0) 00410 { 00411 return AUDIO_ERROR; 00412 } 00413 else 00414 { 00415 /* Call the Media layer pause/resume function */ 00416 HAL_SAI_DMAResume(&haudio_out_sai); 00417 00418 /* Return AUDIO_OK when all operations are correctly done */ 00419 return AUDIO_OK; 00420 } 00421 } 00422 00423 /** 00424 * @brief Stops audio playing and Power down the Audio Codec. 00425 * @param Option: could be one of the following parameters 00426 * - CODEC_PDWN_SW: for software power off (by writing registers). 00427 * Then no need to reconfigure the Codec after power on. 00428 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00429 * Then need to reconfigure the Codec after power on. 00430 * @retval AUDIO_OK if correct communication, else wrong communication 00431 */ 00432 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option) 00433 { 00434 /* Call the Media layer stop function */ 00435 HAL_SAI_DMAStop(&haudio_out_sai); 00436 00437 /* Call Audio Codec Stop function */ 00438 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 00439 { 00440 return AUDIO_ERROR; 00441 } 00442 else 00443 { 00444 if(Option == CODEC_PDWN_HW) 00445 { 00446 /* Wait at least 100us */ 00447 HAL_Delay(1); 00448 } 00449 /* Return AUDIO_OK when all operations are correctly done */ 00450 return AUDIO_OK; 00451 } 00452 } 00453 00454 /** 00455 * @brief Controls the current audio volume level. 00456 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00457 * Mute and 100 for Max volume level). 00458 * @retval AUDIO_OK if correct communication, else wrong communication 00459 */ 00460 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume) 00461 { 00462 /* Call the codec volume control function with converted volume value */ 00463 if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 00464 { 00465 return AUDIO_ERROR; 00466 } 00467 else 00468 { 00469 /* Return AUDIO_OK when all operations are correctly done */ 00470 return AUDIO_OK; 00471 } 00472 } 00473 00474 /** 00475 * @brief Enables or disables the MUTE mode by software 00476 * @param Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 00477 * unmute the codec and restore previous volume level. 00478 * @retval AUDIO_OK if correct communication, else wrong communication 00479 */ 00480 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd) 00481 { 00482 /* Call the Codec Mute function */ 00483 if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0) 00484 { 00485 return AUDIO_ERROR; 00486 } 00487 else 00488 { 00489 /* Return AUDIO_OK when all operations are correctly done */ 00490 return AUDIO_OK; 00491 } 00492 } 00493 00494 /** 00495 * @brief Switch dynamically (while audio file is played) the output target 00496 * (speaker or headphone). 00497 * @param Output: The audio output target: OUTPUT_DEVICE_SPEAKER, 00498 * OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH 00499 * @retval AUDIO_OK if correct communication, else wrong communication 00500 */ 00501 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output) 00502 { 00503 /* Call the Codec output device function */ 00504 if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0) 00505 { 00506 return AUDIO_ERROR; 00507 } 00508 else 00509 { 00510 /* Return AUDIO_OK when all operations are correctly done */ 00511 return AUDIO_OK; 00512 } 00513 } 00514 00515 /** 00516 * @brief Updates the audio frequency. 00517 * @param AudioFreq: Audio frequency used to play the audio stream. 00518 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00519 * audio frequency. 00520 * @retval None 00521 */ 00522 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq) 00523 { 00524 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00525 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00526 00527 /* Disable SAI peripheral to allow access to SAI internal registers */ 00528 __HAL_SAI_DISABLE(&haudio_out_sai); 00529 00530 /* Update the SAI audio frequency configuration */ 00531 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00532 HAL_SAI_Init(&haudio_out_sai); 00533 00534 /* Enable SAI peripheral to generate MCLK */ 00535 __HAL_SAI_ENABLE(&haudio_out_sai); 00536 } 00537 00538 /** 00539 * @brief Updates the Audio frame slot configuration. 00540 * @param AudioFrameSlot: specifies the audio Frame slot 00541 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00542 * audio frame slot. 00543 * @retval None 00544 */ 00545 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot) 00546 { 00547 /* Disable SAI peripheral to allow access to SAI internal registers */ 00548 __HAL_SAI_DISABLE(&haudio_out_sai); 00549 00550 /* Update the SAI audio frame slot configuration */ 00551 haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot; 00552 HAL_SAI_Init(&haudio_out_sai); 00553 00554 /* Enable SAI peripheral to generate MCLK */ 00555 __HAL_SAI_ENABLE(&haudio_out_sai); 00556 } 00557 00558 /** 00559 * @brief De-initializes the audio out peripheral. 00560 * @retval None 00561 */ 00562 void BSP_AUDIO_OUT_DeInit(void) 00563 { 00564 SAIx_Out_DeInit(); 00565 /* DeInit the SAI MSP : this __weak function can be rewritten by the application */ 00566 BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL); 00567 } 00568 00569 /** 00570 * @brief Tx Transfer completed callbacks. 00571 * @param hsai: SAI handle 00572 * @retval None 00573 */ 00574 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) 00575 { 00576 /* Manage the remaining file size and new address offset: This function 00577 should be coded by user (its prototype is already declared in stm32f769i_discovery_audio.h) */ 00578 BSP_AUDIO_OUT_TransferComplete_CallBack(); 00579 } 00580 00581 /** 00582 * @brief Tx Half Transfer completed callbacks. 00583 * @param hsai: SAI handle 00584 * @retval None 00585 */ 00586 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 00587 { 00588 /* Manage the remaining file size and new address offset: This function 00589 should be coded by user (its prototype is already declared in stm32f769i_discovery_audio.h) */ 00590 BSP_AUDIO_OUT_HalfTransfer_CallBack(); 00591 } 00592 00593 /** 00594 * @brief SAI error callbacks. 00595 * @param hsai: SAI handle 00596 * @retval None 00597 */ 00598 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 00599 { 00600 if(hsai->Instance == AUDIO_OUT_SAIx) 00601 { 00602 BSP_AUDIO_OUT_Error_CallBack(); 00603 } 00604 else 00605 { 00606 BSP_AUDIO_IN_Error_CallBack(); 00607 } 00608 } 00609 00610 /** 00611 * @brief Manages the DMA full Transfer complete event. 00612 * @retval None 00613 */ 00614 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void) 00615 { 00616 } 00617 00618 /** 00619 * @brief Manages the DMA Half Transfer complete event. 00620 * @retval None 00621 */ 00622 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) 00623 { 00624 } 00625 00626 /** 00627 * @brief Manages the DMA FIFO error event. 00628 * @retval None 00629 */ 00630 __weak void BSP_AUDIO_OUT_Error_CallBack(void) 00631 { 00632 } 00633 00634 /** 00635 * @brief Initializes BSP_AUDIO_OUT MSP. 00636 * @param hsai: SAI handle 00637 * @param Params 00638 * @retval None 00639 */ 00640 __weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params) 00641 { 00642 static DMA_HandleTypeDef hdma_sai_tx; 00643 GPIO_InitTypeDef gpio_init_structure; 00644 00645 /* Enable SAI clock */ 00646 AUDIO_OUT_SAIx_CLK_ENABLE(); 00647 00648 00649 /* Enable GPIO clock */ 00650 AUDIO_OUT_SAIx_MCLK_ENABLE(); 00651 AUDIO_OUT_SAIx_SD_FS_CLK_ENABLE(); 00652 00653 /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/ 00654 gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SD_PIN; 00655 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00656 gpio_init_structure.Pull = GPIO_NOPULL; 00657 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00658 gpio_init_structure.Alternate = AUDIO_OUT_SAIx_AF; 00659 HAL_GPIO_Init(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, &gpio_init_structure); 00660 00661 gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN; 00662 HAL_GPIO_Init(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, &gpio_init_structure); 00663 00664 /* Enable the DMA clock */ 00665 AUDIO_OUT_SAIx_DMAx_CLK_ENABLE(); 00666 00667 if(hsai->Instance == AUDIO_OUT_SAIx) 00668 { 00669 /* Configure the hdma_saiTx handle parameters */ 00670 hdma_sai_tx.Init.Channel = AUDIO_OUT_SAIx_DMAx_CHANNEL; 00671 hdma_sai_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; 00672 hdma_sai_tx.Init.PeriphInc = DMA_PINC_DISABLE; 00673 hdma_sai_tx.Init.MemInc = DMA_MINC_ENABLE; 00674 hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_OUT_SAIx_DMAx_PERIPH_DATA_SIZE; 00675 hdma_sai_tx.Init.MemDataAlignment = AUDIO_OUT_SAIx_DMAx_MEM_DATA_SIZE; 00676 hdma_sai_tx.Init.Mode = DMA_CIRCULAR; 00677 hdma_sai_tx.Init.Priority = DMA_PRIORITY_HIGH; 00678 hdma_sai_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; 00679 hdma_sai_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 00680 hdma_sai_tx.Init.MemBurst = DMA_MBURST_SINGLE; 00681 hdma_sai_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; 00682 00683 hdma_sai_tx.Instance = AUDIO_OUT_SAIx_DMAx_STREAM; 00684 00685 /* Associate the DMA handle */ 00686 __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx); 00687 00688 /* Deinitialize the Stream for new transfer */ 00689 HAL_DMA_DeInit(&hdma_sai_tx); 00690 00691 /* Configure the DMA Stream */ 00692 HAL_DMA_Init(&hdma_sai_tx); 00693 } 00694 00695 /* SAI DMA IRQ Channel configuration */ 00696 HAL_NVIC_SetPriority(AUDIO_OUT_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 00697 HAL_NVIC_EnableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ); 00698 } 00699 00700 /** 00701 * @brief Initializes SAI Audio IN MSP. 00702 * @param hsai: SAI handle 00703 * @param Params 00704 * @retval None 00705 */ 00706 static void SAI_AUDIO_IN_MspInit(SAI_HandleTypeDef *hsai, void *Params) 00707 { 00708 static DMA_HandleTypeDef hdma_sai_rx; 00709 GPIO_InitTypeDef gpio_init_structure; 00710 00711 /* Enable SAI clock */ 00712 AUDIO_IN_SAIx_CLK_ENABLE(); 00713 00714 /* Enable SD GPIO clock */ 00715 AUDIO_IN_SAIx_SD_ENABLE(); 00716 /* CODEC_SAI pin configuration: SD pin */ 00717 gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN; 00718 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00719 gpio_init_structure.Pull = GPIO_NOPULL; 00720 gpio_init_structure.Speed = GPIO_SPEED_FAST; 00721 gpio_init_structure.Alternate = AUDIO_IN_SAIx_AF; 00722 HAL_GPIO_Init(AUDIO_IN_SAIx_SD_GPIO_PORT, &gpio_init_structure); 00723 00724 /* Enable Audio INT GPIO clock */ 00725 AUDIO_IN_INT_GPIO_ENABLE(); 00726 /* Audio INT pin configuration: input */ 00727 gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN; 00728 gpio_init_structure.Mode = GPIO_MODE_INPUT; 00729 gpio_init_structure.Pull = GPIO_NOPULL; 00730 gpio_init_structure.Speed = GPIO_SPEED_FAST; 00731 HAL_GPIO_Init(AUDIO_IN_INT_GPIO_PORT, &gpio_init_structure); 00732 00733 /* Enable the DMA clock */ 00734 AUDIO_IN_SAIx_DMAx_CLK_ENABLE(); 00735 00736 if(hsai->Instance == AUDIO_IN_SAIx) 00737 { 00738 /* Configure the hdma_sai_rx handle parameters */ 00739 hdma_sai_rx.Init.Channel = AUDIO_IN_SAIx_DMAx_CHANNEL; 00740 hdma_sai_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; 00741 hdma_sai_rx.Init.PeriphInc = DMA_PINC_DISABLE; 00742 hdma_sai_rx.Init.MemInc = DMA_MINC_ENABLE; 00743 hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAIx_DMAx_PERIPH_DATA_SIZE; 00744 hdma_sai_rx.Init.MemDataAlignment = AUDIO_IN_SAIx_DMAx_MEM_DATA_SIZE; 00745 hdma_sai_rx.Init.Mode = DMA_CIRCULAR; 00746 hdma_sai_rx.Init.Priority = DMA_PRIORITY_HIGH; 00747 hdma_sai_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 00748 hdma_sai_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 00749 hdma_sai_rx.Init.MemBurst = DMA_MBURST_SINGLE; 00750 hdma_sai_rx.Init.PeriphBurst = DMA_MBURST_SINGLE; 00751 00752 hdma_sai_rx.Instance = AUDIO_IN_SAIx_DMAx_STREAM; 00753 00754 /* Associate the DMA handle */ 00755 __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx); 00756 00757 /* Deinitialize the Stream for new transfer */ 00758 HAL_DMA_DeInit(&hdma_sai_rx); 00759 00760 /* Configure the DMA Stream */ 00761 HAL_DMA_Init(&hdma_sai_rx); 00762 } 00763 00764 /* SAI DMA IRQ Channel configuration */ 00765 HAL_NVIC_SetPriority(AUDIO_IN_SAIx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 00766 HAL_NVIC_EnableIRQ(AUDIO_IN_SAIx_DMAx_IRQ); 00767 00768 /* Audio INT IRQ Channel configuration */ 00769 HAL_NVIC_SetPriority(AUDIO_IN_INT_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 00770 HAL_NVIC_EnableIRQ(AUDIO_IN_INT_IRQ); 00771 } 00772 00773 /** 00774 * @brief De-Initializes SAI Audio IN MSP. 00775 * @param hsai: SAI handle 00776 * @param Params 00777 * @retval None 00778 */ 00779 static void SAI_AUDIO_IN_MspDeInit(SAI_HandleTypeDef *hsai, void *Params) 00780 { 00781 GPIO_InitTypeDef gpio_init_structure; 00782 00783 /* SAI DMA IRQ Channel deactivation */ 00784 HAL_NVIC_DisableIRQ(AUDIO_IN_SAIx_DMAx_IRQ); 00785 00786 if(hsai->Instance == AUDIO_IN_SAIx) 00787 { 00788 /* Deinitialize the DMA stream */ 00789 HAL_DMA_DeInit(hsai->hdmatx); 00790 } 00791 00792 /* Disable SAI peripheral */ 00793 __HAL_SAI_DISABLE(hsai); 00794 00795 /* Deactivates CODEC_SAI pin SD by putting them in input mode */ 00796 gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN; 00797 HAL_GPIO_DeInit(AUDIO_IN_SAIx_SD_GPIO_PORT, gpio_init_structure.Pin); 00798 00799 gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN; 00800 HAL_GPIO_DeInit(AUDIO_IN_INT_GPIO_PORT, gpio_init_structure.Pin); 00801 00802 /* Disable SAI clock */ 00803 AUDIO_IN_SAIx_CLK_DISABLE(); 00804 } 00805 00806 /** 00807 * @brief Deinitializes SAI MSP. 00808 * @param hsai: SAI handle 00809 * @param Params 00810 * @retval None 00811 */ 00812 __weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params) 00813 { 00814 GPIO_InitTypeDef gpio_init_structure; 00815 00816 /* SAI DMA IRQ Channel deactivation */ 00817 HAL_NVIC_DisableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ); 00818 00819 if(hsai->Instance == AUDIO_OUT_SAIx) 00820 { 00821 /* Deinitialize the DMA stream */ 00822 HAL_DMA_DeInit(hsai->hdmatx); 00823 } 00824 00825 /* Disable SAI peripheral */ 00826 __HAL_SAI_DISABLE(hsai); 00827 00828 /* Deactivates CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */ 00829 gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SD_PIN; 00830 HAL_GPIO_DeInit(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, gpio_init_structure.Pin); 00831 00832 gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN; 00833 HAL_GPIO_DeInit(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin); 00834 00835 /* Disable SAI clock */ 00836 AUDIO_OUT_SAIx_CLK_DISABLE(); 00837 00838 /* GPIO pins clock and DMA clock can be shut down in the applic 00839 by surcharging this __weak function */ 00840 } 00841 00842 /** 00843 * @brief Clock Config. 00844 * @param hsai: might be required to set audio peripheral predivider if any. 00845 * @param AudioFreq: Audio frequency used to play the audio stream. 00846 * @param Params 00847 * @note This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency() 00848 * Being __weak it can be overwritten by the application 00849 * @retval None 00850 */ 00851 __weak void BSP_AUDIO_OUT_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params) 00852 { 00853 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 00854 00855 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 00856 00857 /* Set the PLL configuration according to the audio frequency */ 00858 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 00859 { 00860 /* Configure PLLSAI prescalers */ 00861 /* PLLSAI_VCO: VCO_429M 00862 SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 429/2 = 214.5 Mhz 00863 SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 214.5/19 = 11.289 Mhz */ 00864 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 00865 rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLI2S; 00866 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429; 00867 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2; 00868 rcc_ex_clk_init_struct.PLLI2SDivQ = 19; 00869 00870 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00871 00872 } 00873 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 00874 { 00875 /* SAI clock config 00876 PLLSAI_VCO: VCO_344M 00877 SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 344/7 = 49.142 Mhz 00878 SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 49.142/1 = 49.142 Mhz */ 00879 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 00880 rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLI2S; 00881 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 00882 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 00883 rcc_ex_clk_init_struct.PLLI2SDivQ = 1; 00884 00885 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00886 } 00887 } 00888 00889 /******************************************************************************* 00890 Static Functions 00891 *******************************************************************************/ 00892 00893 /** 00894 * @brief Initializes the Audio Codec audio interface (SAI). 00895 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00896 * @note The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 00897 * and user can update this configuration using 00898 * @retval None 00899 */ 00900 static void SAIx_Out_Init(uint32_t AudioFreq) 00901 { 00902 /* Initialize the haudio_out_sai Instance parameter */ 00903 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00904 00905 /* Disable SAI peripheral to allow access to SAI internal registers */ 00906 __HAL_SAI_DISABLE(&haudio_out_sai); 00907 00908 /* Configure SAI_Block_x 00909 LSBFirst: Disabled 00910 DataSize: 16 */ 00911 haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE; 00912 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00913 haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX; 00914 haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED; 00915 haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL; 00916 haudio_out_sai.Init.DataSize = SAI_DATASIZE_16; 00917 haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 00918 haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 00919 haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS; 00920 haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLED; 00921 haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 00922 haudio_out_sai.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 00923 haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING; 00924 haudio_out_sai.Init.TriState = SAI_OUTPUT_NOTRELEASED; 00925 haudio_out_sai.Init.Mckdiv = 0; 00926 00927 /* Configure SAI_Block_x Frame 00928 Frame Length: 64 00929 Frame active Length: 32 00930 FS Definition: Start frame + Channel Side identification 00931 FS Polarity: FS active Low 00932 FS Offset: FS asserted one bit before the first bit of slot 0 */ 00933 haudio_out_sai.FrameInit.FrameLength = 128; 00934 haudio_out_sai.FrameInit.ActiveFrameLength = 64; 00935 haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 00936 haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 00937 haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 00938 00939 /* Configure SAI Block_x Slot 00940 Slot First Bit Offset: 0 00941 Slot Size : 16 00942 Slot Number: 4 00943 Slot Active: All slot actives */ 00944 haudio_out_sai.SlotInit.FirstBitOffset = 0; 00945 haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 00946 haudio_out_sai.SlotInit.SlotNumber = 4; 00947 haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123; 00948 00949 HAL_SAI_Init(&haudio_out_sai); 00950 00951 /* Enable SAI peripheral to generate MCLK */ 00952 __HAL_SAI_ENABLE(&haudio_out_sai); 00953 } 00954 00955 /** 00956 * @brief Deinitializes the Audio Codec audio interface (SAI). 00957 * @retval None 00958 */ 00959 static void SAIx_Out_DeInit(void) 00960 { 00961 /* Initialize the haudio_out_sai Instance parameter */ 00962 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00963 00964 /* Disable SAI peripheral */ 00965 __HAL_SAI_DISABLE(&haudio_out_sai); 00966 00967 HAL_SAI_DeInit(&haudio_out_sai); 00968 } 00969 00970 /** 00971 * @brief Initializes the Audio Codec audio interface (SAI). 00972 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00973 * @note The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 00974 * and user can update this configuration using 00975 * @retval None 00976 */ 00977 static void SAIx_In_Init(uint32_t AudioFreq) 00978 { 00979 /* Initialize SAI1 block A in MASTER TX */ 00980 /* Initialize the haudio_out_sai Instance parameter */ 00981 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 00982 00983 /* Disable SAI peripheral to allow access to SAI internal registers */ 00984 __HAL_SAI_DISABLE(&haudio_out_sai); 00985 00986 /* Configure SAI_Block_x 00987 LSBFirst: Disabled 00988 DataSize: 16 */ 00989 haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE; 00990 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00991 haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_RX; 00992 haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; 00993 haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL; 00994 haudio_out_sai.Init.DataSize = SAI_DATASIZE_16; 00995 haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 00996 haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; 00997 haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS; 00998 haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE; 00999 haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 01000 haudio_out_sai.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 01001 haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING; 01002 haudio_out_sai.Init.TriState = SAI_OUTPUT_NOTRELEASED; 01003 haudio_out_sai.Init.Mckdiv = 0; 01004 01005 /* Configure SAI_Block_x Frame 01006 Frame Length: 64 01007 Frame active Length: 32 01008 FS Definition: Start frame + Channel Side identification 01009 FS Polarity: FS active Low 01010 FS Offset: FS asserted one bit before the first bit of slot 0 */ 01011 haudio_out_sai.FrameInit.FrameLength = 64; 01012 haudio_out_sai.FrameInit.ActiveFrameLength = 32; 01013 haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 01014 haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 01015 haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 01016 01017 /* Configure SAI Block_x Slot 01018 Slot First Bit Offset: 0 01019 Slot Size : 16 01020 Slot Number: 4 01021 Slot Active: All slot actives */ 01022 haudio_out_sai.SlotInit.FirstBitOffset = 0; 01023 haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 01024 haudio_out_sai.SlotInit.SlotNumber = 4; 01025 haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_02; 01026 01027 HAL_SAI_Init(&haudio_out_sai); 01028 01029 /* Initialize SAI1 block B in SLAVE RX synchronous from SAI1 block A */ 01030 /* Initialize the haudio_in_sai Instance parameter */ 01031 haudio_in_sai.Instance = AUDIO_IN_SAIx; 01032 01033 /* Disable SAI peripheral to allow access to SAI internal registers */ 01034 __HAL_SAI_DISABLE(&haudio_in_sai); 01035 01036 /* Configure SAI_Block_x 01037 LSBFirst: Disabled 01038 DataSize: 16 */ 01039 haudio_in_sai.Init.MonoStereoMode = SAI_STEREOMODE; 01040 haudio_in_sai.Init.AudioFrequency = AudioFreq; 01041 haudio_in_sai.Init.AudioMode = SAI_MODESLAVE_RX; 01042 haudio_in_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; 01043 haudio_in_sai.Init.Protocol = SAI_FREE_PROTOCOL; 01044 haudio_in_sai.Init.DataSize = SAI_DATASIZE_16; 01045 haudio_in_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 01046 haudio_in_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 01047 haudio_in_sai.Init.Synchro = SAI_SYNCHRONOUS; 01048 haudio_in_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE; 01049 haudio_in_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 01050 haudio_in_sai.Init.SynchroExt = SAI_SYNCEXT_DISABLE; 01051 haudio_in_sai.Init.CompandingMode = SAI_NOCOMPANDING; 01052 haudio_in_sai.Init.TriState = SAI_OUTPUT_RELEASED; 01053 haudio_in_sai.Init.Mckdiv = 0; 01054 01055 /* Configure SAI_Block_x Frame 01056 Frame Length: 64 01057 Frame active Length: 32 01058 FS Definition: Start frame + Channel Side identification 01059 FS Polarity: FS active Low 01060 FS Offset: FS asserted one bit before the first bit of slot 0 */ 01061 haudio_in_sai.FrameInit.FrameLength = 64; 01062 haudio_in_sai.FrameInit.ActiveFrameLength = 32; 01063 haudio_in_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 01064 haudio_in_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 01065 haudio_in_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 01066 01067 /* Configure SAI Block_x Slot 01068 Slot First Bit Offset: 0 01069 Slot Size : 16 01070 Slot Number: 4 01071 Slot Active: All slot active */ 01072 haudio_in_sai.SlotInit.FirstBitOffset = 0; 01073 haudio_in_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 01074 haudio_in_sai.SlotInit.SlotNumber = 4; 01075 haudio_in_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_02; 01076 01077 HAL_SAI_Init(&haudio_in_sai); 01078 01079 /* Enable SAI peripheral */ 01080 __HAL_SAI_ENABLE(&haudio_in_sai); 01081 01082 /* Enable SAI peripheral to generate MCLK */ 01083 __HAL_SAI_ENABLE(&haudio_out_sai); 01084 } 01085 01086 /** 01087 * @brief Deinitializes the output Audio Codec audio interface (SAI). 01088 * @retval None 01089 */ 01090 static void SAIx_In_DeInit(void) 01091 { 01092 /* Initialize the haudio_in_sai Instance parameter */ 01093 haudio_in_sai.Instance = AUDIO_IN_SAIx; 01094 haudio_out_sai.Instance = AUDIO_OUT_SAIx; 01095 /* Disable SAI peripheral */ 01096 __HAL_SAI_DISABLE(&haudio_in_sai); 01097 01098 HAL_SAI_DeInit(&haudio_in_sai); 01099 HAL_SAI_DeInit(&haudio_out_sai); 01100 } 01101 01102 /** 01103 * @} 01104 */ 01105 01106 /** @defgroup STM32F769I_DISCOVERY_AUDIO_In_Private_Functions STM32F769I_DISCOVERY_AUDIO_In Private Functions 01107 * @{ 01108 */ 01109 01110 /** 01111 * @brief Initialize wave recording. 01112 * @param AudioFreq: Audio frequency to be configured for the DFSDM peripheral. 01113 * @param BitRes: Audio frequency to be configured for the DFSDM peripheral. 01114 * @param ChnlNbr: Audio frequency to be configured for the DFSDM peripheral. 01115 * @retval AUDIO_OK if correct communication, else wrong communication 01116 */ 01117 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 01118 { 01119 return BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC, AudioFreq, BitRes, ChnlNbr); 01120 } 01121 01122 /** 01123 * @brief Initialize wave recording. 01124 * @param InputDevice: INPUT_DEVICE_DIGITAL_MIC or INPUT_DEVICE_ANALOG_MIC. 01125 * @param AudioFreq: Audio frequency to be configured. 01126 * @param BitRes: Audio bit resolution to be configured.. 01127 * @param ChnlNbr: Number of channel to be configured. 01128 * @retval AUDIO_OK if correct communication, else wrong communication 01129 */ 01130 uint8_t BSP_AUDIO_IN_InitEx(uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 01131 { 01132 uint8_t ret = AUDIO_ERROR; 01133 AudioIn_Device = InputDevice; 01134 01135 if(InputDevice == INPUT_DEVICE_DIGITAL_MIC) 01136 { 01137 AudioIn_ChannelNumber = ChnlNbr; 01138 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 01139 BSP_AUDIO_IN_ClockConfig(&hAudioInTopLeftFilter, AudioFreq, NULL); 01140 01141 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 01142 BSP_AUDIO_IN_MspInit(); 01143 01144 /* Initializes DFSDM peripheral */ 01145 DFSDMx_Init(AudioFreq); 01146 ret = AUDIO_OK; 01147 } 01148 else 01149 { 01150 /* Disable SAI */ 01151 SAIx_In_DeInit(); 01152 01153 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 01154 BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL); 01155 01156 haudio_in_sai.Instance = AUDIO_IN_SAIx; 01157 if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET) 01158 { 01159 BSP_AUDIO_OUT_MspInit(&haudio_in_sai, NULL); 01160 BSP_AUDIO_IN_MspInit(); 01161 } 01162 01163 SAIx_In_Init(AudioFreq); 01164 01165 if((wm8994_drv.ReadID(AUDIO_I2C_ADDRESS)) == WM8994_ID) 01166 { 01167 /* Reset the Codec Registers */ 01168 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 01169 /* Initialize the audio driver structure */ 01170 audio_drv = &wm8994_drv; 01171 ret = AUDIO_OK; 01172 } 01173 else 01174 { 01175 ret = AUDIO_ERROR; 01176 } 01177 01178 if(ret == AUDIO_OK) 01179 { 01180 /* Initialize the codec internal registers */ 01181 audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice, 100, AudioFreq); 01182 } 01183 } 01184 01185 /* Return AUDIO_OK when all operations are correctly done */ 01186 return ret; 01187 } 01188 01189 /** 01190 * @brief Allocate channel buffer scratch 01191 * @param pScratch : pointer to scratch tables. 01192 * @param size of scratch buffer 01193 */ 01194 uint8_t BSP_AUDIO_IN_AllocScratch (int32_t *pScratch, uint32_t size) 01195 { 01196 uint32_t idx; 01197 01198 ScratchSize = (size / AudioIn_ChannelNumber); 01199 01200 /* copy scratch pointers */ 01201 for (idx = 0; idx < AudioIn_ChannelNumber; idx++) 01202 { 01203 pScratchBuff[idx] = (int32_t *)(pScratch + (idx * ScratchSize)); 01204 } 01205 /* Return AUDIO_OK */ 01206 return AUDIO_OK; 01207 } 01208 01209 /** 01210 * @brief Return audio in channel number 01211 * @retval Number of channel 01212 */ 01213 uint8_t BSP_AUDIO_IN_GetChannelNumber(void) 01214 { 01215 return AudioIn_ChannelNumber; 01216 } 01217 01218 /** 01219 * @brief Start audio recording. 01220 * @param pbuf: Main buffer pointer for the recorded data storing 01221 * @param size: Current size of the recorded buffer 01222 * @retval AUDIO_OK if correct communication, else wrong communication 01223 */ 01224 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size) 01225 { 01226 if (AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC) 01227 { 01228 hAudioIn.pRecBuf = pbuf; 01229 hAudioIn.RecSize = size; 01230 /* Reset Application Buffer Trigger */ 01231 AppBuffTrigger = 0; 01232 AppBuffHalf = 0; 01233 01234 if(AudioIn_ChannelNumber > 2) 01235 { 01236 /* Call the Media layer start function for buttom right channel */ 01237 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInButtomRightFilter, pScratchBuff[2], ScratchSize)) 01238 { 01239 return AUDIO_ERROR; 01240 } 01241 01242 /* Call the Media layer start function for buttom left channel */ 01243 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInButtomLeftFilter, pScratchBuff[3], ScratchSize)) 01244 { 01245 return AUDIO_ERROR; 01246 } 01247 } 01248 01249 /* Call the Media layer start function for top right channel */ 01250 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInTopRightFilter, pScratchBuff[0], ScratchSize)) 01251 { 01252 return AUDIO_ERROR; 01253 } 01254 01255 /* Call the Media layer start function for top left channel */ 01256 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInTopLeftFilter, pScratchBuff[1], ScratchSize)) 01257 { 01258 return AUDIO_ERROR; 01259 } 01260 } 01261 else 01262 { 01263 /* Start the process receive DMA */ 01264 if(HAL_OK !=HAL_SAI_Receive_DMA(&haudio_in_sai, (uint8_t*)pbuf, size)) 01265 { 01266 return AUDIO_ERROR; 01267 } 01268 } 01269 /* Return AUDIO_OK when all operations are correctly done */ 01270 return AUDIO_OK; 01271 } 01272 01273 /** 01274 * @brief Stop audio recording. 01275 * @retval AUDIO_OK if correct communication, else wrong communication 01276 */ 01277 uint8_t BSP_AUDIO_IN_Stop(void) 01278 { 01279 if (AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC) 01280 { 01281 AppBuffTrigger = 0; 01282 AppBuffHalf = 0; 01283 01284 if(AudioIn_ChannelNumber > 2) 01285 { 01286 /* Call the Media layer stop function for buttom right channel */ 01287 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInButtomRightFilter)) 01288 { 01289 return AUDIO_ERROR; 01290 } 01291 01292 /* Call the Media layer stop function for buttom left channel */ 01293 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInButtomLeftFilter)) 01294 { 01295 return AUDIO_ERROR; 01296 } 01297 } 01298 01299 /* Call the Media layer stop function for top right channel */ 01300 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInTopRightFilter)) 01301 { 01302 return AUDIO_ERROR; 01303 } 01304 01305 /* Call the Media layer stop function for top left channel */ 01306 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInTopLeftFilter)) 01307 { 01308 return AUDIO_ERROR; 01309 } 01310 } 01311 else 01312 { 01313 /* Call the Media layer stop function */ 01314 HAL_SAI_DMAStop(&haudio_in_sai); 01315 01316 /* Call Audio Codec Stop function */ 01317 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, CODEC_PDWN_HW) != 0) 01318 { 01319 return AUDIO_ERROR; 01320 } 01321 else 01322 { 01323 /* Wait at least 100us */ 01324 HAL_Delay(1); 01325 01326 /* Return AUDIO_OK when all operations are correctly done */ 01327 return AUDIO_OK; 01328 } 01329 } 01330 /* Return AUDIO_OK when all operations are correctly done */ 01331 return AUDIO_OK; 01332 } 01333 01334 /** 01335 * @brief Pause the audio file stream. 01336 * @retval AUDIO_OK if correct communication, else wrong communication 01337 */ 01338 uint8_t BSP_AUDIO_IN_Pause(void) 01339 { 01340 if(AudioIn_ChannelNumber > 2) 01341 { 01342 /* Call the Media layer stop function */ 01343 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInButtomRightFilter)) 01344 { 01345 return AUDIO_ERROR; 01346 } 01347 01348 /* Call the Media layer stop function */ 01349 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInButtomLeftFilter)) 01350 { 01351 return AUDIO_ERROR; 01352 } 01353 } 01354 /* Call the Media layer stop function */ 01355 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInTopRightFilter)) 01356 { 01357 return AUDIO_ERROR; 01358 } 01359 01360 /* Call the Media layer stop function */ 01361 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInTopLeftFilter)) 01362 { 01363 return AUDIO_ERROR; 01364 } 01365 01366 /* Return AUDIO_OK when all operations are correctly done */ 01367 return AUDIO_OK; 01368 } 01369 01370 /** 01371 * @brief Resume the audio file stream. 01372 * @retval AUDIO_OK if correct communication, else wrong communication 01373 */ 01374 uint8_t BSP_AUDIO_IN_Resume(void) 01375 { 01376 if(AudioIn_ChannelNumber > 2) 01377 { 01378 /* Call the Media layer start function for buttom right channel */ 01379 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInButtomRightFilter, pScratchBuff[2], ScratchSize)) 01380 { 01381 return AUDIO_ERROR; 01382 } 01383 01384 /* Call the Media layer start function for buttom left channel */ 01385 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInButtomLeftFilter, pScratchBuff[3], ScratchSize)) 01386 { 01387 return AUDIO_ERROR; 01388 } 01389 } 01390 /* Call the Media layer start function for top right channel */ 01391 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInTopRightFilter, pScratchBuff[0], ScratchSize)) 01392 { 01393 return AUDIO_ERROR; 01394 } 01395 01396 /* Call the Media layer start function for top left channel */ 01397 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInTopLeftFilter, pScratchBuff[1], ScratchSize)) 01398 { 01399 return AUDIO_ERROR; 01400 } 01401 01402 /* Return AUDIO_OK when all operations are correctly done */ 01403 return AUDIO_OK; 01404 } 01405 01406 /** 01407 * @brief Deinit the audio IN peripherals. 01408 * @retval None 01409 */ 01410 void BSP_AUDIO_IN_DeInit(void) 01411 { 01412 BSP_AUDIO_IN_MspDeInit(); 01413 01414 if(AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC) 01415 { 01416 DFSDMx_DeInit(); 01417 } 01418 else 01419 { 01420 SAIx_In_DeInit(); 01421 } 01422 } 01423 01424 /** 01425 * @brief Regular conversion complete callback. 01426 * @note In interrupt mode, user has to read conversion value in this function 01427 using HAL_DFSDM_FilterGetRegularValue. 01428 * @param hdfsdm_filter : DFSDM filter handle. 01429 * @retval None 01430 */ 01431 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01432 { 01433 uint32_t index = 0; 01434 01435 if(hdfsdm_filter == &hAudioInTopLeftFilter) 01436 { 01437 DmaTopLeftRecCplt = 1; 01438 } 01439 else if(hdfsdm_filter == &hAudioInTopRightFilter) 01440 { 01441 DmaTopRightRecCplt = 1; 01442 } 01443 else if(hdfsdm_filter == &hAudioInButtomLeftFilter) 01444 { 01445 DmaButtomLeftRecCplt = 1; 01446 } 01447 else 01448 { 01449 DmaButtomRightRecCplt = 1; 01450 } 01451 01452 if(AudioIn_ChannelNumber > 2) 01453 { 01454 if((DmaTopLeftRecCplt == 1) && (DmaTopRightRecCplt == 1) && (DmaButtomLeftRecCplt == 1) && (DmaButtomRightRecCplt == 1)) 01455 { 01456 for(index = (ScratchSize/2) ; index < ScratchSize; index++) 01457 { 01458 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760)); 01459 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760)); 01460 hAudioIn.pRecBuf[AppBuffTrigger + 2] = (uint16_t)(SaturaLH((pScratchBuff[3][index] >> 8), -32760, 32760)); 01461 hAudioIn.pRecBuf[AppBuffTrigger + 3] = (uint16_t)(SaturaLH((pScratchBuff[2][index] >> 8), -32760, 32760)); 01462 AppBuffTrigger +=4; 01463 } 01464 DmaTopLeftRecCplt = 0; 01465 DmaTopRightRecCplt = 0; 01466 DmaButtomLeftRecCplt = 0; 01467 DmaButtomRightRecCplt = 0; 01468 } 01469 } 01470 else 01471 { 01472 if((DmaTopLeftRecCplt == 1) && (DmaTopRightRecCplt == 1)) 01473 { 01474 for(index = (ScratchSize/2) ; index < ScratchSize; index++) 01475 { 01476 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760)); 01477 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760)); 01478 AppBuffTrigger +=2; 01479 } 01480 DmaTopLeftRecCplt = 0; 01481 DmaTopRightRecCplt = 0; 01482 } 01483 } 01484 01485 /* Call Half Transfer Complete callback */ 01486 if((AppBuffTrigger == hAudioIn.RecSize/2) && (AppBuffHalf == 0)) 01487 { 01488 AppBuffHalf = 1; 01489 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01490 } 01491 /* Call Transfer Complete callback */ 01492 if(AppBuffTrigger == hAudioIn.RecSize) 01493 { 01494 /* Reset Application Buffer Trigger */ 01495 AppBuffTrigger = 0; 01496 AppBuffHalf = 0; 01497 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01498 BSP_AUDIO_IN_TransferComplete_CallBack(); 01499 } 01500 } 01501 01502 /** 01503 * @brief Half regular conversion complete callback. 01504 * @param hdfsdm_filter : DFSDM filter handle. 01505 * @retval None 01506 */ 01507 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01508 { 01509 uint32_t index = 0; 01510 01511 if(hdfsdm_filter == &hAudioInTopLeftFilter) 01512 { 01513 DmaTopLeftRecHalfCplt = 1; 01514 } 01515 else if(hdfsdm_filter == &hAudioInTopRightFilter) 01516 { 01517 DmaTopRightRecHalfCplt = 1; 01518 } 01519 else if(hdfsdm_filter == &hAudioInButtomLeftFilter) 01520 { 01521 DmaButtomLeftRecHalfCplt = 1; 01522 } 01523 else 01524 { 01525 DmaButtomRightRecHalfCplt = 1; 01526 } 01527 01528 if(AudioIn_ChannelNumber > 2) 01529 { 01530 if((DmaTopLeftRecHalfCplt == 1) && (DmaTopRightRecHalfCplt == 1) && (DmaButtomLeftRecHalfCplt == 1) && (DmaButtomRightRecHalfCplt == 1)) 01531 { 01532 for(index = 0 ; index < ScratchSize/2; index++) 01533 { 01534 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760)); 01535 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760)); 01536 hAudioIn.pRecBuf[AppBuffTrigger + 2] = (uint16_t)(SaturaLH((pScratchBuff[3][index] >> 8), -32760, 32760)); 01537 hAudioIn.pRecBuf[AppBuffTrigger + 3] = (uint16_t)(SaturaLH((pScratchBuff[2][index] >> 8), -32760, 32760)); 01538 AppBuffTrigger +=4; 01539 } 01540 DmaTopLeftRecHalfCplt = 0; 01541 DmaTopRightRecHalfCplt = 0; 01542 DmaButtomLeftRecHalfCplt = 0; 01543 DmaButtomRightRecHalfCplt = 0; 01544 } 01545 } 01546 else 01547 { 01548 if((DmaTopLeftRecHalfCplt == 1) && (DmaTopRightRecHalfCplt == 1)) 01549 { 01550 for(index = 0 ; index < ScratchSize/2; index++) 01551 { 01552 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760)); 01553 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760)); 01554 AppBuffTrigger +=2; 01555 } 01556 DmaTopLeftRecHalfCplt = 0; 01557 DmaTopRightRecHalfCplt = 0; 01558 } 01559 } 01560 01561 /* Call Half Transfer Complete callback */ 01562 if((AppBuffTrigger == hAudioIn.RecSize/2) && (AppBuffHalf == 0)) 01563 { 01564 AppBuffHalf = 1; 01565 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01566 } 01567 /* Call Transfer Complete callback */ 01568 if(AppBuffTrigger == hAudioIn.RecSize) 01569 { 01570 /* Reset Application Buffer Trigger */ 01571 AppBuffTrigger = 0; 01572 AppBuffHalf = 0; 01573 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01574 BSP_AUDIO_IN_TransferComplete_CallBack(); 01575 } 01576 } 01577 01578 /** 01579 * @brief Half reception complete callback. 01580 * @param hsai : SAI handle. 01581 * @retval None 01582 */ 01583 void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai) 01584 { 01585 /* Manage the remaining file size and new address offset: This function 01586 should be coded by user (its prototype is already declared in stm32769i_discovery_audio.h) */ 01587 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01588 } 01589 01590 /** 01591 * @brief Reception complete callback. 01592 * @param hsai : SAI handle. 01593 * @retval None 01594 */ 01595 void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai) 01596 { 01597 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01598 BSP_AUDIO_IN_TransferComplete_CallBack(); 01599 } 01600 01601 /** 01602 * @brief User callback when record buffer is filled. 01603 * @retval None 01604 */ 01605 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void) 01606 { 01607 /* This function should be implemented by the user application. 01608 It is called into this driver when the current buffer is filled 01609 to prepare the next buffer pointer and its size. */ 01610 } 01611 01612 /** 01613 * @brief Manages the DMA Half Transfer complete event. 01614 * @retval None 01615 */ 01616 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 01617 { 01618 /* This function should be implemented by the user application. 01619 It is called into this driver when the current buffer is filled 01620 to prepare the next buffer pointer and its size. */ 01621 } 01622 01623 /** 01624 * @brief Audio IN Error callback function. 01625 * @retval None 01626 */ 01627 __weak void BSP_AUDIO_IN_Error_CallBack(void) 01628 { 01629 /* This function is called when an Interrupt due to transfer error on or peripheral 01630 error occurs. */ 01631 } 01632 01633 /** 01634 * @brief Initialize BSP_AUDIO_IN MSP. 01635 * @retval None 01636 */ 01637 __weak void BSP_AUDIO_IN_MspInit(void) 01638 { 01639 if (AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC) 01640 { 01641 /* MSP channels initialization */ 01642 DFSDMx_ChannelMspInit(); 01643 /* MSP filters initialization */ 01644 DFSDMx_FilterMspInit(); 01645 } 01646 else 01647 { 01648 SAI_AUDIO_IN_MspInit(&haudio_in_sai, NULL); 01649 } 01650 } 01651 01652 /** 01653 * @brief DeInitialize BSP_AUDIO_IN MSP. 01654 * @retval None 01655 */ 01656 __weak void BSP_AUDIO_IN_MspDeInit(void) 01657 { 01658 if (AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC) 01659 { 01660 /* MSP channels initialization */ 01661 DFSDMx_ChannelMspDeInit(); 01662 /* MSP filters initialization */ 01663 DFSDMx_FilterMspDeInit(); 01664 } 01665 else 01666 { 01667 SAI_AUDIO_IN_MspDeInit(&haudio_in_sai, NULL); 01668 } 01669 } 01670 01671 /** 01672 * @brief Clock Config. 01673 * @param hdfsdm_filter: might be required to set audio peripheral predivider if any. 01674 * @param AudioFreq: Audio frequency used to play the audio stream. 01675 * @param Params 01676 * @note This API is called by BSP_AUDIO_IN_Init() 01677 * Being __weak it can be overwritten by the application 01678 * @retval None 01679 */ 01680 __weak void BSP_AUDIO_IN_ClockConfig(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, uint32_t AudioFreq, void *Params) 01681 { 01682 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 01683 01684 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 01685 01686 /* Set the PLL configuration according to the audio frequency */ 01687 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 01688 { 01689 /* Configure PLLSAI prescalers */ 01690 /* PLLI2S_VCO: VCO_429M 01691 SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 429/2 = 214.5 Mhz 01692 SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 214.5/19 = 11.289 Mhz */ 01693 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 01694 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S; 01695 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429; 01696 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2; 01697 rcc_ex_clk_init_struct.PLLI2SDivQ = 19; 01698 01699 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01700 01701 } 01702 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_32K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 01703 { 01704 /* SAI clock config 01705 PLLI2S_VCO: VCO_344M 01706 SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 344/7 = 49.142 Mhz 01707 SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 49.142/1 = 49.142 Mhz */ 01708 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 01709 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S; 01710 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 01711 rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 01712 rcc_ex_clk_init_struct.PLLI2SDivQ = 1; 01713 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01714 } 01715 01716 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_DFSDM1_AUDIO; 01717 rcc_ex_clk_init_struct.Dfsdm1AudioClockSelection = RCC_DFSDM1AUDIOCLKSOURCE_SAI2; 01718 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 01719 } 01720 01721 /******************************************************************************* 01722 Static Functions 01723 *******************************************************************************/ 01724 /** 01725 * @brief Initialize the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01726 * @param AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral. 01727 * @note Channel output Clock Divider and Filter Oversampling are calculated as follow: 01728 * - Clock_Divider = CLK(input DFSDM)/CLK(micro) with 01729 * 1MHZ < CLK(micro) < 3.2MHZ (TYP 2.4MHZ for MP34DT01TR) 01730 * - Oversampling = CLK(input DFSDM)/(Clock_Divider * AudioFreq) 01731 * @retval AUDIO_OK if correct communication, else wrong communication 01732 */ 01733 static uint8_t DFSDMx_Init(uint32_t AudioFreq) 01734 { 01735 /****************************************************************************/ 01736 /********************** Channels configuration *****************************/ 01737 /****************************************************************************/ 01738 /* CHANNEL 1 configuration */ 01739 __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInTopLeftChannel); 01740 hAudioInTopLeftChannel.Instance = DFSDM1_Channel1; 01741 hAudioInTopLeftChannel.Init.OutputClock.Activation = ENABLE; 01742 hAudioInTopLeftChannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01743 /* Set the DFSDM clock OUT audio frequency configuration */ 01744 hAudioInTopLeftChannel.Init.OutputClock.Divider = DFSDM_CLOCK_DIVIDER(AudioFreq); 01745 hAudioInTopLeftChannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01746 hAudioInTopLeftChannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01747 hAudioInTopLeftChannel.Init.Input.Pins = DFSDM_CHANNEL_SAME_CHANNEL_PINS; 01748 /* Request to sample stable data for LEFT micro on Rising edge */ 01749 hAudioInTopLeftChannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_RISING; 01750 hAudioInTopLeftChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01751 hAudioInTopLeftChannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER; 01752 hAudioInTopLeftChannel.Init.Awd.Oversampling = 10; 01753 hAudioInTopLeftChannel.Init.Offset = 0; 01754 hAudioInTopLeftChannel.Init.RightBitShift = DFSDM_RIGHT_BIT_SHIFT(AudioFreq); 01755 if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInTopLeftChannel)) 01756 { 01757 return AUDIO_ERROR; 01758 } 01759 01760 /* CHANNEL 0 configuration */ 01761 __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInTopRightChannel); 01762 hAudioInTopRightChannel.Instance = DFSDM1_Channel0; 01763 hAudioInTopRightChannel.Init.OutputClock.Activation = ENABLE; 01764 hAudioInTopRightChannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01765 /* Set the DFSDM clock OUT audio frequency configuration */ 01766 hAudioInTopRightChannel.Init.OutputClock.Divider = DFSDM_CLOCK_DIVIDER(AudioFreq); 01767 hAudioInTopRightChannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01768 hAudioInTopRightChannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01769 hAudioInTopRightChannel.Init.Input.Pins = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS; 01770 /* Request to sample stable data for RIGHT micro on Falling edge */ 01771 hAudioInTopRightChannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_FALLING; 01772 hAudioInTopRightChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01773 hAudioInTopRightChannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER; 01774 hAudioInTopRightChannel.Init.Awd.Oversampling = 10; 01775 hAudioInTopRightChannel.Init.Offset = 0; 01776 hAudioInTopRightChannel.Init.RightBitShift = DFSDM_RIGHT_BIT_SHIFT(AudioFreq); 01777 if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInTopRightChannel)) 01778 { 01779 return AUDIO_ERROR; 01780 } 01781 01782 if(AudioIn_ChannelNumber > 2) 01783 { 01784 /* CHANNEL 5 configuration */ 01785 __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInButtomLeftChannel); 01786 hAudioInButtomLeftChannel.Instance = DFSDM1_Channel5; 01787 hAudioInButtomLeftChannel.Init.OutputClock.Activation = ENABLE; 01788 hAudioInButtomLeftChannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01789 /* Set the DFSDM clock OUT audio frequency configuration */ 01790 hAudioInButtomLeftChannel.Init.OutputClock.Divider = DFSDM_CLOCK_DIVIDER(AudioFreq); 01791 hAudioInButtomLeftChannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01792 hAudioInButtomLeftChannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01793 hAudioInButtomLeftChannel.Init.Input.Pins = DFSDM_CHANNEL_SAME_CHANNEL_PINS; 01794 /* Request to sample stable data for LEFT micro on Rising edge */ 01795 hAudioInButtomLeftChannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_RISING; 01796 hAudioInButtomLeftChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01797 hAudioInButtomLeftChannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER; 01798 hAudioInButtomLeftChannel.Init.Awd.Oversampling = 10; 01799 hAudioInButtomLeftChannel.Init.Offset = 0; 01800 hAudioInButtomLeftChannel.Init.RightBitShift = DFSDM_RIGHT_BIT_SHIFT(AudioFreq); 01801 if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInButtomLeftChannel)) 01802 { 01803 return AUDIO_ERROR; 01804 } 01805 01806 /* CHANNEL 4 configuration */ 01807 __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInButtomRightChannel); 01808 hAudioInButtomRightChannel.Instance = DFSDM1_Channel4; 01809 hAudioInButtomRightChannel.Init.OutputClock.Activation = ENABLE; 01810 hAudioInButtomRightChannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01811 /* Set the DFSDM clock OUT audio frequency configuration */ 01812 hAudioInButtomRightChannel.Init.OutputClock.Divider = DFSDM_CLOCK_DIVIDER(AudioFreq); 01813 hAudioInButtomRightChannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01814 hAudioInButtomRightChannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01815 hAudioInButtomRightChannel.Init.Input.Pins = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS; 01816 /* Request to sample stable data for RIGHT micro on Falling edge */ 01817 hAudioInButtomRightChannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_FALLING; 01818 hAudioInButtomRightChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01819 hAudioInButtomRightChannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER; 01820 hAudioInButtomRightChannel.Init.Awd.Oversampling = 10; 01821 hAudioInButtomRightChannel.Init.Offset = 0; 01822 hAudioInButtomRightChannel.Init.RightBitShift = DFSDM_RIGHT_BIT_SHIFT(AudioFreq); 01823 if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInButtomRightChannel)) 01824 { 01825 return AUDIO_ERROR; 01826 } 01827 } 01828 /****************************************************************************/ 01829 /********************** Filters configuration ******************************/ 01830 /****************************************************************************/ 01831 01832 /* FILTER 0 configuration */ 01833 __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInTopLeftFilter); 01834 hAudioInTopLeftFilter.Instance = AUDIO_DFSDMx_TOP_LEFT_FILTER; 01835 hAudioInTopLeftFilter.Init.RegularParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01836 hAudioInTopLeftFilter.Init.RegularParam.FastMode = ENABLE; 01837 hAudioInTopLeftFilter.Init.RegularParam.DmaMode = ENABLE; 01838 hAudioInTopLeftFilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01839 hAudioInTopLeftFilter.Init.InjectedParam.ScanMode = ENABLE; 01840 hAudioInTopLeftFilter.Init.InjectedParam.DmaMode = DISABLE; 01841 hAudioInTopLeftFilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO; 01842 hAudioInTopLeftFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE; 01843 hAudioInTopLeftFilter.Init.FilterParam.SincOrder = DFSDM_FILTER_ORDER(AudioFreq); 01844 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01845 hAudioInTopLeftFilter.Init.FilterParam.Oversampling = DFSDM_OVER_SAMPLING(AudioFreq); 01846 hAudioInTopLeftFilter.Init.FilterParam.IntOversampling = 1; 01847 if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInTopLeftFilter)) 01848 { 01849 return AUDIO_ERROR; 01850 } 01851 01852 /* Configure injected channel */ 01853 if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInTopLeftFilter, AUDIO_DFSDMx_TOP_LEFT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON)) 01854 { 01855 return AUDIO_ERROR; 01856 } 01857 01858 /* FILTER 1 configuration */ 01859 __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInTopRightFilter); 01860 hAudioInTopRightFilter.Instance = AUDIO_DFSDMx_TOP_RIGHT_FILTER; 01861 hAudioInTopRightFilter.Init.RegularParam.Trigger = DFSDM_FILTER_SYNC_TRIGGER; 01862 hAudioInTopRightFilter.Init.RegularParam.FastMode = ENABLE; 01863 hAudioInTopRightFilter.Init.RegularParam.DmaMode = ENABLE; 01864 hAudioInTopRightFilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01865 hAudioInTopRightFilter.Init.InjectedParam.ScanMode = DISABLE; 01866 hAudioInTopRightFilter.Init.InjectedParam.DmaMode = DISABLE; 01867 hAudioInTopRightFilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO; 01868 hAudioInTopRightFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE; 01869 hAudioInTopRightFilter.Init.FilterParam.SincOrder = DFSDM_FILTER_ORDER(AudioFreq); 01870 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01871 hAudioInTopRightFilter.Init.FilterParam.Oversampling = DFSDM_OVER_SAMPLING(AudioFreq); 01872 hAudioInTopRightFilter.Init.FilterParam.IntOversampling = 1; 01873 if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInTopRightFilter)) 01874 { 01875 return AUDIO_ERROR; 01876 } 01877 /* Configure injected channel */ 01878 if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInTopRightFilter, AUDIO_DFSDMx_TOP_RIGHT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON)) 01879 { 01880 return AUDIO_ERROR; 01881 } 01882 01883 if(AudioIn_ChannelNumber > 2) 01884 { 01885 /* FILTER 2 configuration */ 01886 __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInButtomLeftFilter); 01887 hAudioInButtomLeftFilter.Instance = AUDIO_DFSDMx_BUTTOM_LEFT_FILTER; 01888 hAudioInButtomLeftFilter.Init.RegularParam.Trigger = DFSDM_FILTER_SYNC_TRIGGER; 01889 hAudioInButtomLeftFilter.Init.RegularParam.FastMode = ENABLE; 01890 hAudioInButtomLeftFilter.Init.RegularParam.DmaMode = ENABLE; 01891 hAudioInButtomLeftFilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01892 hAudioInButtomLeftFilter.Init.InjectedParam.ScanMode = ENABLE; 01893 hAudioInButtomLeftFilter.Init.InjectedParam.DmaMode = DISABLE; 01894 hAudioInButtomLeftFilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO; 01895 hAudioInButtomLeftFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE; 01896 hAudioInButtomLeftFilter.Init.FilterParam.SincOrder = DFSDM_FILTER_ORDER(AudioFreq); 01897 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01898 hAudioInButtomLeftFilter.Init.FilterParam.Oversampling = DFSDM_OVER_SAMPLING(AudioFreq); 01899 hAudioInButtomLeftFilter.Init.FilterParam.IntOversampling = 1; 01900 if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInButtomLeftFilter)) 01901 { 01902 return AUDIO_ERROR; 01903 } 01904 01905 /* Configure injected channel */ 01906 if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInButtomLeftFilter, AUDIO_DFSDMx_BUTTOM_LEFT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON)) 01907 { 01908 return AUDIO_ERROR; 01909 } 01910 01911 /* FILTER 3 configuration */ 01912 __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInButtomRightFilter); 01913 hAudioInButtomRightFilter.Instance = AUDIO_DFSDMx_BUTTOM_RIGHT_FILTER; 01914 hAudioInButtomRightFilter.Init.RegularParam.Trigger = DFSDM_FILTER_SYNC_TRIGGER; 01915 hAudioInButtomRightFilter.Init.RegularParam.FastMode = ENABLE; 01916 hAudioInButtomRightFilter.Init.RegularParam.DmaMode = ENABLE; 01917 hAudioInButtomRightFilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01918 hAudioInButtomRightFilter.Init.InjectedParam.ScanMode = DISABLE; 01919 hAudioInButtomRightFilter.Init.InjectedParam.DmaMode = DISABLE; 01920 hAudioInButtomRightFilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO; 01921 hAudioInButtomRightFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE; 01922 hAudioInButtomRightFilter.Init.FilterParam.SincOrder = DFSDM_FILTER_ORDER(AudioFreq); 01923 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01924 hAudioInButtomRightFilter.Init.FilterParam.Oversampling = DFSDM_OVER_SAMPLING(AudioFreq); 01925 hAudioInButtomRightFilter.Init.FilterParam.IntOversampling = 1; 01926 if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInButtomRightFilter)) 01927 { 01928 return AUDIO_ERROR; 01929 } 01930 /* Configure injected channel */ 01931 if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInButtomRightFilter, AUDIO_DFSDMx_BUTTOM_RIGHT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON)) 01932 { 01933 return AUDIO_ERROR; 01934 } 01935 } 01936 return AUDIO_OK; 01937 } 01938 01939 /** 01940 * @brief De-initialize the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01941 * @retval AUDIO_OK if correct communication, else wrong communication 01942 */ 01943 static uint8_t DFSDMx_DeInit(void) 01944 { 01945 /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */ 01946 if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInTopLeftFilter)) 01947 { 01948 return AUDIO_ERROR; 01949 } 01950 01951 if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInTopRightFilter)) 01952 { 01953 return AUDIO_ERROR; 01954 } 01955 01956 /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */ 01957 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInTopLeftChannel)) 01958 { 01959 return AUDIO_ERROR; 01960 } 01961 01962 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInTopRightChannel)) 01963 { 01964 return AUDIO_ERROR; 01965 } 01966 01967 if(AudioIn_ChannelNumber > 2) 01968 { 01969 /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */ 01970 if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInButtomLeftFilter)) 01971 { 01972 return AUDIO_ERROR; 01973 } 01974 01975 if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInButtomRightFilter)) 01976 { 01977 return AUDIO_ERROR; 01978 } 01979 01980 /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */ 01981 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInButtomLeftChannel)) 01982 { 01983 return AUDIO_ERROR; 01984 } 01985 01986 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInButtomRightChannel)) 01987 { 01988 return AUDIO_ERROR; 01989 } 01990 } 01991 01992 return AUDIO_OK; 01993 } 01994 01995 /** 01996 * @brief Initialize the DFSDM channel MSP. 01997 * @retval None 01998 */ 01999 static void DFSDMx_ChannelMspInit(void) 02000 { 02001 GPIO_InitTypeDef GPIO_InitStruct; 02002 02003 /* Enable DFSDM clock */ 02004 AUDIO_DFSDMx_CLK_ENABLE(); 02005 02006 /* Enable GPIO clock */ 02007 AUDIO_DFSDMx_DMIC_DATIN_GPIO_CLK_ENABLE(); 02008 AUDIO_DFSDMx_CKOUT_DMIC_GPIO_CLK_ENABLE(); 02009 02010 /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN1 pins ------------------*/ 02011 GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN; 02012 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 02013 GPIO_InitStruct.Pull = GPIO_NOPULL; 02014 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 02015 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_CKOUT_AF; 02016 HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT, &GPIO_InitStruct); 02017 02018 /* DFSDM pin configuration: DMIC_DATIN1 pin --------------------------------*/ 02019 GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_DATIN1_PIN; 02020 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_DMIC_DATIN_AF; 02021 HAL_GPIO_Init(AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct); 02022 02023 if(AudioIn_ChannelNumber > 2) 02024 { 02025 /* DFSDM pin configuration: DMIC_DATIN5 pin --------------------------------*/ 02026 GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_DATIN5_PIN; 02027 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_DMIC_DATIN_AF; 02028 HAL_GPIO_Init(AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct); 02029 } 02030 } 02031 02032 /** 02033 * @brief DeInitialize the DFSDM channel MSP. 02034 * @retval None 02035 */ 02036 static void DFSDMx_ChannelMspDeInit(void) 02037 { 02038 GPIO_InitTypeDef GPIO_InitStruct; 02039 02040 /* DFSDM pin configuration: DMIC_DATIN1 pin --------------------------------*/ 02041 GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN; 02042 HAL_GPIO_DeInit(AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 02043 GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_DATIN1_PIN; 02044 HAL_GPIO_DeInit(AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, GPIO_InitStruct.Pin); 02045 02046 if(AudioIn_ChannelNumber > 2) 02047 { 02048 /* DFSDM pin configuration: DMIC_DATIN5 pin ------------------------------*/ 02049 GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN; 02050 HAL_GPIO_DeInit(AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT, GPIO_InitStruct.Pin); 02051 GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_DATIN5_PIN; 02052 HAL_GPIO_DeInit(AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, GPIO_InitStruct.Pin); 02053 } 02054 } 02055 02056 /** 02057 * @brief Initialize the DFSDM filter MSP. 02058 * @retval None 02059 */ 02060 static void DFSDMx_FilterMspInit(void) 02061 { 02062 /* Enable DFSDM clock */ 02063 AUDIO_DFSDMx_CLK_ENABLE(); 02064 02065 /* Enable the DMA clock */ 02066 AUDIO_DFSDMx_DMAx_CLK_ENABLE(); 02067 02068 /*********** Configure DMA stream for TOP LEFT microphone *******************/ 02069 hDmaTopLeft.Init.Direction = DMA_PERIPH_TO_MEMORY; 02070 hDmaTopLeft.Init.PeriphInc = DMA_PINC_DISABLE; 02071 hDmaTopLeft.Init.MemInc = DMA_MINC_ENABLE; 02072 hDmaTopLeft.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE; 02073 hDmaTopLeft.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE; 02074 hDmaTopLeft.Init.Mode = DMA_CIRCULAR; 02075 hDmaTopLeft.Init.Priority = DMA_PRIORITY_HIGH; 02076 hDmaTopLeft.Instance = AUDIO_DFSDMx_DMAx_TOP_LEFT_STREAM; 02077 hDmaTopLeft.Init.Channel = AUDIO_DFSDMx_DMAx_CHANNEL; 02078 02079 /* Associate the DMA handle */ 02080 __HAL_LINKDMA(&hAudioInTopLeftFilter, hdmaReg, hDmaTopLeft); 02081 02082 /* Reset DMA handle state */ 02083 __HAL_DMA_RESET_HANDLE_STATE(&hDmaTopLeft); 02084 02085 /* Configure the DMA Channel */ 02086 HAL_DMA_Init(&hDmaTopLeft); 02087 02088 /* DMA IRQ Channel configuration */ 02089 HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_TOP_LEFT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 02090 HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_TOP_LEFT_IRQ); 02091 02092 02093 /*********** Configure DMA stream for TOP RIGHT microphone ******************/ 02094 hDmaTopRight.Init.Direction = DMA_PERIPH_TO_MEMORY; 02095 hDmaTopRight.Init.PeriphInc = DMA_PINC_DISABLE; 02096 hDmaTopRight.Init.MemInc = DMA_MINC_ENABLE; 02097 hDmaTopRight.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE; 02098 hDmaTopRight.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE; 02099 hDmaTopRight.Init.Mode = DMA_CIRCULAR; 02100 hDmaTopRight.Init.Priority = DMA_PRIORITY_HIGH; 02101 hDmaTopRight.Instance = AUDIO_DFSDMx_DMAx_TOP_RIGHT_STREAM; 02102 hDmaTopRight.Init.Channel = AUDIO_DFSDMx_DMAx_CHANNEL; 02103 02104 /* Associate the DMA handle */ 02105 __HAL_LINKDMA(&hAudioInTopRightFilter, hdmaReg, hDmaTopRight); 02106 02107 /* Reset DMA handle state */ 02108 __HAL_DMA_RESET_HANDLE_STATE(&hDmaTopRight); 02109 02110 /* Configure the DMA Channel */ 02111 HAL_DMA_Init(&hDmaTopRight); 02112 02113 /* DMA IRQ Channel configuration */ 02114 HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_TOP_RIGHT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 02115 HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_TOP_RIGHT_IRQ); 02116 02117 if(AudioIn_ChannelNumber > 2) 02118 { 02119 /*********** Configure DMA stream for BUTTOM LEFT microphone ****************/ 02120 hDmaButtomLeft.Init.Direction = DMA_PERIPH_TO_MEMORY; 02121 hDmaButtomLeft.Init.PeriphInc = DMA_PINC_DISABLE; 02122 hDmaButtomLeft.Init.MemInc = DMA_MINC_ENABLE; 02123 hDmaButtomLeft.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE; 02124 hDmaButtomLeft.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE; 02125 hDmaButtomLeft.Init.Mode = DMA_CIRCULAR; 02126 hDmaButtomLeft.Init.Priority = DMA_PRIORITY_HIGH; 02127 hDmaButtomLeft.Instance = AUDIO_DFSDMx_DMAx_BUTTOM_LEFT_STREAM; 02128 hDmaButtomLeft.Init.Channel = AUDIO_DFSDMx_DMAx_CHANNEL; 02129 02130 /* Associate the DMA handle */ 02131 __HAL_LINKDMA(&hAudioInButtomLeftFilter, hdmaReg, hDmaButtomLeft); 02132 02133 /* Reset DMA handle state */ 02134 __HAL_DMA_RESET_HANDLE_STATE(&hDmaButtomLeft); 02135 02136 /* Configure the DMA Channel */ 02137 HAL_DMA_Init(&hDmaButtomLeft); 02138 02139 /* DMA IRQ Channel configuration */ 02140 HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_BUTTOM_LEFT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 02141 HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_BUTTOM_LEFT_IRQ); 02142 02143 02144 /*********** Configure DMA stream for BUTTOM RIGHT microphone ***************/ 02145 hDmaButtomRight.Init.Direction = DMA_PERIPH_TO_MEMORY; 02146 hDmaButtomRight.Init.PeriphInc = DMA_PINC_DISABLE; 02147 hDmaButtomRight.Init.MemInc = DMA_MINC_ENABLE; 02148 hDmaButtomRight.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE; 02149 hDmaButtomRight.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE; 02150 hDmaButtomRight.Init.Mode = DMA_CIRCULAR; 02151 hDmaButtomRight.Init.Priority = DMA_PRIORITY_HIGH; 02152 hDmaButtomRight.Instance = AUDIO_DFSDMx_DMAx_BUTTOM_RIGHT_STREAM; 02153 hDmaButtomRight.Init.Channel = AUDIO_DFSDMx_DMAx_CHANNEL; 02154 02155 /* Associate the DMA handle */ 02156 __HAL_LINKDMA(&hAudioInButtomRightFilter, hdmaReg, hDmaButtomRight); 02157 02158 /* Reset DMA handle state */ 02159 __HAL_DMA_RESET_HANDLE_STATE(&hDmaButtomRight); 02160 02161 /* Configure the DMA Channel */ 02162 HAL_DMA_Init(&hDmaButtomRight); 02163 02164 /* DMA IRQ Channel configuration */ 02165 HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_BUTTOM_RIGHT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 02166 HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_BUTTOM_RIGHT_IRQ); 02167 } 02168 } 02169 02170 /** 02171 * @brief DeInitialize the DFSDM filter MSP. 02172 * @retval None 02173 */ 02174 static void DFSDMx_FilterMspDeInit(void) 02175 { 02176 /* Configure the DMA Channel */ 02177 HAL_DMA_DeInit(&hDmaTopLeft); 02178 HAL_DMA_DeInit(&hDmaTopRight); 02179 if(AudioIn_ChannelNumber > 2) 02180 { 02181 HAL_DMA_DeInit(&hDmaButtomLeft); 02182 HAL_DMA_DeInit(&hDmaButtomRight); 02183 } 02184 } 02185 02186 /** 02187 * @} 02188 */ 02189 02190 /** 02191 * @} 02192 */ 02193 02194 /** 02195 * @} 02196 */ 02197 02198 /** 02199 * @} 02200 */ 02201 02202 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Fri Dec 30 2016 18:30:07 for STM32F769I-Discovery BSP User Manual by
