STM324x9I_EVAL BSP User Manual
|
stm324x9i_eval_audio.c
Go to the documentation of this file.
00001 /** 00002 ****************************************************************************** 00003 * @file stm324x9i_eval_audio.c 00004 * @author MCD Application Team 00005 * @version V2.2.2 00006 * @date 13-January-2016 00007 * @brief This file provides the Audio driver for the STM324x9I-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 STM324x9I-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 IOExpander 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 + Call the function BSP_EVAL_AUDIO_OUT_Play( 00060 pBuffer: pointer to the audio data file address 00061 Size : size of the buffer to be sent in Bytes 00062 ) 00063 to start playing (for the first time) from the audio file/stream. 00064 + Call the function BSP_AUDIO_OUT_Pause() to pause playing 00065 + Call the function BSP_AUDIO_OUT_Resume() to resume playing. 00066 Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called 00067 for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case). 00068 Note. This function should be called only when the audio file is played or paused (not stopped). 00069 + For each mode, you may need to implement the relative callback functions into your code. 00070 The Callback functions are named AUDIO_OUT_XXX_CallBack() and only their prototypes are declared in 00071 the stm324x9i_eval_audio.h file. (refer to the example for more details on the callbacks implementations) 00072 + To Stop playing, to modify the volume level, the frequency, the audio frame slot, 00073 the device output mode the mute or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(), 00074 AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetAudioFrameSlot(), BSP_AUDIO_OUT_SetOutputMode(), 00075 BSP_AUDIO_OUT_SetMute() and BSP_AUDIO_OUT_Stop(). 00076 + The driver API and the callback functions are at the end of the stm324x9i_eval_audio.h file. 00077 00078 Driver architecture: 00079 -------------------- 00080 + This driver provide the High Audio Layer: consists of the function API exported in the stm324x9i_eval_audio.h file 00081 (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...) 00082 + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/ 00083 providing the audio file/stream. These functions are also included as local functions into 00084 the stm324x9i_eval_audio_codec.c file (SAIx_MspInit() and SAIx_Init()) 00085 00086 Known Limitations: 00087 ------------------ 00088 1- If the TDM Format used to paly in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second 00089 Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams. 00090 2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 00091 File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file. 00092 3- Supports only Stereo audio streaming. 00093 4- Supports only 16-bits audio data size. 00094 ==============================================================================*/ 00095 00096 /* Includes ------------------------------------------------------------------*/ 00097 #include "stm324x9i_eval_audio.h" 00098 00099 /** @addtogroup BSP 00100 * @{ 00101 */ 00102 00103 /** @addtogroup STM324x9I_EVAL 00104 * @{ 00105 */ 00106 00107 /** @defgroup STM324x9I_EVAL_AUDIO STM324x9I EVAL AUDIO 00108 * @brief This file includes the low layer driver for wm8994 Audio Codec 00109 * available on STM324x9I-EVAL evaluation board(MB1045). 00110 * @{ 00111 */ 00112 00113 /** @defgroup STM324x9I_EVAL_AUDIO_Private_Types STM324x9I EVAL AUDIO Private Types 00114 * @{ 00115 */ 00116 /** 00117 * @} 00118 */ 00119 00120 /** @defgroup STM324x9I_EVAL_AUDIO_Private_Defines STM324x9I EVAL AUDIO Private Defines 00121 * @{ 00122 */ 00123 /** 00124 * @} 00125 */ 00126 00127 /** @defgroup STM324x9I_EVAL_AUDIO_Private_Macros STM324x9I EVAL AUDIO Private Macros 00128 * @{ 00129 */ 00130 /** 00131 * @} 00132 */ 00133 00134 /** @defgroup STM324x9I_EVAL_AUDIO_Private_Variables STM324x9I EVAL AUDIO Private Variables 00135 * @{ 00136 */ 00137 AUDIO_DrvTypeDef *audio_drv; 00138 SAI_HandleTypeDef haudio_out_sai; 00139 I2S_HandleTypeDef haudio_in_i2s; 00140 TIM_HandleTypeDef haudio_tim; 00141 00142 PDMFilter_InitStruct Filter[2]; 00143 uint8_t Channel_Demux[128] = { 00144 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x02, 0x03, 00145 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x02, 0x03, 00146 0x04, 0x05, 0x04, 0x05, 0x06, 0x07, 0x06, 0x07, 00147 0x04, 0x05, 0x04, 0x05, 0x06, 0x07, 0x06, 0x07, 00148 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x02, 0x03, 00149 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x02, 0x03, 00150 0x04, 0x05, 0x04, 0x05, 0x06, 0x07, 0x06, 0x07, 00151 0x04, 0x05, 0x04, 0x05, 0x06, 0x07, 0x06, 0x07, 00152 0x08, 0x09, 0x08, 0x09, 0x0a, 0x0b, 0x0a, 0x0b, 00153 0x08, 0x09, 0x08, 0x09, 0x0a, 0x0b, 0x0a, 0x0b, 00154 0x0c, 0x0d, 0x0c, 0x0d, 0x0e, 0x0f, 0x0e, 0x0f, 00155 0x0c, 0x0d, 0x0c, 0x0d, 0x0e, 0x0f, 0x0e, 0x0f, 00156 0x08, 0x09, 0x08, 0x09, 0x0a, 0x0b, 0x0a, 0x0b, 00157 0x08, 0x09, 0x08, 0x09, 0x0a, 0x0b, 0x0a, 0x0b, 00158 0x0c, 0x0d, 0x0c, 0x0d, 0x0e, 0x0f, 0x0e, 0x0f, 00159 0x0c, 0x0d, 0x0c, 0x0d, 0x0e, 0x0f, 0x0e, 0x0f 00160 }; 00161 00162 uint16_t __IO AudioInVolume = DEFAULT_AUDIO_IN_VOLUME; 00163 00164 /** 00165 * @} 00166 */ 00167 00168 /** @defgroup STM324x9I_EVAL_AUDIO_Private_Function_Prototypes STM324x9I EVAL AUDIO Private Function Prototypes 00169 * @{ 00170 */ 00171 static void SAIx_MspInit(void); 00172 static void SAIx_Init(uint32_t AudioFreq); 00173 static void I2Sx_MspInit(void); 00174 static void I2Sx_Init(uint32_t AudioFreq); 00175 static void TIMx_IC_MspInit(TIM_HandleTypeDef *htim); 00176 static void TIMx_Init(void); 00177 static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr); 00178 /** 00179 * @} 00180 */ 00181 00182 /** @defgroup STM324x9I_EVAL_AUDIO_out_Private_Functions STM324x9I EVAL AUDIO OUT Private Functions 00183 * @{ 00184 */ 00185 00186 /** 00187 * @brief Configures the audio peripherals. 00188 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00189 * or OUTPUT_DEVICE_BOTH. 00190 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00191 * @param AudioFreq: Audio frequency used to play the audio stream. 00192 * @note The I2S PLL input clock must be done in the user application. 00193 * @retval AUDIO_OK if correct communication, else wrong communication 00194 */ 00195 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00196 { 00197 uint8_t ret = AUDIO_ERROR; 00198 uint32_t deviceid = 0x00; 00199 RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct; 00200 00201 HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct); 00202 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 00203 { 00204 /* Configure PLLSAI prescalers */ 00205 /* PLLI2S_VCO: VCO_429M 00206 SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 429/2 = 214.5 Mhz 00207 SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 214.5/19 = 11.289 Mhz */ 00208 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI_PLLI2S; 00209 RCC_ExCLKInitStruct.PLLI2S.PLLI2SN = 429; 00210 RCC_ExCLKInitStruct.PLLI2S.PLLI2SQ = 2; 00211 RCC_ExCLKInitStruct.PLLI2SDivQ = 19; 00212 HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct); 00213 } 00214 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K), AUDIO_FREQUENCY_96K */ 00215 { 00216 /* SAI clock config 00217 PLLI2S_VCO: VCO_344M 00218 SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 344/7 = 49.142 Mhz 00219 SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 49.142/1 = 49.142 Mhz */ 00220 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI_PLLI2S; 00221 RCC_ExCLKInitStruct.PLLI2S.PLLI2SN = 344; 00222 RCC_ExCLKInitStruct.PLLI2S.PLLI2SQ = 7; 00223 RCC_ExCLKInitStruct.PLLI2SDivQ = 1; 00224 HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct); 00225 } 00226 00227 /* SAI data transfer preparation: 00228 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00229 SAIx_Init(AudioFreq); 00230 00231 /* wm8994 codec initialization */ 00232 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00233 00234 if((deviceid) == WM8994_ID) 00235 { 00236 /* Initialize the audio driver structure */ 00237 audio_drv = &wm8994_drv; 00238 ret = AUDIO_OK; 00239 } 00240 else 00241 { 00242 ret = AUDIO_ERROR; 00243 } 00244 00245 if(ret == AUDIO_OK) 00246 { 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 RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct; 00436 00437 HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct); 00438 00439 /* Update the PLL configuration according to the new frequency */ 00440 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 00441 { 00442 /* Configure PLLSAI prescalers */ 00443 /* PLLSAI_VCO: VCO_429M 00444 SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 429/2 = 214.5 Mhz 00445 SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 214.5/19 = 11.289 Mhz */ 00446 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI_PLLI2S; 00447 RCC_ExCLKInitStruct.PLLI2S.PLLI2SN = 429; 00448 RCC_ExCLKInitStruct.PLLI2S.PLLI2SQ = 2; 00449 RCC_ExCLKInitStruct.PLLI2SDivQ = 19; 00450 HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct); 00451 } 00452 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K), AUDIO_FREQUENCY_96K */ 00453 { 00454 /* SAI clock config 00455 PLLI2S_VCO: VCO_344M 00456 SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 344/7 = 49.142 Mhz 00457 SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 49.142/1 = 49.142 Mhz */ 00458 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI_PLLI2S; 00459 RCC_ExCLKInitStruct.PLLI2S.PLLI2SN = 344; 00460 RCC_ExCLKInitStruct.PLLI2S.PLLI2SQ = 7; 00461 RCC_ExCLKInitStruct.PLLI2SDivQ = 1; 00462 HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct); 00463 } 00464 /* Disable SAI peripheral to allow access to SAI internal registers */ 00465 __HAL_SAI_DISABLE(&haudio_out_sai); 00466 00467 /* Update the SAI audio frequency configuration */ 00468 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00469 HAL_SAI_Init(&haudio_out_sai); 00470 00471 /* Enable SAI peripheral to generate MCLK */ 00472 __HAL_SAI_ENABLE(&haudio_out_sai); 00473 } 00474 00475 /** 00476 * @brief Updates the Audio frame slot configuration. 00477 * @param AudioFrameSlot: specifies the audio Frame slot 00478 * This parameter can be any value of @ref CODEC_AudioFrame_SLOT_TDMMode 00479 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00480 * audio frame slot. 00481 */ 00482 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot) 00483 { 00484 /* Disable SAI peripheral to allow access to SAI internal registers */ 00485 __HAL_SAI_DISABLE(&haudio_out_sai); 00486 00487 /* Update the SAI audio frame slot configuration */ 00488 haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot; 00489 HAL_SAI_Init(&haudio_out_sai); 00490 00491 /* Enable SAI peripheral to generate MCLK */ 00492 __HAL_SAI_ENABLE(&haudio_out_sai); 00493 } 00494 00495 /** 00496 * @brief Tx Transfer completed callbacks. 00497 * @param hsai: SAI handle 00498 */ 00499 void HAL_SAI_TxCpltCallback(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 stm324x9i_eval_audio.h) */ 00503 BSP_AUDIO_OUT_TransferComplete_CallBack(); 00504 } 00505 00506 /** 00507 * @brief Tx Half Transfer completed callbacks. 00508 * @param hsai: SAI handle 00509 */ 00510 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 00511 { 00512 /* Manage the remaining file size and new address offset: This function 00513 should be coded by user (its prototype is already declared in stm324x9i_eval_audio.h) */ 00514 BSP_AUDIO_OUT_HalfTransfer_CallBack(); 00515 } 00516 00517 /** 00518 * @brief SAI error callbacks. 00519 * @param hsai: SAI handle 00520 */ 00521 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 00522 { 00523 BSP_AUDIO_OUT_Error_CallBack(); 00524 } 00525 00526 /** 00527 * @brief Manages the DMA full Transfer complete event. 00528 */ 00529 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void) 00530 { 00531 } 00532 00533 /** 00534 * @brief Manages the DMA Half Transfer complete event. 00535 */ 00536 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) 00537 { 00538 } 00539 00540 /** 00541 * @brief Manages the DMA FIFO error event. 00542 */ 00543 __weak void BSP_AUDIO_OUT_Error_CallBack(void) 00544 { 00545 } 00546 00547 /******************************************************************************* 00548 Static Functions 00549 *******************************************************************************/ 00550 00551 /** 00552 * @brief Initializes SAI MSP. 00553 */ 00554 static void SAIx_MspInit(void) 00555 { 00556 static DMA_HandleTypeDef hdma_saiTx; 00557 GPIO_InitTypeDef GPIO_InitStruct; 00558 SAI_HandleTypeDef *hsai = &haudio_out_sai; 00559 00560 /* Enable SAI clock */ 00561 AUDIO_SAIx_CLK_ENABLE(); 00562 00563 /* Enable GPIO clock */ 00564 AUDIO_SAIx_MCLK_SCK_SD_FS_ENABLE(); 00565 00566 /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/ 00567 GPIO_InitStruct.Pin = AUDIO_SAIx_FS_PIN | AUDIO_SAIx_SCK_PIN | AUDIO_SAIx_SD_PIN | AUDIO_SAIx_MCK_PIN; 00568 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 00569 GPIO_InitStruct.Pull = GPIO_NOPULL; 00570 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; 00571 GPIO_InitStruct.Alternate = AUDIO_SAIx_MCLK_SCK_SD_FS_AF; 00572 HAL_GPIO_Init(AUDIO_SAIx_MCLK_SCK_SD_FS_GPIO_PORT, &GPIO_InitStruct); 00573 00574 /* Enable the DMA clock */ 00575 AUDIO_SAIx_DMAx_CLK_ENABLE(); 00576 00577 if(hsai->Instance == AUDIO_SAIx) 00578 { 00579 /* Configure the hdma_saiTx handle parameters */ 00580 hdma_saiTx.Init.Channel = AUDIO_SAIx_DMAx_CHANNEL; 00581 hdma_saiTx.Init.Direction = DMA_MEMORY_TO_PERIPH; 00582 hdma_saiTx.Init.PeriphInc = DMA_PINC_DISABLE; 00583 hdma_saiTx.Init.MemInc = DMA_MINC_ENABLE; 00584 hdma_saiTx.Init.PeriphDataAlignment = AUDIO_SAIx_DMAx_PERIPH_DATA_SIZE; 00585 hdma_saiTx.Init.MemDataAlignment = AUDIO_SAIx_DMAx_MEM_DATA_SIZE; 00586 hdma_saiTx.Init.Mode = DMA_NORMAL; 00587 hdma_saiTx.Init.Priority = DMA_PRIORITY_HIGH; 00588 hdma_saiTx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; 00589 hdma_saiTx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 00590 hdma_saiTx.Init.MemBurst = DMA_MBURST_SINGLE; 00591 hdma_saiTx.Init.PeriphBurst = DMA_PBURST_SINGLE; 00592 00593 hdma_saiTx.Instance = AUDIO_SAIx_DMAx_STREAM; 00594 00595 /* Associate the DMA handle */ 00596 __HAL_LINKDMA(hsai, hdmatx, hdma_saiTx); 00597 00598 /* Deinitialize the Stream for new transfer */ 00599 HAL_DMA_DeInit(&hdma_saiTx); 00600 00601 /* Configure the DMA Stream */ 00602 HAL_DMA_Init(&hdma_saiTx); 00603 } 00604 00605 /* SAI DMA IRQ Channel configuration */ 00606 HAL_NVIC_SetPriority(AUDIO_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 00607 HAL_NVIC_EnableIRQ(AUDIO_SAIx_DMAx_IRQ); 00608 } 00609 00610 /** 00611 * @brief Initializes the Audio Codec audio interface (SAI). 00612 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00613 * @note The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 00614 * and user can update this configuration using 00615 */ 00616 static void SAIx_Init(uint32_t AudioFreq) 00617 { 00618 /* Initialize the haudio_out_sai Instance parameter */ 00619 haudio_out_sai.Instance = AUDIO_SAIx; 00620 00621 /* Disable SAI peripheral to allow access to SAI internal registers */ 00622 __HAL_SAI_DISABLE(&haudio_out_sai); 00623 00624 /* Configure SAI_Block_x 00625 LSBFirst: Disabled 00626 DataSize: 16 */ 00627 haudio_out_sai.Init.AudioFrequency = AudioFreq; 00628 haudio_out_sai.Init.ClockSource = SAI_CLKSOURCE_PLLI2S; 00629 haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX; 00630 haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED; 00631 haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL; 00632 haudio_out_sai.Init.DataSize = SAI_DATASIZE_16; 00633 haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 00634 haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 00635 haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS; 00636 haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLED; 00637 haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 00638 00639 /* Configure SAI_Block_x Frame 00640 Frame Length: 64 00641 Frame active Length: 32 00642 FS Definition: Start frame + Channel Side identification 00643 FS Polarity: FS active Low 00644 FS Offset: FS asserted one bit before the first bit of slot 0 */ 00645 haudio_out_sai.FrameInit.FrameLength = 64; 00646 haudio_out_sai.FrameInit.ActiveFrameLength = 32; 00647 haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 00648 haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 00649 haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 00650 00651 /* Configure SAI Block_x Slot 00652 Slot First Bit Offset: 0 00653 Slot Size : 16 00654 Slot Number: 4 00655 Slot Active: All slot actives */ 00656 haudio_out_sai.SlotInit.FirstBitOffset = 0; 00657 haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 00658 haudio_out_sai.SlotInit.SlotNumber = 4; 00659 haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123; 00660 if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET) 00661 { 00662 /* Init the SAI */ 00663 SAIx_MspInit(); 00664 } 00665 HAL_SAI_Init(&haudio_out_sai); 00666 00667 /* Enable SAI peripheral to generate MCLK */ 00668 __HAL_SAI_ENABLE(&haudio_out_sai); 00669 } 00670 00671 /** 00672 * @brief Initializes wave recording. 00673 * @note This function assumes that the I2S input clock (through PLL_R in 00674 * Devices RevA/Z and through dedicated PLLI2S_R in Devices RevB/Y) 00675 * is already configured and ready to be used. 00676 * @param AudioFreq: Audio frequency to be configured for the I2S peripheral. 00677 * @param BitRes: Audio frequency to be configured for the I2S peripheral. 00678 * @param ChnlNbr: Audio frequency to be configured for the I2S peripheral. 00679 * @retval AUDIO_OK if correct communication, else wrong communication 00680 */ 00681 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00682 { 00683 RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct; 00684 00685 HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct); 00686 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S; 00687 RCC_ExCLKInitStruct.PLLI2S.PLLI2SN = 384; 00688 RCC_ExCLKInitStruct.PLLI2S.PLLI2SR = 2; 00689 HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct); 00690 00691 /* Configure the PDM library */ 00692 PDMDecoder_Init(AudioFreq, ChnlNbr); 00693 00694 /* Configure the Timer which clocks the MEMS */ 00695 TIMx_Init(); 00696 00697 /* Configure the I2S peripheral */ 00698 I2Sx_Init(AudioFreq); 00699 00700 /* Return AUDIO_OK when all operations are correctly done */ 00701 return AUDIO_OK; 00702 } 00703 00704 /** 00705 * @brief Starts audio recording. 00706 * @param pbuf: Main buffer pointer for the recorded data storing 00707 * @param size: Current size of the recorded buffer 00708 * @retval AUDIO_OK if correct communication, else wrong communication 00709 */ 00710 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size) 00711 { 00712 uint32_t ret = AUDIO_ERROR; 00713 00714 /* Start the process receive DMA */ 00715 HAL_I2S_Receive_DMA(&haudio_in_i2s, pbuf, size); 00716 00717 /* Return AUDIO_OK when all operations are correctly done */ 00718 ret = AUDIO_OK; 00719 00720 return ret; 00721 } 00722 00723 /** 00724 * @brief Stops audio recording. 00725 * @retval AUDIO_OK if correct communication, else wrong communication 00726 */ 00727 uint8_t BSP_AUDIO_IN_Stop(void) 00728 { 00729 uint32_t ret = AUDIO_ERROR; 00730 00731 /* Call the Media layer pause function */ 00732 HAL_I2S_DMAPause(&haudio_in_i2s); 00733 00734 /* TIMx Peripheral clock disable */ 00735 AUDIO_TIMx_CLK_DISABLE(); 00736 00737 /* Return AUDIO_OK when all operations are correctly done */ 00738 ret = AUDIO_OK; 00739 00740 return ret; 00741 } 00742 00743 /** 00744 * @brief Pauses the audio file stream. 00745 * @retval AUDIO_OK if correct communication, else wrong communication 00746 */ 00747 uint8_t BSP_AUDIO_IN_Pause(void) 00748 { 00749 /* Call the Media layer pause function */ 00750 HAL_I2S_DMAPause(&haudio_in_i2s); 00751 00752 /* Return AUDIO_OK when all operations are correctly done */ 00753 return AUDIO_OK; 00754 } 00755 00756 /** 00757 * @brief Resumes the audio file stream. 00758 * @retval AUDIO_OK if correct communication, else wrong communication 00759 */ 00760 uint8_t BSP_AUDIO_IN_Resume(void) 00761 { 00762 /* Call the Media layer pause/resume function */ 00763 HAL_I2S_DMAResume(&haudio_in_i2s); 00764 00765 /* Return AUDIO_OK when all operations are correctly done */ 00766 return AUDIO_OK; 00767 } 00768 00769 /** 00770 * @brief Controls the audio in volume level. 00771 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00772 * Mute and 100 for Max volume level). 00773 * @retval AUDIO_OK if correct communication, else wrong communication 00774 */ 00775 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume) 00776 { 00777 /* Set the Global variable AudioInVolume */ 00778 AudioInVolume = Volume; 00779 00780 /* Return AUDIO_OK when all operations are correctly done */ 00781 return AUDIO_OK; 00782 } 00783 00784 /** 00785 * @brief Converts audio format from PDM to PCM. 00786 * @param PDMBuf: Pointer to data PDM buffer 00787 * @param PCMBuf: Pointer to data PCM buffer 00788 * @retval AUDIO_OK if correct communication, else wrong communication 00789 */ 00790 uint8_t BSP_AUDIO_IN_PDMToPCM(uint16_t* PDMBuf, uint16_t* PCMBuf) 00791 { 00792 uint8_t AppPDM[INTERNAL_BUFF_SIZE*2]; 00793 uint8_t byte1 = 0, byte2 = 0; 00794 uint32_t index = 0; 00795 00796 /* PDM Demux */ 00797 for(index = 0; index<INTERNAL_BUFF_SIZE/2; index++) 00798 { 00799 byte2 = (PDMBuf[index] >> 8)& 0xFF; 00800 byte1 = (PDMBuf[index] & 0xFF); 00801 AppPDM[(index*2)+1] = Channel_Demux[byte1 & CHANNEL_DEMUX_MASK] | Channel_Demux[byte2 & CHANNEL_DEMUX_MASK] << 4; 00802 AppPDM[(index*2)] = Channel_Demux[(byte1 >> 1) & CHANNEL_DEMUX_MASK] | Channel_Demux[(byte2 >> 1) & CHANNEL_DEMUX_MASK] << 4; 00803 } 00804 00805 for(index = 0; index < DEFAULT_AUDIO_IN_CHANNEL_NBR; index++) 00806 { 00807 /* PDM to PCM filter */ 00808 PDM_Filter_64_LSB((uint8_t*)&AppPDM[index], (uint16_t*)&(PCMBuf[index]), AudioInVolume , (PDMFilter_InitStruct *)&Filter[index]); 00809 } 00810 00811 /* Return AUDIO_OK when all operations are correctly done */ 00812 return AUDIO_OK; 00813 } 00814 00815 /** 00816 * @brief Rx Transfer completed callbacks. 00817 * @param hi2s: I2S handle 00818 */ 00819 void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) 00820 { 00821 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 00822 BSP_AUDIO_IN_TransferComplete_CallBack(); 00823 } 00824 00825 /** 00826 * @brief Rx Half Transfer completed callbacks. 00827 * @param hi2s: I2S handle 00828 */ 00829 void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s) 00830 { 00831 /* Manage the remaining file size and new address offset: This function 00832 should be coded by user (its prototype is already declared in stm324x9i_eval_audio.h) */ 00833 BSP_AUDIO_IN_HalfTransfer_CallBack(); 00834 } 00835 00836 /** 00837 * @brief I2S error callbacks. 00838 * @param hi2s: I2S handle 00839 */ 00840 void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s) 00841 { 00842 /* Manage the error generated on DMA FIFO: This function 00843 should be coded by user (its prototype is already declared in stm324x9i_eval_audio.h) */ 00844 BSP_AUDIO_IN_Error_Callback(); 00845 } 00846 00847 /** 00848 * @brief User callback when record buffer is filled. 00849 */ 00850 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void) 00851 { 00852 /* This function should be implemented by the user application. 00853 It is called into this driver when the current buffer is filled 00854 to prepare the next buffer pointer and its size. */ 00855 } 00856 00857 /** 00858 * @brief Manages the DMA Half Transfer complete event. 00859 */ 00860 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 00861 { 00862 /* This function should be implemented by the user application. 00863 It is called into this driver when the current buffer is filled 00864 to prepare the next buffer pointer and its size. */ 00865 } 00866 00867 /** 00868 * @brief Audio IN Error callback function. 00869 */ 00870 __weak void BSP_AUDIO_IN_Error_Callback(void) 00871 { 00872 /* This function is called when an Interrupt due to transfer error on or peripheral 00873 error occurs. */ 00874 } 00875 00876 /******************************************************************************* 00877 Static Functions 00878 *******************************************************************************/ 00879 00880 /** 00881 * @brief Initializes the PDM library. 00882 * @param AudioFreq: Audio sampling frequency 00883 * @param ChnlNbr: Number of audio channels (1: mono; 2: stereo) 00884 */ 00885 static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr) 00886 { 00887 uint32_t i = 0; 00888 00889 /* Enable CRC peripheral to unlock the PDM library */ 00890 __CRC_CLK_ENABLE(); 00891 00892 for(i = 0; i < ChnlNbr; i++) 00893 { 00894 /* Filter LP & HP Init */ 00895 Filter[i].LP_HZ = AudioFreq/2; 00896 Filter[i].HP_HZ = 10; 00897 Filter[i].Fs = AudioFreq; 00898 Filter[i].Out_MicChannels = ChnlNbr; 00899 Filter[i].In_MicChannels = ChnlNbr; 00900 PDM_Filter_Init((PDMFilter_InitStruct *)&Filter[i]); 00901 } 00902 } 00903 00904 /** 00905 * @brief AUDIO IN I2S MSP Init. 00906 */ 00907 static void I2Sx_MspInit(void) 00908 { 00909 static DMA_HandleTypeDef hdma_i2sRx; 00910 GPIO_InitTypeDef GPIO_InitStruct; 00911 I2S_HandleTypeDef *hi2s = &haudio_in_i2s; 00912 00913 /* Enable I2S clock */ 00914 AUDIO_I2Sx_CLK_ENABLE(); 00915 00916 /* Enable SCK and SD GPIO clock */ 00917 AUDIO_I2Sx_SD_GPIO_CLK_ENABLE(); 00918 AUDIO_I2Sx_SCK_GPIO_CLK_ENABLE(); 00919 /* CODEC_I2S pins configuration: WS, SCK and SD pins */ 00920 GPIO_InitStruct.Pin = AUDIO_I2Sx_SCK_PIN; 00921 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 00922 GPIO_InitStruct.Pull = GPIO_NOPULL; 00923 GPIO_InitStruct.Speed = GPIO_SPEED_FAST; 00924 GPIO_InitStruct.Alternate = AUDIO_I2Sx_SCK_AF; 00925 HAL_GPIO_Init(AUDIO_I2Sx_SCK_GPIO_PORT, &GPIO_InitStruct); 00926 00927 GPIO_InitStruct.Pin = AUDIO_I2Sx_SD_PIN; 00928 GPIO_InitStruct.Alternate = AUDIO_I2Sx_SD_AF; 00929 HAL_GPIO_Init(AUDIO_I2Sx_SD_GPIO_PORT, &GPIO_InitStruct); 00930 00931 /* Enable the DMA clock */ 00932 AUDIO_I2Sx_DMAx_CLK_ENABLE(); 00933 00934 if(hi2s->Instance == AUDIO_I2Sx) 00935 { 00936 /* Configure the hdma_i2sRx handle parameters */ 00937 hdma_i2sRx.Init.Channel = AUDIO_I2Sx_DMAx_CHANNEL; 00938 hdma_i2sRx.Init.Direction = DMA_PERIPH_TO_MEMORY; 00939 hdma_i2sRx.Init.PeriphInc = DMA_PINC_DISABLE; 00940 hdma_i2sRx.Init.MemInc = DMA_MINC_ENABLE; 00941 hdma_i2sRx.Init.PeriphDataAlignment = AUDIO_I2Sx_DMAx_PERIPH_DATA_SIZE; 00942 hdma_i2sRx.Init.MemDataAlignment = AUDIO_I2Sx_DMAx_MEM_DATA_SIZE; 00943 hdma_i2sRx.Init.Mode = DMA_CIRCULAR; 00944 hdma_i2sRx.Init.Priority = DMA_PRIORITY_HIGH; 00945 hdma_i2sRx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; 00946 hdma_i2sRx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; 00947 hdma_i2sRx.Init.MemBurst = DMA_MBURST_SINGLE; 00948 hdma_i2sRx.Init.PeriphBurst = DMA_MBURST_SINGLE; 00949 00950 hdma_i2sRx.Instance = AUDIO_I2Sx_DMAx_STREAM; 00951 00952 /* Associate the DMA handle */ 00953 __HAL_LINKDMA(hi2s, hdmarx, hdma_i2sRx); 00954 00955 /* Deinitialize the Stream for new transfer */ 00956 HAL_DMA_DeInit(&hdma_i2sRx); 00957 00958 /* Configure the DMA Stream */ 00959 HAL_DMA_Init(&hdma_i2sRx); 00960 } 00961 00962 /* I2S DMA IRQ Channel configuration */ 00963 HAL_NVIC_SetPriority(AUDIO_I2Sx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0); 00964 HAL_NVIC_EnableIRQ(AUDIO_I2Sx_DMAx_IRQ); 00965 } 00966 00967 /** 00968 * @brief Initializes the Audio Codec audio interface (I2S) 00969 * @note This function assumes that the I2S input clock (through PLL_R in 00970 * Devices RevA/Z and through dedicated PLLI2S_R in Devices RevB/Y) 00971 * is already configured and ready to be used. 00972 * @param AudioFreq: Audio frequency to be configured for the I2S peripheral. 00973 */ 00974 static void I2Sx_Init(uint32_t AudioFreq) 00975 { 00976 /* Initialize the haudio_in_i2s Instance parameter */ 00977 haudio_in_i2s.Instance = AUDIO_I2Sx; 00978 00979 /* Disable I2S block */ 00980 __HAL_I2S_DISABLE(&haudio_in_i2s); 00981 00982 /* I2S2 peripheral configuration */ 00983 haudio_in_i2s.Init.AudioFreq = 4 * AudioFreq; 00984 haudio_in_i2s.Init.ClockSource = I2S_CLOCK_PLL; 00985 haudio_in_i2s.Init.CPOL = I2S_CPOL_HIGH; 00986 haudio_in_i2s.Init.DataFormat = I2S_DATAFORMAT_16B; 00987 haudio_in_i2s.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE; 00988 haudio_in_i2s.Init.Mode = I2S_MODE_MASTER_RX; 00989 haudio_in_i2s.Init.Standard = I2S_STANDARD_LSB; 00990 if(HAL_I2S_GetState(&haudio_in_i2s) == HAL_I2S_STATE_RESET) 00991 { 00992 /* Initialize the I2S peripheral with the structure above */ 00993 I2Sx_MspInit(); 00994 } 00995 00996 /* Init the I2S */ 00997 HAL_I2S_Init(&haudio_in_i2s); 00998 } 00999 01000 /** 01001 * @brief Initializes the TIM INput Capture MSP. 01002 * @param htim: TIM handle 01003 */ 01004 static void TIMx_IC_MspInit(TIM_HandleTypeDef *htim) 01005 { 01006 GPIO_InitTypeDef GPIO_InitStruct; 01007 01008 /* Enable peripherals and GPIO Clocks --------------------------------------*/ 01009 /* TIMx Peripheral clock enable */ 01010 AUDIO_TIMx_CLK_ENABLE(); 01011 01012 /* Enable GPIO Channels Clock */ 01013 AUDIO_TIMx_GPIO_CLK_ENABLE(); 01014 01015 /* Configure I/Os ----------------------------------------------------------*/ 01016 /* Common configuration for all channels */ 01017 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 01018 GPIO_InitStruct.Pull = GPIO_NOPULL; 01019 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; 01020 GPIO_InitStruct.Alternate = AUDIO_TIMx_AF; 01021 01022 /* Configure TIM input channel */ 01023 GPIO_InitStruct.Pin = AUDIO_TIMx_IN_GPIO_PIN; 01024 HAL_GPIO_Init(AUDIO_TIMx_GPIO, &GPIO_InitStruct); 01025 01026 /* Configure TIM output channel */ 01027 GPIO_InitStruct.Pin = AUDIO_TIMx_OUT_GPIO_PIN; 01028 HAL_GPIO_Init(AUDIO_TIMx_GPIO, &GPIO_InitStruct); 01029 } 01030 01031 /** 01032 * @brief Configure TIM as a clock divider by 2. 01033 * I2S_SCK is externally connected to TIMx input channel 01034 */ 01035 static void TIMx_Init(void) 01036 { 01037 TIM_IC_InitTypeDef sICConfig; 01038 TIM_OC_InitTypeDef sOCConfig; 01039 TIM_ClockConfigTypeDef sCLKSourceConfig; 01040 TIM_SlaveConfigTypeDef sSlaveConfig; 01041 01042 /* Configure the TIM peripheral --------------------------------------------*/ 01043 /* Set TIMx instance */ 01044 haudio_tim.Instance = AUDIO_TIMx; 01045 /* Timer Input Capture Configuration Structure declaration */ 01046 /* Initialize TIMx peripheral as follow: 01047 + Period = 0xFFFF 01048 + Prescaler = 0 01049 + ClockDivision = 0 01050 + Counter direction = Up 01051 */ 01052 haudio_tim.Init.Period = 1; 01053 haudio_tim.Init.Prescaler = 0; 01054 haudio_tim.Init.ClockDivision = 0; 01055 haudio_tim.Init.CounterMode = TIM_COUNTERMODE_UP; 01056 01057 /* Initialize the TIMx peripheral with the structure above */ 01058 TIMx_IC_MspInit(&haudio_tim); 01059 HAL_TIM_IC_Init(&haudio_tim); 01060 01061 /* Configure the Input Capture channel -------------------------------------*/ 01062 /* Configure the Input Capture of channel 2 */ 01063 sICConfig.ICPolarity = TIM_ICPOLARITY_FALLING; 01064 sICConfig.ICSelection = TIM_ICSELECTION_DIRECTTI; 01065 sICConfig.ICPrescaler = TIM_ICPSC_DIV1; 01066 sICConfig.ICFilter = 0; 01067 HAL_TIM_IC_ConfigChannel(&haudio_tim, &sICConfig, AUDIO_TIMx_IN_CHANNEL); 01068 01069 /* Select external clock mode 1 */ 01070 sCLKSourceConfig.ClockSource = TIM_CLOCKSOURCE_ETRMODE1; 01071 sCLKSourceConfig.ClockPolarity = TIM_CLOCKPOLARITY_NONINVERTED; 01072 sCLKSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1; 01073 sCLKSourceConfig.ClockFilter = 0; 01074 HAL_TIM_ConfigClockSource(&haudio_tim, &sCLKSourceConfig); 01075 01076 /* Select Input Channel as input trigger */ 01077 sSlaveConfig.InputTrigger = TIM_TS_TI1FP1; 01078 sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1; 01079 sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_NONINVERTED; 01080 sSlaveConfig.TriggerPrescaler = TIM_CLOCKPRESCALER_DIV1; 01081 sSlaveConfig.TriggerFilter = 0; 01082 HAL_TIM_SlaveConfigSynchronization(&haudio_tim, &sSlaveConfig); 01083 01084 /* Output Compare PWM Mode configuration: Channel2 */ 01085 sOCConfig.OCMode = TIM_OCMODE_PWM1; 01086 sOCConfig.OCIdleState = TIM_OCIDLESTATE_SET; 01087 sOCConfig.Pulse = 1; 01088 sOCConfig.OCPolarity = TIM_OCPOLARITY_HIGH; 01089 sOCConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH; 01090 sOCConfig.OCFastMode = TIM_OCFAST_DISABLE; 01091 sOCConfig.OCNIdleState = TIM_OCNIDLESTATE_SET; 01092 01093 /* Initialize the TIM3 Channel2 with the structure above */ 01094 HAL_TIM_PWM_ConfigChannel(&haudio_tim, &sOCConfig, AUDIO_TIMx_OUT_CHANNEL); 01095 01096 /* Start the TIM3 Channel2 */ 01097 HAL_TIM_PWM_Start(&haudio_tim, AUDIO_TIMx_OUT_CHANNEL); 01098 01099 /* Start the TIM3 Channel1 */ 01100 HAL_TIM_IC_Start(&haudio_tim, AUDIO_TIMx_IN_CHANNEL); 01101 } 01102 01103 /** 01104 * @} 01105 */ 01106 01107 /** 01108 * @} 01109 */ 01110 01111 /** 01112 * @} 01113 */ 01114 01115 /** 01116 * @} 01117 */ 01118 01119 /** 01120 * @} 01121 */ 01122 01123 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Wed Jan 13 2016 15:52:54 for STM324x9I_EVAL BSP User Manual by 1.7.6.1