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