STM32769I_EVAL BSP User Manual: stm32f769i_eval_audio.c Source File

STM32769I_EVAL BSP

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