STM32L476G_EVAL BSP User Manual: stm32l476g_eval_audio.c Source File

STM32L476G_EVAL BSP

stm32l476g_eval_audio.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l476g_eval_audio.c
00004   * @author  MCD Application Team
00005   * @version $VERSION$
00006   * @date    $DATE$
00007   * @brief   This file provides the Audio driver for the STM32L476G-EVAL evaluation board.
00008   ******************************************************************************
00009   * @attention
00010   *
00011   * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
00012   *
00013   * Redistribution and use in source and binary forms, with or without modification,
00014   * are permitted provided that the following conditions are met:
00015   *   1. Redistributions of source code must retain the above copyright notice,
00016   *      this list of conditions and the following disclaimer.
00017   *   2. Redistributions in binary form must reproduce the above copyright notice,
00018   *      this list of conditions and the following disclaimer in the documentation
00019   *      and/or other materials provided with the distribution.
00020   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00021   *      may be used to endorse or promote products derived from this software
00022   *      without specific prior written permission.
00023   *
00024   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00025   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00026   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00028   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00029   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00030   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00032   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034   *
00035   ******************************************************************************
00036   */
00037 
00038 /*==============================================================================
00039                                  User NOTES
00040                                  
00041 1. How To use this driver:
00042 --------------------------
00043    + This driver supports STM32L4xx devices on STM32L476G-EVAL (MB1144) Evaluation boards.
00044         a) to play an audio file (all functions names start by BSP_AUDIO_OUT_xxx)
00045         b) to record an audio file through MP34DT01TR, ST MEMS (all functions names start by BSP_AUDIO_IN_xxx)
00046 
00047 a) PLAY A FILE:
00048 ==============
00049    + Call the function BSP_AUDIO_OUT_Init(
00050                                     OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 
00051                                                   OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH)
00052                                     Volume      : Initial volume to be set (0 is min (mute), 100 is max (100%)
00053                                     AudioFreq   : Audio frequency in Hz (8000, 16000, 22500, 32000...)
00054                                                   this parameter is relative to the audio file/stream type.
00055                                    )
00056       This function configures all the hardware required for the audio application (codec, I2C, SAI, 
00057       GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK.
00058       If the returned value is different from AUDIO_OK or the function is stuck then the communication with
00059       the codec or the IOExpander has failed (try to un-plug the power or reset device in this case).
00060       - OUTPUT_DEVICE_SPEAKER  : only speaker will be set as output for the audio stream.
00061       - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream.
00062       - OUTPUT_DEVICE_BOTH     : both Speaker and Headphone are used as outputs for the audio stream
00063                                  at the same time.
00064    + Call the function BSP_AUDIO_OUT_Play(
00065                                   pBuffer: pointer to the audio data file address
00066                                   Size   : size of the buffer to be sent in Bytes
00067                                  )
00068       to start playing (for the first time) from the audio file/stream.
00069    + Call the function BSP_AUDIO_OUT_Pause() to pause playing   
00070    + Call the function BSP_AUDIO_OUT_Resume() to resume playing.
00071        Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called
00072           for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case).
00073        Note. This function should be called only when the audio file is played or paused (not stopped).
00074    + For each mode, you may need to implement the relative callback functions into your code.
00075       The Callback functions are named BSP_AUDIO_OUT_XXXCallBack() and only their prototypes are declared in 
00076       the stm32l476g_eval_audio.h file. (refer to the example for more details on the callbacks implementations)
00077    + To Stop playing, to modify the volume level, the frequency, the audio frame slot, 
00078       the device output mode, the mute, the audio configuratio or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(), 
00079       AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetAudioFrameSlot(), BSP_AUDIO_OUT_SetOutputMode(),
00080       BSP_AUDIO_OUT_SetMute(), BSP_AUDIO_OUT_ChangeAudioConfig() and BSP_AUDIO_OUT_Stop().
00081    + The driver API and the callback functions are at the end of the stm32l476g_eval_audio.h file.
00082  
00083 Driver architecture:
00084 --------------------
00085    + This driver provide the High Audio Layer: consists of the function API exported in the stm32l476g_eval_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 stm32l476g_eval_audio_codec.c file (SAIx_MspInit() and SAIx_Init())   
00090 
00091 Known Limitations:
00092 ------------------
00093    1- When using the Speaker, if the audio file quality is not high enough, the speaker output
00094       may produce high and uncomfortable noise level. To avoid this issue, to use speaker
00095       output properly, try to increase audio file sampling rate (typically higher than 48KHz).
00096       This operation will lead to larger file size.
00097    2- Communication with the audio codec (through I2C) may be corrupted if it is interrupted by some
00098       user interrupt routines (in this case, interrupts could be disabled just before the start of 
00099       communication then re-enabled when it is over). Note that this communication is only done at
00100       the configuration phase (BSP_AUDIO_OUT_Init() or BSP_AUDIO_OUT_Stop()) and when Volume control modification is 
00101       performed (BSP_AUDIO_OUT_SetVolume() or BSP_AUDIO_OUT_SetMute()or BSP_AUDIO_OUT_SetOutputMode()). 
00102       When the audio data is played, no communication is required with the audio codec.
00103    3- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 
00104       File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file.
00105    4- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second 
00106       Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams.
00107    5- Supports only Stereo audio streaming.
00108    6- Supports only 16-bits audio data size.
00109 
00110 b) RECORD A FILE:
00111 ================
00112    + Call the function BSP_AUDIO_IN_Init(
00113                                     AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...)
00114                                     )
00115       This function configures all the hardware required for the audio application (SAI, 
00116       GPIOs, DMA and interrupt if needed). This function returns 0 if configuration is OK.
00117 
00118    + Call the function BSP_AUDIO_IN_Record(
00119                             pbuf Main buffer pointer for the recorded data storing  
00120                             size Current size of the recorded buffer
00121                             )
00122       to start recording from the microphones.
00123 
00124    + User needs to implement user callbacks to follow the process of data recorded in the record buffer
00125       (BSP_AUDIO_IN_HalfTransfer_CallBack()/BSP_AUDIO_IN_TransferComplete_CallBack()
00126 
00127    + Call the function AUDIO_IN_STOP() to stop recording 
00128 ==============================================================================*/
00129 
00130 /* Includes ------------------------------------------------------------------*/
00131 #include "stm32l476g_eval_audio.h"
00132 
00133 /** @addtogroup BSP
00134   * @{
00135   */
00136 
00137 /** @addtogroup STM32L476G_EVAL
00138   * @{
00139   */
00140 
00141 /** @defgroup STM32L476G_EVAL_AUDIO STM32L476G_EVAL AUDIO
00142   * @brief This file includes the low layer driver for wm8994 Audio Codec
00143   *        available on STM32L476G-EVAL evaluation board(MB1144).
00144   * @{
00145   */ 
00146 
00147 /** @defgroup STM32L476G_EVAL_AUDIO_Private_Types Private Types
00148   * @{
00149   */
00150 typedef struct
00151 {
00152   uint32_t      Frequency;      /* Record Frequency */
00153   uint32_t      BitResolution;  /* Record bit resolution */
00154   uint32_t      ChannelNbr;     /* Record Channel Number */
00155   uint16_t      *pRecBuf;       /* Pointer to record user buffer */
00156   uint32_t      RecSize;        /* Size to record in mono, double size to record in stereo */
00157 }AUDIOIN_TypeDef;
00158 /**
00159   * @}
00160   */ 
00161   
00162 /** @defgroup STM32L476G_EVAL_AUDIO_Private_Constants Private Constants
00163   * @{
00164   */
00165 /**
00166   * @}
00167   */ 
00168 
00169 /** @defgroup STM32L476G_EVAL_AUDIO_Private_Macros Private Macros
00170   * @{
00171   */
00172 /*### PLAY ###*/
00173 /* SCK(kHz) = SAI_CK_x/(SAIClockDivider*2*256) */
00174 #define SAIClockDivider(__FREQUENCY__) \
00175         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 12 \
00176       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 2 \
00177       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 6 \
00178       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 1 \
00179       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 3 \
00180       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 0 \
00181       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 2 : 1  \
00182 
00183 /*### RECORD ###*/
00184 #define DFSDMOverSampling(__FREQUENCY__) \
00185         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 256 \
00186       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \
00187       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \
00188       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \
00189       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \
00190       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64  \
00191       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 16  \
00192 
00193 #define DFSDMClockDivider(__FREQUENCY__) \
00194         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 24 \
00195       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \
00196       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \
00197       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
00198       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \
00199       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4  \
00200       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 32  \
00201 
00202 #define DFSDMFilterOrder(__FREQUENCY__) \
00203         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? DFSDM_FILTER_SINC3_ORDER \
00204       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \
00205       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \
00206       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \
00207       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \
00208       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC4_ORDER  \
00209       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC4_ORDER : DFSDM_FILTER_SINC5_ORDER  \
00210 
00211 #define DFSDMRightBitShift(__FREQUENCY__) \
00212         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 3 \
00213       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 3 \
00214       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 0 \
00215       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 0 \
00216       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 3 \
00217       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 3  \
00218       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 0 : 0  \
00219 
00220 /* Saturate the record PCM sample */
00221 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N)))
00222 
00223 /**
00224   * @}
00225   */ 
00226   
00227 /** @defgroup STM32L476G_EVAL_AUDIO_Private_Variables Private Variables
00228   * @{
00229   */
00230 /*### PLAY ###*/
00231 AUDIO_DrvTypeDef                *audio_drv;
00232 SAI_HandleTypeDef               haudio_out_sai;
00233 
00234 /*### RECORD ###*/
00235 AUDIOIN_TypeDef                 audio_in_context;
00236 
00237 DFSDM_Channel_HandleTypeDef     haudio_in_dfsdm_leftchannel;
00238 DFSDM_Channel_HandleTypeDef     haudio_in_dfsdm_rightchannel;
00239 DFSDM_Filter_HandleTypeDef      haudio_in_dfsdm_leftfilter;
00240 DFSDM_Filter_HandleTypeDef      haudio_in_dfsdm_rightfilter;
00241 DMA_HandleTypeDef               hdma_dfsdm_left;
00242 DMA_HandleTypeDef               hdma_dfsdm_right;
00243 
00244 /* Buffers for right and left samples */
00245 int32_t                         LeftRecBuff[INTERNAL_BUFF_SIZE];
00246 int32_t                         RightRecBuff[INTERNAL_BUFF_SIZE];
00247 
00248 /* Buffers status flags */
00249 uint32_t                        DmaLeftRecHalfBuffCplt  = 0;
00250 uint32_t                        DmaLeftRecBuffCplt      = 0;
00251 uint32_t                        DmaRightRecHalfBuffCplt = 0;
00252 uint32_t                        DmaRightRecBuffCplt     = 0;
00253 
00254 /* Application Buffer Trigger */
00255 __IO uint32_t                   AppBuffTrigger          = 0;
00256 uint32_t __IO                   AppBuffHalf             = 0;
00257 
00258 /* Default record volume */
00259 uint16_t __IO AudioInVolume = DEFAULT_AUDIO_IN_VOLUME;
00260     
00261 /**
00262   * @}
00263   */ 
00264 
00265 /** @defgroup STM32L476G_EVAL_AUDIO_Private_Functions Private Functions
00266   * @{
00267   */
00268 static void    CODEC_Reset(void);
00269 static void    SAIx_MspInit(void);
00270 static void    SAIx_Init(uint32_t AudioFreq);
00271 static void    DFSDMx_ChannelMspInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel);
00272 static void    DFSDMx_FilterMspInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter);
00273 static void    DFSDMx_ChannelMspDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel);
00274 static void    DFSDMx_FilterMspDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter);
00275 static uint8_t DFSDMx_Init(uint32_t AudioFreq);
00276 static uint8_t DFSDMx_DeInit(void);
00277 /**
00278   * @}
00279   */ 
00280 
00281 /** @addtogroup STM32L476G_EVAL_AUDIO_Exported_Functions
00282   * @{
00283   */ 
00284 
00285 /**
00286   * @brief  Configures the audio peripherals.
00287   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
00288   *                       or OUTPUT_DEVICE_BOTH.
00289   * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
00290   * @param  AudioFreq: Audio frequency used to play the audio stream.
00291   * @note   The SAI PLL input clock must be done in the user application.  
00292   * @retval AUDIO_OK if correct communication, else wrong communication
00293   */
00294 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
00295 { 
00296   uint8_t ret = AUDIO_ERROR;
00297   uint32_t deviceid = 0x00;
00298   RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct;
00299   
00300   HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct);
00301   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
00302   {
00303     /* Configure PLLSAI prescalers */
00304     /* SAI clock config 
00305     PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 24 = VCO_192M 
00306     SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 192/17 = 11.294 Mhz */  
00307     RCC_ExCLKInitStruct.PeriphClockSelection    = RCC_PERIPHCLK_SAI1;
00308     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N        = 24; 
00309     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P        = 17; 
00310     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
00311     RCC_ExCLKInitStruct.Sai1ClockSelection      = RCC_SAI1CLKSOURCE_PLLSAI1;
00312     HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct);
00313   }
00314   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
00315   {
00316     /* SAI clock config 
00317     PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 43 = VCO_344M 
00318     SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 344/7 = 49.142 Mhz */  
00319     RCC_ExCLKInitStruct.PeriphClockSelection    = RCC_PERIPHCLK_SAI1;
00320     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N        = 43;
00321     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P        = 7;
00322     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
00323     RCC_ExCLKInitStruct.Sai1ClockSelection      = RCC_SAI1CLKSOURCE_PLLSAI1;
00324     HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct);    
00325   }
00326   
00327   /* SAI data transfer preparation:
00328   Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
00329   SAIx_Init(AudioFreq);
00330 
00331   /* wm8994 codec initialization */
00332   deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
00333   
00334   /* Reset the Codec Registers */
00335   CODEC_Reset();
00336   
00337   if((deviceid) == WM8994_ID)
00338   {  
00339     /* Initialize the audio driver structure */
00340     audio_drv = &wm8994_drv; 
00341     ret = AUDIO_OK;
00342   }
00343   else
00344   {
00345     ret = AUDIO_ERROR;
00346   }
00347 
00348   if(ret == AUDIO_OK)
00349   {
00350     /* Initialize the codec internal registers */
00351     audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq);
00352   }
00353   
00354   /* Set the request volume */
00355   BSP_AUDIO_OUT_SetVolume(Volume);
00356   
00357   return ret;
00358 }
00359 
00360 /**
00361   * @brief  Starts playing audio stream from a data buffer for a determined size. 
00362   * @param  pBuffer: Pointer to the buffer 
00363   * @param  Size: Number of audio data BYTES.
00364   * @retval AUDIO_OK if correct communication, else wrong communication
00365   */
00366 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size)
00367 {
00368   /* Call the audio Codec Play function */
00369   if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0)
00370   {  
00371     return AUDIO_ERROR;
00372   }
00373   else
00374   {
00375     /* Update the Media layer and enable it for play */  
00376     HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t *)pBuffer, DMA_MAX(Size));
00377         
00378     return AUDIO_OK;
00379   }
00380 }
00381 
00382 /**
00383   * @brief  Sends n-Bytes on the SAI interface.
00384   * @param  pData: pointer on data address 
00385   * @param  Size: number of data to be written
00386   * @retval AUDIO_OK if correct communication, else wrong communication
00387   */
00388 uint8_t BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size)
00389 {
00390    return (HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t *)pData, Size));
00391 }
00392 
00393 /**
00394   * @brief  This function Pauses the audio file stream. In case
00395   *         of using DMA, the DMA Pause feature is used.
00396   * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only
00397   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00398   *          function for resume could lead to unexpected behavior).
00399   * @retval AUDIO_OK if correct communication, else wrong communication
00400   */
00401 uint8_t BSP_AUDIO_OUT_Pause(void)
00402 {    
00403   /* Call the Audio Codec Pause/Resume function */
00404   if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0)
00405   {
00406     return AUDIO_ERROR;
00407   }
00408   else
00409   {
00410     /* Call the Media layer pause function */
00411     HAL_SAI_DMAPause(&haudio_out_sai);
00412     
00413     /* Return AUDIO_OK when all operations are correctly done */
00414     return AUDIO_OK;
00415   }
00416 }
00417 
00418 /**
00419   * @brief  This function  Resumes the audio file stream.  
00420   * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only
00421   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00422   *          function for resume could lead to unexpected behavior).
00423   * @retval AUDIO_OK if correct communication, else wrong communication
00424   */
00425 uint8_t BSP_AUDIO_OUT_Resume(void)
00426 {    
00427   /* Call the Audio Codec Pause/Resume function */
00428   if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0)
00429   {
00430     return AUDIO_ERROR;
00431   }
00432   else
00433   {
00434     /* Call the Media layer pause/resume function */
00435     HAL_SAI_DMAResume(&haudio_out_sai);
00436     
00437     /* Return AUDIO_OK when all operations are correctly done */
00438     return AUDIO_OK;
00439   }
00440 }
00441 
00442 /**
00443   * @brief  Stops audio playing and Power down the Audio Codec. 
00444   * @param  Option: could be one of the following parameters 
00445   *           - CODEC_PDWN_SW: for software power off (by writing registers). 
00446   *                            Then no need to reconfigure the Codec after power on.
00447   *           - CODEC_PDWN_HW: completely shut down the codec (physically). 
00448   *                            Then need to reconfigure the Codec after power on.  
00449   * @retval AUDIO_OK if correct communication, else wrong communication
00450   */
00451 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
00452 {
00453   /* Call the Media layer stop function */
00454   HAL_SAI_DMAStop(&haudio_out_sai);
00455   
00456   /* Call Audio Codec Stop function */
00457   if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
00458   {
00459     return AUDIO_ERROR;
00460   }
00461   else
00462   {
00463     if(Option == CODEC_PDWN_HW)
00464     { 
00465       /* Wait at least 100us */
00466       HAL_Delay(1);
00467   
00468       /* Power Down the codec */
00469       HAL_GPIO_WritePin(AUDIO_RESET_GPIO, AUDIO_RESET_PIN, GPIO_PIN_RESET);
00470   
00471     }
00472     /* Return AUDIO_OK when all operations are correctly done */
00473     return AUDIO_OK;
00474   }
00475 }
00476 
00477 /**
00478   * @brief  Controls the current audio volume level. 
00479   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for 
00480   *         Mute and 100 for Max volume level).
00481   * @retval AUDIO_OK if correct communication, else wrong communication
00482   */
00483 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume)
00484 {
00485   /* Call the codec volume control function with converted volume value */
00486   if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
00487   {
00488     return AUDIO_ERROR;
00489   }
00490   else
00491   {
00492     /* Return AUDIO_OK when all operations are correctly done */
00493     return AUDIO_OK;
00494   }
00495 }
00496 
00497 /**
00498   * @brief  Enables or disables the MUTE mode by software 
00499   * @param  Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 
00500   *         unmute the codec and restore previous volume level.
00501   * @retval AUDIO_OK if correct communication, else wrong communication
00502   */
00503 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd)
00504 { 
00505   /* Call the Codec Mute function */
00506   if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0)
00507   {
00508     return AUDIO_ERROR;
00509   }
00510   else
00511   {
00512     /* Return AUDIO_OK when all operations are correctly done */
00513     return AUDIO_OK;
00514   }
00515 }
00516 
00517 /**
00518   * @brief  Switch dynamically (while audio file is played) the output target 
00519   *         (speaker or headphone).
00520   * @param  Output: The audio output target: OUTPUT_DEVICE_SPEAKER,
00521   *         OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH
00522   * @retval AUDIO_OK if correct communication, else wrong communication
00523   */
00524 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)
00525 {
00526   /* Call the Codec output device function */
00527   if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0)
00528   {
00529     return AUDIO_ERROR;
00530   }
00531   else
00532   {
00533     /* Return AUDIO_OK when all operations are correctly done */
00534     return AUDIO_OK;
00535   }
00536 }
00537 
00538 /**
00539   * @brief  Update the audio frequency.
00540   * @param  AudioFreq: Audio frequency used to play the audio stream.
00541   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00542   *         audio frequency.
00543   * @retval None
00544   */
00545 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)
00546 { 
00547   RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct;
00548   
00549   HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct);
00550   
00551   /* Update the PLL configuration according to the new frequency */
00552   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
00553   {
00554     /* Configure PLLSAI prescalers */
00555     /* SAI clock config 
00556     PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 24 = VCO_192M 
00557     SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 192/17 = 11.294 Mhz */  
00558     RCC_ExCLKInitStruct.PeriphClockSelection    = RCC_PERIPHCLK_SAI1;
00559     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N        = 24; 
00560     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P        = 17; 
00561     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
00562     RCC_ExCLKInitStruct.Sai1ClockSelection      = RCC_SAI1CLKSOURCE_PLLSAI1;
00563     HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct);
00564   }
00565   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
00566   {
00567     /* SAI clock config 
00568     PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 43 = VCO_344M 
00569     SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 344/7 = 49.142 Mhz */  
00570     RCC_ExCLKInitStruct.PeriphClockSelection    = RCC_PERIPHCLK_SAI1;
00571     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N        = 43;
00572     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P        = 7;
00573     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
00574     RCC_ExCLKInitStruct.Sai1ClockSelection      = RCC_SAI1CLKSOURCE_PLLSAI1;
00575     HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct);    
00576   }
00577   /* Disable SAI peripheral to allow access to SAI internal registers */
00578   __HAL_SAI_DISABLE(&haudio_out_sai);
00579   
00580   /* Update the SAI audio frequency configuration */
00581   haudio_out_sai.Init.Mckdiv = SAIClockDivider(AudioFreq);
00582   HAL_SAI_Init(&haudio_out_sai);
00583   
00584   /* Enable SAI peripheral to generate MCLK */
00585   __HAL_SAI_ENABLE(&haudio_out_sai);
00586 }
00587 
00588 /**
00589   * @brief  Updates the Audio frame slot configuration.
00590   * @param  AudioFrameSlot: specifies the audio Frame slot
00591   *         This parameter can be any value of @ref CODEC_AudioFrame_SLOT_TDMMode
00592   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00593   *         audio frame slot.
00594   * @retval None
00595   */
00596 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot)
00597 { 
00598   /* Disable SAI peripheral to allow access to SAI internal registers */
00599   __HAL_SAI_DISABLE(&haudio_out_sai);
00600   
00601   /* Update the SAI audio frame slot configuration */
00602   haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot;
00603   HAL_SAI_Init(&haudio_out_sai);
00604   
00605   /* Enable SAI peripheral to generate MCLK */
00606   __HAL_SAI_ENABLE(&haudio_out_sai);
00607 }
00608 
00609 /**
00610   * @brief  Changes the Audio Out Configuration.
00611   * @param  AudioOutOption: specifies the audio out new configuration
00612   *         This parameter can be any value of @ref BSP_Audio_Out_Option
00613   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00614   *         audio out configuration.
00615   * @retval None
00616   */
00617 void BSP_AUDIO_OUT_ChangeAudioConfig(uint32_t AudioOutOption)
00618 { 
00619   /********** Playback Buffer circular/normal mode **********/
00620   if(AudioOutOption & BSP_AUDIO_OUT_CIRCULARMODE)
00621   {
00622     /* Deinitialize the Stream to update DMA mode */
00623     HAL_DMA_DeInit(haudio_out_sai.hdmatx);
00624     
00625     /* Update the SAI audio Transfer DMA mode */
00626     haudio_out_sai.hdmatx->Init.Mode = DMA_CIRCULAR;
00627     
00628     /* Configure the DMA Stream with new Transfer DMA mode */
00629     HAL_DMA_Init(haudio_out_sai.hdmatx);      
00630   }
00631   else /* BSP_AUDIO_OUT_NORMALMODE */
00632   {
00633     /* Deinitialize the Stream to update DMA mode */
00634     HAL_DMA_DeInit(haudio_out_sai.hdmatx);
00635     
00636     /* Update the SAI audio Transfer DMA mode */
00637     haudio_out_sai.hdmatx->Init.Mode = DMA_NORMAL;
00638     
00639     /* Configure the DMA Stream with new Transfer DMA mode */
00640     HAL_DMA_Init(haudio_out_sai.hdmatx);      
00641   }
00642   
00643   /********** Playback Buffer stereo/mono mode **********/
00644   if(AudioOutOption & BSP_AUDIO_OUT_STEREOMODE)
00645   {
00646     /* Disable SAI peripheral to allow access to SAI internal registers */
00647     __HAL_SAI_DISABLE(&haudio_out_sai);
00648     
00649     /* Update the SAI audio frame slot configuration */
00650     haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE;
00651     HAL_SAI_Init(&haudio_out_sai);
00652     
00653     /* Enable SAI peripheral to generate MCLK */
00654     __HAL_SAI_ENABLE(&haudio_out_sai);
00655   }
00656   else /* BSP_AUDIO_OUT_MONOMODE */
00657   {
00658     /* Disable SAI peripheral to allow access to SAI internal registers */
00659     __HAL_SAI_DISABLE(&haudio_out_sai);
00660     
00661     /* Update the SAI audio frame slot configuration */
00662     haudio_out_sai.Init.MonoStereoMode = SAI_MONOMODE;
00663     HAL_SAI_Init(&haudio_out_sai);
00664     
00665     /* Enable SAI peripheral to generate MCLK */
00666     __HAL_SAI_ENABLE(&haudio_out_sai);
00667   }
00668 }
00669 
00670 /**
00671   * @brief  Tx Transfer completed callbacks.
00672   * @param  hsai: SAI handle
00673   * @retval None
00674   */
00675 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
00676 {
00677   /* Manage the remaining file size and new address offset: This function 
00678      should be coded by user (its prototype is already declared in stm32l476g_eval_audio.h) */
00679   BSP_AUDIO_OUT_TransferComplete_CallBack();
00680 }
00681 
00682 /**
00683   * @brief  Tx Half Transfer completed callbacks.
00684   * @param  hsai: SAI handle
00685   * @retval None
00686   */
00687 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
00688 {
00689   /* Manage the remaining file size and new address offset: This function 
00690      should be coded by user (its prototype is already declared in stm32l476g_eval_audio.h) */
00691   BSP_AUDIO_OUT_HalfTransfer_CallBack();
00692 }
00693 
00694 /**
00695   * @brief  SAI error callbacks.
00696   * @param  hsai: SAI handle
00697   * @retval None
00698   */
00699 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
00700 {
00701   BSP_AUDIO_OUT_Error_CallBack();
00702 }
00703 
00704 /**
00705   * @brief  Manages the DMA full Transfer complete event.
00706   * @retval None
00707   */
00708 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
00709 {
00710 }
00711 
00712 /**
00713   * @brief  Manages the DMA Half Transfer complete event.
00714   * @retval None
00715   */
00716 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void)
00717 {
00718 }
00719 
00720 /**
00721   * @brief  Manages the DMA FIFO error event.
00722   * @retval None
00723   */
00724 __weak void BSP_AUDIO_OUT_Error_CallBack(void)
00725 {
00726 }
00727 
00728 /**
00729   * @}
00730   */
00731 
00732 /** @addtogroup STM32L476G_EVAL_AUDIO_Private_Functions
00733   * @{
00734   */
00735 
00736 /*******************************************************************************
00737                             Static Functions
00738 *******************************************************************************/
00739 /**
00740   * @brief  Initializes SAI MSP.
00741   * @retval None
00742   */
00743 static void SAIx_MspInit(void)
00744 { 
00745   static DMA_HandleTypeDef hdma_saiTx;
00746   GPIO_InitTypeDef  GPIO_InitStruct;  
00747   SAI_HandleTypeDef *hsai = &haudio_out_sai;
00748 
00749   /* Enable SAI clock */
00750   AUDIO_SAIx_CLK_ENABLE();
00751   
00752   /* Enable GPIO clock */
00753   AUDIO_SAIx_MCKB_SCKB_SDB_FSB_ENABLE();
00754   
00755   /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/
00756   GPIO_InitStruct.Pin = AUDIO_SAIx_FSB_PIN | AUDIO_SAIx_SCKB_PIN | AUDIO_SAIx_SDB_PIN | AUDIO_SAIx_MCKB_PIN;
00757   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
00758   GPIO_InitStruct.Pull = GPIO_NOPULL;
00759   GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
00760   GPIO_InitStruct.Alternate = AUDIO_SAIx_MCKB_SCKB_SDB_FSB_AF;
00761   HAL_GPIO_Init(AUDIO_SAIx_MCKB_SCKB_SDB_FSB_GPIO_PORT, &GPIO_InitStruct);
00762 
00763   /* Enable the DMA clock */
00764   AUDIO_SAIx_DMAx_CLK_ENABLE();
00765     
00766   if(hsai->Instance == AUDIO_SAIx)
00767   {
00768     /* Configure the hdma_saiTx handle parameters */   
00769     hdma_saiTx.Init.Request             = DMA_REQUEST_1;
00770     hdma_saiTx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
00771     hdma_saiTx.Init.PeriphInc           = DMA_PINC_DISABLE;
00772     hdma_saiTx.Init.MemInc              = DMA_MINC_ENABLE;
00773     hdma_saiTx.Init.PeriphDataAlignment = AUDIO_SAIx_DMAx_PERIPH_DATA_SIZE;
00774     hdma_saiTx.Init.MemDataAlignment    = AUDIO_SAIx_DMAx_MEM_DATA_SIZE;
00775     hdma_saiTx.Init.Mode                = DMA_NORMAL;
00776     hdma_saiTx.Init.Priority            = DMA_PRIORITY_HIGH;
00777     
00778     hdma_saiTx.Instance = AUDIO_SAIx_DMAx_CHANNEL;
00779     
00780     /* Associate the DMA handle */
00781     __HAL_LINKDMA(hsai, hdmatx, hdma_saiTx);
00782     
00783     /* Deinitialize the Stream for new transfer */
00784     HAL_DMA_DeInit(&hdma_saiTx);
00785     
00786     /* Configure the DMA Stream */
00787     HAL_DMA_Init(&hdma_saiTx);      
00788   }
00789   
00790   /* SAI DMA IRQ Channel configuration */
00791   HAL_NVIC_SetPriority(AUDIO_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
00792   HAL_NVIC_EnableIRQ(AUDIO_SAIx_DMAx_IRQ); 
00793 }
00794 
00795 /**
00796   * @brief  Initializes the Audio Codec audio interface (SAI).
00797   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00798   * @note   The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 
00799   *         and user can update this configuration using 
00800   * @retval None
00801   */
00802 static void SAIx_Init(uint32_t AudioFreq)
00803 {
00804   /* Initialize the haudio_out_sai Instance parameter */
00805   haudio_out_sai.Instance = AUDIO_SAIx;
00806   
00807   /* Disable SAI peripheral to allow access to SAI internal registers */
00808   __HAL_SAI_DISABLE(&haudio_out_sai);
00809   
00810   /* Configure SAI_Block_x 
00811   LSBFirst: Disabled 
00812   DataSize: 16 */
00813   haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE;
00814   haudio_out_sai.Init.Mckdiv = SAIClockDivider(AudioFreq);
00815   haudio_out_sai.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV;
00816   haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX;
00817   haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
00818   haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL;
00819   haudio_out_sai.Init.DataSize = SAI_DATASIZE_16;
00820   haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
00821   haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
00822   haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS;
00823   haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
00824   haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
00825   
00826   /* Configure SAI_Block_x Frame 
00827   Frame Length: 64
00828   Frame active Length: 32
00829   FS Definition: Start frame + Channel Side identification
00830   FS Polarity: FS active Low
00831   FS Offset: FS asserted one bit before the first bit of slot 0 */ 
00832   haudio_out_sai.FrameInit.FrameLength = 64; 
00833   haudio_out_sai.FrameInit.ActiveFrameLength = 32;
00834   haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
00835   haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
00836   haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
00837   
00838   /* Configure SAI Block_x Slot 
00839   Slot First Bit Offset: 0
00840   Slot Size  : 16
00841   Slot Number: 4
00842   Slot Active: All slot actives */
00843   haudio_out_sai.SlotInit.FirstBitOffset = 0;
00844   haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
00845   haudio_out_sai.SlotInit.SlotNumber = 4; 
00846   haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123;
00847 
00848   /* Init the SAI */
00849   SAIx_MspInit();
00850 
00851   HAL_SAI_Init(&haudio_out_sai);
00852   
00853   /* Enable SAI peripheral to generate MCLK */
00854   __HAL_SAI_ENABLE(&haudio_out_sai);
00855 }
00856 
00857 /**
00858   * @brief  Resets the audio codec. It restores the default configuration of the 
00859   *         codec (this function shall be called before initializing the codec).
00860   * @retval None
00861   */
00862 static void CODEC_Reset(void)
00863 {
00864   /* Initialize the audio driver structure */
00865   audio_drv = &wm8994_drv; 
00866   
00867   audio_drv->Reset(AUDIO_I2C_ADDRESS);
00868 }
00869 
00870 /**
00871   * @}
00872   */
00873 
00874 /** @addtogroup STM32L476G_EVAL_AUDIO_Exported_Functions
00875   * @{
00876   */
00877   
00878 /**
00879   * @brief  Initializes wave recording.
00880   * @note   This function assumes that the SAI input clock (through PLL_M)
00881   *         is already configured and ready to be used.  
00882   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral. 
00883   * @param  BitRes: Audio frequency to be configured for the SAI peripheral.
00884   * @param  ChnlNbr: Audio frequency to be configured for the SAI peripheral.
00885   * @retval AUDIO_OK if correct communication, else wrong communication
00886   */
00887 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00888 {
00889   RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct;
00890   uint32_t ret = AUDIO_ERROR;
00891 
00892   /* Store the audio record context */
00893   audio_in_context.Frequency     = AudioFreq;
00894   audio_in_context.BitResolution = BitRes;
00895   audio_in_context.ChannelNbr    = ChnlNbr;
00896   
00897   /* Update the PLL configuration according to the new frequency */
00898   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
00899   {
00900     /* Configure PLLSAI prescalers */
00901     /* SAI clock config 
00902     PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 24 = VCO_192M 
00903     SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 192/17 = 11.294 Mhz */  
00904     RCC_ExCLKInitStruct.PeriphClockSelection    = RCC_PERIPHCLK_SAI1;
00905     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N        = 24; 
00906     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P        = 17; 
00907     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
00908     RCC_ExCLKInitStruct.Sai1ClockSelection      = RCC_SAI1CLKSOURCE_PLLSAI1;
00909     HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct);
00910   }
00911   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
00912   {
00913     /* SAI clock config 
00914     PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 43 = VCO_344M 
00915     SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 344/7 = 49.142 Mhz */  
00916     RCC_ExCLKInitStruct.PeriphClockSelection    = RCC_PERIPHCLK_SAI1;
00917     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N        = 43;
00918     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P        = 7;
00919     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
00920     RCC_ExCLKInitStruct.Sai1ClockSelection      = RCC_SAI1CLKSOURCE_PLLSAI1;
00921     HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct);    
00922   }
00923 
00924   /* SAI data transfer preparation:
00925   Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
00926   ret = DFSDMx_Init(AudioFreq);
00927 
00928   /* Return AUDIO_OK when all operations are correctly done */
00929   return ret;
00930 }
00931 
00932 /**
00933   * @brief  DeInitializes the audio peripheral.
00934   * @retval None
00935   */
00936 void BSP_AUDIO_IN_DeInit(void)
00937 {
00938   DFSDMx_DeInit();
00939 }
00940 
00941 /**
00942   * @brief  Starts audio recording.
00943   * @param  pbuf: Main buffer pointer for the recorded data storing  
00944   * @param  size: Current size of the recorded buffer
00945   * @note   The Right channel is start at first with synchro on start of Left channel
00946   * @retval AUDIO_OK if correct communication, else wrong communication
00947   */
00948 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size)
00949 {
00950   uint8_t ret = AUDIO_ERROR;
00951   
00952   audio_in_context.pRecBuf = pbuf;
00953   audio_in_context.RecSize = size;
00954   /* Reset Application Buffer Trigger */
00955   AppBuffTrigger = 0;
00956   AppBuffHalf = 0;
00957     
00958   if(audio_in_context.ChannelNbr == 2)
00959   {
00960     /* Call the Media layer start function for right channel */
00961     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_rightfilter, (int32_t*)RightRecBuff, INTERNAL_BUFF_SIZE))
00962     {
00963       return ret;
00964     }
00965   }
00966   
00967   /* Call the Media layer start function for left channel */
00968   if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_leftfilter, (int32_t*)LeftRecBuff, INTERNAL_BUFF_SIZE))
00969   {
00970     return ret;
00971   }
00972 
00973   /* Return AUDIO_OK when all operations are correctly done */
00974   ret = AUDIO_OK;
00975   
00976   return ret;
00977 }
00978 
00979 /**
00980   * @brief  Updates the audio frequency.
00981   * @param  AudioFreq: Audio frequency used to record the audio stream.
00982   * @note   This API should be called after the BSP_AUDIO_IN_Init() to adjust the
00983   *         audio frequency.
00984   * @retval AUDIO_OK if correct communication, else wrong communication
00985   */
00986 uint8_t BSP_AUDIO_IN_SetFrequency(uint32_t AudioFreq)
00987 { 
00988   RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct;
00989   
00990   HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct);
00991   
00992   /* Update the PLL configuration according to the new frequency */
00993   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
00994   {
00995     /* Configure PLLSAI prescalers */
00996     /* SAI clock config 
00997     PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 24 = VCO_192M 
00998     SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 192/17 = 11.294 Mhz */  
00999     RCC_ExCLKInitStruct.PeriphClockSelection    = RCC_PERIPHCLK_SAI1;
01000     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N        = 24; 
01001     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P        = 17; 
01002     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
01003     RCC_ExCLKInitStruct.Sai1ClockSelection      = RCC_SAI1CLKSOURCE_PLLSAI1;
01004     HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct);
01005   }
01006   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
01007   {
01008     /* SAI clock config 
01009     PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 43 = VCO_344M 
01010     SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 344/7 = 49.142 Mhz */  
01011     RCC_ExCLKInitStruct.PeriphClockSelection    = RCC_PERIPHCLK_SAI1;
01012     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N        = 43;
01013     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P        = 7;
01014     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
01015     RCC_ExCLKInitStruct.Sai1ClockSelection      = RCC_SAI1CLKSOURCE_PLLSAI1;
01016     HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct);    
01017   }
01018 
01019   /* De-initializes the Digital Filter for Sigma-Delta Modulators interface */
01020   if(AUDIO_OK != DFSDMx_DeInit())
01021   {
01022     return AUDIO_ERROR;
01023   }
01024   
01025   /* Initializes the Digital Filter for Sigma-Delta Modulators interface */
01026   if(AUDIO_OK != DFSDMx_Init(AudioFreq))
01027   {
01028     return AUDIO_ERROR;
01029   }
01030   
01031   /* Return AUDIO_OK when all operations are correctly done */
01032   return AUDIO_OK;
01033 }
01034 
01035 /**
01036   * @brief  Regular conversion complete callback. 
01037   * @note   In interrupt mode, user has to read conversion value in this function
01038             using HAL_DFSDM_FilterGetRegularValue.
01039   * @param  hdfsdm_filter : DFSDM filter handle.
01040   * @retval None
01041   */
01042 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01043 {
01044   uint32_t index;
01045 
01046   /* Stereo Channels treatment */
01047   if(audio_in_context.ChannelNbr == 2)
01048   {
01049     if(hdfsdm_filter == &haudio_in_dfsdm_leftfilter)
01050     {
01051       DmaLeftRecBuffCplt = 1;
01052     }
01053     else
01054     {
01055       DmaRightRecBuffCplt = 1;
01056     }
01057 
01058     if((DmaRightRecBuffCplt == 1) && (DmaLeftRecBuffCplt == 1))
01059     {
01060       if(AppBuffTrigger >= audio_in_context.RecSize)
01061         AppBuffTrigger = 0;
01062 
01063       for(index = (INTERNAL_BUFF_SIZE/2) ; index < INTERNAL_BUFF_SIZE; index++)
01064       {
01065         audio_in_context.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((LeftRecBuff[index] >> 8), -32760, 32760));
01066         audio_in_context.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((RightRecBuff[index] >> 8), -32760, 32760));
01067         AppBuffTrigger += 2;
01068       }
01069       DmaRightRecBuffCplt = DmaLeftRecBuffCplt = 0;
01070     }
01071   }
01072   else /* Mono Channel treatment */
01073   {
01074     for(index = (INTERNAL_BUFF_SIZE/2); index < INTERNAL_BUFF_SIZE; index++)
01075     {
01076       audio_in_context.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((LeftRecBuff[index] >> 8), -32760, 32760));
01077       AppBuffTrigger++;
01078     }
01079   }
01080 
01081   /* Update Trigger with Remaining Byte before callback if necessary */
01082   if(AppBuffTrigger >= audio_in_context.RecSize)
01083   {
01084     /* Reset Application Buffer Trigger */
01085     AppBuffTrigger = 0;
01086     AppBuffHalf = 0;
01087     
01088     /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01089     BSP_AUDIO_IN_TransferComplete_CallBack();
01090   }
01091   else if((AppBuffTrigger >= audio_in_context.RecSize/2))
01092   {
01093      if(AppBuffHalf == 0)
01094      {
01095         AppBuffHalf = 1;
01096         /* Manage the remaining file size and new address offset: This function 
01097            should be coded by user (its prototype is already declared in stm32l476g_eval_audio.h) */
01098         BSP_AUDIO_IN_HalfTransfer_CallBack();
01099      }
01100   }
01101 }
01102 
01103 /**
01104   * @brief  Half regular conversion complete callback. 
01105   * @param  hdfsdm_filter : DFSDM filter handle.
01106   * @retval None
01107   */
01108 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01109 {
01110   uint32_t index;
01111 
01112   /* Stereo Channels treatment */
01113   if(audio_in_context.ChannelNbr == 2)
01114   {
01115     if(hdfsdm_filter == &haudio_in_dfsdm_leftfilter)
01116     {
01117       DmaLeftRecHalfBuffCplt = 1;
01118     }
01119     else
01120     {
01121       DmaRightRecHalfBuffCplt = 1;
01122     }
01123 
01124     if((DmaRightRecHalfBuffCplt == 1) && (DmaLeftRecHalfBuffCplt == 1))
01125     {
01126       if(AppBuffTrigger >= audio_in_context.RecSize)
01127         AppBuffTrigger = 0;
01128 
01129       for(index = 0; index < INTERNAL_BUFF_SIZE/2; index++)
01130       {
01131         audio_in_context.pRecBuf[AppBuffTrigger]     = (int16_t)(SaturaLH((LeftRecBuff[index] >> 8), -32760, 32760));
01132         audio_in_context.pRecBuf[AppBuffTrigger + 1] = (int16_t)(SaturaLH((RightRecBuff[index] >> 8), -32760, 32760));
01133         AppBuffTrigger += 2;
01134       }
01135       DmaRightRecHalfBuffCplt = DmaLeftRecHalfBuffCplt = 0;
01136     }
01137   }
01138   else /* Mono Channel treatment */
01139   {
01140     for(index = 0; index < (INTERNAL_BUFF_SIZE/2); index++)
01141     {
01142       audio_in_context.pRecBuf[AppBuffTrigger]     = (uint16_t)(SaturaLH((LeftRecBuff[index] >> 8), -32760, 32760));
01143       AppBuffTrigger++;
01144     }
01145   }
01146 
01147   /* Update Trigger with Remaining Byte before callback if necessary */
01148   if(AppBuffTrigger >= audio_in_context.RecSize)
01149   {
01150     /* Reset Application Buffer Trigger */
01151     AppBuffTrigger = 0;
01152     AppBuffHalf = 0;
01153     
01154     /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01155     BSP_AUDIO_IN_TransferComplete_CallBack();
01156   }
01157   else if((AppBuffTrigger >= audio_in_context.RecSize/2))
01158   {
01159      if(AppBuffHalf == 0)
01160      {
01161         AppBuffHalf = 1;
01162         /* Manage the remaining file size and new address offset: This function 
01163         should be coded by user (its prototype is already declared in stm32l476g_eval_audio.h) */
01164         BSP_AUDIO_IN_HalfTransfer_CallBack();
01165      }
01166   }
01167 }
01168 
01169 /**
01170   * @brief  Stops audio recording.
01171   * @retval AUDIO_OK if correct communication, else wrong communication
01172   */
01173 uint8_t BSP_AUDIO_IN_Stop(void)
01174 {
01175   uint32_t ret = AUDIO_ERROR;
01176   
01177   AppBuffTrigger = 0;
01178   AppBuffHalf    = 0;
01179   
01180   if(audio_in_context.ChannelNbr == 2)
01181   {
01182     /* Call the Media layer stop function for right channel */
01183     if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_rightfilter))
01184   {
01185     return ret;
01186   }
01187   }
01188   
01189   /* Call the Media layer stop function for left channel */
01190   if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_leftfilter))
01191   {
01192     return ret;
01193   }
01194 
01195   /* Return AUDIO_OK when all operations are correctly done */
01196   ret = AUDIO_OK;
01197   
01198   return ret;
01199 }
01200 
01201 /**
01202   * @brief  Pauses the audio file stream.
01203   * @retval AUDIO_OK if correct communication, else wrong communication
01204   */
01205 uint8_t BSP_AUDIO_IN_Pause(void)
01206 {    
01207   if(audio_in_context.ChannelNbr == 2)
01208   {
01209   /* Call the Media layer stop function */
01210     if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_rightfilter))
01211   {
01212     return AUDIO_ERROR;
01213   }
01214   }
01215   
01216   /* Call the Media layer stop function */
01217   if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_leftfilter))
01218   {
01219     return AUDIO_ERROR;
01220   }
01221   
01222   /* Return AUDIO_OK when all operations are correctly done */
01223   return AUDIO_OK;
01224 }
01225 
01226 /**
01227   * @brief  Resumes the audio file stream.
01228   * @note   The Right channel is start a first with synchro on start Left channel
01229   * @retval AUDIO_OK if correct communication, else wrong communication
01230   */
01231 uint8_t BSP_AUDIO_IN_Resume(void)
01232 {    
01233   uint8_t ret = AUDIO_ERROR;
01234   
01235   if(audio_in_context.ChannelNbr == 2)
01236   {
01237     /* Call the Media layer start function for right channel */
01238     if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_rightfilter, (int32_t*)RightRecBuff, (audio_in_context.RecSize/DEFAULT_AUDIO_IN_CHANNEL_NBR)))
01239     {
01240       return ret;
01241     }
01242   }
01243   
01244   /* Call the Media layer start function for left channel */
01245   if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_leftfilter, (int32_t*)LeftRecBuff, (audio_in_context.RecSize/DEFAULT_AUDIO_IN_CHANNEL_NBR)))
01246   {
01247     return ret;
01248   }
01249   
01250   /* Return AUDIO_OK when all operations are correctly done */
01251   return AUDIO_OK;
01252 }
01253 
01254 /**
01255   * @brief  Controls the audio in volume level. 
01256   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for 
01257   *         Mute and 100 for Max volume level).
01258   * @retval AUDIO_OK if correct communication, else wrong communication
01259   */
01260 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume)
01261 {
01262   /* Set the Global variable AudioInVolume  */
01263   AudioInVolume = Volume; 
01264   
01265   /* Return AUDIO_OK when all operations are correctly done */
01266   return AUDIO_OK;
01267 }
01268 
01269 /**
01270   * @brief  User callback when record buffer is filled.
01271   * @retval None
01272   */
01273 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void)
01274 {
01275   /* This function should be implemented by the user application.
01276      It is called into this driver when the current buffer is filled
01277      to prepare the next buffer pointer and its size. */
01278 }
01279 
01280 /**
01281   * @brief  Manages the DMA Half Transfer complete event.
01282   * @retval None
01283   */
01284 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
01285 { 
01286   /* This function should be implemented by the user application.
01287      It is called into this driver when the current buffer is filled
01288      to prepare the next buffer pointer and its size. */
01289 }
01290 
01291 /**
01292   * @brief  Audio IN Error callback function.
01293   * @retval None
01294   */
01295 __weak void BSP_AUDIO_IN_Error_Callback(void)
01296 {   
01297   /* This function is called when an Interrupt due to transfer error on or peripheral
01298      error occurs. */
01299 }
01300 
01301 /**
01302   * @}
01303   */
01304 
01305 /** @addtogroup STM32L476G_EVAL_AUDIO_Private_Functions
01306   * @{
01307   */
01308 
01309 /*******************************************************************************
01310                             Static Functions
01311 *******************************************************************************/
01312 /**
01313   * @brief  Initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01314   * @param  AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral.
01315   * @retval AUDIO_OK if correct communication, else wrong communication
01316   */
01317 static uint8_t DFSDMx_Init(uint32_t AudioFreq)
01318 {
01319   /*####CHANNEL 4####*/
01320   haudio_in_dfsdm_leftchannel.Init.OutputClock.Activation   = ENABLE;
01321   haudio_in_dfsdm_leftchannel.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
01322   /* Set the DFSDM clock OUT audio frequency configuration */
01323   haudio_in_dfsdm_leftchannel.Init.OutputClock.Divider      = DFSDMClockDivider(AudioFreq);
01324   haudio_in_dfsdm_leftchannel.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
01325   haudio_in_dfsdm_leftchannel.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
01326   haudio_in_dfsdm_leftchannel.Init.Input.Pins               = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
01327   /* Request to sample stable data for LEFT micro on Rising edge */
01328   haudio_in_dfsdm_leftchannel.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_RISING;
01329   haudio_in_dfsdm_leftchannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
01330   haudio_in_dfsdm_leftchannel.Init.Awd.FilterOrder          = DFSDM_CHANNEL_SINC1_ORDER;
01331   haudio_in_dfsdm_leftchannel.Init.Awd.Oversampling         = 10;
01332   haudio_in_dfsdm_leftchannel.Init.Offset                   = 0;
01333   haudio_in_dfsdm_leftchannel.Init.RightBitShift            = DFSDMRightBitShift(AudioFreq);
01334 
01335   haudio_in_dfsdm_leftchannel.Instance                      = DFSDM_Channel4;
01336   if(HAL_DFSDM_ChannelGetState(&haudio_in_dfsdm_leftchannel) == HAL_DFSDM_CHANNEL_STATE_RESET)
01337   {
01338     /* Init the DFSDM Channel */
01339     DFSDMx_ChannelMspInit(&haudio_in_dfsdm_leftchannel);
01340   }
01341 
01342   if(HAL_OK != HAL_DFSDM_ChannelInit(&haudio_in_dfsdm_leftchannel))
01343   {
01344     return AUDIO_ERROR;
01345   }
01346 
01347   /*####CHANNEL 3####*/
01348   haudio_in_dfsdm_rightchannel.Init.OutputClock.Activation   = ENABLE;
01349   haudio_in_dfsdm_rightchannel.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
01350   /* Set the DFSDM clock OUT audio frequency configuration */
01351   haudio_in_dfsdm_rightchannel.Init.OutputClock.Divider      = DFSDMClockDivider(AudioFreq);
01352   haudio_in_dfsdm_rightchannel.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
01353   haudio_in_dfsdm_rightchannel.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
01354   haudio_in_dfsdm_rightchannel.Init.Input.Pins               = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS;
01355   /* Request to sample stable data for RIGHT micro on Falling edge */
01356   haudio_in_dfsdm_rightchannel.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_FALLING;
01357   haudio_in_dfsdm_rightchannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
01358   haudio_in_dfsdm_rightchannel.Init.Awd.FilterOrder          = DFSDM_CHANNEL_SINC1_ORDER;
01359   haudio_in_dfsdm_rightchannel.Init.Awd.Oversampling         = 10;
01360   haudio_in_dfsdm_rightchannel.Init.Offset                   = 0;
01361   haudio_in_dfsdm_rightchannel.Init.RightBitShift            = DFSDMRightBitShift(AudioFreq);
01362 
01363   haudio_in_dfsdm_rightchannel.Instance                      = DFSDM_Channel3;
01364 
01365   if(HAL_DFSDM_ChannelGetState(&haudio_in_dfsdm_rightchannel) == HAL_DFSDM_CHANNEL_STATE_RESET)
01366   {
01367     /* Init the DFSDM Channel */
01368     DFSDMx_ChannelMspInit(&haudio_in_dfsdm_rightchannel);
01369   }
01370 
01371   if(HAL_OK != HAL_DFSDM_ChannelInit(&haudio_in_dfsdm_rightchannel))
01372   {
01373     return AUDIO_ERROR;
01374   }
01375   
01376   /*####FILTER 0####*/
01377   haudio_in_dfsdm_leftfilter.Init.RegularParam.Trigger         = DFSDM_FILTER_SW_TRIGGER;
01378   haudio_in_dfsdm_leftfilter.Init.RegularParam.FastMode        = ENABLE;
01379   haudio_in_dfsdm_leftfilter.Init.RegularParam.DmaMode         = ENABLE;
01380   haudio_in_dfsdm_leftfilter.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
01381   haudio_in_dfsdm_leftfilter.Init.InjectedParam.ScanMode       = DISABLE;
01382   haudio_in_dfsdm_leftfilter.Init.InjectedParam.DmaMode        = DISABLE;
01383   haudio_in_dfsdm_leftfilter.Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO;
01384   haudio_in_dfsdm_leftfilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES;
01385   haudio_in_dfsdm_leftfilter.Init.FilterParam.SincOrder        = DFSDMFilterOrder(AudioFreq);
01386   /* Set the DFSDM Filters Oversampling to have correct sample rate */
01387   haudio_in_dfsdm_leftfilter.Init.FilterParam.Oversampling     = DFSDMOverSampling(AudioFreq);
01388   haudio_in_dfsdm_leftfilter.Init.FilterParam.IntOversampling  = 1;
01389   
01390   haudio_in_dfsdm_leftfilter.Instance                          = AUDIO_DFSDMx_LEFT_FILTER;
01391 
01392   if(HAL_DFSDM_FilterGetState(&haudio_in_dfsdm_leftfilter) == HAL_DFSDM_FILTER_STATE_RESET)
01393   {
01394     /* Init the DFSDM Filter */
01395     DFSDMx_FilterMspInit(&haudio_in_dfsdm_leftfilter);
01396   }
01397 
01398   if(HAL_OK != HAL_DFSDM_FilterInit(&haudio_in_dfsdm_leftfilter))
01399   {
01400     return AUDIO_ERROR;
01401   }
01402   
01403   /* Configure injected channel */
01404   if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&haudio_in_dfsdm_leftfilter, DFSDM_CHANNEL_4, DFSDM_CONTINUOUS_CONV_ON))
01405   {
01406     return AUDIO_ERROR;
01407   }
01408 
01409   /*####FILTER 1####*/
01410   haudio_in_dfsdm_rightfilter.Init.RegularParam.Trigger         = DFSDM_FILTER_SYNC_TRIGGER;
01411   haudio_in_dfsdm_rightfilter.Init.RegularParam.FastMode        = ENABLE;
01412   haudio_in_dfsdm_rightfilter.Init.RegularParam.DmaMode         = ENABLE;
01413   haudio_in_dfsdm_rightfilter.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
01414   haudio_in_dfsdm_rightfilter.Init.InjectedParam.ScanMode       = DISABLE;
01415   haudio_in_dfsdm_rightfilter.Init.InjectedParam.DmaMode        = DISABLE;
01416   haudio_in_dfsdm_rightfilter.Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO;
01417   haudio_in_dfsdm_rightfilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES;
01418   haudio_in_dfsdm_rightfilter.Init.FilterParam.SincOrder        = DFSDMFilterOrder(AudioFreq);
01419   /* Set the DFSDM Filters Oversampling to have correct sample rate */
01420   haudio_in_dfsdm_rightfilter.Init.FilterParam.Oversampling     = DFSDMOverSampling(AudioFreq);
01421   haudio_in_dfsdm_rightfilter.Init.FilterParam.IntOversampling  = 1;
01422   
01423   haudio_in_dfsdm_rightfilter.Instance                          = AUDIO_DFSDMx_RIGHT_FILTER;
01424 
01425   if(HAL_DFSDM_FilterGetState(&haudio_in_dfsdm_rightfilter) == HAL_DFSDM_FILTER_STATE_RESET)
01426   {
01427     /* Init the DFSDM Filter */
01428     DFSDMx_FilterMspInit(&haudio_in_dfsdm_rightfilter);
01429   }
01430 
01431   if(HAL_OK != HAL_DFSDM_FilterInit(&haudio_in_dfsdm_rightfilter))
01432   {
01433     return AUDIO_ERROR;
01434   }
01435   
01436   /* Configure injected channel */
01437   if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&haudio_in_dfsdm_rightfilter, DFSDM_CHANNEL_3, DFSDM_CONTINUOUS_CONV_ON))
01438   {
01439     return AUDIO_ERROR;
01440   }
01441   
01442   return AUDIO_OK;
01443 }
01444 
01445 /**
01446   * @brief  De-initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01447   * @retval AUDIO_OK if correct communication, else wrong communication
01448   */
01449 static uint8_t DFSDMx_DeInit(void)
01450 {
01451   /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */
01452   if(HAL_OK != HAL_DFSDM_FilterDeInit(&haudio_in_dfsdm_leftfilter))
01453   {
01454     return AUDIO_ERROR;
01455   }
01456 
01457   if(HAL_OK != HAL_DFSDM_FilterDeInit(&haudio_in_dfsdm_rightfilter))
01458   {
01459     return AUDIO_ERROR;
01460   }
01461 
01462   DFSDMx_FilterMspDeInit(&haudio_in_dfsdm_leftfilter);
01463   DFSDMx_FilterMspDeInit(&haudio_in_dfsdm_rightfilter);
01464 
01465   /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */
01466   if(HAL_OK != HAL_DFSDM_ChannelDeInit(&haudio_in_dfsdm_leftchannel))
01467   {
01468     return AUDIO_ERROR;
01469   }
01470 
01471   if(HAL_OK != HAL_DFSDM_ChannelDeInit(&haudio_in_dfsdm_rightchannel))
01472   {
01473     return AUDIO_ERROR;
01474   }
01475 
01476   DFSDMx_ChannelMspDeInit(&haudio_in_dfsdm_leftchannel);
01477   DFSDMx_ChannelMspDeInit(&haudio_in_dfsdm_rightchannel);
01478 
01479   return AUDIO_OK;
01480 }
01481 
01482 /**
01483   * @brief  Initializes the DFSDM channel MSP.
01484   * @param  hdfsdm_channel : DFSDM channel handle.
01485   * @retval None
01486   */
01487 static void DFSDMx_ChannelMspInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
01488 {
01489   GPIO_InitTypeDef  GPIO_InitStruct;  
01490 
01491   /* Enable DFSDM clock */
01492   AUDIO_DFSDMx_CLK_ENABLE();
01493   
01494   /* Enable GPIO clock */
01495   AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_CLK_ENABLE();
01496   
01497   /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN pins ------------------*/
01498   GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN | AUDIO_DFSDMx_DMIC_DATIN_PIN;
01499   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
01500   GPIO_InitStruct.Pull = GPIO_NOPULL;
01501   GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
01502   GPIO_InitStruct.Alternate = AUDIO_DFSDMx_CKOUT_DMIC_DATIN_AF;
01503   HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct);
01504 }
01505 
01506 /**
01507   * @brief  DeInitializes the DFSDM channel MSP.
01508   * @param  hdfsdm_channel : DFSDM channel handle.
01509   * @retval None
01510   */
01511 static void DFSDMx_ChannelMspDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
01512 {
01513   GPIO_InitTypeDef  GPIO_InitStruct;  
01514 
01515   /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN pins ------------------*/
01516   GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN | AUDIO_DFSDMx_DMIC_DATIN_PIN;
01517   HAL_GPIO_DeInit(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, GPIO_InitStruct.Pin);
01518 }
01519 
01520 /**
01521   * @brief  Initializes the DFSDM filter MSP.
01522   * @param  hdfsdm_filter : DFSDM filter handle.
01523   * @retval None
01524   */
01525 static void DFSDMx_FilterMspInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01526 {
01527   DMA_HandleTypeDef *hdma_dfsdmReg;
01528   
01529   /* Enable DFSDM clock */
01530   AUDIO_DFSDMx_CLK_ENABLE();
01531   
01532   /* Enable the DMA clock */
01533   AUDIO_DFSDMx_DMAx_CLK_ENABLE();
01534     
01535   if(hdfsdm_filter->Instance == AUDIO_DFSDMx_LEFT_FILTER)
01536   {
01537     hdma_dfsdmReg = &hdma_dfsdm_left;
01538   }
01539   else /* AUDIO_DFSDMx_RIGHT_FILTER */
01540   {
01541     hdma_dfsdmReg = &hdma_dfsdm_right;
01542   }
01543 
01544   /* Configure the hdma_dfsdmReg handle parameters */   
01545   hdma_dfsdmReg->Init.Request             = DMA_REQUEST_0;
01546   hdma_dfsdmReg->Init.Direction           = DMA_PERIPH_TO_MEMORY;
01547   hdma_dfsdmReg->Init.PeriphInc           = DMA_PINC_DISABLE;
01548   hdma_dfsdmReg->Init.MemInc              = DMA_MINC_ENABLE;
01549   hdma_dfsdmReg->Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
01550   hdma_dfsdmReg->Init.MemDataAlignment    = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
01551   hdma_dfsdmReg->Init.Mode                = DMA_CIRCULAR;
01552   hdma_dfsdmReg->Init.Priority            = DMA_PRIORITY_HIGH;
01553   
01554   if(hdfsdm_filter->Instance == AUDIO_DFSDMx_LEFT_FILTER)
01555   {
01556     hdma_dfsdmReg->Instance               = AUDIO_DFSDMx_DMAx_LEFT_CHANNEL;
01557   }
01558   else /* AUDIO_DFSDMx_RIGHT_FILTER */
01559   {
01560     hdma_dfsdmReg->Instance               = AUDIO_DFSDMx_DMAx_RIGHT_CHANNEL;
01561   }
01562   
01563   /* Associate the DMA handle */
01564   __HAL_LINKDMA(hdfsdm_filter, hdmaReg, *hdma_dfsdmReg);
01565   
01566   /* Reset DMA handle state */
01567   __HAL_DMA_RESET_HANDLE_STATE(hdma_dfsdmReg);
01568 
01569   /* Configure the DMA Channel */
01570   HAL_DMA_Init(hdma_dfsdmReg);      
01571 
01572   /* DMA IRQ Channel configuration */
01573   if(hdfsdm_filter->Instance == AUDIO_DFSDMx_LEFT_FILTER)
01574   {
01575     HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_LEFT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
01576     HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_LEFT_IRQ);
01577   }
01578   else /* AUDIO_DFSDMx_RIGHT_FILTER */
01579   {
01580     HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_RIGHT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
01581     HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_RIGHT_IRQ);
01582   }
01583 }
01584 
01585 /**
01586   * @brief  DeInitializes the DFSDM filter MSP.
01587   * @param  hdfsdm_filter : DFSDM filter handle.
01588   * @retval None
01589   */
01590 static void DFSDMx_FilterMspDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01591 {
01592   DMA_HandleTypeDef *hdma_dfsdmReg;
01593   
01594   if(hdfsdm_filter->Instance == AUDIO_DFSDMx_LEFT_FILTER)
01595   {
01596     hdma_dfsdmReg = &hdma_dfsdm_left;
01597   }
01598   else /* AUDIO_DFSDMx_RIGHT_FILTER */
01599   {
01600     hdma_dfsdmReg = &hdma_dfsdm_right;
01601   }
01602 
01603   /* Configure the DMA Channel */
01604   HAL_DMA_DeInit(hdma_dfsdmReg);
01605 }
01606 
01607 /**
01608   * @}
01609   */
01610 
01611 /**
01612   * @}
01613   */
01614 
01615 /**
01616   * @}
01617   */
01618 
01619 /**
01620   * @}
01621   */
01622 
01623 /**
01624   * @}
01625   */
01626 
01627 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Sun Jun 21 2015 23:46:41 for STM32L476G_EVAL BSP User Manual by   doxygen 1.7.6.1