Senior Design: Sound Monitor / BSP

Dependencies:   CMSIS_STM32L4xx CMSIS_DSP_401 STM32L4xx_HAL_Driver

Dependents:   DiscoAudioRecord

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