L4 HAL Drivers

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32l4xx_hal_sai.c Source File

stm32l4xx_hal_sai.c

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l4xx_hal_sai.c
00004   * @author  MCD Application Team
00005   * @version V1.1.0
00006   * @date    16-September-2015
00007   * @brief   SAI HAL module driver.
00008   *          This file provides firmware functions to manage the following 
00009   *          functionalities of the Serial Audio Interface (SAI) peripheral:
00010   *           + Initialization/de-initialization functions
00011   *           + I/O operation functions
00012   *           + Peripheral Control functions 
00013   *           + Peripheral State functions
00014   *         
00015   @verbatim
00016  ==============================================================================
00017                   ##### How to use this driver #####
00018  ==============================================================================           
00019   [..]
00020     The SAI HAL driver can be used as follows:
00021     
00022     (#) Declare a SAI_HandleTypeDef handle structure (eg. SAI_HandleTypeDef hsai).
00023     (#) Initialize the SAI low level resources by implementing the HAL_SAI_MspInit() API:
00024         (##) Enable the SAI interface clock.
00025         (##) SAI pins configuration:
00026             (+++) Enable the clock for the SAI GPIOs.
00027             (+++) Configure these SAI pins as alternate function pull-up.
00028         (##) NVIC configuration if you need to use interrupt process (HAL_SAI_Transmit_IT()
00029              and HAL_SAI_Receive_IT() APIs):
00030             (+++) Configure the SAI interrupt priority.
00031             (+++) Enable the NVIC SAI IRQ handle.
00032 
00033         (##) DMA Configuration if you need to use DMA process (HAL_SAI_Transmit_DMA()
00034              and HAL_SAI_Receive_DMA() APIs):
00035             (+++) Declare a DMA handle structure for the Tx/Rx channel.
00036             (+++) Enable the DMAx interface clock.
00037             (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
00038             (+++) Configure the DMA Tx/Rx Channel.
00039             (+++) Associate the initialized DMA handle to the SAI DMA Tx/Rx handle.
00040             (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the 
00041                 DMA Tx/Rx Channel.
00042   
00043     (#) The initialization can be done by two ways 
00044         (##) Expert mode : Initialize the structures Init, FrameInit and SlotInit and call HAL_SAI_Init().
00045         (##) Simplified mode : Initialize the high part of Init Structure and call HAL_SAI_InitProtocol().
00046    
00047   [..]           
00048    (@) The specific SAI interrupts (FIFO request and Overrun underrun interrupt)
00049        will be managed using the macros __HAL_SAI_ENABLE_IT() and __HAL_SAI_DISABLE_IT()
00050        inside the transmit and receive process.   
00051        
00052   [..]           
00053    (@) Make sure that either:
00054        (+@) PLLSAI1CLK output is configured or 
00055        (+@) PLLSAI2CLK output is configured or 
00056        (+@) PLLSAI3CLK output is configured or 
00057        (+@) External clock source is configured after setting correctly 
00058             the define constant EXTERNAL_SAI1_CLOCK_VALUE or EXTERNAL_SAI2_CLOCK_VALUE in the stm32l4xx_hal_conf.h file. 
00059 
00060   [..]
00061     (@) In master Tx mode: enabling the audio block immediately generates the bit clock 
00062         for the external slaves even if there is no data in the FIFO, However FS signal 
00063         generation is conditioned by the presence of data in the FIFO.
00064 
00065   [..]
00066     (@) In master Rx mode: enabling the audio block immediately generates the bit clock 
00067         and FS signal for the external slaves.
00068 
00069   [..]
00070     (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior:
00071         (+@)  First bit Offset <= (SLOT size - Data size)
00072         (+@)  Data size <= SLOT size
00073         (+@)  Number of SLOT x SLOT size = Frame length
00074         (+@)  The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected.
00075 
00076   [..]
00077      Three operation modes are available within this driver :
00078   
00079    *** Polling mode IO operation ***
00080    =================================
00081    [..]
00082      (+) Send an amount of data in blocking mode using HAL_SAI_Transmit() 
00083      (+) Receive an amount of data in blocking mode using HAL_SAI_Receive()
00084    
00085    *** Interrupt mode IO operation ***    
00086    ===================================
00087    [..]
00088      (+) Send an amount of data in non-blocking mode using HAL_SAI_Transmit_IT() 
00089      (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can 
00090          add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
00091      (+) Receive an amount of data in non-blocking mode using HAL_SAI_Receive_IT() 
00092      (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can 
00093          add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
00094      (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can 
00095          add his own code by customization of function pointer HAL_SAI_ErrorCallback()
00096 
00097    *** DMA mode IO operation ***
00098    ==============================
00099    [..] 
00100      (+) Send an amount of data in non-blocking mode (DMA) using HAL_SAI_Transmit_DMA() 
00101      (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can 
00102          add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
00103      (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SAI_Receive_DMA() 
00104      (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can 
00105          add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
00106      (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can 
00107          add his own code by customization of function pointer HAL_SAI_ErrorCallback()
00108      (+) Pause the DMA Transfer using HAL_SAI_DMAPause()
00109      (+) Resume the DMA Transfer using HAL_SAI_DMAResume()
00110      (+) Stop the DMA Transfer using HAL_SAI_DMAStop()
00111    
00112    *** SAI HAL driver additional function list ***
00113    ================================================= 
00114    [..]
00115      Below the list the others API available SAI HAL driver :
00116        
00117       (+) HAL_SAI_EnableTxMuteMode(): Enable the mute in tx mode 
00118       (+) HAL_SAI_DisableTxMuteMode(): Disable the mute in tx mode 
00119       (+) HAL_SAI_EnableRxMuteMode(): Enable the mute in Rx mode
00120       (+) HAL_SAI_DisableRxMuteMode(): Disable the mute in Rx mode
00121       (+) HAL_SAI_FlushRxFifo(): Flush the rx fifo.
00122       (+) HAL_SAI_Abort(): Abort the current transfer
00123 
00124    *** SAI HAL driver macros list ***
00125    ============================================= 
00126    [..]
00127      Below the list of most used macros in SAI HAL driver :
00128        
00129       (+) __HAL_SAI_ENABLE(): Enable the SAI peripheral
00130       (+) __HAL_SAI_DISABLE(): Disable the SAI peripheral
00131       (+) __HAL_SAI_ENABLE_IT(): Enable the specified SAI interrupts
00132       (+) __HAL_SAI_DISABLE_IT(): Disable the specified SAI interrupts
00133       (+) __HAL_SAI_GET_IT_SOURCE(): Check if the specified SAI interrupt source is 
00134           enabled or disabled
00135       (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not
00136   
00137   @endverbatim
00138   ******************************************************************************
00139   * @attention
00140   *
00141   * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
00142   *
00143   * Redistribution and use in source and binary forms, with or without modification,
00144   * are permitted provided that the following conditions are met:
00145   *   1. Redistributions of source code must retain the above copyright notice,
00146   *      this list of conditions and the following disclaimer.
00147   *   2. Redistributions in binary form must reproduce the above copyright notice,
00148   *      this list of conditions and the following disclaimer in the documentation
00149   *      and/or other materials provided with the distribution.
00150   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00151   *      may be used to endorse or promote products derived from this software
00152   *      without specific prior written permission.
00153   *
00154   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00155   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00156   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00157   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00158   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00159   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00160   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00161   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00162   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00163   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00164   *
00165   ******************************************************************************
00166   */ 
00167 
00168 /* Includes ------------------------------------------------------------------*/
00169 #include "stm32l4xx_hal.h"
00170 
00171 /** @addtogroup STM32L4xx_HAL_Driver
00172   * @{
00173   */
00174 
00175 /** @defgroup SAI SAI
00176   * @brief SAI HAL module driver
00177   * @{
00178   */
00179 
00180 #ifdef HAL_SAI_MODULE_ENABLED
00181 
00182 /* Private typedef -----------------------------------------------------------*/
00183 /** @defgroup SAI_Private_Typedefs  SAI Private Typedefs
00184   * @{
00185   */
00186 typedef enum {
00187   SAI_MODE_DMA,
00188   SAI_MODE_IT
00189 }SAI_ModeTypedef;
00190 /**
00191   * @}
00192   */
00193 
00194 /* Private define ------------------------------------------------------------*/
00195 /** @defgroup SAI_Private_Constants  SAI Private Constants
00196   * @{
00197   */
00198 #define SAI_FIFO_SIZE       8
00199 #define SAI_DEFAULT_TIMEOUT 4
00200 /**
00201   * @}
00202   */
00203 
00204 /* Private macro -------------------------------------------------------------*/
00205 /* Private variables ---------------------------------------------------------*/
00206 /* Private function prototypes -----------------------------------------------*/
00207 /** @defgroup SAI_Private_Functions  SAI Private Functions
00208   * @{
00209   */
00210 static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
00211 static int32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode);
00212 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
00213 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
00214 
00215 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
00216 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
00217 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
00218 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
00219 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
00220 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
00221 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
00222 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
00223 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
00224 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
00225 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
00226 static void SAI_DMAError(DMA_HandleTypeDef *hdma);
00227 /**
00228   * @}
00229   */
00230 
00231 /* Exported functions --------------------------------------------------------*/
00232 
00233 /** @defgroup SAI_Exported_Functions SAI Exported Functions
00234   * @{
00235   */
00236 
00237 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions 
00238  *  @brief    Initialization and Configuration functions 
00239  *
00240 @verbatim    
00241  ===============================================================================
00242               ##### Initialization and de-initialization functions #####
00243  ===============================================================================
00244     [..]  This subsection provides a set of functions allowing to initialize and 
00245           de-initialize the SAIx peripheral:
00246 
00247       (+) User must implement HAL_SAI_MspInit() function in which he configures 
00248           all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
00249 
00250       (+) Call the function HAL_SAI_Init() to configure the selected device with 
00251           the selected configuration:
00252         (++) Mode (Master/slave TX/RX)
00253         (++) Protocol 
00254         (++) Data Size
00255         (++) MCLK Output
00256         (++) Audio frequency
00257         (++) FIFO Threshold
00258         (++) Frame Config
00259         (++) Slot Config
00260 
00261       (+) Call the function HAL_SAI_DeInit() to restore the default configuration 
00262           of the selected SAI peripheral.     
00263 
00264 @endverbatim
00265   * @{
00266   */
00267 
00268 /**
00269   * @brief  Initialize the structure FrameInit, SlotInit and the low part of 
00270   *         Init according to the specified parameters and call the function
00271   *         HAL_SAI_Init to initialize the SAI block.
00272   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains 
00273   *               the configuration information for SAI module.
00274   * @param  protocol: one of the supported protocol @ref SAI_Protocol
00275   * @param  datasize: one of the supported datasize @ref SAI_Protocol_DataSize
00276   *                   the configuration information for SAI module.
00277   * @param  nbslot: Number of slot.
00278   * @retval HAL status
00279   */
00280 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
00281 {
00282   HAL_StatusTypeDef errorcode = HAL_OK;
00283   
00284   switch(protocol)
00285   {
00286   case SAI_I2S_STANDARD :
00287   case SAI_I2S_MSBJUSTIFIED :
00288   case SAI_I2S_LSBJUSTIFIED :
00289     errorcode = SAI_InitI2S(hsai, protocol, datasize, nbslot);
00290     break;  
00291   case SAI_PCM_LONG :
00292   case SAI_PCM_SHORT :
00293     errorcode = SAI_InitPCM(hsai, protocol, datasize, nbslot);
00294     break;
00295   default :
00296     errorcode = HAL_ERROR;
00297     break;
00298   }
00299   
00300   if(errorcode == HAL_OK)
00301   {
00302     errorcode = HAL_SAI_Init(hsai);
00303   }
00304 
00305   return errorcode;
00306 }
00307 
00308 /**
00309   * @brief  Initialize the SAI according to the specified parameters 
00310   *         in the SAI_InitTypeDef structure and initialize the associated handle.
00311   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
00312   *                the configuration information for SAI module.
00313   * @retval HAL status
00314   */
00315 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
00316 { 
00317   uint32_t tmpregisterGCR = 0;
00318 
00319   /* Check the SAI handle allocation */
00320   if(hsai == NULL)
00321   {
00322     return HAL_ERROR;
00323   }
00324   
00325   /* check the instance */
00326   assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance));
00327   
00328   /* Check the SAI Block parameters */
00329   assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
00330   assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
00331   assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
00332   assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
00333   assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
00334   assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
00335   assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
00336   assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
00337   assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
00338   assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
00339   assert_param(IS_SAI_MONOSTEREO_MODE(hsai->Init.MonoStereoMode));
00340   assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));
00341   assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));
00342   assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));
00343   
00344   /* Check the SAI Block Frame parameters */
00345   assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
00346   assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
00347   assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
00348   assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
00349   assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
00350   
00351   /* Check the SAI Block Slot parameters */
00352   assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
00353   assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
00354   assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
00355   assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
00356   
00357   if(hsai->State == HAL_SAI_STATE_RESET)
00358   {
00359     /* Allocate lock resource and initialize it */
00360     hsai->Lock = HAL_UNLOCKED;
00361 
00362     /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
00363     HAL_SAI_MspInit(hsai);
00364   }
00365   
00366   hsai->State = HAL_SAI_STATE_BUSY;
00367   
00368   /* Disable the selected SAI peripheral */
00369   SAI_Disable(hsai);
00370 
00371   /* SAI Block Synchro Configuration ---------------------------------------------------*/
00372   /* This setting must be done with both audio block (A & B) disabled                   */
00373   switch(hsai->Init.SynchroExt)
00374   {
00375     case SAI_SYNCEXT_DISABLE :
00376       tmpregisterGCR = 0;
00377       break;
00378     case SAI_SYNCEXT_IN_ENABLE :
00379       tmpregisterGCR = SAI_GCR_SYNCIN_0;
00380       break;
00381     case SAI_SYNCEXT_OUTBLOCKA_ENABLE :
00382       tmpregisterGCR = SAI_GCR_SYNCOUT_0;
00383       break;
00384     case SAI_SYNCEXT_OUTBLOCKB_ENABLE :
00385       tmpregisterGCR = SAI_GCR_SYNCOUT_1;
00386       break;
00387   }
00388     
00389   if((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
00390   {
00391     SAI1->GCR = tmpregisterGCR;
00392   }
00393   else 
00394   {
00395     SAI2->GCR = tmpregisterGCR;
00396   }
00397 
00398   if(hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)
00399   {
00400     uint32_t freq = 0;
00401     uint32_t tmpval;
00402     /* In this case, the MCKDIV value is calculated to get AudioFrequency */
00403     if((hsai->Instance == SAI1_Block_A ) || (hsai->Instance == SAI1_Block_B ))
00404     {
00405       freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1);  
00406     }
00407     if((hsai->Instance == SAI2_Block_A ) || (hsai->Instance == SAI2_Block_B )) 
00408     {
00409       freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2);  
00410     }
00411     
00412     /* Configure Master Clock using the following formula :
00413        MCLK_x = SAI_CK_x / (MCKDIV[3:0] * 2) with MCLK_x = 256 * FS
00414        FS = SAI_CK_x / (MCKDIV[3:0] * 2) * 256
00415         MCKDIV[3:0] = SAI_CK_x / FS * 512 */
00416     /* (freq x 10) to keep Significant digits */
00417     tmpval = (freq * 10) / (hsai->Init.AudioFrequency * 2 * 256);
00418     hsai->Init.Mckdiv = tmpval / 10;
00419     
00420     /* Round result to the nearest integer */
00421     if((tmpval % 10) > 8) 
00422     {
00423       hsai->Init.Mckdiv+= 1;
00424     }
00425   }
00426   
00427   /* SAI Block Configuration ------------------------------------------------------------*/
00428   /* SAI CR1 Configuration */
00429   hsai->Instance->CR1&=~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG |  SAI_xCR1_DS |      \
00430                          SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN |\
00431                          SAI_xCR1_MONO | SAI_xCR1_OUTDRIV  | SAI_xCR1_DMAEN |  \
00432                          SAI_xCR1_NODIV | SAI_xCR1_MCKDIV);
00433     
00434   hsai->Instance->CR1|=(hsai->Init.AudioMode | hsai->Init.Protocol |           \
00435                         hsai->Init.DataSize | hsai->Init.FirstBit  |           \
00436                         hsai->Init.ClockStrobing | hsai->Init.Synchro |        \
00437                         hsai->Init.MonoStereoMode | hsai->Init.OutputDrive |   \
00438                         hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) | hsai->Init.CompandingMode);
00439   
00440   /* SAI CR2 Configuration */
00441   hsai->Instance->CR2&= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP);
00442   hsai->Instance->CR2|=  (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);
00443 
00444 
00445   /* SAI Frame Configuration -----------------------------------------*/
00446   hsai->Instance->FRCR&=(~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \
00447                            SAI_xFRCR_FSPO | SAI_xFRCR_FSOFF));
00448   hsai->Instance->FRCR|=((hsai->FrameInit.FrameLength - 1)  | 
00449                             hsai->FrameInit.FSOffset | 
00450                             hsai->FrameInit.FSDefinition | 
00451                             hsai->FrameInit.FSPolarity   | 
00452                             ((hsai->FrameInit.ActiveFrameLength - 1) << 8));  
00453   
00454   /* SAI Block_x SLOT Configuration ------------------------------------------*/
00455   /* This register has no meaning in AC 97 and SPDIF audio protocol */
00456   hsai->Instance->SLOTR&= (~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ |            \
00457                              SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN ));
00458   
00459   hsai->Instance->SLOTR|=  hsai->SlotInit.FirstBitOffset |  hsai->SlotInit.SlotSize
00460                           | hsai->SlotInit.SlotActive | ((hsai->SlotInit.SlotNumber - 1) <<  8);           
00461   
00462   /* Initialize the error code */
00463   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00464   
00465   /* Initialize the SAI state */
00466   hsai->State= HAL_SAI_STATE_READY;
00467   
00468   /* Release Lock */
00469   __HAL_UNLOCK(hsai);
00470   
00471   return HAL_OK;
00472 }
00473 
00474 /**
00475   * @brief  DeInitialize the SAI peripheral. 
00476   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
00477   *                the configuration information for SAI module.
00478   * @retval HAL status
00479   */
00480 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
00481 {
00482   /* Check the SAI handle allocation */
00483   if(hsai == NULL)
00484   {
00485     return HAL_ERROR;
00486   }
00487 
00488   hsai->State = HAL_SAI_STATE_BUSY;
00489   
00490   /* Disabled All interrupt and clear all the flag */
00491   hsai->Instance->IMR = 0;
00492   hsai->Instance->CLRFR = 0xFFFFFFFF;
00493   
00494   /* Disable the SAI */
00495   SAI_Disable(hsai);
00496 
00497   /* Flush the fifo */
00498   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
00499 
00500   /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
00501   HAL_SAI_MspDeInit(hsai);
00502 
00503   /* Initialize the error code */
00504   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00505   
00506   /* Initialize the SAI state */
00507   hsai->State = HAL_SAI_STATE_RESET;
00508 
00509   return HAL_OK;
00510 }
00511 
00512 /**
00513   * @brief Initialize the SAI MSP.
00514   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
00515   *                the configuration information for SAI module.
00516   * @retval None
00517   */
00518 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
00519 {
00520   /* NOTE : This function should not be modified, when the callback is needed,
00521             the HAL_SAI_MspInit could be implemented in the user file
00522    */ 
00523 }
00524 
00525 /**
00526   * @brief DeInitialize the SAI MSP.
00527   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
00528   *                the configuration information for SAI module.
00529   * @retval None
00530   */
00531 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
00532 {
00533   /* NOTE : This function should not be modified, when the callback is needed,
00534             the HAL_SAI_MspDeInit could be implemented in the user file
00535    */ 
00536 }
00537 
00538 /**
00539   * @}
00540   */
00541 
00542 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions 
00543  *  @brief   Data transfers functions 
00544  *
00545 @verbatim   
00546   ===============================================================================
00547                       ##### IO operation functions #####
00548  ===============================================================================  
00549     [..]
00550     This subsection provides a set of functions allowing to manage the SAI data 
00551     transfers.
00552 
00553     (+) There are two modes of transfer:
00554        (++) Blocking mode : The communication is performed in the polling mode. 
00555             The status of all data processing is returned by the same function 
00556             after finishing transfer.  
00557        (++) No-Blocking mode : The communication is performed using Interrupts 
00558             or DMA. These functions return the status of the transfer startup.
00559             The end of the data processing will be indicated through the 
00560             dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when 
00561             using DMA mode.
00562 
00563     (+) Blocking mode functions are :
00564         (++) HAL_SAI_Transmit()
00565         (++) HAL_SAI_Receive()
00566         (++) HAL_SAI_TransmitReceive()
00567         
00568     (+) Non Blocking mode functions with Interrupt are :
00569         (++) HAL_SAI_Transmit_IT()
00570         (++) HAL_SAI_Receive_IT()
00571         (++) HAL_SAI_TransmitReceive_IT()
00572 
00573     (+) Non Blocking mode functions with DMA are :
00574         (++) HAL_SAI_Transmit_DMA()
00575         (++) HAL_SAI_Receive_DMA()
00576         (++) HAL_SAI_TransmitReceive_DMA()
00577 
00578     (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
00579         (++) HAL_SAI_TxCpltCallback()
00580         (++) HAL_SAI_RxCpltCallback()
00581         (++) HAL_SAI_ErrorCallback()
00582 
00583 @endverbatim
00584   * @{
00585   */
00586 
00587 /**
00588   * @brief  Transmit an amount of data in blocking mode.
00589   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
00590   *                the configuration information for SAI module.
00591   * @param  pData: Pointer to data buffer
00592   * @param  Size: Amount of data to be sent
00593   * @param  Timeout: Timeout duration
00594   * @retval HAL status
00595   */
00596 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t* pData, uint16_t Size, uint32_t Timeout)
00597 {
00598   uint32_t tickstart = HAL_GetTick();
00599   HAL_StatusTypeDef errorcode = HAL_OK;
00600   
00601   /* Process Locked */
00602   __HAL_LOCK(hsai);
00603   
00604   if((pData == NULL ) || (Size == 0)) 
00605   {
00606     errorcode = HAL_ERROR;
00607     goto error;
00608   }
00609   
00610   if(hsai->State != HAL_SAI_STATE_READY)
00611   {
00612     errorcode = HAL_BUSY;
00613     goto error;
00614   }
00615   
00616   hsai->State = HAL_SAI_STATE_BUSY_TX;
00617   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00618   hsai->XferSize = Size;
00619   hsai->XferCount = Size;
00620   hsai->pBuffPtr = pData;
00621 
00622   /* Check if the SAI is already enabled */ 
00623   if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
00624   {
00625     /* fill the fifo with data before to enabled the SAI */
00626     SAI_FillFifo(hsai);
00627     /* Enable SAI peripheral */    
00628     __HAL_SAI_ENABLE(hsai);
00629   }
00630 
00631   do 
00632   { 
00633     /* Write data if the FIFO is not full */
00634     if((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
00635     {
00636       if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
00637       {
00638         hsai->Instance->DR = (*hsai->pBuffPtr++);
00639       }
00640       else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
00641       {
00642         *(uint16_t *)&hsai->Instance->DR = *((uint16_t *)hsai->pBuffPtr);
00643         hsai->pBuffPtr+= 2;
00644       }
00645       else
00646       {
00647         hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
00648         hsai->pBuffPtr+= 4;
00649       }
00650       hsai->XferCount--;
00651     }
00652     else
00653     {
00654       /* Check for the Timeout */
00655       if((Timeout != HAL_MAX_DELAY) && ((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)))
00656       {
00657         errorcode = HAL_TIMEOUT;
00658         goto error;
00659       }
00660     }
00661   }
00662   while(0 != hsai->XferCount);
00663     
00664 error :
00665   hsai->State = HAL_SAI_STATE_READY; 
00666   /* Process Unlocked */
00667   __HAL_UNLOCK(hsai);
00668   return errorcode;
00669 }
00670   
00671 /**
00672   * @brief  Receive an amount of data in blocking mode. 
00673   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
00674   *                the configuration information for SAI module.
00675   * @param  pData: Pointer to data buffer
00676   * @param  Size: Amount of data to be received
00677   * @param  Timeout: Timeout duration
00678   * @retval HAL status
00679   */
00680 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
00681 {
00682   uint32_t tickstart = HAL_GetTick();
00683   HAL_StatusTypeDef errorcode = HAL_OK;
00684   
00685   /* Process Locked */
00686   __HAL_LOCK(hsai);
00687   
00688   if((pData == NULL ) || (Size == 0)) 
00689   {
00690     errorcode = HAL_ERROR;
00691     goto error;
00692   }
00693   
00694   if(hsai->State != HAL_SAI_STATE_READY)
00695   { 
00696     errorcode = HAL_BUSY;
00697     goto error;
00698   }
00699   
00700   hsai->pBuffPtr = pData;
00701   hsai->XferSize = Size;
00702   hsai->XferCount = Size;
00703   hsai->State = HAL_SAI_STATE_BUSY_RX;
00704   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00705   
00706   /* Check if the SAI is already enabled */ 
00707   if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
00708   {
00709     /* Enable SAI peripheral */    
00710     __HAL_SAI_ENABLE(hsai);
00711   }
00712   
00713    /* Receive data */
00714   do
00715   { 
00716     /* Wait until RXNE flag is set */
00717     if((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)
00718     {
00719       if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
00720       {
00721         (*hsai->pBuffPtr++) = hsai->Instance->DR;
00722       }
00723       else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
00724       {
00725         *((uint16_t*)hsai->pBuffPtr) = hsai->Instance->DR;
00726         hsai->pBuffPtr+= 2;
00727       }
00728       else
00729       {
00730         *((uint32_t*)hsai->pBuffPtr) = hsai->Instance->DR;
00731         hsai->pBuffPtr+= 4;
00732       }  
00733       hsai->XferCount--; 
00734     }
00735     else
00736     {
00737       /* Check for the Timeout */
00738       if((Timeout != HAL_MAX_DELAY) && ((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)))
00739       {
00740         errorcode = HAL_TIMEOUT;
00741         goto error;
00742       }
00743     }
00744   }
00745   while(0 != hsai->XferCount);
00746     
00747 error : 
00748   hsai->State = HAL_SAI_STATE_READY; 
00749   /* Process Unlocked */
00750   __HAL_UNLOCK(hsai);
00751   return errorcode;
00752 }
00753 
00754 /**
00755   * @brief  Transmit an amount of data in non-blocking mode with Interrupt.
00756   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
00757   *                the configuration information for SAI module.
00758   * @param  pData: Pointer to data buffer
00759   * @param  Size: Amount of data to be sent
00760   * @retval HAL status
00761   */
00762 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
00763 {
00764   HAL_StatusTypeDef errorcode = HAL_OK;
00765   
00766   /* Process Locked */
00767   __HAL_LOCK(hsai);  
00768   
00769   if((pData == NULL) || (Size == 0)) 
00770   {
00771     errorcode = HAL_ERROR;
00772     goto error;
00773   }
00774   
00775   if(hsai->State != HAL_SAI_STATE_READY)
00776   {
00777     errorcode = HAL_BUSY;
00778     goto error;
00779   }
00780   
00781   hsai->pBuffPtr = pData;
00782   hsai->XferSize = Size;
00783   hsai->XferCount = Size;
00784   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00785   hsai->State = HAL_SAI_STATE_BUSY_TX;
00786   if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
00787   {
00788     hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;
00789   }
00790   else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
00791   {
00792     hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;
00793   }
00794   else
00795   {
00796     hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;
00797   }
00798   
00799   /* Enable FRQ and OVRUDR interrupts */
00800   __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
00801   
00802   /* Check if the SAI is already enabled */ 
00803   if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
00804   {
00805     /* Fill the fifo before starting the communication */
00806     SAI_FillFifo(hsai);
00807     /* Enable SAI peripheral */    
00808     __HAL_SAI_ENABLE(hsai);
00809   }
00810   
00811 error :
00812   /* Process Unlocked */
00813   __HAL_UNLOCK(hsai);
00814   return errorcode;
00815 }
00816 
00817 /**
00818   * @brief  Receive an amount of data in non-blocking mode with Interrupt.
00819   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
00820   *                the configuration information for SAI module.
00821   * @param  pData: Pointer to data buffer
00822   * @param  Size: Amount of data to be received
00823   * @retval HAL status
00824   */
00825 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
00826 {
00827   HAL_StatusTypeDef errorcode = HAL_OK;
00828   
00829   /* Process Locked */
00830   __HAL_LOCK(hsai);
00831   
00832   if((pData == NULL) || (Size == 0)) 
00833   {
00834     errorcode =  HAL_ERROR;
00835     goto error;
00836   }
00837   
00838   if(hsai->State != HAL_SAI_STATE_READY)
00839   {
00840     errorcode = HAL_BUSY;
00841     goto error;
00842   }
00843   
00844   hsai->pBuffPtr = pData;
00845   hsai->XferSize = Size;
00846   hsai->XferCount = Size;
00847   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00848   hsai->State = HAL_SAI_STATE_BUSY_RX;
00849   if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
00850   {
00851     hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;
00852   }
00853   else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
00854   {
00855     hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;
00856   }
00857   else
00858   {
00859     hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;
00860   }
00861   
00862   /* Enable the interrupts */
00863   __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
00864   
00865   /* Check if the SAI is already enabled */ 
00866   if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
00867   {
00868     /* Enable SAI peripheral */
00869     __HAL_SAI_ENABLE(hsai);
00870   }
00871   
00872 error :
00873   /* Process Unlocked */
00874   __HAL_UNLOCK(hsai);
00875   return errorcode;
00876 }
00877 
00878 /**
00879   * @brief Pause the audio stream playing from the Media.
00880   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
00881   *                the configuration information for SAI module.
00882   * @retval HAL status
00883   */
00884 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
00885 {
00886   /* Process Locked */
00887   __HAL_LOCK(hsai);
00888   
00889   /* Pause the audio file playing by disabling the SAI DMA requests */
00890   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
00891 
00892   /* Process Unlocked */
00893   __HAL_UNLOCK(hsai);
00894   
00895   return HAL_OK; 
00896 }
00897 
00898 /**
00899   * @brief Resume the audio stream playing from the Media.
00900   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
00901   *                the configuration information for SAI module.
00902   * @retval HAL status
00903   */
00904 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
00905 {
00906   /* Process Locked */
00907   __HAL_LOCK(hsai);
00908   
00909   /* Enable the SAI DMA requests */
00910   hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
00911 
00912   /* If the SAI peripheral is still not enabled, enable it */
00913   if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
00914   {
00915     /* Enable SAI peripheral */    
00916     __HAL_SAI_ENABLE(hsai);
00917   }
00918 
00919   /* Process Unlocked */
00920   __HAL_UNLOCK(hsai);
00921   
00922   return HAL_OK;
00923 }
00924 
00925 /**
00926   * @brief Stop the audio stream playing from the Media.
00927   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
00928   *                the configuration information for SAI module.
00929   * @retval HAL status
00930   */
00931 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
00932 {
00933   /* Process Locked */
00934   __HAL_LOCK(hsai);
00935   
00936   /* Disable the SAI DMA request */
00937   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
00938   
00939   /* Abort the SAI DMA Channel */
00940   if(hsai->hdmatx != NULL)
00941   {
00942     HAL_DMA_Abort(hsai->hdmatx);
00943   }
00944 
00945   if(hsai->hdmarx != NULL)
00946   {
00947     HAL_DMA_Abort(hsai->hdmarx);
00948   }
00949   
00950   /* Disable SAI peripheral */
00951   SAI_Disable(hsai);
00952   
00953   hsai->State = HAL_SAI_STATE_READY;
00954   
00955   /* Process Unlocked */
00956   __HAL_UNLOCK(hsai);
00957   
00958   return HAL_OK;
00959 }
00960 
00961 /**
00962   * @brief Abort the current transfer and disable the SAI.
00963   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
00964   *                the configuration information for SAI module.
00965   * @retval HAL status
00966   */
00967 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
00968 {
00969   /* Disable the SAI DMA request */
00970   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
00971   
00972   /* Abort the SAI DMA Channel */
00973   if(hsai->hdmatx != NULL)
00974   {
00975     HAL_DMA_Abort(hsai->hdmatx);
00976   }
00977   
00978   if(hsai->hdmarx != NULL)
00979   {
00980     HAL_DMA_Abort(hsai->hdmarx);
00981   }
00982   
00983   /* Disabled All interrupt and clear all the flag */
00984   hsai->Instance->IMR = 0;
00985   hsai->Instance->CLRFR = 0xFFFFFFFF;
00986   
00987   /* Disable SAI peripheral */
00988   SAI_Disable(hsai);
00989   
00990   /* Flush the fifo */
00991   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
00992   
00993   hsai->State = HAL_SAI_STATE_READY;
00994   
00995   /* Process Unlocked */
00996   __HAL_UNLOCK(hsai);
00997   
00998   return HAL_OK;
00999 }
01000 
01001 /**
01002   * @brief  Transmit an amount of data in non-blocking mode with DMA.
01003   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01004   *                the configuration information for SAI module.
01005   * @param  pData: Pointer to data buffer
01006   * @param  Size: Amount of data to be sent
01007   * @retval HAL status
01008   */
01009 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
01010 {
01011   HAL_StatusTypeDef errorcode = HAL_OK;
01012   
01013   /* Process Locked */
01014   __HAL_LOCK(hsai);
01015   
01016   if((pData == NULL) || (Size == 0)) 
01017   {
01018     errorcode = HAL_ERROR;
01019     goto error;
01020   }
01021   
01022   if(hsai->State != HAL_SAI_STATE_READY)
01023   {
01024     errorcode = HAL_BUSY;
01025     goto error;  
01026   }
01027   
01028   hsai->pBuffPtr = pData;
01029   hsai->XferSize = Size;
01030   hsai->XferCount = Size;
01031   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
01032   hsai->State = HAL_SAI_STATE_BUSY_TX;
01033   
01034   /* Set the SAI Tx DMA Half transfer complete callback */
01035   hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
01036   
01037   /* Set the SAI TxDMA transfer complete callback */
01038   hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
01039   
01040   /* Set the DMA error callback */
01041   hsai->hdmatx->XferErrorCallback = SAI_DMAError;
01042   
01043   /* Enable the Tx DMA Channel */
01044   HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize);
01045   
01046   /* Check if the SAI is already enabled */ 
01047   if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
01048   {
01049     /* Enable SAI peripheral */
01050     __HAL_SAI_ENABLE(hsai);
01051   }
01052   
01053   /* Enable the interrupts for error handling */
01054   __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
01055   
01056   /* Enable SAI Tx DMA Request */  
01057   hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
01058   
01059 error :     
01060   /* Process Unlocked */
01061   __HAL_UNLOCK(hsai);
01062   return errorcode;
01063 }
01064 
01065 /**
01066   * @brief  Receive an amount of data in non-blocking mode with DMA. 
01067   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01068   *                the configuration information for SAI module.
01069   * @param  pData: Pointer to data buffer
01070   * @param  Size: Amount of data to be received
01071   * @retval HAL status
01072   */
01073 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
01074 {
01075   HAL_StatusTypeDef errorcode = HAL_OK;
01076   
01077   /* Process Locked */
01078   __HAL_LOCK(hsai);
01079   
01080   if((pData == NULL) || (Size == 0))
01081   {
01082     errorcode = HAL_ERROR;
01083     goto error;
01084   } 
01085   
01086   if(hsai->State != HAL_SAI_STATE_READY)
01087   {    
01088     errorcode = HAL_BUSY;
01089     goto error;
01090   }
01091   hsai->pBuffPtr = pData;
01092   hsai->XferSize = Size;
01093   hsai->XferCount = Size;
01094   hsai->ErrorCode = HAL_SAI_ERROR_NONE; 
01095   hsai->State = HAL_SAI_STATE_BUSY_RX;
01096   
01097   /* Set the SAI Rx DMA Half transfer complete callback */
01098   hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
01099   
01100   /* Set the SAI Rx DMA transfer complete callback */
01101   hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
01102   
01103   /* Set the DMA error callback */
01104   hsai->hdmarx->XferErrorCallback = SAI_DMAError;
01105   
01106   /* Enable the Rx DMA Channel */
01107   HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize);
01108   
01109   /* Check if the SAI is already enabled */
01110   if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
01111   {
01112     /* Enable SAI peripheral */
01113     __HAL_SAI_ENABLE(hsai);
01114   }
01115   
01116   /* Enable the interrupts for error handling */
01117   __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
01118     
01119   /* Enable SAI Rx DMA Request */
01120   hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
01121   
01122 error :     
01123   /* Process Unlocked */
01124   __HAL_UNLOCK(hsai);
01125   return errorcode;
01126 }
01127 
01128 /**
01129   * @brief  Enable the Tx mute mode.
01130   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01131   *                the configuration information for SAI module.
01132   * @param  val:  value sent during the mute @ref SAI_Block_Mute_Value
01133   * @retval HAL status
01134   */
01135 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
01136 {
01137   assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));
01138   
01139   if(hsai->State != HAL_SAI_STATE_RESET)
01140   {
01141     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
01142     SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | val);
01143     return HAL_OK;
01144   }
01145   return HAL_ERROR;
01146 }
01147 
01148 /**
01149   * @brief  Disable the Tx mute mode.
01150   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01151   *                the configuration information for SAI module.
01152   * @retval HAL status
01153   */
01154 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
01155 {
01156   if(hsai->State != HAL_SAI_STATE_RESET)
01157   {
01158     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
01159     return HAL_OK;
01160   }
01161   return HAL_ERROR;
01162 }
01163 
01164 /**
01165   * @brief  Enable the Rx mute detection.
01166   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01167   *                the configuration information for SAI module.
01168   * @param  callback: function called when the mute is detected
01169   * @param  counter: number a data before mute detection max 63.
01170   * @retval HAL status
01171   */
01172 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
01173 {
01174   assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));
01175   
01176   if(hsai->State != HAL_SAI_STATE_RESET)
01177   {
01178     /* set the mute counter */
01179     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);
01180     SET_BIT(hsai->Instance->CR2, ((uint32_t)counter << 6));
01181     hsai->mutecallback = callback;
01182     /* enable the IT interrupt */
01183     __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);
01184     return HAL_OK;
01185   }
01186   return HAL_ERROR;
01187 }
01188 
01189 /**
01190   * @brief  Disable the Rx mute detection.
01191   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01192   *                the configuration information for SAI module.
01193   * @retval HAL status
01194   */
01195 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
01196 {
01197   if(hsai->State != HAL_SAI_STATE_RESET)
01198   {
01199     /* set the mutecallback to NULL */
01200     hsai->mutecallback = (SAIcallback)NULL;
01201     /* enable the IT interrupt */
01202     __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);
01203     return HAL_OK;
01204   }
01205   return HAL_ERROR;
01206 }
01207 
01208 /**
01209   * @brief  Handle SAI interrupt request.
01210   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01211   *                the configuration information for SAI module.
01212   * @retval None
01213   */
01214 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
01215 { 
01216   if(hsai->State != HAL_SAI_STATE_RESET)
01217   {
01218     __IO uint32_t tmpFlag = hsai->Instance->SR;
01219     __IO uint32_t tmpItSource = hsai->Instance->IMR; 
01220     
01221     if(((tmpFlag & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((tmpItSource & SAI_IT_FREQ) == SAI_IT_FREQ))
01222     {
01223       hsai->InterruptServiceRoutine(hsai);
01224       goto exit;
01225     }
01226     
01227     /* check the flag only if one of them is set */
01228     if(tmpFlag != 0x00000000)
01229     {
01230       /* SAI Overrun error interrupt occurred ----------------------------------*/
01231       if(((tmpFlag & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((tmpItSource & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))
01232       {
01233         /* Clear the SAI Overrun flag */
01234         __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
01235         /* Change the SAI error code */
01236         hsai->ErrorCode = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);
01237         /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
01238         HAL_SAI_ErrorCallback(hsai);
01239         goto exit;
01240       }
01241       
01242       /* SAI mutedet interrupt occurred ----------------------------------*/
01243       if(((tmpFlag & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((tmpItSource & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))
01244       {
01245         /* Clear the SAI mutedet flag */
01246         __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);
01247         /* call the call back function */
01248         if(hsai->mutecallback != (SAIcallback)NULL)
01249         {
01250           /* inform the user that an RX mute event has been detected */
01251           hsai->mutecallback();
01252         }
01253         goto exit;
01254       }
01255       
01256       /* SAI AFSDET interrupt occurred ----------------------------------*/
01257       if(((tmpFlag & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((tmpItSource & SAI_IT_AFSDET) == SAI_IT_AFSDET))
01258       {
01259         /* Change the SAI error code */
01260         hsai->ErrorCode = HAL_SAI_ERROR_AFSDET;
01261         goto error;
01262       }
01263       
01264       /* SAI LFSDET interrupt occurred ----------------------------------*/
01265       if(((tmpFlag & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((tmpItSource & SAI_IT_LFSDET) == SAI_IT_LFSDET))
01266       {
01267         /* Change the SAI error code */
01268         hsai->ErrorCode = HAL_SAI_ERROR_LFSDET;
01269         goto error;
01270       }
01271 
01272       /* SAI WCKCFG interrupt occurred ----------------------------------*/
01273       if(((tmpFlag & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((tmpItSource & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
01274       {
01275         /* Change the SAI error code */
01276         hsai->ErrorCode = HAL_SAI_ERROR_WCKCFG;
01277         goto error;
01278       }
01279     }
01280   }
01281   
01282 exit :
01283   return;
01284 error :
01285   /* Abort the current communication, disable the SAI block, and clear all the flags */
01286   HAL_SAI_Abort(hsai);
01287   HAL_SAI_ErrorCallback(hsai);
01288   return;
01289 }
01290 
01291 /**
01292   * @brief Tx Transfer completed callback.
01293   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01294   *                the configuration information for SAI module.
01295   * @retval None
01296   */
01297  __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
01298 {
01299   /* NOTE : This function should not be modified, when the callback is needed,
01300             the HAL_SAI_TxCpltCallback could be implemented in the user file
01301    */ 
01302 }
01303 
01304 /**
01305   * @brief Tx Transfer Half completed callback.
01306   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01307   *                the configuration information for SAI module.
01308   * @retval None
01309   */
01310  __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
01311 {
01312   /* NOTE : This function should not be modified, when the callback is needed,
01313             the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
01314    */ 
01315 }
01316 
01317 /**
01318   * @brief Rx Transfer completed callback.
01319   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01320   *                the configuration information for SAI module.
01321   * @retval None
01322   */
01323 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
01324 {
01325   /* NOTE : This function should not be modified, when the callback is needed,
01326             the HAL_SAI_RxCpltCallback could be implemented in the user file
01327    */
01328 }
01329 
01330 /**
01331   * @brief Rx Transfer half completed callback.
01332   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01333   *                the configuration information for SAI module.
01334   * @retval None
01335   */
01336 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
01337 {
01338   /* NOTE : This function should not be modified, when the callback is needed,
01339             the HAL_SAI_RxCpltCallback could be implemented in the user file
01340    */
01341 }
01342 
01343 /**
01344   * @brief SAI error callback.
01345   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01346   *                the configuration information for SAI module.
01347   * @retval None
01348   */
01349 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
01350 {
01351   /* NOTE : This function should not be modified, when the callback is needed,
01352             the HAL_SAI_ErrorCallback could be implemented in the user file
01353    */ 
01354 }
01355 
01356 /**
01357   * @}
01358   */
01359 
01360 
01361 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions 
01362  *  @brief   Peripheral State functions 
01363  *
01364 @verbatim   
01365  ===============================================================================
01366                 ##### Peripheral State and Errors functions #####
01367  ===============================================================================  
01368     [..]
01369     This subsection permits to get in run-time the status of the peripheral 
01370     and the data flow.
01371 
01372 @endverbatim
01373   * @{
01374   */
01375 
01376 /**
01377   * @brief  Return the SAI handle state.
01378   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01379   *                the configuration information for SAI module.
01380   * @retval HAL state
01381   */
01382 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai)
01383 {
01384   /* Return SAI handle state */
01385   return hsai->State;
01386 }
01387 
01388 /**
01389 * @brief  Return the SAI error code.
01390 * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01391   *              the configuration information for the specified SAI Block.
01392 * @retval SAI Error Code
01393 */
01394 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai)
01395 {
01396   return hsai->ErrorCode;
01397 }
01398 /**
01399   * @}
01400   */
01401 
01402 /**
01403   * @}
01404   */
01405 
01406 /** @addtogroup SAI_Private_Functions 
01407  *  @brief   Private functions 
01408   * @{
01409   */
01410 /**
01411   * @brief  Initialize the SAI I2S protocol according to the specified parameters 
01412   *         in the SAI_InitTypeDef and create the associated handle.
01413   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01414   *                the configuration information for SAI module.
01415   * @param  protocol: one of the supported protocol
01416   * @param  datasize: one of the supported datasize @ref SAI_Protocol_DataSize
01417   *                the configuration information for SAI module.
01418   * @param  nbslot: number of slot minimum value is 2 and max is 16. 
01419   *                    the value must be a multiple of 2.
01420   * @retval HAL status
01421   */
01422 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
01423 {
01424   HAL_StatusTypeDef errorcode = HAL_OK;
01425 
01426   hsai->Init.Protocol            = SAI_FREE_PROTOCOL;
01427   hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;
01428   hsai->Init.ClockStrobing       = SAI_CLOCKSTROBING_FALLINGEDGE;
01429   hsai->FrameInit.FSDefinition   = SAI_FS_CHANNEL_IDENTIFICATION;
01430   hsai->SlotInit.SlotActive      = SAI_SLOTACTIVE_ALL;
01431   hsai->SlotInit.FirstBitOffset  = 0;
01432   hsai->SlotInit.SlotNumber      = nbslot;
01433   
01434   /* in IS2 the number of slot must be even */
01435   if((nbslot & 0x1) != 0 )
01436   {
01437     return HAL_ERROR;
01438   }
01439     
01440   switch(protocol)
01441   {
01442   case SAI_I2S_STANDARD :
01443     hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
01444     hsai->FrameInit.FSOffset   = SAI_FS_BEFOREFIRSTBIT;
01445     break;
01446   case SAI_I2S_MSBJUSTIFIED :
01447   case SAI_I2S_LSBJUSTIFIED :
01448     hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
01449     hsai->FrameInit.FSOffset   = SAI_FS_FIRSTBIT;
01450     break;
01451   default :
01452     return HAL_ERROR;
01453   }
01454    
01455   /* Frame definition */
01456   hsai->Init.DataSize = 0xFFFFFFFF;
01457   if(datasize == SAI_PROTOCOL_DATASIZE_16BIT)
01458   {
01459     hsai->Init.DataSize = SAI_DATASIZE_16;
01460     hsai->FrameInit.FrameLength = 32*(nbslot/2);
01461     hsai->FrameInit.ActiveFrameLength = 16*(nbslot/2);
01462     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
01463   }
01464   else if(datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
01465   {
01466     if(hsai->Init.DataSize == 0xFFFFFFFF)
01467     {
01468       hsai->Init.DataSize = SAI_DATASIZE_16;
01469     }
01470   }
01471   else if(datasize == SAI_PROTOCOL_DATASIZE_24BIT)
01472   { 
01473     if(hsai->Init.DataSize == 0xFFFFFFFF)
01474     {
01475       hsai->Init.DataSize = SAI_DATASIZE_24;
01476     }
01477   }
01478   else if(datasize == SAI_PROTOCOL_DATASIZE_32BIT)
01479   {
01480     if(hsai->Init.DataSize == 0xFFFFFFFF) 
01481     {
01482       hsai->Init.DataSize = SAI_DATASIZE_32;
01483     }
01484   }
01485   else
01486   {
01487     errorcode = HAL_ERROR;
01488   }
01489     
01490   if(errorcode == HAL_OK)
01491   {
01492     hsai->FrameInit.FrameLength = 64*(nbslot/2);
01493     hsai->FrameInit.ActiveFrameLength = 32*(nbslot/2);
01494     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
01495     
01496     if(protocol == SAI_I2S_LSBJUSTIFIED)
01497     {
01498       if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
01499       {
01500         hsai->SlotInit.FirstBitOffset = 16;
01501       }
01502       else if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
01503       {
01504         hsai->SlotInit.FirstBitOffset = 8;
01505       }
01506     }
01507   }
01508 
01509   return errorcode;
01510 }
01511 
01512 /**
01513   * @brief  Initialize the SAI PCM protocol according to the specified parameters 
01514   *         in the SAI_InitTypeDef and create the associated handle.
01515   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01516   *                the configuration information for SAI module.
01517   * @param  protocol: one of the supported protocol
01518   * @param  datasize: one of the supported datasize @ref SAI_Protocol_DataSize
01519   * @param  nbslot: number of slot minimum value is 1 and the max is 16.
01520   * @retval HAL status
01521   */
01522 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
01523 {
01524   hsai->Init.Protocol            = SAI_FREE_PROTOCOL;
01525   hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;
01526   hsai->Init.ClockStrobing       = SAI_CLOCKSTROBING_FALLINGEDGE;
01527   hsai->FrameInit.FSDefinition   = SAI_FS_STARTFRAME;
01528   hsai->FrameInit.FSPolarity     = SAI_FS_ACTIVE_HIGH;
01529   hsai->FrameInit.FSOffset       = SAI_FS_BEFOREFIRSTBIT;
01530   hsai->SlotInit.FirstBitOffset  = 0;
01531   hsai->SlotInit.SlotNumber      = nbslot;
01532   hsai->SlotInit.SlotActive      = SAI_SLOTACTIVE_ALL;
01533   
01534   switch(protocol)
01535   {
01536   case SAI_PCM_SHORT :
01537     hsai->FrameInit.ActiveFrameLength = 1;
01538     break;
01539   case SAI_PCM_LONG :
01540     hsai->FrameInit.ActiveFrameLength = 13;
01541     break;
01542   default :
01543     return HAL_ERROR;
01544   }
01545  
01546   switch(datasize)
01547   {
01548   case SAI_PROTOCOL_DATASIZE_16BIT:
01549     hsai->Init.DataSize = SAI_DATASIZE_16;
01550     hsai->FrameInit.FrameLength = 16 * nbslot;
01551     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
01552     break; 
01553   case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
01554     hsai->Init.DataSize = SAI_DATASIZE_16;
01555     hsai->FrameInit.FrameLength = 32 * nbslot;
01556     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
01557     break;
01558     
01559   case SAI_PROTOCOL_DATASIZE_32BIT: 
01560     hsai->Init.DataSize = SAI_DATASIZE_32;
01561     hsai->FrameInit.FrameLength = 32 * nbslot;
01562     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
01563     break;
01564   default :
01565     return HAL_ERROR;
01566   }
01567  
01568   return HAL_OK;
01569 }
01570 
01571 /**
01572   * @brief  Fill the fifo.
01573   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01574   *                the configuration information for SAI module.
01575   * @retval None
01576   */
01577 static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
01578 {
01579   /* fill the fifo with data before to enabled the SAI */
01580   while((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
01581   {
01582     if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
01583     {
01584       hsai->Instance->DR = (*hsai->pBuffPtr++);
01585     }
01586     else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
01587     {
01588       hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
01589       hsai->pBuffPtr+= 2;
01590     }
01591     else
01592     {
01593       hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
01594       hsai->pBuffPtr+= 4;
01595     }
01596     hsai->XferCount--;
01597   }
01598 }
01599 
01600 /**
01601   * @brief  Return the interrupt flag to set according the SAI setup.
01602   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01603   *                the configuration information for SAI module.
01604   * @param  mode: SAI_MODE_DMA or SAI_MODE_IT
01605   * @retval the list of the IT flag to enable
01606  */
01607 static int32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode)
01608 {
01609   int32_t tmpIT = SAI_IT_OVRUDR; 
01610   
01611   if(mode == SAI_MODE_IT)
01612   {
01613     tmpIT|= SAI_IT_FREQ;
01614   }
01615   
01616   if((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
01617   {
01618     tmpIT|= SAI_IT_AFSDET | SAI_IT_LFSDET;
01619   }
01620   else
01621   {
01622     /* hsai has been configured in master mode */
01623     tmpIT|= SAI_IT_WCKCFG;
01624   }
01625   return tmpIT;
01626 }
01627 
01628 /**
01629   * @brief  Disable the SAI and wait for the disabling.
01630   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01631   *                the configuration information for SAI module.
01632   * @retval None
01633   */
01634 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
01635 {
01636   uint32_t tickstart = HAL_GetTick();
01637   HAL_StatusTypeDef errorcode = HAL_OK;
01638   
01639   __HAL_SAI_DISABLE(hsai);
01640   while((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != RESET)
01641   {
01642     /* Check for the Timeout */
01643     if((HAL_GetTick() - tickstart) > SAI_DEFAULT_TIMEOUT)
01644     {
01645       errorcode = HAL_TIMEOUT;
01646       goto error;
01647     }
01648   }
01649 error:
01650   return errorcode;
01651 }
01652 
01653 /**
01654   * @brief  Tx Handler for Transmit in Interrupt mode 8-bit transfer.
01655   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01656   *                the configuration information for SAI module.
01657   * @retval None
01658   */
01659 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
01660 {
01661   /* Write data on DR register */
01662   hsai->Instance->DR = (*hsai->pBuffPtr++);
01663   hsai->XferCount--;
01664   
01665   /* Handle the end of the transmission */
01666   if(hsai->XferCount == 0)
01667   {
01668     /* Disable FREQ and OVRUDR interrupts */
01669     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 
01670     hsai->State = HAL_SAI_STATE_READY;
01671     HAL_SAI_TxCpltCallback(hsai);
01672   }
01673 }
01674 
01675 /**
01676   * @brief  Tx Handler for Transmit in Interrupt mode for 16-bit transfer.
01677   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01678   *                the configuration information for SAI module.
01679   * @retval None
01680   */
01681 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
01682 {
01683   /* Write data on DR register */
01684   hsai->Instance->DR = *(uint16_t *)hsai->pBuffPtr;
01685   hsai->pBuffPtr+=2;
01686   hsai->XferCount--;
01687   
01688   /* Handle the end of the transmission */
01689   if(hsai->XferCount == 0)
01690   {
01691     /* Disable FREQ and OVRUDR interrupts */
01692     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 
01693     hsai->State = HAL_SAI_STATE_READY;
01694     HAL_SAI_TxCpltCallback(hsai);
01695   }
01696 }
01697 
01698 /**
01699   * @brief  Tx Handler for Transmit in Interrupt mode for 32-bit transfer.
01700   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01701   *                the configuration information for SAI module.
01702   * @retval None
01703   */
01704 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
01705 {
01706   /* Write data on DR register */
01707   hsai->Instance->DR = *(uint32_t *)hsai->pBuffPtr;
01708   hsai->pBuffPtr+=4;
01709   hsai->XferCount--;
01710   
01711   /* Handle the end of the transmission */
01712   if(hsai->XferCount == 0)
01713   {
01714     /* Disable FREQ and OVRUDR interrupts */
01715     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 
01716     hsai->State = HAL_SAI_STATE_READY;
01717     HAL_SAI_TxCpltCallback(hsai);
01718   }
01719 }
01720 
01721 /**
01722   * @brief  Rx Handler for Receive in Interrupt mode 8-bit transfer.
01723   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01724   *                the configuration information for SAI module.
01725   * @retval None
01726   */
01727 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
01728 {
01729   /* Receive data */    
01730   (*hsai->pBuffPtr++) = hsai->Instance->DR;
01731   hsai->XferCount--;
01732   
01733   /* Check end of the transfer */  
01734   if(hsai->XferCount == 0)
01735   {    
01736     /* Disable TXE and OVRUDR interrupts */
01737     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
01738     
01739     /* Clear the SAI Overrun flag */
01740     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
01741     
01742     hsai->State = HAL_SAI_STATE_READY;
01743     HAL_SAI_RxCpltCallback(hsai); 
01744   }
01745 }
01746 
01747 /**
01748   * @brief  Rx Handler for Receive in Interrupt mode for 16-bit transfer.
01749   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01750   *                the configuration information for SAI module.
01751   * @retval None
01752   */
01753 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
01754 {
01755   /* Receive data */    
01756   *(uint16_t*)hsai->pBuffPtr = hsai->Instance->DR;
01757   hsai->pBuffPtr+=2;
01758   hsai->XferCount--;
01759   
01760   /* Check end of the transfer */  
01761   if(hsai->XferCount == 0)
01762   {    
01763     /* Disable TXE and OVRUDR interrupts */
01764     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
01765     
01766     /* Clear the SAI Overrun flag */
01767     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
01768     
01769     hsai->State = HAL_SAI_STATE_READY;
01770     HAL_SAI_RxCpltCallback(hsai); 
01771   }
01772 }
01773 /**
01774   * @brief  Rx Handler for Receive in Interrupt mode for 32-bit transfer.
01775   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains
01776   *                the configuration information for SAI module.
01777   * @retval None
01778   */
01779 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
01780 {
01781   /* Receive data */    
01782   *(uint32_t*)hsai->pBuffPtr = hsai->Instance->DR;
01783   hsai->pBuffPtr+=4;
01784   hsai->XferCount--;
01785   
01786   /* Check end of the transfer */  
01787   if(hsai->XferCount == 0)
01788   {    
01789     /* Disable TXE and OVRUDR interrupts */
01790     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
01791     
01792     /* Clear the SAI Overrun flag */
01793     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
01794     
01795     hsai->State = HAL_SAI_STATE_READY;
01796     HAL_SAI_RxCpltCallback(hsai); 
01797   }
01798 }
01799 /**
01800   * @brief DMA SAI transmit process complete callback.
01801   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
01802   *                the configuration information for the specified DMA module.
01803   * @retval None
01804   */
01805 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)   
01806 {
01807   SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef* )hdma)->Parent;
01808 
01809   if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0)
01810   { 
01811     hsai->XferCount = 0;
01812     
01813     /* Disable SAI Tx DMA Request */  
01814     hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
01815     
01816     /* Stop the interrupts error handling */
01817     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
01818     
01819     hsai->State= HAL_SAI_STATE_READY;
01820   }
01821   HAL_SAI_TxCpltCallback(hsai);
01822 }
01823 
01824 /**
01825   * @brief DMA SAI transmit process half complete callback.
01826   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
01827   *                the configuration information for the specified DMA module.
01828   * @retval None
01829   */
01830 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
01831 {
01832   SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
01833 
01834   HAL_SAI_TxHalfCpltCallback(hsai);
01835 }
01836 
01837 /**
01838   * @brief DMA SAI receive process complete callback. 
01839   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
01840   *                the configuration information for the specified DMA module.
01841   * @retval None
01842   */
01843 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)   
01844 {
01845   SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
01846   if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0)
01847   {
01848     /* Disable Rx DMA Request */
01849     hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
01850     hsai->XferCount = 0;
01851     
01852     /* Stop the interrupts error handling */
01853     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
01854     
01855     hsai->State = HAL_SAI_STATE_READY;
01856   }
01857   HAL_SAI_RxCpltCallback(hsai); 
01858 }
01859 
01860 /**
01861   * @brief DMA SAI receive process half complete callback. 
01862   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
01863   *                the configuration information for the specified DMA module.
01864   * @retval None
01865   */
01866 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
01867 {
01868   SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
01869 
01870   HAL_SAI_RxHalfCpltCallback(hsai); 
01871 }
01872 /**
01873   * @brief DMA SAI communication error callback. 
01874   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
01875   *                the configuration information for the specified DMA module.
01876   * @retval None
01877   */
01878 static void SAI_DMAError(DMA_HandleTypeDef *hdma)   
01879 {
01880   SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
01881   
01882   /* Stop the DMA transfer */
01883   HAL_SAI_DMAStop(hsai);
01884   
01885   /* Set the SAI state ready to be able to start again the process */
01886   hsai->State= HAL_SAI_STATE_READY;
01887   HAL_SAI_ErrorCallback(hsai);
01888   hsai->XferCount = 0;
01889 }
01890 
01891 /**
01892   * @}
01893   */
01894 
01895 #endif /* HAL_SAI_MODULE_ENABLED */
01896 /**
01897   * @}
01898   */
01899 
01900 /**
01901   * @}
01902   */
01903 
01904 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
01905