STM32746G-Discovery board drivers V1.0.0

Dependents:   DISCO-F746NG_LCDTS_CC3000_NTP DISCO-F746NG_ROPE_WIFI F746_SpectralAnalysis_NoPhoto ecte433 ... more

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