STM32F723E-Discovery BSP User Manual: stm32f723e_discovery_audio.c Source File

STM32F723E-Discovery BSP Drivers

stm32f723e_discovery_audio.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32f723e_discovery_audio.c
00004   * @author  MCD Application Team
00005   * @version V1.0.0
00006   * @date    30-December-2016
00007   * @brief   This file provides the Audio driver for the STM32F723E-DISCOVERY  
00008   *          board.
00009   @verbatim
00010   How To use this driver:
00011   -----------------------
00012    + This driver supports STM32F7xx devices on STM32F723E-DISCOVERY (MB1260) Evaluation boards.
00013    + Call the function BSP_AUDIO_OUT_Init(
00014                                     OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 
00015                                                   OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH)
00016                                     Volume      : Initial volume to be set (0 is min (mute), 100 is max (100%)
00017                                     AudioFreq   : Audio frequency in Hz (8000, 16000, 22500, 32000...)
00018                                                   this parameter is relative to the audio file/stream type.
00019                                    )
00020       This function configures all the hardware required for the audio application (codec, I2C, SAI, 
00021       GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK.
00022       If the returned value is different from AUDIO_OK or the function is stuck then the communication with
00023       the codec has failed (try to un-plug the power or reset device in this case).
00024       - OUTPUT_DEVICE_SPEAKER  : only speaker will be set as output for the audio stream.
00025       - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream.
00026       - OUTPUT_DEVICE_BOTH     : both Speaker and Headphone are used as outputs for the audio stream
00027                                  at the same time.
00028    + Call the function BSP_DISCOVERY_AUDIO_OUT_Play(
00029                                   pBuffer: pointer to the audio data file address
00030                                   Size   : size of the buffer to be sent in Bytes
00031                                  )
00032       to start playing (for the first time) from the audio file/stream.
00033    + Call the function BSP_AUDIO_OUT_Pause() to pause playing   
00034    + Call the function BSP_AUDIO_OUT_Resume() to resume playing.
00035        Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called
00036           for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case).
00037        Note. This function should be called only when the audio file is played or paused (not stopped).
00038    + For each mode, you may need to implement the relative callback functions into your code.
00039       The Callback functions are named AUDIO_OUT_XXX_CallBack() and only their prototypes are declared in 
00040       the stm32f723e_discovery_audio.h file. (refer to the example for more details on the callbacks implementations)
00041    + To Stop playing, to modify the volume level, the frequency, the audio frame slot, 
00042       the device output mode the mute or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(), 
00043       AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetAudioFrameSlot(), BSP_AUDIO_OUT_SetOutputMode(),
00044       BSP_AUDIO_OUT_SetMute() and BSP_AUDIO_OUT_Stop().
00045    + The driver API and the callback functions are at the end of the stm32f723e_discovery_audio.h file.
00046 
00047    + Call the function BSP_AUDIO_IN_Init(
00048                                     InputDevice: physical input mode (INPUT_DEVICE_DIGITAL_MICROPHONE_1, 
00049                                                   INPUT_DEVICE_DIGITAL_MICROPHONE_2, INPUT_DEVICE_DIGITAL_MIC1_MIC2
00050                                                   or INPUT_DEVICE_INPUT_LINE_1)
00051                                     Volume      : Initial volume to be set (0 is min (mute), 100 is max (100%)
00052                                     AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000...)
00053                                                   this parameter is relative to the audio file/stream type.
00054                                    )
00055       This function configures all the hardware required for the AUDIO IN application (SAI blocks, 
00056       SAI clock source, GPIOs, DMA and interrupt if needed). 
00057       This function returns AUDIO_OK if configuration is OK.If the returned value is different from AUDIO_OK then
00058       the configuration should be wrong.
00059       Note: On STM32F723E-DISCOVERY, two SAI blocks are configured and their DMA streams are configured
00060             in CIRCULAR mode.
00061    + Call the function BSP_AUDIO_IN_RECORD(
00062                                   pBuf: pointer to the recorded audio data file address
00063                                   Size: size of the buffer to be written in Bytes
00064                                  )
00065       to start recording from microphones.
00066 
00067    + Call the function BSP_AUDIO_IN_Pause() to pause recording   
00068    + Call the function BSP_AUDIO_IN_Resume() to recording playing.
00069        Note. After calling BSP_AUDIO_IN_Pause() function for pause, only BSP_AUDIO_IN_Resume() should be called
00070           for resume (it is not allowed to call BSP_AUDIO_IN_RECORD() in this case).
00071    + Call the function BSP_AUDIO_IN_Stop() to stop recording 
00072    + For each mode, you may need to implement the relative callback functions into your code.
00073       The Callback functions are named BSP_AUDIO_IN_XXX_CallBack() and only their prototypes are declared in 
00074       the stm32f723e_discovery_audio.h file. (refer to the example for more details on the callbacks implementations)
00075 
00076    + Call the function BSP_AUDIO_IN_OUT_Init(
00077                                     InputDevice : physical input mode (INPUT_DEVICE_DIGITAL_MICROPHONE_1, 
00078                                                   INPUT_DEVICE_DIGITAL_MICROPHONE_2, INPUT_DEVICE_DIGITAL_MIC1_MIC2
00079                                                   or INPUT_DEVICE_INPUT_LINE_1)
00080                                     OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 
00081                                                   OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH)
00082                                     Volume      : Initial volume to be set (0 is min (mute), 100 is max (100%)
00083                                     AudioFreq   : Audio frequency in Hz (8000, 16000, 22500, 32000...)
00084                                                   this parameter is relative to the audio file/stream type.
00085                                    )
00086       This function configures all the hardware required for the AUDIO IN(record) and AUDIO OUT(play)
00087       application (SAI blocks, SAI clock source, GPIOs, DMA and interrupt if needed). 
00088 
00089   Driver architecture:
00090   --------------------
00091    + This driver provides the High Audio Layer: consists of the function API exported in the stm32f723e_discovery_audio.h file
00092      (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...)
00093    + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/
00094      providing the audio file/stream. These functions are also included as local functions into
00095      the stm32f723e_discovery_audio.c file (SAIx_Out_Init() and SAIx_Out_DeInit(), SAIx_In_Init() and SAIx_In_DeInit())
00096 
00097   Known Limitations:
00098   ------------------
00099    1- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second 
00100       Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams.
00101    2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 
00102       File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file.
00103    3- Supports only Stereo audio streaming.
00104    4- Supports only 16-bits audio data size.
00105   @endverbatim  
00106   ******************************************************************************
00107   * @attention
00108   *
00109   * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
00110   *
00111   * Redistribution and use in source and binary forms, with or without modification,
00112   * are permitted provided that the following conditions are met:
00113   *   1. Redistributions of source code must retain the above copyright notice,
00114   *      this list of conditions and the following disclaimer.
00115   *   2. Redistributions in binary form must reproduce the above copyright notice,
00116   *      this list of conditions and the following disclaimer in the documentation
00117   *      and/or other materials provided with the distribution.
00118   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00119   *      may be used to endorse or promote products derived from this software
00120   *      without specific prior written permission.
00121   *
00122   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00123   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00124   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00125   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00126   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00127   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00128   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00129   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00130   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00131   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00132   *
00133   ******************************************************************************
00134   */
00135 /* Includes ------------------------------------------------------------------*/
00136 #include "stm32f723e_discovery_audio.h"
00137 
00138 /** @addtogroup BSP
00139   * @{
00140   */
00141 
00142 /** @addtogroup STM32F723E_DISCOVERY
00143   * @{
00144   */ 
00145   
00146 /** @defgroup STM32F723E_DISCOVERY_AUDIO STM32F723E_DISCOVERY_AUDIO
00147   * @brief This file includes the low layer driver for wm8994 Audio Codec
00148   *        available on STM32F723E-DISCOVERY discoveryuation board(MB1260).
00149   * @{
00150   */ 
00151 
00152 /** @defgroup STM32F723E_DISCOVERY_AUDIO_Private_Types STM32F723E_DISCOVERY_AUDIO Private Types
00153   * @{
00154   */
00155 /**
00156   * @}
00157   */ 
00158   
00159 /** @defgroup STM32F723E_DISCOVERY_AUDIO_Private_Defines STM32F723E_DISCOVERY_AUDIO Private Defines
00160   * @{
00161   */
00162 /**
00163   * @}
00164   */ 
00165 
00166 /** @defgroup STM32F723E_DISCOVERY_AUDIO_Private_Macros STM32F723E_DISCOVERY_AUDIO Private Macros
00167   * @{
00168   */
00169 
00170 /**
00171   * @}
00172   */ 
00173   
00174 /** @defgroup STM32F723E_DISCOVERY_AUDIO_Private_Variables STM32F723E_DISCOVERY_AUDIO Private Variables
00175   * @{
00176   */
00177 AUDIO_DrvTypeDef          *audio_drv;
00178 SAI_HandleTypeDef         haudio_out_sai;
00179 SAI_HandleTypeDef         haudio_in_sai;
00180 
00181 uint16_t __IO AudioInVolume = DEFAULT_AUDIO_IN_VOLUME;
00182 /**
00183   * @}
00184   */ 
00185 
00186 /** @defgroup STM32F723E_DISCOVERY_AUDIO_Private_Function_Prototypes STM32F723E_DISCOVERY_AUDIO Private Function Prototypes
00187   * @{
00188   */
00189 static void SAIx_Out_Init(uint32_t AudioFreq);
00190 static void SAIx_Out_DeInit(void);
00191 static void SAIx_In_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq);
00192 static void SAIx_In_DeInit(void);
00193 
00194 /**
00195   * @}
00196   */ 
00197 
00198 /** @defgroup STM32F723E_DISCOVERY_AUDIO_out_Private_Functions STM32F723E_DISCOVERY_AUDIO_Out Private Functions
00199   * @{
00200   */ 
00201 
00202 /**
00203   * @brief  Configures the audio out peripheral(SAI2 BlockA).
00204   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
00205   *                       or OUTPUT_DEVICE_BOTH.
00206   * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
00207   * @param  AudioFreq: Audio frequency used to play the audio stream.  
00208   * @retval AUDIO_OK if correct communication, else wrong communication
00209   */
00210 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
00211 { 
00212   uint8_t ret = AUDIO_ERROR;
00213   uint32_t deviceid = 0x00;
00214 
00215   /* Disable SAI */
00216   SAIx_Out_DeInit();
00217 
00218   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
00219   BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
00220  
00221   /* SAI data transfer preparation:
00222   Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
00223   haudio_out_sai.Instance = AUDIO_OUT_SAIx;
00224   if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET)
00225   {
00226     /* Init the SAI MSP: this __weak function can be redefined by the application*/
00227     BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL);
00228   }
00229   SAIx_Out_Init(AudioFreq);
00230 
00231   /* wm8994 codec initialization */
00232   deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
00233   
00234   if((deviceid) == WM8994_ID)
00235   {  
00236     /* Reset the Codec Registers */
00237     wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
00238     /* Initialize the audio driver structure */
00239     audio_drv = &wm8994_drv; 
00240     ret = AUDIO_OK;
00241   }
00242   else
00243   {
00244     ret = AUDIO_ERROR;
00245   }
00246 
00247   if(ret == AUDIO_OK)
00248   {
00249     /* Initialize the codec internal registers */
00250     audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq);
00251   }
00252  
00253   return ret;
00254 }
00255 
00256 /**
00257   * @brief  Starts playing audio stream from a data buffer for a determined size. 
00258   * @param  pBuffer: Pointer to the buffer 
00259   * @param  Size: Number of audio data BYTES.
00260   * @retval AUDIO_OK if correct communication, else wrong communication
00261   */
00262 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size)
00263 {
00264   /* Call the audio Codec Play function */
00265   if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0)
00266   {  
00267     return AUDIO_ERROR;
00268   }
00269   else
00270   {
00271     /* Update the Media layer and enable it for play */  
00272     HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE));
00273     
00274     return AUDIO_OK;
00275   }
00276 }
00277 
00278 /**
00279   * @brief  This function Pauses the audio file stream. In case
00280   *         of using DMA, the DMA Pause feature is used.
00281   * @note    When calling BSP_AUDIO_OUT_Pause() function for pause, only
00282   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00283   *          function for resume could lead to unexpected behaviour).
00284   * @retval AUDIO_OK if correct communication, else wrong communication
00285   */
00286 uint8_t BSP_AUDIO_OUT_Pause(void)
00287 {    
00288   /* Call the Audio Codec Pause/Resume function */
00289   if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0)
00290   {
00291     return AUDIO_ERROR;
00292   }
00293   else
00294   {
00295     /* Call the Media layer pause function */
00296     HAL_SAI_DMAPause(&haudio_out_sai);
00297     
00298     /* Return AUDIO_OK when all operations are correctly done */
00299     return AUDIO_OK;
00300   }
00301 }
00302 
00303 /**
00304   * @brief  This function  Resumes the audio file stream.  
00305   * @note    When calling BSP_AUDIO_OUT_Pause() function for pause, only
00306   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00307   *          function for resume could lead to unexpected behaviour).
00308   * @retval AUDIO_OK if correct communication, else wrong communication
00309   */
00310 uint8_t BSP_AUDIO_OUT_Resume(void)
00311 {    
00312   /* Call the Audio Codec Pause/Resume function */
00313   if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0)
00314   {
00315     return AUDIO_ERROR;
00316   }
00317   else
00318   {
00319     /* Call the Media layer pause/resume function */
00320     HAL_SAI_DMAResume(&haudio_out_sai);
00321     
00322     /* Return AUDIO_OK when all operations are correctly done */
00323     return AUDIO_OK;
00324   }
00325 }
00326 
00327 /**
00328   * @brief  Stops audio playing and Power down the Audio Codec. 
00329   * @param  Option: could be one of the following parameters 
00330   *           - CODEC_PDWN_SW: for software power off (by writing registers). 
00331   *                            Then no need to reconfigure the Codec after power on.
00332   *           - CODEC_PDWN_HW: completely shut down the codec (physically). 
00333   *                            Then need to reconfigure the Codec after power on.  
00334   * @retval AUDIO_OK if correct communication, else wrong communication
00335   */
00336 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
00337 {
00338   /* Call the Media layer stop function */
00339   HAL_SAI_DMAStop(&haudio_out_sai);
00340   
00341   /* Call Audio Codec Stop function */
00342   if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
00343   {
00344     return AUDIO_ERROR;
00345   }
00346   else
00347   {
00348     if(Option == CODEC_PDWN_HW)
00349     { 
00350       /* Wait at least 100us */
00351       HAL_Delay(1);
00352     }
00353     /* Return AUDIO_OK when all operations are correctly done */
00354     return AUDIO_OK;
00355   }
00356 }
00357 
00358 /**
00359   * @brief  Controls the current audio volume level. 
00360   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for 
00361   *         Mute and 100 for Max volume level).
00362   * @retval AUDIO_OK if correct communication, else wrong communication
00363   */
00364 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume)
00365 {
00366   /* Call the codec volume control function with converted volume value */
00367   if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
00368   {
00369     return AUDIO_ERROR;
00370   }
00371   else
00372   {
00373     /* Return AUDIO_OK when all operations are correctly done */
00374     return AUDIO_OK;
00375   }
00376 }
00377 
00378 /**
00379   * @brief  Enables or disables the MUTE mode by software 
00380   * @param  Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 
00381   *         unmute the codec and restore previous volume level.
00382   * @retval AUDIO_OK if correct communication, else wrong communication
00383   */
00384 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd)
00385 { 
00386   /* Call the Codec Mute function */
00387   if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0)
00388   {
00389     return AUDIO_ERROR;
00390   }
00391   else
00392   {
00393     /* Return AUDIO_OK when all operations are correctly done */
00394     return AUDIO_OK;
00395   }
00396 }
00397 
00398 /**
00399   * @brief  Switch dynamically (while audio file is played) the output target 
00400   *         (speaker or headphone).
00401   * @param  Output: The audio output target: OUTPUT_DEVICE_SPEAKER,
00402   *         OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH
00403   * @retval AUDIO_OK if correct communication, else wrong communication
00404   */
00405 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)
00406 {
00407   /* Call the Codec output device function */
00408   if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0)
00409   {
00410     return AUDIO_ERROR;
00411   }
00412   else
00413   {
00414     /* Return AUDIO_OK when all operations are correctly done */
00415     return AUDIO_OK;
00416   }
00417 }
00418 
00419 /**
00420   * @brief  Updates the audio frequency.
00421   * @param  AudioFreq: Audio frequency used to play the audio stream.
00422   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00423   *         audio frequency.
00424   * @retval None
00425   */
00426 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)
00427 { 
00428   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
00429   BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
00430 
00431   /* Disable SAI peripheral to allow access to SAI internal registers */
00432   __HAL_SAI_DISABLE(&haudio_out_sai);
00433   
00434   /* Update the SAI audio frequency configuration */
00435   haudio_out_sai.Init.AudioFrequency = AudioFreq;
00436   HAL_SAI_Init(&haudio_out_sai);
00437   
00438   /* Enable SAI peripheral to generate MCLK */
00439   __HAL_SAI_ENABLE(&haudio_out_sai);
00440 }
00441 
00442 /**
00443   * @brief  Updates the Audio frame slot configuration.
00444   * @param  AudioFrameSlot: specifies the audio Frame slot
00445   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00446   *         audio frame slot.
00447   * @retval None
00448   */
00449 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot)
00450 { 
00451   /* Disable SAI peripheral to allow access to SAI internal registers */
00452   __HAL_SAI_DISABLE(&haudio_out_sai);
00453   
00454   /* Update the SAI audio frame slot configuration */
00455   haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot;
00456   HAL_SAI_Init(&haudio_out_sai);
00457   
00458   /* Enable SAI peripheral to generate MCLK */
00459   __HAL_SAI_ENABLE(&haudio_out_sai);
00460 }
00461 
00462 /**
00463   * @brief  Send n-Bytes on the SAI interface.
00464   * @param  pData: pointer on data address 
00465   * @param  Size: number of data to be written
00466   * @retval None
00467   */
00468 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size)
00469 {
00470    HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size);
00471 }
00472                          
00473 /**
00474   * @brief  Deinit the audio peripherals.
00475   * @retval None
00476   */
00477 void BSP_AUDIO_OUT_DeInit(void)
00478 {
00479   SAIx_Out_DeInit();
00480   /* DeInit the SAI MSP : this __weak function can be rewritten by the application */
00481   BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL);
00482 }
00483 
00484 /**
00485   * @brief  Tx Transfer completed callbacks.
00486   * @param  hsai: SAI handle
00487   * @retval None
00488   */
00489 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
00490 {
00491   /* Manage the remaining file size and new address offset: This function 
00492      should be coded by user (its prototype is already declared in stm32f723e_discovery_audio.h) */
00493   BSP_AUDIO_OUT_TransferComplete_CallBack();
00494 }
00495 
00496 /**
00497   * @brief  Tx Half Transfer completed callbacks.
00498   * @param  hsai: SAI handle
00499   * @retval None
00500   */
00501 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
00502 {
00503   /* Manage the remaining file size and new address offset: This function 
00504      should be coded by user (its prototype is already declared in stm32f723e_discovery_audio.h) */
00505   BSP_AUDIO_OUT_HalfTransfer_CallBack();
00506 }
00507 
00508 /**
00509   * @brief  SAI error callbacks.
00510   * @param  hsai: SAI handle
00511   * @retval None
00512   */
00513 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
00514 {
00515   BSP_AUDIO_OUT_Error_CallBack();
00516 }
00517 
00518 /**
00519   * @brief  Manages the DMA full Transfer complete event.
00520   * @retval None
00521   */
00522 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
00523 {
00524 }
00525 
00526 /**
00527   * @brief  Manages the DMA Half Transfer complete event.
00528   * @retval None
00529   */
00530 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void)
00531 { 
00532 }
00533 
00534 /**
00535   * @brief  Manages the DMA FIFO error event.
00536   * @retval None
00537   */
00538 __weak void BSP_AUDIO_OUT_Error_CallBack(void)
00539 {
00540 }
00541 
00542 /**
00543   * @brief  Initializes BSP_AUDIO_OUT MSP.
00544   * @param  hsai: SAI handle
00545   * @param  Params  
00546   * @retval None
00547   */
00548 __weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params)
00549 { 
00550   static DMA_HandleTypeDef hdma_sai_tx;
00551   GPIO_InitTypeDef  gpio_init_structure;  
00552 
00553   /* Enable SAI clock */
00554   AUDIO_OUT_SAIx_CLK_ENABLE();
00555   
00556   /* Enable GPIO clock */
00557   AUDIO_OUT_SAIx_MCLK_ENABLE();
00558   AUDIO_OUT_SAIx_SD_FS_CLK_ENABLE();
00559 
00560   /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/
00561   gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SD_PIN;
00562   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
00563   gpio_init_structure.Pull = GPIO_NOPULL;
00564   gpio_init_structure.Speed = GPIO_SPEED_HIGH;
00565   gpio_init_structure.Alternate = AUDIO_OUT_SAIx_AF;
00566   HAL_GPIO_Init(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, &gpio_init_structure);
00567 
00568   gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN;
00569   HAL_GPIO_Init(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, &gpio_init_structure);
00570 
00571   /* Enable the DMA clock */
00572   AUDIO_OUT_SAIx_DMAx_CLK_ENABLE();
00573     
00574   if(hsai->Instance == AUDIO_OUT_SAIx)
00575   {
00576     /* Configure the hdma_saiTx handle parameters */   
00577     hdma_sai_tx.Init.Channel             = AUDIO_OUT_SAIx_DMAx_CHANNEL;
00578     hdma_sai_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
00579     hdma_sai_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
00580     hdma_sai_tx.Init.MemInc              = DMA_MINC_ENABLE;
00581     hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_OUT_SAIx_DMAx_PERIPH_DATA_SIZE;
00582     hdma_sai_tx.Init.MemDataAlignment    = AUDIO_OUT_SAIx_DMAx_MEM_DATA_SIZE;
00583     hdma_sai_tx.Init.Mode                = DMA_CIRCULAR;
00584     hdma_sai_tx.Init.Priority            = DMA_PRIORITY_HIGH;
00585     hdma_sai_tx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;         
00586     hdma_sai_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
00587     hdma_sai_tx.Init.MemBurst            = DMA_MBURST_SINGLE;
00588     hdma_sai_tx.Init.PeriphBurst         = DMA_PBURST_SINGLE; 
00589     
00590     hdma_sai_tx.Instance = AUDIO_OUT_SAIx_DMAx_STREAM;
00591     
00592     /* Associate the DMA handle */
00593     __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx);
00594     
00595     /* Deinitialize the Stream for new transfer */
00596     HAL_DMA_DeInit(&hdma_sai_tx);
00597     
00598     /* Configure the DMA Stream */
00599     HAL_DMA_Init(&hdma_sai_tx);      
00600   }
00601   
00602   /* SAI DMA IRQ Channel configuration */
00603   HAL_NVIC_SetPriority(AUDIO_OUT_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
00604   HAL_NVIC_EnableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ); 
00605 }
00606 
00607 /**
00608   * @brief  Deinitializes SAI MSP.
00609   * @param  hsai: SAI handle
00610   * @param  Params  
00611   * @retval None
00612   */
00613 __weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params)
00614 {
00615     GPIO_InitTypeDef  gpio_init_structure;
00616 
00617     /* SAI DMA IRQ Channel deactivation */
00618     HAL_NVIC_DisableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ);
00619 
00620     if(hsai->Instance == AUDIO_OUT_SAIx)
00621     {
00622       /* Deinitialize the DMA stream */
00623       HAL_DMA_DeInit(hsai->hdmatx);
00624     }
00625 
00626     /* Disable SAI peripheral */
00627     __HAL_SAI_DISABLE(hsai);  
00628 
00629     /* Deactivates CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */
00630     gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN | AUDIO_OUT_SAIx_SCK_PIN | AUDIO_OUT_SAIx_SCK_PIN;
00631     HAL_GPIO_DeInit(AUDIO_OUT_SAIx_SD_FS_SCK_GPIO_PORT, gpio_init_structure.Pin);
00632 
00633     gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN;
00634     HAL_GPIO_DeInit(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin);
00635   
00636     /* Disable SAI clock */
00637     AUDIO_OUT_SAIx_CLK_DISABLE();
00638 
00639     /* GPIO pins clock and DMA clock can be shut down in the applic 
00640        by surcharging this __weak function */ 
00641 }
00642 
00643 /**
00644   * @brief  Clock Config.
00645   * @param  hsai: might be required to set audio peripheral predivider if any.
00646   * @param  AudioFreq: Audio frequency used to play the audio stream.
00647   * @param  Params  
00648   * @note   This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency()
00649   *         Being __weak it can be overwritten by the application     
00650   * @retval None
00651   */
00652 __weak void BSP_AUDIO_OUT_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params)
00653 { 
00654   RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct;
00655 
00656   HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct);
00657   
00658   /* Set the PLL configuration according to the audio frequency */
00659   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
00660   {
00661     /* Configure PLLSAI prescalers */
00662     /* PLLSAI_VCO: VCO_429M 
00663     SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 429/2 = 214.5 Mhz
00664     SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 214.5/19 = 11.289 Mhz */ 
00665     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2;
00666     rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S;
00667     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429;
00668     rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2;
00669     rcc_ex_clk_init_struct.PLLI2SDivQ = 19;
00670     
00671     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
00672     
00673   }
00674   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
00675   {
00676     /* SAI clock config 
00677     PLLSAI_VCO: VCO_344M 
00678     SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 344/7 = 49.142 Mhz 
00679     SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 49.142/1 = 49.142 Mhz */  
00680     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2;
00681     rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S;
00682     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 
00683     rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 
00684     rcc_ex_clk_init_struct.PLLI2SDivQ = 1;      
00685     
00686     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
00687   }
00688 }
00689 
00690 /*******************************************************************************
00691                             Static Functions
00692 *******************************************************************************/
00693 
00694 /**
00695   * @brief  Initializes the Audio Codec audio interface (SAI).
00696   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00697   * @note   The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 
00698   *         and user can update this configuration using 
00699   * @retval None
00700   */
00701 static void SAIx_Out_Init(uint32_t AudioFreq)
00702 {
00703   /* Initialize the haudio_out_sai Instance parameter */
00704   haudio_out_sai.Instance = AUDIO_OUT_SAIx;
00705   
00706   /* Disable SAI peripheral to allow access to SAI internal registers */
00707   __HAL_SAI_DISABLE(&haudio_out_sai);
00708   
00709   /* Configure SAI_Block_x 
00710   LSBFirst: Disabled 
00711   DataSize: 16 */
00712   haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE;
00713   haudio_out_sai.Init.AudioFrequency = AudioFreq;
00714   haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX;
00715   haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED;
00716   haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL;
00717   haudio_out_sai.Init.DataSize = SAI_DATASIZE_16;
00718   haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
00719   haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
00720   haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS;
00721   haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
00722   haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
00723   haudio_out_sai.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
00724   haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING;
00725   haudio_out_sai.Init.TriState       = SAI_OUTPUT_NOTRELEASED;
00726   haudio_out_sai.Init.Mckdiv         = 0;
00727     
00728   /* Configure SAI_Block_x Frame 
00729   Frame Length: 64
00730   Frame active Length: 32
00731   FS Definition: Start frame + Channel Side identification
00732   FS Polarity: FS active Low
00733   FS Offset: FS asserted one bit before the first bit of slot 0 */ 
00734   haudio_out_sai.FrameInit.FrameLength = 64; 
00735   haudio_out_sai.FrameInit.ActiveFrameLength = 32;
00736   haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
00737   haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
00738   haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
00739   
00740   /* Configure SAI Block_x Slot 
00741   Slot First Bit Offset: 0
00742   Slot Size  : 16
00743   Slot Number: 4
00744   Slot Active: All slot actives */
00745   haudio_out_sai.SlotInit.FirstBitOffset = 0;
00746   haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
00747   haudio_out_sai.SlotInit.SlotNumber = 4; 
00748   haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123;
00749 
00750   HAL_SAI_Init(&haudio_out_sai);
00751   
00752   /* Enable SAI peripheral to generate MCLK */
00753   __HAL_SAI_ENABLE(&haudio_out_sai);
00754 }
00755 
00756 /**
00757   * @brief  Deinitializes the Audio Codec audio interface (SAI).
00758   * @retval None
00759   */
00760 static void SAIx_Out_DeInit(void)
00761 {
00762   /* Initialize the haudio_out_sai Instance parameter */
00763   haudio_out_sai.Instance = AUDIO_OUT_SAIx;
00764 
00765   /* Disable SAI peripheral */
00766   __HAL_SAI_DISABLE(&haudio_out_sai);
00767 
00768   HAL_SAI_DeInit(&haudio_out_sai);
00769 }
00770 
00771 
00772 /**
00773   * @}
00774   */
00775 
00776 /** @defgroup STM32F723E_DISCOVERY_AUDIO_In_Private_Functions STM32F723E_DISCOVERY_AUDIO_In Private Functions
00777   * @{
00778   */
00779 
00780 /**
00781   * @brief  Initializes wave recording.
00782   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00783   * @param  BitRes: Audio frequency to be configured.
00784   * @param  ChnlNbr: Channel number.
00785   * @retval AUDIO_OK if correct communication, else wrong communication
00786   */
00787 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00788 {
00789   return BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC1_MIC2, AudioFreq, BitRes, ChnlNbr); 
00790 }
00791 
00792 /**
00793   * @brief  Initializes wave recording.
00794   * @param  InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_1, INPUT_DEVICE_DIGITAL_MICROPHONE_2
00795   *                      INPUT_DEVICE_INPUT_LINE_1 or INPUT_DEVICE_DIGITAL_MIC1_MIC2
00796   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00797   * @param  BitRes: Audio frequency to be configured.
00798   * @param  ChnlNbr: Channel number.
00799   * @retval AUDIO_OK if correct communication, else wrong communication
00800   */
00801 uint8_t BSP_AUDIO_IN_InitEx(uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00802 {
00803   uint8_t ret = AUDIO_ERROR;
00804   uint32_t deviceid = 0x00;
00805   uint32_t slot_active;
00806   
00807   /* Only INPUT_LINE_1, MICROPHONE_1, MICROPHONE_2 and MIC1&MIC2 inputs supported */
00808   if ((InputDevice != INPUT_DEVICE_INPUT_LINE_1) &&       
00809       (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_1) &&
00810       (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2) &&
00811       (InputDevice != INPUT_DEVICE_DIGITAL_MIC1_MIC2))
00812   {
00813     ret = AUDIO_ERROR;
00814   }
00815   else
00816   {
00817     /* Disable SAI */
00818     SAIx_In_DeInit();
00819 
00820     /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
00821     BSP_AUDIO_IN_ClockConfig(&haudio_in_sai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */
00822 
00823     /* SAI data transfer preparation:
00824     Prepare the Media to be used for the audio transfer from SAI peripheral to memory */
00825     haudio_in_sai.Instance = AUDIO_IN_SAIx;
00826     if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET)
00827     {
00828       /* Init the SAI MSP: this __weak function can be redefined by the application*/
00829       BSP_AUDIO_OUT_MspInit(&haudio_in_sai, NULL);  /* Initialize GPIOs for SAI2 block A Master signals */
00830       BSP_AUDIO_IN_MspInit(&haudio_in_sai, NULL);
00831     }
00832 
00833     /* Configure SAI in master RX mode :
00834      *   - SAI2_block_A in master RX mode
00835      *   - SAI2_block_B in slave RX mode synchronous from SAI2_block_A
00836      */
00837     if (InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2)
00838     {
00839       slot_active = CODEC_AUDIOFRAME_SLOT_13;
00840     }
00841     else if (InputDevice == INPUT_DEVICE_DIGITAL_MIC1_MIC2)
00842     {
00843       slot_active = CODEC_AUDIOFRAME_SLOT_0123;
00844     }    
00845     else
00846     {
00847       slot_active = CODEC_AUDIOFRAME_SLOT_02;
00848     }
00849     SAIx_In_Init(SAI_MODEMASTER_RX, slot_active, AudioFreq);
00850 
00851     /* wm8994 codec initialization */
00852     deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
00853 
00854     if((deviceid) == WM8994_ID)
00855     {
00856       /* Reset the Codec Registers */
00857       wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
00858       /* Initialize the audio driver structure */
00859       audio_drv = &wm8994_drv;
00860       ret = AUDIO_OK;
00861     }
00862     else
00863     {
00864       ret = AUDIO_ERROR;
00865     }
00866 
00867     if(ret == AUDIO_OK)
00868     {
00869       /* Initialize the codec internal registers */
00870       audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice, 100, AudioFreq);
00871     }
00872   }
00873   return ret;
00874 }
00875 
00876 /**
00877   * @brief  Initializes wave recording and playback in parallel.
00878   * @param  InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_1, INPUT_DEVICE_DIGITAL_MICROPHONE_2 
00879   *                      or INPUT_DEVICE_DIGITAL_MIC1_MIC2
00880   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
00881   *                       or OUTPUT_DEVICE_BOTH.
00882   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00883   * @param  BitRes: Audio frequency to be configured.
00884   * @param  ChnlNbr: Channel number.
00885   * @retval AUDIO_OK if correct communication, else wrong communication
00886   */
00887 uint8_t BSP_AUDIO_IN_OUT_Init(uint16_t InputDevice, uint16_t OutputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00888 {
00889   uint8_t ret = AUDIO_ERROR;
00890   uint32_t deviceid = 0x00;
00891   uint32_t slot_active;
00892 
00893   if ((InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_1) &&
00894       (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2) &&
00895       (InputDevice != INPUT_DEVICE_DIGITAL_MIC1_MIC2))
00896   {
00897     ret = AUDIO_ERROR;
00898   }
00899   else
00900   {
00901     /* Disable SAI */
00902     SAIx_In_DeInit();
00903     SAIx_Out_DeInit();
00904 
00905     /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
00906     BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */
00907 
00908     /* SAI data transfer preparation:
00909     Prepare the Media to be used for the audio transfer from SAI peripheral to memory */
00910     haudio_in_sai.Instance = AUDIO_IN_SAIx;
00911     if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET)
00912     {
00913       /* Init the SAI MSP: this __weak function can be redefined by the application*/
00914       BSP_AUDIO_IN_MspInit(&haudio_in_sai, NULL);
00915     }
00916 
00917     /* SAI data transfer preparation:
00918     Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
00919     haudio_out_sai.Instance = AUDIO_OUT_SAIx;
00920     if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET)
00921     {
00922       /* Init the SAI MSP: this __weak function can be redefined by the application*/
00923       BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL);
00924     }
00925 
00926     /* Configure SAI in master mode :
00927      *   - SAI2_block_A in master TX mode
00928      *   - SAI2_block_B in slave RX mode synchronous from SAI2_block_A
00929      */
00930     if (InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2)
00931     {
00932       slot_active = CODEC_AUDIOFRAME_SLOT_13;
00933     }
00934     else if (InputDevice == INPUT_DEVICE_DIGITAL_MIC1_MIC2)
00935     {
00936       slot_active = CODEC_AUDIOFRAME_SLOT_0123;
00937     }    
00938     else
00939     {
00940       slot_active = CODEC_AUDIOFRAME_SLOT_02;
00941     }
00942     SAIx_In_Init(SAI_MODEMASTER_TX, slot_active, AudioFreq);
00943 
00944     /* wm8994 codec initialization */
00945     deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
00946 
00947     if((deviceid) == WM8994_ID)
00948     {
00949       /* Reset the Codec Registers */
00950       wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
00951       /* Initialize the audio driver structure */
00952       audio_drv = &wm8994_drv;
00953       ret = AUDIO_OK;
00954     }
00955     else
00956     {
00957       ret = AUDIO_ERROR;
00958     }
00959 
00960     if(ret == AUDIO_OK)
00961     {
00962       /* Initialize the codec internal registers */
00963       audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice | OutputDevice, 100, AudioFreq);
00964     }
00965   }
00966   return ret;
00967 }
00968 
00969 /**
00970   * @brief  Starts audio recording.
00971   * @param  pbuf: Main buffer pointer for the recorded data storing  
00972   * @param  size: size of the recorded buffer in number of elements (typically number of half-words)
00973   *               Be careful that it is not the same unit than BSP_AUDIO_OUT_Play function
00974   * @retval AUDIO_OK if correct communication, else wrong communication
00975   */
00976 uint8_t  BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size)
00977 {
00978   uint32_t ret = AUDIO_ERROR;
00979   
00980   /* Start the process receive DMA */
00981   if(HAL_SAI_Receive_DMA(&haudio_in_sai, (uint8_t*)pbuf, size) == HAL_OK)
00982   {
00983     /* Return AUDIO_OK when all operations are correctly done */
00984     ret = AUDIO_OK;
00985   }
00986   
00987   return ret;
00988 }
00989 
00990 /**
00991   * @brief  Stops audio recording.
00992   * @param  Option: could be one of the following parameters
00993   *           - CODEC_PDWN_SW: for software power off (by writing registers).
00994   *                            Then no need to reconfigure the Codec after power on.
00995   *           - CODEC_PDWN_HW: completely shut down the codec (physically).
00996   *                            Then need to reconfigure the Codec after power on.
00997   * @retval AUDIO_OK if correct communication, else wrong communication
00998   */
00999 uint8_t BSP_AUDIO_IN_Stop(uint32_t Option)
01000 {
01001   /* Call the Media layer stop function */
01002   HAL_SAI_DMAStop(&haudio_in_sai);
01003   
01004   /* Call Audio Codec Stop function */
01005   if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
01006   {
01007     return AUDIO_ERROR;
01008   }
01009   else
01010   {
01011     if(Option == CODEC_PDWN_HW)
01012     {
01013       /* Wait at least 100us */
01014       HAL_Delay(1);
01015     }
01016     /* Return AUDIO_OK when all operations are correctly done */
01017     return AUDIO_OK;
01018   }
01019 }
01020 
01021 /**
01022   * @brief  Pauses the audio file stream.
01023   * @retval AUDIO_OK if correct communication, else wrong communication
01024   */
01025 uint8_t BSP_AUDIO_IN_Pause(void)
01026 {    
01027   /* Call the Media layer pause function */
01028   HAL_SAI_DMAPause(&haudio_in_sai);
01029   /* Return AUDIO_OK when all operations are correctly done */
01030   return AUDIO_OK;
01031 }
01032 
01033 /**
01034   * @brief  Resumes the audio file stream.
01035   * @retval AUDIO_OK if correct communication, else wrong communication
01036   */
01037 uint8_t BSP_AUDIO_IN_Resume(void)
01038 {    
01039   /* Call the Media layer pause/resume function */
01040   HAL_SAI_DMAResume(&haudio_in_sai);
01041   /* Return AUDIO_OK when all operations are correctly done */
01042   return AUDIO_OK;
01043 }
01044 
01045 /**
01046   * @brief  Controls the audio in volume level. 
01047   * @param  Volume: Volume level in range 0(Mute)..80(+0dB)..100(+17.625dB)
01048   * @retval AUDIO_OK if correct communication, else wrong communication
01049   */
01050 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume)
01051 {
01052   /* Call the codec volume control function with converted volume value */
01053   if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
01054   {
01055     return AUDIO_ERROR;
01056   }
01057   else
01058   {
01059     /* Set the Global variable AudioInVolume  */
01060     AudioInVolume = Volume;
01061     /* Return AUDIO_OK when all operations are correctly done */
01062     return AUDIO_OK;
01063   }
01064 }
01065 
01066 /**
01067   * @brief  Deinit the audio IN peripherals.
01068   * @retval None
01069   */
01070 void BSP_AUDIO_IN_DeInit(void)
01071 {
01072   SAIx_In_DeInit();
01073   /* DeInit the SAI MSP : this __weak function can be rewritten by the application */
01074   BSP_AUDIO_IN_MspDeInit(&haudio_in_sai, NULL);
01075 }
01076 
01077  /**
01078   * @brief  Rx Transfer completed callbacks.
01079   * @param  hsai: SAI handle
01080   * @retval None
01081   */
01082 void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
01083 {
01084   /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01085   BSP_AUDIO_IN_TransferComplete_CallBack();
01086 }
01087 
01088 /**
01089   * @brief  Rx Half Transfer completed callbacks.
01090   * @param  hsai: SAI handle
01091   * @retval None
01092   */
01093 void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
01094 {
01095   /* Manage the remaining file size and new address offset: This function 
01096      should be coded by user (its prototype is already declared in stm32f723e_discovery_audio.h) */
01097   BSP_AUDIO_IN_HalfTransfer_CallBack();
01098 }
01099 
01100 /**
01101   * @brief  User callback when record buffer is filled.
01102   * @retval None
01103   */
01104 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void)
01105 {
01106   /* This function should be implemented by the user application.
01107      It is called into this driver when the current buffer is filled
01108      to prepare the next buffer pointer and its size. */
01109 }
01110 
01111 /**
01112   * @brief  Manages the DMA Half Transfer complete event.
01113   * @retval None
01114   */
01115 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
01116 { 
01117   /* This function should be implemented by the user application.
01118      It is called into this driver when the current buffer is filled
01119      to prepare the next buffer pointer and its size. */
01120 }
01121 
01122 /**
01123   * @brief  Audio IN Error callback function.
01124   * @retval None
01125   */
01126 __weak void BSP_AUDIO_IN_Error_CallBack(void)
01127 {   
01128   /* This function is called when an Interrupt due to transfer error on or peripheral
01129      error occurs. */
01130 }
01131 
01132 /**
01133   * @brief  Initializes BSP_AUDIO_IN MSP.
01134   * @param  hsai: SAI handle
01135   * @param  Params
01136   * @retval None
01137   */
01138 __weak void BSP_AUDIO_IN_MspInit(SAI_HandleTypeDef *hsai, void *Params)
01139 { 
01140   static DMA_HandleTypeDef hdma_sai_rx;
01141   GPIO_InitTypeDef  gpio_init_structure;  
01142 
01143   /* Enable SAI clock */
01144   AUDIO_IN_SAIx_CLK_ENABLE();
01145   
01146   /* Enable SD GPIO clock */
01147   AUDIO_IN_SAIx_SD_ENABLE();
01148   /* CODEC_SAI pin configuration: SD pin */
01149   gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN;
01150   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
01151   gpio_init_structure.Pull = GPIO_NOPULL;
01152   gpio_init_structure.Speed = GPIO_SPEED_FAST;
01153   gpio_init_structure.Alternate = AUDIO_IN_SAIx_SD_AF;
01154   HAL_GPIO_Init(AUDIO_IN_SAIx_SD_GPIO_PORT, &gpio_init_structure);
01155 
01156   /* Enable Audio INT GPIO clock */
01157   AUDIO_IN_INT_GPIO_ENABLE();
01158   /* Audio INT pin configuration: input */
01159   gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN;
01160   gpio_init_structure.Mode = GPIO_MODE_INPUT;
01161   gpio_init_structure.Pull = GPIO_NOPULL;
01162   gpio_init_structure.Speed = GPIO_SPEED_FAST;
01163   HAL_GPIO_Init(AUDIO_IN_INT_GPIO_PORT, &gpio_init_structure);
01164 
01165   /* Enable the DMA clock */
01166   AUDIO_IN_SAIx_DMAx_CLK_ENABLE();
01167     
01168   if(hsai->Instance == AUDIO_IN_SAIx)
01169   {
01170     /* Configure the hdma_sai_rx handle parameters */
01171     hdma_sai_rx.Init.Channel             = AUDIO_IN_SAIx_DMAx_CHANNEL;
01172     hdma_sai_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
01173     hdma_sai_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
01174     hdma_sai_rx.Init.MemInc              = DMA_MINC_ENABLE;
01175     hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAIx_DMAx_PERIPH_DATA_SIZE;
01176     hdma_sai_rx.Init.MemDataAlignment    = AUDIO_IN_SAIx_DMAx_MEM_DATA_SIZE;
01177     hdma_sai_rx.Init.Mode                = DMA_CIRCULAR;
01178     hdma_sai_rx.Init.Priority            = DMA_PRIORITY_HIGH;
01179     hdma_sai_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
01180     hdma_sai_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
01181     hdma_sai_rx.Init.MemBurst            = DMA_MBURST_SINGLE;
01182     hdma_sai_rx.Init.PeriphBurst         = DMA_MBURST_SINGLE;
01183     
01184     hdma_sai_rx.Instance = AUDIO_IN_SAIx_DMAx_STREAM;
01185     
01186     /* Associate the DMA handle */
01187     __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx);
01188     
01189     /* Deinitialize the Stream for new transfer */
01190     HAL_DMA_DeInit(&hdma_sai_rx);
01191     
01192     /* Configure the DMA Stream */
01193     HAL_DMA_Init(&hdma_sai_rx);
01194   }
01195   
01196   /* SAI DMA IRQ Channel configuration */
01197   HAL_NVIC_SetPriority(AUDIO_IN_SAIx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
01198   HAL_NVIC_EnableIRQ(AUDIO_IN_SAIx_DMAx_IRQ);
01199 
01200   /* Audio INT IRQ Channel configuration */
01201   HAL_NVIC_SetPriority(AUDIO_IN_INT_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
01202   HAL_NVIC_EnableIRQ(AUDIO_IN_INT_IRQ);
01203 }
01204 
01205 /**
01206   * @brief  DeInitializes BSP_AUDIO_IN MSP.
01207   * @param  hsai: SAI handle
01208   * @param  Params
01209   * @retval None
01210   */
01211 __weak void BSP_AUDIO_IN_MspDeInit(SAI_HandleTypeDef *hsai, void *Params)
01212 {
01213   GPIO_InitTypeDef  gpio_init_structure;
01214 
01215   /* SAI IN DMA IRQ Channel deactivation */
01216   HAL_NVIC_DisableIRQ(AUDIO_IN_SAIx_DMAx_IRQ);
01217 
01218   if(hsai->Instance == AUDIO_IN_SAIx)
01219   {
01220     /* Deinitialize the Stream for new transfer */
01221     HAL_DMA_DeInit(haudio_in_sai.hdmarx);
01222   }
01223 
01224  /* Disable SAI block */
01225   __HAL_SAI_DISABLE(hsai);
01226 
01227   /* Disable pin: SD pin */
01228   gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN;
01229   HAL_GPIO_DeInit(AUDIO_IN_SAIx_SD_GPIO_PORT, gpio_init_structure.Pin);
01230 
01231   /* Disable SAI clock */
01232   AUDIO_IN_SAIx_CLK_DISABLE();
01233 
01234   /* GPIO pins clock and DMA clock can be shut down in the application
01235      by surcharging this __weak function */
01236 }
01237 
01238 /**
01239   * @brief  Clock Config.
01240   * @param  hsai: might be required to set audio peripheral predivider if any.
01241   * @param  AudioFreq: Audio frequency used to play the audio stream.
01242   * @param  Params  
01243   * @note   This API is called by BSP_AUDIO_IN_Init() 
01244   *         Being __weak it can be overwritten by the application     
01245   * @retval None
01246   */
01247 __weak void BSP_AUDIO_IN_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params)
01248 { 
01249   RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct;
01250 
01251   HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct);
01252   
01253   /* Set the PLL configuration according to the audio frequency */
01254   if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
01255   {
01256     /* Configure PLLSAI prescalers */
01257     /* PLLSAI_VCO: VCO_429M 
01258     SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 429/2 = 214.5 Mhz
01259     SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 214.5/19 = 11.289 Mhz */ 
01260     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2;
01261     rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S;
01262     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429;
01263     rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2;
01264     rcc_ex_clk_init_struct.PLLI2SDivQ = 19;
01265     
01266     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
01267     
01268   }
01269   else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K), AUDIO_FREQUENCY_96K */
01270   {
01271     /* SAI clock config 
01272     PLLSAI_VCO: VCO_344M 
01273     SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 344/7 = 49.142 Mhz 
01274     SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 49.142/1 = 49.142 Mhz */  
01275     rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2;
01276     rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S;
01277     rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344; 
01278     rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7; 
01279     rcc_ex_clk_init_struct.PLLI2SDivQ = 1;   
01280     HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
01281   }
01282 }
01283 
01284 /*******************************************************************************
01285                             Static Functions
01286 *******************************************************************************/
01287 /**
01288   * @brief  Initializes the input Audio Codec audio interface (SAI).
01289   * @param  SaiOutMode: SAI_MODEMASTER_TX (for record and playback in parallel)
01290   *                     or SAI_MODEMASTER_RX (for record only).
01291   * @param  SlotActive: CODEC_AUDIOFRAME_SLOT_02, CODEC_AUDIOFRAME_SLOT_13 or
01292   *                     CODEC_AUDIOFRAME_SLOT_0123
01293   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
01294   * @retval None
01295   */
01296 static void SAIx_In_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq)
01297 {
01298   /* Initialize the haudio_out_sai instance parameters */
01299   haudio_out_sai.Instance = AUDIO_OUT_SAIx;
01300 
01301   /* Disable SAI peripheral to allow access to SAI internal registers */
01302   __HAL_SAI_DISABLE(&haudio_out_sai);
01303 
01304   /* Configure SAI_Block_x
01305   LSBFirst: Disabled
01306   DataSize: 16 */
01307   haudio_out_sai.Init.AudioFrequency = AudioFreq;
01308   haudio_out_sai.Init.AudioMode      = SaiOutMode;
01309   haudio_out_sai.Init.NoDivider      = SAI_MASTERDIVIDER_ENABLE;
01310   haudio_out_sai.Init.Protocol       = SAI_FREE_PROTOCOL;
01311   haudio_out_sai.Init.DataSize       = SAI_DATASIZE_16;
01312   haudio_out_sai.Init.FirstBit       = SAI_FIRSTBIT_MSB;
01313   haudio_out_sai.Init.ClockStrobing  = SAI_CLOCKSTROBING_FALLINGEDGE;
01314   haudio_out_sai.Init.Synchro        = SAI_ASYNCHRONOUS;
01315   haudio_out_sai.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
01316   haudio_out_sai.Init.OutputDrive    = SAI_OUTPUTDRIVE_DISABLE;
01317   haudio_out_sai.Init.FIFOThreshold  = SAI_FIFOTHRESHOLD_1QF;
01318   haudio_out_sai.Init.Mckdiv         = 0;
01319   haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE;
01320   haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING;
01321   haudio_out_sai.Init.TriState       = SAI_OUTPUT_NOTRELEASED;  
01322 
01323   /* Configure SAI_Block_x Frame
01324   Frame Length: 64
01325   Frame active Length: 32
01326   FS Definition: Start frame + Channel Side identification
01327   FS Polarity: FS active Low
01328   FS Offset: FS asserted one bit before the first bit of slot 0 */
01329   haudio_out_sai.FrameInit.FrameLength = 64;
01330   haudio_out_sai.FrameInit.ActiveFrameLength = 32;
01331   haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
01332   haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
01333   haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
01334 
01335   /* Configure SAI Block_x Slot
01336   Slot First Bit Offset: 0
01337   Slot Size  : 16
01338   Slot Number: 4
01339   Slot Active: All slot actives */
01340   haudio_out_sai.SlotInit.FirstBitOffset = 0;
01341   haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
01342   haudio_out_sai.SlotInit.SlotNumber = 4;
01343   haudio_out_sai.SlotInit.SlotActive = SlotActive;
01344 
01345   HAL_SAI_Init(&haudio_out_sai);
01346   
01347   /* Initialize SAI2 block B in SLAVE RX synchronous from SAI2 block A */
01348   /* Initialize the haudio_in_sai instance parameters */
01349   haudio_in_sai.Instance = AUDIO_IN_SAIx;
01350   
01351   /* Disable SAI peripheral to allow access to SAI internal registers */
01352   __HAL_SAI_DISABLE(&haudio_in_sai);
01353   
01354   /* Configure SAI_Block_x
01355   LSBFirst: Disabled
01356   DataSize: 16 */
01357   haudio_in_sai.Init.AudioFrequency = AudioFreq;
01358   haudio_in_sai.Init.AudioMode      = SAI_MODESLAVE_RX;
01359   haudio_in_sai.Init.NoDivider      = SAI_MASTERDIVIDER_ENABLE;
01360   haudio_in_sai.Init.Protocol       = SAI_FREE_PROTOCOL;
01361   haudio_in_sai.Init.DataSize       = SAI_DATASIZE_16;
01362   haudio_in_sai.Init.FirstBit       = SAI_FIRSTBIT_MSB;
01363   haudio_in_sai.Init.ClockStrobing  = SAI_CLOCKSTROBING_RISINGEDGE;
01364   haudio_in_sai.Init.Synchro        = SAI_SYNCHRONOUS;
01365   haudio_in_sai.Init.SynchroExt     = SAI_SYNCEXT_DISABLE;
01366   haudio_in_sai.Init.OutputDrive    = SAI_OUTPUTDRIVE_DISABLE;
01367   haudio_in_sai.Init.FIFOThreshold  = SAI_FIFOTHRESHOLD_1QF;
01368   haudio_in_sai.Init.Mckdiv         = 0;
01369   haudio_in_sai.Init.MonoStereoMode = SAI_STEREOMODE;
01370   haudio_in_sai.Init.CompandingMode = SAI_NOCOMPANDING;
01371   haudio_in_sai.Init.TriState       = SAI_OUTPUT_NOTRELEASED;
01372   
01373   /* Configure SAI_Block_x Frame
01374   Frame Length: 64
01375   Frame active Length: 32
01376   FS Definition: Start frame + Channel Side identification
01377   FS Polarity: FS active Low
01378   FS Offset: FS asserted one bit before the first bit of slot 0 */
01379   haudio_in_sai.FrameInit.FrameLength = 64;
01380   haudio_in_sai.FrameInit.ActiveFrameLength = 32;
01381   haudio_in_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
01382   haudio_in_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
01383   haudio_in_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
01384   
01385   /* Configure SAI Block_x Slot
01386   Slot First Bit Offset: 0
01387   Slot Size  : 16
01388   Slot Number: 4
01389   Slot Active: All slot active */
01390   haudio_in_sai.SlotInit.FirstBitOffset = 0;
01391   haudio_in_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
01392   haudio_in_sai.SlotInit.SlotNumber = 4;
01393   haudio_in_sai.SlotInit.SlotActive = SlotActive;
01394 
01395   HAL_SAI_Init(&haudio_in_sai);
01396   
01397   /* Enable SAI peripheral */
01398   __HAL_SAI_ENABLE(&haudio_in_sai);
01399   
01400   /* Enable SAI peripheral to generate MCLK */
01401   __HAL_SAI_ENABLE(&haudio_out_sai);
01402 }
01403 
01404 
01405 
01406 /**
01407   * @brief  Deinitializes the output Audio Codec audio interface (SAI).
01408   * @retval None
01409   */
01410 static void SAIx_In_DeInit(void)
01411 {
01412   /* Initialize the haudio_in_sai Instance parameter */
01413   haudio_in_sai.Instance = AUDIO_IN_SAIx;
01414 
01415   /* Disable SAI peripheral */
01416   __HAL_SAI_DISABLE(&haudio_in_sai);
01417 
01418   HAL_SAI_DeInit(&haudio_in_sai);
01419 }
01420 
01421 /**
01422   * @}
01423   */ 
01424   
01425 /**
01426   * @}
01427   */
01428 
01429 /**
01430   * @}
01431   */
01432 
01433 /**
01434   * @}
01435   */ 
01436 
01437 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Mon Jan 2 2017 09:52:50 for STM32F723E-Discovery BSP User Manual by   doxygen 1.7.6.1