STM32756G_EVAL BSP User Manual
|
stm32756g_eval_audio.c
Go to the documentation of this file.
00001 /** 00002 ****************************************************************************** 00003 * @file stm32756g_eval_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 STM32756G-EVAL and 00008 * STM32746G_EVAL evaluation board. 00009 @verbatim 00010 How To use this driver: 00011 ----------------------- 00012 + This driver supports STM32F7xx devices on STM32756G-EVAL (MB1167) 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 or the MFX 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 STM32756G-EVAL 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_EVAL_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 AUDIO_OUT_XXX_CallBack() and only their prototypes are declared in 00042 the stm32756g_eval_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 + The driver API and the callback functions are at the end of the stm32756g_eval_audio.h file. 00048 00049 Driver architecture: 00050 -------------------- 00051 + This driver provides the High Audio Layer: consists of the function API exported in the stm32756g_eval_audio.h file 00052 (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...) 00053 + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/ 00054 providing the audio file/stream. These functions are also included as local functions into 00055 the stm32756g_eval_audio_codec.c file (I2Sx_Init(), I2Sx_DeInit(), SAIx_Init() and SAIx_DeInit()) 00056 00057 Known Limitations: 00058 ------------------ 00059 1- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second 00060 Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams. 00061 2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 00062 File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file. 00063 3- Supports only Stereo audio streaming. 00064 4- Supports only 16-bits audio data size. 00065 @endverbatim 00066 ****************************************************************************** 00067 * @attention 00068 * 00069 * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> 00070 * 00071 * Redistribution and use in source and binary forms, with or without modification, 00072 * are permitted provided that the following conditions are met: 00073 * 1. Redistributions of source code must retain the above copyright notice, 00074 * this list of conditions and the following disclaimer. 00075 * 2. Redistributions in binary form must reproduce the above copyright notice, 00076 * this list of conditions and the following disclaimer in the documentation 00077 * and/or other materials provided with the distribution. 00078 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00079 * may be used to endorse or promote products derived from this software 00080 * without specific prior written permission. 00081 * 00082 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00083 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00084 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00085 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00086 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00087 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00088 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00089 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00090 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00091 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00092 * 00093 ****************************************************************************** 00094 */ 00095 /* Includes ------------------------------------------------------------------*/ 00096 #include "stm32756g_eval_audio.h" 00097 00098 /** @addtogroup BSP 00099 * @{ 00100 */ 00101 00102 /** @addtogroup STM32756G_EVAL 00103 * @{ 00104 */ 00105 00106 /** @defgroup STM32756G_EVAL_AUDIO STM32756G_EVAL AUDIO 00107 * @brief This file includes the low layer driver for wm8994 Audio Codec 00108 * available on STM32756G-EVAL evaluation board(MB1167). 00109 * @{ 00110 */ 00111 00112 /** @defgroup STM32756G_EVAL_AUDIO_Private_Types STM32756G_EVAL_AUDIO Private Types 00113 * @{ 00114 */ 00115 /** 00116 * @} 00117 */ 00118 00119 /** @defgroup STM32756G_EVAL_AUDIO_Private_Defines STM32756G_EVAL_AUDIO Private Defines 00120 * @{ 00121 */ 00122 /** 00123 * @} 00124 */ 00125 00126 /** @defgroup STM32756G_EVAL_AUDIO_Private_Macros STM32756G_EVAL_AUDIO Private Macros 00127 * @{ 00128 */ 00129 /** 00130 * @} 00131 */ 00132 00133 /** @defgroup STM32756G_EVAL_AUDIO_Private_Variables STM32756G_EVAL_AUDIO Private Variables 00134 * @{ 00135 */ 00136 AUDIO_DrvTypeDef *audio_drv; 00137 SAI_HandleTypeDef haudio_out_sai; 00138 I2S_HandleTypeDef haudio_in_i2s; 00139 TIM_HandleTypeDef haudio_tim; 00140 00141 PDMFilter_InitStruct Filter[2]; 00142 uint8_t Channel_Demux[128] = { 00143 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x02, 0x03, 00144 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x02, 0x03, 00145 0x04, 0x05, 0x04, 0x05, 0x06, 0x07, 0x06, 0x07, 00146 0x04, 0x05, 0x04, 0x05, 0x06, 0x07, 0x06, 0x07, 00147 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x02, 0x03, 00148 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x02, 0x03, 00149 0x04, 0x05, 0x04, 0x05, 0x06, 0x07, 0x06, 0x07, 00150 0x04, 0x05, 0x04, 0x05, 0x06, 0x07, 0x06, 0x07, 00151 0x08, 0x09, 0x08, 0x09, 0x0a, 0x0b, 0x0a, 0x0b, 00152 0x08, 0x09, 0x08, 0x09, 0x0a, 0x0b, 0x0a, 0x0b, 00153 0x0c, 0x0d, 0x0c, 0x0d, 0x0e, 0x0f, 0x0e, 0x0f, 00154 0x0c, 0x0d, 0x0c, 0x0d, 0x0e, 0x0f, 0x0e, 0x0f, 00155 0x08, 0x09, 0x08, 0x09, 0x0a, 0x0b, 0x0a, 0x0b, 00156 0x08, 0x09, 0x08, 0x09, 0x0a, 0x0b, 0x0a, 0x0b, 00157 0x0c, 0x0d, 0x0c, 0x0d, 0x0e, 0x0f, 0x0e, 0x0f, 00158 0x0c, 0x0d, 0x0c, 0x0d, 0x0e, 0x0f, 0x0e, 0x0f 00159 }; 00160 00161 uint16_t __IO AudioInVolume = DEFAULT_AUDIO_IN_VOLUME; 00162 00163 /** 00164 * @} 00165 */ 00166 00167 /** @defgroup STM32756G_EVAL_AUDIO_Private_Function_Prototypes STM32756G_EVAL_AUDIO Private Function Prototypes 00168 * @{ 00169 */ 00170 static void SAIx_Init(uint32_t AudioFreq); 00171 static void SAIx_DeInit(void); 00172 static void I2Sx_Init(uint32_t AudioFreq); 00173 static void I2Sx_DeInit(void); 00174 static void TIMx_IC_MspInit(TIM_HandleTypeDef *htim); 00175 static void TIMx_IC_MspDeInit(TIM_HandleTypeDef *htim); 00176 static void TIMx_Init(void); 00177 static void TIMx_DeInit(void); 00178 static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr); 00179 /** 00180 * @} 00181 */ 00182 00183 /** @defgroup STM32756G_EVAL_AUDIO_out_Private_Functions STM32756G_EVAL_AUDIO_Out Private Functions 00184 * @{ 00185 */ 00186 00187 /** 00188 * @brief Configures the audio peripherals. 00189 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00190 * or OUTPUT_DEVICE_BOTH. 00191 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00192 * @param AudioFreq: Audio frequency used to play the audio stream. 00193 * @note The I2S PLL input clock must be done in the user application. 00194 * @retval AUDIO_OK if correct communication, else wrong communication 00195 */ 00196 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00197 { 00198 uint8_t ret = AUDIO_ERROR; 00199 uint32_t deviceid = 0x00; 00200 00201 /* Disable SAI */ 00202 SAIx_DeInit(); 00203 00204 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00205 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00206 00207 /* SAI data transfer preparation: 00208 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00209 haudio_out_sai.Instance = AUDIO_SAIx; 00210 if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET) 00211 { 00212 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00213 BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL); 00214 } 00215 SAIx_Init(AudioFreq); 00216 00217 /* wm8994 codec initialization */ 00218 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00219 00220 if((deviceid) == WM8994_ID) 00221 { 00222 /* Reset the Codec Registers */ 00223 wm8994_drv.Reset(AUDIO_I2C_ADDRESS); 00224 /* Initialize the audio driver structure */ 00225 audio_drv = &wm8994_drv; 00226 ret = AUDIO_OK; 00227 } 00228 else 00229 { 00230 ret = AUDIO_ERROR; 00231 } 00232 00233 if(ret == AUDIO_OK) 00234 { 00235 /* Initialize the codec internal registers */ 00236 audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq); 00237 } 00238 00239 return ret; 00240 } 00241 00242 /** 00243 * @brief Starts playing audio stream from a data buffer for a determined size. 00244 * @param pBuffer: Pointer to the buffer 00245 * @param Size: Number of audio data BYTES. 00246 * @retval AUDIO_OK if correct communication, else wrong communication 00247 */ 00248 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size) 00249 { 00250 /* Call the audio Codec Play function */ 00251 if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0) 00252 { 00253 return AUDIO_ERROR; 00254 } 00255 else 00256 { 00257 /* Update the Media layer and enable it for play */ 00258 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE)); 00259 00260 return AUDIO_OK; 00261 } 00262 } 00263 00264 /** 00265 * @brief Sends n-Bytes on the SAI interface. 00266 * @param pData: pointer on data address 00267 * @param Size: number of data to be written 00268 * @retval None 00269 */ 00270 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size) 00271 { 00272 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size); 00273 } 00274 00275 /** 00276 * @brief This function Pauses the audio file stream. In case 00277 * of using DMA, the DMA Pause feature is used. 00278 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00279 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00280 * function for resume could lead to unexpected behaviour). 00281 * @retval AUDIO_OK if correct communication, else wrong communication 00282 */ 00283 uint8_t BSP_AUDIO_OUT_Pause(void) 00284 { 00285 /* Call the Audio Codec Pause/Resume function */ 00286 if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0) 00287 { 00288 return AUDIO_ERROR; 00289 } 00290 else 00291 { 00292 /* Call the Media layer pause function */ 00293 HAL_SAI_DMAPause(&haudio_out_sai); 00294 00295 /* Return AUDIO_OK when all operations are correctly done */ 00296 return AUDIO_OK; 00297 } 00298 } 00299 00300 /** 00301 * @brief This function Resumes the audio file stream. 00302 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00303 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00304 * function for resume could lead to unexpected behaviour). 00305 * @retval AUDIO_OK if correct communication, else wrong communication 00306 */ 00307 uint8_t BSP_AUDIO_OUT_Resume(void) 00308 { 00309 /* Call the Audio Codec Pause/Resume function */ 00310 if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0) 00311 { 00312 return AUDIO_ERROR; 00313 } 00314 else 00315 { 00316 /* Call the Media layer pause/resume function */ 00317 HAL_SAI_DMAResume(&haudio_out_sai); 00318 00319 /* Return AUDIO_OK when all operations are correctly done */ 00320 return AUDIO_OK; 00321 } 00322 } 00323 00324 /** 00325 * @brief Stops audio playing and Power down the Audio Codec. 00326 * @param Option: could be one of the following parameters 00327 * - CODEC_PDWN_SW: for software power off (by writing registers). 00328 * Then no need to reconfigure the Codec after power on. 00329 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00330 * Then need to reconfigure the Codec after power on. 00331 * @retval AUDIO_OK if correct communication, else wrong communication 00332 */ 00333 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option) 00334 { 00335 /* Call the Media layer stop function */ 00336 HAL_SAI_DMAStop(&haudio_out_sai); 00337 00338 /* Call Audio Codec Stop function */ 00339 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 00340 { 00341 return AUDIO_ERROR; 00342 } 00343 else 00344 { 00345 if(Option == CODEC_PDWN_HW) 00346 { 00347 /* Wait at least 100us */ 00348 HAL_Delay(1); 00349 } 00350 /* Return AUDIO_OK when all operations are correctly done */ 00351 return AUDIO_OK; 00352 } 00353 } 00354 00355 /** 00356 * @brief Controls the current audio volume level. 00357 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00358 * Mute and 100 for Max volume level). 00359 * @retval AUDIO_OK if correct communication, else wrong communication 00360 */ 00361 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume) 00362 { 00363 /* Call the codec volume control function with converted volume value */ 00364 if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 00365 { 00366 return AUDIO_ERROR; 00367 } 00368 else 00369 { 00370 /* Return AUDIO_OK when all operations are correctly done */ 00371 return AUDIO_OK; 00372 } 00373 } 00374 00375 /** 00376 * @brief Enables or disables the MUTE mode by software 00377 * @param Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 00378 * unmute the codec and restore previous volume level. 00379 * @retval AUDIO_OK if correct communication, else wrong communication 00380 */ 00381 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd) 00382 { 00383 /* Call the Codec Mute function */ 00384 if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0) 00385 { 00386 return AUDIO_ERROR; 00387 } 00388 else 00389 { 00390 /* Return AUDIO_OK when all operations are correctly done */ 00391 return AUDIO_OK; 00392 } 00393 } 00394 00395 /** 00396 * @brief Switch dynamically (while audio file is played) the output target 00397 * (speaker or headphone). 00398 * @param Output: The audio output target: OUTPUT_DEVICE_SPEAKER, 00399 * OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH 00400 * @retval AUDIO_OK if correct communication, else wrong communication 00401 */ 00402 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output) 00403 { 00404 /* Call the Codec output device function */ 00405 if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0) 00406 { 00407 return AUDIO_ERROR; 00408 } 00409 else 00410 { 00411 /* Return AUDIO_OK when all operations are correctly done */ 00412 return AUDIO_OK; 00413 } 00414 } 00415 00416 /** 00417 * @brief Updates the audio frequency. 00418 * @param AudioFreq: Audio frequency used to play the audio stream. 00419 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00420 * audio frequency. 00421 * @retval None 00422 */ 00423 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq) 00424 { 00425 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00426 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00427 00428 /* Disable SAI peripheral to allow access to SAI internal registers */ 00429 __HAL_SAI_DISABLE(&haudio_out_sai); 00430 00431 /* Update the SAI audio frequency configuration */ 00432 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00433 HAL_SAI_Init(&haudio_out_sai); 00434 00435 /* Enable SAI peripheral to generate MCLK */ 00436 __HAL_SAI_ENABLE(&haudio_out_sai); 00437 } 00438 00439 /** 00440 * @brief Updates the Audio frame slot configuration. 00441 * @param AudioFrameSlot: specifies the audio Frame slot 00442 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00443 * audio frame slot. 00444 * @retval None 00445 */ 00446 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot) 00447 { 00448 /* Disable SAI peripheral to allow access to SAI internal registers */ 00449 __HAL_SAI_DISABLE(&haudio_out_sai); 00450 00451 /* Update the SAI audio frame slot configuration */ 00452 haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot; 00453 HAL_SAI_Init(&haudio_out_sai); 00454 00455 /* Enable SAI peripheral to generate MCLK */ 00456 __HAL_SAI_ENABLE(&haudio_out_sai); 00457 } 00458 00459 /** 00460 * @brief Deinit the audio peripherals. 00461 * @retval None 00462 */ 00463 void BSP_AUDIO_OUT_DeInit(void) 00464 { 00465 SAIx_DeInit(); 00466 /* DeInit the SAI MSP : this __weak function can be rewritten by the application */ 00467 BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL); 00468 } 00469 00470 /** 00471 * @brief Tx Transfer completed callbacks. 00472 * @param hsai: SAI handle 00473 * @retval None 00474 */ 00475 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) 00476 { 00477 /* Manage the remaining file size and new address offset: This function 00478 should be coded by user (its prototype is already declared in stm32756g_eval_audio.h) */ 00479 BSP_AUDIO_OUT_TransferComplete_CallBack(); 00480 } 00481 00482 /** 00483 * @brief Tx Half Transfer completed callbacks. 00484 * @param hsai: SAI handle 00485 * @retval None 00486 */ 00487 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 00488 { 00489 /* Manage the remaining file size and new address offset: This function 00490 should be coded by user (its prototype is already declared in stm32756g_eval_audio.h) */ 00491 BSP_AUDIO_OUT_HalfTransfer_CallBack(); 00492 } 00493 00494 /** 00495 * @brief SAI error callbacks. 00496 * @param hsai: SAI handle 00497 * @retval None 00498 */ 00499 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 00500 { 00501 BSP_AUDIO_OUT_Error_CallBack(); 00502 } 00503 00504 /** 00505 * @brief Manages the DMA full Transfer complete event. 00506 * @retval None 00507 */ 00508 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void) 00509 { 00510 } 00511 00512 /** 00513 * @brief Manages the DMA Half Transfer complete event. 00514 * @retval None 00515 */ 00516 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) 00517 { 00518 } 00519 00520 /** 00521 * @brief Manages the DMA FIFO error event. 00522 * @retval None 00523 */ 00524 __weak void BSP_AUDIO_OUT_Error_CallBack(void) 00525 { 00526 } 00527 00528 /** 00529 * @brief Initializes BSP_AUDIO_OUT MSP. 00530 * @param hsai: SAI handle 00531 * @param Params 00532 * @retval None 00533 */ 00534 __weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params) 00535 { 00536 static DMA_HandleTypeDef hdma_sai_tx; 00537 GPIO_InitTypeDef gpio_init_structure; 00538 00539 /* Enable SAI clock */ 00540 AUDIO_SAIx_CLK_ENABLE(); 00541 00542 /* Enable GPIO clock */ 00543 AUDIO_SAIx_MCLK_ENABLE(); 00544 AUDIO_SAIx_SCK_SD_ENABLE(); 00545 AUDIO_SAIx_FS_ENABLE(); 00546 /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/ 00547 gpio_init_structure.Pin = AUDIO_SAIx_FS_PIN; 00548 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00549 gpio_init_structure.Pull = GPIO_NOPULL; 00550 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00551 gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF; 00552 HAL_GPIO_Init(AUDIO_SAIx_FS_GPIO_PORT, &gpio_init_structure); 00553 00554 gpio_init_structure.Pin = AUDIO_SAIx_SCK_PIN; 00555 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00556 gpio_init_structure.Pull = GPIO_NOPULL; 00557 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00558 gpio_init_structure.Alternate = AUDIO_SAIx_SCK_AF; 00559 HAL_GPIO_Init(AUDIO_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure); 00560 00561 gpio_init_structure.Pin = AUDIO_SAIx_SD_PIN; 00562 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00563 gpio_init_structure.Pull = GPIO_NOPULL; 00564 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00565 gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF; 00566 HAL_GPIO_Init(AUDIO_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure); 00567 00568 gpio_init_structure.Pin = AUDIO_SAIx_MCLK_PIN; 00569 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00570 gpio_init_structure.Pull = GPIO_NOPULL; 00571 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00572 gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF; 00573 HAL_GPIO_Init(AUDIO_SAIx_MCLK_GPIO_PORT, &gpio_init_structure); 00574 00575 /* Enable the DMA clock */ 00576 AUDIO_SAIx_DMAx_CLK_ENABLE(); 00577 00578 if(hsai->Instance == AUDIO_SAIx) 00579 { 00580 /* Configure the hdma_saiTx handle parameters */ 00581 hdma_sai_tx.Init.Channel = AUDIO_SAIx_DMAx_CHANNEL; 00582 hdma_sai_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; 00583 hdma_sai_tx.Init.PeriphInc = DMA_PINC_DISABLE; 00584 hdma_sai_tx.Init.MemInc = DMA_MINC_ENABLE; 00585 hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_SAIx_DMAx_PERIPH_DATA_SIZE; 00586 hdma_sai_tx.Init.MemDataAlignment = AUDIO_SAIx_DMAx_MEM_DATA_SIZE; 00587 hdma_sai_tx.Init.Mode = DMA_CIRCULAR; 00588 hdma_sai_tx.Init.Priority = DMA_PRIORITY_HIGH; 00589 hdma_sai_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; 00590 hdma_sai_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 00591 hdma_sai_tx.Init.MemBurst = DMA_MBURST_SINGLE; 00592 hdma_sai_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; 00593 00594 hdma_sai_tx.Instance = AUDIO_SAIx_DMAx_STREAM; 00595 00596 /* Associate the DMA handle */ 00597 __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx); 00598 00599 /* Deinitialize the Stream for new transfer */ 00600 HAL_DMA_DeInit(&hdma_sai_tx); 00601 00602 /* Configure the DMA Stream */ 00603 HAL_DMA_Init(&hdma_sai_tx); 00604 } 00605 00606 /* SAI DMA IRQ Channel configuration */ 00607 HAL_NVIC_SetPriority(AUDIO_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 00608 HAL_NVIC_EnableIRQ(AUDIO_SAIx_DMAx_IRQ); 00609 } 00610 00611 /** 00612 * @brief Deinitializes SAI MSP. 00613 * @param hsai: SAI handle 00614 * @param Params 00615 * @retval None 00616 */ 00617 __weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params) 00618 { 00619 GPIO_InitTypeDef gpio_init_structure; 00620 00621 /* SAI DMA IRQ Channel deactivation */ 00622 HAL_NVIC_DisableIRQ(AUDIO_SAIx_DMAx_IRQ); 00623 00624 if(hsai->Instance == AUDIO_SAIx) 00625 { 00626 /* Deinitialize the DMA stream */ 00627 HAL_DMA_DeInit(hsai->hdmatx); 00628 } 00629 00630 /* Disable SAI peripheral */ 00631 __HAL_SAI_DISABLE(hsai); 00632 00633 /* Deactivates CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */ 00634 gpio_init_structure.Pin = AUDIO_SAIx_FS_PIN; 00635 HAL_GPIO_DeInit(AUDIO_SAIx_FS_GPIO_PORT, gpio_init_structure.Pin); 00636 00637 gpio_init_structure.Pin = AUDIO_SAIx_SCK_PIN; 00638 HAL_GPIO_DeInit(AUDIO_SAIx_SCK_SD_GPIO_PORT, gpio_init_structure.Pin); 00639 00640 gpio_init_structure.Pin = AUDIO_SAIx_SD_PIN; 00641 HAL_GPIO_DeInit(AUDIO_SAIx_SCK_SD_GPIO_PORT, gpio_init_structure.Pin); 00642 00643 gpio_init_structure.Pin = AUDIO_SAIx_MCLK_PIN; 00644 HAL_GPIO_DeInit(AUDIO_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin); 00645 00646 /* Disable SAI clock */ 00647 AUDIO_SAIx_CLK_DISABLE(); 00648 00649 /* GPIO pins clock and DMA clock can be shut down in the applic 00650 by surcharging this __weak function */ 00651 } 00652 00653 /** 00654 * @brief Clock Config. 00655 * @param hsai: might be required to set audio peripheral predivider if any. 00656 * @param AudioFreq: Audio frequency used to play the audio stream. 00657 * @param Params 00658 * @note This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency() 00659 * Being __weak it can be overwritten by the application 00660 * @retval None 00661 */ 00662 __weak void BSP_AUDIO_OUT_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params) 00663 { 00664 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 00665 00666 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 00667 00668 /* Set the PLL configuration according to the audio frequency */ 00669 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 00670 { 00671 /* Configure PLLSAI prescalers */ 00672 /* PLLSAI_VCO: VCO_429M 00673 SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 429/2 = 214.5 Mhz 00674 SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 214.5/19 = 11.289 Mhz */ 00675 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 00676 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLSAI; 00677 rcc_ex_clk_init_struct.PLLSAI.PLLSAIN = 429; 00678 rcc_ex_clk_init_struct.PLLSAI.PLLSAIQ = 2; 00679 rcc_ex_clk_init_struct.PLLSAIDivQ = 19; 00680 00681 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00682 00683 } 00684 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K), AUDIO_FREQUENCY_96K */ 00685 { 00686 /* SAI clock config 00687 PLLSAI_VCO: VCO_344M 00688 SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 344/7 = 49.142 Mhz 00689 SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 49.142/1 = 49.142 Mhz */ 00690 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2; 00691 rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLSAI; 00692 rcc_ex_clk_init_struct.PLLSAI.PLLSAIN = 344; 00693 rcc_ex_clk_init_struct.PLLSAI.PLLSAIQ = 7; 00694 rcc_ex_clk_init_struct.PLLSAIDivQ = 1; 00695 00696 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00697 } 00698 } 00699 00700 /******************************************************************************* 00701 Static Functions 00702 *******************************************************************************/ 00703 00704 /** 00705 * @brief Initializes the Audio Codec audio interface (SAI). 00706 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00707 * @note The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 00708 * and user can update this configuration using 00709 * @retval None 00710 */ 00711 static void SAIx_Init(uint32_t AudioFreq) 00712 { 00713 /* Initialize the haudio_out_sai Instance parameter */ 00714 haudio_out_sai.Instance = AUDIO_SAIx; 00715 00716 /* Disable SAI peripheral to allow access to SAI internal registers */ 00717 __HAL_SAI_DISABLE(&haudio_out_sai); 00718 00719 /* Configure SAI_Block_x 00720 LSBFirst: Disabled 00721 DataSize: 16 */ 00722 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00723 haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX; 00724 haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED; 00725 haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL; 00726 haudio_out_sai.Init.DataSize = SAI_DATASIZE_16; 00727 haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 00728 haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; 00729 haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS; 00730 haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLED; 00731 haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 00732 00733 /* Configure SAI_Block_x Frame 00734 Frame Length: 64 00735 Frame active Length: 32 00736 FS Definition: Start frame + Channel Side identification 00737 FS Polarity: FS active Low 00738 FS Offset: FS asserted one bit before the first bit of slot 0 */ 00739 haudio_out_sai.FrameInit.FrameLength = 64; 00740 haudio_out_sai.FrameInit.ActiveFrameLength = 32; 00741 haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 00742 haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 00743 haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 00744 00745 /* Configure SAI Block_x Slot 00746 Slot First Bit Offset: 0 00747 Slot Size : 16 00748 Slot Number: 4 00749 Slot Active: All slot actives */ 00750 haudio_out_sai.SlotInit.FirstBitOffset = 0; 00751 haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 00752 haudio_out_sai.SlotInit.SlotNumber = 4; 00753 haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123; 00754 00755 HAL_SAI_Init(&haudio_out_sai); 00756 00757 /* Enable SAI peripheral to generate MCLK */ 00758 __HAL_SAI_ENABLE(&haudio_out_sai); 00759 } 00760 00761 /** 00762 * @brief Deinitializes the Audio Codec audio interface (SAI). 00763 * @retval None 00764 */ 00765 static void SAIx_DeInit(void) 00766 { 00767 /* Initialize the haudio_out_sai Instance parameter */ 00768 haudio_out_sai.Instance = AUDIO_SAIx; 00769 00770 /* Disable SAI peripheral */ 00771 __HAL_SAI_DISABLE(&haudio_out_sai); 00772 00773 HAL_SAI_DeInit(&haudio_out_sai); 00774 } 00775 00776 /** 00777 * @} 00778 */ 00779 00780 /** @defgroup STM32756G_EVAL_AUDIO_out_Private_Functions STM32756G_EVAL_AUDIO_Out Private Functions 00781 * @{ 00782 */ 00783 00784 /** 00785 * @brief Initializes wave recording. 00786 * @note This function assumes that the I2S input clock (through PLL_R in 00787 * Devices RevA/Z and through dedicated PLLI2S_R in Devices RevB/Y) 00788 * is already configured and ready to be used. 00789 * @param AudioFreq: Audio frequency to be configured for the I2S peripheral. 00790 * @param BitRes: Audio frequency to be configured for the I2S peripheral. 00791 * @param ChnlNbr: Audio frequency to be configured for the I2S peripheral. 00792 * @retval AUDIO_OK if correct communication, else wrong communication 00793 */ 00794 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00795 { 00796 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 00797 00798 /* Disable I2S */ 00799 I2Sx_DeInit(); 00800 00801 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 00802 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_I2S; 00803 rcc_ex_clk_init_struct.I2sClockSelection = RCC_I2SCLKSOURCE_PLLI2S; 00804 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 384; 00805 rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 2; 00806 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00807 00808 /* Configure the PDM library */ 00809 PDMDecoder_Init(AudioFreq, ChnlNbr); 00810 00811 /* Configure the I2S peripheral */ 00812 haudio_in_i2s.Instance = AUDIO_I2Sx; 00813 if(HAL_I2S_GetState(&haudio_in_i2s) == HAL_I2S_STATE_RESET) 00814 { 00815 /* Initialize the I2S Msp: this __weak function can be rewritten by the application */ 00816 BSP_AUDIO_IN_MspInit(&haudio_in_i2s, NULL); 00817 } 00818 I2Sx_Init(AudioFreq); 00819 00820 /* Return AUDIO_OK when all operations are correctly done */ 00821 return AUDIO_OK; 00822 } 00823 00824 /** 00825 * @brief Starts audio recording. 00826 * @param pbuf: Main buffer pointer for the recorded data storing 00827 * @param size: Current size of the recorded buffer 00828 * @retval AUDIO_OK if correct communication, else wrong communication 00829 */ 00830 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size) 00831 { 00832 uint32_t ret = AUDIO_ERROR; 00833 00834 /* Start the process receive DMA */ 00835 HAL_I2S_Receive_DMA(&haudio_in_i2s, pbuf, size); 00836 00837 /* Return AUDIO_OK when all operations are correctly done */ 00838 ret = AUDIO_OK; 00839 00840 return ret; 00841 } 00842 00843 /** 00844 * @brief Stops audio recording. 00845 * @retval AUDIO_OK if correct communication, else wrong communication 00846 */ 00847 uint8_t BSP_AUDIO_IN_Stop(void) 00848 { 00849 uint32_t ret = AUDIO_ERROR; 00850 /* Call the Media layer stop function */ 00851 HAL_I2S_DMAStop(&haudio_in_i2s); 00852 00853 /* TIMx Peripheral clock disable */ 00854 AUDIO_TIMx_CLK_DISABLE(); 00855 00856 /* Return AUDIO_OK when all operations are correctly done */ 00857 ret = AUDIO_OK; 00858 00859 return ret; 00860 } 00861 00862 /** 00863 * @brief Pauses the audio file stream. 00864 * @retval AUDIO_OK if correct communication, else wrong communication 00865 */ 00866 uint8_t BSP_AUDIO_IN_Pause(void) 00867 { 00868 /* Call the Media layer pause function */ 00869 HAL_I2S_DMAPause(&haudio_in_i2s); 00870 /* Return AUDIO_OK when all operations are correctly done */ 00871 return AUDIO_OK; 00872 } 00873 00874 /** 00875 * @brief Resumes the audio file stream. 00876 * @retval AUDIO_OK if correct communication, else wrong communication 00877 */ 00878 uint8_t BSP_AUDIO_IN_Resume(void) 00879 { 00880 /* Call the Media layer pause/resume function */ 00881 HAL_I2S_DMAResume(&haudio_in_i2s); 00882 /* Return AUDIO_OK when all operations are correctly done */ 00883 return AUDIO_OK; 00884 } 00885 00886 /** 00887 * @brief Controls the audio in volume level. 00888 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00889 * Mute and 100 for Max volume level). 00890 * @retval AUDIO_OK if correct communication, else wrong communication 00891 */ 00892 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume) 00893 { 00894 /* Set the Global variable AudioInVolume */ 00895 AudioInVolume = Volume; 00896 00897 /* Return AUDIO_OK when all operations are correctly done */ 00898 return AUDIO_OK; 00899 } 00900 00901 /** 00902 * @brief Deinit the audio IN peripherals. 00903 * @retval None 00904 */ 00905 void BSP_AUDIO_IN_DeInit(void) 00906 { 00907 I2Sx_DeInit(); 00908 /* DeInit the I2S MSP : this __weak function can be rewritten by the application */ 00909 BSP_AUDIO_IN_MspDeInit(&haudio_in_i2s, NULL); 00910 TIMx_DeInit(); 00911 } 00912 00913 /** 00914 * @brief Converts audio format from PDM to PCM. 00915 * @param PDMBuf: Pointer to data PDM buffer 00916 * @param PCMBuf: Pointer to data PCM buffer 00917 * @retval AUDIO_OK if correct communication, else wrong communication 00918 */ 00919 uint8_t BSP_AUDIO_IN_PDMToPCM(uint16_t* PDMBuf, uint16_t* PCMBuf) 00920 { 00921 uint8_t app_pdm[INTERNAL_BUFF_SIZE*2]; 00922 uint8_t byte1 = 0, byte2 = 0; 00923 uint32_t index = 0; 00924 00925 /* PDM Demux */ 00926 for(index = 0; index<INTERNAL_BUFF_SIZE/2; index++) 00927 { 00928 byte2 = (PDMBuf[index] >> 8)& 0xFF; 00929 byte1 = (PDMBuf[index] & 0xFF); 00930 app_pdm[(index*2)+1] = Channel_Demux[byte1 & CHANNEL_DEMUX_MASK] | Channel_Demux[byte2 & CHANNEL_DEMUX_MASK] << 4; 00931 app_pdm[(index*2)] = Channel_Demux[(byte1 >> 1) & CHANNEL_DEMUX_MASK] | Channel_Demux[(byte2 >> 1) & CHANNEL_DEMUX_MASK] << 4; 00932 } 00933 00934 for(index = 0; index < DEFAULT_AUDIO_IN_CHANNEL_NBR; index++) 00935 { 00936 /* PDM to PCM filter */ 00937 PDM_Filter_64_LSB((uint8_t*)&app_pdm[index], (uint16_t*)&(PCMBuf[index]), AudioInVolume , (PDMFilter_InitStruct *)&Filter[index]); 00938 } 00939 00940 /* Return AUDIO_OK when all operations are correctly done */ 00941 return AUDIO_OK; 00942 } 00943 00944 /** 00945 * @brief Rx Transfer completed callbacks. 00946 * @param hi2s: I2S handle 00947 * @retval None 00948 */ 00949 void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) 00950 { 00951 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 00952 BSP_AUDIO_IN_TransferComplete_CallBack(); 00953 } 00954 00955 /** 00956 * @brief Rx Half Transfer completed callbacks. 00957 * @param hi2s: I2S handle 00958 * @retval None 00959 */ 00960 void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s) 00961 { 00962 /* Manage the remaining file size and new address offset: This function 00963 should be coded by user (its prototype is already declared in stm32756g_eval_audio.h) */ 00964 BSP_AUDIO_IN_HalfTransfer_CallBack(); 00965 } 00966 00967 /** 00968 * @brief I2S error callbacks. 00969 * @param hi2s: I2S handle 00970 * @retval None 00971 */ 00972 void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s) 00973 { 00974 /* Manage the error generated on DMA FIFO: This function 00975 should be coded by user (its prototype is already declared in stm32756g_eval_audio.h) */ 00976 BSP_AUDIO_IN_Error_Callback(); 00977 } 00978 00979 /** 00980 * @brief User callback when record buffer is filled. 00981 * @retval None 00982 */ 00983 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void) 00984 { 00985 /* This function should be implemented by the user application. 00986 It is called into this driver when the current buffer is filled 00987 to prepare the next buffer pointer and its size. */ 00988 } 00989 00990 /** 00991 * @brief Manages the DMA Half Transfer complete event. 00992 * @retval None 00993 */ 00994 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 00995 { 00996 /* This function should be implemented by the user application. 00997 It is called into this driver when the current buffer is filled 00998 to prepare the next buffer pointer and its size. */ 00999 } 01000 01001 /** 01002 * @brief Audio IN Error callback function. 01003 * @retval None 01004 */ 01005 __weak void BSP_AUDIO_IN_Error_Callback(void) 01006 { 01007 /* This function is called when an Interrupt due to transfer error on or peripheral 01008 error occurs. */ 01009 } 01010 01011 /** 01012 * @brief Initializes BSP_AUDIO_IN MSP. 01013 * @param hi2s: I2S handle 01014 * @param Params 01015 * @retval None 01016 */ 01017 __weak void BSP_AUDIO_IN_MspInit(I2S_HandleTypeDef *hi2s, void *Params) 01018 { 01019 static DMA_HandleTypeDef hdma_i2s_rx; 01020 GPIO_InitTypeDef gpio_init_structure; 01021 01022 /* Configure the Timer which clocks the MEMS */ 01023 /* Moved inside MSP to allow applic to redefine the TIMx_MspInit */ 01024 TIMx_Init(); 01025 01026 /* Enable I2S clock */ 01027 AUDIO_I2Sx_CLK_ENABLE(); 01028 01029 /* Enable SCK and SD GPIO clock */ 01030 AUDIO_I2Sx_SD_GPIO_CLK_ENABLE(); 01031 AUDIO_I2Sx_SCK_GPIO_CLK_ENABLE(); 01032 /* CODEC_I2S pins configuration: SCK and SD pins */ 01033 gpio_init_structure.Pin = AUDIO_I2Sx_SCK_PIN; 01034 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 01035 gpio_init_structure.Pull = GPIO_NOPULL; 01036 gpio_init_structure.Speed = GPIO_SPEED_FAST; 01037 gpio_init_structure.Alternate = AUDIO_I2Sx_SCK_AF; 01038 HAL_GPIO_Init(AUDIO_I2Sx_SCK_GPIO_PORT, &gpio_init_structure); 01039 01040 gpio_init_structure.Pin = AUDIO_I2Sx_SD_PIN; 01041 gpio_init_structure.Alternate = AUDIO_I2Sx_SD_AF; 01042 HAL_GPIO_Init(AUDIO_I2Sx_SD_GPIO_PORT, &gpio_init_structure); 01043 01044 /* Enable the DMA clock */ 01045 AUDIO_I2Sx_DMAx_CLK_ENABLE(); 01046 01047 if(hi2s->Instance == AUDIO_I2Sx) 01048 { 01049 /* Configure the hdma_i2s_rx handle parameters */ 01050 hdma_i2s_rx.Init.Channel = AUDIO_I2Sx_DMAx_CHANNEL; 01051 hdma_i2s_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; 01052 hdma_i2s_rx.Init.PeriphInc = DMA_PINC_DISABLE; 01053 hdma_i2s_rx.Init.MemInc = DMA_MINC_ENABLE; 01054 hdma_i2s_rx.Init.PeriphDataAlignment = AUDIO_I2Sx_DMAx_PERIPH_DATA_SIZE; 01055 hdma_i2s_rx.Init.MemDataAlignment = AUDIO_I2Sx_DMAx_MEM_DATA_SIZE; 01056 hdma_i2s_rx.Init.Mode = DMA_CIRCULAR; 01057 hdma_i2s_rx.Init.Priority = DMA_PRIORITY_HIGH; 01058 hdma_i2s_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 01059 hdma_i2s_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 01060 hdma_i2s_rx.Init.MemBurst = DMA_MBURST_SINGLE; 01061 hdma_i2s_rx.Init.PeriphBurst = DMA_MBURST_SINGLE; 01062 01063 hdma_i2s_rx.Instance = AUDIO_I2Sx_DMAx_STREAM; 01064 01065 /* Associate the DMA handle */ 01066 __HAL_LINKDMA(hi2s, hdmarx, hdma_i2s_rx); 01067 01068 /* Deinitialize the Stream for new transfer */ 01069 HAL_DMA_DeInit(&hdma_i2s_rx); 01070 01071 /* Configure the DMA Stream */ 01072 HAL_DMA_Init(&hdma_i2s_rx); 01073 } 01074 01075 /* I2S DMA IRQ Channel configuration */ 01076 HAL_NVIC_SetPriority(AUDIO_I2Sx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 01077 HAL_NVIC_EnableIRQ(AUDIO_I2Sx_DMAx_IRQ); 01078 } 01079 01080 /** 01081 * @brief DeInitializes BSP_AUDIO_IN MSP. 01082 * @param hi2s: I2S handle 01083 * @param Params 01084 * @retval None 01085 */ 01086 __weak void BSP_AUDIO_IN_MspDeInit(I2S_HandleTypeDef *hi2s, void *Params) 01087 { 01088 GPIO_InitTypeDef gpio_init_structure; 01089 01090 static DMA_HandleTypeDef hdma_i2s_rx; 01091 01092 /* I2S DMA IRQ Channel deactivation */ 01093 HAL_NVIC_DisableIRQ(AUDIO_I2Sx_DMAx_IRQ); 01094 01095 if(hi2s->Instance == AUDIO_I2Sx) 01096 { 01097 /* Deinitialize the Stream for new transfer */ 01098 HAL_DMA_DeInit(&hdma_i2s_rx); 01099 } 01100 01101 /* Disable I2S block */ 01102 __HAL_I2S_DISABLE(hi2s); 01103 01104 /* Disable pins: SCK and SD pins */ 01105 gpio_init_structure.Pin = AUDIO_I2Sx_SCK_PIN; 01106 HAL_GPIO_DeInit(AUDIO_I2Sx_SCK_GPIO_PORT, gpio_init_structure.Pin); 01107 gpio_init_structure.Pin = AUDIO_I2Sx_SD_PIN; 01108 HAL_GPIO_DeInit(AUDIO_I2Sx_SD_GPIO_PORT, gpio_init_structure.Pin); 01109 01110 /* Disable I2S clock */ 01111 AUDIO_I2Sx_CLK_DISABLE(); 01112 01113 /* GPIO pins clock and DMA clock can be shut down in the application 01114 by surcharging this __weak function */ 01115 } 01116 01117 01118 /******************************************************************************* 01119 Static Functions 01120 *******************************************************************************/ 01121 01122 /** 01123 * @brief Initializes the PDM library. 01124 * @param AudioFreq: Audio sampling frequency 01125 * @param ChnlNbr: Number of audio channels (1: mono; 2: stereo) 01126 * @retval None 01127 */ 01128 static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr) 01129 { 01130 uint32_t i = 0; 01131 01132 /* Enable CRC peripheral to unlock the PDM library */ 01133 __HAL_RCC_CRC_CLK_ENABLE(); 01134 01135 for(i = 0; i < ChnlNbr; i++) 01136 { 01137 /* Filter LP & HP Init */ 01138 Filter[i].LP_HZ = AudioFreq/2; 01139 Filter[i].HP_HZ = 10; 01140 Filter[i].Fs = AudioFreq; 01141 Filter[i].Out_MicChannels = ChnlNbr; 01142 Filter[i].In_MicChannels = ChnlNbr; 01143 PDM_Filter_Init((PDMFilter_InitStruct *)&Filter[i]); 01144 } 01145 } 01146 01147 /** 01148 * @brief Initializes the Audio Codec audio interface (I2S) 01149 * @note This function assumes that the I2S input clock (through PLL_R in 01150 * Devices RevA/Z and through dedicated PLLI2S_R in Devices RevB/Y) 01151 * is already configured and ready to be used. 01152 * @param AudioFreq: Audio frequency to be configured for the I2S peripheral. 01153 * @retval None 01154 */ 01155 static void I2Sx_Init(uint32_t AudioFreq) 01156 { 01157 /* Initialize the haudio_in_i2s Instance parameter */ 01158 haudio_in_i2s.Instance = AUDIO_I2Sx; 01159 01160 /* Disable I2S block */ 01161 __HAL_I2S_DISABLE(&haudio_in_i2s); 01162 01163 /* I2S2 peripheral configuration */ 01164 haudio_in_i2s.Init.AudioFreq = 4 * AudioFreq; 01165 haudio_in_i2s.Init.ClockSource = I2S_CLOCK_SYSCLK; 01166 haudio_in_i2s.Init.CPOL = I2S_CPOL_HIGH; 01167 haudio_in_i2s.Init.DataFormat = I2S_DATAFORMAT_16B; 01168 haudio_in_i2s.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE; 01169 haudio_in_i2s.Init.Mode = I2S_MODE_MASTER_RX; 01170 haudio_in_i2s.Init.Standard = I2S_STANDARD_LSB; 01171 01172 /* Init the I2S */ 01173 HAL_I2S_Init(&haudio_in_i2s); 01174 01175 /* Enable I2S peripheral */ 01176 __HAL_I2S_ENABLE(&haudio_in_i2s); 01177 } 01178 01179 /** 01180 * @brief Deinitializes the Audio Codec audio interface (I2S). 01181 * @retval None 01182 */ 01183 static void I2Sx_DeInit(void) 01184 { 01185 /* Initialize the haudio_in_i2s Instance parameter */ 01186 haudio_in_i2s.Instance = AUDIO_I2Sx; 01187 01188 /* Disable I2S block */ 01189 __HAL_I2S_DISABLE(&haudio_in_i2s); 01190 01191 /* DeInit the I2S */ 01192 HAL_I2S_DeInit(&haudio_in_i2s); 01193 } 01194 01195 01196 /** 01197 * @brief Initializes the TIM INput Capture MSP. 01198 * @param htim: TIM handle 01199 * @retval None 01200 */ 01201 static void TIMx_IC_MspInit(TIM_HandleTypeDef *htim) 01202 { 01203 GPIO_InitTypeDef gpio_init_structure; 01204 01205 /* Enable peripherals and GPIO Clocks --------------------------------------*/ 01206 /* TIMx Peripheral clock enable */ 01207 AUDIO_TIMx_CLK_ENABLE(); 01208 01209 /* Enable GPIO Channels Clock */ 01210 AUDIO_TIMx_GPIO_CLK_ENABLE(); 01211 01212 /* Configure I/Os ----------------------------------------------------------*/ 01213 /* Common configuration for all channels */ 01214 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 01215 gpio_init_structure.Pull = GPIO_NOPULL; 01216 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 01217 gpio_init_structure.Alternate = AUDIO_TIMx_AF; 01218 01219 /* Configure TIM input channel */ 01220 gpio_init_structure.Pin = AUDIO_TIMx_IN_GPIO_PIN; 01221 HAL_GPIO_Init(AUDIO_TIMx_GPIO_PORT, &gpio_init_structure); 01222 01223 /* Configure TIM output channel */ 01224 gpio_init_structure.Pin = AUDIO_TIMx_OUT_GPIO_PIN; 01225 HAL_GPIO_Init(AUDIO_TIMx_GPIO_PORT, &gpio_init_structure); 01226 01227 } 01228 01229 /** 01230 * @brief Initializes the TIM INput Capture MSP. 01231 * @param htim: TIM handle 01232 * @retval None 01233 */ 01234 static void TIMx_IC_MspDeInit(TIM_HandleTypeDef *htim) 01235 { 01236 /* Disable TIMx Peripheral clock */ 01237 AUDIO_TIMx_CLK_DISABLE(); 01238 01239 /* GPIO pins clock and DMA clock can be shut down in the application 01240 by surcharging this __weak function */ 01241 } 01242 01243 /** 01244 * @brief Configure TIM as a clock divider by 2. 01245 * I2S_SCK is externally connected to TIMx input channel 01246 * @retval None 01247 */ 01248 static void TIMx_Init(void) 01249 { 01250 TIM_IC_InitTypeDef s_ic_config; 01251 TIM_OC_InitTypeDef s_oc_config; 01252 TIM_ClockConfigTypeDef s_clk_source_config; 01253 TIM_SlaveConfigTypeDef s_slave_config; 01254 01255 /* Configure the TIM peripheral --------------------------------------------*/ 01256 /* Set TIMx instance */ 01257 haudio_tim.Instance = AUDIO_TIMx; 01258 /* Timer Input Capture Configuration Structure declaration */ 01259 /* Initialize TIMx peripheral as follow: 01260 + Period = 0xFFFF 01261 + Prescaler = 0 01262 + ClockDivision = 0 01263 + Counter direction = Up 01264 */ 01265 haudio_tim.Init.Period = 1; 01266 haudio_tim.Init.Prescaler = 0; 01267 haudio_tim.Init.ClockDivision = 0; 01268 haudio_tim.Init.CounterMode = TIM_COUNTERMODE_UP; 01269 01270 /* Initialize the TIMx peripheral with the structure above */ 01271 TIMx_IC_MspInit(&haudio_tim); 01272 HAL_TIM_IC_Init(&haudio_tim); 01273 01274 /* Configure the Input Capture channel -------------------------------------*/ 01275 /* Configure the Input Capture of channel 2 */ 01276 s_ic_config.ICPolarity = TIM_ICPOLARITY_FALLING; 01277 s_ic_config.ICSelection = TIM_ICSELECTION_DIRECTTI; 01278 s_ic_config.ICPrescaler = TIM_ICPSC_DIV1; 01279 s_ic_config.ICFilter = 0; 01280 HAL_TIM_IC_ConfigChannel(&haudio_tim, &s_ic_config, AUDIO_TIMx_IN_CHANNEL); 01281 01282 /* Select external clock mode 1 */ 01283 s_clk_source_config.ClockSource = TIM_CLOCKSOURCE_ETRMODE1; 01284 s_clk_source_config.ClockPolarity = TIM_CLOCKPOLARITY_NONINVERTED; 01285 s_clk_source_config.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1; 01286 s_clk_source_config.ClockFilter = 0; 01287 HAL_TIM_ConfigClockSource(&haudio_tim, &s_clk_source_config); 01288 01289 /* Select Input Channel as input trigger */ 01290 s_slave_config.InputTrigger = TIM_TS_TI1FP1; 01291 s_slave_config.SlaveMode = TIM_SLAVEMODE_EXTERNAL1; 01292 s_slave_config.TriggerPolarity = TIM_TRIGGERPOLARITY_NONINVERTED; 01293 s_slave_config.TriggerPrescaler = TIM_CLOCKPRESCALER_DIV1; 01294 s_slave_config.TriggerFilter = 0; 01295 HAL_TIM_SlaveConfigSynchronization(&haudio_tim, &s_slave_config); 01296 01297 /* Output Compare PWM Mode configuration: Channel2 */ 01298 s_oc_config.OCMode = TIM_OCMODE_PWM1; 01299 s_oc_config.OCIdleState = TIM_OCIDLESTATE_SET; 01300 s_oc_config.Pulse = 1; 01301 s_oc_config.OCPolarity = TIM_OCPOLARITY_HIGH; 01302 s_oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH; 01303 s_oc_config.OCFastMode = TIM_OCFAST_DISABLE; 01304 s_oc_config.OCNIdleState = TIM_OCNIDLESTATE_SET; 01305 01306 /* Initialize the TIM3 Channel2 with the structure above */ 01307 HAL_TIM_PWM_ConfigChannel(&haudio_tim, &s_oc_config, AUDIO_TIMx_OUT_CHANNEL); 01308 01309 /* Start the TIM3 Channel2 */ 01310 HAL_TIM_PWM_Start(&haudio_tim, AUDIO_TIMx_OUT_CHANNEL); 01311 01312 /* Start the TIM3 Channel1 */ 01313 HAL_TIM_IC_Start(&haudio_tim, AUDIO_TIMx_IN_CHANNEL); 01314 } 01315 01316 /** 01317 * @brief Configure TIM as a clock divider by 2. 01318 * I2S_SCK is externally connected to TIMx input channel 01319 * @retval None 01320 */ 01321 static void TIMx_DeInit(void) 01322 { 01323 haudio_tim.Instance = AUDIO_TIMx; 01324 01325 /* Stop the TIM4 Channel2 */ 01326 HAL_TIM_PWM_Stop(&haudio_tim, AUDIO_TIMx_OUT_CHANNEL); 01327 /* Stop the TIM4 Channel1 */ 01328 HAL_TIM_IC_Stop(&haudio_tim, AUDIO_TIMx_IN_CHANNEL); 01329 01330 HAL_TIM_IC_DeInit(&haudio_tim); 01331 01332 /* Initialize the TIMx peripheral with the structure above */ 01333 TIMx_IC_MspDeInit(&haudio_tim); 01334 } 01335 01336 /** 01337 * @} 01338 */ 01339 01340 /** 01341 * @} 01342 */ 01343 01344 /** 01345 * @} 01346 */ 01347 01348 /** 01349 * @} 01350 */ 01351 01352 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Fri Dec 30 2016 19:47:41 for STM32756G_EVAL BSP User Manual by
