No changes made

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 V2.0.0
00006   * @date    30-December-2016
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) 2016 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 void wait_ms(int ms); // MBED to replace HAL_Delay function
00099 
00100 /** @addtogroup BSP
00101   * @{
00102   */
00103 
00104 /** @addtogroup STM32746G_DISCOVERY
00105   * @{
00106   */ 
00107   
00108 /** @defgroup STM32746G_DISCOVERY_AUDIO STM32746G_DISCOVERY AUDIO
00109   * @brief This file includes the low layer driver for wm8994 Audio Codec
00110   *        available on STM32746G-Discovery board(MB1191).
00111   * @{
00112   */ 
00113 
00114 /** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Types STM32746G_DISCOVERY AUDIO Private Types
00115   * @{
00116   */ 
00117 /**
00118   * @}
00119   */ 
00120   
00121 /** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Defines STM32746G_DISCOVERY AUDIO Private Defines
00122   * @{
00123   */
00124 /**
00125   * @}
00126   */ 
00127 
00128 /** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Macros STM32746G_DISCOVERY AUDIO Private Macros
00129   * @{
00130   */
00131 /**
00132   * @}
00133   */ 
00134   
00135 /** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Variables STM32746G_DISCOVERY AUDIO Private Variables
00136   * @{
00137   */
00138 AUDIO_DrvTypeDef          *audio_drv;
00139 SAI_HandleTypeDef         haudio_out_sai={0};
00140 SAI_HandleTypeDef         haudio_in_sai={0};
00141 TIM_HandleTypeDef         haudio_tim;
00142 
00143 uint16_t __IO AudioInVolume = DEFAULT_AUDIO_IN_VOLUME;
00144     
00145 /**
00146   * @}
00147   */ 
00148 
00149 /** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Function_Prototypes STM32746G_DISCOVERY AUDIO Private Function Prototypes
00150   * @{
00151   */
00152 static void AUDIO_IN_INT_IRQHandler(void); // MBED
00153 static void AUDIO_IN_SAIx_DMAx_IRQHandler(void); // MBED
00154 static void AUDIO_OUT_SAIx_DMAx_IRQHandler(void); // MBED
00155 static void SAIx_Out_Init(uint32_t AudioFreq);
00156 static void SAIx_Out_DeInit(void);
00157 static void SAIx_In_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq);
00158 static void SAIx_In_DeInit(void);
00159 /**
00160   * @}
00161   */ 
00162 
00163 /** @defgroup STM32746G_DISCOVERY_AUDIO_OUT_Exported_Functions STM32746G_DISCOVERY AUDIO Out Exported Functions
00164   * @{
00165   */ 
00166 
00167 /**
00168   * @brief  Configures the audio peripherals.
00169   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
00170   *                       or OUTPUT_DEVICE_BOTH.
00171   * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
00172   * @param  AudioFreq: Audio frequency used to play the audio stream.
00173   * @note   The I2S PLL input clock must be done in the user application.  
00174   * @retval AUDIO_OK if correct communication, else wrong communication
00175   */
00176 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
00177 { 
00178   uint8_t ret = AUDIO_ERROR;
00179   uint32_t deviceid = 0x00;
00180 
00181   /* Disable SAI */
00182   SAIx_Out_DeInit();
00183 
00184   /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
00185   BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
00186  
00187   /* SAI data transfer preparation:
00188   Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
00189   haudio_out_sai.Instance = AUDIO_OUT_SAIx;
00190   if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET)
00191   {
00192     /* Init the SAI MSP: this __weak function can be redefined by the application*/
00193     BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL);
00194   }
00195   SAIx_Out_Init(AudioFreq);
00196 
00197   /* wm8994 codec initialization */
00198   deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
00199   
00200   if((deviceid) == WM8994_ID)
00201   {  
00202     /* Reset the Codec Registers */
00203     wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
00204     /* Initialize the audio driver structure */
00205     audio_drv = &wm8994_drv; 
00206     ret = AUDIO_OK;
00207   }
00208   else
00209   {
00210     ret = AUDIO_ERROR;
00211   }
00212 
00213   if(ret == AUDIO_OK)
00214   {
00215     /* Initialize the codec internal registers */
00216     audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq);
00217   }
00218  
00219   return ret;
00220 }
00221 
00222 /**
00223   * @brief  Starts playing audio stream from a data buffer for a determined size. 
00224   * @param  pBuffer: Pointer to the buffer 
00225   * @param  Size: Number of audio data in BYTES unit.
00226   *         In memory, first element is for left channel, second element is for right channel
00227   * @retval AUDIO_OK if correct communication, else wrong communication
00228   */
00229 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size)
00230 {
00231   /* Call the audio Codec Play function */
00232   if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0)
00233   {  
00234     return AUDIO_ERROR;
00235   }
00236   else
00237   {
00238     /* Update the Media layer and enable it for play */  
00239     HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE));
00240     
00241     return AUDIO_OK;
00242   }
00243 }
00244 
00245 /**
00246   * @brief  Sends n-Bytes on the SAI interface.
00247   * @param  pData: pointer on data address 
00248   * @param  Size: number of data to be written
00249   * @retval None
00250   */
00251 void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size)
00252 {
00253    HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size);
00254 }
00255 
00256 /**
00257   * @brief  This function Pauses the audio file stream. In case
00258   *         of using DMA, the DMA Pause feature is used.
00259   * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only
00260   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00261   *          function for resume could lead to unexpected behaviour).
00262   * @retval AUDIO_OK if correct communication, else wrong communication
00263   */
00264 uint8_t BSP_AUDIO_OUT_Pause(void)
00265 {    
00266   /* Call the Audio Codec Pause/Resume function */
00267   if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0)
00268   {
00269     return AUDIO_ERROR;
00270   }
00271   else
00272   {
00273     /* Call the Media layer pause function */
00274     HAL_SAI_DMAPause(&haudio_out_sai);
00275     
00276     /* Return AUDIO_OK when all operations are correctly done */
00277     return AUDIO_OK;
00278   }
00279 }
00280 
00281 /**
00282   * @brief  This function  Resumes the audio file stream.  
00283   * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only
00284   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
00285   *          function for resume could lead to unexpected behaviour).
00286   * @retval AUDIO_OK if correct communication, else wrong communication
00287   */
00288 uint8_t BSP_AUDIO_OUT_Resume(void)
00289 {    
00290   /* Call the Audio Codec Pause/Resume function */
00291   if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0)
00292   {
00293     return AUDIO_ERROR;
00294   }
00295   else
00296   {
00297     /* Call the Media layer pause/resume function */
00298     HAL_SAI_DMAResume(&haudio_out_sai);
00299     
00300     /* Return AUDIO_OK when all operations are correctly done */
00301     return AUDIO_OK;
00302   }
00303 }
00304 
00305 /**
00306   * @brief  Stops audio playing and Power down the Audio Codec. 
00307   * @param  Option: could be one of the following parameters 
00308   *           - CODEC_PDWN_SW: for software power off (by writing registers). 
00309   *                            Then no need to reconfigure the Codec after power on.
00310   *           - CODEC_PDWN_HW: completely shut down the codec (physically). 
00311   *                            Then need to reconfigure the Codec after power on.  
00312   * @retval AUDIO_OK if correct communication, else wrong communication
00313   */
00314 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
00315 {
00316   /* Call the Media layer stop function */
00317   HAL_SAI_DMAStop(&haudio_out_sai);
00318   
00319   /* Call Audio Codec Stop function */
00320   if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
00321   {
00322     return AUDIO_ERROR;
00323   }
00324   else
00325   {
00326     if(Option == CODEC_PDWN_HW)
00327     { 
00328       /* Wait at least 100us */
00329       wait_ms(1);
00330     }
00331     /* Return AUDIO_OK when all operations are correctly done */
00332     return AUDIO_OK;
00333   }
00334 }
00335 
00336 /**
00337   * @brief  Controls the current audio volume level. 
00338   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for 
00339   *         Mute and 100 for Max volume level).
00340   * @retval AUDIO_OK if correct communication, else wrong communication
00341   */
00342 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume)
00343 {
00344   /* Call the codec volume control function with converted volume value */
00345   if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
00346   {
00347     return AUDIO_ERROR;
00348   }
00349   else
00350   {
00351     /* Return AUDIO_OK when all operations are correctly done */
00352     return AUDIO_OK;
00353   }
00354 }
00355 
00356 /**
00357   * @brief  Enables or disables the MUTE mode by software 
00358   * @param  Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 
00359   *         unmute the codec and restore previous volume level.
00360   * @retval AUDIO_OK if correct communication, else wrong communication
00361   */
00362 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd)
00363 { 
00364   /* Call the Codec Mute function */
00365   if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0)
00366   {
00367     return AUDIO_ERROR;
00368   }
00369   else
00370   {
00371     /* Return AUDIO_OK when all operations are correctly done */
00372     return AUDIO_OK;
00373   }
00374 }
00375 
00376 /**
00377   * @brief  Switch dynamically (while audio file is played) the output target 
00378   *         (speaker or headphone).
00379   * @param  Output: The audio output target: OUTPUT_DEVICE_SPEAKER,
00380   *         OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH
00381   * @retval AUDIO_OK if correct communication, else wrong communication
00382   */
00383 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)
00384 {
00385   /* Call the Codec output device function */
00386   if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0)
00387   {
00388     return AUDIO_ERROR;
00389   }
00390   else
00391   {
00392     /* Return AUDIO_OK when all operations are correctly done */
00393     return AUDIO_OK;
00394   }
00395 }
00396 
00397 /**
00398   * @brief  Updates the audio frequency.
00399   * @param  AudioFreq: Audio frequency used to play the audio stream.
00400   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00401   *         audio frequency.
00402   * @retval None
00403   */
00404 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)
00405 { 
00406   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
00407   BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
00408 
00409   /* Disable SAI peripheral to allow access to SAI internal registers */
00410   __HAL_SAI_DISABLE(&haudio_out_sai);
00411   
00412   /* Update the SAI audio frequency configuration */
00413   haudio_out_sai.Init.AudioFrequency = AudioFreq;
00414   HAL_SAI_Init(&haudio_out_sai);
00415   
00416   /* Enable SAI peripheral to generate MCLK */
00417   __HAL_SAI_ENABLE(&haudio_out_sai);
00418 }
00419 
00420 /**
00421   * @brief  Updates the Audio frame slot configuration.
00422   * @param  AudioFrameSlot: specifies the audio Frame slot
00423   *         This parameter can be one of the following values
00424   *            @arg CODEC_AUDIOFRAME_SLOT_0123
00425   *            @arg CODEC_AUDIOFRAME_SLOT_02
00426   *            @arg CODEC_AUDIOFRAME_SLOT_13
00427   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
00428   *         audio frame slot.
00429   * @retval None
00430   */
00431 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot)
00432 { 
00433   /* Disable SAI peripheral to allow access to SAI internal registers */
00434   __HAL_SAI_DISABLE(&haudio_out_sai);
00435   
00436   /* Update the SAI audio frame slot configuration */
00437   haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot;
00438   HAL_SAI_Init(&haudio_out_sai);
00439   
00440   /* Enable SAI peripheral to generate MCLK */
00441   __HAL_SAI_ENABLE(&haudio_out_sai);
00442 }
00443 
00444 /**
00445   * @brief  Deinit the audio peripherals.
00446   * @retval None
00447   */
00448 void BSP_AUDIO_OUT_DeInit(void)
00449 {
00450   SAIx_Out_DeInit();
00451   /* DeInit the SAI MSP : this __weak function can be rewritten by the application */
00452   BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL);
00453 }
00454 
00455 /**
00456   * @brief  Tx Transfer completed callbacks.
00457   * @param  hsai: SAI handle
00458   * @retval None
00459   */
00460 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
00461 {
00462   /* Manage the remaining file size and new address offset: This function 
00463      should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */
00464   BSP_AUDIO_OUT_TransferComplete_CallBack();
00465 }
00466 
00467 /**
00468   * @brief  Tx Half Transfer completed callbacks.
00469   * @param  hsai: SAI handle
00470   * @retval None
00471   */
00472 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
00473 {
00474   /* Manage the remaining file size and new address offset: This function 
00475      should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */
00476   BSP_AUDIO_OUT_HalfTransfer_CallBack();
00477 }
00478 
00479 /**
00480   * @brief  SAI error callbacks.
00481   * @param  hsai: SAI handle
00482   * @retval None
00483   */
00484 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
00485 {
00486   HAL_SAI_StateTypeDef audio_out_state;
00487   HAL_SAI_StateTypeDef audio_in_state;
00488 
00489   audio_out_state = HAL_SAI_GetState(&haudio_out_sai);
00490   audio_in_state = HAL_SAI_GetState(&haudio_in_sai);
00491 
00492   /* Determines if it is an audio out or audio in error */
00493   if ((audio_out_state == HAL_SAI_STATE_BUSY) || (audio_out_state == HAL_SAI_STATE_BUSY_TX))
00494   {
00495     BSP_AUDIO_OUT_Error_CallBack();
00496   }
00497 
00498   if ((audio_in_state == HAL_SAI_STATE_BUSY) || (audio_in_state == HAL_SAI_STATE_BUSY_RX))
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  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00799   * @param  BitRes: Audio frequency to be configured.
00800   * @param  ChnlNbr: Channel number.
00801   * @retval AUDIO_OK if correct communication, else wrong communication
00802   */
00803 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00804 {
00805   return BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MICROPHONE_2, AudioFreq, BitRes, ChnlNbr); 
00806 }
00807 
00808 /**
00809   * @brief  Initializes wave recording.
00810   * @param  InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_2 or INPUT_DEVICE_INPUT_LINE_1
00811   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00812   * @param  BitRes: Audio frequency to be configured.
00813   * @param  ChnlNbr: Channel number.
00814   * @retval AUDIO_OK if correct communication, else wrong communication
00815   */
00816 uint8_t BSP_AUDIO_IN_InitEx(uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00817 {
00818   uint8_t ret = AUDIO_ERROR;
00819   uint32_t deviceid = 0x00;
00820   uint32_t slot_active;
00821 
00822   if ((InputDevice != INPUT_DEVICE_INPUT_LINE_1) &&       /* Only INPUT_LINE_1 and MICROPHONE_2 inputs supported */
00823       (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2))
00824   {
00825     ret = AUDIO_ERROR;
00826   }
00827   else
00828   {
00829     /* Disable SAI */
00830     SAIx_In_DeInit();
00831 
00832     /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
00833     BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */
00834 
00835     /* SAI data transfer preparation:
00836     Prepare the Media to be used for the audio transfer from SAI peripheral to memory */
00837     haudio_in_sai.Instance = AUDIO_IN_SAIx;
00838     if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET)
00839     {
00840       /* Init the SAI MSP: this __weak function can be redefined by the application*/
00841       BSP_AUDIO_OUT_MspInit(&haudio_in_sai, NULL);  /* Initialize GPIOs for SAI2 block A Master signals */
00842       BSP_AUDIO_IN_MspInit(&haudio_in_sai, NULL);
00843     }
00844 
00845     /* Configure SAI in master RX mode :
00846      *   - SAI2_block_A in master RX mode
00847      *   - SAI2_block_B in slave RX mode synchronous from SAI2_block_A
00848      */
00849     if (InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2)
00850     {
00851       slot_active = CODEC_AUDIOFRAME_SLOT_13;
00852     }
00853     else
00854     {
00855       slot_active = CODEC_AUDIOFRAME_SLOT_02;
00856     }
00857     SAIx_In_Init(SAI_MODEMASTER_RX, slot_active, AudioFreq);
00858 
00859     /* wm8994 codec initialization */
00860     deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
00861 
00862     if((deviceid) == WM8994_ID)
00863     {
00864       /* Reset the Codec Registers */
00865       wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
00866       /* Initialize the audio driver structure */
00867       audio_drv = &wm8994_drv;
00868       ret = AUDIO_OK;
00869     }
00870     else
00871     {
00872       ret = AUDIO_ERROR;
00873     }
00874 
00875     if(ret == AUDIO_OK)
00876     {
00877       /* Initialize the codec internal registers */
00878       audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice, 100, AudioFreq);
00879     }
00880   }
00881   return ret;
00882 }
00883 
00884 /**
00885   * @brief  Initializes wave recording and playback in parallel.
00886   * @param  InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_2
00887   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
00888   *                       or OUTPUT_DEVICE_BOTH.
00889   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
00890   * @param  BitRes: Audio frequency to be configured.
00891   * @param  ChnlNbr: Channel number.
00892   * @retval AUDIO_OK if correct communication, else wrong communication
00893   */
00894 uint8_t BSP_AUDIO_IN_OUT_Init(uint16_t InputDevice, uint16_t OutputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
00895 {
00896   uint8_t ret = AUDIO_ERROR;
00897   uint32_t deviceid = 0x00;
00898   uint32_t slot_active;
00899 
00900   if (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2)  /* Only MICROPHONE_2 input supported */
00901   {
00902     ret = AUDIO_ERROR;
00903   }
00904   else
00905   {
00906     /* Disable SAI */
00907     SAIx_In_DeInit();
00908     SAIx_Out_DeInit();
00909 
00910     /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
00911     BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */
00912 
00913     /* SAI data transfer preparation:
00914     Prepare the Media to be used for the audio transfer from SAI peripheral to memory */
00915     haudio_in_sai.Instance = AUDIO_IN_SAIx;
00916     if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET)
00917     {
00918       /* Init the SAI MSP: this __weak function can be redefined by the application*/
00919       BSP_AUDIO_IN_MspInit(&haudio_in_sai, NULL);
00920     }
00921 
00922     /* SAI data transfer preparation:
00923     Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
00924     haudio_out_sai.Instance = AUDIO_OUT_SAIx;
00925     if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET)
00926     {
00927       /* Init the SAI MSP: this __weak function can be redefined by the application*/
00928       BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL);
00929     }
00930 
00931     /* Configure SAI in master mode :
00932      *   - SAI2_block_A in master TX mode
00933      *   - SAI2_block_B in slave RX mode synchronous from SAI2_block_A
00934      */
00935     if (InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2)
00936     {
00937       slot_active = CODEC_AUDIOFRAME_SLOT_13;
00938     }
00939     else
00940     {
00941       slot_active = CODEC_AUDIOFRAME_SLOT_02;
00942     }
00943     SAIx_In_Init(SAI_MODEMASTER_TX, slot_active, AudioFreq);
00944 
00945     /* wm8994 codec initialization */
00946     deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
00947 
00948     if((deviceid) == WM8994_ID)
00949     {
00950       /* Reset the Codec Registers */
00951       wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
00952       /* Initialize the audio driver structure */
00953       audio_drv = &wm8994_drv;
00954       ret = AUDIO_OK;
00955     }
00956     else
00957     {
00958       ret = AUDIO_ERROR;
00959     }
00960 
00961     if(ret == AUDIO_OK)
00962     {
00963       /* Initialize the codec internal registers */
00964       audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice | OutputDevice, 100, AudioFreq);
00965     }
00966   }
00967   return ret;
00968 }
00969 
00970 
00971 /**
00972   * @brief  Starts audio recording.
00973   * @param  pbuf: Main buffer pointer for the recorded data storing  
00974   * @param  size: size of the recorded buffer in number of elements (typically number of half-words)
00975   *               Be careful that it is not the same unit than BSP_AUDIO_OUT_Play function
00976   * @retval AUDIO_OK if correct communication, else wrong communication
00977   */
00978 uint8_t  BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size)
00979 {
00980   uint32_t ret = AUDIO_ERROR;
00981   
00982   /* Start the process receive DMA */
00983   HAL_SAI_Receive_DMA(&haudio_in_sai, (uint8_t*)pbuf, size);
00984   
00985   /* Return AUDIO_OK when all operations are correctly done */
00986   ret = AUDIO_OK;
00987   
00988   return ret;
00989 }
00990 
00991 /**
00992   * @brief  Stops audio recording.
00993   * @param  Option: could be one of the following parameters
00994   *           - CODEC_PDWN_SW: for software power off (by writing registers).
00995   *                            Then no need to reconfigure the Codec after power on.
00996   *           - CODEC_PDWN_HW: completely shut down the codec (physically).
00997   *                            Then need to reconfigure the Codec after power on.
00998   * @retval AUDIO_OK if correct communication, else wrong communication
00999   */
01000 uint8_t BSP_AUDIO_IN_Stop(uint32_t Option)
01001 {
01002   /* Call the Media layer stop function */
01003   HAL_SAI_DMAStop(&haudio_in_sai);
01004   
01005   /* Call Audio Codec Stop function */
01006   if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
01007   {
01008     return AUDIO_ERROR;
01009   }
01010   else
01011   {
01012     if(Option == CODEC_PDWN_HW)
01013     {
01014       /* Wait at least 100us */
01015       wait_ms(1);
01016     }
01017     /* Return AUDIO_OK when all operations are correctly done */
01018     return AUDIO_OK;
01019   }
01020 }
01021 
01022 /**
01023   * @brief  Pauses the audio file stream.
01024   * @retval AUDIO_OK if correct communication, else wrong communication
01025   */
01026 uint8_t BSP_AUDIO_IN_Pause(void)
01027 {    
01028   /* Call the Media layer pause function */
01029   HAL_SAI_DMAPause(&haudio_in_sai);
01030   /* Return AUDIO_OK when all operations are correctly done */
01031   return AUDIO_OK;
01032 }
01033 
01034 /**
01035   * @brief  Resumes the audio file stream.
01036   * @retval AUDIO_OK if correct communication, else wrong communication
01037   */
01038 uint8_t BSP_AUDIO_IN_Resume(void)
01039 {    
01040   /* Call the Media layer pause/resume function */
01041   HAL_SAI_DMAResume(&haudio_in_sai);
01042   /* Return AUDIO_OK when all operations are correctly done */
01043   return AUDIO_OK;
01044 }
01045 
01046 /**
01047   * @brief  Controls the audio in volume level. 
01048   * @param  Volume: Volume level in range 0(Mute)..80(+0dB)..100(+17.625dB)
01049   * @retval AUDIO_OK if correct communication, else wrong communication
01050   */
01051 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume)
01052 {
01053   /* Call the codec volume control function with converted volume value */
01054   if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
01055   {
01056     return AUDIO_ERROR;
01057   }
01058   else
01059   {
01060     /* Set the Global variable AudioInVolume  */
01061     AudioInVolume = Volume;
01062     /* Return AUDIO_OK when all operations are correctly done */
01063     return AUDIO_OK;
01064   }
01065 }
01066 
01067 /**
01068   * @brief  Deinit the audio IN peripherals.
01069   * @retval None
01070   */
01071 void BSP_AUDIO_IN_DeInit(void)
01072 {
01073   SAIx_In_DeInit();
01074   /* DeInit the SAI MSP : this __weak function can be rewritten by the application */
01075   BSP_AUDIO_IN_MspDeInit(&haudio_in_sai, NULL);
01076 }
01077 
01078  /**
01079   * @brief  Rx Transfer completed callbacks.
01080   * @param  hsai: SAI handle
01081   * @retval None
01082   */
01083 void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
01084 {
01085   /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
01086   BSP_AUDIO_IN_TransferComplete_CallBack();
01087 }
01088 
01089 /**
01090   * @brief  Rx Half Transfer completed callbacks.
01091   * @param  hsai: SAI handle
01092   * @retval None
01093   */
01094 void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
01095 {
01096   /* Manage the remaining file size and new address offset: This function 
01097      should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */
01098   BSP_AUDIO_IN_HalfTransfer_CallBack();
01099 }
01100 
01101 /**
01102   * @brief  User callback when record buffer is filled.
01103   * @retval None
01104   */
01105 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void)
01106 {
01107   /* This function should be implemented by the user application.
01108      It is called into this driver when the current buffer is filled
01109      to prepare the next buffer pointer and its size. */
01110 }
01111 
01112 /**
01113   * @brief  Manages the DMA Half Transfer complete event.
01114   * @retval None
01115   */
01116 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
01117 { 
01118   /* This function should be implemented by the user application.
01119      It is called into this driver when the current buffer is filled
01120      to prepare the next buffer pointer and its size. */
01121 }
01122 
01123 /**
01124   * @brief  Audio IN Error callback function.
01125   * @retval None
01126   */
01127 __weak void BSP_AUDIO_IN_Error_CallBack(void)
01128 {   
01129   /* This function is called when an Interrupt due to transfer error on or peripheral
01130      error occurs. */
01131 }
01132 
01133 /**
01134   * @brief  Initializes BSP_AUDIO_IN MSP.
01135   * @param  hsai: SAI handle
01136   * @param  Params
01137   * @retval None
01138   */
01139 __weak void BSP_AUDIO_IN_MspInit(SAI_HandleTypeDef *hsai, void *Params)
01140 {
01141   static DMA_HandleTypeDef hdma_sai_rx;
01142   GPIO_InitTypeDef  gpio_init_structure;  
01143 
01144   /* Enable SAI clock */
01145   AUDIO_IN_SAIx_CLK_ENABLE();
01146   
01147   /* Enable SD GPIO clock */
01148   AUDIO_IN_SAIx_SD_ENABLE();
01149   /* CODEC_SAI pin configuration: SD pin */
01150   gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN;
01151   gpio_init_structure.Mode = GPIO_MODE_AF_PP;
01152   gpio_init_structure.Pull = GPIO_NOPULL;
01153   gpio_init_structure.Speed = GPIO_SPEED_FAST;
01154   gpio_init_structure.Alternate = AUDIO_IN_SAIx_SD_AF;
01155   HAL_GPIO_Init(AUDIO_IN_SAIx_SD_GPIO_PORT, &gpio_init_structure);
01156 
01157   /* Enable Audio INT GPIO clock */
01158   AUDIO_IN_INT_GPIO_ENABLE();
01159   /* Audio INT pin configuration: input */
01160   gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN;
01161   gpio_init_structure.Mode = GPIO_MODE_INPUT;
01162   gpio_init_structure.Pull = GPIO_NOPULL;
01163   gpio_init_structure.Speed = GPIO_SPEED_FAST;
01164   HAL_GPIO_Init(AUDIO_IN_INT_GPIO_PORT, &gpio_init_structure);
01165 
01166   /* Enable the DMA clock */
01167   AUDIO_IN_SAIx_DMAx_CLK_ENABLE();
01168     
01169   if(hsai->Instance == AUDIO_IN_SAIx)
01170   {
01171     /* Configure the hdma_sai_rx handle parameters */
01172     hdma_sai_rx.Init.Channel             = AUDIO_IN_SAIx_DMAx_CHANNEL;
01173     hdma_sai_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
01174     hdma_sai_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
01175     hdma_sai_rx.Init.MemInc              = DMA_MINC_ENABLE;
01176     hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAIx_DMAx_PERIPH_DATA_SIZE;
01177     hdma_sai_rx.Init.MemDataAlignment    = AUDIO_IN_SAIx_DMAx_MEM_DATA_SIZE;
01178     hdma_sai_rx.Init.Mode                = DMA_CIRCULAR;
01179     hdma_sai_rx.Init.Priority            = DMA_PRIORITY_HIGH;
01180     hdma_sai_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
01181     hdma_sai_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
01182     hdma_sai_rx.Init.MemBurst            = DMA_MBURST_SINGLE;
01183     hdma_sai_rx.Init.PeriphBurst         = DMA_MBURST_SINGLE;
01184     
01185     hdma_sai_rx.Instance = AUDIO_IN_SAIx_DMAx_STREAM;
01186     
01187     /* Associate the DMA handle */
01188     __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx);
01189     
01190     /* Deinitialize the Stream for new transfer */
01191     HAL_DMA_DeInit(&hdma_sai_rx);
01192     
01193     /* Configure the DMA Stream */
01194     HAL_DMA_Init(&hdma_sai_rx);
01195   }
01196   
01197   /* SAI DMA IRQ Channel configuration */
01198 #if ( __MBED__ == 1)
01199     IRQn_Type irqn = (IRQn_Type)(AUDIO_IN_SAIx_DMAx_IRQ);
01200     NVIC_ClearPendingIRQ(irqn);
01201     NVIC_DisableIRQ(irqn);
01202     NVIC_SetPriority(irqn, AUDIO_IN_IRQ_PREPRIO);
01203     NVIC_SetVector(irqn, (uint32_t)AUDIO_IN_SAIx_DMAx_IRQHandler);
01204     NVIC_EnableIRQ(irqn);
01205 #else
01206   HAL_NVIC_SetPriority(AUDIO_IN_SAIx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
01207   HAL_NVIC_EnableIRQ(AUDIO_IN_SAIx_DMAx_IRQ);
01208 #endif
01209 
01210   /* Audio INT IRQ Channel configuration */
01211 #if ( __MBED__ == 1)
01212     irqn = (IRQn_Type)(AUDIO_IN_INT_IRQ);
01213     NVIC_ClearPendingIRQ(irqn);
01214     NVIC_DisableIRQ(irqn);
01215     NVIC_SetPriority(irqn, AUDIO_IN_IRQ_PREPRIO);
01216     NVIC_SetVector(irqn, (uint32_t)AUDIO_IN_INT_IRQHandler);
01217     NVIC_EnableIRQ(irqn);
01218 #else
01219   HAL_NVIC_SetPriority(AUDIO_IN_INT_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
01220   HAL_NVIC_EnableIRQ(AUDIO_IN_INT_IRQ);
01221 #endif
01222 }
01223 
01224 /**
01225   * @brief  DeInitializes BSP_AUDIO_IN MSP.
01226   * @param  hsai: SAI handle
01227   * @param  Params
01228   * @retval None
01229   */
01230 __weak void BSP_AUDIO_IN_MspDeInit(SAI_HandleTypeDef *hsai, void *Params)
01231 {
01232   GPIO_InitTypeDef  gpio_init_structure;
01233 
01234   static DMA_HandleTypeDef hdma_sai_rx;
01235 
01236   /* SAI IN DMA IRQ Channel deactivation */
01237   HAL_NVIC_DisableIRQ(AUDIO_IN_SAIx_DMAx_IRQ);
01238 
01239   if(hsai->Instance == AUDIO_IN_SAIx)
01240   {
01241     /* Deinitialize the Stream for new transfer */
01242     HAL_DMA_DeInit(&hdma_sai_rx);
01243   }
01244 
01245  /* Disable SAI block */
01246   __HAL_SAI_DISABLE(hsai);
01247 
01248   /* Disable pin: SD pin */
01249   gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN;
01250   HAL_GPIO_DeInit(AUDIO_IN_SAIx_SD_GPIO_PORT, gpio_init_structure.Pin);
01251 
01252   /* Disable SAI clock */
01253   AUDIO_IN_SAIx_CLK_DISABLE();
01254 
01255   /* GPIO pins clock and DMA clock can be shut down in the application
01256      by surcharging this __weak function */
01257 }
01258 
01259 
01260 /*******************************************************************************
01261                             Static Functions
01262 *******************************************************************************/
01263 
01264 /**
01265   * @brief  Initializes the input Audio Codec audio interface (SAI).
01266   * @param  SaiOutMode: SAI_MODEMASTER_TX (for record and playback in parallel)
01267   *                     or SAI_MODEMASTER_RX (for record only).
01268   * @param  SlotActive: CODEC_AUDIOFRAME_SLOT_02 or CODEC_AUDIOFRAME_SLOT_13
01269   * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
01270   * @retval None
01271   */
01272 static void SAIx_In_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq)
01273 {
01274   /* Initialize SAI2 block A in MASTER RX */
01275   /* Initialize the haudio_out_sai Instance parameter */
01276   haudio_out_sai.Instance = AUDIO_OUT_SAIx;
01277 
01278   /* Disable SAI peripheral to allow access to SAI internal registers */
01279   __HAL_SAI_DISABLE(&haudio_out_sai);
01280 
01281   /* Configure SAI_Block_x
01282   LSBFirst: Disabled
01283   DataSize: 16 */
01284   haudio_out_sai.Init.AudioFrequency = AudioFreq;
01285   haudio_out_sai.Init.AudioMode = SaiOutMode;
01286   haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED;
01287   haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL;
01288   haudio_out_sai.Init.DataSize = SAI_DATASIZE_16;
01289   haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
01290   haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
01291   haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS;
01292   haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLED;
01293   haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
01294 
01295   /* Configure SAI_Block_x Frame
01296   Frame Length: 64
01297   Frame active Length: 32
01298   FS Definition: Start frame + Channel Side identification
01299   FS Polarity: FS active Low
01300   FS Offset: FS asserted one bit before the first bit of slot 0 */
01301   haudio_out_sai.FrameInit.FrameLength = 64;
01302   haudio_out_sai.FrameInit.ActiveFrameLength = 32;
01303   haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
01304   haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
01305   haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
01306 
01307   /* Configure SAI Block_x Slot
01308   Slot First Bit Offset: 0
01309   Slot Size  : 16
01310   Slot Number: 4
01311   Slot Active: All slot actives */
01312   haudio_out_sai.SlotInit.FirstBitOffset = 0;
01313   haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
01314   haudio_out_sai.SlotInit.SlotNumber = 4;
01315   haudio_out_sai.SlotInit.SlotActive = SlotActive;
01316 
01317   HAL_SAI_Init(&haudio_out_sai);
01318 
01319   /* Initialize SAI2 block B in SLAVE RX synchronous from SAI2 block A */
01320   /* Initialize the haudio_in_sai Instance parameter */
01321   haudio_in_sai.Instance = AUDIO_IN_SAIx;
01322   
01323   /* Disable SAI peripheral to allow access to SAI internal registers */
01324   __HAL_SAI_DISABLE(&haudio_in_sai);
01325   
01326   /* Configure SAI_Block_x
01327   LSBFirst: Disabled
01328   DataSize: 16 */
01329   haudio_in_sai.Init.AudioFrequency = AudioFreq;
01330   haudio_in_sai.Init.AudioMode = SAI_MODESLAVE_RX;
01331   haudio_in_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED;
01332   haudio_in_sai.Init.Protocol = SAI_FREE_PROTOCOL;
01333   haudio_in_sai.Init.DataSize = SAI_DATASIZE_16;
01334   haudio_in_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
01335   haudio_in_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
01336   haudio_in_sai.Init.Synchro = SAI_SYNCHRONOUS;
01337   haudio_in_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLED;
01338   haudio_in_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
01339   
01340   /* Configure SAI_Block_x Frame
01341   Frame Length: 64
01342   Frame active Length: 32
01343   FS Definition: Start frame + Channel Side identification
01344   FS Polarity: FS active Low
01345   FS Offset: FS asserted one bit before the first bit of slot 0 */
01346   haudio_in_sai.FrameInit.FrameLength = 64;
01347   haudio_in_sai.FrameInit.ActiveFrameLength = 32;
01348   haudio_in_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
01349   haudio_in_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
01350   haudio_in_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
01351   
01352   /* Configure SAI Block_x Slot
01353   Slot First Bit Offset: 0
01354   Slot Size  : 16
01355   Slot Number: 4
01356   Slot Active: All slot active */
01357   haudio_in_sai.SlotInit.FirstBitOffset = 0;
01358   haudio_in_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
01359   haudio_in_sai.SlotInit.SlotNumber = 4;
01360   haudio_in_sai.SlotInit.SlotActive = SlotActive;
01361 
01362   HAL_SAI_Init(&haudio_in_sai);
01363 
01364   /* Enable SAI peripheral to generate MCLK */
01365   __HAL_SAI_ENABLE(&haudio_out_sai);
01366 
01367   /* Enable SAI peripheral */
01368   __HAL_SAI_ENABLE(&haudio_in_sai);
01369 }
01370 
01371 
01372 
01373 /**
01374   * @brief  Deinitializes the output Audio Codec audio interface (SAI).
01375   * @retval None
01376   */
01377 static void SAIx_In_DeInit(void)
01378 {
01379   /* Initialize the haudio_in_sai Instance parameter */
01380   haudio_in_sai.Instance = AUDIO_IN_SAIx;
01381 
01382   /* Disable SAI peripheral */
01383   __HAL_SAI_DISABLE(&haudio_in_sai);
01384 
01385   HAL_SAI_DeInit(&haudio_in_sai);
01386 }
01387 
01388 #if ( __MBED__ == 1)
01389 /**
01390   * @brief  This function handles External line 15_10 interrupt request.
01391   * @param  None
01392   * @retval None
01393   */
01394 static void AUDIO_IN_INT_IRQHandler(void)
01395 {
01396   /* Interrupt handler shared between SD_DETECT pin, USER_KEY button and touch screen interrupt */
01397   if (__HAL_GPIO_EXTI_GET_IT(AUDIO_IN_INT_GPIO_PIN) != RESET)
01398   {
01399     HAL_GPIO_EXTI_IRQHandler(AUDIO_IN_INT_GPIO_PIN);   /* Audio Interrupt */
01400   }
01401 }
01402 
01403 /**
01404   * @brief This function handles DMA2 Stream 7 interrupt request.
01405   * @param None
01406   * @retval None
01407   */
01408 static void AUDIO_IN_SAIx_DMAx_IRQHandler(void)
01409 {
01410   HAL_DMA_IRQHandler(haudio_in_sai.hdmarx);
01411 }
01412 
01413 /**
01414   * @brief  This function handles DMA2 Stream 6 interrupt request.
01415   * @param  None
01416   * @retval None
01417   */
01418 static void AUDIO_OUT_SAIx_DMAx_IRQHandler(void)
01419 {
01420   HAL_DMA_IRQHandler(haudio_out_sai.hdmatx);
01421 }
01422 #endif
01423 
01424 /**
01425   * @}
01426   */ 
01427   
01428 /**
01429   * @}
01430   */
01431 
01432 /**
01433   * @}
01434   */
01435 
01436 /**
01437   * @}
01438   */ 
01439 
01440 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/