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

STM32F723E-Discovery BSP

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