STM32F469I-Discovery BSP User Manual: stm32469i_discovery_audio.c Source File

STM32F469I-Discovery BSP Drivers

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>&copy; 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   doxygen 1.7.6.1