STM32469I_EVAL BSP User Manual: stm32469i_eval_audio.c Source File

STM32469I EVAL BSP Drivers

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