STM32L4R9I-Discovery BSP User Manual: stm32l4r9i_discovery_audio.c Source File

STM32L4R9I-Discovery BSP

stm32l4r9i_discovery_audio.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l4r9i_discovery_audio.c
00004   * @author  MCD Application Team
00005   * @brief   This file provides a set of functions needed to manage the
00006   *          Audio driver for the STM32L4R9I_DISCOVERY board.
00007   ******************************************************************************
00008   * @attention
00009   *
00010   * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
00011   *
00012   * Redistribution and use in source and binary forms, with or without modification,
00013   * are permitted provided that the following conditions are met:
00014   *   1. Redistributions of source code must retain the above copyright notice,
00015   *      this list of conditions and the following disclaimer.
00016   *   2. Redistributions in binary form must reproduce the above copyright notice,
00017   *      this list of conditions and the following disclaimer in the documentation
00018   *      and/or other materials provided with the distribution.
00019   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00020   *      may be used to endorse or promote products derived from this software
00021   *      without specific prior written permission.
00022   *
00023   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00026   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00027   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00028   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00029   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00031   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00032   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033   *
00034   ******************************************************************************
00035   */
00036 
00037 /*==============================================================================
00038                                  User NOTES
00039 
00040 1. How To use this driver:
00041 --------------------------
00042    + This driver supports STM32L4xx devices on STM32L4R9I_DISCOVERY (MB1311) Discovery boards.
00043         a) to play an audio file through headset. All functions names start by BSP_AUDIO_OUT_xxx.
00044         b) to record an audio file through digital microphones (MP34DT01TR ST mems)
00045            or analog microphone (headset microphone). 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 (only OUTPUT_DEVICE_HEADPHONE).
00051                                     Volume      : Initial volume to be set (0 is min (mute), 100 is max (100%)
00052                                     AudioFreq   : Audio frequency in Hz (8000, 16000, 22500, 32000...)
00053                                                   this parameter is relative to the audio file/stream type.
00054                                    )
00055       This function configures all the hardware required for the audio application (codec, I2C, SAI,
00056       GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK.
00057       If the returned value is different from AUDIO_OK or the function is stuck then the communication with
00058       the audio codec has failed.
00059       - OUTPUT_DEVICE_HEADPHONE: only Headphone output is available on this board.
00060 
00061    + Call the function BSP_AUDIO_OUT_RegisterCallbacks to register user callbacks
00062      required to manage audio data streaming towards the audio codec (ErrorCallback(),
00063      HalfTransfer_CallBack() and TransferComplete_CallBack()).
00064 
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_discovery_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_discovery_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_InitEx(
00102                                     InputDevice: physical input mode (INPUT_DEVICE_DIGITAL_MIC
00103                                                   INPUT_DEVICE_DIGITAL_MIC1, INPUT_DEVICE_DIGITAL_MIC2
00104                                                   or INPUT_DEVICE_ANALOG_MIC)
00105                                     AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...)
00106                                     )
00107       This function configures all the hardware required for the audio application (DFSDM or SAI,
00108       GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if the
00109       configuration completes successfully.
00110       - INPUT_DEVICE_DIGITAL_MIC: Record from digital microphones mounted on board.
00111       - INPUT_DEVICE_DIGITAL_MIC1: Record from digital microphone 1 mounted on board (left microphone).
00112       - INPUT_DEVICE_DIGITAL_MIC2: Record from digital microphone 2 mounted on board (right microphone).
00113       - INPUT_DEVICE_ANALOG_MIC: Record from headset microphone.
00114 
00115    + Call the function BSP_AUDIO_IN_RegisterCallbacks to register user callbacks
00116      used to stream audio data toward the record buffer (ErrorCallback(),
00117      HalfTransfer_CallBack() and TransferComplete_CallBack()).
00118 
00119    + Call the function BSP_AUDIO_IN_Record(
00120                             pbuf Main buffer pointer for the recorded data storing
00121                             size Current size of the recorded buffer
00122                             )
00123       to start recording from the microphone.
00124 
00125    + Call the function BSP_AUDIO_IN_Stop() to stop recording.
00126 ==============================================================================*/
00127 
00128 /* Includes ------------------------------------------------------------------*/
00129 #include <string.h>
00130 #include "stm32l4r9i_discovery_audio.h"
00131 
00132 /** @addtogroup BSP
00133   * @{
00134   */
00135 
00136 /** @addtogroup STM32L4R9I_DISCOVERY
00137   * @{
00138   */
00139 
00140 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO STM32L4R9I_DISCOVERY AUDIO
00141   * @brief This file includes the low layer driver for cs42l51 Audio Codec
00142   *        available on STM32L4R9I_DISCOVERY board (MB1311).
00143   * @{
00144   */
00145 
00146 /* Private typedef -----------------------------------------------------------*/
00147 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Private_Types Private Types
00148   * @{
00149   */
00150 typedef struct
00151 {
00152   AUDIO_DrvTypeDef *    AudioDrv;           /* Audio codec driver */
00153   uint32_t              OutputDevice;       /* Output device */
00154   uint32_t              Frequency;          /* Playback frequency */
00155   uint32_t              Volume;             /* Playback volume */
00156   Audio_CallbackTypeDef CbError;            /* pointer to the callback function invoked when error occurs */
00157   Audio_CallbackTypeDef CbHalfTransfer;     /* pointer to the callback function invoked when half transfer occurs */
00158   Audio_CallbackTypeDef CbTransferComplete; /* pointer to the callback function invoked when transfer complete occurs */
00159 } AUDIO_OUT_TypeDef;
00160 
00161 typedef struct
00162 {
00163   AUDIO_DrvTypeDef *          AudioDrv;           /* Audio codec driver */
00164   DFSDM_Channel_HandleTypeDef hDfsdmLeftChannel;  /* DFSDM channel handle used for left channel */
00165   DFSDM_Channel_HandleTypeDef hDfsdmRightChannel; /* DFSDM channel handle used for right channel */
00166   DMA_HandleTypeDef           hDmaDfsdmLeft;      /* DMA handle used for DFSDM regular conversions on left channel */
00167   DMA_HandleTypeDef           hDmaDfsdmRight;     /* DMA handle used for DFSDM regular conversions on right channel */
00168   int32_t *                   LeftRecBuff;        /* Buffers for left samples */
00169   int32_t *                   RightRecBuff;       /* Buffers for right samples */
00170   uint32_t                    InputDevice;        /* Input device */
00171   uint32_t                    Frequency;          /* Record Frequency */
00172   uint32_t                    BitResolution;      /* Record bit resolution */
00173   uint32_t                    ChannelNbr;         /* Record Channel Number */
00174   uint16_t *                  pRecBuf;            /* Pointer to record user buffer */
00175   uint32_t                    RecSize;            /* Size to record in mono, double size to record in stereo */
00176   Audio_CallbackTypeDef       CbError;            /* pointer to the callback function invoked when a DMA transfer fails */
00177   Audio_CallbackTypeDef       CbHalfTransfer;     /* pointer to the callback function invoked when half of the DMA transfer is completed */
00178   Audio_CallbackTypeDef       CbTransferComplete; /* pointer to the callback function invoked when the DMA transfer is completed */
00179 } AUDIO_IN_TypeDef;
00180 
00181 /**
00182   * @}
00183   */
00184 
00185 /* Private macros ------------------------------------------------------------*/
00186 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Private_Macros Private Macros
00187   * @{
00188   */
00189 /*### PLAY ###*/
00190 /* SCK(kHz) = SAI_CK_x/(SAIClockDivider*2*256) */
00191 #define SAIClockDivider(__FREQUENCY__) \
00192         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 24 \
00193       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \
00194       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 12 \
00195       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 2 \
00196       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 6 \
00197       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 1 \
00198       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 4 : 2  \
00199 
00200 /*### RECORD ###*/
00201 #define DFSDMOverSampling(__FREQUENCY__) \
00202         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 256 \
00203       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \
00204       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \
00205       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \
00206       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \
00207       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64  \
00208       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 16  \
00209 
00210 #define DFSDMClockDivider(__FREQUENCY__) \
00211         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 24 \
00212       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \
00213       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \
00214       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
00215       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \
00216       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4  \
00217       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 32  \
00218 
00219 #define DFSDMFilterOrder(__FREQUENCY__) \
00220         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? DFSDM_FILTER_SINC3_ORDER \
00221       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \
00222       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \
00223       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \
00224       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \
00225       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC4_ORDER  \
00226       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC4_ORDER : DFSDM_FILTER_SINC5_ORDER  \
00227 
00228 #define DFSDMRightBitShift(__FREQUENCY__) \
00229         (__FREQUENCY__ == AUDIO_FREQUENCY_8K)  ? 7 \
00230       : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 7 \
00231       : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 4 \
00232       : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
00233       : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 7 \
00234       : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 7  \
00235       : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 3 : 4  \
00236 
00237 /* Saturate the record PCM sample */
00238 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N)))
00239 
00240 /**
00241   * @}
00242   */
00243 
00244 /* Private variables ---------------------------------------------------------*/
00245 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Private_Variables Private Variables
00246   * @{
00247   */
00248 /* Audio output context information */
00249 static AUDIO_OUT_TypeDef hAudioOut = {0};
00250 
00251 /* Audio input context information */
00252 static AUDIO_IN_TypeDef hAudioIn = {0};
00253 
00254 /* SAI DMA handle */
00255 static DMA_HandleTypeDef hDmaSaiTx;
00256 static DMA_HandleTypeDef hDmaSaiRx;
00257 
00258 static uint32_t DmaLeftRecHalfBuffCplt;
00259 static uint32_t DmaLeftRecBuffCplt;
00260 static uint32_t DmaRightRecHalfBuffCplt;
00261 static uint32_t DmaRightRecBuffCplt;
00262 
00263 /**
00264   * @}
00265   */
00266 
00267 /* Exported variables ---------------------------------------------------------*/
00268 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Exported_Variables Exported Variables
00269   * @{
00270   */
00271 /* SAIx handle */
00272 SAI_HandleTypeDef               BSP_AUDIO_hSai_Tx;
00273 SAI_HandleTypeDef               BSP_AUDIO_hSai_Rx;
00274 
00275 /* DFSDM filter handle */
00276 DFSDM_Filter_HandleTypeDef      BSP_AUDIO_hDfsdmLeftFilter;
00277 DFSDM_Filter_HandleTypeDef      BSP_AUDIO_hDfsdmRightFilter;
00278 /**
00279   * @}
00280   */
00281 
00282 /* Private function prototypes -----------------------------------------------*/
00283 /** @defgroup STM32L4R9I_DISCOVERY_AUDIO_Private_Functions Private Functions
00284   * @{
00285   */
00286 static uint8_t AUDIO_SAIx_Init(uint32_t AudioFreq);
00287 static uint8_t AUDIO_SAIx_DeInit(void);
00288 static uint8_t AUDIO_DFSDMx_Init(uint32_t AudioFreq);
00289 static uint8_t AUDIO_DFSDMx_DeInit(void);
00290 static uint8_t AUDIO_SAIPLLConfig(uint32_t AudioFreq);
00291 /**
00292   * @}
00293   */
00294 
00295 /* Exported functions --------------------------------------------------------*/
00296 /** @addtogroup STM32L4R9I_DISCOVERY_AUDIO_Exported_Functions
00297   * @{
00298   */
00299 
00300 /**
00301   * @brief  Configures the audio codec related peripherals.
00302   * @param  OutputDevice: OUTPUT_DEVICE_HEADPHONE.
00303   * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
00304   * @param  AudioFreq: Audio frequency used to play the audio stream.
00305   * @retval BSP AUDIO status
00306   * @note   The SAI PLL input clock must be configure in the user application.
00307   *         The SAI PLL configuration done within this function assumes that
00308   *         the SAI PLL input clock runs at 8 MHz.
00309   */
00310 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice,
00311                            uint8_t  Volume,
00312                            uint32_t AudioFreq)
00313 {
00314   /* Initialize the audio output context */
00315   hAudioOut.AudioDrv           = &cs42l51_drv;
00316   hAudioOut.OutputDevice       = OutputDevice;
00317   hAudioOut.Frequency          = AudioFreq;
00318   hAudioOut.Volume             = Volume;
00319   hAudioOut.CbError            = (Audio_CallbackTypeDef)NULL;
00320   hAudioOut.CbHalfTransfer     = (Audio_CallbackTypeDef)NULL;
00321   hAudioOut.CbTransferComplete = (Audio_CallbackTypeDef)NULL;
00322 
00323   /* Check if input device is currently used */
00324   if(hAudioIn.InputDevice != 0)
00325   {
00326     /* If input device is currently used, SAI PLL is already initialized */
00327     /* Check that AudioFreq for record and playback is the same */
00328     if(hAudioIn.Frequency != hAudioOut.Frequency)
00329     {
00330       return AUDIO_ERROR;
00331     }
00332   }
00333   else
00334   {
00335     /* Configure the SAI PLL according to the requested audio frequency */
00336     if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK)
00337     {
00338       return AUDIO_ERROR;
00339     }
00340   }
00341 
00342   /* If input device is analogic mic, SAI is already initialized */
00343   if(hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
00344   {
00345     /* SAI data transfer preparation: prepare the Media to be used for the audio
00346     transfer from memory to SAI peripheral. */
00347     if (AUDIO_SAIx_Init(AudioFreq) != AUDIO_OK)
00348     {
00349       return AUDIO_ERROR;
00350     }
00351   }
00352 
00353   /* Initialize the audio codec internal registers */
00354   if (hAudioOut.AudioDrv->Init(AUDIO_I2C_ADDRESS,
00355                                (hAudioOut.OutputDevice | hAudioIn.InputDevice),
00356                                Volume,
00357                                AudioFreq) != 0)
00358   {
00359     return AUDIO_ERROR;
00360   }
00361 
00362   return AUDIO_OK;
00363 }
00364 
00365 /**
00366   * @brief  De-Initializes audio codec related peripherals
00367   * @retval BSP AUDIO status
00368 
00369   */
00370 uint8_t BSP_AUDIO_OUT_DeInit(void)
00371 {
00372   if(hAudioIn.InputDevice == INPUT_DEVICE_ANALOG_MIC)
00373   {
00374     /* Reset playback path on audio codec */
00375     if(hAudioIn.AudioDrv->Init(AUDIO_I2C_ADDRESS,
00376                                hAudioIn.InputDevice,
00377                                (uint8_t) hAudioOut.Volume,
00378                                hAudioIn.Frequency) != 0)
00379     {
00380       return AUDIO_ERROR;
00381     }
00382   }
00383   else
00384   {
00385     /* De-initializes SAI interface */
00386     if(AUDIO_SAIx_DeInit() != AUDIO_OK)
00387     {
00388       return AUDIO_ERROR;
00389     }
00390 
00391     /* DeInit audio codec */
00392     hAudioOut.AudioDrv->DeInit();
00393   }
00394 
00395   /* Disable SAI PLL if no more device is used */
00396   if(hAudioIn.InputDevice == 0)
00397   {
00398     if (AUDIO_SAIx_PLL_DISABLE() != AUDIO_OK)
00399     {
00400       return AUDIO_ERROR;
00401     }
00402   }
00403 
00404   /* Reset the audio output context */
00405   memset(&hAudioOut, 0, sizeof(hAudioOut));
00406 
00407   return AUDIO_OK;
00408 }
00409 
00410 /**
00411   * @brief  Starts playing audio stream from a data buffer for a determined size.
00412   * @param  pData: pointer on PCM samples buffer
00413   * @param  Size: Number of audio data HALF WORD.
00414   * @retval BSP AUDIO status
00415   */
00416 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pData, uint32_t Size)
00417 {
00418   /* Initiate a DMA transfer of PCM samples towards the serial audio interface */
00419   if (HAL_SAI_Transmit_DMA(&BSP_AUDIO_hSai_Tx, (uint8_t *)pData, DMA_MAX(Size))!= HAL_OK)
00420   {
00421     return AUDIO_ERROR;
00422   }
00423 
00424   /* Call the audio Codec Play function */
00425   if (hAudioOut.AudioDrv->Play(AUDIO_I2C_ADDRESS, pData, Size) != 0)
00426   {
00427     return AUDIO_ERROR;
00428   }
00429 
00430   return AUDIO_OK;
00431   }
00432 
00433 /**
00434   * @brief  Sends n-Bytes on the SAI interface.
00435   * @param  pData: pointer on PCM samples buffer
00436   * @param  Size: number of data to be written
00437   * @retval BSP AUDIO status
00438   */
00439 uint8_t BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size)
00440 {
00441   /* Initiate a DMA transfer of PCM samples towards the serial audio interface */
00442   if (HAL_SAI_Transmit_DMA(&BSP_AUDIO_hSai_Tx, (uint8_t *)pData, Size)!= HAL_OK)
00443   {
00444     return AUDIO_ERROR;
00445   }
00446 
00447   return AUDIO_OK;
00448 }
00449 
00450 /**
00451   * @brief  This function Pauses the audio file stream. In case
00452   *         of using DMA, the DMA Pause feature is used.
00453   * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only
00454   *       BSP_AUDIO_OUT_Resume() function should be called for resume
00455   *       (use of BSP_AUDIO_OUT_Play() function for resume could lead
00456   *       to unexpected behavior).
00457   * @retval BSP AUDIO status
00458   */
00459 uint8_t BSP_AUDIO_OUT_Pause(void)
00460 {
00461   /* Call the Audio Codec Pause function */
00462   if (hAudioOut.AudioDrv->Pause(AUDIO_I2C_ADDRESS) != 0)
00463   {
00464     return AUDIO_ERROR;
00465   }
00466 
00467   /* Pause DMA transfer of PCM samples towards the serial audio interface */
00468   if (HAL_SAI_DMAPause(&BSP_AUDIO_hSai_Tx)!= HAL_OK)
00469   {
00470     return AUDIO_ERROR;
00471   }
00472 
00473   return AUDIO_OK;
00474 }
00475 
00476 /**
00477   * @brief  This function  Resumes the audio file stream.
00478   * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only
00479   *       BSP_AUDIO_OUT_Resume() function should be called for resume
00480   *       (use of BSP_AUDIO_OUT_Play() function for resume could lead to
00481   *       unexpected behavior).
00482   * @retval BSP AUDIO status
00483   */
00484 uint8_t BSP_AUDIO_OUT_Resume(void)
00485 {
00486   /* Call the Audio Codec Resume function */
00487   if (hAudioOut.AudioDrv->Resume(AUDIO_I2C_ADDRESS) != 0)
00488   {
00489     return AUDIO_ERROR;
00490   }
00491 
00492   /* Resume DMA transfer of PCM samples towards the serial audio interface */
00493   if (HAL_SAI_DMAResume(&BSP_AUDIO_hSai_Tx)!= HAL_OK)
00494   {
00495     return AUDIO_ERROR;
00496   }
00497 
00498   return AUDIO_OK;
00499 }
00500 
00501 /**
00502   * @brief  Stops audio playing and Power down the Audio Codec.
00503   * @param  Option: could be one of the following parameters
00504   *           - CODEC_PDWN_SW: for software power off (by writing registers).
00505   *                            Then no need to reconfigure the Codec after power on.
00506   *           - CODEC_PDWN_HW: completely shut down the codec (physically).
00507   *                            Then need to reconfigure the Codec after power on.
00508   * @retval BSP AUDIO status
00509   */
00510 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
00511 {
00512   /* Prevent unused argument(s) compilation warning */
00513   UNUSED(Option);
00514 
00515   /* Call Audio Codec Stop function */
00516   if (hAudioOut.AudioDrv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
00517   {
00518     return AUDIO_ERROR;
00519   }
00520 
00521   /* Wait at least 100ms */
00522   HAL_Delay(100);
00523 
00524   /* Stop DMA transfer of PCM samples towards the serial audio interface */
00525   if (HAL_SAI_DMAStop(&BSP_AUDIO_hSai_Tx)!= HAL_OK)
00526   {
00527     return AUDIO_ERROR;
00528   }
00529 
00530   return AUDIO_OK;
00531 }
00532 
00533 /**
00534   * @brief  Controls the current audio volume level.
00535   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for
00536   *         Mute and 100 for Max volume level).
00537   * @retval BSP AUDIO status
00538   */
00539 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume)
00540 {
00541   /* Call the codec volume control function with converted volume value */
00542   if (hAudioOut.AudioDrv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
00543   {
00544     return AUDIO_ERROR;
00545   }
00546 
00547   hAudioOut.Volume = Volume;
00548 
00549   return AUDIO_OK;
00550 }
00551 
00552 /**
00553   * @brief  Enables or disables the MUTE mode by software
00554   * @param  Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to
00555   *         unmute the codec and restore previous volume level.
00556   * @retval BSP AUDIO status
00557   */
00558 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd)
00559 {
00560   /* Call the Codec Mute function */
00561   if (hAudioOut.AudioDrv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0)
00562   {
00563     return AUDIO_ERROR;
00564   }
00565 
00566   return AUDIO_OK;
00567 }
00568 
00569 /**
00570   * @brief  Switch dynamically (while audio file is being played) the output
00571   *          target (speaker or headphone).
00572   * @param  Output: The audio output target: OUTPUT_DEVICE_SPEAKER,
00573   *         OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH
00574   * @retval BSP AUDIO status
00575   */
00576 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)
00577 {
00578   /* Call the Codec output device function */
00579   if (hAudioOut.AudioDrv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0)
00580   {
00581     return AUDIO_ERROR;
00582   }
00583 
00584   return AUDIO_OK;
00585 }
00586 
00587 /**
00588   * @brief  Updates the audio frequency.
00589   * @param  AudioFreq: Audio frequency used to play the audio stream.
00590   * @note   The SAI PLL input clock must be configure in the user application.
00591   *         The SAI PLL configuration done within this function assumes that
00592   *         the SAI PLL input clock runs at 8 MHz.
00593   * @retval BSP AUDIO status
00594   */
00595 uint8_t BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)
00596 {
00597   uint8_t TxData[2] = {0x00, 0x00};
00598 
00599   /* Configure the SAI PLL according to the requested audio frequency */
00600   if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK)
00601   {
00602     return AUDIO_ERROR;
00603   }
00604 
00605   /* Disable SAI peripheral to allow access to SAI internal registers */
00606   __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx);
00607   __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Rx);
00608 
00609   /* Update the SAI audio frequency configuration */
00610   BSP_AUDIO_hSai_Tx.Init.Mckdiv = SAIClockDivider(AudioFreq);
00611   HAL_SAI_Init(&BSP_AUDIO_hSai_Tx);
00612   BSP_AUDIO_hSai_Rx.Init.Mckdiv = SAIClockDivider(AudioFreq);
00613   HAL_SAI_Init(&BSP_AUDIO_hSai_Rx);
00614 
00615   /* Enable SAI peripheral to generate MCLK */
00616   __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx);
00617   /* Transmit one byte to start FS generation */
00618   if(HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000) != HAL_OK)
00619   {
00620     return AUDIO_ERROR;
00621   }
00622 
00623   hAudioOut.Frequency = AudioFreq;
00624 
00625   return AUDIO_OK;
00626 }
00627 
00628 /**
00629   * @brief  Changes the Audio Out Configuration.
00630   * @param  AudioOutOption: specifies the audio out new configuration
00631   *         This parameter can be any value of @ref BSP_Audio_Out_Option
00632   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00633   *         audio out configuration.
00634   * @retval None
00635   */
00636 void BSP_AUDIO_OUT_ChangeAudioConfig(uint32_t AudioOutOption)
00637 {
00638   uint8_t TxData[2] = {0x00, 0x00};
00639 
00640   /********** Playback Buffer circular/normal mode **********/
00641   if(AudioOutOption & BSP_AUDIO_OUT_CIRCULARMODE)
00642   {
00643     /* Deinitialize the Stream to update DMA mode */
00644     HAL_DMA_DeInit(BSP_AUDIO_hSai_Tx.hdmatx);
00645 
00646     /* Update the SAI audio Transfer DMA mode */
00647     BSP_AUDIO_hSai_Tx.hdmatx->Init.Mode = DMA_CIRCULAR;
00648 
00649     /* Configure the DMA Stream with new Transfer DMA mode */
00650     HAL_DMA_Init(BSP_AUDIO_hSai_Tx.hdmatx);
00651   }
00652   else /* BSP_AUDIO_OUT_NORMALMODE */
00653   {
00654     /* Deinitialize the Stream to update DMA mode */
00655     HAL_DMA_DeInit(BSP_AUDIO_hSai_Tx.hdmatx);
00656 
00657     /* Update the SAI audio Transfer DMA mode */
00658     BSP_AUDIO_hSai_Tx.hdmatx->Init.Mode = DMA_NORMAL;
00659 
00660     /* Configure the DMA Stream with new Transfer DMA mode */
00661     HAL_DMA_Init(BSP_AUDIO_hSai_Tx.hdmatx);
00662   }
00663 
00664   /********** Playback Buffer stereo/mono mode **********/
00665   if(AudioOutOption & BSP_AUDIO_OUT_STEREOMODE)
00666   {
00667     /* Disable SAI peripheral to allow access to SAI internal registers */
00668     __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx);
00669 
00670     /* Update the SAI audio frame slot configuration */
00671     BSP_AUDIO_hSai_Tx.Init.MonoStereoMode = SAI_STEREOMODE;
00672     HAL_SAI_Init(&BSP_AUDIO_hSai_Tx);
00673 
00674     /* Enable SAI peripheral to generate MCLK */
00675     __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx);
00676     /* Transmit one byte to start FS generation */
00677     HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000);
00678   }
00679   else /* BSP_AUDIO_OUT_MONOMODE */
00680   {
00681     /* Disable SAI peripheral to allow access to SAI internal registers */
00682     __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx);
00683 
00684     /* Update the SAI audio frame slot configuration */
00685     BSP_AUDIO_hSai_Tx.Init.MonoStereoMode = SAI_MONOMODE;
00686     HAL_SAI_Init(&BSP_AUDIO_hSai_Tx);
00687 
00688     /* Enable SAI peripheral to generate MCLK */
00689     __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx);
00690     /* Transmit one byte to start FS generation */
00691     HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000);
00692   }
00693 }
00694 
00695 /**
00696   * @brief  register user callback functions
00697   * @param  ErrorCallback: pointer to the error callback function
00698   * @param  HalfTransferCallback: pointer to the half transfer callback function
00699   * @param  TransferCompleteCallback: pointer to the transfer complete callback function
00700   * @retval None
00701   */
00702 void BSP_AUDIO_OUT_RegisterCallbacks(Audio_CallbackTypeDef ErrorCallback,
00703                                      Audio_CallbackTypeDef HalfTransferCallback,
00704                                      Audio_CallbackTypeDef TransferCompleteCallback)
00705 {
00706   hAudioOut.CbError            = ErrorCallback;
00707   hAudioOut.CbHalfTransfer     = HalfTransferCallback;
00708   hAudioOut.CbTransferComplete = TransferCompleteCallback;
00709 }
00710 
00711 /**
00712   * @brief  Tx Transfer completed callbacks.
00713   * @param  hsai: SAI handle
00714   * @retval None
00715   */
00716 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
00717 {
00718   /* Invoke the registered 'TransferComplete' function (if any) */
00719   if (hAudioOut.CbTransferComplete != (Audio_CallbackTypeDef)NULL)
00720   {
00721     hAudioOut.CbTransferComplete();
00722   }
00723 }
00724 
00725 /**
00726   * @brief  Tx Half Transfer completed callbacks.
00727   * @param  hsai: SAI handle
00728   * @retval None
00729   */
00730 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
00731 {
00732   /* Invoke the registered 'HalfTransfer' callback function (if any) */
00733   if (hAudioOut.CbHalfTransfer != (Audio_CallbackTypeDef)NULL)
00734   {
00735     hAudioOut.CbHalfTransfer();
00736   }
00737 }
00738 
00739 /**
00740   * @brief  SAI error callbacks.
00741   * @param  hsai: SAI handle
00742   * @retval None
00743   */
00744 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
00745 {
00746   /* Invoke the registered 'ErrorCallback' callback function (if any) */
00747   if (hAudioOut.CbError != (Audio_CallbackTypeDef)NULL)
00748   {
00749     hAudioOut.CbError();
00750   }
00751   /* Invoke the registered 'ErrorCallback' callback function (if any) */
00752   if (hAudioIn.CbError != (Audio_CallbackTypeDef)NULL)
00753   {
00754     hAudioIn.CbError();
00755   }
00756 }
00757 
00758 /**
00759   * @}
00760   */
00761 
00762 /** @addtogroup STM32L4R9I_DISCOVERY_AUDIO_Exported_Functions
00763   * @{
00764   */
00765 
00766 /**
00767   * @brief  Initializes micropone related peripherals.
00768   * @note   This function assumes that the SAI input clock (through PLL_M)
00769   *         is already configured and ready to be used.
00770   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00771   * @param  BitRes: Audio frequency to be configured for the SAI peripheral.
00772   * @param  ChnlNbr: Audio frequency to be configured for the SAI peripheral.
00773   * @retval BSP AUDIO status
00774   */
00775 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00776 {
00777   return BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC, AudioFreq, BitRes, ChnlNbr);
00778 }
00779 
00780 /**
00781   * @brief  Initialize wave recording.
00782   * @param  InputDevice: INPUT_DEVICE_DIGITAL_MIC, INPUT_DEVICE_DIGITAL_MIC1,
00783   *                      INPUT_DEVICE_DIGITAL_MIC2 or INPUT_DEVICE_ANALOG_MIC.
00784   * @param  AudioFreq: Audio frequency to be configured.
00785   * @param  BitRes: Audio bit resolution to be configured..
00786   * @param  ChnlNbr: Number of channel to be configured.
00787   * @retval AUDIO_OK if correct communication, else wrong communication
00788   */
00789 uint8_t BSP_AUDIO_IN_InitEx(uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00790 {
00791   /* Update the audio input context */
00792   hAudioIn.AudioDrv           = &cs42l51_drv;
00793   hAudioIn.InputDevice        = InputDevice;
00794   hAudioIn.Frequency          = AudioFreq;
00795   hAudioIn.BitResolution      = BitRes;
00796   hAudioIn.ChannelNbr         = ChnlNbr;
00797   hAudioIn.CbError            = (Audio_CallbackTypeDef)NULL;
00798   hAudioIn.CbHalfTransfer     = (Audio_CallbackTypeDef)NULL;
00799   hAudioIn.CbTransferComplete = (Audio_CallbackTypeDef)NULL;
00800 
00801   /* Check channel number according device : only record mono with analog mic and stereo with digital mic are allowed */
00802   if(((InputDevice == INPUT_DEVICE_DIGITAL_MIC) && (ChnlNbr == 1)) ||
00803      ((InputDevice == INPUT_DEVICE_DIGITAL_MIC1) && (ChnlNbr == 2)) ||
00804      ((InputDevice == INPUT_DEVICE_DIGITAL_MIC2) && (ChnlNbr == 2)) ||
00805      ((InputDevice == INPUT_DEVICE_ANALOG_MIC) && (ChnlNbr == 2)))
00806   {
00807     return AUDIO_ERROR;
00808   }
00809 
00810   /* Check if output device is currently used */
00811   if(hAudioOut.OutputDevice != 0)
00812   {
00813     /* If output device is currently used, SAI PLL is already initialized */
00814     /* Check that AudioFreq for record and playback is the same */
00815     if(hAudioIn.Frequency != hAudioOut.Frequency)
00816     {
00817       return AUDIO_ERROR;
00818     }
00819   }
00820   else
00821   {
00822     /* Configure the SAI PLL according to the requested audio frequency */
00823     if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK)
00824     {
00825       return AUDIO_ERROR;
00826     }
00827   }
00828 
00829   if(InputDevice != INPUT_DEVICE_ANALOG_MIC)
00830   {
00831     /* Initializes the Digital Filter for Sigma-Delta Modulators interface */
00832     if(AUDIO_DFSDMx_Init(AudioFreq) != AUDIO_OK)
00833     {
00834       return AUDIO_ERROR;
00835     }
00836   }
00837   else
00838   { /* INPUT_DEVICE_ANALOG_MIC */
00839     /* If output device is currently used, SAI is already initialized */
00840     if(hAudioOut.OutputDevice == 0)
00841     {
00842       /* SAI data transfer preparation: prepare the Media to be used for the audio
00843       transfer from SAI peripheral to memory. */
00844       if(AUDIO_SAIx_Init(AudioFreq) != AUDIO_OK)
00845       {
00846         return AUDIO_ERROR;
00847       }
00848     }
00849 
00850     /* Initialize the audio codec internal registers */
00851     if(hAudioIn.AudioDrv->Init(AUDIO_I2C_ADDRESS,
00852                                (hAudioOut.OutputDevice | hAudioIn.InputDevice),
00853                                hAudioOut.Volume,
00854                                AudioFreq) != 0)
00855     {
00856       return AUDIO_ERROR;
00857     }
00858   }
00859 
00860   /* Initialise transfer control flag */
00861   DmaLeftRecHalfBuffCplt  = 0;
00862   DmaLeftRecBuffCplt      = 0;
00863   DmaRightRecHalfBuffCplt = 0;
00864   DmaRightRecBuffCplt     = 0;
00865 
00866   return AUDIO_OK;
00867 }
00868 
00869 /**
00870   * @brief  De-Initializes microphone related peripherals.
00871   * @retval BSP AUDIO status
00872 
00873   */
00874 uint8_t BSP_AUDIO_IN_DeInit(void)
00875 {
00876   if(hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
00877   {
00878     /* De-initializes the Digital Filter for Sigma-Delta Modulators interface */
00879     if (AUDIO_DFSDMx_DeInit() != AUDIO_OK)
00880     {
00881       return AUDIO_ERROR;
00882     }
00883   }
00884   else
00885   { /* INPUT_DEVICE_ANALOG_MIC */
00886     /* Check if output device is currently used */
00887     if(hAudioOut.OutputDevice != 0)
00888     {
00889       /* Reset record path on audio codec */
00890       if(hAudioOut.AudioDrv->Init(AUDIO_I2C_ADDRESS,
00891                                  hAudioOut.OutputDevice,
00892                                  (uint8_t) hAudioOut.Volume,
00893                                  hAudioOut.Frequency) != 0)
00894       {
00895         return AUDIO_ERROR;
00896       }
00897     }
00898     else
00899     {
00900       /* De-initializes SAI interface */
00901       if(AUDIO_SAIx_DeInit() != AUDIO_OK)
00902       {
00903         return AUDIO_ERROR;
00904       }
00905 
00906       /* DeInit audio codec */
00907       hAudioIn.AudioDrv->DeInit();
00908     }
00909   }
00910 
00911   /* Disable SAI PLL if no more device is used */
00912   if(hAudioOut.OutputDevice == 0)
00913   {
00914     if (AUDIO_SAIx_PLL_DISABLE() != AUDIO_OK)
00915     {
00916       return AUDIO_ERROR;
00917     }
00918   }
00919 
00920   /* Reset the audio input context */
00921   memset(&hAudioIn, 0, sizeof(hAudioIn));
00922 
00923   return AUDIO_OK;
00924 }
00925 
00926 /**
00927   * @brief  Starts audio recording.
00928   * @param  pbuf: Main buffer pointer for the recorded data storing
00929   * @param  size: Current size of the recorded buffer
00930   * @note   The Right channel is start at first with synchro on start of Left channel
00931   * @retval BSP AUDIO status
00932   */
00933 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size)
00934 {
00935   hAudioIn.pRecBuf = pbuf;
00936   hAudioIn.RecSize = size;
00937 
00938 
00939   if(hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
00940   {
00941     if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
00942     {
00943       /* Allocate hAudioIn.LeftRecBuff buffer */
00944 #if defined(BSP_AUDIO_USE_RTOS)
00945       hAudioIn.LeftRecBuff  = (int32_t *)k_malloc((size / hAudioIn.ChannelNbr) * sizeof(int32_t));
00946 #else
00947       hAudioIn.LeftRecBuff  = (int32_t *)malloc((size / hAudioIn.ChannelNbr) * sizeof(int32_t));
00948 #endif
00949       if(hAudioIn.LeftRecBuff == NULL)
00950       {
00951         return AUDIO_ERROR;
00952       }
00953     }
00954 
00955     if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
00956     {
00957       /* Allocate hAudioIn.RightRecBuff buffer */
00958 #if defined(BSP_AUDIO_USE_RTOS)
00959       hAudioIn.RightRecBuff  = (int32_t *)k_malloc((size / hAudioIn.ChannelNbr) * sizeof(int32_t));
00960 #else
00961       hAudioIn.RightRecBuff  = (int32_t *)malloc((size / hAudioIn.ChannelNbr) * sizeof(int32_t));
00962 #endif
00963       if(hAudioIn.RightRecBuff == NULL)
00964       {
00965         return AUDIO_ERROR;
00966       }
00967     }
00968 
00969     if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
00970     {
00971       /* Call the Media layer start function for right channel */
00972       if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmRightFilter,
00973                                           (int32_t*)hAudioIn.RightRecBuff,
00974                                           (hAudioIn.RecSize/hAudioIn.ChannelNbr)) != HAL_OK)
00975       {
00976         return AUDIO_ERROR;
00977       }
00978     }
00979 
00980     if((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
00981     {
00982       /* Call the Media layer start function for left channel */
00983       if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmLeftFilter,
00984                                           (int32_t*)hAudioIn.LeftRecBuff,
00985                                           (hAudioIn.RecSize/hAudioIn.ChannelNbr)) != HAL_OK)
00986       {
00987         return AUDIO_ERROR;
00988       }
00989     }
00990   }
00991   else
00992   { /* INPUT_DEVICE_ANALOG_MIC */
00993     /* Call the audio Codec Play function */
00994     if (hAudioIn.AudioDrv->Play(AUDIO_I2C_ADDRESS, pbuf, size) != 0)
00995     {
00996       return AUDIO_ERROR;
00997     }
00998 
00999     /* Start the process receive DMA */
01000     if(HAL_OK != HAL_SAI_Receive_DMA(&BSP_AUDIO_hSai_Rx, (uint8_t*)pbuf, size))
01001     {
01002       return AUDIO_ERROR;
01003     }
01004   }
01005 
01006   return AUDIO_OK;
01007 }
01008 
01009 /**
01010   * @brief  Updates the audio frequency.
01011   * @param  AudioFreq: Audio frequency used to record the audio stream.
01012   * @note   This API should be called after the BSP_AUDIO_IN_Init() to adjust the
01013   *         audio frequency.
01014   * @retval BSP AUDIO status
01015   */
01016 uint8_t BSP_AUDIO_IN_SetFrequency(uint32_t AudioFreq)
01017 {
01018   uint8_t TxData[2] = {0x00, 0x00};
01019 
01020   /* Configure the SAI PLL according to the requested audio frequency */
01021   if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK)
01022   {
01023     return AUDIO_ERROR;
01024   }
01025 
01026   if (hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
01027   {
01028     /* De-initializes the Digital Filter for Sigma-Delta Modulators interface */
01029     if(AUDIO_DFSDMx_DeInit() != AUDIO_OK)
01030     {
01031       return AUDIO_ERROR;
01032     }
01033 
01034     /* Initializes the Digital Filter for Sigma-Delta Modulators interface */
01035     if(AUDIO_DFSDMx_Init(AudioFreq) != AUDIO_OK)
01036     {
01037       return AUDIO_ERROR;
01038     }
01039   }
01040   else
01041   { /* INPUT_DEVICE_ANALOG_MIC */
01042     /* Disable SAI peripheral to allow access to SAI internal registers */
01043     __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx);
01044     __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Rx);
01045 
01046     /* Update the SAI audio frequency configuration */
01047     BSP_AUDIO_hSai_Tx.Init.Mckdiv = SAIClockDivider(AudioFreq);
01048     HAL_SAI_Init(&BSP_AUDIO_hSai_Tx);
01049     BSP_AUDIO_hSai_Rx.Init.Mckdiv = SAIClockDivider(AudioFreq);
01050     HAL_SAI_Init(&BSP_AUDIO_hSai_Rx);
01051 
01052     /* Enable SAI peripheral to generate MCLK */
01053     __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx);
01054     /* Transmit one byte to start FS generation */
01055     if(HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000) != HAL_OK)
01056     {
01057       return AUDIO_ERROR;
01058     }
01059   }
01060 
01061   hAudioIn.Frequency = AudioFreq;
01062 
01063   return AUDIO_OK;
01064 }
01065 
01066 /**
01067   * @brief  Regular conversion complete callback.
01068   * @note   In interrupt mode, user has to read conversion value in this function
01069             using HAL_DFSDM_FilterGetRegularValue.
01070   * @param  hdfsdm_filter : DFSDM filter handle.
01071   * @retval None
01072   */
01073 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01074 {
01075   uint32_t index;
01076   uint32_t recbufsize = (hAudioIn.RecSize/hAudioIn.ChannelNbr);
01077 
01078   if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC)
01079   {
01080     for (index = (recbufsize / 2); index < recbufsize; index++)
01081     {
01082       hAudioIn.pRecBuf[2 * index]       = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32768, 32767));
01083       hAudioIn.pRecBuf[(2 * index) + 1] = (uint16_t)(SaturaLH((hAudioIn.RightRecBuff[index] >> 8), -32768, 32767));
01084     }
01085   }
01086   else if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC1)
01087   {
01088     for (index = (recbufsize / 2); index < recbufsize; index++)
01089     {
01090       hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32768, 32767));
01091     }
01092   }
01093   else if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)
01094   {
01095     for (index = (recbufsize / 2); index < recbufsize; index++)
01096     {
01097       hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.RightRecBuff[index] >> 8), -32768, 32767));
01098     }
01099   }
01100 
01101   /* Invoke the registered 'TransferCompete' callback function (if any) */
01102   if (hAudioIn.CbTransferComplete != (Audio_CallbackTypeDef)NULL)
01103   {
01104     if(hdfsdm_filter == &BSP_AUDIO_hDfsdmLeftFilter)
01105     {
01106       if (DmaLeftRecBuffCplt) BSP_ErrorHandler();
01107 
01108       DmaLeftRecBuffCplt = 1;
01109     }
01110     else
01111     {
01112       if (DmaRightRecBuffCplt) BSP_ErrorHandler();
01113 
01114       DmaRightRecBuffCplt = 1;
01115     }
01116 
01117     if (((DmaLeftRecBuffCplt != 0) && (DmaRightRecBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC)) ||
01118         ((DmaLeftRecBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC1)) ||
01119         ((DmaRightRecBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)))
01120     {
01121       hAudioIn.CbTransferComplete();
01122       DmaLeftRecBuffCplt = 0;
01123       DmaRightRecBuffCplt = 0;
01124     }
01125   }
01126 }
01127 
01128 /**
01129   * @brief  Half regular conversion complete callback.
01130   * @param  hdfsdm_filter : DFSDM filter handle.
01131   * @retval None
01132   */
01133 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01134 {
01135   uint32_t index;
01136   uint32_t recbufsize = (hAudioIn.RecSize/hAudioIn.ChannelNbr);
01137 
01138   if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC)
01139   {
01140     for (index = 0; index < (recbufsize / 2); index++)
01141     {
01142       hAudioIn.pRecBuf[2 * index]       = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32768, 32767));
01143       hAudioIn.pRecBuf[(2 * index) + 1] = (uint16_t)(SaturaLH((hAudioIn.RightRecBuff[index] >> 8), -32768, 32767));
01144     }
01145   }
01146   else if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC1)
01147   {
01148     for (index = 0; index < (recbufsize / 2); index++)
01149     {
01150       hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32768, 32767));
01151     }
01152   }
01153   else if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)
01154   {
01155     for (index = 0; index < (recbufsize / 2); index++)
01156     {
01157       hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.RightRecBuff[index] >> 8), -32768, 32767));
01158     }
01159   }
01160 
01161   /* Invoke the registered 'HalfTransfer' callback function (if any) */
01162   if (hAudioIn.CbHalfTransfer != (Audio_CallbackTypeDef)NULL)
01163   {
01164     if(hdfsdm_filter == &BSP_AUDIO_hDfsdmLeftFilter)
01165     {
01166       if (DmaLeftRecHalfBuffCplt) BSP_ErrorHandler();
01167 
01168       DmaLeftRecHalfBuffCplt = 1;
01169     }
01170     else
01171     {
01172       if (DmaRightRecHalfBuffCplt) BSP_ErrorHandler();
01173 
01174       DmaRightRecHalfBuffCplt = 1;
01175     }
01176 
01177 
01178     if (((DmaLeftRecHalfBuffCplt != 0) && (DmaRightRecHalfBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC)) ||
01179         ((DmaLeftRecHalfBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC1)) ||
01180         ((DmaRightRecHalfBuffCplt != 0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)))
01181     {
01182       hAudioIn.CbHalfTransfer();
01183       DmaLeftRecHalfBuffCplt = 0;
01184       DmaRightRecHalfBuffCplt = 0;
01185     }
01186   }
01187 }
01188 
01189 /**
01190   * @brief  Error callback.
01191   * @param  hdfsdm_filter : DFSDM filter handle.
01192   * @retval None
01193   */
01194 void HAL_DFSDM_FilterErrorCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01195 {
01196   /* Invoke the registered 'ErrorCallback' callback function (if any) */
01197   if (hAudioIn.CbError != (Audio_CallbackTypeDef)NULL)
01198   {
01199     hAudioIn.CbError();
01200   }
01201 }
01202 
01203 /**
01204   * @brief  SAI Rx Transfer completed callbacks.
01205   * @param  hsai: SAI handle
01206   * @retval None
01207   */
01208 void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
01209 {
01210   /* Invoke the registered 'TransferComplete' function (if any) */
01211   if (hAudioIn.CbTransferComplete != (Audio_CallbackTypeDef)NULL)
01212   {
01213     hAudioIn.CbTransferComplete();
01214   }
01215 }
01216 
01217 /**
01218   * @brief  SAI Rx Half Transfer completed callbacks.
01219   * @param  hsai: SAI handle
01220   * @retval None
01221   */
01222 void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
01223 {
01224   /* Invoke the registered 'HalfTransfer' callback function (if any) */
01225   if (hAudioIn.CbHalfTransfer != (Audio_CallbackTypeDef)NULL)
01226   {
01227     hAudioIn.CbHalfTransfer();
01228   }
01229 }
01230 
01231 /**
01232   * @brief  Stops audio recording.
01233   * @retval BSP AUDIO status
01234   */
01235 uint8_t BSP_AUDIO_IN_Stop(void)
01236 {
01237   if (hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
01238   {
01239     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01240     {
01241       /* Call the Media layer stop function for right channel */
01242       if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmRightFilter) != HAL_OK )
01243       {
01244         return AUDIO_ERROR;
01245       }
01246     }
01247     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01248     {
01249       /* Call the Media layer stop function for left channel */
01250       if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK )
01251       {
01252         return AUDIO_ERROR;
01253       }
01254     }
01255 
01256     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01257     {
01258       /* Free hAudioIn.LeftRecBuff buffer */
01259 #if defined(BSP_AUDIO_USE_RTOS)
01260       k_free((void *)hAudioIn.LeftRecBuff);
01261 #else
01262       free((void *)hAudioIn.LeftRecBuff);
01263 #endif
01264     }
01265     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01266     {
01267       /* Free hAudioIn.RightRecBuff buffer */
01268 #if defined(BSP_AUDIO_USE_RTOS)
01269       k_free((void *)hAudioIn.RightRecBuff);
01270 #else
01271       free((void *)hAudioIn.RightRecBuff);
01272 #endif
01273     }
01274   }
01275   else
01276   { /* INPUT_DEVICE_ANALOG_MIC */
01277     /* Call Audio Codec Stop function */
01278     if (hAudioIn.AudioDrv->Stop(AUDIO_I2C_ADDRESS, CODEC_PDWN_HW) != 0)
01279     {
01280       return AUDIO_ERROR;
01281     }
01282 
01283     /* Wait at least 100ms */
01284     HAL_Delay(100);
01285 
01286     /* Stop DMA transfer of PCM samples towards the serial audio interface */
01287     if (HAL_SAI_DMAStop(&BSP_AUDIO_hSai_Rx)!= HAL_OK)
01288     {
01289       return AUDIO_ERROR;
01290     }
01291   }
01292 
01293   return AUDIO_OK;
01294 }
01295 
01296 /**
01297   * @brief  Pauses the audio file stream.
01298   * @retval BSP AUDIO status
01299   */
01300 uint8_t BSP_AUDIO_IN_Pause(void)
01301 {
01302   if (hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
01303   {
01304     /* Call the Media layer stop function */
01305     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01306     {
01307       if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmRightFilter) != HAL_OK)
01308       {
01309         return AUDIO_ERROR;
01310       }
01311     }
01312 
01313     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01314     {
01315       if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK)
01316       {
01317         return AUDIO_ERROR;
01318       }
01319     }
01320   }
01321   else
01322   { /* INPUT_DEVICE_ANALOG_MIC */
01323     /* Pause DMA transfer of PCM samples towards the serial audio interface */
01324     if (HAL_SAI_DMAPause(&BSP_AUDIO_hSai_Rx)!= HAL_OK)
01325     {
01326       return AUDIO_ERROR;
01327     }
01328   }
01329 
01330   return AUDIO_OK;
01331 }
01332 
01333 /**
01334   * @brief  Resumes the audio file stream.
01335   * @retval BSP AUDIO status
01336   */
01337 uint8_t BSP_AUDIO_IN_Resume(void)
01338 {
01339   if (hAudioIn.InputDevice != INPUT_DEVICE_ANALOG_MIC)
01340   {
01341     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01342     {
01343       /* Call the Media layer start function for right channel */
01344       if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmRightFilter,
01345                                           (int32_t*)hAudioIn.RightRecBuff,
01346                                           (hAudioIn.RecSize/hAudioIn.ChannelNbr)) != HAL_OK)
01347       {
01348         return AUDIO_ERROR;
01349       }
01350     }
01351 
01352     if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01353     {
01354       /* Call the Media layer start function for left channel */
01355       if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmLeftFilter,
01356                                           (int32_t*)hAudioIn.LeftRecBuff,
01357                                           (hAudioIn.RecSize/hAudioIn.ChannelNbr)) != HAL_OK)
01358       {
01359         return AUDIO_ERROR;
01360       }
01361     }
01362   }
01363   else
01364   { /* INPUT_DEVICE_ANALOG_MIC */
01365     /* Resume DMA transfer of PCM samples towards the serial audio interface */
01366     if (HAL_SAI_DMAResume(&BSP_AUDIO_hSai_Rx) != HAL_OK)
01367     {
01368       return AUDIO_ERROR;
01369     }
01370   }
01371 
01372   return AUDIO_OK;
01373 }
01374 
01375 /**
01376   * @brief  register user callback functions
01377   * @param  ErrorCallback: pointer to the error callback function
01378   * @param  HalfTransferCallback: pointer to the half transfer callback function
01379   * @param  TransferCompleteCallback: pointer to the transfer complete callback function
01380   * @retval None
01381   */
01382 void BSP_AUDIO_IN_RegisterCallbacks(Audio_CallbackTypeDef ErrorCallback,
01383                                     Audio_CallbackTypeDef HalfTransferCallback,
01384                                     Audio_CallbackTypeDef TransferCompleteCallback)
01385 {
01386   hAudioIn.CbError            = ErrorCallback;
01387   hAudioIn.CbHalfTransfer     = HalfTransferCallback;
01388   hAudioIn.CbTransferComplete = TransferCompleteCallback;
01389 }
01390 
01391 /**
01392   * @}
01393   */
01394 
01395 /* Private functions --------------------------------------------------------*/
01396 /** @addtogroup STM32L4R9I_DISCOVERY_AUDIO_Private_Functions
01397   * @{
01398   */
01399 /**
01400   * @brief  Initializes the Audio Codec audio interface (SAI).
01401   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
01402   * @retval BSP AUDIO status
01403   */
01404 static uint8_t AUDIO_SAIx_Init(uint32_t AudioFreq)
01405 {
01406   uint8_t TxData[2] = {0x00, 0x00};
01407 
01408   /* Initialize the BSP_AUDIO_hSai_Xx instances parameter */
01409   BSP_AUDIO_hSai_Tx.Instance = SAI1_Block_A;
01410   BSP_AUDIO_hSai_Rx.Instance = SAI1_Block_B;
01411 
01412   /* Disable SAI peripheral to allow access to SAI internal registers */
01413   __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx);
01414   __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Rx);
01415 
01416   /*******************************/
01417   /* SAI block used for playback */
01418   /*******************************/
01419   /* Configure SAI_Block_x used for transmit
01420   LSBFirst: Disabled
01421   DataSize: 16 */
01422   BSP_AUDIO_hSai_Tx.Init.AudioMode      = SAI_MODEMASTER_TX;
01423   BSP_AUDIO_hSai_Tx.Init.Synchro        = SAI_ASYNCHRONOUS;
01424   BSP_AUDIO_hSai_Tx.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
01425   BSP_AUDIO_hSai_Tx.Init.OutputDrive    = SAI_OUTPUTDRIVE_ENABLE;
01426   BSP_AUDIO_hSai_Tx.Init.NoDivider      = SAI_MASTERDIVIDER_ENABLE;
01427   BSP_AUDIO_hSai_Tx.Init.FIFOThreshold  = SAI_FIFOTHRESHOLD_1QF;
01428   BSP_AUDIO_hSai_Tx.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV;
01429   BSP_AUDIO_hSai_Tx.Init.Mckdiv         = SAIClockDivider(AudioFreq);
01430   BSP_AUDIO_hSai_Tx.Init.MonoStereoMode = SAI_STEREOMODE;
01431   BSP_AUDIO_hSai_Tx.Init.CompandingMode = SAI_NOCOMPANDING;
01432   BSP_AUDIO_hSai_Tx.Init.TriState       = SAI_OUTPUT_NOTRELEASED;
01433   BSP_AUDIO_hSai_Tx.Init.Protocol       = SAI_FREE_PROTOCOL;
01434   BSP_AUDIO_hSai_Tx.Init.DataSize       = SAI_DATASIZE_16;
01435   BSP_AUDIO_hSai_Tx.Init.FirstBit       = SAI_FIRSTBIT_MSB;
01436   BSP_AUDIO_hSai_Tx.Init.ClockStrobing  = SAI_CLOCKSTROBING_FALLINGEDGE;
01437 
01438   /* Configure SAI_Block_x Frame
01439   Frame Length: 32
01440   Frame active Length: 16
01441   FS Definition: Start frame + Channel Side identification
01442   FS Polarity: FS active Low
01443   FS Offset: FS asserted one bit before the first bit of slot 0 */
01444   BSP_AUDIO_hSai_Tx.FrameInit.FrameLength = 32;
01445   BSP_AUDIO_hSai_Tx.FrameInit.ActiveFrameLength = 16;
01446   BSP_AUDIO_hSai_Tx.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
01447   BSP_AUDIO_hSai_Tx.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
01448   BSP_AUDIO_hSai_Tx.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
01449 
01450   /* Configure SAI Block_x Slot
01451   Slot First Bit Offset: 0
01452   Slot Size  : 16
01453   Slot Number: 2
01454   Slot Active: Slots 0 and 1 actives */
01455   BSP_AUDIO_hSai_Tx.SlotInit.FirstBitOffset = 0;
01456   BSP_AUDIO_hSai_Tx.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
01457   BSP_AUDIO_hSai_Tx.SlotInit.SlotNumber = 2;
01458   BSP_AUDIO_hSai_Tx.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1;
01459 
01460   /*****************************/
01461   /* SAI block used for record */
01462   /*****************************/
01463   /* Configure SAI_Block_x used for receive
01464   LSBFirst: Disabled
01465   DataSize: 16 */
01466   BSP_AUDIO_hSai_Rx.Init.AudioMode      = SAI_MODESLAVE_RX;
01467   BSP_AUDIO_hSai_Rx.Init.Synchro        = SAI_SYNCHRONOUS;
01468   BSP_AUDIO_hSai_Rx.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
01469   BSP_AUDIO_hSai_Rx.Init.OutputDrive    = SAI_OUTPUTDRIVE_ENABLE;
01470   BSP_AUDIO_hSai_Rx.Init.NoDivider      = SAI_MASTERDIVIDER_ENABLE;
01471   BSP_AUDIO_hSai_Rx.Init.FIFOThreshold  = SAI_FIFOTHRESHOLD_1QF;
01472   BSP_AUDIO_hSai_Rx.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV;
01473   BSP_AUDIO_hSai_Rx.Init.Mckdiv         = SAIClockDivider(AudioFreq);
01474   BSP_AUDIO_hSai_Rx.Init.MonoStereoMode = SAI_MONOMODE;
01475   BSP_AUDIO_hSai_Rx.Init.CompandingMode = SAI_NOCOMPANDING;
01476   BSP_AUDIO_hSai_Rx.Init.TriState       = SAI_OUTPUT_NOTRELEASED;
01477   BSP_AUDIO_hSai_Rx.Init.Protocol       = SAI_FREE_PROTOCOL;
01478   BSP_AUDIO_hSai_Rx.Init.DataSize       = SAI_DATASIZE_16;
01479   BSP_AUDIO_hSai_Rx.Init.FirstBit       = SAI_FIRSTBIT_MSB;
01480   BSP_AUDIO_hSai_Rx.Init.ClockStrobing  = SAI_CLOCKSTROBING_FALLINGEDGE;
01481 
01482   /* Configure SAI_Block_x Frame
01483   Frame Length: 32
01484   Frame active Length: 16
01485   FS Definition: Start frame + Channel Side identification
01486   FS Polarity: FS active Low
01487   FS Offset: FS asserted one bit before the first bit of slot 0 */
01488   BSP_AUDIO_hSai_Rx.FrameInit.FrameLength = 32;
01489   BSP_AUDIO_hSai_Rx.FrameInit.ActiveFrameLength = 16;
01490   BSP_AUDIO_hSai_Rx.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
01491   BSP_AUDIO_hSai_Rx.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
01492   BSP_AUDIO_hSai_Rx.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
01493 
01494   /* Configure SAI Block_x Slot
01495   Slot First Bit Offset: 0
01496   Slot Size  : 16
01497   Slot Number: 2
01498   Slot Active: Slots 0 and 1 actives */
01499   BSP_AUDIO_hSai_Rx.SlotInit.FirstBitOffset = 0;
01500   BSP_AUDIO_hSai_Rx.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
01501   BSP_AUDIO_hSai_Rx.SlotInit.SlotNumber = 2;
01502   BSP_AUDIO_hSai_Rx.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1;
01503 
01504   /*********************************/
01505   /* Initializes the SAI peripheral*/
01506   /*********************************/
01507   if (HAL_SAI_Init(&BSP_AUDIO_hSai_Tx) != HAL_OK)
01508   {
01509     return AUDIO_ERROR;
01510   }
01511   if (HAL_SAI_Init(&BSP_AUDIO_hSai_Rx) != HAL_OK)
01512   {
01513     return AUDIO_ERROR;
01514   }
01515 
01516   /******************************************/
01517   /* Enable SAI peripheral to generate MCLK */
01518   /******************************************/
01519   __HAL_SAI_ENABLE(&BSP_AUDIO_hSai_Tx);
01520   /* Transmit one byte to start FS generation */
01521   if(HAL_SAI_Transmit(&BSP_AUDIO_hSai_Tx, TxData, 2, 1000) != HAL_OK)
01522   {
01523     return AUDIO_ERROR;
01524   }
01525 
01526   return AUDIO_OK;
01527 }
01528 
01529 /**
01530   * @brief  De-initializes the Audio Codec audio interface (SAI).
01531   * @retval BSP AUDIO status
01532   */
01533 static uint8_t AUDIO_SAIx_DeInit(void)
01534 {
01535   /* Disable the SAI audio block */
01536   __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Tx);
01537   __HAL_SAI_DISABLE(&BSP_AUDIO_hSai_Rx);
01538 
01539   /* De-initializes the SAI peripheral */
01540   if (HAL_SAI_DeInit(&BSP_AUDIO_hSai_Tx) != HAL_OK)
01541   {
01542     return AUDIO_ERROR;
01543   }
01544   if (HAL_SAI_DeInit(&BSP_AUDIO_hSai_Rx) != HAL_OK)
01545   {
01546     return AUDIO_ERROR;
01547   }
01548 
01549   return AUDIO_OK;
01550 }
01551 
01552 /**
01553   * @brief  SAI MSP Init
01554   * @param  hsai : pointer to a SAI_HandleTypeDef structure
01555   * @retval None
01556   */
01557 void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
01558 {
01559   GPIO_InitTypeDef  GPIO_InitStruct;
01560 
01561   /* Enable SAI clock */
01562   __HAL_RCC_SAI1_CLK_ENABLE();
01563 
01564   if(hsai->Instance == SAI1_Block_A)
01565   {
01566     /* SAI pins configuration: FS, SCK, MCLK and SD pins */
01567     __HAL_RCC_GPIOB_CLK_ENABLE();
01568     __HAL_RCC_GPIOE_CLK_ENABLE();
01569     GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
01570     GPIO_InitStruct.Pull      = GPIO_NOPULL;
01571     GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
01572     GPIO_InitStruct.Alternate = GPIO_AF13_SAI1;
01573     GPIO_InitStruct.Pin       = GPIO_PIN_2;
01574     HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); /* SAI1_MCLK_A */
01575     GPIO_InitStruct.Pin       = GPIO_PIN_9;
01576     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* SAI1_FS_A */
01577     GPIO_InitStruct.Pin       = GPIO_PIN_5;
01578     HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); /* SAI1_SCK_A */
01579     GPIO_InitStruct.Pin       = GPIO_PIN_6;
01580     HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); /* SAI1_SD_A */
01581 
01582     /* Configure the hDmaSaiTx handle parameters */
01583     __HAL_RCC_DMA2_CLK_ENABLE();
01584     __HAL_RCC_DMAMUX1_CLK_ENABLE();
01585     hDmaSaiTx.Init.Request             = DMA_REQUEST_SAI1_A;
01586     hDmaSaiTx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
01587     hDmaSaiTx.Init.PeriphInc           = DMA_PINC_DISABLE;
01588     hDmaSaiTx.Init.MemInc              = DMA_MINC_ENABLE;
01589     hDmaSaiTx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
01590     hDmaSaiTx.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;
01591     hDmaSaiTx.Init.Mode                = DMA_CIRCULAR;
01592     hDmaSaiTx.Init.Priority            = DMA_PRIORITY_HIGH;
01593     hDmaSaiTx.Instance                 = DMA2_Channel1;
01594     /* Associate the DMA handle */
01595     __HAL_LINKDMA(hsai, hdmatx, hDmaSaiTx);
01596     /* Deinitialize the Stream for new transfer */
01597     HAL_DMA_DeInit(&hDmaSaiTx);
01598     /* Configure the DMA Stream */
01599     HAL_DMA_Init(&hDmaSaiTx);
01600     /* SAI DMA IRQ Channel configuration */
01601     HAL_NVIC_SetPriority(DMA2_Channel1_IRQn, 5, 0);
01602     HAL_NVIC_EnableIRQ(DMA2_Channel1_IRQn);
01603   }
01604   else /* SAI1_BlockB */
01605   {
01606     /* SAI pins configuration: SD pin */
01607     __HAL_RCC_GPIOB_CLK_ENABLE();
01608     GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
01609     GPIO_InitStruct.Pull      = GPIO_NOPULL;
01610     GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
01611     GPIO_InitStruct.Alternate = GPIO_AF13_SAI1;
01612     GPIO_InitStruct.Pin       = GPIO_PIN_5;
01613     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* SAI1_SD_B */
01614 
01615     /* Configure the hDmaSaiRx handle parameters */
01616     __HAL_RCC_DMA2_CLK_ENABLE();
01617     __HAL_RCC_DMAMUX1_CLK_ENABLE();
01618     hDmaSaiRx.Init.Request             = DMA_REQUEST_SAI1_B;
01619     hDmaSaiRx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
01620     hDmaSaiRx.Init.PeriphInc           = DMA_PINC_DISABLE;
01621     hDmaSaiRx.Init.MemInc              = DMA_MINC_ENABLE;
01622     hDmaSaiRx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
01623     hDmaSaiRx.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;
01624     hDmaSaiRx.Init.Mode                = DMA_CIRCULAR;
01625     hDmaSaiRx.Init.Priority            = DMA_PRIORITY_HIGH;
01626     hDmaSaiRx.Instance                 = DMA2_Channel2;
01627     /* Associate the DMA handle */
01628     __HAL_LINKDMA(hsai, hdmarx, hDmaSaiRx);
01629     /* Deinitialize the Stream for new transfer */
01630     HAL_DMA_DeInit(&hDmaSaiRx);
01631     /* Configure the DMA Stream */
01632     HAL_DMA_Init(&hDmaSaiRx);
01633     /* SAI DMA IRQ Channel configuration */
01634     HAL_NVIC_SetPriority(DMA2_Channel2_IRQn, 5, 0);
01635     HAL_NVIC_EnableIRQ(DMA2_Channel2_IRQn);
01636   }
01637 }
01638 
01639 /**
01640   * @brief  SAI MSP De-init
01641   * @param  hsai : pointer to a SAI_HandleTypeDef structure
01642   * @retval None
01643   */
01644 void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
01645 {
01646   if(hsai->Instance == SAI1_Block_A)
01647   {
01648     /* Disable SAI DMA Channel IRQ  */
01649     HAL_NVIC_DisableIRQ(DMA2_Channel1_IRQn);
01650 
01651     /* Reset the DMA Stream configuration*/
01652     HAL_DMA_DeInit(&hDmaSaiTx);
01653 
01654     /* Don't disable the DMA clock used for other SAI block */
01655     /* __HAL_RCC_DMA2_CLK_DISABLE(); */
01656     /* __HAL_RCC_DMAMUX1_CLK_DISABLE(); */
01657 
01658     /* De-initialize FS, SCK, MCK and SD pins*/
01659     HAL_GPIO_DeInit(GPIOE, GPIO_PIN_2);  /* SAI1_MCLK_A */
01660     HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9);  /* SAI1_FS_A */
01661     HAL_GPIO_DeInit(GPIOE, GPIO_PIN_5);  /* SAI1_SCK_A */
01662     HAL_GPIO_DeInit(GPIOE, GPIO_PIN_6);  /* SAI1_SD_A */
01663 
01664     /* Don't disable SAI clock used for other SAI block */
01665     /*__HAL_RCC_SAI1_CLK_DISABLE(); */
01666   }
01667   else /* SAI1_BlockB */
01668   {
01669     /* Disable SAI DMA Channel IRQ  */
01670     HAL_NVIC_DisableIRQ(DMA2_Channel2_IRQn);
01671 
01672     /* Reset the DMA Stream configuration*/
01673     HAL_DMA_DeInit(&hDmaSaiRx);
01674 
01675     /* De-initialize SD pin */
01676     HAL_GPIO_DeInit(GPIOB, GPIO_PIN_5);  /* SAI1_SD_B */
01677 
01678     /* Disable SAI clock */
01679     __HAL_RCC_SAI1_CLK_DISABLE();
01680   }
01681 }
01682 
01683 /**
01684   * @}
01685   */
01686 
01687 /** @addtogroup STM32L4R9I_DISCOVERY_AUDIO_Private_Functions
01688   * @{
01689   */
01690 
01691 /**
01692   * @brief  Initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01693   * @param  AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral.
01694   * @retval BSP AUDIO status
01695   */
01696 static uint8_t AUDIO_DFSDMx_Init(uint32_t AudioFreq)
01697 {
01698   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01699   {
01700     /*####CHANNEL 3####*/
01701     hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Activation   = ENABLE;
01702     hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
01703     /* Set the DFSDM clock OUT audio frequency configuration */
01704     hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Divider      = DFSDMClockDivider(AudioFreq);
01705     hAudioIn.hDfsdmLeftChannel.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
01706     hAudioIn.hDfsdmLeftChannel.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
01707     hAudioIn.hDfsdmLeftChannel.Init.Input.Pins               = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
01708     /* Request to sample stable data for LEFT micro on Rising edge */
01709     hAudioIn.hDfsdmLeftChannel.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_RISING;
01710     hAudioIn.hDfsdmLeftChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
01711     hAudioIn.hDfsdmLeftChannel.Init.Awd.FilterOrder          = DFSDM_CHANNEL_SINC1_ORDER;
01712     hAudioIn.hDfsdmLeftChannel.Init.Awd.Oversampling         = 10;
01713     hAudioIn.hDfsdmLeftChannel.Init.Offset                   = 0;
01714     hAudioIn.hDfsdmLeftChannel.Init.RightBitShift            = DFSDMRightBitShift(AudioFreq);
01715     hAudioIn.hDfsdmLeftChannel.Instance                      = DFSDM1_Channel1;
01716 
01717     /* Init the DFSDM Channel */
01718     if (HAL_DFSDM_ChannelInit(&hAudioIn.hDfsdmLeftChannel) != HAL_OK)
01719     {
01720       return AUDIO_ERROR;
01721     }
01722   }
01723 
01724   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01725   {
01726     /*####CHANNEL 2####*/
01727     hAudioIn.hDfsdmRightChannel.Init.OutputClock.Activation   = ENABLE;
01728     hAudioIn.hDfsdmRightChannel.Init.OutputClock.Selection    = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
01729     /* Set the DFSDM clock OUT audio frequency configuration */
01730     hAudioIn.hDfsdmRightChannel.Init.OutputClock.Divider      = DFSDMClockDivider(AudioFreq);
01731     hAudioIn.hDfsdmRightChannel.Init.Input.Multiplexer        = DFSDM_CHANNEL_EXTERNAL_INPUTS;
01732     hAudioIn.hDfsdmRightChannel.Init.Input.DataPacking        = DFSDM_CHANNEL_STANDARD_MODE;
01733     hAudioIn.hDfsdmRightChannel.Init.Input.Pins               = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS;
01734     /* Request to sample stable data for LEFT micro on Rising edge */
01735     hAudioIn.hDfsdmRightChannel.Init.SerialInterface.Type     = DFSDM_CHANNEL_SPI_FALLING;
01736     hAudioIn.hDfsdmRightChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
01737     hAudioIn.hDfsdmRightChannel.Init.Awd.FilterOrder          = DFSDM_CHANNEL_SINC1_ORDER;
01738     hAudioIn.hDfsdmRightChannel.Init.Awd.Oversampling         = 10;
01739     hAudioIn.hDfsdmRightChannel.Init.Offset                   = 0;
01740     hAudioIn.hDfsdmRightChannel.Init.RightBitShift            = DFSDMRightBitShift(AudioFreq);
01741     hAudioIn.hDfsdmRightChannel.Instance                      = DFSDM1_Channel0;
01742 
01743     /* Init the DFSDM Channel */
01744     if (HAL_DFSDM_ChannelInit(&hAudioIn.hDfsdmRightChannel) != HAL_OK)
01745     {
01746       return AUDIO_ERROR;
01747     }
01748   }
01749 
01750   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01751   {
01752     /*####FILTER 0####*/
01753     BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.Trigger         = DFSDM_FILTER_SW_TRIGGER;
01754     BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.FastMode        = ENABLE;
01755     BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.DmaMode         = ENABLE;
01756     BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
01757     BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ScanMode       = DISABLE;
01758     BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.DmaMode        = DISABLE;
01759     BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO;
01760     BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES;
01761     BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.SincOrder        = DFSDMFilterOrder(AudioFreq);
01762     /* Set the DFSDM Filters Oversampling to have correct sample rate */
01763     BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.Oversampling     = DFSDMOverSampling(AudioFreq);
01764     BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.IntOversampling  = 1;
01765     BSP_AUDIO_hDfsdmLeftFilter.Instance                          = DFSDM1_Filter0;
01766 
01767     /* Init the DFSDM Filter */
01768     if (HAL_DFSDM_FilterInit(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK)
01769     {
01770       return AUDIO_ERROR;
01771     }
01772 
01773     /* Configure regular channel */
01774     if (HAL_DFSDM_FilterConfigRegChannel(&BSP_AUDIO_hDfsdmLeftFilter,
01775                                          DFSDM_CHANNEL_1,
01776                                          DFSDM_CONTINUOUS_CONV_ON) != HAL_OK)
01777     {
01778       return AUDIO_ERROR;
01779     }
01780   }
01781 
01782   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01783   {
01784     /*####FILTER 1####*/
01785     if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)
01786     {
01787       BSP_AUDIO_hDfsdmRightFilter.Init.RegularParam.Trigger       = DFSDM_FILTER_SW_TRIGGER;
01788     }
01789     else
01790     {
01791       BSP_AUDIO_hDfsdmRightFilter.Init.RegularParam.Trigger       = DFSDM_FILTER_SYNC_TRIGGER;
01792     }
01793     BSP_AUDIO_hDfsdmRightFilter.Init.RegularParam.FastMode        = ENABLE;
01794     BSP_AUDIO_hDfsdmRightFilter.Init.RegularParam.DmaMode         = ENABLE;
01795     BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.Trigger        = DFSDM_FILTER_SW_TRIGGER;
01796     BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.ScanMode       = DISABLE;
01797     BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.DmaMode        = DISABLE;
01798     BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.ExtTrigger     = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO;
01799     BSP_AUDIO_hDfsdmRightFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES;
01800     BSP_AUDIO_hDfsdmRightFilter.Init.FilterParam.SincOrder        = DFSDMFilterOrder(AudioFreq);
01801     /* Set the DFSDM Filters Oversampling to have correct sample rate */
01802     BSP_AUDIO_hDfsdmRightFilter.Init.FilterParam.Oversampling     = DFSDMOverSampling(AudioFreq);
01803     BSP_AUDIO_hDfsdmRightFilter.Init.FilterParam.IntOversampling  = 1;
01804     BSP_AUDIO_hDfsdmRightFilter.Instance                          = DFSDM1_Filter1;
01805 
01806     /* Init the DFSDM Filter */
01807     if (HAL_DFSDM_FilterInit(&BSP_AUDIO_hDfsdmRightFilter) != HAL_OK)
01808     {
01809       return AUDIO_ERROR;
01810     }
01811 
01812     /* Configure regular channel */
01813     if (HAL_DFSDM_FilterConfigRegChannel(&BSP_AUDIO_hDfsdmRightFilter,
01814                                          DFSDM_CHANNEL_0,
01815                                          DFSDM_CONTINUOUS_CONV_ON) != HAL_OK)
01816     {
01817       return AUDIO_ERROR;
01818     }
01819   }
01820 
01821   return AUDIO_OK;
01822 }
01823 
01824 /**
01825   * @brief  De-initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
01826   * @retval BSP AUDIO status
01827   */
01828 static uint8_t AUDIO_DFSDMx_DeInit(void)
01829 {
01830   /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */
01831   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01832   {
01833     if (HAL_DFSDM_FilterDeInit(&BSP_AUDIO_hDfsdmRightFilter) != HAL_OK)
01834     {
01835       return AUDIO_ERROR;
01836     }
01837   }
01838   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01839   {
01840     if (HAL_DFSDM_FilterDeInit(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK)
01841     {
01842       return AUDIO_ERROR;
01843     }
01844   }
01845 
01846   /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */
01847   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC2) == INPUT_DEVICE_DIGITAL_MIC2)
01848   {
01849     if (HAL_DFSDM_ChannelDeInit(&hAudioIn.hDfsdmRightChannel) != HAL_OK)
01850     {
01851       return AUDIO_ERROR;
01852     }
01853   }
01854   if ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) == INPUT_DEVICE_DIGITAL_MIC1)
01855   {
01856     if (HAL_DFSDM_ChannelDeInit(&hAudioIn.hDfsdmLeftChannel) != HAL_OK)
01857     {
01858       return AUDIO_ERROR;
01859     }
01860   }
01861 
01862   /* DFSDM reset */
01863   __HAL_RCC_DFSDM1_FORCE_RESET();
01864   __HAL_RCC_DFSDM1_RELEASE_RESET();
01865 
01866   return AUDIO_OK;
01867 }
01868 
01869 /**
01870   * @brief  Initializes the DFSDM channel MSP.
01871   * @param  hdfsdm_channel : DFSDM channel handle.
01872   * @retval None
01873   */
01874 void HAL_DFSDM_ChannelMspInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
01875 {
01876   if (((hdfsdm_channel->Instance == DFSDM1_Channel1) && ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) != 0)) || \
01877       ((hdfsdm_channel->Instance == DFSDM1_Channel0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)))
01878   {
01879     GPIO_InitTypeDef  GPIO_InitStruct;
01880 
01881     /* Enable DFSDM clock */
01882     __HAL_RCC_DFSDM1_CLK_ENABLE();
01883 
01884     /* DFSDM pins configuration: DFSDM1_CKOUT, DFSDM1_DATIN1 pins */
01885     __HAL_RCC_GPIOB_CLK_ENABLE();
01886     __HAL_RCC_GPIOC_CLK_ENABLE();
01887     GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
01888     GPIO_InitStruct.Pull      = GPIO_NOPULL;
01889     GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
01890     GPIO_InitStruct.Alternate = GPIO_AF6_DFSDM1;
01891     GPIO_InitStruct.Pin       = GPIO_PIN_2;
01892     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /* DFSDM1_CKOUT */
01893     GPIO_InitStruct.Pin       = GPIO_PIN_12;
01894     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* DFSDM1_DATIN1 */
01895 
01896     /* Enable MIC_VDD (PH2) */
01897     __HAL_RCC_GPIOH_CLK_ENABLE();
01898     GPIO_InitStruct.Mode      = GPIO_MODE_OUTPUT_PP;
01899     GPIO_InitStruct.Pull      = GPIO_NOPULL;
01900     GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
01901     GPIO_InitStruct.Pin       = GPIO_PIN_2;
01902     HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
01903     HAL_GPIO_WritePin(GPIOH, GPIO_PIN_2, GPIO_PIN_SET);
01904   }
01905 }
01906 
01907 /**
01908   * @brief  De-initializes the DFSDM channel MSP.
01909   * @param  hdfsdm_channel : DFSDM channel handle.
01910   * @retval None
01911   */
01912 void HAL_DFSDM_ChannelMspDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
01913 {
01914   if (((hdfsdm_channel->Instance == DFSDM1_Channel1) && ((hAudioIn.InputDevice & INPUT_DEVICE_DIGITAL_MIC1) != 0)) || \
01915       ((hdfsdm_channel->Instance == DFSDM1_Channel0) && (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)))
01916   {
01917     /* Disable MIC_VDD (PH2) */
01918     HAL_GPIO_WritePin(GPIOH, GPIO_PIN_2, GPIO_PIN_RESET);
01919     HAL_GPIO_DeInit(GPIOH, GPIO_PIN_2);
01920 
01921     /* De-initialize DFSDM1_CKOUT, DFSDM1_DATIN1 pins */
01922     HAL_GPIO_DeInit(GPIOC, GPIO_PIN_2);  /* DFSDM1_CKOUT */
01923     HAL_GPIO_DeInit(GPIOB, GPIO_PIN_12); /* DFSDM1_DATIN1 */
01924 
01925     /* Disable DFSDM1 */
01926     __HAL_RCC_DFSDM1_CLK_DISABLE();
01927   }
01928 }
01929 
01930 /**
01931   * @brief  Initializes the DFSDM filter MSP.
01932   * @param  hdfsdm_filter : DFSDM filter handle.
01933   * @retval None
01934   */
01935 void HAL_DFSDM_FilterMspInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
01936 {
01937   if(hdfsdm_filter->Instance == DFSDM1_Filter0)
01938   {
01939     /* Enable the DMA clock */
01940     __HAL_RCC_DMA1_CLK_ENABLE();
01941     __HAL_RCC_DMAMUX1_CLK_ENABLE();
01942 
01943     /* Configure the hAudioIn.hDmaDfsdmLeft handle parameters */
01944     hAudioIn.hDmaDfsdmLeft.Init.Request             = DMA_REQUEST_DFSDM1_FLT0;
01945     hAudioIn.hDmaDfsdmLeft.Init.Direction           = DMA_PERIPH_TO_MEMORY;
01946     hAudioIn.hDmaDfsdmLeft.Init.PeriphInc           = DMA_PINC_DISABLE;
01947     hAudioIn.hDmaDfsdmLeft.Init.MemInc              = DMA_MINC_ENABLE;
01948     hAudioIn.hDmaDfsdmLeft.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
01949     hAudioIn.hDmaDfsdmLeft.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
01950     hAudioIn.hDmaDfsdmLeft.Init.Mode                = DMA_CIRCULAR;
01951     hAudioIn.hDmaDfsdmLeft.Init.Priority            = DMA_PRIORITY_HIGH;
01952     hAudioIn.hDmaDfsdmLeft.Instance                 = DMA1_Channel4;
01953 
01954     /* Associate the DMA handle */
01955     __HAL_LINKDMA(hdfsdm_filter, hdmaReg, hAudioIn.hDmaDfsdmLeft);
01956 
01957     /* Reset DMA handle state */
01958     __HAL_DMA_RESET_HANDLE_STATE(&hAudioIn.hDmaDfsdmLeft);
01959 
01960     /* Configure the DMA Channel */
01961     HAL_DMA_Init(&hAudioIn.hDmaDfsdmLeft);
01962 
01963     /* DMA IRQ Channel configuration */
01964     HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 5, 0);
01965     HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
01966   }
01967   else /* DFSDM1_Filter1 */
01968   {
01969     if (hAudioIn.InputDevice == INPUT_DEVICE_DIGITAL_MIC2)
01970     {
01971       /* Enable the DMA clock needed if only MIC2 is used */
01972       __HAL_RCC_DMA1_CLK_ENABLE();
01973       __HAL_RCC_DMAMUX1_CLK_ENABLE();
01974     }
01975 
01976     /* Configure the hAudioIn.hDmaDfsdmRight handle parameters */
01977     hAudioIn.hDmaDfsdmRight.Init.Request             = DMA_REQUEST_DFSDM1_FLT1;
01978     hAudioIn.hDmaDfsdmRight.Init.Direction           = DMA_PERIPH_TO_MEMORY;
01979     hAudioIn.hDmaDfsdmRight.Init.PeriphInc           = DMA_PINC_DISABLE;
01980     hAudioIn.hDmaDfsdmRight.Init.MemInc              = DMA_MINC_ENABLE;
01981     hAudioIn.hDmaDfsdmRight.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
01982     hAudioIn.hDmaDfsdmRight.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
01983     hAudioIn.hDmaDfsdmRight.Init.Mode                = DMA_CIRCULAR;
01984     hAudioIn.hDmaDfsdmRight.Init.Priority            = DMA_PRIORITY_HIGH;
01985     hAudioIn.hDmaDfsdmRight.Instance                 = DMA1_Channel5;
01986 
01987     /* Associate the DMA handle */
01988     __HAL_LINKDMA(hdfsdm_filter, hdmaReg, hAudioIn.hDmaDfsdmRight);
01989 
01990     /* Reset DMA handle state */
01991     __HAL_DMA_RESET_HANDLE_STATE(&hAudioIn.hDmaDfsdmRight);
01992 
01993     /* Configure the DMA Channel */
01994     HAL_DMA_Init(&hAudioIn.hDmaDfsdmRight);
01995 
01996     /* DMA IRQ Channel configuration */
01997     HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 5, 0);
01998     HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
01999   }
02000 }
02001 
02002  /**
02003   * @brief  De-initializes the DFSDM filter MSP.
02004   * @param  hdfsdm_filter : DFSDM filter handle.
02005   * @retval None
02006   */
02007 void HAL_DFSDM_FilterMspDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
02008 {
02009   if(hdfsdm_filter->Instance == DFSDM1_Filter0)
02010   {
02011     /* Disable DMA  Channel IRQ */
02012     HAL_NVIC_DisableIRQ(DMA1_Channel4_IRQn);
02013 
02014     /* De-initialize the DMA Channel */
02015     HAL_DMA_DeInit(&hAudioIn.hDmaDfsdmLeft);
02016   }
02017   else /* DFSDM1_Filter1 */
02018   {
02019     /* Disable DMA  Channel IRQ */
02020     HAL_NVIC_DisableIRQ(DMA1_Channel5_IRQn);
02021 
02022     /* De-initialize the DMA Channel */
02023     HAL_DMA_DeInit(&hAudioIn.hDmaDfsdmRight);
02024   }
02025 }
02026 
02027 /**
02028   * @brief  Configures the SAI PLL clock according to the required audio frequency.
02029   * @param  Frequency: Audio frequency.
02030   * @retval BSP AUDIO status
02031   * @note   The SAI PLL input clock must be configured in the user application.
02032   *         The SAI PLL configuration done within this function assumes that
02033   *         the SAI PLL input clock runs at 4 MHz.
02034   */
02035 static uint8_t AUDIO_SAIPLLConfig(uint32_t Frequency)
02036 {
02037   RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct;
02038 
02039   /* Retrieve actual RCC configuration */
02040   HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct);
02041 
02042   if (   (Frequency == AUDIO_FREQUENCY_11K)
02043       || (Frequency == AUDIO_FREQUENCY_22K)
02044       || (Frequency == AUDIO_FREQUENCY_44K) )
02045   {
02046     /* Configure PLLSAI prescalers */
02047     /* SAI clock config
02048     PLLSAI1_VCO= 4 Mhz * PLLSAI1N = 4 * 48 = VCO_192M
02049     SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 192/17 = 11.294 Mhz */
02050     RCC_ExCLKInitStruct.PeriphClockSelection    = RCC_PERIPHCLK_SAI1;
02051     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1M        = 1;
02052     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N        = 48;
02053     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P        = 17;
02054     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
02055     RCC_ExCLKInitStruct.Sai1ClockSelection      = RCC_SAI1CLKSOURCE_PLLSAI1;
02056   }
02057   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
02058   {
02059     /* SAI clock config
02060     PLLSAI2_VCO= 4 Mhz * PLLSAI1N = 4 * 86 = VCO_344M
02061     SAI_CK_x = PLLSAI1_VCO/PLLSAI2P = 344/7 = 49.142 Mhz */
02062     RCC_ExCLKInitStruct.PeriphClockSelection    = RCC_PERIPHCLK_SAI1;
02063     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1M        = 1;
02064     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N        = 86;
02065     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P        = 7;
02066     RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
02067     RCC_ExCLKInitStruct.Sai1ClockSelection      = RCC_SAI1CLKSOURCE_PLLSAI1;
02068   }
02069 
02070   if (HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct) != HAL_OK)
02071   {
02072     return AUDIO_ERROR;
02073   }
02074 
02075   return AUDIO_OK;
02076 }
02077 
02078 /**
02079   * @}
02080   */
02081 
02082 /**
02083   * @}
02084   */
02085 
02086 /**
02087   * @}
02088   */
02089 
02090 /**
02091   * @}
02092   */
02093 
02094 /**
02095   * @}
02096   */
02097 
02098 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Fri Oct 13 2017 02:37:42 for STM32L4R9I-Discovery BSP User Manual by   doxygen 1.7.6.1