bugfixes and reduced version for disco board only

Dependents:   Scope DISCO-F746NG_Sinewave DISCO-F746NG_Sweep DISCO-F746NG_Oscilloscope ... more

Fork of BSP_DISCO_F746NG_patch by Nirvana Jay

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32746g_discovery_audio.c Source File

stm32746g_discovery_audio.c

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