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 V2.0.0
00006   * @date    30-December-2016
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) 2016 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 SAIx_Init(uint32_t AudioFreq);
00171 static void SAIx_DeInit(void);
00172 static void I2Sx_Init(uint32_t AudioFreq);
00173 static void I2Sx_DeInit(void);
00174 static void TIMx_IC_MspInit(TIM_HandleTypeDef *htim);
00175 static void TIMx_IC_MspDeInit(TIM_HandleTypeDef *htim);
00176 static void TIMx_Init(void);
00177 static void TIMx_DeInit(void);
00178 static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr);
00179 /**
00180   * @}
00181   */ 
00182 
00183 /** @defgroup STM32756G_EVAL_AUDIO_out_Private_Functions STM32756G_EVAL_AUDIO_Out Private Functions
00184   * @{
00185   */ 
00186 
00187 /**
00188   * @brief  Configures the audio peripherals.
00189   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
00190   *                       or OUTPUT_DEVICE_BOTH.
00191   * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
00192   * @param  AudioFreq: Audio frequency used to play the audio stream.
00193   * @note   The I2S PLL input clock must be done in the user application.  
00194   * @retval AUDIO_OK if correct communication, else wrong communication
00195   */
00196 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
00197 { 
00198   uint8_t ret = AUDIO_ERROR;
00199   uint32_t deviceid = 0x00;
00200 
00201   /* Disable SAI */
00202   SAIx_DeInit();
00203 
00204   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
00205   BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
00206  
00207   /* SAI data transfer preparation:
00208   Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
00209   haudio_out_sai.Instance = AUDIO_SAIx;
00210   if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET)
00211   {
00212     /* Init the SAI MSP: this __weak function can be redefined by the application*/
00213     BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL);
00214   }
00215   SAIx_Init(AudioFreq);
00216 
00217   /* wm8994 codec initialization */
00218   deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
00219   
00220   if((deviceid) == WM8994_ID)
00221   {  
00222     /* Reset the Codec Registers */
00223     wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
00224     /* Initialize the audio driver structure */
00225     audio_drv = &wm8994_drv; 
00226     ret = AUDIO_OK;
00227   }
00228   else
00229   {
00230     ret = AUDIO_ERROR;
00231   }
00232 
00233   if(ret == AUDIO_OK)
00234   {
00235     /* Initialize the codec internal registers */
00236     audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq);
00237   }
00238  
00239   return ret;
00240 }
00241 
00242 /**
00243   * @brief  Starts playing audio stream from a data buffer for a determined size. 
00244   * @param  pBuffer: Pointer to the buffer 
00245   * @param  Size: Number of audio data BYTES.
00246   * @retval AUDIO_OK if correct communication, else wrong communication
00247   */
00248 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size)
00249 {
00250   /* Call the audio Codec Play function */
00251   if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0)
00252   {  
00253     return AUDIO_ERROR;
00254   }
00255   else
00256   {
00257     /* Update the Media layer and enable it for play */  
00258     HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE));
00259     
00260     return AUDIO_OK;
00261   }
00262 }
00263 
00264 /**
00265   * @brief  Sends n-Bytes on the SAI interface.
00266   * @param  pData: pointer on data address 
00267   * @param  Size: number of data to be written
00268   * @retval None
00269   */
00270 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size)
00271 {
00272    HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size);
00273 }
00274 
00275 /**
00276   * @brief  This function Pauses the audio file stream. In case
00277   *         of using DMA, the DMA Pause feature is used.
00278   * @note   When calling BSP_AUDIO_OUT_Pause() function for pause, only
00279   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00280   *          function for resume could lead to unexpected behaviour).
00281   * @retval AUDIO_OK if correct communication, else wrong communication
00282   */
00283 uint8_t BSP_AUDIO_OUT_Pause(void)
00284 {    
00285   /* Call the Audio Codec Pause/Resume function */
00286   if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0)
00287   {
00288     return AUDIO_ERROR;
00289   }
00290   else
00291   {
00292     /* Call the Media layer pause function */
00293     HAL_SAI_DMAPause(&haudio_out_sai);
00294     
00295     /* Return AUDIO_OK when all operations are correctly done */
00296     return AUDIO_OK;
00297   }
00298 }
00299 
00300 /**
00301   * @brief  This function  Resumes the audio file stream.  
00302   * @note   When calling BSP_AUDIO_OUT_Pause() function for pause, only
00303   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00304   *          function for resume could lead to unexpected behaviour).
00305   * @retval AUDIO_OK if correct communication, else wrong communication
00306   */
00307 uint8_t BSP_AUDIO_OUT_Resume(void)
00308 {    
00309   /* Call the Audio Codec Pause/Resume function */
00310   if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0)
00311   {
00312     return AUDIO_ERROR;
00313   }
00314   else
00315   {
00316     /* Call the Media layer pause/resume function */
00317     HAL_SAI_DMAResume(&haudio_out_sai);
00318     
00319     /* Return AUDIO_OK when all operations are correctly done */
00320     return AUDIO_OK;
00321   }
00322 }
00323 
00324 /**
00325   * @brief  Stops audio playing and Power down the Audio Codec. 
00326   * @param  Option: could be one of the following parameters 
00327   *           - CODEC_PDWN_SW: for software power off (by writing registers). 
00328   *                            Then no need to reconfigure the Codec after power on.
00329   *           - CODEC_PDWN_HW: completely shut down the codec (physically). 
00330   *                            Then need to reconfigure the Codec after power on.  
00331   * @retval AUDIO_OK if correct communication, else wrong communication
00332   */
00333 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
00334 {
00335   /* Call the Media layer stop function */
00336   HAL_SAI_DMAStop(&haudio_out_sai);
00337   
00338   /* Call Audio Codec Stop function */
00339   if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
00340   {
00341     return AUDIO_ERROR;
00342   }
00343   else
00344   {
00345     if(Option == CODEC_PDWN_HW)
00346     { 
00347       /* Wait at least 100us */
00348       HAL_Delay(1);
00349     }
00350     /* Return AUDIO_OK when all operations are correctly done */
00351     return AUDIO_OK;
00352   }
00353 }
00354 
00355 /**
00356   * @brief  Controls the current audio volume level. 
00357   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for 
00358   *         Mute and 100 for Max volume level).
00359   * @retval AUDIO_OK if correct communication, else wrong communication
00360   */
00361 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume)
00362 {
00363   /* Call the codec volume control function with converted volume value */
00364   if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
00365   {
00366     return AUDIO_ERROR;
00367   }
00368   else
00369   {
00370     /* Return AUDIO_OK when all operations are correctly done */
00371     return AUDIO_OK;
00372   }
00373 }
00374 
00375 /**
00376   * @brief  Enables or disables the MUTE mode by software 
00377   * @param  Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 
00378   *         unmute the codec and restore previous volume level.
00379   * @retval AUDIO_OK if correct communication, else wrong communication
00380   */
00381 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd)
00382 { 
00383   /* Call the Codec Mute function */
00384   if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0)
00385   {
00386     return AUDIO_ERROR;
00387   }
00388   else
00389   {
00390     /* Return AUDIO_OK when all operations are correctly done */
00391     return AUDIO_OK;
00392   }
00393 }
00394 
00395 /**
00396   * @brief  Switch dynamically (while audio file is played) the output target 
00397   *         (speaker or headphone).
00398   * @param  Output: The audio output target: OUTPUT_DEVICE_SPEAKER,
00399   *         OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH
00400   * @retval AUDIO_OK if correct communication, else wrong communication
00401   */
00402 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)
00403 {
00404   /* Call the Codec output device function */
00405   if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0)
00406   {
00407     return AUDIO_ERROR;
00408   }
00409   else
00410   {
00411     /* Return AUDIO_OK when all operations are correctly done */
00412     return AUDIO_OK;
00413   }
00414 }
00415 
00416 /**
00417   * @brief  Updates the audio frequency.
00418   * @param  AudioFreq: Audio frequency used to play the audio stream.
00419   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00420   *         audio frequency.
00421   * @retval None
00422   */
00423 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)
00424 { 
00425   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
00426   BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
00427 
00428   /* Disable SAI peripheral to allow access to SAI internal registers */
00429   __HAL_SAI_DISABLE(&haudio_out_sai);
00430   
00431   /* Update the SAI audio frequency configuration */
00432   haudio_out_sai.Init.AudioFrequency = AudioFreq;
00433   HAL_SAI_Init(&haudio_out_sai);
00434   
00435   /* Enable SAI peripheral to generate MCLK */
00436   __HAL_SAI_ENABLE(&haudio_out_sai);
00437 }
00438 
00439 /**
00440   * @brief  Updates the Audio frame slot configuration.
00441   * @param  AudioFrameSlot: specifies the audio Frame slot
00442   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00443   *         audio frame slot.
00444   * @retval None
00445   */
00446 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot)
00447 { 
00448   /* Disable SAI peripheral to allow access to SAI internal registers */
00449   __HAL_SAI_DISABLE(&haudio_out_sai);
00450   
00451   /* Update the SAI audio frame slot configuration */
00452   haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot;
00453   HAL_SAI_Init(&haudio_out_sai);
00454   
00455   /* Enable SAI peripheral to generate MCLK */
00456   __HAL_SAI_ENABLE(&haudio_out_sai);
00457 }
00458 
00459 /**
00460   * @brief  Deinit the audio peripherals.
00461   * @retval None
00462   */
00463 void BSP_AUDIO_OUT_DeInit(void)
00464 {
00465   SAIx_DeInit();
00466   /* DeInit the SAI MSP : this __weak function can be rewritten by the application */
00467   BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL);
00468 }
00469 
00470 /**
00471   * @brief  Tx Transfer completed callbacks.
00472   * @param  hsai: SAI handle
00473   * @retval None
00474   */
00475 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
00476 {
00477   /* Manage the remaining file size and new address offset: This function 
00478      should be coded by user (its prototype is already declared in stm32756g_eval_audio.h) */
00479   BSP_AUDIO_OUT_TransferComplete_CallBack();
00480 }
00481 
00482 /**
00483   * @brief  Tx Half Transfer completed callbacks.
00484   * @param  hsai: SAI handle
00485   * @retval None
00486   */
00487 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
00488 {
00489   /* Manage the remaining file size and new address offset: This function 
00490      should be coded by user (its prototype is already declared in stm32756g_eval_audio.h) */
00491   BSP_AUDIO_OUT_HalfTransfer_CallBack();
00492 }
00493 
00494 /**
00495   * @brief  SAI error callbacks.
00496   * @param  hsai: SAI handle
00497   * @retval None
00498   */
00499 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
00500 {
00501   BSP_AUDIO_OUT_Error_CallBack();
00502 }
00503 
00504 /**
00505   * @brief  Manages the DMA full Transfer complete event.
00506   * @retval None
00507   */
00508 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
00509 {
00510 }
00511 
00512 /**
00513   * @brief  Manages the DMA Half Transfer complete event.
00514   * @retval None
00515   */
00516 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void)
00517 { 
00518 }
00519 
00520 /**
00521   * @brief  Manages the DMA FIFO error event.
00522   * @retval None
00523   */
00524 __weak void BSP_AUDIO_OUT_Error_CallBack(void)
00525 {
00526 }
00527 
00528 /**
00529   * @brief  Initializes BSP_AUDIO_OUT MSP.
00530   * @param  hsai: SAI handle
00531   * @param  Params  
00532   * @retval None
00533   */
00534 __weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params)
00535 { 
00536   static DMA_HandleTypeDef hdma_sai_tx;
00537   GPIO_InitTypeDef  gpio_init_structure;  
00538 
00539   /* Enable SAI clock */
00540   AUDIO_SAIx_CLK_ENABLE();
00541   
00542   /* Enable GPIO clock */
00543   AUDIO_SAIx_MCLK_ENABLE();
00544   AUDIO_SAIx_SCK_SD_ENABLE();
00545   AUDIO_SAIx_FS_ENABLE();
00546   /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/
00547   gpio_init_structure.Pin = AUDIO_SAIx_FS_PIN;
00548   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
00549   gpio_init_structure.Pull = GPIO_NOPULL;
00550   gpio_init_structure.Speed = GPIO_SPEED_HIGH;
00551   gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF;
00552   HAL_GPIO_Init(AUDIO_SAIx_FS_GPIO_PORT, &gpio_init_structure);
00553 
00554   gpio_init_structure.Pin = AUDIO_SAIx_SCK_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_SCK_AF;
00559   HAL_GPIO_Init(AUDIO_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure);
00560 
00561   gpio_init_structure.Pin =  AUDIO_SAIx_SD_PIN;
00562   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
00563   gpio_init_structure.Pull = GPIO_NOPULL;
00564   gpio_init_structure.Speed = GPIO_SPEED_HIGH;
00565   gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF;
00566   HAL_GPIO_Init(AUDIO_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure);
00567 
00568   gpio_init_structure.Pin = AUDIO_SAIx_MCLK_PIN;
00569   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
00570   gpio_init_structure.Pull = GPIO_NOPULL;
00571   gpio_init_structure.Speed = GPIO_SPEED_HIGH;
00572   gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF;
00573   HAL_GPIO_Init(AUDIO_SAIx_MCLK_GPIO_PORT, &gpio_init_structure);
00574 
00575   /* Enable the DMA clock */
00576   AUDIO_SAIx_DMAx_CLK_ENABLE();
00577     
00578   if(hsai->Instance == AUDIO_SAIx)
00579   {
00580     /* Configure the hdma_saiTx handle parameters */   
00581     hdma_sai_tx.Init.Channel             = AUDIO_SAIx_DMAx_CHANNEL;
00582     hdma_sai_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
00583     hdma_sai_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
00584     hdma_sai_tx.Init.MemInc              = DMA_MINC_ENABLE;
00585     hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_SAIx_DMAx_PERIPH_DATA_SIZE;
00586     hdma_sai_tx.Init.MemDataAlignment    = AUDIO_SAIx_DMAx_MEM_DATA_SIZE;
00587     hdma_sai_tx.Init.Mode                = DMA_CIRCULAR;
00588     hdma_sai_tx.Init.Priority            = DMA_PRIORITY_HIGH;
00589     hdma_sai_tx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;         
00590     hdma_sai_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
00591     hdma_sai_tx.Init.MemBurst            = DMA_MBURST_SINGLE;
00592     hdma_sai_tx.Init.PeriphBurst         = DMA_PBURST_SINGLE; 
00593     
00594     hdma_sai_tx.Instance = AUDIO_SAIx_DMAx_STREAM;
00595     
00596     /* Associate the DMA handle */
00597     __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx);
00598     
00599     /* Deinitialize the Stream for new transfer */
00600     HAL_DMA_DeInit(&hdma_sai_tx);
00601     
00602     /* Configure the DMA Stream */
00603     HAL_DMA_Init(&hdma_sai_tx);      
00604   }
00605   
00606   /* SAI DMA IRQ Channel configuration */
00607   HAL_NVIC_SetPriority(AUDIO_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
00608   HAL_NVIC_EnableIRQ(AUDIO_SAIx_DMAx_IRQ); 
00609 }
00610 
00611 /**
00612   * @brief  Deinitializes SAI MSP.
00613   * @param  hsai: SAI handle
00614   * @param  Params  
00615   * @retval None
00616   */
00617 __weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params)
00618 {
00619     GPIO_InitTypeDef  gpio_init_structure;
00620 
00621     /* SAI DMA IRQ Channel deactivation */
00622     HAL_NVIC_DisableIRQ(AUDIO_SAIx_DMAx_IRQ);
00623 
00624     if(hsai->Instance == AUDIO_SAIx)
00625     {
00626       /* Deinitialize the DMA stream */
00627       HAL_DMA_DeInit(hsai->hdmatx);
00628     }
00629 
00630     /* Disable SAI peripheral */
00631     __HAL_SAI_DISABLE(hsai);  
00632 
00633     /* Deactivates CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */
00634     gpio_init_structure.Pin = AUDIO_SAIx_FS_PIN;
00635     HAL_GPIO_DeInit(AUDIO_SAIx_FS_GPIO_PORT, gpio_init_structure.Pin);
00636 
00637     gpio_init_structure.Pin = AUDIO_SAIx_SCK_PIN;
00638     HAL_GPIO_DeInit(AUDIO_SAIx_SCK_SD_GPIO_PORT, gpio_init_structure.Pin);
00639 
00640     gpio_init_structure.Pin =  AUDIO_SAIx_SD_PIN;
00641     HAL_GPIO_DeInit(AUDIO_SAIx_SCK_SD_GPIO_PORT, gpio_init_structure.Pin);
00642 
00643     gpio_init_structure.Pin = AUDIO_SAIx_MCLK_PIN;
00644     HAL_GPIO_DeInit(AUDIO_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin);
00645   
00646     /* Disable SAI clock */
00647     AUDIO_SAIx_CLK_DISABLE();
00648 
00649     /* GPIO pins clock and DMA clock can be shut down in the applic 
00650        by surcharging this __weak function */ 
00651 }
00652 
00653 /**
00654   * @brief  Clock Config.
00655   * @param  hsai: might be required to set audio peripheral predivider if any.
00656   * @param  AudioFreq: Audio frequency used to play the audio stream.
00657   * @param  Params  
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_FALLINGEDGE;
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   * @}
00778   */
00779 
00780 /** @defgroup STM32756G_EVAL_AUDIO_out_Private_Functions STM32756G_EVAL_AUDIO_Out Private Functions
00781   * @{
00782   */ 
00783   
00784 /**
00785   * @brief  Initializes wave recording.
00786   * @note   This function assumes that the I2S input clock (through PLL_R in 
00787   *         Devices RevA/Z and through dedicated PLLI2S_R in Devices RevB/Y)
00788   *         is already configured and ready to be used.  
00789   * @param  AudioFreq: Audio frequency to be configured for the I2S peripheral. 
00790   * @param  BitRes: Audio frequency to be configured for the I2S peripheral.
00791   * @param  ChnlNbr: Audio frequency to be configured for the I2S peripheral.
00792   * @retval AUDIO_OK if correct communication, else wrong communication
00793   */
00794 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00795 {
00796   RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct;
00797   
00798   /* Disable I2S */
00799   I2Sx_DeInit();
00800 
00801   HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct);
00802   rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
00803   rcc_ex_clk_init_struct.I2sClockSelection = RCC_I2SCLKSOURCE_PLLI2S;
00804   rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 384;
00805   rcc_ex_clk_init_struct.PLLI2S.PLLI2SR = 2;
00806   HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 
00807   
00808   /* Configure the PDM library */
00809   PDMDecoder_Init(AudioFreq, ChnlNbr);
00810  
00811   /* Configure the I2S peripheral */
00812   haudio_in_i2s.Instance = AUDIO_I2Sx;
00813   if(HAL_I2S_GetState(&haudio_in_i2s) == HAL_I2S_STATE_RESET)
00814   { 
00815     /* Initialize the I2S Msp: this __weak function can be rewritten by the application */
00816     BSP_AUDIO_IN_MspInit(&haudio_in_i2s, NULL);
00817   }
00818   I2Sx_Init(AudioFreq);
00819 
00820   /* Return AUDIO_OK when all operations are correctly done */
00821   return AUDIO_OK;
00822 }
00823 
00824 /**
00825   * @brief  Starts audio recording.
00826   * @param  pbuf: Main buffer pointer for the recorded data storing  
00827   * @param  size: Current size of the recorded buffer
00828   * @retval AUDIO_OK if correct communication, else wrong communication
00829   */
00830 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size)
00831 {
00832   uint32_t ret = AUDIO_ERROR;
00833   
00834   /* Start the process receive DMA */
00835   HAL_I2S_Receive_DMA(&haudio_in_i2s, pbuf, size);
00836   
00837   /* Return AUDIO_OK when all operations are correctly done */
00838   ret = AUDIO_OK;
00839   
00840   return ret;
00841 }
00842 
00843 /**
00844   * @brief  Stops audio recording.
00845   * @retval AUDIO_OK if correct communication, else wrong communication
00846   */
00847 uint8_t BSP_AUDIO_IN_Stop(void)
00848 {
00849   uint32_t ret = AUDIO_ERROR;
00850   /* Call the Media layer stop function */
00851   HAL_I2S_DMAStop(&haudio_in_i2s);
00852 
00853   /* TIMx Peripheral clock disable */
00854   AUDIO_TIMx_CLK_DISABLE();
00855 
00856   /* Return AUDIO_OK when all operations are correctly done */
00857   ret = AUDIO_OK;
00858   
00859   return ret;
00860 }
00861 
00862 /**
00863   * @brief  Pauses the audio file stream.
00864   * @retval AUDIO_OK if correct communication, else wrong communication
00865   */
00866 uint8_t BSP_AUDIO_IN_Pause(void)
00867 {    
00868   /* Call the Media layer pause function */
00869   HAL_I2S_DMAPause(&haudio_in_i2s);
00870   /* Return AUDIO_OK when all operations are correctly done */
00871   return AUDIO_OK;
00872 }
00873 
00874 /**
00875   * @brief  Resumes the audio file stream.
00876   * @retval AUDIO_OK if correct communication, else wrong communication
00877   */
00878 uint8_t BSP_AUDIO_IN_Resume(void)
00879 {    
00880   /* Call the Media layer pause/resume function */
00881   HAL_I2S_DMAResume(&haudio_in_i2s);
00882   /* Return AUDIO_OK when all operations are correctly done */
00883   return AUDIO_OK;
00884 }
00885 
00886 /**
00887   * @brief  Controls the audio in volume level. 
00888   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for 
00889   *         Mute and 100 for Max volume level).
00890   * @retval AUDIO_OK if correct communication, else wrong communication
00891   */
00892 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume)
00893 {
00894   /* Set the Global variable AudioInVolume  */
00895   AudioInVolume = Volume; 
00896   
00897   /* Return AUDIO_OK when all operations are correctly done */
00898   return AUDIO_OK;
00899 }
00900 
00901 /**
00902   * @brief  Deinit the audio IN peripherals.
00903   * @retval None
00904   */
00905 void BSP_AUDIO_IN_DeInit(void)
00906 {
00907   I2Sx_DeInit();
00908   /* DeInit the I2S MSP : this __weak function can be rewritten by the application */
00909   BSP_AUDIO_IN_MspDeInit(&haudio_in_i2s, NULL);
00910   TIMx_DeInit();
00911 }
00912 
00913 /**
00914   * @brief  Converts audio format from PDM to PCM. 
00915   * @param  PDMBuf: Pointer to data PDM buffer
00916   * @param  PCMBuf: Pointer to data PCM buffer
00917   * @retval AUDIO_OK if correct communication, else wrong communication
00918   */
00919 uint8_t BSP_AUDIO_IN_PDMToPCM(uint16_t* PDMBuf, uint16_t* PCMBuf)
00920 {
00921   uint8_t app_pdm[INTERNAL_BUFF_SIZE*2];
00922   uint8_t byte1 = 0, byte2 = 0;
00923   uint32_t index = 0; 
00924   
00925   /* PDM Demux */
00926   for(index = 0; index<INTERNAL_BUFF_SIZE/2; index++)
00927   {
00928     byte2 = (PDMBuf[index] >> 8)& 0xFF;
00929     byte1 = (PDMBuf[index] & 0xFF);
00930     app_pdm[(index*2)+1] = Channel_Demux[byte1 & CHANNEL_DEMUX_MASK] | Channel_Demux[byte2 & CHANNEL_DEMUX_MASK] << 4;
00931     app_pdm[(index*2)] = Channel_Demux[(byte1 >> 1) & CHANNEL_DEMUX_MASK] | Channel_Demux[(byte2 >> 1) & CHANNEL_DEMUX_MASK] << 4;
00932   }
00933   
00934   for(index = 0; index < DEFAULT_AUDIO_IN_CHANNEL_NBR; index++)
00935   {
00936     /* PDM to PCM filter */
00937     PDM_Filter_64_LSB((uint8_t*)&app_pdm[index], (uint16_t*)&(PCMBuf[index]), AudioInVolume , (PDMFilter_InitStruct *)&Filter[index]);
00938   }
00939     
00940   /* Return AUDIO_OK when all operations are correctly done */
00941   return AUDIO_OK; 
00942 }
00943 
00944  /**
00945   * @brief  Rx Transfer completed callbacks.
00946   * @param  hi2s: I2S handle
00947   * @retval None
00948   */
00949 void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
00950 {
00951   /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
00952   BSP_AUDIO_IN_TransferComplete_CallBack();
00953 }
00954 
00955 /**
00956   * @brief  Rx Half Transfer completed callbacks.
00957   * @param  hi2s: I2S handle
00958   * @retval None
00959   */
00960 void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
00961 {
00962   /* Manage the remaining file size and new address offset: This function 
00963      should be coded by user (its prototype is already declared in stm32756g_eval_audio.h) */
00964   BSP_AUDIO_IN_HalfTransfer_CallBack();
00965 }
00966 
00967 /**
00968   * @brief  I2S error callbacks.
00969   * @param  hi2s: I2S handle
00970   * @retval None
00971   */
00972 void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s)
00973 {
00974   /* Manage the error generated on DMA FIFO: This function 
00975      should be coded by user (its prototype is already declared in stm32756g_eval_audio.h) */
00976   BSP_AUDIO_IN_Error_Callback();
00977 }
00978 
00979 /**
00980   * @brief  User callback when record buffer is filled.
00981   * @retval None
00982   */
00983 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void)
00984 {
00985   /* This function should be implemented by the user application.
00986      It is called into this driver when the current buffer is filled
00987      to prepare the next buffer pointer and its size. */
00988 }
00989 
00990 /**
00991   * @brief  Manages the DMA Half Transfer complete event.
00992   * @retval None
00993   */
00994 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
00995 { 
00996   /* This function should be implemented by the user application.
00997      It is called into this driver when the current buffer is filled
00998      to prepare the next buffer pointer and its size. */
00999 }
01000 
01001 /**
01002   * @brief  Audio IN Error callback function.
01003   * @retval None
01004   */
01005 __weak void BSP_AUDIO_IN_Error_Callback(void)
01006 {   
01007   /* This function is called when an Interrupt due to transfer error on or peripheral
01008      error occurs. */
01009 }
01010 
01011 /**
01012   * @brief  Initializes BSP_AUDIO_IN MSP.
01013   * @param  hi2s: I2S handle
01014   * @param  Params  
01015   * @retval None
01016   */
01017 __weak void BSP_AUDIO_IN_MspInit(I2S_HandleTypeDef *hi2s, void *Params)
01018 {
01019   static DMA_HandleTypeDef hdma_i2s_rx;
01020   GPIO_InitTypeDef  gpio_init_structure;  
01021 
01022   /* Configure the Timer which clocks the MEMS */
01023   /* Moved inside MSP to allow applic to redefine the TIMx_MspInit */
01024   TIMx_Init();
01025   
01026   /* Enable I2S clock */
01027   AUDIO_I2Sx_CLK_ENABLE();
01028   
01029   /* Enable SCK and SD GPIO clock */
01030   AUDIO_I2Sx_SD_GPIO_CLK_ENABLE();
01031   AUDIO_I2Sx_SCK_GPIO_CLK_ENABLE();
01032   /* CODEC_I2S pins configuration: SCK and SD pins */
01033   gpio_init_structure.Pin = AUDIO_I2Sx_SCK_PIN;
01034   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
01035   gpio_init_structure.Pull = GPIO_NOPULL;
01036   gpio_init_structure.Speed = GPIO_SPEED_FAST;
01037   gpio_init_structure.Alternate = AUDIO_I2Sx_SCK_AF;
01038   HAL_GPIO_Init(AUDIO_I2Sx_SCK_GPIO_PORT, &gpio_init_structure);
01039   
01040   gpio_init_structure.Pin = AUDIO_I2Sx_SD_PIN;
01041   gpio_init_structure.Alternate = AUDIO_I2Sx_SD_AF;
01042   HAL_GPIO_Init(AUDIO_I2Sx_SD_GPIO_PORT, &gpio_init_structure); 
01043   
01044   /* Enable the DMA clock */
01045   AUDIO_I2Sx_DMAx_CLK_ENABLE();
01046     
01047   if(hi2s->Instance == AUDIO_I2Sx)
01048   {
01049     /* Configure the hdma_i2s_rx handle parameters */
01050     hdma_i2s_rx.Init.Channel             = AUDIO_I2Sx_DMAx_CHANNEL;
01051     hdma_i2s_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
01052     hdma_i2s_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
01053     hdma_i2s_rx.Init.MemInc              = DMA_MINC_ENABLE;
01054     hdma_i2s_rx.Init.PeriphDataAlignment = AUDIO_I2Sx_DMAx_PERIPH_DATA_SIZE;
01055     hdma_i2s_rx.Init.MemDataAlignment    = AUDIO_I2Sx_DMAx_MEM_DATA_SIZE;
01056     hdma_i2s_rx.Init.Mode                = DMA_CIRCULAR;
01057     hdma_i2s_rx.Init.Priority            = DMA_PRIORITY_HIGH;
01058     hdma_i2s_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;         
01059     hdma_i2s_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
01060     hdma_i2s_rx.Init.MemBurst            = DMA_MBURST_SINGLE;
01061     hdma_i2s_rx.Init.PeriphBurst         = DMA_MBURST_SINGLE; 
01062     
01063     hdma_i2s_rx.Instance = AUDIO_I2Sx_DMAx_STREAM;
01064     
01065     /* Associate the DMA handle */
01066     __HAL_LINKDMA(hi2s, hdmarx, hdma_i2s_rx);
01067     
01068     /* Deinitialize the Stream for new transfer */
01069     HAL_DMA_DeInit(&hdma_i2s_rx);
01070     
01071     /* Configure the DMA Stream */
01072     HAL_DMA_Init(&hdma_i2s_rx);      
01073   }
01074   
01075   /* I2S DMA IRQ Channel configuration */
01076   HAL_NVIC_SetPriority(AUDIO_I2Sx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
01077   HAL_NVIC_EnableIRQ(AUDIO_I2Sx_DMAx_IRQ); 
01078 }
01079 
01080 /**
01081   * @brief  DeInitializes BSP_AUDIO_IN MSP.
01082   * @param  hi2s: I2S handle
01083   * @param  Params  
01084   * @retval None
01085   */
01086 __weak void BSP_AUDIO_IN_MspDeInit(I2S_HandleTypeDef *hi2s, void *Params)
01087 {
01088   GPIO_InitTypeDef  gpio_init_structure;
01089 
01090   static DMA_HandleTypeDef hdma_i2s_rx;
01091 
01092   /* I2S DMA IRQ Channel deactivation */
01093   HAL_NVIC_DisableIRQ(AUDIO_I2Sx_DMAx_IRQ);
01094 
01095   if(hi2s->Instance == AUDIO_I2Sx)
01096   {
01097     /* Deinitialize the Stream for new transfer */
01098     HAL_DMA_DeInit(&hdma_i2s_rx);
01099   }
01100 
01101  /* Disable I2S block */
01102   __HAL_I2S_DISABLE(hi2s);
01103 
01104   /* Disable pins: SCK and SD pins */
01105   gpio_init_structure.Pin = AUDIO_I2Sx_SCK_PIN;
01106   HAL_GPIO_DeInit(AUDIO_I2Sx_SCK_GPIO_PORT, gpio_init_structure.Pin);
01107   gpio_init_structure.Pin = AUDIO_I2Sx_SD_PIN;
01108   HAL_GPIO_DeInit(AUDIO_I2Sx_SD_GPIO_PORT, gpio_init_structure.Pin);
01109 
01110   /* Disable I2S clock */
01111   AUDIO_I2Sx_CLK_DISABLE();
01112 
01113   /* GPIO pins clock and DMA clock can be shut down in the application
01114      by surcharging this __weak function */
01115 }
01116 
01117 
01118 /*******************************************************************************
01119                             Static Functions
01120 *******************************************************************************/
01121 
01122 /**
01123   * @brief  Initializes the PDM library.
01124   * @param  AudioFreq: Audio sampling frequency
01125   * @param  ChnlNbr: Number of audio channels (1: mono; 2: stereo)
01126   * @retval None
01127   */
01128 static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr)
01129 { 
01130   uint32_t i = 0;
01131   
01132   /* Enable CRC peripheral to unlock the PDM library */
01133   __HAL_RCC_CRC_CLK_ENABLE();
01134   
01135   for(i = 0; i < ChnlNbr; i++)
01136   {
01137     /* Filter LP & HP Init */
01138     Filter[i].LP_HZ = AudioFreq/2;
01139     Filter[i].HP_HZ = 10;
01140     Filter[i].Fs = AudioFreq;
01141     Filter[i].Out_MicChannels = ChnlNbr;
01142     Filter[i].In_MicChannels = ChnlNbr; 
01143     PDM_Filter_Init((PDMFilter_InitStruct *)&Filter[i]);
01144   }  
01145 }
01146 
01147 /**
01148   * @brief  Initializes the Audio Codec audio interface (I2S)
01149   * @note   This function assumes that the I2S input clock (through PLL_R in 
01150   *         Devices RevA/Z and through dedicated PLLI2S_R in Devices RevB/Y)
01151   *         is already configured and ready to be used.    
01152   * @param  AudioFreq: Audio frequency to be configured for the I2S peripheral. 
01153   * @retval None
01154   */
01155 static void I2Sx_Init(uint32_t AudioFreq)
01156 {
01157   /* Initialize the haudio_in_i2s Instance parameter */
01158   haudio_in_i2s.Instance = AUDIO_I2Sx;
01159 
01160  /* Disable I2S block */
01161   __HAL_I2S_DISABLE(&haudio_in_i2s);
01162   
01163   /* I2S2 peripheral configuration */
01164   haudio_in_i2s.Init.AudioFreq = 4 * AudioFreq;
01165   haudio_in_i2s.Init.ClockSource = I2S_CLOCK_SYSCLK;
01166   haudio_in_i2s.Init.CPOL = I2S_CPOL_HIGH;
01167   haudio_in_i2s.Init.DataFormat = I2S_DATAFORMAT_16B;
01168   haudio_in_i2s.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE;
01169   haudio_in_i2s.Init.Mode = I2S_MODE_MASTER_RX;
01170   haudio_in_i2s.Init.Standard = I2S_STANDARD_LSB;
01171   
01172   /* Init the I2S */
01173   HAL_I2S_Init(&haudio_in_i2s); 
01174 
01175   /* Enable I2S peripheral */
01176   __HAL_I2S_ENABLE(&haudio_in_i2s);
01177 }
01178 
01179 /**
01180   * @brief  Deinitializes the Audio Codec audio interface (I2S).
01181   * @retval None
01182   */
01183 static void I2Sx_DeInit(void)
01184 {
01185   /* Initialize the haudio_in_i2s Instance parameter */
01186   haudio_in_i2s.Instance = AUDIO_I2Sx;
01187 
01188  /* Disable I2S block */
01189   __HAL_I2S_DISABLE(&haudio_in_i2s);
01190 
01191   /* DeInit the I2S */
01192   HAL_I2S_DeInit(&haudio_in_i2s); 
01193 }
01194 
01195 
01196 /**
01197   * @brief  Initializes the TIM INput Capture MSP.
01198   * @param  htim: TIM handle
01199   * @retval None
01200   */
01201 static void TIMx_IC_MspInit(TIM_HandleTypeDef *htim)
01202 {
01203   GPIO_InitTypeDef   gpio_init_structure;
01204   
01205   /* Enable peripherals and GPIO Clocks --------------------------------------*/
01206   /* TIMx Peripheral clock enable */
01207   AUDIO_TIMx_CLK_ENABLE();
01208     
01209   /* Enable GPIO Channels Clock */
01210   AUDIO_TIMx_GPIO_CLK_ENABLE();
01211   
01212   /* Configure I/Os ----------------------------------------------------------*/
01213   /* Common configuration for all channels */
01214   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
01215   gpio_init_structure.Pull = GPIO_NOPULL;
01216   gpio_init_structure.Speed = GPIO_SPEED_HIGH;
01217   gpio_init_structure.Alternate = AUDIO_TIMx_AF;
01218   
01219   /* Configure TIM input channel */
01220   gpio_init_structure.Pin = AUDIO_TIMx_IN_GPIO_PIN;
01221   HAL_GPIO_Init(AUDIO_TIMx_GPIO_PORT, &gpio_init_structure);
01222 
01223   /* Configure TIM output channel */
01224   gpio_init_structure.Pin = AUDIO_TIMx_OUT_GPIO_PIN;
01225   HAL_GPIO_Init(AUDIO_TIMx_GPIO_PORT, &gpio_init_structure);
01226 
01227 }
01228 
01229 /**
01230   * @brief  Initializes the TIM INput Capture MSP.
01231   * @param  htim: TIM handle
01232   * @retval None
01233   */
01234 static void TIMx_IC_MspDeInit(TIM_HandleTypeDef *htim)
01235 {
01236     /* Disable TIMx Peripheral clock  */
01237     AUDIO_TIMx_CLK_DISABLE();
01238 
01239     /* GPIO pins clock and DMA clock can be shut down in the application 
01240        by surcharging this __weak function */ 
01241 }
01242 
01243 /**
01244   * @brief  Configure TIM as a clock divider by 2.
01245   *         I2S_SCK is externally connected to TIMx input channel
01246   * @retval None
01247   */
01248 static void TIMx_Init(void)
01249 {
01250   TIM_IC_InitTypeDef     s_ic_config;
01251   TIM_OC_InitTypeDef     s_oc_config;
01252   TIM_ClockConfigTypeDef s_clk_source_config;
01253   TIM_SlaveConfigTypeDef s_slave_config;
01254   
01255   /* Configure the TIM peripheral --------------------------------------------*/
01256   /* Set TIMx instance */
01257   haudio_tim.Instance = AUDIO_TIMx;
01258   /* Timer Input Capture Configuration Structure declaration */
01259    /* Initialize TIMx peripheral as follow:
01260        + Period = 0xFFFF
01261        + Prescaler = 0
01262        + ClockDivision = 0
01263        + Counter direction = Up
01264   */
01265   haudio_tim.Init.Period        = 1;
01266   haudio_tim.Init.Prescaler     = 0;
01267   haudio_tim.Init.ClockDivision = 0;
01268   haudio_tim.Init.CounterMode   = TIM_COUNTERMODE_UP; 
01269   
01270   /* Initialize the TIMx peripheral with the structure above */
01271   TIMx_IC_MspInit(&haudio_tim);
01272   HAL_TIM_IC_Init(&haudio_tim);
01273   
01274   /* Configure the Input Capture channel -------------------------------------*/ 
01275   /* Configure the Input Capture of channel 2 */
01276   s_ic_config.ICPolarity  = TIM_ICPOLARITY_FALLING;
01277   s_ic_config.ICSelection = TIM_ICSELECTION_DIRECTTI;
01278   s_ic_config.ICPrescaler = TIM_ICPSC_DIV1;
01279   s_ic_config.ICFilter    = 0;
01280   HAL_TIM_IC_ConfigChannel(&haudio_tim, &s_ic_config, AUDIO_TIMx_IN_CHANNEL);
01281   
01282   /* Select external clock mode 1 */
01283   s_clk_source_config.ClockSource = TIM_CLOCKSOURCE_ETRMODE1;
01284   s_clk_source_config.ClockPolarity = TIM_CLOCKPOLARITY_NONINVERTED;
01285   s_clk_source_config.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;
01286   s_clk_source_config.ClockFilter = 0;
01287   HAL_TIM_ConfigClockSource(&haudio_tim, &s_clk_source_config);
01288   
01289   /* Select Input Channel as input trigger */
01290   s_slave_config.InputTrigger = TIM_TS_TI1FP1;
01291   s_slave_config.SlaveMode = TIM_SLAVEMODE_EXTERNAL1;
01292   s_slave_config.TriggerPolarity = TIM_TRIGGERPOLARITY_NONINVERTED;
01293   s_slave_config.TriggerPrescaler = TIM_CLOCKPRESCALER_DIV1;
01294   s_slave_config.TriggerFilter = 0;
01295   HAL_TIM_SlaveConfigSynchronization(&haudio_tim, &s_slave_config);
01296   
01297   /* Output Compare PWM Mode configuration: Channel2 */
01298   s_oc_config.OCMode = TIM_OCMODE_PWM1;
01299   s_oc_config.OCIdleState = TIM_OCIDLESTATE_SET;
01300   s_oc_config.Pulse = 1;
01301   s_oc_config.OCPolarity = TIM_OCPOLARITY_HIGH;
01302   s_oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH;
01303   s_oc_config.OCFastMode = TIM_OCFAST_DISABLE;
01304   s_oc_config.OCNIdleState = TIM_OCNIDLESTATE_SET;
01305   
01306   /* Initialize the TIM3 Channel2 with the structure above */
01307   HAL_TIM_PWM_ConfigChannel(&haudio_tim, &s_oc_config, AUDIO_TIMx_OUT_CHANNEL);
01308   
01309   /* Start the TIM3 Channel2 */
01310   HAL_TIM_PWM_Start(&haudio_tim, AUDIO_TIMx_OUT_CHANNEL);
01311 
01312   /* Start the TIM3 Channel1 */
01313   HAL_TIM_IC_Start(&haudio_tim, AUDIO_TIMx_IN_CHANNEL);
01314 }
01315 
01316 /**
01317   * @brief  Configure TIM as a clock divider by 2.
01318   *         I2S_SCK is externally connected to TIMx input channel
01319   * @retval None
01320   */
01321 static void TIMx_DeInit(void)
01322 {
01323   haudio_tim.Instance = AUDIO_TIMx;
01324   
01325   /* Stop the TIM4 Channel2 */
01326   HAL_TIM_PWM_Stop(&haudio_tim, AUDIO_TIMx_OUT_CHANNEL);
01327   /* Stop the TIM4 Channel1 */
01328   HAL_TIM_IC_Stop(&haudio_tim, AUDIO_TIMx_IN_CHANNEL);
01329 
01330   HAL_TIM_IC_DeInit(&haudio_tim);
01331   
01332   /* Initialize the TIMx peripheral with the structure above */
01333   TIMx_IC_MspDeInit(&haudio_tim);
01334 }
01335 
01336 /**
01337   * @}
01338   */ 
01339   
01340 /**
01341   * @}
01342   */
01343 
01344 /**
01345   * @}
01346   */
01347 
01348 /**
01349   * @}
01350   */ 
01351 
01352 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Fri Dec 30 2016 19:47:41 for STM32756G_EVAL BSP User Manual by   doxygen 1.7.6.1