STM32746G-Discovery BSP User Manual: stm32746g_discovery_audio.c Source File

STM32746G-Discovery BSP Drivers

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