STM32L476G-Discovery board drivers V1.0.0

Dependents:   DiscoLogger DISCO_L476VG_GlassLCD DISCO_L476VG_MicrophoneRecorder DISCO_L476VG_UART ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32l476g_discovery_audio.c Source File

stm32l476g_discovery_audio.c

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