STM32L4R9I_EVAL BSP User Manual: stm32l4r9i_eval_audio.c Source File

STM32L4R9I_EVAL BSP

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