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 V1.0.0 00006 * @date 22-May-2015 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) 2015 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 CODEC_Reset(void); 00171 static void SAIx_Init(uint32_t AudioFreq); 00172 static void SAIx_DeInit(void); 00173 static void I2Sx_Init(uint32_t AudioFreq); 00174 static void I2Sx_DeInit(void); 00175 static void TIMx_IC_MspInit(TIM_HandleTypeDef *htim); 00176 static void TIMx_IC_MspDeInit(TIM_HandleTypeDef *htim); 00177 static void TIMx_Init(void); 00178 static void TIMx_DeInit(void); 00179 static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr); 00180 /** 00181 * @} 00182 */ 00183 00184 /** @defgroup STM32756G_EVAL_AUDIO_out_Private_Functions STM32756G_EVAL_AUDIO_Out Private Functions 00185 * @{ 00186 */ 00187 00188 /** 00189 * @brief Configures the audio peripherals. 00190 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00191 * or OUTPUT_DEVICE_BOTH. 00192 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00193 * @param AudioFreq: Audio frequency used to play the audio stream. 00194 * @note The I2S PLL input clock must be done in the user application. 00195 * @retval AUDIO_OK if correct communication, else wrong communication 00196 */ 00197 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00198 { 00199 uint8_t ret = AUDIO_ERROR; 00200 uint32_t deviceid = 0x00; 00201 00202 /* Disable SAI */ 00203 SAIx_DeInit(); 00204 00205 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00206 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00207 00208 /* SAI data transfer preparation: 00209 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00210 haudio_out_sai.Instance = AUDIO_SAIx; 00211 if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET) 00212 { 00213 /* Init the SAI MSP: this __weak function can be redefined by the application*/ 00214 BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL); 00215 } 00216 SAIx_Init(AudioFreq); 00217 00218 /* Reset the Codec Registers */ 00219 CODEC_Reset(); 00220 00221 /* wm8994 codec initialization */ 00222 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00223 00224 if((deviceid) == WM8994_ID) 00225 { 00226 /* Initialize the audio driver structure */ 00227 audio_drv = &wm8994_drv; 00228 ret = AUDIO_OK; 00229 } 00230 else 00231 { 00232 ret = AUDIO_ERROR; 00233 } 00234 00235 if(ret == AUDIO_OK) 00236 { 00237 /* Initialize the codec internal registers */ 00238 audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq); 00239 } 00240 00241 return ret; 00242 } 00243 00244 /** 00245 * @brief Starts playing audio stream from a data buffer for a determined size. 00246 * @param pBuffer: Pointer to the buffer 00247 * @param Size: Number of audio data BYTES. 00248 * @retval AUDIO_OK if correct communication, else wrong communication 00249 */ 00250 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size) 00251 { 00252 /* Call the audio Codec Play function */ 00253 if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0) 00254 { 00255 return AUDIO_ERROR; 00256 } 00257 else 00258 { 00259 /* Update the Media layer and enable it for play */ 00260 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE)); 00261 00262 return AUDIO_OK; 00263 } 00264 } 00265 00266 /** 00267 * @brief Sends n-Bytes on the SAI interface. 00268 * @param pData: pointer on data address 00269 * @param Size: number of data to be written 00270 * @retval None 00271 */ 00272 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size) 00273 { 00274 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size); 00275 } 00276 00277 /** 00278 * @brief This function Pauses the audio file stream. In case 00279 * of using DMA, the DMA Pause feature is used. 00280 * @WARNING When calling BSP_AUDIO_OUT_Pause() function for pause, only 00281 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00282 * function for resume could lead to unexpected behaviour). 00283 * @retval AUDIO_OK if correct communication, else wrong communication 00284 */ 00285 uint8_t BSP_AUDIO_OUT_Pause(void) 00286 { 00287 /* Call the Audio Codec Pause/Resume function */ 00288 if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0) 00289 { 00290 return AUDIO_ERROR; 00291 } 00292 else 00293 { 00294 /* Call the Media layer pause function */ 00295 HAL_SAI_DMAPause(&haudio_out_sai); 00296 00297 /* Return AUDIO_OK when all operations are correctly done */ 00298 return AUDIO_OK; 00299 } 00300 } 00301 00302 /** 00303 * @brief This function Resumes the audio file stream. 00304 * @WARNING When calling BSP_AUDIO_OUT_Pause() function for pause, only 00305 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00306 * function for resume could lead to unexpected behaviour). 00307 * @retval AUDIO_OK if correct communication, else wrong communication 00308 */ 00309 uint8_t BSP_AUDIO_OUT_Resume(void) 00310 { 00311 /* Call the Audio Codec Pause/Resume function */ 00312 if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0) 00313 { 00314 return AUDIO_ERROR; 00315 } 00316 else 00317 { 00318 /* Call the Media layer pause/resume function */ 00319 HAL_SAI_DMAResume(&haudio_out_sai); 00320 00321 /* Return AUDIO_OK when all operations are correctly done */ 00322 return AUDIO_OK; 00323 } 00324 } 00325 00326 /** 00327 * @brief Stops audio playing and Power down the Audio Codec. 00328 * @param Option: could be one of the following parameters 00329 * - CODEC_PDWN_SW: for software power off (by writing registers). 00330 * Then no need to reconfigure the Codec after power on. 00331 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00332 * Then need to reconfigure the Codec after power on. 00333 * @retval AUDIO_OK if correct communication, else wrong communication 00334 */ 00335 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option) 00336 { 00337 /* Call the Media layer stop function */ 00338 HAL_SAI_DMAStop(&haudio_out_sai); 00339 00340 /* Call Audio Codec Stop function */ 00341 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 00342 { 00343 return AUDIO_ERROR; 00344 } 00345 else 00346 { 00347 if(Option == CODEC_PDWN_HW) 00348 { 00349 /* Wait at least 100us */ 00350 HAL_Delay(1); 00351 } 00352 /* Return AUDIO_OK when all operations are correctly done */ 00353 return AUDIO_OK; 00354 } 00355 } 00356 00357 /** 00358 * @brief Controls the current audio volume level. 00359 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00360 * Mute and 100 for Max volume level). 00361 * @retval AUDIO_OK if correct communication, else wrong communication 00362 */ 00363 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume) 00364 { 00365 /* Call the codec volume control function with converted volume value */ 00366 if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 00367 { 00368 return AUDIO_ERROR; 00369 } 00370 else 00371 { 00372 /* Return AUDIO_OK when all operations are correctly done */ 00373 return AUDIO_OK; 00374 } 00375 } 00376 00377 /** 00378 * @brief Enables or disables the MUTE mode by software 00379 * @param Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 00380 * unmute the codec and restore previous volume level. 00381 * @retval AUDIO_OK if correct communication, else wrong communication 00382 */ 00383 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd) 00384 { 00385 /* Call the Codec Mute function */ 00386 if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0) 00387 { 00388 return AUDIO_ERROR; 00389 } 00390 else 00391 { 00392 /* Return AUDIO_OK when all operations are correctly done */ 00393 return AUDIO_OK; 00394 } 00395 } 00396 00397 /** 00398 * @brief Switch dynamically (while audio file is played) the output target 00399 * (speaker or headphone). 00400 * @param Output: The audio output target: OUTPUT_DEVICE_SPEAKER, 00401 * OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH 00402 * @retval AUDIO_OK if correct communication, else wrong communication 00403 */ 00404 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output) 00405 { 00406 /* Call the Codec output device function */ 00407 if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0) 00408 { 00409 return AUDIO_ERROR; 00410 } 00411 else 00412 { 00413 /* Return AUDIO_OK when all operations are correctly done */ 00414 return AUDIO_OK; 00415 } 00416 } 00417 00418 /** 00419 * @brief Updates the audio frequency. 00420 * @param AudioFreq: Audio frequency used to play the audio stream. 00421 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00422 * audio frequency. 00423 * @retval None 00424 */ 00425 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq) 00426 { 00427 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 00428 BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL); 00429 00430 /* Disable SAI peripheral to allow access to SAI internal registers */ 00431 __HAL_SAI_DISABLE(&haudio_out_sai); 00432 00433 /* Update the SAI audio frequency configuration */ 00434 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00435 HAL_SAI_Init(&haudio_out_sai); 00436 00437 /* Enable SAI peripheral to generate MCLK */ 00438 __HAL_SAI_ENABLE(&haudio_out_sai); 00439 } 00440 00441 /** 00442 * @brief Updates the Audio frame slot configuration. 00443 * @param AudioFrameSlot: specifies the audio Frame slot 00444 * This parameter can be any value of @ref CODEC_AudioFrame_SLOT_TDMMode 00445 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00446 * audio frame slot. 00447 * @retval None 00448 */ 00449 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot) 00450 { 00451 /* Disable SAI peripheral to allow access to SAI internal registers */ 00452 __HAL_SAI_DISABLE(&haudio_out_sai); 00453 00454 /* Update the SAI audio frame slot configuration */ 00455 haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot; 00456 HAL_SAI_Init(&haudio_out_sai); 00457 00458 /* Enable SAI peripheral to generate MCLK */ 00459 __HAL_SAI_ENABLE(&haudio_out_sai); 00460 } 00461 00462 /** 00463 * @brief Deinit the audio peripherals. 00464 * @retval None 00465 */ 00466 void BSP_AUDIO_OUT_DeInit(void) 00467 { 00468 SAIx_DeInit(); 00469 /* DeInit the SAI MSP : this __weak function can be rewritten by the application */ 00470 BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL); 00471 } 00472 00473 /** 00474 * @brief Tx Transfer completed callbacks. 00475 * @param hsai: SAI handle 00476 * @retval None 00477 */ 00478 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) 00479 { 00480 /* Manage the remaining file size and new address offset: This function 00481 should be coded by user (its prototype is already declared in stm32756g_eval_audio.h) */ 00482 BSP_AUDIO_OUT_TransferComplete_CallBack(); 00483 } 00484 00485 /** 00486 * @brief Tx Half Transfer completed callbacks. 00487 * @param hsai: SAI handle 00488 * @retval None 00489 */ 00490 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 00491 { 00492 /* Manage the remaining file size and new address offset: This function 00493 should be coded by user (its prototype is already declared in stm32756g_eval_audio.h) */ 00494 BSP_AUDIO_OUT_HalfTransfer_CallBack(); 00495 } 00496 00497 /** 00498 * @brief SAI error callbacks. 00499 * @param hsai: SAI handle 00500 * @retval None 00501 */ 00502 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 00503 { 00504 BSP_AUDIO_OUT_Error_CallBack(); 00505 } 00506 00507 /** 00508 * @brief Manages the DMA full Transfer complete event. 00509 * @retval None 00510 */ 00511 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void) 00512 { 00513 } 00514 00515 /** 00516 * @brief Manages the DMA Half Transfer complete event. 00517 * @retval None 00518 */ 00519 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) 00520 { 00521 } 00522 00523 /** 00524 * @brief Manages the DMA FIFO error event. 00525 * @retval None 00526 */ 00527 __weak void BSP_AUDIO_OUT_Error_CallBack(void) 00528 { 00529 } 00530 00531 /** 00532 * @brief Initializes BSP_AUDIO_OUT MSP. 00533 * @param hsai: SAI handle 00534 * @retval None 00535 */ 00536 __weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params) 00537 { 00538 static DMA_HandleTypeDef hdma_sai_tx; 00539 GPIO_InitTypeDef gpio_init_structure; 00540 00541 /* Enable SAI clock */ 00542 AUDIO_SAIx_CLK_ENABLE(); 00543 00544 /* Enable GPIO clock */ 00545 AUDIO_SAIx_MCLK_ENABLE(); 00546 AUDIO_SAIx_SCK_SD_ENABLE(); 00547 AUDIO_SAIx_FS_ENABLE(); 00548 /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/ 00549 gpio_init_structure.Pin = AUDIO_SAIx_FS_PIN; 00550 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00551 gpio_init_structure.Pull = GPIO_NOPULL; 00552 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00553 gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF; 00554 HAL_GPIO_Init(AUDIO_SAIx_FS_GPIO_PORT, &gpio_init_structure); 00555 00556 gpio_init_structure.Pin = AUDIO_SAIx_SCK_PIN; 00557 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00558 gpio_init_structure.Pull = GPIO_NOPULL; 00559 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00560 gpio_init_structure.Alternate = AUDIO_SAIx_SCK_AF; 00561 HAL_GPIO_Init(AUDIO_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure); 00562 00563 gpio_init_structure.Pin = AUDIO_SAIx_SD_PIN; 00564 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00565 gpio_init_structure.Pull = GPIO_NOPULL; 00566 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00567 gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF; 00568 HAL_GPIO_Init(AUDIO_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure); 00569 00570 gpio_init_structure.Pin = AUDIO_SAIx_MCLK_PIN; 00571 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 00572 gpio_init_structure.Pull = GPIO_NOPULL; 00573 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 00574 gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF; 00575 HAL_GPIO_Init(AUDIO_SAIx_MCLK_GPIO_PORT, &gpio_init_structure); 00576 00577 /* Enable the DMA clock */ 00578 AUDIO_SAIx_DMAx_CLK_ENABLE(); 00579 00580 if(hsai->Instance == AUDIO_SAIx) 00581 { 00582 /* Configure the hdma_saiTx handle parameters */ 00583 hdma_sai_tx.Init.Channel = AUDIO_SAIx_DMAx_CHANNEL; 00584 hdma_sai_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; 00585 hdma_sai_tx.Init.PeriphInc = DMA_PINC_DISABLE; 00586 hdma_sai_tx.Init.MemInc = DMA_MINC_ENABLE; 00587 hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_SAIx_DMAx_PERIPH_DATA_SIZE; 00588 hdma_sai_tx.Init.MemDataAlignment = AUDIO_SAIx_DMAx_MEM_DATA_SIZE; 00589 hdma_sai_tx.Init.Mode = DMA_CIRCULAR; 00590 hdma_sai_tx.Init.Priority = DMA_PRIORITY_HIGH; 00591 hdma_sai_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; 00592 hdma_sai_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 00593 hdma_sai_tx.Init.MemBurst = DMA_MBURST_SINGLE; 00594 hdma_sai_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; 00595 00596 hdma_sai_tx.Instance = AUDIO_SAIx_DMAx_STREAM; 00597 00598 /* Associate the DMA handle */ 00599 __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx); 00600 00601 /* Deinitialize the Stream for new transfer */ 00602 HAL_DMA_DeInit(&hdma_sai_tx); 00603 00604 /* Configure the DMA Stream */ 00605 HAL_DMA_Init(&hdma_sai_tx); 00606 } 00607 00608 /* SAI DMA IRQ Channel configuration */ 00609 HAL_NVIC_SetPriority(AUDIO_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 00610 HAL_NVIC_EnableIRQ(AUDIO_SAIx_DMAx_IRQ); 00611 } 00612 00613 /** 00614 * @brief Deinitializes SAI MSP. 00615 * @param hsai: SAI handle 00616 * @retval None 00617 */ 00618 __weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params) 00619 { 00620 GPIO_InitTypeDef gpio_init_structure; 00621 00622 /* SAI DMA IRQ Channel deactivation */ 00623 HAL_NVIC_DisableIRQ(AUDIO_SAIx_DMAx_IRQ); 00624 00625 if(hsai->Instance == AUDIO_SAIx) 00626 { 00627 /* Deinitialize the DMA stream */ 00628 HAL_DMA_DeInit(hsai->hdmatx); 00629 } 00630 00631 /* Disable SAI peripheral */ 00632 __HAL_SAI_DISABLE(hsai); 00633 00634 /* Deactivates CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */ 00635 gpio_init_structure.Pin = AUDIO_SAIx_FS_PIN; 00636 HAL_GPIO_DeInit(AUDIO_SAIx_FS_GPIO_PORT, gpio_init_structure.Pin); 00637 00638 gpio_init_structure.Pin = AUDIO_SAIx_SCK_PIN; 00639 HAL_GPIO_DeInit(AUDIO_SAIx_SCK_SD_GPIO_PORT, gpio_init_structure.Pin); 00640 00641 gpio_init_structure.Pin = AUDIO_SAIx_SD_PIN; 00642 HAL_GPIO_DeInit(AUDIO_SAIx_SCK_SD_GPIO_PORT, gpio_init_structure.Pin); 00643 00644 gpio_init_structure.Pin = AUDIO_SAIx_MCLK_PIN; 00645 HAL_GPIO_DeInit(AUDIO_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin); 00646 00647 /* Disable SAI clock */ 00648 AUDIO_SAIx_CLK_DISABLE(); 00649 00650 /* GPIO pins clock and DMA clock can be shut down in the applic 00651 by surcharging this __weak function */ 00652 } 00653 00654 /** 00655 * @brief Clock Config. 00656 * @param hsai: might be required to set audio peripheral predivider if any. 00657 * @param AudioFreq: Audio frequency used to play the audio stream. 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_RISINGEDGE; 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 * @brief Resets the audio codec. It restores the default configuration of the 00778 * codec (this function shall be called before initializing the codec). 00779 * @retval None 00780 */ 00781 static void CODEC_Reset(void) 00782 { 00783 /* Initialize the audio driver structure */ 00784 audio_drv = &wm8994_drv; 00785 00786 audio_drv->Reset(AUDIO_I2C_ADDRESS); 00787 } 00788 00789 /** 00790 * @} 00791 */ 00792 00793 /** @defgroup STM32756G_EVAL_AUDIO_out_Private_Functions STM32756G_EVAL_AUDIO_Out Private Functions 00794 * @{ 00795 */ 00796 00797 /** 00798 * @brief Initializes wave recording. 00799 * @note This function assumes that the I2S input clock (through PLL_R in 00800 * Devices RevA/Z and through dedicated PLLI2S_R in Devices RevB/Y) 00801 * is already configured and ready to be used. 00802 * @param AudioFreq: Audio frequency to be configured for the I2S peripheral. 00803 * @param BitRes: Audio frequency to be configured for the I2S peripheral. 00804 * @param ChnlNbr: Audio frequency to be configured for the I2S peripheral. 00805 * @retval AUDIO_OK if correct communication, else wrong communication 00806 */ 00807 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00808 { 00809 RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct; 00810 00811 /* Disable I2S */ 00812 I2Sx_DeInit(); 00813 00814 HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct); 00815 rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_I2S; 00816 rcc_ex_clk_init_struct.I2sClockSelection = RCC_I2SCLKSOURCE_PLLI2S; 00817 rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 384; 00818 rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 2; 00819 HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 00820 00821 /* Configure the PDM library */ 00822 PDMDecoder_Init(AudioFreq, ChnlNbr); 00823 00824 /* Configure the I2S peripheral */ 00825 haudio_in_i2s.Instance = AUDIO_I2Sx; 00826 if(HAL_I2S_GetState(&haudio_in_i2s) == HAL_I2S_STATE_RESET) 00827 { 00828 /* Initialize the I2S Msp: this __weak function can be rewritten by the application */ 00829 BSP_AUDIO_IN_MspInit(&haudio_in_i2s, NULL); 00830 } 00831 I2Sx_Init(AudioFreq); 00832 00833 /* Return AUDIO_OK when all operations are correctly done */ 00834 return AUDIO_OK; 00835 } 00836 00837 /** 00838 * @brief Starts audio recording. 00839 * @param pbuf: Main buffer pointer for the recorded data storing 00840 * @param size: Current size of the recorded buffer 00841 * @retval AUDIO_OK if correct communication, else wrong communication 00842 */ 00843 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size) 00844 { 00845 uint32_t ret = AUDIO_ERROR; 00846 00847 /* Start the process receive DMA */ 00848 HAL_I2S_Receive_DMA(&haudio_in_i2s, pbuf, size); 00849 00850 /* Return AUDIO_OK when all operations are correctly done */ 00851 ret = AUDIO_OK; 00852 00853 return ret; 00854 } 00855 00856 /** 00857 * @brief Stops audio recording. 00858 * @retval AUDIO_OK if correct communication, else wrong communication 00859 */ 00860 uint8_t BSP_AUDIO_IN_Stop(void) 00861 { 00862 uint32_t ret = AUDIO_ERROR; 00863 /* Call the Media layer stop function */ 00864 HAL_I2S_DMAStop(&haudio_in_i2s); 00865 00866 /* TIMx Peripheral clock disable */ 00867 AUDIO_TIMx_CLK_DISABLE(); 00868 00869 /* Return AUDIO_OK when all operations are correctly done */ 00870 ret = AUDIO_OK; 00871 00872 return ret; 00873 } 00874 00875 /** 00876 * @brief Pauses the audio file stream. 00877 * @retval AUDIO_OK if correct communication, else wrong communication 00878 */ 00879 uint8_t BSP_AUDIO_IN_Pause(void) 00880 { 00881 /* Call the Media layer pause function */ 00882 HAL_I2S_DMAPause(&haudio_in_i2s); 00883 /* Return AUDIO_OK when all operations are correctly done */ 00884 return AUDIO_OK; 00885 } 00886 00887 /** 00888 * @brief Resumes the audio file stream. 00889 * @retval AUDIO_OK if correct communication, else wrong communication 00890 */ 00891 uint8_t BSP_AUDIO_IN_Resume(void) 00892 { 00893 /* Call the Media layer pause/resume function */ 00894 HAL_I2S_DMAResume(&haudio_in_i2s); 00895 /* Return AUDIO_OK when all operations are correctly done */ 00896 return AUDIO_OK; 00897 } 00898 00899 /** 00900 * @brief Controls the audio in volume level. 00901 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00902 * Mute and 100 for Max volume level). 00903 * @retval AUDIO_OK if correct communication, else wrong communication 00904 */ 00905 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume) 00906 { 00907 /* Set the Global variable AudioInVolume */ 00908 AudioInVolume = Volume; 00909 00910 /* Return AUDIO_OK when all operations are correctly done */ 00911 return AUDIO_OK; 00912 } 00913 00914 /** 00915 * @brief Deinit the audio IN peripherals. 00916 * @retval None 00917 */ 00918 void BSP_AUDIO_IN_DeInit(void) 00919 { 00920 I2Sx_DeInit(); 00921 /* DeInit the I2S MSP : this __weak function can be rewritten by the application */ 00922 BSP_AUDIO_IN_MspDeInit(&haudio_in_i2s, NULL); 00923 TIMx_DeInit(); 00924 } 00925 00926 /** 00927 * @brief Converts audio format from PDM to PCM. 00928 * @param PDMBuf: Pointer to data PDM buffer 00929 * @param PCMBuf: Pointer to data PCM buffer 00930 * @retval AUDIO_OK if correct communication, else wrong communication 00931 */ 00932 uint8_t BSP_AUDIO_IN_PDMToPCM(uint16_t* PDMBuf, uint16_t* PCMBuf) 00933 { 00934 uint8_t app_pdm[INTERNAL_BUFF_SIZE*2]; 00935 uint8_t byte1 = 0, byte2 = 0; 00936 uint32_t index = 0; 00937 00938 /* PDM Demux */ 00939 for(index = 0; index<INTERNAL_BUFF_SIZE/2; index++) 00940 { 00941 byte2 = (PDMBuf[index] >> 8)& 0xFF; 00942 byte1 = (PDMBuf[index] & 0xFF); 00943 app_pdm[(index*2)+1] = Channel_Demux[byte1 & CHANNEL_DEMUX_MASK] | Channel_Demux[byte2 & CHANNEL_DEMUX_MASK] << 4; 00944 app_pdm[(index*2)] = Channel_Demux[(byte1 >> 1) & CHANNEL_DEMUX_MASK] | Channel_Demux[(byte2 >> 1) & CHANNEL_DEMUX_MASK] << 4; 00945 } 00946 00947 for(index = 0; index < DEFAULT_AUDIO_IN_CHANNEL_NBR; index++) 00948 { 00949 /* PDM to PCM filter */ 00950 PDM_Filter_64_LSB((uint8_t*)&app_pdm[index], (uint16_t*)&(PCMBuf[index]), AudioInVolume , (PDMFilter_InitStruct *)&Filter[index]); 00951 } 00952 00953 /* Return AUDIO_OK when all operations are correctly done */ 00954 return AUDIO_OK; 00955 } 00956 00957 /** 00958 * @brief Rx Transfer completed callbacks. 00959 * @param hi2s: I2S handle 00960 * @retval None 00961 */ 00962 void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) 00963 { 00964 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 00965 BSP_AUDIO_IN_TransferComplete_CallBack(); 00966 } 00967 00968 /** 00969 * @brief Rx Half Transfer completed callbacks. 00970 * @param hi2s: I2S handle 00971 * @retval None 00972 */ 00973 void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s) 00974 { 00975 /* Manage the remaining file size and new address offset: This function 00976 should be coded by user (its prototype is already declared in stm32756g_eval_audio.h) */ 00977 BSP_AUDIO_IN_HalfTransfer_CallBack(); 00978 } 00979 00980 /** 00981 * @brief I2S error callbacks. 00982 * @param hi2s: I2S handle 00983 * @retval None 00984 */ 00985 void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s) 00986 { 00987 /* Manage the error generated on DMA FIFO: This function 00988 should be coded by user (its prototype is already declared in stm32756g_eval_audio.h) */ 00989 BSP_AUDIO_IN_Error_Callback(); 00990 } 00991 00992 /** 00993 * @brief User callback when record buffer is filled. 00994 * @retval None 00995 */ 00996 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void) 00997 { 00998 /* This function should be implemented by the user application. 00999 It is called into this driver when the current buffer is filled 01000 to prepare the next buffer pointer and its size. */ 01001 } 01002 01003 /** 01004 * @brief Manages the DMA Half Transfer complete event. 01005 * @retval None 01006 */ 01007 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 01008 { 01009 /* This function should be implemented by the user application. 01010 It is called into this driver when the current buffer is filled 01011 to prepare the next buffer pointer and its size. */ 01012 } 01013 01014 /** 01015 * @brief Audio IN Error callback function. 01016 * @retval None 01017 */ 01018 __weak void BSP_AUDIO_IN_Error_Callback(void) 01019 { 01020 /* This function is called when an Interrupt due to transfer error on or peripheral 01021 error occurs. */ 01022 } 01023 01024 /** 01025 * @brief Initializes BSP_AUDIO_IN MSP. 01026 * @param hi2s: I2S handle 01027 * @retval None 01028 */ 01029 __weak void BSP_AUDIO_IN_MspInit(I2S_HandleTypeDef *hi2s, void *Params) 01030 { 01031 static DMA_HandleTypeDef hdma_i2s_rx; 01032 GPIO_InitTypeDef gpio_init_structure; 01033 01034 /* Configure the Timer which clocks the MEMS */ 01035 /* Moved inside MSP to allow applic to redefine the TIMx_MspInit */ 01036 TIMx_Init(); 01037 01038 /* Enable I2S clock */ 01039 AUDIO_I2Sx_CLK_ENABLE(); 01040 01041 /* Enable SCK and SD GPIO clock */ 01042 AUDIO_I2Sx_SD_GPIO_CLK_ENABLE(); 01043 AUDIO_I2Sx_SCK_GPIO_CLK_ENABLE(); 01044 /* CODEC_I2S pins configuration: SCK and SD pins */ 01045 gpio_init_structure.Pin = AUDIO_I2Sx_SCK_PIN; 01046 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 01047 gpio_init_structure.Pull = GPIO_NOPULL; 01048 gpio_init_structure.Speed = GPIO_SPEED_FAST; 01049 gpio_init_structure.Alternate = AUDIO_I2Sx_SCK_AF; 01050 HAL_GPIO_Init(AUDIO_I2Sx_SCK_GPIO_PORT, &gpio_init_structure); 01051 01052 gpio_init_structure.Pin = AUDIO_I2Sx_SD_PIN; 01053 gpio_init_structure.Alternate = AUDIO_I2Sx_SD_AF; 01054 HAL_GPIO_Init(AUDIO_I2Sx_SD_GPIO_PORT, &gpio_init_structure); 01055 01056 /* Enable the DMA clock */ 01057 AUDIO_I2Sx_DMAx_CLK_ENABLE(); 01058 01059 if(hi2s->Instance == AUDIO_I2Sx) 01060 { 01061 /* Configure the hdma_i2s_rx handle parameters */ 01062 hdma_i2s_rx.Init.Channel = AUDIO_I2Sx_DMAx_CHANNEL; 01063 hdma_i2s_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; 01064 hdma_i2s_rx.Init.PeriphInc = DMA_PINC_DISABLE; 01065 hdma_i2s_rx.Init.MemInc = DMA_MINC_ENABLE; 01066 hdma_i2s_rx.Init.PeriphDataAlignment = AUDIO_I2Sx_DMAx_PERIPH_DATA_SIZE; 01067 hdma_i2s_rx.Init.MemDataAlignment = AUDIO_I2Sx_DMAx_MEM_DATA_SIZE; 01068 hdma_i2s_rx.Init.Mode = DMA_CIRCULAR; 01069 hdma_i2s_rx.Init.Priority = DMA_PRIORITY_HIGH; 01070 hdma_i2s_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 01071 hdma_i2s_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 01072 hdma_i2s_rx.Init.MemBurst = DMA_MBURST_SINGLE; 01073 hdma_i2s_rx.Init.PeriphBurst = DMA_MBURST_SINGLE; 01074 01075 hdma_i2s_rx.Instance = AUDIO_I2Sx_DMAx_STREAM; 01076 01077 /* Associate the DMA handle */ 01078 __HAL_LINKDMA(hi2s, hdmarx, hdma_i2s_rx); 01079 01080 /* Deinitialize the Stream for new transfer */ 01081 HAL_DMA_DeInit(&hdma_i2s_rx); 01082 01083 /* Configure the DMA Stream */ 01084 HAL_DMA_Init(&hdma_i2s_rx); 01085 } 01086 01087 /* I2S DMA IRQ Channel configuration */ 01088 HAL_NVIC_SetPriority(AUDIO_I2Sx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 01089 HAL_NVIC_EnableIRQ(AUDIO_I2Sx_DMAx_IRQ); 01090 } 01091 01092 /** 01093 * @brief DeInitializes BSP_AUDIO_IN MSP. 01094 * @param hi2s: I2S handle 01095 * @retval None 01096 */ 01097 __weak void BSP_AUDIO_IN_MspDeInit(I2S_HandleTypeDef *hi2s, void *Params) 01098 { 01099 GPIO_InitTypeDef gpio_init_structure; 01100 01101 static DMA_HandleTypeDef hdma_i2s_rx; 01102 01103 /* I2S DMA IRQ Channel deactivation */ 01104 HAL_NVIC_DisableIRQ(AUDIO_I2Sx_DMAx_IRQ); 01105 01106 if(hi2s->Instance == AUDIO_I2Sx) 01107 { 01108 /* Deinitialize the Stream for new transfer */ 01109 HAL_DMA_DeInit(&hdma_i2s_rx); 01110 } 01111 01112 /* Disable I2S block */ 01113 __HAL_I2S_DISABLE(hi2s); 01114 01115 /* Disable pins: SCK and SD pins */ 01116 gpio_init_structure.Pin = AUDIO_I2Sx_SCK_PIN; 01117 HAL_GPIO_DeInit(AUDIO_I2Sx_SCK_GPIO_PORT, gpio_init_structure.Pin); 01118 gpio_init_structure.Pin = AUDIO_I2Sx_SD_PIN; 01119 HAL_GPIO_DeInit(AUDIO_I2Sx_SD_GPIO_PORT, gpio_init_structure.Pin); 01120 01121 /* Disable I2S clock */ 01122 AUDIO_I2Sx_CLK_DISABLE(); 01123 01124 /* GPIO pins clock and DMA clock can be shut down in the application 01125 by surcharging this __weak function */ 01126 } 01127 01128 01129 /******************************************************************************* 01130 Static Functions 01131 *******************************************************************************/ 01132 01133 /** 01134 * @brief Initializes the PDM library. 01135 * @param AudioFreq: Audio sampling frequency 01136 * @param ChnlNbr: Number of audio channels (1: mono; 2: stereo) 01137 * @retval None 01138 */ 01139 static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr) 01140 { 01141 uint32_t i = 0; 01142 01143 /* Enable CRC peripheral to unlock the PDM library */ 01144 __HAL_RCC_CRC_CLK_ENABLE(); 01145 01146 for(i = 0; i < ChnlNbr; i++) 01147 { 01148 /* Filter LP & HP Init */ 01149 Filter[i].LP_HZ = AudioFreq/2; 01150 Filter[i].HP_HZ = 10; 01151 Filter[i].Fs = AudioFreq; 01152 Filter[i].Out_MicChannels = ChnlNbr; 01153 Filter[i].In_MicChannels = ChnlNbr; 01154 PDM_Filter_Init((PDMFilter_InitStruct *)&Filter[i]); 01155 } 01156 } 01157 01158 /** 01159 * @brief Initializes the Audio Codec audio interface (I2S) 01160 * @note This function assumes that the I2S input clock (through PLL_R in 01161 * Devices RevA/Z and through dedicated PLLI2S_R in Devices RevB/Y) 01162 * is already configured and ready to be used. 01163 * @param AudioFreq: Audio frequency to be configured for the I2S peripheral. 01164 * @retval None 01165 */ 01166 static void I2Sx_Init(uint32_t AudioFreq) 01167 { 01168 /* Initialize the haudio_in_i2s Instance parameter */ 01169 haudio_in_i2s.Instance = AUDIO_I2Sx; 01170 01171 /* Disable I2S block */ 01172 __HAL_I2S_DISABLE(&haudio_in_i2s); 01173 01174 /* I2S2 peripheral configuration */ 01175 haudio_in_i2s.Init.AudioFreq = 4 * AudioFreq; 01176 haudio_in_i2s.Init.ClockSource = I2S_CLOCK_SYSCLK; 01177 haudio_in_i2s.Init.CPOL = I2S_CPOL_HIGH; 01178 haudio_in_i2s.Init.DataFormat = I2S_DATAFORMAT_16B; 01179 haudio_in_i2s.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE; 01180 haudio_in_i2s.Init.Mode = I2S_MODE_MASTER_RX; 01181 haudio_in_i2s.Init.Standard = I2S_STANDARD_LSB; 01182 01183 /* Init the I2S */ 01184 HAL_I2S_Init(&haudio_in_i2s); 01185 01186 /* Enable I2S peripheral */ 01187 __HAL_I2S_ENABLE(&haudio_in_i2s); 01188 } 01189 01190 /** 01191 * @brief Deinitializes the Audio Codec audio interface (I2S). 01192 * @retval None 01193 */ 01194 static void I2Sx_DeInit(void) 01195 { 01196 /* Initialize the haudio_in_i2s Instance parameter */ 01197 haudio_in_i2s.Instance = AUDIO_I2Sx; 01198 01199 /* Disable I2S block */ 01200 __HAL_I2S_DISABLE(&haudio_in_i2s); 01201 01202 /* DeInit the I2S */ 01203 HAL_I2S_DeInit(&haudio_in_i2s); 01204 } 01205 01206 01207 /** 01208 * @brief Initializes the TIM INput Capture MSP. 01209 * @param htim: TIM handle 01210 * @retval None 01211 */ 01212 static void TIMx_IC_MspInit(TIM_HandleTypeDef *htim) 01213 { 01214 GPIO_InitTypeDef gpio_init_structure; 01215 01216 /* Enable peripherals and GPIO Clocks --------------------------------------*/ 01217 /* TIMx Peripheral clock enable */ 01218 AUDIO_TIMx_CLK_ENABLE(); 01219 01220 /* Enable GPIO Channels Clock */ 01221 AUDIO_TIMx_GPIO_CLK_ENABLE(); 01222 01223 /* Configure I/Os ----------------------------------------------------------*/ 01224 /* Common configuration for all channels */ 01225 gpio_init_structure.Mode = GPIO_MODE_AF_PP; 01226 gpio_init_structure.Pull = GPIO_NOPULL; 01227 gpio_init_structure.Speed = GPIO_SPEED_HIGH; 01228 gpio_init_structure.Alternate = AUDIO_TIMx_AF; 01229 01230 /* Configure TIM input channel */ 01231 gpio_init_structure.Pin = AUDIO_TIMx_IN_GPIO_PIN; 01232 HAL_GPIO_Init(AUDIO_TIMx_GPIO_PORT, &gpio_init_structure); 01233 01234 /* Configure TIM output channel */ 01235 gpio_init_structure.Pin = AUDIO_TIMx_OUT_GPIO_PIN; 01236 HAL_GPIO_Init(AUDIO_TIMx_GPIO_PORT, &gpio_init_structure); 01237 01238 } 01239 01240 /** 01241 * @brief Initializes the TIM INput Capture MSP. 01242 * @param htim: TIM handle 01243 * @retval None 01244 */ 01245 static void TIMx_IC_MspDeInit(TIM_HandleTypeDef *htim) 01246 { 01247 /* Disable TIMx Peripheral clock */ 01248 AUDIO_TIMx_CLK_DISABLE(); 01249 01250 /* GPIO pins clock and DMA clock can be shut down in the application 01251 by surcharging this __weak function */ 01252 } 01253 01254 /** 01255 * @brief Configure TIM as a clock divider by 2. 01256 * I2S_SCK is externally connected to TIMx input channel 01257 * @retval None 01258 */ 01259 static void TIMx_Init(void) 01260 { 01261 TIM_IC_InitTypeDef s_ic_config; 01262 TIM_OC_InitTypeDef s_oc_config; 01263 TIM_ClockConfigTypeDef s_clk_source_config; 01264 TIM_SlaveConfigTypeDef s_slave_config; 01265 01266 /* Configure the TIM peripheral --------------------------------------------*/ 01267 /* Set TIMx instance */ 01268 haudio_tim.Instance = AUDIO_TIMx; 01269 /* Timer Input Capture Configuration Structure declaration */ 01270 /* Initialize TIMx peripheral as follow: 01271 + Period = 0xFFFF 01272 + Prescaler = 0 01273 + ClockDivision = 0 01274 + Counter direction = Up 01275 */ 01276 haudio_tim.Init.Period = 1; 01277 haudio_tim.Init.Prescaler = 0; 01278 haudio_tim.Init.ClockDivision = 0; 01279 haudio_tim.Init.CounterMode = TIM_COUNTERMODE_UP; 01280 01281 /* Initialize the TIMx peripheral with the structure above */ 01282 TIMx_IC_MspInit(&haudio_tim); 01283 HAL_TIM_IC_Init(&haudio_tim); 01284 01285 /* Configure the Input Capture channel -------------------------------------*/ 01286 /* Configure the Input Capture of channel 2 */ 01287 s_ic_config.ICPolarity = TIM_ICPOLARITY_FALLING; 01288 s_ic_config.ICSelection = TIM_ICSELECTION_DIRECTTI; 01289 s_ic_config.ICPrescaler = TIM_ICPSC_DIV1; 01290 s_ic_config.ICFilter = 0; 01291 HAL_TIM_IC_ConfigChannel(&haudio_tim, &s_ic_config, AUDIO_TIMx_IN_CHANNEL); 01292 01293 /* Select external clock mode 1 */ 01294 s_clk_source_config.ClockSource = TIM_CLOCKSOURCE_ETRMODE1; 01295 s_clk_source_config.ClockPolarity = TIM_CLOCKPOLARITY_NONINVERTED; 01296 s_clk_source_config.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1; 01297 s_clk_source_config.ClockFilter = 0; 01298 HAL_TIM_ConfigClockSource(&haudio_tim, &s_clk_source_config); 01299 01300 /* Select Input Channel as input trigger */ 01301 s_slave_config.InputTrigger = TIM_TS_TI1FP1; 01302 s_slave_config.SlaveMode = TIM_SLAVEMODE_EXTERNAL1; 01303 s_slave_config.TriggerPolarity = TIM_TRIGGERPOLARITY_NONINVERTED; 01304 s_slave_config.TriggerPrescaler = TIM_CLOCKPRESCALER_DIV1; 01305 s_slave_config.TriggerFilter = 0; 01306 HAL_TIM_SlaveConfigSynchronization(&haudio_tim, &s_slave_config); 01307 01308 /* Output Compare PWM Mode configuration: Channel2 */ 01309 s_oc_config.OCMode = TIM_OCMODE_PWM1; 01310 s_oc_config.OCIdleState = TIM_OCIDLESTATE_SET; 01311 s_oc_config.Pulse = 1; 01312 s_oc_config.OCPolarity = TIM_OCPOLARITY_HIGH; 01313 s_oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH; 01314 s_oc_config.OCFastMode = TIM_OCFAST_DISABLE; 01315 s_oc_config.OCNIdleState = TIM_OCNIDLESTATE_SET; 01316 01317 /* Initialize the TIM3 Channel2 with the structure above */ 01318 HAL_TIM_PWM_ConfigChannel(&haudio_tim, &s_oc_config, AUDIO_TIMx_OUT_CHANNEL); 01319 01320 /* Start the TIM3 Channel2 */ 01321 HAL_TIM_PWM_Start(&haudio_tim, AUDIO_TIMx_OUT_CHANNEL); 01322 01323 /* Start the TIM3 Channel1 */ 01324 HAL_TIM_IC_Start(&haudio_tim, AUDIO_TIMx_IN_CHANNEL); 01325 } 01326 01327 /** 01328 * @brief Configure TIM as a clock divider by 2. 01329 * I2S_SCK is externally connected to TIMx input channel 01330 * @retval None 01331 */ 01332 static void TIMx_DeInit(void) 01333 { 01334 haudio_tim.Instance = AUDIO_TIMx; 01335 01336 /* Stop the TIM4 Channel2 */ 01337 HAL_TIM_PWM_Stop(&haudio_tim, AUDIO_TIMx_OUT_CHANNEL); 01338 /* Stop the TIM4 Channel1 */ 01339 HAL_TIM_IC_Stop(&haudio_tim, AUDIO_TIMx_IN_CHANNEL); 01340 01341 HAL_TIM_IC_DeInit(&haudio_tim); 01342 01343 /* Initialize the TIMx peripheral with the structure above */ 01344 TIMx_IC_MspDeInit(&haudio_tim); 01345 } 01346 01347 /** 01348 * @} 01349 */ 01350 01351 /** 01352 * @} 01353 */ 01354 01355 /** 01356 * @} 01357 */ 01358 01359 /** 01360 * @} 01361 */ 01362 01363 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Fri May 22 2015 13:59:20 for STM32756G_EVAL BSP User Manual by 1.7.6.1