STM32F769I-Discovery BSP User Manual: stm32f769i_discovery_audio.c Source File

STM32F769I-Discovery BSP Drivers

stm32f769i_discovery_audio.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32f769i_discovery_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-DISCOVERY  
00008   *          board.
00009   @verbatim
00010   How To use this driver:
00011   -----------------------
00012    + This driver supports STM32F7xx devices on STM32F769I-DISCOVERY (MB1225) 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 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-DISCOVERY 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_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 BSP_AUDIO_OUT_XXX_CallBack() and only their prototypes are declared in 
00042       the stm32f769i_discovery_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 
00048    + Call the function BSP_AUDIO_IN_Init(
00049                                     AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000...)
00050                                                   this parameter is relative to the audio file/stream type.
00051                                     BitRes: Bit resolution fixed to 16bit
00052                                     ChnlNbr: Number of channel to be configured for the DFSDM peripheral
00053                                    )
00054       This function configures all the hardware required for the audio in application (DFSDM filters and channels, 
00055       Clock source for DFSDM periphiral, GPIOs, DMA and interrupt if needed). 
00056       This function returns AUDIO_OK if configuration is OK.If the returned value is different from AUDIO_OK then
00057       the configuration should be wrong.
00058       Note: On STM32F769I-DISCOVERY, four DFSDM Channel/Filters are configured and their DMA streams are configured
00059             in CIRCULAR mode.
00060    + Call the function BSP_AUDIO_IN_AllocScratch(
00061                                         pScratch: pointer to scratch tables
00062                                         size: size of scratch buffer)
00063      This function must be called before BSP_AUDIO_IN_RECORD() to allocate buffer scratch for each DFSDM channel
00064      and its size.
00065      Note: These buffers scratch are used as intermidiate buffers to collect data within final record buffer.
00066            size is the total size of the four buffers scratch; If size is 512 then the size of each is 128.
00067            This function must be called after BSP_AUDIO_IN_Init()
00068    + Call the function BSP_AUDIO_IN_RECORD(
00069                                   pBuf: pointer to the recorded audio data file address
00070                                   Size: size of the buffer to be written in Bytes
00071                                  )
00072       to start recording from microphones.
00073 
00074    + Call the function BSP_AUDIO_IN_Pause() to pause recording   
00075    + Call the function BSP_AUDIO_IN_Resume() to recording playing.
00076        Note. After calling BSP_AUDIO_IN_Pause() function for pause, only BSP_AUDIO_IN_Resume() should be called
00077           for resume (it is not allowed to call BSP_AUDIO_IN_RECORD() in this case).
00078    + Call the function BSP_AUDIO_IN_Stop() to stop recording 
00079    + For each mode, you may need to implement the relative callback functions into your code.
00080       The Callback functions are named BSP_AUDIO_IN_XXX_CallBack() and only their prototypes are declared in 
00081       the stm32f769i_discovery_audio.h file. (refer to the example for more details on the callbacks implementations)
00082 
00083   Driver architecture:
00084   --------------------
00085    + This driver provides the High Audio Layer: consists of the function API exported in the stm32f769i_discovery_audio.h file
00086      (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...)
00087    + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/
00088      providing the audio file/stream. These functions are also included as local functions into
00089      the stm32f769i_discovery_audio.c file (DFSDMx_Init(), DFSDMx_DeInit(), SAIx_Init() and SAIx_DeInit())
00090 
00091   Known Limitations:
00092   ------------------
00093    1- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second 
00094       Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams.
00095    2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 
00096       File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file.
00097    3- Supports only Stereo audio streaming.
00098    4- Supports only 16-bits audio data size.
00099   @endverbatim  
00100   ******************************************************************************
00101   * @attention
00102   *
00103   * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
00104   *
00105   * Redistribution and use in source and binary forms, with or without modification,
00106   * are permitted provided that the following conditions are met:
00107   *   1. Redistributions of source code must retain the above copyright notice,
00108   *      this list of conditions and the following disclaimer.
00109   *   2. Redistributions in binary form must reproduce the above copyright notice,
00110   *      this list of conditions and the following disclaimer in the documentation
00111   *      and/or other materials provided with the distribution.
00112   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00113   *      may be used to endorse or promote products derived from this software
00114   *      without specific prior written permission.
00115   *
00116   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00117   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00118   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00119   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00120   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00121   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00122   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00123   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00124   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00125   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00126   *
00127   ******************************************************************************
00128   */
00129 /* Includes ------------------------------------------------------------------*/
00130 #include "stm32f769i_discovery_audio.h"
00131 
00132 /** @addtogroup BSP
00133   * @{
00134   */
00135 
00136 /** @addtogroup STM32F769I_DISCOVERY
00137   * @{
00138   */ 
00139   
00140 /** @defgroup STM32F769I_DISCOVERY_AUDIO STM32F769I_DISCOVERY AUDIO
00141   * @brief This file includes the low layer driver for wm8994 Audio Codec
00142   *        available on STM32F769I-DISCOVERY discoveryuation board(MB1225).
00143   * @{
00144   */ 
00145 
00146 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Types STM32F769I_DISCOVERY_AUDIO Private Types
00147   * @{
00148   */ 
00149 typedef struct
00150 {
00151   uint16_t      *pRecBuf;       /* Pointer to record user buffer */
00152   uint32_t      RecSize;        /* Size to record in mono, double size to record in stereo */
00153 }AUDIOIN_TypeDef;
00154 
00155 /**
00156   * @}
00157   */ 
00158   
00159 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Defines STM32F769I_DISCOVERY_AUDIO Private Defines
00160   * @{
00161   */
00162 /**
00163   * @}
00164   */ 
00165 
00166 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Macros STM32F769I_DISCOVERY_AUDIO Private Macros
00167   * @{
00168   */
00169 /*### RECORD ###*/
00170 #define DFSDM_OVER_SAMPLING(__FREQUENCY__) \
00171         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 256 \
00172       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \
00173       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \
00174       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \
00175       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \
00176       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64  \
00177       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 40 : 20  \
00178 
00179 #define DFSDM_CLOCK_DIVIDER(__FREQUENCY__) \
00180         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 24 \
00181       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \
00182       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \
00183       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
00184       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \
00185       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4  \
00186       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 25 : 25  \
00187 
00188 #define DFSDM_FILTER_ORDER(__FREQUENCY__) \
00189         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? DFSDM_FILTER_SINC3_ORDER \
00190       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \
00191       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \
00192       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \
00193       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \
00194       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC3_ORDER  \
00195       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC3_ORDER : DFSDM_FILTER_SINC5_ORDER  \
00196 
00197 #define DFSDM_RIGHT_BIT_SHIFT(__FREQUENCY__) \
00198         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 8 \
00199       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 8 \
00200       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 3 \
00201       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
00202       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 7 \
00203       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 0  \
00204       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 0 : 4  \
00205 
00206 /* Saturate the record PCM sample */
00207 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N)))
00208 /**
00209   * @}
00210   */ 
00211   
00212 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Variables STM32F769I_DISCOVERY_AUDIO Private Variables
00213   * @{
00214   */
00215 /* PLAY */
00216 AUDIO_DrvTypeDef                *audio_drv;
00217 SAI_HandleTypeDef               haudio_out_sai;
00218 SAI_HandleTypeDef               haudio_in_sai;
00219 
00220 /* RECORD */
00221 AUDIOIN_TypeDef                 hAudioIn;
00222 
00223 DFSDM_Channel_HandleTypeDef     hAudioInTopLeftChannel;
00224 DFSDM_Channel_HandleTypeDef     hAudioInTopRightChannel;
00225 DFSDM_Filter_HandleTypeDef      hAudioInTopLeftFilter;
00226 DFSDM_Filter_HandleTypeDef      hAudioInTopRightFilter;
00227 DMA_HandleTypeDef               hDmaTopLeft;
00228 DMA_HandleTypeDef               hDmaTopRight;
00229 
00230 DFSDM_Channel_HandleTypeDef     hAudioInButtomLeftChannel;
00231 DFSDM_Channel_HandleTypeDef     hAudioInButtomRightChannel;
00232 DFSDM_Filter_HandleTypeDef      hAudioInButtomLeftFilter;
00233 DFSDM_Filter_HandleTypeDef      hAudioInButtomRightFilter;
00234 DMA_HandleTypeDef               hDmaButtomLeft;
00235 DMA_HandleTypeDef               hDmaButtomRight;
00236 
00237 /* Buffers for right and left samples */
00238 static int32_t                  *pScratchBuff[2*DEFAULT_AUDIO_IN_CHANNEL_NBR];
00239 static __IO int32_t             ScratchSize;
00240 /* Cannel number to be used: 2 channels by default */
00241 static uint8_t                  AudioIn_ChannelNumber = DEFAULT_AUDIO_IN_CHANNEL_NBR;
00242 /* Input device to be used: digital microphones by default */
00243 static uint16_t                 AudioIn_Device = INPUT_DEVICE_DIGITAL_MIC; 
00244 
00245 /* Buffers status flags */
00246 static uint32_t                DmaTopLeftRecHalfCplt  = 0;
00247 static uint32_t                DmaTopLeftRecCplt      = 0;
00248 static uint32_t                DmaTopRightRecHalfCplt = 0;
00249 static uint32_t                DmaTopRightRecCplt     = 0;
00250 static uint32_t                DmaButtomLeftRecHalfCplt  = 0;
00251 static uint32_t                DmaButtomLeftRecCplt      = 0;
00252 static uint32_t                DmaButtomRightRecHalfCplt = 0;
00253 static uint32_t                DmaButtomRightRecCplt     = 0;
00254 
00255 /* Application Buffer Trigger */
00256 static __IO uint32_t           AppBuffTrigger          = 0;
00257 static __IO uint32_t           AppBuffHalf             = 0;
00258 
00259 /**
00260   * @}
00261   */ 
00262 
00263 /** @defgroup STM32F769I_DISCOVERY_AUDIO_Private_Function_Prototypes STM32F769I_DISCOVERY_AUDIO Private Function Prototypes
00264   * @{
00265   */
00266 static void SAIx_Out_Init(uint32_t AudioFreq);
00267 static void SAIx_Out_DeInit(void);
00268 static void SAI_AUDIO_IN_MspInit(SAI_HandleTypeDef *hsai, void *Params);
00269 static void SAI_AUDIO_IN_MspDeInit(SAI_HandleTypeDef *hsai, void *Params);
00270 static void SAIx_In_Init(uint32_t AudioFreq);
00271 static void SAIx_In_DeInit(void);
00272 static void    DFSDMx_ChannelMspInit(void);
00273 static void    DFSDMx_FilterMspInit(void);
00274 static void    DFSDMx_ChannelMspDeInit(void);
00275 static void    DFSDMx_FilterMspDeInit(void);
00276 static uint8_t DFSDMx_Init(uint32_t AudioFreq);
00277 static uint8_t DFSDMx_DeInit(void);
00278 
00279 /**
00280   * @}
00281   */ 
00282 
00283 /** @defgroup STM32F769I_DISCOVERY_AUDIO_out_Private_Functions STM32F769I_DISCOVERY_AUDIO_Out Private Functions
00284   * @{
00285   */ 
00286 
00287 /**
00288   * @brief  Configures the audio peripherals.
00289   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
00290   *                       or OUTPUT_DEVICE_BOTH.
00291   * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
00292   * @param  AudioFreq: Audio frequency used to play the audio stream.  
00293   * @retval AUDIO_OK if correct communication, else wrong communication
00294   */
00295 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
00296 { 
00297   uint8_t ret = AUDIO_ERROR;
00298   uint32_t deviceid = 0x00;
00299 
00300   /* Disable SAI */
00301   SAIx_Out_DeInit();
00302 
00303   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
00304   BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
00305  
00306   /* SAI data transfer preparation:
00307   Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
00308   haudio_out_sai.Instance = AUDIO_OUT_SAIx;
00309   if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET)
00310   {
00311     /* Init the SAI MSP: this __weak function can be redefined by the application*/
00312     BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL);
00313   }
00314   SAIx_Out_Init(AudioFreq);
00315 
00316   /* wm8994 codec initialization */
00317   deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
00318   
00319   if((deviceid) == WM8994_ID)
00320   {  
00321     /* Reset the Codec Registers */
00322     wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
00323     /* Initialize the audio driver structure */
00324     audio_drv = &wm8994_drv; 
00325     ret = AUDIO_OK;
00326   }
00327   else
00328   {
00329     ret = AUDIO_ERROR;
00330   }
00331 
00332   if(ret == AUDIO_OK)
00333   {
00334     /* Initialize the codec internal registers */
00335     audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq);
00336   }
00337  
00338   return ret;
00339 }
00340 
00341 /**
00342   * @brief  Starts playing audio stream from a data buffer for a determined size. 
00343   * @param  pBuffer: Pointer to the buffer 
00344   * @param  Size: Number of audio data BYTES.
00345   * @retval AUDIO_OK if correct communication, else wrong communication
00346   */
00347 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size)
00348 {
00349   /* Call the audio Codec Play function */
00350   if(audio_drv->Play(AUDIO_I2C_ADDRESS, (uint16_t *)pBuffer, Size) != 0)
00351   {  
00352     return AUDIO_ERROR;
00353   }
00354   else
00355   {
00356     /* Update the Media layer and enable it for play */  
00357     HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE));
00358     
00359     return AUDIO_OK;
00360   }
00361 }
00362 
00363 /**
00364   * @brief  Sends n-Bytes on the SAI interface.
00365   * @param  pData: pointer on data address 
00366   * @param  Size: number of data to be written
00367   * @retval None
00368   */
00369 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size)
00370 {
00371    HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size);
00372 }
00373 
00374 /**
00375   * @brief  This function Pauses the audio file stream. In case
00376   *         of using DMA, the DMA Pause feature is used.
00377   * @note    When calling BSP_AUDIO_OUT_Pause() function for pause, only
00378   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00379   *          function for resume could lead to unexpected behaviour).
00380   * @retval AUDIO_OK if correct communication, else wrong communication
00381   */
00382 uint8_t BSP_AUDIO_OUT_Pause(void)
00383 {    
00384   /* Call the Audio Codec Pause/Resume function */
00385   if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0)
00386   {
00387     return AUDIO_ERROR;
00388   }
00389   else
00390   {
00391     /* Call the Media layer pause function */
00392     HAL_SAI_DMAPause(&haudio_out_sai);
00393     
00394     /* Return AUDIO_OK when all operations are correctly done */
00395     return AUDIO_OK;
00396   }
00397 }
00398 
00399 /**
00400   * @brief   Resumes the audio file stream.  
00401   * @note    When calling BSP_AUDIO_OUT_Pause() function for pause, only
00402   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00403   *          function for resume could lead to unexpected behaviour).
00404   * @retval AUDIO_OK if correct communication, else wrong communication
00405   */
00406 uint8_t BSP_AUDIO_OUT_Resume(void)
00407 {    
00408   /* Call the Audio Codec Pause/Resume function */
00409   if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0)
00410   {
00411     return AUDIO_ERROR;
00412   }
00413   else
00414   {
00415     /* Call the Media layer pause/resume function */
00416     HAL_SAI_DMAResume(&haudio_out_sai);
00417     
00418     /* Return AUDIO_OK when all operations are correctly done */
00419     return AUDIO_OK;
00420   }
00421 }
00422 
00423 /**
00424   * @brief  Stops audio playing and Power down the Audio Codec. 
00425   * @param  Option: could be one of the following parameters 
00426   *           - CODEC_PDWN_SW: for software power off (by writing registers). 
00427   *                            Then no need to reconfigure the Codec after power on.
00428   *           - CODEC_PDWN_HW: completely shut down the codec (physically). 
00429   *                            Then need to reconfigure the Codec after power on.  
00430   * @retval AUDIO_OK if correct communication, else wrong communication
00431   */
00432 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
00433 {
00434   /* Call the Media layer stop function */
00435   HAL_SAI_DMAStop(&haudio_out_sai);
00436   
00437   /* Call Audio Codec Stop function */
00438   if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
00439   {
00440     return AUDIO_ERROR;
00441   }
00442   else
00443   {
00444     if(Option == CODEC_PDWN_HW)
00445     { 
00446       /* Wait at least 100us */
00447       HAL_Delay(1);
00448     }
00449     /* Return AUDIO_OK when all operations are correctly done */
00450     return AUDIO_OK;
00451   }
00452 }
00453 
00454 /**
00455   * @brief  Controls the current audio volume level. 
00456   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for 
00457   *         Mute and 100 for Max volume level).
00458   * @retval AUDIO_OK if correct communication, else wrong communication
00459   */
00460 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume)
00461 {
00462   /* Call the codec volume control function with converted volume value */
00463   if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
00464   {
00465     return AUDIO_ERROR;
00466   }
00467   else
00468   {
00469     /* Return AUDIO_OK when all operations are correctly done */
00470     return AUDIO_OK;
00471   }
00472 }
00473 
00474 /**
00475   * @brief  Enables or disables the MUTE mode by software 
00476   * @param  Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 
00477   *         unmute the codec and restore previous volume level.
00478   * @retval AUDIO_OK if correct communication, else wrong communication
00479   */
00480 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd)
00481 { 
00482   /* Call the Codec Mute function */
00483   if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0)
00484   {
00485     return AUDIO_ERROR;
00486   }
00487   else
00488   {
00489     /* Return AUDIO_OK when all operations are correctly done */
00490     return AUDIO_OK;
00491   }
00492 }
00493 
00494 /**
00495   * @brief  Switch dynamically (while audio file is played) the output target 
00496   *         (speaker or headphone).
00497   * @param  Output: The audio output target: OUTPUT_DEVICE_SPEAKER,
00498   *         OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH
00499   * @retval AUDIO_OK if correct communication, else wrong communication
00500   */
00501 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)
00502 {
00503   /* Call the Codec output device function */
00504   if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0)
00505   {
00506     return AUDIO_ERROR;
00507   }
00508   else
00509   {
00510     /* Return AUDIO_OK when all operations are correctly done */
00511     return AUDIO_OK;
00512   }
00513 }
00514 
00515 /**
00516   * @brief  Updates the audio frequency.
00517   * @param  AudioFreq: Audio frequency used to play the audio stream.
00518   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00519   *         audio frequency.
00520   * @retval None
00521   */
00522 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)
00523 { 
00524   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
00525   BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
00526 
00527   /* Disable SAI peripheral to allow access to SAI internal registers */
00528   __HAL_SAI_DISABLE(&haudio_out_sai);
00529   
00530   /* Update the SAI audio frequency configuration */
00531   haudio_out_sai.Init.AudioFrequency = AudioFreq;
00532   HAL_SAI_Init(&haudio_out_sai);
00533   
00534   /* Enable SAI peripheral to generate MCLK */
00535   __HAL_SAI_ENABLE(&haudio_out_sai);
00536 }
00537 
00538 /**
00539   * @brief  Updates the Audio frame slot configuration.
00540   * @param  AudioFrameSlot: specifies the audio Frame slot
00541   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00542   *         audio frame slot.
00543   * @retval None
00544   */
00545 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot)
00546 { 
00547   /* Disable SAI peripheral to allow access to SAI internal registers */
00548   __HAL_SAI_DISABLE(&haudio_out_sai);
00549   
00550   /* Update the SAI audio frame slot configuration */
00551   haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot;
00552   HAL_SAI_Init(&haudio_out_sai);
00553   
00554   /* Enable SAI peripheral to generate MCLK */
00555   __HAL_SAI_ENABLE(&haudio_out_sai);
00556 }
00557                         
00558 /**
00559   * @brief  De-initializes the audio out peripheral.
00560   * @retval None
00561   */
00562 void BSP_AUDIO_OUT_DeInit(void)
00563 {
00564   SAIx_Out_DeInit();
00565   /* DeInit the SAI MSP : this __weak function can be rewritten by the application */
00566   BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL);
00567 }
00568 
00569 /**
00570   * @brief  Tx Transfer completed callbacks.
00571   * @param  hsai: SAI handle
00572   * @retval None
00573   */
00574 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
00575 {
00576   /* Manage the remaining file size and new address offset: This function 
00577      should be coded by user (its prototype is already declared in stm32f769i_discovery_audio.h) */
00578   BSP_AUDIO_OUT_TransferComplete_CallBack();
00579 }
00580 
00581 /**
00582   * @brief  Tx Half Transfer completed callbacks.
00583   * @param  hsai: SAI handle
00584   * @retval None
00585   */
00586 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
00587 {
00588   /* Manage the remaining file size and new address offset: This function 
00589      should be coded by user (its prototype is already declared in stm32f769i_discovery_audio.h) */
00590   BSP_AUDIO_OUT_HalfTransfer_CallBack();
00591 }
00592 
00593 /**
00594   * @brief  SAI error callbacks.
00595   * @param  hsai: SAI handle
00596   * @retval None
00597   */
00598 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
00599 {
00600   if(hsai->Instance == AUDIO_OUT_SAIx)
00601   {
00602   BSP_AUDIO_OUT_Error_CallBack();
00603   }
00604   else
00605   {
00606     BSP_AUDIO_IN_Error_CallBack();
00607   }
00608 }
00609 
00610 /**
00611   * @brief  Manages the DMA full Transfer complete event.
00612   * @retval None
00613   */
00614 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
00615 {
00616 }
00617 
00618 /**
00619   * @brief  Manages the DMA Half Transfer complete event.
00620   * @retval None
00621   */
00622 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void)
00623 { 
00624 }
00625 
00626 /**
00627   * @brief  Manages the DMA FIFO error event.
00628   * @retval None
00629   */
00630 __weak void BSP_AUDIO_OUT_Error_CallBack(void)
00631 {
00632 }
00633 
00634 /**
00635   * @brief  Initializes BSP_AUDIO_OUT MSP.
00636   * @param  hsai: SAI handle
00637   * @param  Params  
00638   * @retval None
00639   */
00640 __weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params)
00641 { 
00642   static DMA_HandleTypeDef hdma_sai_tx;
00643   GPIO_InitTypeDef  gpio_init_structure;  
00644   
00645   /* Enable SAI clock */
00646   AUDIO_OUT_SAIx_CLK_ENABLE();
00647   
00648   
00649   /* Enable GPIO clock */
00650   AUDIO_OUT_SAIx_MCLK_ENABLE();
00651   AUDIO_OUT_SAIx_SD_FS_CLK_ENABLE();
00652   
00653   /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/
00654   gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SD_PIN;
00655   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
00656   gpio_init_structure.Pull = GPIO_NOPULL;
00657   gpio_init_structure.Speed = GPIO_SPEED_HIGH;
00658   gpio_init_structure.Alternate = AUDIO_OUT_SAIx_AF;
00659   HAL_GPIO_Init(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, &gpio_init_structure);
00660   
00661   gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN;
00662   HAL_GPIO_Init(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, &gpio_init_structure);
00663   
00664   /* Enable the DMA clock */
00665   AUDIO_OUT_SAIx_DMAx_CLK_ENABLE();
00666   
00667   if(hsai->Instance == AUDIO_OUT_SAIx)
00668   {
00669     /* Configure the hdma_saiTx handle parameters */   
00670     hdma_sai_tx.Init.Channel             = AUDIO_OUT_SAIx_DMAx_CHANNEL;
00671     hdma_sai_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
00672     hdma_sai_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
00673     hdma_sai_tx.Init.MemInc              = DMA_MINC_ENABLE;
00674     hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_OUT_SAIx_DMAx_PERIPH_DATA_SIZE;
00675     hdma_sai_tx.Init.MemDataAlignment    = AUDIO_OUT_SAIx_DMAx_MEM_DATA_SIZE;
00676     hdma_sai_tx.Init.Mode                = DMA_CIRCULAR;
00677     hdma_sai_tx.Init.Priority            = DMA_PRIORITY_HIGH;
00678     hdma_sai_tx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;         
00679     hdma_sai_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
00680     hdma_sai_tx.Init.MemBurst            = DMA_MBURST_SINGLE;
00681     hdma_sai_tx.Init.PeriphBurst         = DMA_PBURST_SINGLE; 
00682     
00683     hdma_sai_tx.Instance = AUDIO_OUT_SAIx_DMAx_STREAM;
00684     
00685     /* Associate the DMA handle */
00686     __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx);
00687     
00688     /* Deinitialize the Stream for new transfer */
00689     HAL_DMA_DeInit(&hdma_sai_tx);
00690     
00691     /* Configure the DMA Stream */
00692     HAL_DMA_Init(&hdma_sai_tx);
00693   }
00694   
00695   /* SAI DMA IRQ Channel configuration */
00696   HAL_NVIC_SetPriority(AUDIO_OUT_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
00697   HAL_NVIC_EnableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ);
00698 }
00699 
00700 /**
00701   * @brief  Initializes SAI Audio IN MSP.
00702   * @param  hsai: SAI handle
00703   * @param  Params  
00704   * @retval None
00705   */
00706 static void SAI_AUDIO_IN_MspInit(SAI_HandleTypeDef *hsai, void *Params)
00707 {
00708   static DMA_HandleTypeDef hdma_sai_rx;
00709   GPIO_InitTypeDef  gpio_init_structure;  
00710 
00711   /* Enable SAI clock */
00712   AUDIO_IN_SAIx_CLK_ENABLE();
00713   
00714   /* Enable SD GPIO clock */
00715   AUDIO_IN_SAIx_SD_ENABLE();
00716   /* CODEC_SAI pin configuration: SD pin */
00717   gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN;
00718   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
00719   gpio_init_structure.Pull = GPIO_NOPULL;
00720   gpio_init_structure.Speed = GPIO_SPEED_FAST;
00721   gpio_init_structure.Alternate = AUDIO_IN_SAIx_AF;
00722   HAL_GPIO_Init(AUDIO_IN_SAIx_SD_GPIO_PORT, &gpio_init_structure);
00723 
00724   /* Enable Audio INT GPIO clock */
00725   AUDIO_IN_INT_GPIO_ENABLE();
00726   /* Audio INT pin configuration: input */
00727   gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN;
00728   gpio_init_structure.Mode = GPIO_MODE_INPUT;
00729   gpio_init_structure.Pull = GPIO_NOPULL;
00730   gpio_init_structure.Speed = GPIO_SPEED_FAST;
00731   HAL_GPIO_Init(AUDIO_IN_INT_GPIO_PORT, &gpio_init_structure);
00732 
00733   /* Enable the DMA clock */
00734   AUDIO_IN_SAIx_DMAx_CLK_ENABLE();
00735     
00736   if(hsai->Instance == AUDIO_IN_SAIx)
00737   {
00738     /* Configure the hdma_sai_rx handle parameters */
00739     hdma_sai_rx.Init.Channel             = AUDIO_IN_SAIx_DMAx_CHANNEL;
00740     hdma_sai_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
00741     hdma_sai_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
00742     hdma_sai_rx.Init.MemInc              = DMA_MINC_ENABLE;
00743     hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAIx_DMAx_PERIPH_DATA_SIZE;
00744     hdma_sai_rx.Init.MemDataAlignment    = AUDIO_IN_SAIx_DMAx_MEM_DATA_SIZE;
00745     hdma_sai_rx.Init.Mode                = DMA_CIRCULAR;
00746     hdma_sai_rx.Init.Priority            = DMA_PRIORITY_HIGH;
00747     hdma_sai_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
00748     hdma_sai_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
00749     hdma_sai_rx.Init.MemBurst            = DMA_MBURST_SINGLE;
00750     hdma_sai_rx.Init.PeriphBurst         = DMA_MBURST_SINGLE;
00751     
00752     hdma_sai_rx.Instance = AUDIO_IN_SAIx_DMAx_STREAM;
00753     
00754     /* Associate the DMA handle */
00755     __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx);
00756     
00757     /* Deinitialize the Stream for new transfer */
00758     HAL_DMA_DeInit(&hdma_sai_rx);
00759     
00760     /* Configure the DMA Stream */
00761     HAL_DMA_Init(&hdma_sai_rx);
00762   }
00763   
00764   /* SAI DMA IRQ Channel configuration */
00765   HAL_NVIC_SetPriority(AUDIO_IN_SAIx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
00766   HAL_NVIC_EnableIRQ(AUDIO_IN_SAIx_DMAx_IRQ);
00767 
00768   /* Audio INT IRQ Channel configuration */
00769   HAL_NVIC_SetPriority(AUDIO_IN_INT_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
00770   HAL_NVIC_EnableIRQ(AUDIO_IN_INT_IRQ);
00771 }
00772 
00773 /**
00774   * @brief  De-Initializes SAI Audio IN MSP.
00775   * @param  hsai: SAI handle
00776   * @param  Params  
00777   * @retval None
00778   */
00779 static void SAI_AUDIO_IN_MspDeInit(SAI_HandleTypeDef *hsai, void *Params)
00780 {
00781   GPIO_InitTypeDef  gpio_init_structure;
00782   
00783   /* SAI DMA IRQ Channel deactivation */
00784   HAL_NVIC_DisableIRQ(AUDIO_IN_SAIx_DMAx_IRQ);
00785   
00786   if(hsai->Instance == AUDIO_IN_SAIx)
00787   {
00788     /* Deinitialize the DMA stream */
00789     HAL_DMA_DeInit(hsai->hdmatx);
00790   }
00791   
00792   /* Disable SAI peripheral */
00793   __HAL_SAI_DISABLE(hsai);  
00794   
00795   /* Deactivates CODEC_SAI pin SD by putting them in input mode */
00796   gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN;
00797   HAL_GPIO_DeInit(AUDIO_IN_SAIx_SD_GPIO_PORT, gpio_init_structure.Pin);
00798   
00799   gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN;
00800   HAL_GPIO_DeInit(AUDIO_IN_INT_GPIO_PORT, gpio_init_structure.Pin);
00801   
00802   /* Disable SAI clock */
00803   AUDIO_IN_SAIx_CLK_DISABLE();  
00804 }
00805 
00806 /**
00807   * @brief  Deinitializes SAI MSP.
00808   * @param  hsai: SAI handle
00809   * @param  Params  
00810   * @retval None
00811   */
00812 __weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params)
00813 {
00814     GPIO_InitTypeDef  gpio_init_structure;
00815 
00816     /* SAI DMA IRQ Channel deactivation */
00817     HAL_NVIC_DisableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ);
00818 
00819     if(hsai->Instance == AUDIO_OUT_SAIx)
00820     {
00821       /* Deinitialize the DMA stream */
00822       HAL_DMA_DeInit(hsai->hdmatx);
00823     }
00824 
00825     /* Disable SAI peripheral */
00826     __HAL_SAI_DISABLE(hsai);  
00827 
00828     /* Deactivates CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */
00829     gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SD_PIN;
00830     HAL_GPIO_DeInit(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, gpio_init_structure.Pin);
00831 
00832     gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN;
00833     HAL_GPIO_DeInit(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin);
00834   
00835     /* Disable SAI clock */
00836     AUDIO_OUT_SAIx_CLK_DISABLE();
00837 
00838     /* GPIO pins clock and DMA clock can be shut down in the applic 
00839        by surcharging this __weak function */ 
00840 }
00841 
00842 /**
00843   * @brief  Clock Config.
00844   * @param  hsai: might be required to set audio peripheral predivider if any.
00845   * @param  AudioFreq: Audio frequency used to play the audio stream.
00846   * @param  Params  
00847   * @note   This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency()
00848   *         Being __weak it can be overwritten by the application     
00849   * @retval None
00850   */
00851 __weak void BSP_AUDIO_OUT_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params)
00852 { 
00853   RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct;
00854 
00855   HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct);
00856   
00857   /* Set the PLL configuration according to the audio frequency */
00858   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
00859   {
00860     /* Configure PLLSAI prescalers */
00861     /* PLLSAI_VCO: VCO_429M 
00862     SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 429/2 = 214.5 Mhz
00863     SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 214.5/19 = 11.289 Mhz */ 
00864     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
00865     rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLI2S;
00866     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429;
00867     rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2;
00868     rcc_ex_clk_init_struct.PLLI2SDivQ = 19;
00869     
00870     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
00871     
00872   }
00873   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
00874   {
00875     /* SAI clock config 
00876     PLLSAI_VCO: VCO_344M 
00877     SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 344/7 = 49.142 Mhz 
00878     SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 49.142/1 = 49.142 Mhz */  
00879     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
00880     rcc_ex_clk_init_struct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLI2S;
00881     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 
00882     rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 
00883     rcc_ex_clk_init_struct.PLLI2SDivQ = 1;      
00884     
00885     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
00886   }
00887 }
00888 
00889 /*******************************************************************************
00890                             Static Functions
00891 *******************************************************************************/
00892 
00893 /**
00894   * @brief  Initializes the Audio Codec audio interface (SAI).
00895   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00896   * @note   The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 
00897   *         and user can update this configuration using 
00898   * @retval None
00899   */
00900 static void SAIx_Out_Init(uint32_t AudioFreq)
00901 {
00902   /* Initialize the haudio_out_sai Instance parameter */
00903   haudio_out_sai.Instance = AUDIO_OUT_SAIx;
00904   
00905   /* Disable SAI peripheral to allow access to SAI internal registers */
00906   __HAL_SAI_DISABLE(&haudio_out_sai);
00907   
00908   /* Configure SAI_Block_x 
00909   LSBFirst: Disabled 
00910   DataSize: 16 */
00911   haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE;
00912   haudio_out_sai.Init.AudioFrequency = AudioFreq;
00913   haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX;
00914   haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED;
00915   haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL;
00916   haudio_out_sai.Init.DataSize = SAI_DATASIZE_16;
00917   haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
00918   haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
00919   haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS;
00920   haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLED;
00921   haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
00922   haudio_out_sai.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
00923   haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING;
00924   haudio_out_sai.Init.TriState       = SAI_OUTPUT_NOTRELEASED;
00925   haudio_out_sai.Init.Mckdiv         = 0;
00926     
00927   /* Configure SAI_Block_x Frame 
00928   Frame Length: 64
00929   Frame active Length: 32
00930   FS Definition: Start frame + Channel Side identification
00931   FS Polarity: FS active Low
00932   FS Offset: FS asserted one bit before the first bit of slot 0 */ 
00933   haudio_out_sai.FrameInit.FrameLength = 128; 
00934   haudio_out_sai.FrameInit.ActiveFrameLength = 64;
00935   haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
00936   haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
00937   haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
00938   
00939   /* Configure SAI Block_x Slot 
00940   Slot First Bit Offset: 0
00941   Slot Size  : 16
00942   Slot Number: 4
00943   Slot Active: All slot actives */
00944   haudio_out_sai.SlotInit.FirstBitOffset = 0;
00945   haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
00946   haudio_out_sai.SlotInit.SlotNumber = 4; 
00947   haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123;
00948 
00949   HAL_SAI_Init(&haudio_out_sai);
00950   
00951   /* Enable SAI peripheral to generate MCLK */
00952   __HAL_SAI_ENABLE(&haudio_out_sai);
00953 }
00954 
00955 /**
00956   * @brief  Deinitializes the Audio Codec audio interface (SAI).
00957   * @retval None
00958   */
00959 static void SAIx_Out_DeInit(void)
00960 {
00961   /* Initialize the haudio_out_sai Instance parameter */
00962   haudio_out_sai.Instance = AUDIO_OUT_SAIx;
00963 
00964   /* Disable SAI peripheral */
00965   __HAL_SAI_DISABLE(&haudio_out_sai);
00966 
00967   HAL_SAI_DeInit(&haudio_out_sai);
00968 }
00969 
00970 /**
00971   * @brief  Initializes the Audio Codec audio interface (SAI).
00972   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00973   * @note   The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 
00974   *         and user can update this configuration using 
00975   * @retval None
00976   */
00977 static void SAIx_In_Init(uint32_t AudioFreq)
00978 {
00979   /* Initialize SAI1 block A in MASTER TX */
00980   /* Initialize the haudio_out_sai Instance parameter */
00981   haudio_out_sai.Instance = AUDIO_OUT_SAIx;
00982 
00983   /* Disable SAI peripheral to allow access to SAI internal registers */
00984   __HAL_SAI_DISABLE(&haudio_out_sai);
00985 
00986   /* Configure SAI_Block_x
00987   LSBFirst: Disabled
00988   DataSize: 16 */
00989   haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE;
00990   haudio_out_sai.Init.AudioFrequency = AudioFreq;
00991   haudio_out_sai.Init.AudioMode      = SAI_MODEMASTER_RX;
00992   haudio_out_sai.Init.NoDivider      = SAI_MASTERDIVIDER_ENABLE;
00993   haudio_out_sai.Init.Protocol       = SAI_FREE_PROTOCOL;
00994   haudio_out_sai.Init.DataSize       = SAI_DATASIZE_16;
00995   haudio_out_sai.Init.FirstBit       = SAI_FIRSTBIT_MSB;
00996   haudio_out_sai.Init.ClockStrobing  = SAI_CLOCKSTROBING_FALLINGEDGE;
00997   haudio_out_sai.Init.Synchro        = SAI_ASYNCHRONOUS;
00998   haudio_out_sai.Init.OutputDrive    = SAI_OUTPUTDRIVE_ENABLE;
00999   haudio_out_sai.Init.FIFOThreshold  = SAI_FIFOTHRESHOLD_1QF;
01000   haudio_out_sai.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
01001   haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING;
01002   haudio_out_sai.Init.TriState       = SAI_OUTPUT_NOTRELEASED;
01003   haudio_out_sai.Init.Mckdiv         = 0;  
01004 
01005   /* Configure SAI_Block_x Frame
01006   Frame Length: 64
01007   Frame active Length: 32
01008   FS Definition: Start frame + Channel Side identification
01009   FS Polarity: FS active Low
01010   FS Offset: FS asserted one bit before the first bit of slot 0 */
01011   haudio_out_sai.FrameInit.FrameLength       = 64;
01012   haudio_out_sai.FrameInit.ActiveFrameLength = 32;
01013   haudio_out_sai.FrameInit.FSDefinition      = SAI_FS_CHANNEL_IDENTIFICATION;
01014   haudio_out_sai.FrameInit.FSPolarity        = SAI_FS_ACTIVE_LOW;
01015   haudio_out_sai.FrameInit.FSOffset          = SAI_FS_BEFOREFIRSTBIT;
01016 
01017   /* Configure SAI Block_x Slot
01018   Slot First Bit Offset: 0
01019   Slot Size  : 16
01020   Slot Number: 4
01021   Slot Active: All slot actives */
01022   haudio_out_sai.SlotInit.FirstBitOffset = 0;
01023   haudio_out_sai.SlotInit.SlotSize       = SAI_SLOTSIZE_DATASIZE;
01024   haudio_out_sai.SlotInit.SlotNumber     = 4;
01025   haudio_out_sai.SlotInit.SlotActive     = CODEC_AUDIOFRAME_SLOT_02;
01026 
01027   HAL_SAI_Init(&haudio_out_sai);
01028 
01029   /* Initialize SAI1 block B in SLAVE RX synchronous from SAI1 block A */
01030   /* Initialize the haudio_in_sai Instance parameter */
01031   haudio_in_sai.Instance = AUDIO_IN_SAIx;
01032   
01033   /* Disable SAI peripheral to allow access to SAI internal registers */
01034   __HAL_SAI_DISABLE(&haudio_in_sai);
01035   
01036   /* Configure SAI_Block_x
01037   LSBFirst: Disabled
01038   DataSize: 16 */
01039   haudio_in_sai.Init.MonoStereoMode = SAI_STEREOMODE;
01040   haudio_in_sai.Init.AudioFrequency = AudioFreq;
01041   haudio_in_sai.Init.AudioMode      = SAI_MODESLAVE_RX;
01042   haudio_in_sai.Init.NoDivider      = SAI_MASTERDIVIDER_ENABLE;
01043   haudio_in_sai.Init.Protocol       = SAI_FREE_PROTOCOL;
01044   haudio_in_sai.Init.DataSize       = SAI_DATASIZE_16;
01045   haudio_in_sai.Init.FirstBit       = SAI_FIRSTBIT_MSB;
01046   haudio_in_sai.Init.ClockStrobing  = SAI_CLOCKSTROBING_RISINGEDGE;
01047   haudio_in_sai.Init.Synchro        = SAI_SYNCHRONOUS;
01048   haudio_in_sai.Init.OutputDrive    = SAI_OUTPUTDRIVE_DISABLE;
01049   haudio_in_sai.Init.FIFOThreshold  = SAI_FIFOTHRESHOLD_1QF;
01050   haudio_in_sai.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
01051   haudio_in_sai.Init.CompandingMode = SAI_NOCOMPANDING;
01052   haudio_in_sai.Init.TriState       = SAI_OUTPUT_RELEASED;
01053   haudio_in_sai.Init.Mckdiv         = 0;
01054 
01055   /* Configure SAI_Block_x Frame
01056   Frame Length: 64
01057   Frame active Length: 32
01058   FS Definition: Start frame + Channel Side identification
01059   FS Polarity: FS active Low
01060   FS Offset: FS asserted one bit before the first bit of slot 0 */
01061   haudio_in_sai.FrameInit.FrameLength       = 64;
01062   haudio_in_sai.FrameInit.ActiveFrameLength = 32;
01063   haudio_in_sai.FrameInit.FSDefinition      = SAI_FS_CHANNEL_IDENTIFICATION;
01064   haudio_in_sai.FrameInit.FSPolarity        = SAI_FS_ACTIVE_LOW;
01065   haudio_in_sai.FrameInit.FSOffset          = SAI_FS_BEFOREFIRSTBIT;
01066   
01067   /* Configure SAI Block_x Slot
01068   Slot First Bit Offset: 0
01069   Slot Size  : 16
01070   Slot Number: 4
01071   Slot Active: All slot active */
01072   haudio_in_sai.SlotInit.FirstBitOffset = 0;
01073   haudio_in_sai.SlotInit.SlotSize       = SAI_SLOTSIZE_DATASIZE;
01074   haudio_in_sai.SlotInit.SlotNumber     = 4;
01075   haudio_in_sai.SlotInit.SlotActive     = CODEC_AUDIOFRAME_SLOT_02;
01076 
01077   HAL_SAI_Init(&haudio_in_sai);
01078 
01079   /* Enable SAI peripheral */
01080   __HAL_SAI_ENABLE(&haudio_in_sai);
01081 
01082   /* Enable SAI peripheral to generate MCLK */
01083   __HAL_SAI_ENABLE(&haudio_out_sai);
01084 }
01085 
01086 /**
01087   * @brief  Deinitializes the output Audio Codec audio interface (SAI).
01088   * @retval None
01089   */
01090 static void SAIx_In_DeInit(void)
01091 {
01092   /* Initialize the haudio_in_sai Instance parameter */
01093   haudio_in_sai.Instance = AUDIO_IN_SAIx;
01094   haudio_out_sai.Instance = AUDIO_OUT_SAIx;
01095   /* Disable SAI peripheral */
01096   __HAL_SAI_DISABLE(&haudio_in_sai);
01097 
01098   HAL_SAI_DeInit(&haudio_in_sai);
01099   HAL_SAI_DeInit(&haudio_out_sai);
01100 }
01101 
01102 /**
01103   * @}
01104   */
01105 
01106 /** @defgroup STM32F769I_DISCOVERY_AUDIO_In_Private_Functions STM32F769I_DISCOVERY_AUDIO_In Private Functions
01107   * @{
01108   */
01109 
01110 /**
01111   * @brief  Initialize wave recording. 
01112   * @param  AudioFreq: Audio frequency to be configured for the DFSDM peripheral. 
01113   * @param  BitRes: Audio frequency to be configured for the DFSDM peripheral.
01114   * @param  ChnlNbr: Audio frequency to be configured for the DFSDM peripheral.
01115   * @retval AUDIO_OK if correct communication, else wrong communication
01116   */
01117 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
01118 { 
01119   return BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC, AudioFreq, BitRes, ChnlNbr);
01120 }
01121 
01122 /**
01123   * @brief  Initialize wave recording.
01124   * @param  InputDevice: INPUT_DEVICE_DIGITAL_MIC or INPUT_DEVICE_ANALOG_MIC. 
01125   * @param  AudioFreq: Audio frequency to be configured. 
01126   * @param  BitRes: Audio bit resolution to be configured..
01127   * @param  ChnlNbr: Number of channel to be configured.
01128   * @retval AUDIO_OK if correct communication, else wrong communication
01129   */
01130 uint8_t BSP_AUDIO_IN_InitEx(uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
01131 { 
01132   uint8_t ret = AUDIO_ERROR;
01133   AudioIn_Device = InputDevice;
01134   
01135   if(InputDevice == INPUT_DEVICE_DIGITAL_MIC)
01136   {
01137     AudioIn_ChannelNumber = ChnlNbr;
01138     /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
01139     BSP_AUDIO_IN_ClockConfig(&hAudioInTopLeftFilter, AudioFreq, NULL);
01140     
01141     /* Init the SAI MSP: this __weak function can be redefined by the application*/
01142     BSP_AUDIO_IN_MspInit();
01143     
01144     /* Initializes DFSDM peripheral */
01145     DFSDMx_Init(AudioFreq);
01146     ret = AUDIO_OK;
01147   }
01148   else
01149   {
01150     /* Disable SAI */
01151     SAIx_In_DeInit();
01152     
01153     /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
01154     BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL);
01155     
01156     haudio_in_sai.Instance = AUDIO_IN_SAIx;
01157     if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET)
01158     {    
01159     BSP_AUDIO_OUT_MspInit(&haudio_in_sai, NULL);
01160     BSP_AUDIO_IN_MspInit();
01161     }
01162 
01163     SAIx_In_Init(AudioFreq);
01164     
01165     if((wm8994_drv.ReadID(AUDIO_I2C_ADDRESS)) == WM8994_ID)
01166     {
01167       /* Reset the Codec Registers */
01168       wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
01169       /* Initialize the audio driver structure */
01170       audio_drv = &wm8994_drv;
01171       ret = AUDIO_OK;
01172     }
01173     else
01174     {
01175       ret = AUDIO_ERROR;
01176     }
01177     
01178     if(ret == AUDIO_OK)
01179     {
01180       /* Initialize the codec internal registers */
01181       audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice, 100, AudioFreq);
01182     }    
01183   }
01184   
01185   /* Return AUDIO_OK when all operations are correctly done */
01186   return ret;
01187 }
01188 
01189 /**
01190   * @brief  Allocate channel buffer scratch 
01191   * @param  pScratch : pointer to scratch tables.
01192   * @param  size of scratch buffer
01193   */
01194 uint8_t BSP_AUDIO_IN_AllocScratch (int32_t *pScratch, uint32_t size)
01195 { 
01196   uint32_t idx;
01197   
01198   ScratchSize = (size / AudioIn_ChannelNumber);
01199   
01200   /* copy scratch pointers */
01201   for (idx = 0; idx < AudioIn_ChannelNumber; idx++)
01202   {
01203     pScratchBuff[idx] = (int32_t *)(pScratch + (idx * ScratchSize));
01204   }
01205   /* Return AUDIO_OK */
01206   return AUDIO_OK;
01207 }
01208 
01209 /**
01210   * @brief  Return audio in channel number 
01211   * @retval Number of channel
01212   */
01213 uint8_t BSP_AUDIO_IN_GetChannelNumber(void)
01214 {
01215   return AudioIn_ChannelNumber;
01216 }
01217 
01218 /**
01219   * @brief  Start audio recording.
01220   * @param  pbuf: Main buffer pointer for the recorded data storing  
01221   * @param  size: Current size of the recorded buffer
01222   * @retval AUDIO_OK if correct communication, else wrong communication
01223   */
01224 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size)
01225 {  
01226   if (AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC)
01227   {
01228     hAudioIn.pRecBuf = pbuf;
01229     hAudioIn.RecSize = size;
01230     /* Reset Application Buffer Trigger */
01231     AppBuffTrigger = 0;
01232     AppBuffHalf = 0;
01233     
01234     if(AudioIn_ChannelNumber > 2)
01235     {
01236       /* Call the Media layer start function for buttom right channel */
01237       if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInButtomRightFilter, pScratchBuff[2], ScratchSize))
01238       {
01239         return AUDIO_ERROR;
01240       } 
01241       
01242       /* Call the Media layer start function for buttom left channel */
01243       if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInButtomLeftFilter, pScratchBuff[3], ScratchSize))
01244       {
01245         return AUDIO_ERROR;
01246       }
01247     }
01248 
01249     /* Call the Media layer start function for top right channel */
01250     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInTopRightFilter, pScratchBuff[0], ScratchSize))
01251     {
01252       return AUDIO_ERROR;
01253     }
01254     
01255     /* Call the Media layer start function for top left channel */
01256     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInTopLeftFilter, pScratchBuff[1], ScratchSize))
01257     {
01258       return AUDIO_ERROR;
01259     }
01260   }
01261   else
01262   {
01263     /* Start the process receive DMA */
01264     if(HAL_OK !=HAL_SAI_Receive_DMA(&haudio_in_sai, (uint8_t*)pbuf, size))
01265     {
01266       return AUDIO_ERROR;
01267     }
01268   }
01269   /* Return AUDIO_OK when all operations are correctly done */
01270   return AUDIO_OK;  
01271 }
01272 
01273 /**
01274   * @brief  Stop audio recording.
01275   * @retval AUDIO_OK if correct communication, else wrong communication
01276   */
01277 uint8_t BSP_AUDIO_IN_Stop(void)
01278 {
01279   if (AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC)
01280   { 
01281     AppBuffTrigger = 0;
01282     AppBuffHalf    = 0;
01283     
01284     if(AudioIn_ChannelNumber > 2)
01285     {    
01286       /* Call the Media layer stop function for buttom right channel */
01287       if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInButtomRightFilter))
01288       {
01289         return AUDIO_ERROR;
01290       }
01291       
01292       /* Call the Media layer stop function for buttom left channel */
01293       if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInButtomLeftFilter))
01294       {
01295         return AUDIO_ERROR;
01296       }
01297     }
01298     
01299     /* Call the Media layer stop function for top right channel */
01300     if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInTopRightFilter))
01301     {
01302       return AUDIO_ERROR;
01303     }
01304     
01305     /* Call the Media layer stop function for top left channel */
01306     if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInTopLeftFilter))
01307     {
01308       return AUDIO_ERROR;
01309     }
01310   }
01311   else
01312   {
01313     /* Call the Media layer stop function */
01314     HAL_SAI_DMAStop(&haudio_in_sai);
01315     
01316     /* Call Audio Codec Stop function */
01317     if(audio_drv->Stop(AUDIO_I2C_ADDRESS, CODEC_PDWN_HW) != 0)
01318     {
01319       return AUDIO_ERROR;
01320     }
01321     else
01322     {
01323       /* Wait at least 100us */
01324       HAL_Delay(1);
01325       
01326       /* Return AUDIO_OK when all operations are correctly done */
01327       return AUDIO_OK;
01328     }  
01329   }
01330   /* Return AUDIO_OK when all operations are correctly done */
01331   return AUDIO_OK;
01332 }
01333 
01334 /**
01335   * @brief  Pause the audio file stream.
01336   * @retval AUDIO_OK if correct communication, else wrong communication
01337   */
01338 uint8_t BSP_AUDIO_IN_Pause(void)
01339 {
01340   if(AudioIn_ChannelNumber > 2)
01341   { 
01342     /* Call the Media layer stop function */
01343     if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInButtomRightFilter))
01344     {
01345       return AUDIO_ERROR;
01346     }
01347     
01348     /* Call the Media layer stop function */
01349     if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInButtomLeftFilter))
01350     {
01351       return AUDIO_ERROR;
01352     }
01353   }  
01354   /* Call the Media layer stop function */
01355   if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInTopRightFilter))
01356   {
01357     return AUDIO_ERROR;
01358   }
01359   
01360   /* Call the Media layer stop function */
01361   if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&hAudioInTopLeftFilter))
01362   {
01363     return AUDIO_ERROR;
01364   }
01365   
01366   /* Return AUDIO_OK when all operations are correctly done */
01367   return AUDIO_OK;
01368 }
01369 
01370 /**
01371   * @brief  Resume the audio file stream.
01372   * @retval AUDIO_OK if correct communication, else wrong communication
01373   */
01374 uint8_t BSP_AUDIO_IN_Resume(void)
01375 { 
01376   if(AudioIn_ChannelNumber > 2)
01377   {   
01378     /* Call the Media layer start function for buttom right channel */
01379     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInButtomRightFilter, pScratchBuff[2], ScratchSize))
01380     {
01381       return AUDIO_ERROR;
01382     }
01383     
01384     /* Call the Media layer start function for buttom left channel */
01385     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInButtomLeftFilter, pScratchBuff[3], ScratchSize))
01386     {
01387       return AUDIO_ERROR;
01388     }
01389   } 
01390   /* Call the Media layer start function for top right channel */
01391   if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInTopRightFilter, pScratchBuff[0], ScratchSize))
01392   {
01393     return AUDIO_ERROR;
01394   }
01395   
01396   /* Call the Media layer start function for top left channel */
01397   if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&hAudioInTopLeftFilter, pScratchBuff[1], ScratchSize))
01398   {
01399     return AUDIO_ERROR;
01400   }
01401   
01402   /* Return AUDIO_OK when all operations are correctly done */
01403   return AUDIO_OK;
01404 }
01405 
01406 /**
01407   * @brief  Deinit the audio IN peripherals.
01408   * @retval None
01409   */
01410 void BSP_AUDIO_IN_DeInit(void)
01411 {
01412   BSP_AUDIO_IN_MspDeInit();
01413   
01414   if(AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC)
01415   {
01416     DFSDMx_DeInit();
01417   }
01418   else
01419   {
01420     SAIx_In_DeInit();
01421   }
01422 }
01423 
01424 /**
01425   * @brief  Regular conversion complete callback. 
01426   * @note   In interrupt mode, user has to read conversion value in this function
01427             using HAL_DFSDM_FilterGetRegularValue.
01428   * @param  hdfsdm_filter : DFSDM filter handle.
01429   * @retval None
01430   */
01431 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01432 {
01433   uint32_t index = 0;
01434   
01435   if(hdfsdm_filter == &hAudioInTopLeftFilter)
01436   {
01437     DmaTopLeftRecCplt = 1;
01438   }
01439   else if(hdfsdm_filter == &hAudioInTopRightFilter)
01440   {
01441     DmaTopRightRecCplt = 1;
01442   }
01443   else if(hdfsdm_filter == &hAudioInButtomLeftFilter)
01444   {
01445     DmaButtomLeftRecCplt = 1;
01446   }
01447   else
01448   {
01449     DmaButtomRightRecCplt = 1;
01450   }
01451   
01452   if(AudioIn_ChannelNumber > 2)
01453   {
01454     if((DmaTopLeftRecCplt == 1) && (DmaTopRightRecCplt == 1) && (DmaButtomLeftRecCplt == 1) && (DmaButtomRightRecCplt == 1))
01455     {
01456       for(index = (ScratchSize/2) ; index < ScratchSize; index++)
01457       {
01458         hAudioIn.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760));
01459         hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760));       
01460         hAudioIn.pRecBuf[AppBuffTrigger + 2] = (uint16_t)(SaturaLH((pScratchBuff[3][index] >> 8), -32760, 32760));
01461         hAudioIn.pRecBuf[AppBuffTrigger + 3] = (uint16_t)(SaturaLH((pScratchBuff[2][index] >> 8), -32760, 32760));      
01462         AppBuffTrigger +=4;
01463       }
01464       DmaTopLeftRecCplt  = 0;
01465       DmaTopRightRecCplt = 0;
01466       DmaButtomLeftRecCplt  = 0;
01467       DmaButtomRightRecCplt = 0;     
01468     }
01469   }
01470   else
01471   {
01472     if((DmaTopLeftRecCplt == 1) && (DmaTopRightRecCplt == 1))
01473     {    
01474       for(index = (ScratchSize/2) ; index < ScratchSize; index++)
01475       {
01476         hAudioIn.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760));
01477         hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760));
01478         AppBuffTrigger +=2;
01479       }
01480       DmaTopLeftRecCplt  = 0;
01481       DmaTopRightRecCplt = 0;  
01482     }
01483   }
01484   
01485   /* Call Half Transfer Complete callback */
01486   if((AppBuffTrigger == hAudioIn.RecSize/2) && (AppBuffHalf == 0))
01487   {
01488     AppBuffHalf = 1;  
01489     BSP_AUDIO_IN_HalfTransfer_CallBack();
01490   }
01491   /* Call Transfer Complete callback */
01492   if(AppBuffTrigger == hAudioIn.RecSize)
01493   {
01494     /* Reset Application Buffer Trigger */
01495     AppBuffTrigger = 0;
01496     AppBuffHalf = 0; 
01497     /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01498     BSP_AUDIO_IN_TransferComplete_CallBack();
01499   }  
01500 }
01501 
01502 /**
01503   * @brief  Half regular conversion complete callback. 
01504   * @param  hdfsdm_filter : DFSDM filter handle.
01505   * @retval None
01506   */
01507 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01508 {
01509   uint32_t index = 0;
01510   
01511   if(hdfsdm_filter == &hAudioInTopLeftFilter)
01512   {
01513     DmaTopLeftRecHalfCplt = 1;
01514   }
01515   else if(hdfsdm_filter == &hAudioInTopRightFilter)
01516   {
01517     DmaTopRightRecHalfCplt = 1;
01518   }
01519   else if(hdfsdm_filter == &hAudioInButtomLeftFilter)
01520   {
01521     DmaButtomLeftRecHalfCplt = 1;
01522   }
01523   else
01524   {
01525     DmaButtomRightRecHalfCplt = 1;
01526   }
01527   
01528   if(AudioIn_ChannelNumber > 2)
01529   {
01530     if((DmaTopLeftRecHalfCplt == 1) && (DmaTopRightRecHalfCplt == 1) && (DmaButtomLeftRecHalfCplt == 1) && (DmaButtomRightRecHalfCplt == 1))
01531     {
01532       for(index = 0 ; index < ScratchSize/2; index++)
01533       {
01534         hAudioIn.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760));
01535         hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760)); 
01536         hAudioIn.pRecBuf[AppBuffTrigger + 2] = (uint16_t)(SaturaLH((pScratchBuff[3][index] >> 8), -32760, 32760));
01537         hAudioIn.pRecBuf[AppBuffTrigger + 3] = (uint16_t)(SaturaLH((pScratchBuff[2][index] >> 8), -32760, 32760));      
01538         AppBuffTrigger +=4;
01539       }
01540       DmaTopLeftRecHalfCplt  = 0;
01541       DmaTopRightRecHalfCplt = 0;
01542       DmaButtomLeftRecHalfCplt  = 0;
01543       DmaButtomRightRecHalfCplt = 0;     
01544     }
01545   }
01546   else
01547   {
01548     if((DmaTopLeftRecHalfCplt == 1) && (DmaTopRightRecHalfCplt == 1))
01549     {    
01550       for(index = 0 ; index < ScratchSize/2; index++)
01551       {
01552         hAudioIn.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760));
01553         hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760));
01554         AppBuffTrigger +=2;
01555       }
01556       DmaTopLeftRecHalfCplt  = 0;
01557       DmaTopRightRecHalfCplt = 0;  
01558     }
01559   }
01560   
01561   /* Call Half Transfer Complete callback */
01562   if((AppBuffTrigger == hAudioIn.RecSize/2) && (AppBuffHalf == 0))
01563   { 
01564     AppBuffHalf = 1;  
01565     BSP_AUDIO_IN_HalfTransfer_CallBack();
01566   }
01567   /* Call Transfer Complete callback */
01568   if(AppBuffTrigger == hAudioIn.RecSize)
01569   {
01570     /* Reset Application Buffer Trigger */
01571     AppBuffTrigger = 0;
01572     AppBuffHalf = 0;
01573     /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01574     BSP_AUDIO_IN_TransferComplete_CallBack();
01575   }  
01576 }
01577 
01578 /**
01579   * @brief  Half reception complete callback.
01580   * @param  hsai : SAI handle.
01581   * @retval None
01582   */
01583 void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
01584 {
01585   /* Manage the remaining file size and new address offset: This function 
01586      should be coded by user (its prototype is already declared in stm32769i_discovery_audio.h) */
01587   BSP_AUDIO_IN_HalfTransfer_CallBack();
01588 }
01589 
01590 /**
01591   * @brief  Reception complete callback.
01592   * @param  hsai : SAI handle.
01593   * @retval None
01594   */
01595 void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
01596 {
01597   /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01598   BSP_AUDIO_IN_TransferComplete_CallBack();
01599 }
01600 
01601 /**
01602   * @brief  User callback when record buffer is filled.
01603   * @retval None
01604   */
01605 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void)
01606 {
01607   /* This function should be implemented by the user application.
01608      It is called into this driver when the current buffer is filled
01609      to prepare the next buffer pointer and its size. */
01610 }
01611 
01612 /**
01613   * @brief  Manages the DMA Half Transfer complete event.
01614   * @retval None
01615   */
01616 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
01617 { 
01618   /* This function should be implemented by the user application.
01619      It is called into this driver when the current buffer is filled
01620      to prepare the next buffer pointer and its size. */
01621 }
01622 
01623 /**
01624   * @brief  Audio IN Error callback function.
01625   * @retval None
01626   */
01627 __weak void BSP_AUDIO_IN_Error_CallBack(void)
01628 {   
01629   /* This function is called when an Interrupt due to transfer error on or peripheral
01630      error occurs. */
01631 }
01632 
01633 /**
01634   * @brief  Initialize BSP_AUDIO_IN MSP.
01635   * @retval None
01636   */
01637 __weak void BSP_AUDIO_IN_MspInit(void)
01638 { 
01639   if (AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC)
01640   {  
01641   /* MSP channels initialization */
01642   DFSDMx_ChannelMspInit();  
01643   /* MSP filters initialization */
01644   DFSDMx_FilterMspInit();
01645   }
01646   else
01647   {
01648    SAI_AUDIO_IN_MspInit(&haudio_in_sai, NULL); 
01649   }
01650 }
01651 
01652 /**
01653   * @brief  DeInitialize BSP_AUDIO_IN MSP.
01654   * @retval None
01655   */
01656 __weak void BSP_AUDIO_IN_MspDeInit(void)
01657 {
01658   if (AudioIn_Device == INPUT_DEVICE_DIGITAL_MIC)
01659   {  
01660     /* MSP channels initialization */
01661     DFSDMx_ChannelMspDeInit();  
01662     /* MSP filters initialization */
01663     DFSDMx_FilterMspDeInit();
01664   }
01665   else
01666   {
01667     SAI_AUDIO_IN_MspDeInit(&haudio_in_sai, NULL); 
01668   }
01669 }
01670 
01671 /**
01672   * @brief  Clock Config.
01673   * @param  hdfsdm_filter: might be required to set audio peripheral predivider if any.
01674   * @param  AudioFreq: Audio frequency used to play the audio stream.
01675   * @param  Params  
01676   * @note   This API is called by BSP_AUDIO_IN_Init()
01677   *         Being __weak it can be overwritten by the application     
01678   * @retval None
01679   */
01680 __weak void BSP_AUDIO_IN_ClockConfig(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, uint32_t AudioFreq, void *Params)
01681 { 
01682   RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct;
01683 
01684   HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct);
01685   
01686   /* Set the PLL configuration according to the audio frequency */
01687   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
01688   {
01689     /* Configure PLLSAI prescalers */
01690     /* PLLI2S_VCO: VCO_429M 
01691     SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 429/2 = 214.5 Mhz
01692     SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 214.5/19 = 11.289 Mhz */ 
01693     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2;
01694     rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S;
01695     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429;
01696     rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2;
01697     rcc_ex_clk_init_struct.PLLI2SDivQ = 19;
01698     
01699     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
01700     
01701   }
01702   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_32K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
01703   {
01704     /* SAI clock config 
01705     PLLI2S_VCO: VCO_344M 
01706     SAI_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 344/7 = 49.142 Mhz 
01707     SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ = 49.142/1 = 49.142 Mhz */  
01708     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2;
01709     rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S;
01710     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 
01711     rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 
01712     rcc_ex_clk_init_struct.PLLI2SDivQ = 1;   
01713     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
01714   }
01715   
01716   rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_DFSDM1_AUDIO;
01717   rcc_ex_clk_init_struct.Dfsdm1AudioClockSelection = RCC_DFSDM1AUDIOCLKSOURCE_SAI2;
01718   HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct); 
01719 }
01720 
01721 /*******************************************************************************
01722                             Static Functions
01723 *******************************************************************************/
01724 /**
01725   * @brief  Initialize the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01726   * @param  AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral.
01727   * @note   Channel output Clock Divider and Filter Oversampling are calculated as follow: 
01728   *         - Clock_Divider = CLK(input DFSDM)/CLK(micro) with
01729   *           1MHZ < CLK(micro) < 3.2MHZ (TYP 2.4MHZ for MP34DT01TR)
01730   *         - Oversampling = CLK(input DFSDM)/(Clock_Divider * AudioFreq)  
01731   * @retval AUDIO_OK if correct communication, else wrong communication
01732   */
01733 static uint8_t DFSDMx_Init(uint32_t AudioFreq)
01734 {
01735   /****************************************************************************/ 
01736   /********************** Channels configuration  *****************************/
01737   /****************************************************************************/ 
01738   /* CHANNEL 1 configuration */
01739   __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInTopLeftChannel);  
01740   hAudioInTopLeftChannel.Instance                      = DFSDM1_Channel1;  
01741   hAudioInTopLeftChannel.Init.OutputClock.Activation   = ENABLE;
01742   hAudioInTopLeftChannel.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
01743   /* Set the DFSDM clock OUT audio frequency configuration */
01744   hAudioInTopLeftChannel.Init.OutputClock.Divider      = DFSDM_CLOCK_DIVIDER(AudioFreq);
01745   hAudioInTopLeftChannel.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
01746   hAudioInTopLeftChannel.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
01747   hAudioInTopLeftChannel.Init.Input.Pins               = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
01748   /* Request to sample stable data for LEFT micro on Rising edge */
01749   hAudioInTopLeftChannel.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_RISING;
01750   hAudioInTopLeftChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
01751   hAudioInTopLeftChannel.Init.Awd.FilterOrder          = DFSDM_CHANNEL_FASTSINC_ORDER;
01752   hAudioInTopLeftChannel.Init.Awd.Oversampling         = 10;
01753   hAudioInTopLeftChannel.Init.Offset                   = 0;
01754   hAudioInTopLeftChannel.Init.RightBitShift            = DFSDM_RIGHT_BIT_SHIFT(AudioFreq);
01755   if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInTopLeftChannel))
01756   {
01757     return AUDIO_ERROR;
01758   }
01759   
01760   /* CHANNEL 0 configuration */
01761   __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInTopRightChannel);  
01762   hAudioInTopRightChannel.Instance                      = DFSDM1_Channel0;  
01763   hAudioInTopRightChannel.Init.OutputClock.Activation   = ENABLE;
01764   hAudioInTopRightChannel.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
01765   /* Set the DFSDM clock OUT audio frequency configuration */
01766   hAudioInTopRightChannel.Init.OutputClock.Divider      = DFSDM_CLOCK_DIVIDER(AudioFreq);
01767   hAudioInTopRightChannel.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
01768   hAudioInTopRightChannel.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
01769   hAudioInTopRightChannel.Init.Input.Pins               = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS;
01770   /* Request to sample stable data for RIGHT micro on Falling edge */
01771   hAudioInTopRightChannel.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_FALLING;
01772   hAudioInTopRightChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
01773   hAudioInTopRightChannel.Init.Awd.FilterOrder          = DFSDM_CHANNEL_FASTSINC_ORDER;
01774   hAudioInTopRightChannel.Init.Awd.Oversampling         = 10;
01775   hAudioInTopRightChannel.Init.Offset                   = 0;
01776   hAudioInTopRightChannel.Init.RightBitShift            = DFSDM_RIGHT_BIT_SHIFT(AudioFreq);
01777   if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInTopRightChannel))
01778   {
01779     return AUDIO_ERROR;
01780   }
01781   
01782   if(AudioIn_ChannelNumber > 2)
01783   {  
01784     /* CHANNEL 5 configuration */
01785     __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInButtomLeftChannel);  
01786     hAudioInButtomLeftChannel.Instance                      = DFSDM1_Channel5;  
01787     hAudioInButtomLeftChannel.Init.OutputClock.Activation   = ENABLE;
01788     hAudioInButtomLeftChannel.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
01789     /* Set the DFSDM clock OUT audio frequency configuration */
01790     hAudioInButtomLeftChannel.Init.OutputClock.Divider      = DFSDM_CLOCK_DIVIDER(AudioFreq);
01791     hAudioInButtomLeftChannel.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
01792     hAudioInButtomLeftChannel.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
01793     hAudioInButtomLeftChannel.Init.Input.Pins               = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
01794     /* Request to sample stable data for LEFT micro on Rising edge */
01795     hAudioInButtomLeftChannel.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_RISING;
01796     hAudioInButtomLeftChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
01797     hAudioInButtomLeftChannel.Init.Awd.FilterOrder          = DFSDM_CHANNEL_FASTSINC_ORDER;
01798     hAudioInButtomLeftChannel.Init.Awd.Oversampling         = 10;
01799     hAudioInButtomLeftChannel.Init.Offset                   = 0;
01800     hAudioInButtomLeftChannel.Init.RightBitShift            = DFSDM_RIGHT_BIT_SHIFT(AudioFreq);
01801     if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInButtomLeftChannel))
01802     {
01803       return AUDIO_ERROR;
01804     }
01805     
01806     /* CHANNEL 4 configuration */
01807     __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(&hAudioInButtomRightChannel);  
01808     hAudioInButtomRightChannel.Instance                      = DFSDM1_Channel4;  
01809     hAudioInButtomRightChannel.Init.OutputClock.Activation   = ENABLE;
01810     hAudioInButtomRightChannel.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
01811     /* Set the DFSDM clock OUT audio frequency configuration */
01812     hAudioInButtomRightChannel.Init.OutputClock.Divider      = DFSDM_CLOCK_DIVIDER(AudioFreq);
01813     hAudioInButtomRightChannel.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
01814     hAudioInButtomRightChannel.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
01815     hAudioInButtomRightChannel.Init.Input.Pins               = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS;
01816     /* Request to sample stable data for RIGHT micro on Falling edge */
01817     hAudioInButtomRightChannel.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_FALLING;
01818     hAudioInButtomRightChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
01819     hAudioInButtomRightChannel.Init.Awd.FilterOrder          = DFSDM_CHANNEL_FASTSINC_ORDER;
01820     hAudioInButtomRightChannel.Init.Awd.Oversampling         = 10;
01821     hAudioInButtomRightChannel.Init.Offset                   = 0;
01822     hAudioInButtomRightChannel.Init.RightBitShift            = DFSDM_RIGHT_BIT_SHIFT(AudioFreq);
01823     if(HAL_OK != HAL_DFSDM_ChannelInit(&hAudioInButtomRightChannel))
01824     {
01825       return AUDIO_ERROR;
01826     }
01827   }
01828   /****************************************************************************/ 
01829   /********************** Filters configuration  ******************************/
01830   /****************************************************************************/
01831   
01832   /* FILTER 0 configuration */
01833   __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInTopLeftFilter);
01834   hAudioInTopLeftFilter.Instance                          = AUDIO_DFSDMx_TOP_LEFT_FILTER;  
01835   hAudioInTopLeftFilter.Init.RegularParam.Trigger         = DFSDM_FILTER_SW_TRIGGER;
01836   hAudioInTopLeftFilter.Init.RegularParam.FastMode        = ENABLE;
01837   hAudioInTopLeftFilter.Init.RegularParam.DmaMode         = ENABLE;
01838   hAudioInTopLeftFilter.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
01839   hAudioInTopLeftFilter.Init.InjectedParam.ScanMode       = ENABLE;
01840   hAudioInTopLeftFilter.Init.InjectedParam.DmaMode        = DISABLE;
01841   hAudioInTopLeftFilter.Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
01842   hAudioInTopLeftFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
01843   hAudioInTopLeftFilter.Init.FilterParam.SincOrder        = DFSDM_FILTER_ORDER(AudioFreq);
01844   /* Set the DFSDM Filters Oversampling to have correct sample rate */
01845   hAudioInTopLeftFilter.Init.FilterParam.Oversampling     = DFSDM_OVER_SAMPLING(AudioFreq);
01846   hAudioInTopLeftFilter.Init.FilterParam.IntOversampling  = 1;
01847   if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInTopLeftFilter))
01848   {
01849     return AUDIO_ERROR;
01850   }
01851   
01852   /* Configure injected channel */
01853   if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInTopLeftFilter, AUDIO_DFSDMx_TOP_LEFT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON))
01854   {
01855     return AUDIO_ERROR;
01856   }
01857   
01858   /* FILTER 1 configuration */
01859   __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInTopRightFilter);
01860   hAudioInTopRightFilter.Instance                          = AUDIO_DFSDMx_TOP_RIGHT_FILTER;
01861   hAudioInTopRightFilter.Init.RegularParam.Trigger         = DFSDM_FILTER_SYNC_TRIGGER;
01862   hAudioInTopRightFilter.Init.RegularParam.FastMode        = ENABLE;
01863   hAudioInTopRightFilter.Init.RegularParam.DmaMode         = ENABLE;
01864   hAudioInTopRightFilter.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
01865   hAudioInTopRightFilter.Init.InjectedParam.ScanMode       = DISABLE;
01866   hAudioInTopRightFilter.Init.InjectedParam.DmaMode        = DISABLE;
01867   hAudioInTopRightFilter.Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
01868   hAudioInTopRightFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
01869   hAudioInTopRightFilter.Init.FilterParam.SincOrder        = DFSDM_FILTER_ORDER(AudioFreq);
01870   /* Set the DFSDM Filters Oversampling to have correct sample rate */
01871   hAudioInTopRightFilter.Init.FilterParam.Oversampling     = DFSDM_OVER_SAMPLING(AudioFreq);
01872   hAudioInTopRightFilter.Init.FilterParam.IntOversampling  = 1;
01873   if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInTopRightFilter))
01874   {
01875     return AUDIO_ERROR;
01876   }
01877   /* Configure injected channel */
01878   if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInTopRightFilter, AUDIO_DFSDMx_TOP_RIGHT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON))
01879   {
01880     return AUDIO_ERROR;
01881   } 
01882   
01883   if(AudioIn_ChannelNumber > 2)
01884   {
01885     /* FILTER 2 configuration */
01886     __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInButtomLeftFilter);
01887     hAudioInButtomLeftFilter.Instance                          = AUDIO_DFSDMx_BUTTOM_LEFT_FILTER;  
01888     hAudioInButtomLeftFilter.Init.RegularParam.Trigger         = DFSDM_FILTER_SYNC_TRIGGER;
01889     hAudioInButtomLeftFilter.Init.RegularParam.FastMode        = ENABLE;
01890     hAudioInButtomLeftFilter.Init.RegularParam.DmaMode         = ENABLE;
01891     hAudioInButtomLeftFilter.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
01892     hAudioInButtomLeftFilter.Init.InjectedParam.ScanMode       = ENABLE;
01893     hAudioInButtomLeftFilter.Init.InjectedParam.DmaMode        = DISABLE;
01894     hAudioInButtomLeftFilter.Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
01895     hAudioInButtomLeftFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
01896     hAudioInButtomLeftFilter.Init.FilterParam.SincOrder        = DFSDM_FILTER_ORDER(AudioFreq);
01897     /* Set the DFSDM Filters Oversampling to have correct sample rate */
01898     hAudioInButtomLeftFilter.Init.FilterParam.Oversampling     = DFSDM_OVER_SAMPLING(AudioFreq);
01899     hAudioInButtomLeftFilter.Init.FilterParam.IntOversampling  = 1;
01900     if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInButtomLeftFilter))
01901     {
01902       return AUDIO_ERROR;
01903     }
01904     
01905     /* Configure injected channel */
01906     if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInButtomLeftFilter, AUDIO_DFSDMx_BUTTOM_LEFT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON))
01907     {
01908       return AUDIO_ERROR;
01909     }
01910     
01911     /* FILTER 3 configuration */
01912     __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(&hAudioInButtomRightFilter);
01913     hAudioInButtomRightFilter.Instance                          = AUDIO_DFSDMx_BUTTOM_RIGHT_FILTER;
01914     hAudioInButtomRightFilter.Init.RegularParam.Trigger         = DFSDM_FILTER_SYNC_TRIGGER;
01915     hAudioInButtomRightFilter.Init.RegularParam.FastMode        = ENABLE;
01916     hAudioInButtomRightFilter.Init.RegularParam.DmaMode         = ENABLE;
01917     hAudioInButtomRightFilter.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
01918     hAudioInButtomRightFilter.Init.InjectedParam.ScanMode       = DISABLE;
01919     hAudioInButtomRightFilter.Init.InjectedParam.DmaMode        = DISABLE;
01920     hAudioInButtomRightFilter.Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
01921     hAudioInButtomRightFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
01922     hAudioInButtomRightFilter.Init.FilterParam.SincOrder        = DFSDM_FILTER_ORDER(AudioFreq);
01923     /* Set the DFSDM Filters Oversampling to have correct sample rate */
01924     hAudioInButtomRightFilter.Init.FilterParam.Oversampling     = DFSDM_OVER_SAMPLING(AudioFreq);
01925     hAudioInButtomRightFilter.Init.FilterParam.IntOversampling  = 1;
01926     if(HAL_OK != HAL_DFSDM_FilterInit(&hAudioInButtomRightFilter))
01927     {
01928       return AUDIO_ERROR;
01929     }
01930     /* Configure injected channel */
01931     if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&hAudioInButtomRightFilter, AUDIO_DFSDMx_BUTTOM_RIGHT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON))
01932     {
01933       return AUDIO_ERROR;
01934     } 
01935   }
01936   return AUDIO_OK;
01937 }
01938 
01939 /**
01940   * @brief  De-initialize the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01941   * @retval AUDIO_OK if correct communication, else wrong communication
01942   */
01943 static uint8_t DFSDMx_DeInit(void)
01944 {  
01945   /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */
01946   if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInTopLeftFilter))
01947   {
01948     return AUDIO_ERROR;
01949   }
01950   
01951   if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInTopRightFilter))
01952   {
01953     return AUDIO_ERROR;
01954   }
01955   
01956   /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */
01957   if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInTopLeftChannel))
01958   {
01959     return AUDIO_ERROR;
01960   }
01961   
01962   if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInTopRightChannel))
01963   {
01964     return AUDIO_ERROR;
01965   }
01966 
01967   if(AudioIn_ChannelNumber > 2)
01968   {
01969     /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */        
01970     if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInButtomLeftFilter))
01971     {
01972       return AUDIO_ERROR;
01973     }
01974     
01975     if(HAL_OK != HAL_DFSDM_FilterDeInit(&hAudioInButtomRightFilter))
01976     {
01977       return AUDIO_ERROR;
01978     }
01979     
01980     /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */  
01981     if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInButtomLeftChannel))
01982     {
01983       return AUDIO_ERROR;
01984     }
01985     
01986     if(HAL_OK != HAL_DFSDM_ChannelDeInit(&hAudioInButtomRightChannel))
01987     {
01988       return AUDIO_ERROR;
01989     }  
01990   }
01991   
01992   return AUDIO_OK;
01993 }
01994 
01995 /**
01996   * @brief  Initialize the DFSDM channel MSP.
01997   * @retval None
01998   */
01999 static void DFSDMx_ChannelMspInit(void)
02000 {
02001   GPIO_InitTypeDef  GPIO_InitStruct;  
02002   
02003   /* Enable DFSDM clock */
02004   AUDIO_DFSDMx_CLK_ENABLE();
02005   
02006   /* Enable GPIO clock */
02007   AUDIO_DFSDMx_DMIC_DATIN_GPIO_CLK_ENABLE();
02008   AUDIO_DFSDMx_CKOUT_DMIC_GPIO_CLK_ENABLE();
02009   
02010   /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN1 pins ------------------*/
02011   GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN;
02012   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
02013   GPIO_InitStruct.Pull = GPIO_NOPULL;
02014   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
02015   GPIO_InitStruct.Alternate = AUDIO_DFSDMx_CKOUT_AF;
02016   HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT, &GPIO_InitStruct);
02017   
02018   /* DFSDM pin configuration: DMIC_DATIN1 pin --------------------------------*/
02019   GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_DATIN1_PIN;
02020   GPIO_InitStruct.Alternate = AUDIO_DFSDMx_DMIC_DATIN_AF;
02021   HAL_GPIO_Init(AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct);
02022   
02023   if(AudioIn_ChannelNumber > 2)
02024   {
02025   /* DFSDM pin configuration: DMIC_DATIN5 pin --------------------------------*/  
02026     GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_DATIN5_PIN;
02027     GPIO_InitStruct.Alternate = AUDIO_DFSDMx_DMIC_DATIN_AF;
02028     HAL_GPIO_Init(AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct);    
02029   }
02030 }
02031 
02032 /**
02033   * @brief  DeInitialize the DFSDM channel MSP.
02034   * @retval None
02035   */
02036 static void DFSDMx_ChannelMspDeInit(void)
02037 {
02038   GPIO_InitTypeDef  GPIO_InitStruct;  
02039   
02040   /* DFSDM pin configuration: DMIC_DATIN1 pin --------------------------------*/
02041   GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN;
02042   HAL_GPIO_DeInit(AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT, GPIO_InitStruct.Pin);
02043   GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_DATIN1_PIN;
02044   HAL_GPIO_DeInit(AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, GPIO_InitStruct.Pin);
02045   
02046   if(AudioIn_ChannelNumber > 2)
02047   {
02048     /* DFSDM pin configuration: DMIC_DATIN5 pin ------------------------------*/
02049     GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN;
02050     HAL_GPIO_DeInit(AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT, GPIO_InitStruct.Pin);
02051     GPIO_InitStruct.Pin = AUDIO_DFSDMx_DMIC_DATIN5_PIN;
02052     HAL_GPIO_DeInit(AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, GPIO_InitStruct.Pin);    
02053   }
02054 }
02055 
02056 /**
02057   * @brief  Initialize the DFSDM filter MSP.
02058   * @retval None
02059   */
02060 static void DFSDMx_FilterMspInit(void)
02061 {  
02062   /* Enable DFSDM clock */
02063   AUDIO_DFSDMx_CLK_ENABLE();
02064   
02065   /* Enable the DMA clock */
02066   AUDIO_DFSDMx_DMAx_CLK_ENABLE();
02067   
02068   /*********** Configure DMA stream for TOP LEFT microphone *******************/
02069   hDmaTopLeft.Init.Direction           = DMA_PERIPH_TO_MEMORY;
02070   hDmaTopLeft.Init.PeriphInc           = DMA_PINC_DISABLE;
02071   hDmaTopLeft.Init.MemInc              = DMA_MINC_ENABLE;
02072   hDmaTopLeft.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
02073   hDmaTopLeft.Init.MemDataAlignment    = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
02074   hDmaTopLeft.Init.Mode                = DMA_CIRCULAR;
02075   hDmaTopLeft.Init.Priority            = DMA_PRIORITY_HIGH;
02076   hDmaTopLeft.Instance                 = AUDIO_DFSDMx_DMAx_TOP_LEFT_STREAM;
02077   hDmaTopLeft.Init.Channel             = AUDIO_DFSDMx_DMAx_CHANNEL; 
02078   
02079   /* Associate the DMA handle */
02080   __HAL_LINKDMA(&hAudioInTopLeftFilter, hdmaReg, hDmaTopLeft);
02081   
02082   /* Reset DMA handle state */
02083   __HAL_DMA_RESET_HANDLE_STATE(&hDmaTopLeft);
02084   
02085   /* Configure the DMA Channel */
02086   HAL_DMA_Init(&hDmaTopLeft);      
02087   
02088   /* DMA IRQ Channel configuration */
02089   HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_TOP_LEFT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
02090   HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_TOP_LEFT_IRQ);
02091   
02092   
02093   /*********** Configure DMA stream for TOP RIGHT microphone ******************/
02094   hDmaTopRight.Init.Direction           = DMA_PERIPH_TO_MEMORY;
02095   hDmaTopRight.Init.PeriphInc           = DMA_PINC_DISABLE;
02096   hDmaTopRight.Init.MemInc              = DMA_MINC_ENABLE;
02097   hDmaTopRight.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
02098   hDmaTopRight.Init.MemDataAlignment    = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
02099   hDmaTopRight.Init.Mode                = DMA_CIRCULAR;
02100   hDmaTopRight.Init.Priority            = DMA_PRIORITY_HIGH;  
02101   hDmaTopRight.Instance                 = AUDIO_DFSDMx_DMAx_TOP_RIGHT_STREAM;
02102   hDmaTopRight.Init.Channel             = AUDIO_DFSDMx_DMAx_CHANNEL;
02103   
02104   /* Associate the DMA handle */
02105   __HAL_LINKDMA(&hAudioInTopRightFilter, hdmaReg, hDmaTopRight);
02106   
02107   /* Reset DMA handle state */
02108   __HAL_DMA_RESET_HANDLE_STATE(&hDmaTopRight);
02109   
02110   /* Configure the DMA Channel */
02111   HAL_DMA_Init(&hDmaTopRight);      
02112   
02113   /* DMA IRQ Channel configuration */
02114   HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_TOP_RIGHT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
02115   HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_TOP_RIGHT_IRQ);
02116   
02117   if(AudioIn_ChannelNumber > 2)
02118   {  
02119     /*********** Configure DMA stream for BUTTOM LEFT microphone ****************/
02120     hDmaButtomLeft.Init.Direction           = DMA_PERIPH_TO_MEMORY;
02121     hDmaButtomLeft.Init.PeriphInc           = DMA_PINC_DISABLE;
02122     hDmaButtomLeft.Init.MemInc              = DMA_MINC_ENABLE;
02123     hDmaButtomLeft.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
02124     hDmaButtomLeft.Init.MemDataAlignment    = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
02125     hDmaButtomLeft.Init.Mode                = DMA_CIRCULAR;
02126     hDmaButtomLeft.Init.Priority            = DMA_PRIORITY_HIGH;
02127     hDmaButtomLeft.Instance                 = AUDIO_DFSDMx_DMAx_BUTTOM_LEFT_STREAM;
02128     hDmaButtomLeft.Init.Channel             = AUDIO_DFSDMx_DMAx_CHANNEL; 
02129     
02130     /* Associate the DMA handle */
02131     __HAL_LINKDMA(&hAudioInButtomLeftFilter, hdmaReg, hDmaButtomLeft);
02132     
02133     /* Reset DMA handle state */
02134     __HAL_DMA_RESET_HANDLE_STATE(&hDmaButtomLeft);
02135     
02136     /* Configure the DMA Channel */
02137     HAL_DMA_Init(&hDmaButtomLeft);      
02138     
02139     /* DMA IRQ Channel configuration */
02140     HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_BUTTOM_LEFT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
02141     HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_BUTTOM_LEFT_IRQ);
02142     
02143     
02144     /*********** Configure DMA stream for BUTTOM RIGHT microphone ***************/
02145     hDmaButtomRight.Init.Direction           = DMA_PERIPH_TO_MEMORY;
02146     hDmaButtomRight.Init.PeriphInc           = DMA_PINC_DISABLE;
02147     hDmaButtomRight.Init.MemInc              = DMA_MINC_ENABLE;
02148     hDmaButtomRight.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
02149     hDmaButtomRight.Init.MemDataAlignment    = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
02150     hDmaButtomRight.Init.Mode                = DMA_CIRCULAR;
02151     hDmaButtomRight.Init.Priority            = DMA_PRIORITY_HIGH;  
02152     hDmaButtomRight.Instance                 = AUDIO_DFSDMx_DMAx_BUTTOM_RIGHT_STREAM;
02153     hDmaButtomRight.Init.Channel             = AUDIO_DFSDMx_DMAx_CHANNEL;
02154     
02155     /* Associate the DMA handle */
02156     __HAL_LINKDMA(&hAudioInButtomRightFilter, hdmaReg, hDmaButtomRight);
02157     
02158     /* Reset DMA handle state */
02159     __HAL_DMA_RESET_HANDLE_STATE(&hDmaButtomRight);
02160     
02161     /* Configure the DMA Channel */
02162     HAL_DMA_Init(&hDmaButtomRight);      
02163     
02164     /* DMA IRQ Channel configuration */
02165     HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_BUTTOM_RIGHT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
02166     HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_BUTTOM_RIGHT_IRQ); 
02167   }
02168 }
02169 
02170 /**
02171   * @brief  DeInitialize the DFSDM filter MSP.
02172   * @retval None
02173   */
02174 static void DFSDMx_FilterMspDeInit(void)
02175 {
02176   /* Configure the DMA Channel */
02177   HAL_DMA_DeInit(&hDmaTopLeft);
02178   HAL_DMA_DeInit(&hDmaTopRight);
02179   if(AudioIn_ChannelNumber > 2)
02180   {
02181     HAL_DMA_DeInit(&hDmaButtomLeft);
02182     HAL_DMA_DeInit(&hDmaButtomRight);
02183   }  
02184 }
02185 
02186 /**
02187   * @}
02188   */ 
02189   
02190 /**
02191   * @}
02192   */
02193 
02194 /**
02195   * @}
02196   */
02197 
02198 /**
02199   * @}
02200   */ 
02201 
02202 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Fri Dec 30 2016 18:30:07 for STM32F769I-Discovery BSP User Manual by   doxygen 1.7.6.1