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