STM32746G-Discovery board drivers V1.0.0

Dependents:   F746_SD_GraphicEqualizer_ren0620

Fork of BSP_DISCO_F746NG by ST

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