STM32756G_EVAL BSP User Manual: stm32756g_eval_audio.c Source File

STM32756G EVAL BSP Drivers

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