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