STM32769I_EVAL BSP User Manual: stm32f769i_eval_audio.c Source File

STM32769I EVAL BSP Drivers

stm32f769i_eval_audio.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32f769i_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 STM32F769I-EVAL  
00008   *          evaluation board.
00009   @verbatim
00010   How To use this driver:
00011   -----------------------
00012    + This driver supports STM32F7xx devices on STM32F769I-EVAL (MB1219) 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 STM32F769I-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 stm32f769i_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 stm32f769i_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 stm32f769i_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 stm32f769i_eval_audio_codec.c file (DFSDMx_Init(), DFSDMx_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 "stm32f769i_eval_audio.h"
00097 
00098 /** @addtogroup BSP
00099   * @{
00100   */
00101 
00102 /** @addtogroup STM32F769I_EVAL
00103   * @{
00104   */ 
00105   
00106 /** @defgroup STM32F769I_EVAL_AUDIO STM32F769I_EVAL AUDIO
00107   * @brief This file includes the low layer driver for wm8994 Audio Codec
00108   *        available on STM32F769I-EVAL evaluation board(MB1219).
00109   * @{
00110   */ 
00111 
00112 /** @defgroup STM32F769I_EVAL_AUDIO_Private_Types STM32F769I_EVAL_AUDIO Private Types
00113   * @{
00114   */ 
00115 typedef struct
00116 {
00117   uint16_t      *pRecBuf;       /* Pointer to record user buffer */
00118   uint32_t      RecSize;        /* Size to record in mono, double size to record in stereo */
00119 }AUDIOIN_TypeDef;
00120 
00121 /**
00122   * @}
00123   */ 
00124   
00125 /** @defgroup STM32F769I_EVAL_AUDIO_Private_Defines STM32F769I_EVAL_AUDIO Private Defines
00126   * @{
00127   */
00128 /**
00129   * @}
00130   */ 
00131 
00132 /** @defgroup STM32F769I_EVAL_AUDIO_Private_Macros STM32F769I_EVAL_AUDIO Private Macros
00133   * @{
00134   */
00135 /*### RECORD ###*/
00136 #define DFSDM_OVER_SAMPLING(__FREQUENCY__) \
00137         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 256 \
00138       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \
00139       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \
00140       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \
00141       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \
00142       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64  \
00143       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 40 : 20  \
00144 
00145 #define DFSDM_CLOCK_DIVIDER(__FREQUENCY__) \
00146         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 24 \
00147       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \
00148       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \
00149       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
00150       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \
00151       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4  \
00152       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 25 : 25  \
00153 
00154 #define DFSDM_FILTER_ORDER(__FREQUENCY__) \
00155         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? DFSDM_FILTER_SINC3_ORDER \
00156       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \
00157       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \
00158       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \
00159       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \
00160       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC3_ORDER  \
00161       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC3_ORDER : DFSDM_FILTER_SINC5_ORDER  \
00162 
00163 #define DFSDM_RIGHT_BIT_SHIFT(__FREQUENCY__) \
00164         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 8 \
00165       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 8 \
00166       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 3 \
00167       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
00168       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 7 \
00169       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 0  \
00170       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 0 : 4  \
00171 
00172 /* Saturate the record PCM sample */
00173 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N)))
00174 /**
00175   * @}
00176   */ 
00177   
00178 /** @defgroup STM32F769I_EVAL_AUDIO_Private_Variables STM32F769I_EVAL_AUDIO Private Variables
00179   * @{
00180   */
00181 /*### PLAY ###*/
00182 AUDIO_DrvTypeDef          *audio_drv;
00183 SAI_HandleTypeDef         haudio_out_sai;
00184 
00185 /*### RECORD ###*/
00186 AUDIOIN_TypeDef                 hAudioIn;
00187 
00188 DFSDM_Channel_HandleTypeDef     haudio_in_dfsdm_leftchannel;
00189 DFSDM_Channel_HandleTypeDef     haudio_in_dfsdm_rightchannel;
00190 DFSDM_Filter_HandleTypeDef      haudio_in_dfsdm_leftfilter;
00191 DFSDM_Filter_HandleTypeDef      haudio_in_dfsdm_rightfilter;
00192 DMA_HandleTypeDef               hdma_dfsdm_left;
00193 DMA_HandleTypeDef               hdma_dfsdm_right;
00194 
00195 /* Buffers for right and left samples */
00196 int32_t                         *pScratchBuff[DEFAULT_AUDIO_IN_CHANNEL_NBR];
00197 int32_t                         ScratchSize;
00198 
00199 /* Output device to be used: headphone by default */
00200 static uint16_t                 AudioOut_Device = OUTPUT_DEVICE_HEADPHONE1; 
00201 
00202 /* Buffers status flags */
00203 uint32_t                        DmaLeftRecHalfBuffCplt  = 0;
00204 uint32_t                        DmaLeftRecBuffCplt      = 0;
00205 uint32_t                        DmaRightRecHalfBuffCplt = 0;
00206 uint32_t                        DmaRightRecBuffCplt     = 0;
00207 
00208 /* Application Buffer Trigger */
00209 __IO uint32_t                   AppBuffTrigger          = 0;
00210 __IO uint32_t                   AppBuffHalf             = 0;
00211 
00212 #if defined(USE_LCD_HDMI)
00213 AUDIO_DrvTypeDef          *hdmi_drv;
00214 /* Audio device ID */
00215 static uint32_t                 DeviceId = 0x00;
00216 #endif /* USE_LCD_HDMI */
00217 
00218 /**
00219   * @}
00220   */ 
00221 
00222 /** @defgroup STM32F769I_EVAL_AUDIO_Private_Function_Prototypes STM32F769I_EVAL_AUDIO Private Function Prototypes
00223   * @{
00224   */
00225 static void SAIx_Init(uint32_t AudioFreq);
00226 static void SAIx_DeInit(void);
00227 static void    DFSDMx_ChannelMspInit(void);
00228 static void    DFSDMx_FilterMspInit(void);
00229 static void    DFSDMx_ChannelMspDeInit(void);
00230 static void    DFSDMx_FilterMspDeInit(void);
00231 static uint8_t DFSDMx_Init(uint32_t AudioFreq);
00232 static uint8_t DFSDMx_DeInit(void);
00233 /**
00234   * @}
00235   */ 
00236 
00237 /** @defgroup STM32F769I_EVAL_AUDIO_OUT_Private_Functions STM32F769I_EVAL_AUDIO_OUT Private Functions
00238   * @{
00239   */ 
00240 
00241 /**
00242   * @brief  Configure the audio peripherals.
00243   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
00244   *                       or OUTPUT_DEVICE_BOTH.
00245   * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
00246   * @param  AudioFreq: Audio frequency used to play the audio stream.  
00247   * @retval AUDIO_OK if correct communication, else wrong communication
00248   */
00249 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
00250 { 
00251   uint8_t ret = AUDIO_ERROR;
00252   AudioOut_Device = OutputDevice;
00253 
00254   /* Disable SAI */
00255   SAIx_DeInit();
00256 
00257   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
00258   BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
00259  
00260   /* SAI data transfer preparation:
00261   Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
00262   haudio_out_sai.Instance = AUDIO_SAIx;
00263   if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET)
00264   {
00265     /* Init the SAI MSP: this __weak function can be redefined by the application*/
00266     BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL);
00267   }
00268   SAIx_Init(AudioFreq);
00269 
00270 #if defined(USE_LCD_HDMI)
00271   if((OutputDevice & OUTPUT_DEVICE_HDMI) == OUTPUT_DEVICE_HDMI)
00272   {
00273     /* adv7533 audio driver initialization */
00274     DeviceId = adv7533_drv.ReadID(ADV7533_CEC_DSI_I2C_ADDR);
00275 
00276     if(DeviceId == ADV7533_ID)
00277     { 
00278       /* Initialize the audio driver structure */
00279       hdmi_drv = &adv7533_drv; 
00280       ret = AUDIO_OK;
00281     }
00282     else
00283     {
00284       ret = AUDIO_ERROR;
00285     }
00286 
00287     if(ret == AUDIO_OK)
00288     {
00289       /* Initialize the codec internal registers */
00290       hdmi_drv->Init(ADV7533_MAIN_I2C_ADDR, OutputDevice, Volume, AudioFreq);
00291     }    
00292   }
00293 #endif /* USE_LCD_HDMI */
00294 
00295   if((((OutputDevice & OUTPUT_DEVICE_BOTH) > 0) && 
00296      ((OutputDevice & OUTPUT_DEVICE_BOTH) <= OUTPUT_DEVICE_BOTH)) ||
00297      ((OutputDevice & OUTPUT_DEVICE_AUTO) == OUTPUT_DEVICE_AUTO))
00298   {    
00299     /* wm8994 codec initialization */   
00300     if((wm8994_drv.ReadID(AUDIO_I2C_ADDRESS)) == WM8994_ID)
00301     {  
00302       /* Reset the Codec Registers */
00303       wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
00304       /* Initialize the audio driver structure */
00305       audio_drv = &wm8994_drv; 
00306       ret = AUDIO_OK;
00307     }
00308     else
00309     {
00310       ret = AUDIO_ERROR;
00311     }
00312 
00313     if(ret == AUDIO_OK)
00314     {
00315       /* Initialize the codec internal registers */
00316       audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq);
00317     }
00318   }
00319  
00320   return ret;
00321 }
00322 
00323 /**
00324   * @brief  Start playing audio stream from a data buffer for a determined size. 
00325   * @param  pBuffer: Pointer to the buffer 
00326   * @param  Size: Number of audio data BYTES.
00327   * @retval AUDIO_OK if correct communication, else wrong communication
00328   */
00329 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size)
00330 {
00331   uint8_t ret = 0;
00332 #if defined(USE_LCD_HDMI)  
00333   /* ADV7533 used */
00334   if((AudioOut_Device & OUTPUT_DEVICE_HDMI) == OUTPUT_DEVICE_HDMI)
00335   {
00336     if(DeviceId == ADV7533_ID)
00337     {
00338       /* Call the audio Codec Play function */
00339       if(hdmi_drv->Play(ADV7533_MAIN_I2C_ADDR, (uint16_t *)pBuffer, Size) != 0)
00340       {  
00341         ret = AUDIO_ERROR;
00342       }
00343     }
00344   }
00345 #endif /* USE_LCD_HDMI */
00346 
00347   /* WM8994 used */
00348   if((((AudioOut_Device & OUTPUT_DEVICE_BOTH) > 0) && 
00349      ((AudioOut_Device & OUTPUT_DEVICE_BOTH) <= OUTPUT_DEVICE_BOTH)) ||
00350      ((AudioOut_Device & OUTPUT_DEVICE_AUTO) == OUTPUT_DEVICE_AUTO))
00351   {  
00352     /* Call the audio Codec Play function */
00353     if(audio_drv->Play(AUDIO_I2C_ADDRESS, (uint16_t *)pBuffer, Size) != 0)
00354     {  
00355       ret = AUDIO_ERROR;
00356     } 
00357   }
00358 
00359   if(ret == AUDIO_ERROR)
00360   {
00361     return AUDIO_ERROR;
00362   }
00363   else
00364   {
00365     /* Update the Media layer and enable it for play */  
00366     HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE));
00367     
00368     return AUDIO_OK;
00369   }
00370 }
00371 
00372 /**
00373   * @brief  Send n-Bytes on the SAI interface.
00374   * @param  pData: pointer on data address 
00375   * @param  Size: number of data to be written
00376   * @retval None
00377   */
00378 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size)
00379 {
00380    HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size);
00381 }
00382 
00383 /**
00384   * @brief  Pause the audio file stream. In case
00385   *         of using DMA, the DMA Pause feature is used.
00386   * @note  When calling BSP_AUDIO_OUT_Pause() function for pause, only
00387   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00388   *          function for resume could lead to unexpected behaviour).
00389   * @retval AUDIO_OK if correct communication, else wrong communication
00390   */
00391 uint8_t BSP_AUDIO_OUT_Pause(void)
00392 {
00393   uint8_t ret = 0;
00394 #if defined(USE_LCD_HDMI)  
00395   /* ADV7533 used */
00396   if((AudioOut_Device & OUTPUT_DEVICE_HDMI) == OUTPUT_DEVICE_HDMI)
00397   {
00398     if(DeviceId == ADV7533_ID)
00399     {    
00400       /* Call the audio Codec Pause function */
00401       if(hdmi_drv->Pause(ADV7533_MAIN_I2C_ADDR) != 0)
00402       {  
00403         ret = AUDIO_ERROR;
00404       }
00405     }
00406   }
00407 #endif /* USE_LCD_HDMI */
00408 
00409   /* WM8994 used */
00410   if((((AudioOut_Device & OUTPUT_DEVICE_BOTH) > 0) && 
00411      ((AudioOut_Device & OUTPUT_DEVICE_BOTH) <= OUTPUT_DEVICE_BOTH)) ||
00412      ((AudioOut_Device & OUTPUT_DEVICE_AUTO) == OUTPUT_DEVICE_AUTO))
00413   {  
00414     /* Call the audio Codec Pause function */
00415     if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0)
00416     {  
00417       ret = AUDIO_ERROR;
00418     } 
00419   }
00420 
00421   if(ret == AUDIO_ERROR)
00422   {
00423     return AUDIO_ERROR;
00424   }
00425   else
00426   {
00427     /* Call the Media layer pause function */
00428     HAL_SAI_DMAPause(&haudio_out_sai);
00429     
00430     /* Return AUDIO_OK when all operations are correctly done */
00431     return AUDIO_OK;
00432   }
00433 }
00434 
00435 /**
00436   * @brief  Resume the audio file stream.  
00437   * @note   When calling BSP_AUDIO_OUT_Pause() function for pause, only
00438   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00439   *          function for resume could lead to unexpected behaviour).
00440   * @retval AUDIO_OK if correct communication, else wrong communication
00441   */
00442 uint8_t BSP_AUDIO_OUT_Resume(void)
00443 {
00444   uint8_t ret = 0;
00445 #if defined(USE_LCD_HDMI)  
00446   /* ADV7533 used */
00447   if((AudioOut_Device & OUTPUT_DEVICE_HDMI) == OUTPUT_DEVICE_HDMI)
00448   {
00449     if(DeviceId == ADV7533_ID)
00450     {    
00451       /* Call the audio Codec Resume function */
00452       if(hdmi_drv->Resume(ADV7533_MAIN_I2C_ADDR) != 0)
00453       {  
00454         ret = AUDIO_ERROR;
00455       }
00456     }
00457   }
00458 #endif /* USE_LCD_HDMI */
00459 
00460   /* WM8994 used */
00461   if((((AudioOut_Device & OUTPUT_DEVICE_BOTH) > 0) && 
00462      ((AudioOut_Device & OUTPUT_DEVICE_BOTH) <= OUTPUT_DEVICE_BOTH)) ||
00463      ((AudioOut_Device & OUTPUT_DEVICE_AUTO) == OUTPUT_DEVICE_AUTO))
00464   {  
00465     /* Call the audio Codec Resume function */
00466     if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0)
00467     {  
00468       ret = AUDIO_ERROR;
00469     } 
00470   }
00471 
00472   if(ret == AUDIO_ERROR)
00473   {
00474     return AUDIO_ERROR;
00475   }
00476   else
00477   {
00478     /* Call the Media layer pause/resume function */
00479     HAL_SAI_DMAResume(&haudio_out_sai);
00480     
00481     /* Return AUDIO_OK when all operations are correctly done */
00482     return AUDIO_OK;
00483   }
00484 }
00485 
00486 /**
00487   * @brief  Stop audio playing and Power down the Audio Codec. 
00488   * @param  Option: could be one of the following parameters 
00489   *           - CODEC_PDWN_SW: for software power off (by writing registers). 
00490   *                            Then no need to reconfigure the Codec after power on.
00491   *           - CODEC_PDWN_HW: completely shut down the codec (physically). 
00492   *                            Then need to reconfigure the Codec after power on.  
00493   * @retval AUDIO_OK if correct communication, else wrong communication
00494   */
00495 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
00496 {
00497   uint8_t ret = 0;
00498 
00499   /* Call the Media layer stop function */
00500   HAL_SAI_DMAStop(&haudio_out_sai);
00501 
00502 #if defined(USE_LCD_HDMI)
00503   /* ADV7533 used */
00504   if((AudioOut_Device & OUTPUT_DEVICE_HDMI) == OUTPUT_DEVICE_HDMI)
00505   {
00506     if(DeviceId == ADV7533_ID)
00507     {    
00508       /* Call the audio Codec Stop function */
00509       if(hdmi_drv->Stop(ADV7533_MAIN_I2C_ADDR, Option) != 0)
00510       {  
00511         ret = AUDIO_ERROR;
00512       }
00513     }
00514   }
00515 #endif /* USE_LCD_HDMI */
00516 
00517   /* WM8994 used */
00518   if((((AudioOut_Device & OUTPUT_DEVICE_BOTH) > 0) && 
00519      ((AudioOut_Device & OUTPUT_DEVICE_BOTH) <= OUTPUT_DEVICE_BOTH)) ||
00520      ((AudioOut_Device & OUTPUT_DEVICE_AUTO) == OUTPUT_DEVICE_AUTO))
00521   {  
00522     /* Call the audio Codec Stop function */
00523     if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
00524     {  
00525       ret = AUDIO_ERROR;
00526     } 
00527   }
00528   
00529   if(ret == AUDIO_ERROR)
00530   {
00531     return AUDIO_ERROR;
00532   }
00533   else
00534   {
00535     if(Option == CODEC_PDWN_HW)
00536     { 
00537       /* Wait at least 100us */
00538       HAL_Delay(1);
00539     }
00540     /* Return AUDIO_OK when all operations are correctly done */
00541     return AUDIO_OK;
00542   }
00543 }
00544 
00545 /**
00546   * @brief  Control the current audio volume level. 
00547   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for 
00548   *         Mute and 100 for Max volume level).
00549   * @retval AUDIO_OK if correct communication, else wrong communication
00550   */
00551 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume)
00552 {
00553   /* Call the codec volume control function with converted volume value */
00554   if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
00555   {
00556     return AUDIO_ERROR;
00557   }
00558   else
00559   {
00560     /* Return AUDIO_OK when all operations are correctly done */
00561     return AUDIO_OK;
00562   }
00563 }
00564 
00565 /**
00566   * @brief  Enable or disable the MUTE mode by software 
00567   * @param  Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 
00568   *         unmute the codec and restore previous volume level.
00569   * @retval AUDIO_OK if correct communication, else wrong communication
00570   */
00571 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd)
00572 {
00573   uint8_t ret = 0;
00574 #if defined(USE_LCD_HDMI)  
00575   /* ADV7533 used */
00576   if((AudioOut_Device & OUTPUT_DEVICE_HDMI) == OUTPUT_DEVICE_HDMI)
00577   {
00578     if(DeviceId == ADV7533_ID)
00579     {    
00580       /* Call the audio Codec SetMute function */
00581       if(hdmi_drv->SetMute(ADV7533_MAIN_I2C_ADDR, Cmd) != 0)
00582       {  
00583         ret = AUDIO_ERROR;
00584       }
00585     }
00586   }
00587 #endif /* USE_LCD_HDMI */
00588 
00589   /* WM8994 used */
00590   if((((AudioOut_Device & OUTPUT_DEVICE_BOTH) > 0) && 
00591       ((AudioOut_Device & OUTPUT_DEVICE_BOTH) <= OUTPUT_DEVICE_BOTH)) ||
00592      ((AudioOut_Device & OUTPUT_DEVICE_AUTO) == OUTPUT_DEVICE_AUTO))
00593   {  
00594     /* Call the audio Codec SetMute function */
00595     if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0)
00596     {  
00597       ret = AUDIO_ERROR;
00598     } 
00599   }
00600   
00601   if(ret == AUDIO_ERROR)
00602   {
00603     return AUDIO_ERROR;
00604   }
00605   else
00606   {
00607     /* Return AUDIO_OK when all operations are correctly done */
00608     return AUDIO_OK;
00609   }
00610 }
00611 
00612 /**
00613   * @brief  Switch dynamically (while audio file is played) the output target 
00614   *         (speaker or headphone).
00615   * @param  Output: The audio output target: OUTPUT_DEVICE_SPEAKER,
00616   *         OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH
00617   * @retval AUDIO_OK if correct communication, else wrong communication
00618   */
00619 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)
00620 {
00621   /* Call the Codec output device function */
00622   if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0)
00623   {
00624     return AUDIO_ERROR;
00625   }
00626   else
00627   {
00628     /* Return AUDIO_OK when all operations are correctly done */
00629     return AUDIO_OK;
00630   }
00631 }
00632 
00633 /**
00634   * @brief  Update the audio frequency.
00635   * @param  AudioFreq: Audio frequency used to play the audio stream.
00636   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00637   *         audio frequency.
00638   * @retval None
00639   */
00640 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)
00641 { 
00642   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
00643   BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
00644 
00645   /* Disable SAI peripheral to allow access to SAI internal registers */
00646   __HAL_SAI_DISABLE(&haudio_out_sai);
00647   
00648   /* Update the SAI audio frequency configuration */
00649   haudio_out_sai.Init.AudioFrequency = AudioFreq;
00650   HAL_SAI_Init(&haudio_out_sai);
00651   
00652   /* Enable SAI peripheral to generate MCLK */
00653   __HAL_SAI_ENABLE(&haudio_out_sai);
00654 }
00655 
00656 /**
00657   * @brief  Update the Audio frame slot configuration.
00658   * @param  AudioFrameSlot: specifies the audio Frame slot
00659   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00660   *         audio frame slot.
00661   * @retval None
00662   */
00663 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot)
00664 { 
00665   /* Disable SAI peripheral to allow access to SAI internal registers */
00666   __HAL_SAI_DISABLE(&haudio_out_sai);
00667   
00668   /* Update the SAI audio frame slot configuration */
00669   haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot;
00670   HAL_SAI_Init(&haudio_out_sai);
00671   
00672   /* Enable SAI peripheral to generate MCLK */
00673   __HAL_SAI_ENABLE(&haudio_out_sai);
00674 }
00675 
00676                          
00677 /**
00678   * @brief  De-initialize the audio peripherals.
00679   * @retval None
00680   */
00681 void BSP_AUDIO_OUT_DeInit(void)
00682 {
00683   SAIx_DeInit();
00684   /* DeInit the SAI MSP : this __weak function can be rewritten by the application */
00685   BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL);
00686 }
00687 
00688 /**
00689   * @brief  Tx Transfer completed callbacks.
00690   * @param  hsai: SAI handle
00691   * @retval None
00692   */
00693 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
00694 {
00695   /* Manage the remaining file size and new address offset: This function 
00696      should be coded by user (its prototype is already declared in stm32f769i_eval_audio.h) */
00697   BSP_AUDIO_OUT_TransferComplete_CallBack();
00698 }
00699 
00700 /**
00701   * @brief  Tx Half Transfer completed callbacks.
00702   * @param  hsai: SAI handle
00703   * @retval None
00704   */
00705 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
00706 {
00707   /* Manage the remaining file size and new address offset: This function 
00708      should be coded by user (its prototype is already declared in stm32f769i_eval_audio.h) */
00709   BSP_AUDIO_OUT_HalfTransfer_CallBack();
00710 }
00711 
00712 /**
00713   * @brief  SAI error callbacks.
00714   * @param  hsai: SAI handle
00715   * @retval None
00716   */
00717 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
00718 {
00719   BSP_AUDIO_OUT_Error_CallBack();
00720 }
00721 
00722 /**
00723   * @brief  Manages the DMA full Transfer complete event.
00724   * @retval None
00725   */
00726 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
00727 {
00728 }
00729 
00730 /**
00731   * @brief  Manages the DMA Half Transfer complete event.
00732   * @retval None
00733   */
00734 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void)
00735 { 
00736 }
00737 
00738 /**
00739   * @brief  Manages the DMA FIFO error event.
00740   * @retval None
00741   */
00742 __weak void BSP_AUDIO_OUT_Error_CallBack(void)
00743 {
00744 }
00745 
00746 /**
00747   * @brief  Initialize BSP_AUDIO_OUT MSP.
00748   * @param  hsai: SAI handle
00749   * @param  Params  
00750   * @retval None
00751   */
00752 __weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params)
00753 { 
00754   static DMA_HandleTypeDef hdma_sai_tx;
00755   GPIO_InitTypeDef  gpio_init_structure;  
00756 
00757   /* Enable SAI clock */
00758   AUDIO_SAIx_CLK_ENABLE();
00759   
00760   /* Enable GPIO clock */
00761   AUDIO_SAIx_MCLK_ENABLE();
00762   AUDIO_SAIx_SCK_SD_ENABLE();
00763   AUDIO_SAIx_FS_ENABLE();
00764   /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/
00765   gpio_init_structure.Pin = AUDIO_SAIx_FS_PIN;
00766   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
00767   gpio_init_structure.Pull = GPIO_NOPULL;
00768   gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
00769   gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF;
00770   HAL_GPIO_Init(AUDIO_SAIx_FS_GPIO_PORT, &gpio_init_structure);
00771 
00772   gpio_init_structure.Pin = AUDIO_SAIx_SCK_PIN;
00773   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
00774   gpio_init_structure.Pull = GPIO_NOPULL;
00775   gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
00776   gpio_init_structure.Alternate = AUDIO_SAIx_SCK_AF;
00777   HAL_GPIO_Init(AUDIO_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure);
00778 
00779   gpio_init_structure.Pin =  AUDIO_SAIx_SD_PIN;
00780   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
00781   gpio_init_structure.Pull = GPIO_NOPULL;
00782   gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
00783   gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF;
00784   HAL_GPIO_Init(AUDIO_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure);
00785 
00786   gpio_init_structure.Pin = AUDIO_SAIx_MCLK_PIN;
00787   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
00788   gpio_init_structure.Pull = GPIO_NOPULL;
00789   gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
00790   gpio_init_structure.Alternate = AUDIO_SAIx_FS_SD_MCLK_AF;
00791   HAL_GPIO_Init(AUDIO_SAIx_MCLK_GPIO_PORT, &gpio_init_structure);
00792 
00793   /* Enable the DMA clock */
00794   AUDIO_SAIx_DMAx_CLK_ENABLE();
00795     
00796   if(hsai->Instance == AUDIO_SAIx)
00797   {
00798     /* Configure the hdma_saiTx handle parameters */   
00799     hdma_sai_tx.Init.Channel             = AUDIO_SAIx_DMAx_CHANNEL;
00800     hdma_sai_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
00801     hdma_sai_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
00802     hdma_sai_tx.Init.MemInc              = DMA_MINC_ENABLE;
00803     hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_SAIx_DMAx_PERIPH_DATA_SIZE;
00804     hdma_sai_tx.Init.MemDataAlignment    = AUDIO_SAIx_DMAx_MEM_DATA_SIZE;
00805     hdma_sai_tx.Init.Mode                = DMA_CIRCULAR;
00806     hdma_sai_tx.Init.Priority            = DMA_PRIORITY_HIGH;
00807     hdma_sai_tx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;         
00808     hdma_sai_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
00809     hdma_sai_tx.Init.MemBurst            = DMA_MBURST_SINGLE;
00810     hdma_sai_tx.Init.PeriphBurst         = DMA_PBURST_SINGLE; 
00811     
00812     hdma_sai_tx.Instance = AUDIO_SAIx_DMAx_STREAM;
00813     
00814     /* Associate the DMA handle */
00815     __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx);
00816     
00817     /* Deinitialize the Stream for new transfer */
00818     HAL_DMA_DeInit(&hdma_sai_tx);
00819     
00820     /* Configure the DMA Stream */
00821     HAL_DMA_Init(&hdma_sai_tx);      
00822   }
00823   
00824   /* SAI DMA IRQ Channel configuration */
00825   HAL_NVIC_SetPriority(AUDIO_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
00826   HAL_NVIC_EnableIRQ(AUDIO_SAIx_DMAx_IRQ); 
00827 }
00828 
00829 /**
00830   * @brief  Deinitialize SAI MSP.
00831   * @param  hsai: SAI handle
00832   * @param  Params  
00833   * @retval None
00834   */
00835 __weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params)
00836 {
00837     GPIO_InitTypeDef  gpio_init_structure;
00838 
00839     /* SAI DMA IRQ Channel deactivation */
00840     HAL_NVIC_DisableIRQ(AUDIO_SAIx_DMAx_IRQ);
00841 
00842     if(hsai->Instance == AUDIO_SAIx)
00843     {
00844       /* Deinitialize the DMA stream */
00845       HAL_DMA_DeInit(hsai->hdmatx);
00846     }
00847 
00848     /* Disable SAI peripheral */
00849     __HAL_SAI_DISABLE(hsai);  
00850 
00851     /* Deactivates CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */
00852     gpio_init_structure.Pin = AUDIO_SAIx_FS_PIN;
00853     HAL_GPIO_DeInit(AUDIO_SAIx_FS_GPIO_PORT, gpio_init_structure.Pin);
00854 
00855     gpio_init_structure.Pin = AUDIO_SAIx_SCK_PIN;
00856     HAL_GPIO_DeInit(AUDIO_SAIx_SCK_SD_GPIO_PORT, gpio_init_structure.Pin);
00857 
00858     gpio_init_structure.Pin =  AUDIO_SAIx_SD_PIN;
00859     HAL_GPIO_DeInit(AUDIO_SAIx_SCK_SD_GPIO_PORT, gpio_init_structure.Pin);
00860 
00861     gpio_init_structure.Pin = AUDIO_SAIx_MCLK_PIN;
00862     HAL_GPIO_DeInit(AUDIO_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin);
00863   
00864     /* Disable SAI clock */
00865     AUDIO_SAIx_CLK_DISABLE();
00866 
00867     /* GPIO pins clock and DMA clock can be shut down in the applic 
00868        by surcharging this __weak function */ 
00869 }
00870 
00871 /**
00872   * @brief  Clock Config.
00873   * @param  hsai: might be required to set audio peripheral predivider if any.
00874   * @param  AudioFreq: Audio frequency used to play the audio stream.
00875   * @param  Params   
00876   * @note   This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency()
00877   *         Being __weak it can be overwritten by the application     
00878   * @retval None
00879   */
00880 __weak void BSP_AUDIO_OUT_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params)
00881 { 
00882   RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct;
00883 
00884   HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct);
00885   
00886   /* Set the PLL configuration according to the audio frequency */
00887   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
00888   {
00889     /* Configure PLLSAI prescalers */
00890     /* PLLSAI_VCO: VCO_429M 
00891     SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 429/2 = 214.5 Mhz
00892     SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 214.5/19 = 11.289 Mhz */ 
00893     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2;
00894     rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S;
00895     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429;
00896     rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2;
00897     rcc_ex_clk_init_struct.PLLI2SDivQ = 19;
00898     
00899     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
00900     
00901   }
00902   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_32K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
00903   {
00904     /* SAI clock config 
00905     PLLSAI_VCO: VCO_344M 
00906     SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 344/7 = 49.142 Mhz 
00907     SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 49.142/1 = 49.142 Mhz */  
00908     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2;
00909     rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S;
00910     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 
00911     rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 
00912     rcc_ex_clk_init_struct.PLLI2SDivQ = 1;      
00913     
00914     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
00915   }
00916 }
00917 
00918 /*******************************************************************************
00919                             Static Functions
00920 *******************************************************************************/
00921 
00922 /**
00923   * @brief  Initialize the Audio Codec audio interface (SAI).
00924   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00925   * @note   The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 
00926   *         and user can update this configuration using 
00927   * @retval None
00928   */
00929 static void SAIx_Init(uint32_t AudioFreq)
00930 {
00931   /* Initialize the haudio_out_sai Instance parameter */
00932   haudio_out_sai.Instance = AUDIO_SAIx;
00933   
00934   /* Disable SAI peripheral to allow access to SAI internal registers */
00935   __HAL_SAI_DISABLE(&haudio_out_sai);
00936   
00937   /* Configure SAI_Block_x 
00938   LSBFirst: Disabled 
00939   DataSize: 16 */
00940   haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE;
00941   haudio_out_sai.Init.AudioFrequency = AudioFreq;
00942   haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX;
00943   haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
00944   haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL;
00945   haudio_out_sai.Init.DataSize = SAI_DATASIZE_16;
00946   haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
00947   haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
00948   haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS;
00949   haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
00950   haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
00951   haudio_out_sai.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
00952   haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING;
00953   haudio_out_sai.Init.TriState       = SAI_OUTPUT_NOTRELEASED;
00954   haudio_out_sai.Init.Mckdiv         = 0;
00955     
00956   /* Configure SAI_Block_x Frame 
00957   Frame Length: 64
00958   Frame active Length: 32
00959   FS Definition: Start frame + Channel Side identification
00960   FS Polarity: FS active Low
00961   FS Offset: FS asserted one bit before the first bit of slot 0 */ 
00962   haudio_out_sai.FrameInit.FrameLength = 64; 
00963   haudio_out_sai.FrameInit.ActiveFrameLength = 32;
00964   haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
00965   haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
00966   haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
00967   
00968   /* Configure SAI Block_x Slot 
00969   Slot First Bit Offset: 0
00970   Slot Size  : 16
00971   Slot Number: 4
00972   Slot Active: All slot actives */
00973   haudio_out_sai.SlotInit.FirstBitOffset = 0;
00974   haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
00975   haudio_out_sai.SlotInit.SlotNumber = 4; 
00976   haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123;
00977 
00978   HAL_SAI_Init(&haudio_out_sai);
00979   
00980   /* Enable SAI peripheral to generate MCLK */
00981   __HAL_SAI_ENABLE(&haudio_out_sai);
00982 }
00983 
00984 /**
00985   * @brief  Deinitialize the Audio Codec audio interface (SAI).
00986   * @retval None
00987   */
00988 static void SAIx_DeInit(void)
00989 {
00990   /* Initialize the haudio_out_sai Instance parameter */
00991   haudio_out_sai.Instance = AUDIO_SAIx;
00992 
00993   /* Disable SAI peripheral */
00994   __HAL_SAI_DISABLE(&haudio_out_sai);
00995 
00996   HAL_SAI_DeInit(&haudio_out_sai);
00997 }
00998 
00999 /**
01000   * @}
01001   */
01002 
01003 /** @defgroup STM32F769I_EVAL_AUDIO_out_Private_Functions STM32F769I_EVAL_AUDIO_Out Private Functions
01004   * @{
01005   */ 
01006 
01007 /**
01008   * @brief  Initialize wave recording. 
01009   * @param  AudioFreq: Audio frequency to be configured for the DFSDM peripheral. 
01010   * @param  BitRes: Audio frequency to be configured for the DFSDM peripheral.
01011   * @param  ChnlNbr: Audio frequency to be configured for the DFSDM peripheral.
01012   * @retval AUDIO_OK if correct communication, else wrong communication
01013   */
01014 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
01015 { 
01016   
01017   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
01018   BSP_AUDIO_IN_ClockConfig(&haudio_in_dfsdm_leftfilter, AudioFreq, NULL);
01019   
01020   /* Init the SAI MSP: this __weak function can be redefined by the application*/
01021   BSP_AUDIO_IN_MspInit();
01022   
01023   /* Initializes DFSDM peripheral */
01024   DFSDMx_Init(AudioFreq);
01025   
01026   /* Return AUDIO_OK when all operations are correctly done */
01027   return AUDIO_OK;
01028 }
01029 
01030 /**
01031   * @brief  Allocate channel buffer scratch 
01032   * @param  pScratch : pointer to scratch tables.
01033   * @param  size of scratch buffer
01034   */
01035 uint8_t BSP_AUDIO_IN_AllocScratch (int32_t *pScratch, uint32_t size)
01036 { 
01037   uint32_t idx;
01038   
01039   ScratchSize = size / DEFAULT_AUDIO_IN_CHANNEL_NBR;
01040   
01041   /* copy scratch pointers */
01042   for (idx = 0; idx < DEFAULT_AUDIO_IN_CHANNEL_NBR ; idx++)
01043   {
01044     pScratchBuff[idx] = (int32_t *)(pScratch + idx * ScratchSize);
01045   }
01046   /* Return AUDIO_OK */
01047   return AUDIO_OK;
01048 }
01049 
01050 /**
01051   * @brief  Start audio recording.
01052   * @param  pbuf: Main buffer pointer for the recorded data storing  
01053   * @param  size: Current size of the recorded buffer
01054   * @retval AUDIO_OK if correct communication, else wrong communication
01055   */
01056 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size)
01057 {
01058   hAudioIn.pRecBuf = pbuf;
01059   hAudioIn.RecSize = size;
01060   /* Reset Application Buffer Trigger */
01061   AppBuffTrigger = 0;
01062   AppBuffHalf = 0;
01063   
01064   /* Call the Media layer start function for right channel */
01065   if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_rightfilter, pScratchBuff[0], ScratchSize))
01066   {
01067     return AUDIO_ERROR;
01068   }
01069   
01070   /* Call the Media layer start function for left channel */
01071   if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_leftfilter, pScratchBuff[1], ScratchSize))
01072   {
01073     return AUDIO_ERROR;
01074   }
01075   
01076   /* Return AUDIO_OK when all operations are correctly done */
01077   return AUDIO_OK;
01078 }
01079 
01080 /**
01081   * @brief  Stop audio recording.
01082   * @retval AUDIO_OK if correct communication, else wrong communication
01083   */
01084 uint8_t BSP_AUDIO_IN_Stop(void)
01085 {
01086   AppBuffTrigger = 0;
01087   AppBuffHalf    = 0;
01088   
01089   /* Call the Media layer stop function for right channel */
01090   if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_rightfilter))
01091   {
01092     return AUDIO_ERROR;
01093   }
01094   
01095   /* Call the Media layer stop function for left channel */
01096   if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_leftfilter))
01097   {
01098     return AUDIO_ERROR;
01099   }
01100   
01101   /* Return AUDIO_OK when all operations are correctly done */
01102   return AUDIO_OK;
01103 }
01104 
01105 /**
01106   * @brief  Pause the audio file stream.
01107   * @retval AUDIO_OK if correct communication, else wrong communication
01108   */
01109 uint8_t BSP_AUDIO_IN_Pause(void)
01110 {
01111   /* Call the Media layer stop function */
01112   if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_rightfilter))
01113   {
01114     return AUDIO_ERROR;
01115   }
01116   
01117   /* Call the Media layer stop function */
01118   if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_leftfilter))
01119   {
01120     return AUDIO_ERROR;
01121   }
01122   
01123   /* Return AUDIO_OK when all operations are correctly done */
01124   return AUDIO_OK;
01125 }
01126 
01127 /**
01128   * @brief  Resume the audio file stream.
01129   * @retval AUDIO_OK if correct communication, else wrong communication
01130   */
01131 uint8_t BSP_AUDIO_IN_Resume(void)
01132 {
01133   /* Call the Media layer start function for right channel */
01134   if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_rightfilter, pScratchBuff[0], ScratchSize))
01135   {
01136     return AUDIO_ERROR;
01137   }
01138   
01139   /* Call the Media layer start function for left channel */
01140   if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_leftfilter, pScratchBuff[1], ScratchSize))
01141   {
01142     return AUDIO_ERROR;
01143   }
01144   
01145   /* Return AUDIO_OK when all operations are correctly done */
01146   return AUDIO_OK;
01147 }
01148 
01149 /**
01150   * @brief  Deinit the audio IN peripherals.
01151   * @retval None
01152   */
01153 void BSP_AUDIO_IN_DeInit(void)
01154 {
01155   BSP_AUDIO_IN_MspDeInit();
01156   DFSDMx_DeInit();
01157 }
01158 
01159 
01160 /**
01161   * @brief  Regular conversion complete callback. 
01162   * @note   In interrupt mode, user has to read conversion value in this function
01163             using HAL_DFSDM_FilterGetRegularValue.
01164   * @param  hdfsdm_filter : DFSDM filter handle.
01165   * @retval None
01166   */
01167 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01168 {
01169   uint32_t index = 0;
01170 
01171   if(hdfsdm_filter == &haudio_in_dfsdm_leftfilter)
01172   {
01173     DmaLeftRecBuffCplt = 1;
01174   }
01175   else
01176   {
01177     DmaRightRecBuffCplt = 1;
01178   }    
01179     if((DmaLeftRecBuffCplt == 1) && (DmaRightRecBuffCplt == 1))
01180     {    
01181     for(index = (ScratchSize/2) ; index < ScratchSize; index++)
01182     {
01183       hAudioIn.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760));
01184       hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760));
01185       AppBuffTrigger +=2;
01186     }
01187       DmaLeftRecBuffCplt  = 0;
01188       DmaRightRecBuffCplt = 0;
01189     }
01190 
01191   /* Call Half Transfer Complete callback */
01192   if((AppBuffTrigger == hAudioIn.RecSize/2) && (AppBuffHalf == 0))
01193   {
01194   AppBuffHalf = 1;  
01195   BSP_AUDIO_IN_HalfTransfer_CallBack();
01196   }
01197   /* Call Transfer Complete callback */
01198   if(AppBuffTrigger == hAudioIn.RecSize)
01199   {
01200     /* Reset Application Buffer Trigger */
01201     AppBuffTrigger = 0;
01202     AppBuffHalf = 0; 
01203     /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01204     BSP_AUDIO_IN_TransferComplete_CallBack();
01205   }  
01206 }
01207 
01208 /**
01209   * @brief  Half regular conversion complete callback. 
01210   * @param  hdfsdm_filter : DFSDM filter handle.
01211   * @retval None
01212   */
01213 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01214 {
01215   uint32_t index = 0;
01216 
01217     if(hdfsdm_filter == &haudio_in_dfsdm_leftfilter)
01218     {
01219       DmaLeftRecHalfBuffCplt = 1;
01220     }
01221     else
01222     {
01223       DmaRightRecHalfBuffCplt = 1;
01224     }    
01225     if((DmaLeftRecHalfBuffCplt == 1) && (DmaRightRecHalfBuffCplt == 1))
01226     {
01227       for(index = 0; index < ScratchSize/2; index++)
01228       {
01229         hAudioIn.pRecBuf[AppBuffTrigger]     = (int16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760));
01230         hAudioIn.pRecBuf[AppBuffTrigger + 1] = (int16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760));
01231         AppBuffTrigger +=2;
01232       }
01233       DmaLeftRecHalfBuffCplt  = 0;
01234       DmaRightRecHalfBuffCplt = 0; 
01235     }
01236 
01237   /* Call Half Transfer Complete callback */
01238   if((AppBuffTrigger == hAudioIn.RecSize/2) && (AppBuffHalf == 0))
01239   { 
01240   AppBuffHalf = 1;  
01241   BSP_AUDIO_IN_HalfTransfer_CallBack();
01242   }
01243   /* Call Transfer Complete callback */
01244   if(AppBuffTrigger == hAudioIn.RecSize)
01245   {
01246     /* Reset Application Buffer Trigger */
01247     AppBuffTrigger = 0;
01248     AppBuffHalf = 0;
01249     /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01250     BSP_AUDIO_IN_TransferComplete_CallBack();
01251   }  
01252 }
01253 
01254 /**
01255   * @brief  User callback when record buffer is filled.
01256   * @retval None
01257   */
01258 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void)
01259 {
01260   /* This function should be implemented by the user application.
01261      It is called into this driver when the current buffer is filled
01262      to prepare the next buffer pointer and its size. */
01263 }
01264 
01265 /**
01266   * @brief  Manages the DMA Half Transfer complete event.
01267   * @retval None
01268   */
01269 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
01270 { 
01271   /* This function should be implemented by the user application.
01272      It is called into this driver when the current buffer is filled
01273      to prepare the next buffer pointer and its size. */
01274 }
01275 
01276 /**
01277   * @brief  Audio IN Error callback function.
01278   * @retval None
01279   */
01280 __weak void BSP_AUDIO_IN_Error_Callback(void)
01281 {   
01282   /* This function is called when an Interrupt due to transfer error on or peripheral
01283      error occurs. */
01284 }
01285 
01286 /**
01287   * @brief  Initialize BSP_AUDIO_IN MSP.
01288   * @retval None
01289   */
01290 __weak void BSP_AUDIO_IN_MspInit(void)
01291 { 
01292   /* MSP channels initialization */
01293   DFSDMx_ChannelMspInit();  
01294   /* MSP filters initialization */
01295   DFSDMx_FilterMspInit();
01296 }
01297 
01298 /**
01299   * @brief  DeInitialize BSP_AUDIO_IN MSP.
01300   * @retval None
01301   */
01302 __weak void BSP_AUDIO_IN_MspDeInit(void)
01303 { 
01304   /* MSP channels initialization */
01305   DFSDMx_ChannelMspDeInit();  
01306   /* MSP filters initialization */
01307   DFSDMx_FilterMspDeInit();
01308 }
01309 
01310 /**
01311   * @brief  Clock Config.
01312   * @param  hdfsdm_filter: might be required to set audio peripheral predivider if any.
01313   * @param  AudioFreq: Audio frequency used to play the audio stream.
01314   * @param  Params   
01315   * @note   This API is called by BSP_AUDIO_IN_Init()
01316   *         Being __weak it can be overwritten by the application     
01317   * @retval None
01318   */
01319 __weak void BSP_AUDIO_IN_ClockConfig(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, uint32_t AudioFreq, void *Params)
01320 { 
01321   RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct;
01322 
01323   HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct);
01324   
01325   /* Set the PLL configuration according to the audio frequency */
01326   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
01327   {
01328     /* Configure PLLSAI prescalers */
01329     /* PLLI2S_VCO: VCO_429M 
01330     SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 429/2 = 214.5 Mhz
01331     SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 214.5/19 = 11.289 Mhz */ 
01332     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2;
01333     rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S;
01334     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429;
01335     rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2;
01336     rcc_ex_clk_init_struct.PLLI2SDivQ = 19;
01337     
01338     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
01339     
01340   }
01341   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_32K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
01342   {
01343     /* SAI clock config 
01344     PLLI2S_VCO: VCO_344M 
01345     SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 344/7 = 49.142 Mhz 
01346     SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 49.142/1 = 49.142 Mhz */  
01347     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2;
01348     rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S;
01349     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 
01350     rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 
01351     rcc_ex_clk_init_struct.PLLI2SDivQ = 1;   
01352     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
01353   }
01354   
01355   rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_DFSDM1_AUDIO;
01356   rcc_ex_clk_init_struct.Dfsdm1AudioClockSelection = RCC_DFSDM1AUDIOCLKSOURCE_SAI2;
01357   HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 
01358 }
01359 
01360 /*******************************************************************************
01361                             Static Functions
01362 *******************************************************************************/
01363 /**
01364   * @brief  Initialize the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01365   * @param  AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral.
01366   * @note   Channel output Clock Divider and Filter Oversampling are calculated as follow: 
01367   *         - Clock_Divider = CLK(input DFSDM)/CLK(micro) with
01368   *           1MHZ < CLK(micro) < 3.2MHZ (TYP 2.4MHZ for MP34DT01TR)
01369   *         - Oversampling = CLK(input DFSDM)/(Clock_Divider * AudioFreq)  
01370   * @retval AUDIO_OK if correct communication, else wrong communication
01371   */
01372 static uint8_t DFSDMx_Init(uint32_t AudioFreq)
01373 {
01374   /*####CHANNEL 1####*/
01375   __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&haudio_in_dfsdm_leftchannel);  
01376   haudio_in_dfsdm_leftchannel.Instance                      = DFSDM1_Channel1;  
01377   haudio_in_dfsdm_leftchannel.Init.OutputClock.Activation   = ENABLE;
01378   haudio_in_dfsdm_leftchannel.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
01379   /* Set the DFSDM clock OUT audio frequency configuration */
01380   haudio_in_dfsdm_leftchannel.Init.OutputClock.Divider      = DFSDM_CLOCK_DIVIDER(AudioFreq);
01381   haudio_in_dfsdm_leftchannel.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
01382   haudio_in_dfsdm_leftchannel.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
01383   haudio_in_dfsdm_leftchannel.Init.Input.Pins               = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
01384   /* Request to sample stable data for LEFT micro on Rising edge */
01385   haudio_in_dfsdm_leftchannel.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_RISING;
01386   haudio_in_dfsdm_leftchannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
01387   haudio_in_dfsdm_leftchannel.Init.Awd.FilterOrder          = DFSDM_CHANNEL_FASTSINC_ORDER;
01388   haudio_in_dfsdm_leftchannel.Init.Awd.Oversampling         = 10;
01389   haudio_in_dfsdm_leftchannel.Init.Offset                   = 0;
01390   haudio_in_dfsdm_leftchannel.Init.RightBitShift            = DFSDM_RIGHT_BIT_SHIFT(AudioFreq);
01391   if(HAL_OK != HAL_DFSDM_ChannelInit(&haudio_in_dfsdm_leftchannel))
01392   {
01393     return AUDIO_ERROR;
01394   }
01395 
01396   /*####FILTER 0####*/
01397   __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&haudio_in_dfsdm_leftfilter);
01398   haudio_in_dfsdm_leftfilter.Instance                          = AUDIO_DFSDMx_LEFT_FILTER;  
01399   haudio_in_dfsdm_leftfilter.Init.RegularParam.Trigger         = DFSDM_FILTER_SW_TRIGGER;
01400   haudio_in_dfsdm_leftfilter.Init.RegularParam.FastMode        = ENABLE;
01401   haudio_in_dfsdm_leftfilter.Init.RegularParam.DmaMode         = ENABLE;
01402   haudio_in_dfsdm_leftfilter.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
01403   haudio_in_dfsdm_leftfilter.Init.InjectedParam.ScanMode       = ENABLE;
01404   haudio_in_dfsdm_leftfilter.Init.InjectedParam.DmaMode        = DISABLE;
01405   haudio_in_dfsdm_leftfilter.Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
01406   haudio_in_dfsdm_leftfilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
01407   haudio_in_dfsdm_leftfilter.Init.FilterParam.SincOrder        = DFSDM_FILTER_ORDER(AudioFreq);
01408   /* Set the DFSDM Filters Oversampling to have correct sample rate */
01409   haudio_in_dfsdm_leftfilter.Init.FilterParam.Oversampling     = DFSDM_OVER_SAMPLING(AudioFreq);
01410   haudio_in_dfsdm_leftfilter.Init.FilterParam.IntOversampling  = 1;
01411   if(HAL_OK != HAL_DFSDM_FilterInit(&haudio_in_dfsdm_leftfilter))
01412   {
01413     return AUDIO_ERROR;
01414   }
01415 
01416   /* Configure injected channel */
01417   if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&haudio_in_dfsdm_leftfilter, DFSDM_CHANNEL_1, DFSDM_CONTINUOUS_CONV_ON))
01418   {
01419     return AUDIO_ERROR;
01420   }
01421   
01422   /*####CHANNEL 0####*/
01423   __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&haudio_in_dfsdm_rightchannel);  
01424   haudio_in_dfsdm_rightchannel.Instance                      = DFSDM1_Channel0;  
01425   haudio_in_dfsdm_rightchannel.Init.OutputClock.Activation   = ENABLE;
01426   haudio_in_dfsdm_rightchannel.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
01427   /* Set the DFSDM clock OUT audio frequency configuration */
01428   haudio_in_dfsdm_rightchannel.Init.OutputClock.Divider      = DFSDM_CLOCK_DIVIDER(AudioFreq);
01429   haudio_in_dfsdm_rightchannel.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
01430   haudio_in_dfsdm_rightchannel.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
01431   haudio_in_dfsdm_rightchannel.Init.Input.Pins               = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS;
01432   /* Request to sample stable data for RIGHT micro on Falling edge */
01433   haudio_in_dfsdm_rightchannel.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_FALLING;
01434   haudio_in_dfsdm_rightchannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
01435   haudio_in_dfsdm_rightchannel.Init.Awd.FilterOrder          = DFSDM_CHANNEL_FASTSINC_ORDER;
01436   haudio_in_dfsdm_rightchannel.Init.Awd.Oversampling         = 10;
01437   haudio_in_dfsdm_rightchannel.Init.Offset                   = 0;
01438   haudio_in_dfsdm_rightchannel.Init.RightBitShift            = DFSDM_RIGHT_BIT_SHIFT(AudioFreq);
01439   if(HAL_OK != HAL_DFSDM_ChannelInit(&haudio_in_dfsdm_rightchannel))
01440   {
01441     return AUDIO_ERROR;
01442   }
01443   
01444   /*####FILTER 1####*/
01445   __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&haudio_in_dfsdm_rightfilter);
01446   haudio_in_dfsdm_rightfilter.Instance                          = AUDIO_DFSDMx_RIGHT_FILTER;
01447   haudio_in_dfsdm_rightfilter.Init.RegularParam.Trigger         = DFSDM_FILTER_SYNC_TRIGGER;
01448   haudio_in_dfsdm_rightfilter.Init.RegularParam.FastMode        = ENABLE;
01449   haudio_in_dfsdm_rightfilter.Init.RegularParam.DmaMode         = ENABLE;
01450   haudio_in_dfsdm_rightfilter.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
01451   haudio_in_dfsdm_rightfilter.Init.InjectedParam.ScanMode       = DISABLE;
01452   haudio_in_dfsdm_rightfilter.Init.InjectedParam.DmaMode        = DISABLE;
01453   haudio_in_dfsdm_rightfilter.Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
01454   haudio_in_dfsdm_rightfilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
01455   haudio_in_dfsdm_rightfilter.Init.FilterParam.SincOrder        = DFSDM_FILTER_ORDER(AudioFreq);
01456   /* Set the DFSDM Filters Oversampling to have correct sample rate */
01457   haudio_in_dfsdm_rightfilter.Init.FilterParam.Oversampling     = DFSDM_OVER_SAMPLING(AudioFreq);
01458   haudio_in_dfsdm_rightfilter.Init.FilterParam.IntOversampling  = 1;
01459   if(HAL_OK != HAL_DFSDM_FilterInit(&haudio_in_dfsdm_rightfilter))
01460   {
01461     return AUDIO_ERROR;
01462   }
01463   /* Configure injected channel */
01464   if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&haudio_in_dfsdm_rightfilter, DFSDM_CHANNEL_0, DFSDM_CONTINUOUS_CONV_ON))
01465   {
01466     return AUDIO_ERROR;
01467   }  
01468   
01469   return AUDIO_OK;
01470 }
01471 
01472 /**
01473   * @brief  De-initialize the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01474   * @retval AUDIO_OK if correct communication, else wrong communication
01475   */
01476 static uint8_t DFSDMx_DeInit(void)
01477 {
01478   /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */
01479   if(HAL_OK != HAL_DFSDM_FilterDeInit(&haudio_in_dfsdm_leftfilter))
01480   {
01481     return AUDIO_ERROR;
01482   }
01483 
01484   if(HAL_OK != HAL_DFSDM_FilterDeInit(&haudio_in_dfsdm_rightfilter))
01485   {
01486     return AUDIO_ERROR;
01487   }
01488 
01489   /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */
01490   if(HAL_OK != HAL_DFSDM_ChannelDeInit(&haudio_in_dfsdm_leftchannel))
01491   {
01492     return AUDIO_ERROR;
01493   }
01494 
01495   if(HAL_OK != HAL_DFSDM_ChannelDeInit(&haudio_in_dfsdm_rightchannel))
01496   {
01497     return AUDIO_ERROR;
01498   }
01499 
01500   return AUDIO_OK;
01501 }
01502 
01503 /**
01504   * @brief  Initialize the DFSDM channel MSP.
01505   * @retval None
01506   */
01507 static void DFSDMx_ChannelMspInit(void)
01508 {
01509   GPIO_InitTypeDef  GPIO_InitStruct;  
01510 
01511   /* Enable DFSDM clock */
01512   AUDIO_DFSDMx_CLK_ENABLE();
01513   
01514   /* Enable GPIO clock */
01515   AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_CLK_ENABLE();
01516   
01517   /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN pins ------------------*/
01518   GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN;
01519   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
01520   GPIO_InitStruct.Pull = GPIO_NOPULL;
01521   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
01522   GPIO_InitStruct.Alternate = AUDIO_DFSDMx_CKOUT_AF;
01523   HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct);
01524   
01525   GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_DATIN_PIN;
01526   GPIO_InitStruct.Alternate = AUDIO_DFSDMx_DMIC_DATIN_AF;
01527   HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct); 
01528 }
01529 
01530 /**
01531   * @brief  DeInitialize the DFSDM channel MSP.
01532   * @retval None
01533   */
01534 static void DFSDMx_ChannelMspDeInit(void)
01535 {
01536   GPIO_InitTypeDef  GPIO_InitStruct;  
01537 
01538   /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN pins ------------------*/
01539   GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN | AUDIO_DFSDMx_DMIC_DATIN_PIN;
01540   HAL_GPIO_DeInit(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, GPIO_InitStruct.Pin);
01541 }
01542 
01543 /**
01544   * @brief  Initialize the DFSDM filter MSP.
01545   * @retval None
01546   */
01547 static void DFSDMx_FilterMspInit(void)
01548 {  
01549   /* Enable DFSDM clock */
01550   AUDIO_DFSDMx_CLK_ENABLE();
01551   
01552   /* Enable the DMA clock */
01553   AUDIO_DFSDMx_DMAx_CLK_ENABLE();
01554   
01555   hdma_dfsdm_left.Init.Direction           = DMA_PERIPH_TO_MEMORY;
01556   hdma_dfsdm_left.Init.PeriphInc           = DMA_PINC_DISABLE;
01557   hdma_dfsdm_left.Init.MemInc              = DMA_MINC_ENABLE;
01558   hdma_dfsdm_left.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
01559   hdma_dfsdm_left.Init.MemDataAlignment    = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
01560   hdma_dfsdm_left.Init.Mode                = DMA_CIRCULAR;
01561   hdma_dfsdm_left.Init.Priority            = DMA_PRIORITY_HIGH;
01562   hdma_dfsdm_left.Instance               = DMA2_Stream0;
01563   hdma_dfsdm_left.Init.Channel           = AUDIO_DFSDMx_DMAx_LEFT_CHANNEL; 
01564   
01565   /* Associate the DMA handle */
01566   __HAL_LINKDMA(&haudio_in_dfsdm_leftfilter, hdmaReg, hdma_dfsdm_left);
01567   
01568   /* Reset DMA handle state */
01569   __HAL_DMA_RESET_HANDLE_STATE(&hdma_dfsdm_left);
01570   
01571   /* Configure the DMA Channel */
01572   HAL_DMA_Init(&hdma_dfsdm_left);      
01573   
01574   /* DMA IRQ Channel configuration */
01575   HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_LEFT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
01576   HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_LEFT_IRQ);
01577   
01578   
01579   /* Configure the hdma_dfsdmReg handle parameters */ 
01580   hdma_dfsdm_right.Init.Direction           = DMA_PERIPH_TO_MEMORY;
01581   hdma_dfsdm_right.Init.PeriphInc           = DMA_PINC_DISABLE;
01582   hdma_dfsdm_right.Init.MemInc              = DMA_MINC_ENABLE;
01583   hdma_dfsdm_right.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
01584   hdma_dfsdm_right.Init.MemDataAlignment    = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
01585   hdma_dfsdm_right.Init.Mode                = DMA_CIRCULAR;
01586   hdma_dfsdm_right.Init.Priority            = DMA_PRIORITY_HIGH;  
01587   hdma_dfsdm_right.Instance                 = DMA2_Stream5;
01588   hdma_dfsdm_right.Init.Channel             = AUDIO_DFSDMx_DMAx_RIGHT_CHANNEL;
01589   
01590   /* Associate the DMA handle */
01591   __HAL_LINKDMA(&haudio_in_dfsdm_rightfilter, hdmaReg, hdma_dfsdm_right);
01592   
01593   /* Reset DMA handle state */
01594   __HAL_DMA_RESET_HANDLE_STATE(&hdma_dfsdm_right);
01595   
01596   /* Configure the DMA Channel */
01597   HAL_DMA_Init(&hdma_dfsdm_right);      
01598   
01599   /* DMA IRQ Channel configuration */
01600   HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_RIGHT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
01601   HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_RIGHT_IRQ);
01602 }
01603 
01604 /**
01605   * @brief  DeInitialize the DFSDM filter MSP.
01606   * @retval None
01607   */
01608 static void DFSDMx_FilterMspDeInit(void)
01609 {
01610   /* Configure the DMA Channel */
01611   HAL_DMA_DeInit(&hdma_dfsdm_left);
01612   HAL_DMA_DeInit(&hdma_dfsdm_right);  
01613 }
01614 
01615 /**
01616   * @}
01617   */ 
01618   
01619 /**
01620   * @}
01621   */
01622 
01623 /**
01624   * @}
01625   */
01626 
01627 /**
01628   * @}
01629   */ 
01630 
01631 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Fri Dec 30 2016 20:55:35 for STM32769I_EVAL BSP User Manual by   doxygen 1.7.6.1