STM324x9I_EVAL BSP User Manual: stm324x9i_eval_audio.c Source File

STM32429I/STM32439I/STM32469I/STM32479I EVAL BSP Drivers

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