STM32F479xx HAL User Manual
stm32f4xx_hal_sai.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32f4xx_hal_sai.c
00004   * @author  MCD Application Team
00005   * @brief   SAI HAL module driver.
00006   *          This file provides firmware functions to manage the following
00007   *          functionalities of the Serial Audio Interface (SAI) peripheral:
00008   *           + Initialization/de-initialization functions
00009   *           + I/O operation functions
00010   *           + Peripheral Control functions
00011   *           + Peripheral State functions
00012   *
00013   @verbatim
00014   ==============================================================================
00015                   ##### How to use this driver #####
00016   ==============================================================================
00017 
00018   [..]
00019     The SAI HAL driver can be used as follows:
00020 
00021     (#) Declare a SAI_HandleTypeDef handle structure (eg. SAI_HandleTypeDef hsai).
00022     (#) Initialize the SAI low level resources by implementing the HAL_SAI_MspInit() API:
00023         (##) Enable the SAI interface clock.
00024         (##) SAI pins configuration:
00025             (+++) Enable the clock for the SAI GPIOs.
00026             (+++) Configure these SAI pins as alternate function pull-up.
00027         (##) NVIC configuration if you need to use interrupt process (HAL_SAI_Transmit_IT()
00028              and HAL_SAI_Receive_IT() APIs):
00029             (+++) Configure the SAI interrupt priority.
00030             (+++) Enable the NVIC SAI IRQ handle.
00031 
00032         (##) DMA Configuration if you need to use DMA process (HAL_SAI_Transmit_DMA()
00033              and HAL_SAI_Receive_DMA() APIs):
00034             (+++) Declare a DMA handle structure for the Tx/Rx stream.
00035             (+++) Enable the DMAx interface clock.
00036             (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
00037             (+++) Configure the DMA Tx/Rx Stream.
00038             (+++) Associate the initialized DMA handle to the SAI DMA Tx/Rx handle.
00039             (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the
00040                 DMA Tx/Rx Stream.
00041 
00042     (#) The initialization can be done by two ways
00043         (##) Expert mode : Initialize the structures Init, FrameInit and SlotInit and call HAL_SAI_Init().
00044         (##) Simplified mode : Initialize the high part of Init Structure and call HAL_SAI_InitProtocol().
00045 
00046   [..]
00047     (@) The specific SAI interrupts (FIFO request and Overrun underrun interrupt)
00048         will be managed using the macros __HAL_SAI_ENABLE_IT() and __HAL_SAI_DISABLE_IT()
00049         inside the transmit and receive process.
00050 
00051   [..]
00052    (@) SAI Clock Source configuration is managed differently depending on the selected
00053        STM32F4 devices :
00054        (+@) For STM32F446xx devices, the configuration is managed through RCCEx_PeriphCLKConfig()
00055             function in the HAL RCC drivers
00056        (+@) For STM32F439xx/STM32F437xx/STM32F429xx/STM32F427xx devices, the configuration
00057             is managed within HAL SAI drivers through HAL_SAI_Init() function using
00058             ClockSource field of SAI_InitTypeDef structure.
00059   [..]
00060    (@) Make sure that either:
00061        (+@) I2S PLL is configured or
00062        (+@) SAI PLL is configured or
00063        (+@) External clock source is configured after setting correctly
00064             the define constant EXTERNAL_CLOCK_VALUE in the stm32f4xx_hal_conf.h file.
00065   [..]
00066     (@) In master Tx mode: enabling the audio block immediately generates the bit clock
00067         for the external slaves even if there is no data in the FIFO, However FS signal
00068         generation is conditioned by the presence of data in the FIFO.
00069 
00070   [..]
00071     (@) In master Rx mode: enabling the audio block immediately generates the bit clock
00072         and FS signal for the external slaves.
00073 
00074   [..]
00075     (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior:
00076         (+@) First bit Offset <= (SLOT size - Data size)
00077         (+@) Data size <= SLOT size
00078         (+@) Number of SLOT x SLOT size = Frame length
00079         (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected.
00080 
00081   [..]
00082     Three operation modes are available within this driver :
00083 
00084     *** Polling mode IO operation ***
00085     =================================
00086     [..]
00087       (+) Send an amount of data in blocking mode using HAL_SAI_Transmit()
00088       (+) Receive an amount of data in blocking mode using HAL_SAI_Receive()
00089 
00090     *** Interrupt mode IO operation ***
00091     ===================================
00092     [..]
00093       (+) Send an amount of data in non-blocking mode using HAL_SAI_Transmit_IT()
00094       (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
00095           add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
00096       (+) Receive an amount of data in non-blocking mode using HAL_SAI_Receive_IT()
00097       (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
00098           add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
00099       (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
00100           add his own code by customization of function pointer HAL_SAI_ErrorCallback()
00101 
00102     *** DMA mode IO operation ***
00103     =============================
00104     [..]
00105       (+) Send an amount of data in non-blocking mode (DMA) using HAL_SAI_Transmit_DMA()
00106       (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
00107           add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
00108       (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SAI_Receive_DMA()
00109       (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
00110           add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
00111       (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
00112           add his own code by customization of function pointer HAL_SAI_ErrorCallback()
00113       (+) Pause the DMA Transfer using HAL_SAI_DMAPause()
00114       (+) Resume the DMA Transfer using HAL_SAI_DMAResume()
00115       (+) Stop the DMA Transfer using HAL_SAI_DMAStop()
00116 
00117     *** SAI HAL driver additional function list ***
00118     ===============================================
00119     [..]
00120       Below the list the others API available SAI HAL driver :
00121 
00122       (+) HAL_SAI_EnableTxMuteMode(): Enable the mute in tx mode
00123       (+) HAL_SAI_DisableTxMuteMode(): Disable the mute in tx mode
00124       (+) HAL_SAI_EnableRxMuteMode(): Enable the mute in Rx mode
00125       (+) HAL_SAI_DisableRxMuteMode(): Disable the mute in Rx mode
00126       (+) HAL_SAI_FlushRxFifo(): Flush the rx fifo.
00127       (+) HAL_SAI_Abort(): Abort the current transfer
00128 
00129     *** SAI HAL driver macros list ***
00130     ==================================
00131     [..]
00132       Below the list of most used macros in SAI HAL driver :
00133 
00134       (+) __HAL_SAI_ENABLE(): Enable the SAI peripheral
00135       (+) __HAL_SAI_DISABLE(): Disable the SAI peripheral
00136       (+) __HAL_SAI_ENABLE_IT(): Enable the specified SAI interrupts
00137       (+) __HAL_SAI_DISABLE_IT(): Disable the specified SAI interrupts
00138       (+) __HAL_SAI_GET_IT_SOURCE(): Check if the specified SAI interrupt source is
00139           enabled or disabled
00140       (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not
00141 
00142     *** Callback registration ***
00143     =============================
00144     [..]
00145     The compilation define USE_HAL_SAI_REGISTER_CALLBACKS when set to 1
00146     allows the user to configure dynamically the driver callbacks.
00147     Use functions HAL_SAI_RegisterCallback() to register a user callback.
00148 
00149     [..]
00150     Function HAL_SAI_RegisterCallback() allows to register following callbacks:
00151       (+) RxCpltCallback     : SAI receive complete.
00152       (+) RxHalfCpltCallback : SAI receive half complete.
00153       (+) TxCpltCallback     : SAI transmit complete.
00154       (+) TxHalfCpltCallback : SAI transmit half complete.
00155       (+) ErrorCallback      : SAI error.
00156       (+) MspInitCallback    : SAI MspInit.
00157       (+) MspDeInitCallback  : SAI MspDeInit.
00158     [..]
00159     This function takes as parameters the HAL peripheral handle, the callback ID
00160     and a pointer to the user callback function.
00161 
00162     [..]
00163     Use function HAL_SAI_UnRegisterCallback() to reset a callback to the default
00164     weak (surcharged) function.
00165     HAL_SAI_UnRegisterCallback() takes as parameters the HAL peripheral handle,
00166     and the callback ID.
00167     [..]
00168     This function allows to reset following callbacks:
00169       (+) RxCpltCallback     : SAI receive complete.
00170       (+) RxHalfCpltCallback : SAI receive half complete.
00171       (+) TxCpltCallback     : SAI transmit complete.
00172       (+) TxHalfCpltCallback : SAI transmit half complete.
00173       (+) ErrorCallback      : SAI error.
00174       (+) MspInitCallback    : SAI MspInit.
00175       (+) MspDeInitCallback  : SAI MspDeInit.
00176 
00177     [..]
00178     By default, after the HAL_SAI_Init and if the state is HAL_SAI_STATE_RESET
00179     all callbacks are reset to the corresponding legacy weak (surcharged) functions:
00180     examples HAL_SAI_RxCpltCallback(), HAL_SAI_ErrorCallback().
00181     Exception done for MspInit and MspDeInit callbacks that are respectively
00182     reset to the legacy weak (surcharged) functions in the HAL_SAI_Init
00183     and HAL_SAI_DeInit only when these callbacks are null (not registered beforehand).
00184     If not, MspInit or MspDeInit are not null, the HAL_SAI_Init and HAL_SAI_DeInit
00185     keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
00186 
00187     [..]
00188     Callbacks can be registered/unregistered in READY state only.
00189     Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
00190     in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
00191     during the Init/DeInit.
00192     In that case first register the MspInit/MspDeInit user callbacks
00193     using HAL_SAI_RegisterCallback before calling HAL_SAI_DeInit
00194     or HAL_SAI_Init function.
00195 
00196     [..]
00197     When the compilation define USE_HAL_SAI_REGISTER_CALLBACKS is set to 0 or
00198     not defined, the callback registering feature is not available
00199     and weak (surcharged) callbacks are used.
00200 
00201   @endverbatim
00202   ******************************************************************************
00203   * @attention
00204   *
00205   * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
00206   * All rights reserved.</center></h2>
00207   *
00208   * This software component is licensed by ST under BSD 3-Clause license,
00209   * the "License"; You may not use this file except in compliance with the
00210   * License. You may obtain a copy of the License at:
00211   *                        opensource.org/licenses/BSD-3-Clause
00212   *
00213   ******************************************************************************
00214   */
00215 
00216 /* Includes ------------------------------------------------------------------*/
00217 #include "stm32f4xx_hal.h"
00218 
00219 /** @addtogroup STM32F4xx_HAL_Driver
00220   * @{
00221   */
00222 
00223 /** @defgroup SAI SAI
00224   * @brief SAI HAL module driver
00225   * @{
00226   */
00227 
00228 #ifdef HAL_SAI_MODULE_ENABLED
00229 
00230 #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\
00231     defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) ||\
00232     defined(STM32F423xx)
00233 
00234 /** @defgroup SAI_Private_Typedefs  SAI Private Typedefs
00235   * @{
00236   */
00237 typedef enum
00238 {
00239   SAI_MODE_DMA,
00240   SAI_MODE_IT
00241 } SAI_ModeTypedef;
00242 /**
00243   * @}
00244   */
00245 
00246 /* Private define ------------------------------------------------------------*/
00247 
00248 /** @defgroup SAI_Private_Constants  SAI Private Constants
00249   * @{
00250   */
00251 #define SAI_DEFAULT_TIMEOUT   4U /* 4ms */
00252 #define SAI_LONG_TIMEOUT      1000U /* 1s */
00253 /**
00254   * @}
00255   */
00256 
00257 /* Private macro -------------------------------------------------------------*/
00258 /* Private variables ---------------------------------------------------------*/
00259 /* Private function prototypes -----------------------------------------------*/
00260 /** @defgroup SAI_Private_Functions  SAI Private Functions
00261   * @{
00262   */
00263 static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
00264 static uint32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode);
00265 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
00266 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
00267 
00268 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
00269 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
00270 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
00271 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
00272 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
00273 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
00274 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
00275 
00276 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
00277 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
00278 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
00279 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
00280 static void SAI_DMAError(DMA_HandleTypeDef *hdma);
00281 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma);
00282 /**
00283   * @}
00284   */
00285 
00286 /* Exported functions ---------------------------------------------------------*/
00287 /** @defgroup SAI_Exported_Functions SAI Exported Functions
00288   * @{
00289   */
00290 
00291 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions
00292   * @brief    Initialization and Configuration functions
00293   *
00294 @verbatim
00295  ===============================================================================
00296             ##### Initialization and de-initialization functions #####
00297  ===============================================================================
00298   [..]  This subsection provides a set of functions allowing to initialize and
00299         de-initialize the SAIx peripheral:
00300 
00301       (+) User must implement HAL_SAI_MspInit() function in which he configures
00302           all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
00303 
00304       (+) Call the function HAL_SAI_Init() to configure the selected device with
00305           the selected configuration:
00306         (++) Mode (Master/slave TX/RX)
00307         (++) Protocol
00308         (++) Data Size
00309         (++) MCLK Output
00310         (++) Audio frequency
00311         (++) FIFO Threshold
00312         (++) Frame Config
00313         (++) Slot Config
00314 
00315       (+) Call the function HAL_SAI_DeInit() to restore the default configuration
00316           of the selected SAI peripheral.
00317 
00318 @endverbatim
00319   * @{
00320   */
00321 
00322 /**
00323   * @brief  Initialize the structure FrameInit, SlotInit and the low part of
00324   *         Init according to the specified parameters and call the function
00325   *         HAL_SAI_Init to initialize the SAI block.
00326   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00327   *               the configuration information for SAI module.
00328   * @param  protocol one of the supported protocol @ref SAI_Protocol
00329   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize
00330   *                   the configuration information for SAI module.
00331   * @param  nbslot Number of slot.
00332   * @retval HAL status
00333   */
00334 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
00335 {
00336   HAL_StatusTypeDef status = HAL_OK;
00337 
00338   /* Check the parameters */
00339   assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));
00340   assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));
00341 
00342   switch (protocol)
00343   {
00344     case SAI_I2S_STANDARD :
00345     case SAI_I2S_MSBJUSTIFIED :
00346     case SAI_I2S_LSBJUSTIFIED :
00347       status = SAI_InitI2S(hsai, protocol, datasize, nbslot);
00348       break;
00349     case SAI_PCM_LONG :
00350     case SAI_PCM_SHORT :
00351       status = SAI_InitPCM(hsai, protocol, datasize, nbslot);
00352       break;
00353     default :
00354       status = HAL_ERROR;
00355       break;
00356   }
00357 
00358   if (status == HAL_OK)
00359   {
00360     status = HAL_SAI_Init(hsai);
00361   }
00362 
00363   return status;
00364 }
00365 
00366 /**
00367   * @brief  Initialize the SAI according to the specified parameters.
00368   *         in the SAI_InitTypeDef structure and initialize the associated handle.
00369   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00370   *               the configuration information for SAI module.
00371   * @retval HAL status
00372   */
00373 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
00374 {
00375   uint32_t tmpregisterGCR = 0U;
00376 
00377   /* This variable used to store the SAI_CK_x (value in Hz) */
00378   uint32_t freq = 0U;
00379 
00380   /* This variable is used to compute CKSTR bits of SAI CR1 according to
00381      ClockStrobing and AudioMode fields */
00382   uint32_t ckstr_bits = 0U;
00383   uint32_t syncen_bits = 0U;
00384 
00385   /* Check the SAI handle allocation */
00386   if (hsai == NULL)
00387   {
00388     return HAL_ERROR;
00389   }
00390 
00391   /* check the instance */
00392   assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance));
00393 
00394   /* Check the SAI Block parameters */
00395   assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
00396   assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
00397   assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
00398   assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));
00399   assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
00400   assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
00401   assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
00402   assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
00403   assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
00404   assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
00405   assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
00406   assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode));
00407   assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));
00408   assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));
00409 
00410   /* Check the SAI Block Frame parameters */
00411   assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
00412   assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
00413   assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
00414   assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
00415   assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
00416 
00417   /* Check the SAI Block Slot parameters */
00418   assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
00419   assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
00420   assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
00421   assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
00422 
00423   if (hsai->State == HAL_SAI_STATE_RESET)
00424   {
00425     /* Allocate lock resource and initialize it */
00426     hsai->Lock = HAL_UNLOCKED;
00427 
00428 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
00429     /* Reset callback pointers to the weak predefined callbacks */
00430     hsai->RxCpltCallback     = HAL_SAI_RxCpltCallback;
00431     hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
00432     hsai->TxCpltCallback     = HAL_SAI_TxCpltCallback;
00433     hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
00434     hsai->ErrorCallback      = HAL_SAI_ErrorCallback;
00435 
00436     /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
00437     if (hsai->MspInitCallback == NULL)
00438     {
00439       hsai->MspInitCallback = HAL_SAI_MspInit;
00440     }
00441     hsai->MspInitCallback(hsai);
00442 #else
00443     /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
00444     HAL_SAI_MspInit(hsai);
00445 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
00446   }
00447 
00448   hsai->State = HAL_SAI_STATE_BUSY;
00449 
00450   /* Disable the selected SAI peripheral */
00451   SAI_Disable(hsai);
00452 
00453   /* SAI Block Synchro Configuration -----------------------------------------*/
00454   SAI_BlockSynchroConfig(hsai);
00455 
00456   /* Configure Master Clock using the following formula :
00457      MCLK_x = SAI_CK_x / (MCKDIV[3:0] * 2) with MCLK_x = 256 * FS
00458      FS = SAI_CK_x / (MCKDIV[3:0] * 2) * 256
00459      MCKDIV[3:0] = SAI_CK_x / FS * 512 */
00460   if (hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)
00461   {
00462     /* Get SAI clock source based on Source clock selection from RCC */
00463     freq = SAI_GetInputClock(hsai);
00464 
00465     /* (saiclocksource x 10) to keep Significant digits */
00466     tmpregisterGCR = (((freq * 10U) / ((hsai->Init.AudioFrequency) * 512U)));
00467 
00468     hsai->Init.Mckdiv = tmpregisterGCR / 10U;
00469 
00470     /* Round result to the nearest integer */
00471     if ((tmpregisterGCR % 10U) > 8U)
00472     {
00473       hsai->Init.Mckdiv += 1U;
00474     }
00475 
00476     /* For SPDIF protocol, SAI shall provide a bit clock twice faster the symbol-rate */
00477     if (hsai->Init.Protocol == SAI_SPDIF_PROTOCOL)
00478     {
00479       hsai->Init.Mckdiv = hsai->Init.Mckdiv >> 1;
00480     }
00481   }
00482 
00483   /* Check the SAI Block master clock divider parameter */
00484   assert_param(IS_SAI_BLOCK_MASTER_DIVIDER(hsai->Init.Mckdiv));
00485 
00486   /* Compute CKSTR bits of SAI CR1 according to ClockStrobing and AudioMode */
00487   if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
00488   {
00489     ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U : SAI_xCR1_CKSTR;
00490   }
00491   else
00492   {
00493     ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR : 0U;
00494   }
00495 
00496   /* SAI Block Configuration -------------------------------------------------*/
00497   switch (hsai->Init.Synchro)
00498   {
00499     case SAI_ASYNCHRONOUS :
00500     {
00501       syncen_bits = 0U;
00502     }
00503     break;
00504     case SAI_SYNCHRONOUS :
00505     {
00506       syncen_bits = SAI_xCR1_SYNCEN_0;
00507     }
00508     break;
00509     case SAI_SYNCHRONOUS_EXT_SAI1 :
00510     case SAI_SYNCHRONOUS_EXT_SAI2 :
00511     {
00512       syncen_bits = SAI_xCR1_SYNCEN_1;
00513     }
00514     break;
00515     default:
00516       break;
00517   }
00518 
00519   /* SAI CR1 Configuration */
00520   hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG |  SAI_xCR1_DS |      \
00521                            SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
00522                            SAI_xCR1_MONO | SAI_xCR1_OUTDRIV  | SAI_xCR1_DMAEN |  \
00523                            SAI_xCR1_NODIV | SAI_xCR1_MCKDIV);
00524 
00525   hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol |           \
00526                           hsai->Init.DataSize | hsai->Init.FirstBit  |           \
00527                           ckstr_bits | syncen_bits |                             \
00528                           hsai->Init.MonoStereoMode | hsai->Init.OutputDrive |   \
00529                           hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20U));
00530 
00531   /* SAI CR2 Configuration */
00532   hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL);
00533   hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);
00534 
00535   /* SAI Frame Configuration -----------------------------------------*/
00536   hsai->Instance->FRCR &= (~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \
00537                              SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF));
00538   hsai->Instance->FRCR |= ((hsai->FrameInit.FrameLength - 1U) |
00539                            hsai->FrameInit.FSOffset     |
00540                            hsai->FrameInit.FSDefinition |
00541                            hsai->FrameInit.FSPolarity   |
00542                            ((hsai->FrameInit.ActiveFrameLength - 1U) << 8U));
00543 
00544   /* SAI Block_x SLOT Configuration ------------------------------------------*/
00545   /* This register has no meaning in AC 97 and SPDIF audio protocol */
00546   hsai->Instance->SLOTR &= ~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ | \
00547                              SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN);
00548 
00549   hsai->Instance->SLOTR |=  hsai->SlotInit.FirstBitOffset |  hsai->SlotInit.SlotSize  | \
00550                             (hsai->SlotInit.SlotActive << 16U) | ((hsai->SlotInit.SlotNumber - 1U) <<  8U);
00551 
00552   /* Initialize the error code */
00553   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00554 
00555   /* Initialize the SAI state */
00556   hsai->State = HAL_SAI_STATE_READY;
00557 
00558   /* Release Lock */
00559   __HAL_UNLOCK(hsai);
00560 
00561   return HAL_OK;
00562 }
00563 
00564 /**
00565   * @brief  DeInitialize the SAI peripheral.
00566   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00567   *               the configuration information for SAI module.
00568   * @retval HAL status
00569   */
00570 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
00571 {
00572   /* Check the SAI handle allocation */
00573   if (hsai == NULL)
00574   {
00575     return HAL_ERROR;
00576   }
00577 
00578   hsai->State = HAL_SAI_STATE_BUSY;
00579 
00580   /* Disabled All interrupt and clear all the flag */
00581   hsai->Instance->IMR = 0U;
00582   hsai->Instance->CLRFR = 0xFFFFFFFFU;
00583 
00584   /* Disable the SAI */
00585   SAI_Disable(hsai);
00586 
00587   /* Flush the fifo */
00588   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
00589 
00590   /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
00591 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
00592   if (hsai->MspDeInitCallback == NULL)
00593   {
00594     hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
00595   }
00596   hsai->MspDeInitCallback(hsai);
00597 #else
00598   HAL_SAI_MspDeInit(hsai);
00599 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
00600 
00601   /* Initialize the error code */
00602   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00603 
00604   /* Initialize the SAI state */
00605   hsai->State = HAL_SAI_STATE_RESET;
00606 
00607   /* Release Lock */
00608   __HAL_UNLOCK(hsai);
00609 
00610   return HAL_OK;
00611 }
00612 
00613 /**
00614   * @brief Initialize the SAI MSP.
00615   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00616   *               the configuration information for SAI module.
00617   * @retval None
00618   */
00619 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
00620 {
00621   /* Prevent unused argument(s) compilation warning */
00622   UNUSED(hsai);
00623 
00624   /* NOTE : This function should not be modified, when the callback is needed,
00625             the HAL_SAI_MspInit could be implemented in the user file
00626    */
00627 }
00628 
00629 /**
00630   * @brief DeInitialize the SAI MSP.
00631   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00632   *               the configuration information for SAI module.
00633   * @retval None
00634   */
00635 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
00636 {
00637   /* Prevent unused argument(s) compilation warning */
00638   UNUSED(hsai);
00639 
00640   /* NOTE : This function should not be modified, when the callback is needed,
00641             the HAL_SAI_MspDeInit could be implemented in the user file
00642    */
00643 }
00644 
00645 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
00646 /**
00647   * @brief  Register a user SAI callback
00648   *         to be used instead of the weak predefined callback.
00649   * @param  hsai SAI handle.
00650   * @param  CallbackID ID of the callback to be registered.
00651   *         This parameter can be one of the following values:
00652   *           @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
00653   *           @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
00654   *           @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
00655   *           @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
00656   *           @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
00657   *           @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
00658   *           @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
00659   * @param  pCallback pointer to the callback function.
00660   * @retval HAL status.
00661   */
00662 HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef        *hsai,
00663                                            HAL_SAI_CallbackIDTypeDef CallbackID,
00664                                            pSAI_CallbackTypeDef      pCallback)
00665 {
00666   HAL_StatusTypeDef status = HAL_OK;
00667 
00668   if (pCallback == NULL)
00669   {
00670     /* update the error code */
00671     hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
00672     /* update return status */
00673     status = HAL_ERROR;
00674   }
00675   else
00676   {
00677     if (HAL_SAI_STATE_READY == hsai->State)
00678     {
00679       switch (CallbackID)
00680       {
00681         case HAL_SAI_RX_COMPLETE_CB_ID :
00682           hsai->RxCpltCallback = pCallback;
00683           break;
00684         case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
00685           hsai->RxHalfCpltCallback = pCallback;
00686           break;
00687         case HAL_SAI_TX_COMPLETE_CB_ID :
00688           hsai->TxCpltCallback = pCallback;
00689           break;
00690         case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
00691           hsai->TxHalfCpltCallback = pCallback;
00692           break;
00693         case HAL_SAI_ERROR_CB_ID :
00694           hsai->ErrorCallback = pCallback;
00695           break;
00696         case HAL_SAI_MSPINIT_CB_ID :
00697           hsai->MspInitCallback = pCallback;
00698           break;
00699         case HAL_SAI_MSPDEINIT_CB_ID :
00700           hsai->MspDeInitCallback = pCallback;
00701           break;
00702         default :
00703           /* update the error code */
00704           hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
00705           /* update return status */
00706           status = HAL_ERROR;
00707           break;
00708       }
00709     }
00710     else if (HAL_SAI_STATE_RESET == hsai->State)
00711     {
00712       switch (CallbackID)
00713       {
00714         case HAL_SAI_MSPINIT_CB_ID :
00715           hsai->MspInitCallback = pCallback;
00716           break;
00717         case HAL_SAI_MSPDEINIT_CB_ID :
00718           hsai->MspDeInitCallback = pCallback;
00719           break;
00720         default :
00721           /* update the error code */
00722           hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
00723           /* update return status */
00724           status = HAL_ERROR;
00725           break;
00726       }
00727     }
00728     else
00729     {
00730       /* update the error code */
00731       hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
00732       /* update return status */
00733       status = HAL_ERROR;
00734     }
00735   }
00736   return status;
00737 }
00738 
00739 /**
00740   * @brief  Unregister a user SAI callback.
00741   *         SAI callback is redirected to the weak predefined callback.
00742   * @param  hsai SAI handle.
00743   * @param  CallbackID ID of the callback to be unregistered.
00744   *         This parameter can be one of the following values:
00745   *           @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
00746   *           @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
00747   *           @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
00748   *           @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
00749   *           @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
00750   *           @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
00751   *           @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
00752   * @retval HAL status.
00753   */
00754 HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef        *hsai,
00755                                              HAL_SAI_CallbackIDTypeDef CallbackID)
00756 {
00757   HAL_StatusTypeDef status = HAL_OK;
00758 
00759   if (HAL_SAI_STATE_READY == hsai->State)
00760   {
00761     switch (CallbackID)
00762     {
00763       case HAL_SAI_RX_COMPLETE_CB_ID :
00764         hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
00765         break;
00766       case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
00767         hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
00768         break;
00769       case HAL_SAI_TX_COMPLETE_CB_ID :
00770         hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
00771         break;
00772       case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
00773         hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
00774         break;
00775       case HAL_SAI_ERROR_CB_ID :
00776         hsai->ErrorCallback = HAL_SAI_ErrorCallback;
00777         break;
00778       case HAL_SAI_MSPINIT_CB_ID :
00779         hsai->MspInitCallback = HAL_SAI_MspInit;
00780         break;
00781       case HAL_SAI_MSPDEINIT_CB_ID :
00782         hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
00783         break;
00784       default :
00785         /* update the error code */
00786         hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
00787         /* update return status */
00788         status = HAL_ERROR;
00789         break;
00790     }
00791   }
00792   else if (HAL_SAI_STATE_RESET == hsai->State)
00793   {
00794     switch (CallbackID)
00795     {
00796       case HAL_SAI_MSPINIT_CB_ID :
00797         hsai->MspInitCallback = HAL_SAI_MspInit;
00798         break;
00799       case HAL_SAI_MSPDEINIT_CB_ID :
00800         hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
00801         break;
00802       default :
00803         /* update the error code */
00804         hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
00805         /* update return status */
00806         status = HAL_ERROR;
00807         break;
00808     }
00809   }
00810   else
00811   {
00812     /* update the error code */
00813     hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
00814     /* update return status */
00815     status = HAL_ERROR;
00816   }
00817   return status;
00818 }
00819 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
00820 
00821 /**
00822   * @}
00823   */
00824 
00825 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions
00826   * @brief    Data transfers functions
00827   *
00828 @verbatim
00829   ==============================================================================
00830                       ##### IO operation functions #####
00831   ==============================================================================
00832   [..]
00833     This subsection provides a set of functions allowing to manage the SAI data
00834     transfers.
00835 
00836     (+) There are two modes of transfer:
00837       (++) Blocking mode : The communication is performed in the polling mode.
00838            The status of all data processing is returned by the same function
00839            after finishing transfer.
00840       (++) No-Blocking mode : The communication is performed using Interrupts
00841            or DMA. These functions return the status of the transfer startup.
00842            The end of the data processing will be indicated through the
00843            dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when
00844            using DMA mode.
00845 
00846     (+) Blocking mode functions are :
00847       (++) HAL_SAI_Transmit()
00848       (++) HAL_SAI_Receive()
00849 
00850     (+) Non Blocking mode functions with Interrupt are :
00851       (++) HAL_SAI_Transmit_IT()
00852       (++) HAL_SAI_Receive_IT()
00853 
00854     (+) Non Blocking mode functions with DMA are :
00855       (++) HAL_SAI_Transmit_DMA()
00856       (++) HAL_SAI_Receive_DMA()
00857 
00858     (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
00859       (++) HAL_SAI_TxCpltCallback()
00860       (++) HAL_SAI_RxCpltCallback()
00861       (++) HAL_SAI_ErrorCallback()
00862 
00863 @endverbatim
00864   * @{
00865   */
00866 
00867 /**
00868   * @brief  Transmit an amount of data in blocking mode.
00869   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00870   *               the configuration information for SAI module.
00871   * @param  pData Pointer to data buffer
00872   * @param  Size Amount of data to be sent
00873   * @param  Timeout Timeout duration
00874   * @retval HAL status
00875   */
00876 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
00877 {
00878   uint32_t tickstart = HAL_GetTick();
00879 
00880   if ((pData == NULL) || (Size == 0))
00881   {
00882     return  HAL_ERROR;
00883   }
00884 
00885   if (hsai->State == HAL_SAI_STATE_READY)
00886   {
00887     /* Process Locked */
00888     __HAL_LOCK(hsai);
00889 
00890     hsai->XferSize = Size;
00891     hsai->XferCount = Size;
00892     hsai->pBuffPtr = pData;
00893     hsai->State = HAL_SAI_STATE_BUSY_TX;
00894     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00895 
00896     /* Check if the SAI is already enabled */
00897     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
00898     {
00899       /* fill the fifo with data before to enabled the SAI */
00900       SAI_FillFifo(hsai);
00901       /* Enable SAI peripheral */
00902       __HAL_SAI_ENABLE(hsai);
00903     }
00904 
00905     while (hsai->XferCount > 0U)
00906     {
00907       /* Write data if the FIFO is not full */
00908       if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
00909       {
00910         if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
00911         {
00912           hsai->Instance->DR = (*hsai->pBuffPtr++);
00913         }
00914         else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
00915         {
00916           hsai->Instance->DR = *((uint16_t *)hsai->pBuffPtr);
00917           hsai->pBuffPtr += 2U;
00918         }
00919         else
00920         {
00921           hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
00922           hsai->pBuffPtr += 4U;
00923         }
00924         hsai->XferCount--;
00925       }
00926       else
00927       {
00928         /* Check for the Timeout */
00929         if ((Timeout != HAL_MAX_DELAY) && ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)))
00930         {
00931           /* Update error code */
00932           hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
00933 
00934           /* Clear all the flags */
00935           hsai->Instance->CLRFR = 0xFFFFFFFFU;
00936 
00937           /* Disable SAI peripheral */
00938           SAI_Disable(hsai);
00939 
00940           /* Flush the fifo */
00941           SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
00942 
00943           /* Change the SAI state */
00944           hsai->State = HAL_SAI_STATE_READY;
00945 
00946           /* Process Unlocked */
00947           __HAL_UNLOCK(hsai);
00948 
00949           return HAL_ERROR;
00950         }
00951       }
00952     }
00953 
00954     hsai->State = HAL_SAI_STATE_READY;
00955 
00956     /* Process Unlocked */
00957     __HAL_UNLOCK(hsai);
00958 
00959     return HAL_OK;
00960   }
00961   else
00962   {
00963     return HAL_BUSY;
00964   }
00965 }
00966 
00967 /**
00968   * @brief  Receive an amount of data in blocking mode.
00969   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00970   *               the configuration information for SAI module.
00971   * @param  pData Pointer to data buffer
00972   * @param  Size Amount of data to be received
00973   * @param  Timeout Timeout duration
00974   * @retval HAL status
00975   */
00976 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
00977 {
00978   uint32_t tickstart = HAL_GetTick();
00979 
00980   if ((pData == NULL) || (Size == 0))
00981   {
00982     return  HAL_ERROR;
00983   }
00984 
00985   if (hsai->State == HAL_SAI_STATE_READY)
00986   {
00987     /* Process Locked */
00988     __HAL_LOCK(hsai);
00989 
00990     hsai->pBuffPtr = pData;
00991     hsai->XferSize = Size;
00992     hsai->XferCount = Size;
00993     hsai->State = HAL_SAI_STATE_BUSY_RX;
00994     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00995 
00996     /* Check if the SAI is already enabled */
00997     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
00998     {
00999       /* Enable SAI peripheral */
01000       __HAL_SAI_ENABLE(hsai);
01001     }
01002 
01003     /* Receive data */
01004     while (hsai->XferCount > 0U)
01005     {
01006       if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)
01007       {
01008         if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
01009         {
01010           (*hsai->pBuffPtr++) = hsai->Instance->DR;
01011         }
01012         else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
01013         {
01014           *((uint16_t *)hsai->pBuffPtr) = hsai->Instance->DR;
01015           hsai->pBuffPtr += 2U;
01016         }
01017         else
01018         {
01019           *((uint32_t *)hsai->pBuffPtr) = hsai->Instance->DR;
01020           hsai->pBuffPtr += 4U;
01021         }
01022         hsai->XferCount--;
01023       }
01024       else
01025       {
01026         /* Check for the Timeout */
01027         if ((Timeout != HAL_MAX_DELAY) && ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)))
01028         {
01029           /* Update error code */
01030           hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
01031 
01032           /* Clear all the flags */
01033           hsai->Instance->CLRFR = 0xFFFFFFFFU;
01034 
01035           /* Disable SAI peripheral */
01036           SAI_Disable(hsai);
01037 
01038           /* Flush the fifo */
01039           SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
01040 
01041           /* Change the SAI state */
01042           hsai->State = HAL_SAI_STATE_READY;
01043 
01044           /* Process Unlocked */
01045           __HAL_UNLOCK(hsai);
01046 
01047           return HAL_ERROR;
01048         }
01049       }
01050     }
01051 
01052     hsai->State = HAL_SAI_STATE_READY;
01053 
01054     /* Process Unlocked */
01055     __HAL_UNLOCK(hsai);
01056 
01057     return HAL_OK;
01058   }
01059   else
01060   {
01061     return HAL_BUSY;
01062   }
01063 }
01064 
01065 /**
01066   * @brief  Transmit an amount of data in non-blocking mode with Interrupt.
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 sent
01071   * @retval HAL status
01072   */
01073 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
01074 {
01075   if ((pData == NULL) || (Size == 0))
01076   {
01077     return  HAL_ERROR;
01078   }
01079 
01080   if (hsai->State == HAL_SAI_STATE_READY)
01081   {
01082     /* Process Locked */
01083     __HAL_LOCK(hsai);
01084 
01085     hsai->pBuffPtr = pData;
01086     hsai->XferSize = Size;
01087     hsai->XferCount = Size;
01088     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
01089     hsai->State = HAL_SAI_STATE_BUSY_TX;
01090 
01091     if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
01092     {
01093       hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;
01094     }
01095     else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
01096     {
01097       hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;
01098     }
01099     else
01100     {
01101       hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;
01102     }
01103 
01104     /* Fill the fifo before starting the communication */
01105     SAI_FillFifo(hsai);
01106 
01107     /* Enable FRQ and OVRUDR interrupts */
01108     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
01109 
01110     /* Check if the SAI is already enabled */
01111     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
01112     {
01113       /* Enable SAI peripheral */
01114       __HAL_SAI_ENABLE(hsai);
01115     }
01116     /* Process Unlocked */
01117     __HAL_UNLOCK(hsai);
01118 
01119     return HAL_OK;
01120   }
01121   else
01122   {
01123     return HAL_BUSY;
01124   }
01125 }
01126 
01127 /**
01128   * @brief  Receive an amount of data in non-blocking mode with Interrupt.
01129   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01130   *               the configuration information for SAI module.
01131   * @param  pData Pointer to data buffer
01132   * @param  Size Amount of data to be received
01133   * @retval HAL status
01134   */
01135 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
01136 {
01137   if ((pData == NULL) || (Size == 0))
01138   {
01139     return  HAL_ERROR;
01140   }
01141 
01142   if (hsai->State == HAL_SAI_STATE_READY)
01143   {
01144     /* Process Locked */
01145     __HAL_LOCK(hsai);
01146 
01147     hsai->pBuffPtr = pData;
01148     hsai->XferSize = Size;
01149     hsai->XferCount = Size;
01150     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
01151     hsai->State = HAL_SAI_STATE_BUSY_RX;
01152 
01153     if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
01154     {
01155       hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;
01156     }
01157     else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
01158     {
01159       hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;
01160     }
01161     else
01162     {
01163       hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;
01164     }
01165 
01166     /* Enable TXE and OVRUDR interrupts */
01167     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
01168 
01169     /* Check if the SAI is already enabled */
01170     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
01171     {
01172       /* Enable SAI peripheral */
01173       __HAL_SAI_ENABLE(hsai);
01174     }
01175 
01176     /* Process Unlocked */
01177     __HAL_UNLOCK(hsai);
01178 
01179     return HAL_OK;
01180   }
01181   else
01182   {
01183     return HAL_BUSY;
01184   }
01185 }
01186 
01187 /**
01188   * @brief Pause the audio stream playing from the Media.
01189   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01190   *               the configuration information for SAI module.
01191   * @retval HAL status
01192   */
01193 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
01194 {
01195   /* Process Locked */
01196   __HAL_LOCK(hsai);
01197 
01198   /* Pause the audio file playing by disabling the SAI DMA requests */
01199   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
01200 
01201   /* Process Unlocked */
01202   __HAL_UNLOCK(hsai);
01203 
01204   return HAL_OK;
01205 }
01206 
01207 /**
01208   * @brief Resume the audio stream playing from the Media.
01209   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01210   *               the configuration information for SAI module.
01211   * @retval HAL status
01212   */
01213 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
01214 {
01215   /* Process Locked */
01216   __HAL_LOCK(hsai);
01217 
01218   /* Enable the SAI DMA requests */
01219   hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
01220 
01221   /* If the SAI peripheral is still not enabled, enable it */
01222   if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
01223   {
01224     /* Enable SAI peripheral */
01225     __HAL_SAI_ENABLE(hsai);
01226   }
01227 
01228   /* Process Unlocked */
01229   __HAL_UNLOCK(hsai);
01230 
01231   return HAL_OK;
01232 }
01233 
01234 /**
01235   * @brief Stop the audio stream playing from the Media.
01236   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01237   *               the configuration information for SAI module.
01238   * @retval HAL status
01239   */
01240 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
01241 {
01242   HAL_StatusTypeDef status = HAL_OK;
01243 
01244   /* Process Locked */
01245   __HAL_LOCK(hsai);
01246 
01247   /* Disable the SAI DMA request */
01248   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
01249 
01250   /* Abort the SAI Tx DMA Stream */
01251   if ((hsai->hdmatx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_TX))
01252   {
01253     if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
01254     {
01255       /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
01256       if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
01257       {
01258         status = HAL_ERROR;
01259         hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
01260       }
01261     }
01262   }
01263 
01264   /* Abort the SAI Rx DMA Stream */
01265   if ((hsai->hdmarx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_RX))
01266   {
01267     if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
01268     {
01269       /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
01270       if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
01271       {
01272         status = HAL_ERROR;
01273         hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
01274       }
01275     }
01276   }
01277 
01278   /* Disable SAI peripheral */
01279   SAI_Disable(hsai);
01280 
01281   /* Flush the fifo */
01282   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
01283 
01284   /* Set hsai state to ready */
01285   hsai->State = HAL_SAI_STATE_READY;
01286 
01287   /* Process Unlocked */
01288   __HAL_UNLOCK(hsai);
01289 
01290   return status;
01291 }
01292 
01293 /**
01294   * @brief Abort the current transfer and disable the SAI.
01295   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01296   *               the configuration information for SAI module.
01297   * @retval HAL status
01298   */
01299 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
01300 {
01301   HAL_StatusTypeDef status = HAL_OK;
01302 
01303   /* Process Locked */
01304   __HAL_LOCK(hsai);
01305 
01306   /* Check SAI DMA is enabled or not */
01307   if ((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
01308   {
01309     /* Disable the SAI DMA request */
01310     hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
01311 
01312     /* Abort the SAI Tx DMA Stream */
01313     if ((hsai->hdmatx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_TX))
01314     {
01315       if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
01316       {
01317         /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
01318         if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
01319         {
01320           status = HAL_ERROR;
01321           hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
01322         }
01323       }
01324     }
01325 
01326     /* Abort the SAI Rx DMA Stream */
01327     if ((hsai->hdmarx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_RX))
01328     {
01329       if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
01330       {
01331         /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
01332         if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
01333         {
01334           status = HAL_ERROR;
01335           hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
01336         }
01337       }
01338     }
01339   }
01340 
01341   /* Disabled All interrupt and clear all the flag */
01342   hsai->Instance->IMR = 0U;
01343   hsai->Instance->CLRFR = 0xFFFFFFFFU;
01344 
01345   /* Disable SAI peripheral */
01346   SAI_Disable(hsai);
01347 
01348   /* Flush the fifo */
01349   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
01350 
01351   /* Set hsai state to ready */
01352   hsai->State = HAL_SAI_STATE_READY;
01353 
01354   /* Process Unlocked */
01355   __HAL_UNLOCK(hsai);
01356 
01357   return status;
01358 }
01359 
01360 /**
01361   * @brief  Transmit an amount of data in non-blocking mode with DMA.
01362   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01363   *               the configuration information for SAI module.
01364   * @param  pData Pointer to data buffer
01365   * @param  Size Amount of data to be sent
01366   * @retval HAL status
01367   */
01368 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
01369 {
01370   uint32_t tickstart = HAL_GetTick();
01371 
01372   if ((pData == NULL) || (Size == 0))
01373   {
01374     return  HAL_ERROR;
01375   }
01376 
01377   if (hsai->State == HAL_SAI_STATE_READY)
01378   {
01379     /* Process Locked */
01380     __HAL_LOCK(hsai);
01381 
01382     hsai->pBuffPtr = pData;
01383     hsai->XferSize = Size;
01384     hsai->XferCount = Size;
01385     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
01386     hsai->State = HAL_SAI_STATE_BUSY_TX;
01387 
01388     /* Set the SAI Tx DMA Half transfer complete callback */
01389     hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
01390 
01391     /* Set the SAI TxDMA transfer complete callback */
01392     hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
01393 
01394     /* Set the DMA error callback */
01395     hsai->hdmatx->XferErrorCallback = SAI_DMAError;
01396 
01397     /* Set the DMA Tx abort callback */
01398     hsai->hdmatx->XferAbortCallback = NULL;
01399 
01400     /* Enable the Tx DMA Stream */
01401     if (HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK)
01402     {
01403       __HAL_UNLOCK(hsai);
01404       return  HAL_ERROR;
01405     }
01406 
01407     /* Enable the interrupts for error handling */
01408     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
01409 
01410     /* Enable SAI Tx DMA Request */
01411     hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
01412 
01413     /* Wait until FIFO is not empty */
01414     while ((hsai->Instance->SR & SAI_xSR_FLVL) == SAI_FIFOSTATUS_EMPTY)
01415     {
01416       /* Check for the Timeout */
01417       if ((HAL_GetTick() - tickstart) > SAI_LONG_TIMEOUT)
01418       {
01419         /* Update error code */
01420         hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
01421 
01422         /* Process Unlocked */
01423         __HAL_UNLOCK(hsai);
01424 
01425         return HAL_TIMEOUT;
01426       }
01427     }
01428 
01429     /* Check if the SAI is already enabled */
01430     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
01431     {
01432       /* Enable SAI peripheral */
01433       __HAL_SAI_ENABLE(hsai);
01434     }
01435 
01436     /* Process Unlocked */
01437     __HAL_UNLOCK(hsai);
01438 
01439     return HAL_OK;
01440   }
01441   else
01442   {
01443     return HAL_BUSY;
01444   }
01445 }
01446 
01447 /**
01448   * @brief  Receive an amount of data in non-blocking mode with DMA.
01449   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01450   *               the configuration information for SAI module.
01451   * @param  pData Pointer to data buffer
01452   * @param  Size Amount of data to be received
01453   * @retval HAL status
01454   */
01455 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
01456 {
01457   if ((pData == NULL) || (Size == 0))
01458   {
01459     return  HAL_ERROR;
01460   }
01461 
01462   if (hsai->State == HAL_SAI_STATE_READY)
01463   {
01464     /* Process Locked */
01465     __HAL_LOCK(hsai);
01466 
01467     hsai->pBuffPtr = pData;
01468     hsai->XferSize = Size;
01469     hsai->XferCount = Size;
01470     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
01471     hsai->State = HAL_SAI_STATE_BUSY_RX;
01472 
01473     /* Set the SAI Rx DMA Half transfer complete callback */
01474     hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
01475 
01476     /* Set the SAI Rx DMA transfer complete callback */
01477     hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
01478 
01479     /* Set the DMA error callback */
01480     hsai->hdmarx->XferErrorCallback = SAI_DMAError;
01481 
01482     /* Set the DMA Rx abort callback */
01483     hsai->hdmarx->XferAbortCallback = NULL;
01484 
01485     /* Enable the Rx DMA Stream */
01486     if (HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK)
01487     {
01488       __HAL_UNLOCK(hsai);
01489       return  HAL_ERROR;
01490     }
01491 
01492     /* Enable the interrupts for error handling */
01493     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
01494 
01495     /* Enable SAI Rx DMA Request */
01496     hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
01497 
01498     /* Check if the SAI is already enabled */
01499     if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
01500     {
01501       /* Enable SAI peripheral */
01502       __HAL_SAI_ENABLE(hsai);
01503     }
01504 
01505     /* Process Unlocked */
01506     __HAL_UNLOCK(hsai);
01507 
01508     return HAL_OK;
01509   }
01510   else
01511   {
01512     return HAL_BUSY;
01513   }
01514 }
01515 
01516 /**
01517   * @brief  Enable the Tx mute mode.
01518   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01519   *               the configuration information for SAI module.
01520   * @param  val  value sent during the mute @ref SAI_Block_Mute_Value
01521   * @retval HAL status
01522   */
01523 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
01524 {
01525   assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));
01526 
01527   if (hsai->State != HAL_SAI_STATE_RESET)
01528   {
01529     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
01530     SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | val);
01531     return HAL_OK;
01532   }
01533   return HAL_ERROR;
01534 }
01535 
01536 /**
01537   * @brief  Disable the Tx mute mode.
01538   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01539   *               the configuration information for SAI module.
01540   * @retval HAL status
01541   */
01542 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
01543 {
01544   if (hsai->State != HAL_SAI_STATE_RESET)
01545   {
01546     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
01547     return HAL_OK;
01548   }
01549   return HAL_ERROR;
01550 }
01551 
01552 /**
01553   * @brief  Enable the Rx mute detection.
01554   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01555   *               the configuration information for SAI module.
01556   * @param  callback function called when the mute is detected.
01557   * @param  counter number a data before mute detection max 63.
01558   * @retval HAL status
01559   */
01560 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
01561 {
01562   assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));
01563 
01564   if (hsai->State != HAL_SAI_STATE_RESET)
01565   {
01566     /* set the mute counter */
01567     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);
01568     SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos));
01569     hsai->mutecallback = callback;
01570     /* enable the IT interrupt */
01571     __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);
01572     return HAL_OK;
01573   }
01574   return HAL_ERROR;
01575 }
01576 
01577 /**
01578   * @brief  Disable the Rx mute detection.
01579   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01580   *               the configuration information for SAI module.
01581   * @retval HAL status
01582   */
01583 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
01584 {
01585   if (hsai->State != HAL_SAI_STATE_RESET)
01586   {
01587     /* set the mutecallback to NULL */
01588     hsai->mutecallback = (SAIcallback)NULL;
01589     /* enable the IT interrupt */
01590     __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);
01591     return HAL_OK;
01592   }
01593   return HAL_ERROR;
01594 }
01595 
01596 /**
01597   * @brief  Handle SAI interrupt request.
01598   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01599   *               the configuration information for SAI module.
01600   * @retval None
01601   */
01602 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
01603 {
01604   if (hsai->State != HAL_SAI_STATE_RESET)
01605   {
01606     uint32_t itflags = hsai->Instance->SR;
01607     uint32_t itsources = hsai->Instance->IMR;
01608     uint32_t cr1config = hsai->Instance->CR1;
01609     uint32_t tmperror;
01610 
01611     /* SAI Fifo request interrupt occurred ------------------------------------*/
01612     if (((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ))
01613     {
01614       hsai->InterruptServiceRoutine(hsai);
01615     }
01616     /* SAI Overrun error interrupt occurred ----------------------------------*/
01617     else if (((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))
01618     {
01619       /* Clear the SAI Overrun flag */
01620       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
01621 
01622       /* Get the SAI error code */
01623       tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);
01624 
01625       /* Change the SAI error code */
01626       hsai->ErrorCode |= tmperror;
01627 
01628       /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
01629 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
01630       hsai->ErrorCallback(hsai);
01631 #else
01632       HAL_SAI_ErrorCallback(hsai);
01633 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
01634     }
01635     /* SAI mutedet interrupt occurred ----------------------------------*/
01636     else if (((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))
01637     {
01638       /* Clear the SAI mutedet flag */
01639       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);
01640 
01641       /* call the call back function */
01642       if (hsai->mutecallback != (SAIcallback)NULL)
01643       {
01644         /* inform the user that an RX mute event has been detected */
01645         hsai->mutecallback();
01646       }
01647     }
01648     /* SAI AFSDET interrupt occurred ----------------------------------*/
01649     else if (((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET))
01650     {
01651       /* Clear the SAI AFSDET flag */
01652       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_AFSDET);
01653 
01654       /* Change the SAI error code */
01655       hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET;
01656 
01657       /* Check SAI DMA is enabled or not */
01658       if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
01659       {
01660         /* Abort the SAI DMA Streams */
01661         if (hsai->hdmatx != NULL)
01662         {
01663           /* Set the DMA Tx abort callback */
01664           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
01665 
01666           /* Abort DMA in IT mode */
01667           HAL_DMA_Abort_IT(hsai->hdmatx);
01668         }
01669         else if (hsai->hdmarx != NULL)
01670         {
01671           /* Set the DMA Rx abort callback */
01672           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
01673 
01674           /* Abort DMA in IT mode */
01675           HAL_DMA_Abort_IT(hsai->hdmarx);
01676         }
01677       }
01678       else
01679       {
01680         /* Abort SAI */
01681         HAL_SAI_Abort(hsai);
01682 
01683         /* Set error callback */
01684 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
01685         hsai->ErrorCallback(hsai);
01686 #else
01687         HAL_SAI_ErrorCallback(hsai);
01688 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
01689       }
01690     }
01691     /* SAI LFSDET interrupt occurred ----------------------------------*/
01692     else if (((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET))
01693     {
01694       /* Clear the SAI LFSDET flag */
01695       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_LFSDET);
01696 
01697       /* Change the SAI error code */
01698       hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET;
01699 
01700       /* Check SAI DMA is enabled or not */
01701       if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
01702       {
01703         /* Abort the SAI DMA Streams */
01704         if (hsai->hdmatx != NULL)
01705         {
01706           /* Set the DMA Tx abort callback */
01707           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
01708 
01709           /* Abort DMA in IT mode */
01710           HAL_DMA_Abort_IT(hsai->hdmatx);
01711         }
01712         else if (hsai->hdmarx != NULL)
01713         {
01714           /* Set the DMA Rx abort callback */
01715           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
01716 
01717           /* Abort DMA in IT mode */
01718           HAL_DMA_Abort_IT(hsai->hdmarx);
01719         }
01720       }
01721       else
01722       {
01723         /* Abort SAI */
01724         HAL_SAI_Abort(hsai);
01725 
01726         /* Set error callback */
01727 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
01728         hsai->ErrorCallback(hsai);
01729 #else
01730         HAL_SAI_ErrorCallback(hsai);
01731 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
01732       }
01733     }
01734     /* SAI WCKCFG interrupt occurred ----------------------------------*/
01735     else if (((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
01736     {
01737       /* Clear the SAI WCKCFG flag */
01738       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_WCKCFG);
01739 
01740       /* Change the SAI error code */
01741       hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG;
01742 
01743       /* Check SAI DMA is enabled or not */
01744       if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
01745       {
01746         /* Abort the SAI DMA Streams */
01747         if (hsai->hdmatx != NULL)
01748         {
01749           /* Set the DMA Tx abort callback */
01750           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
01751 
01752           /* Abort DMA in IT mode */
01753           HAL_DMA_Abort_IT(hsai->hdmatx);
01754         }
01755         else if (hsai->hdmarx != NULL)
01756         {
01757           /* Set the DMA Rx abort callback */
01758           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
01759 
01760           /* Abort DMA in IT mode */
01761           HAL_DMA_Abort_IT(hsai->hdmarx);
01762         }
01763       }
01764       else
01765       {
01766         /* If WCKCFG occurs, SAI audio block is automatically disabled */
01767         /* Disable all interrupts and clear all flags */
01768         hsai->Instance->IMR = 0U;
01769         hsai->Instance->CLRFR = 0xFFFFFFFFU;
01770 
01771         /* Set the SAI state to ready to be able to start again the process */
01772         hsai->State = HAL_SAI_STATE_READY;
01773 
01774         /* Initialize XferCount */
01775         hsai->XferCount = 0U;
01776 
01777         /* SAI error Callback */
01778 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
01779         hsai->ErrorCallback(hsai);
01780 #else
01781         HAL_SAI_ErrorCallback(hsai);
01782 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
01783       }
01784     }
01785     /* SAI CNRDY interrupt occurred ----------------------------------*/
01786     else if (((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY))
01787     {
01788       /* Clear the SAI CNRDY flag */
01789       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY);
01790 
01791       /* Change the SAI error code */
01792       hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY;
01793 
01794       /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
01795 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
01796       hsai->ErrorCallback(hsai);
01797 #else
01798       HAL_SAI_ErrorCallback(hsai);
01799 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
01800     }
01801     else
01802     {
01803       /* Nothing to do */
01804     }
01805   }
01806 }
01807 
01808 /**
01809   * @brief Tx Transfer completed callback.
01810   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01811   *                the configuration information for SAI module.
01812   * @retval None
01813   */
01814 __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
01815 {
01816   /* Prevent unused argument(s) compilation warning */
01817   UNUSED(hsai);
01818 
01819   /* NOTE : This function should not be modified, when the callback is needed,
01820             the HAL_SAI_TxCpltCallback could be implemented in the user file
01821    */
01822 }
01823 
01824 /**
01825   * @brief Tx Transfer Half completed callback.
01826   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01827   *               the configuration information for SAI module.
01828   * @retval None
01829   */
01830 __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
01831 {
01832   /* Prevent unused argument(s) compilation warning */
01833   UNUSED(hsai);
01834 
01835   /* NOTE : This function should not be modified, when the callback is needed,
01836             the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
01837    */
01838 }
01839 
01840 /**
01841   * @brief Rx Transfer completed callback.
01842   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01843   *               the configuration information for SAI module.
01844   * @retval None
01845   */
01846 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
01847 {
01848   /* Prevent unused argument(s) compilation warning */
01849   UNUSED(hsai);
01850 
01851   /* NOTE : This function should not be modified, when the callback is needed,
01852             the HAL_SAI_RxCpltCallback could be implemented in the user file
01853    */
01854 }
01855 
01856 /**
01857   * @brief Rx Transfer half completed callback.
01858   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01859   *               the configuration information for SAI module.
01860   * @retval None
01861   */
01862 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
01863 {
01864   /* Prevent unused argument(s) compilation warning */
01865   UNUSED(hsai);
01866 
01867   /* NOTE : This function should not be modified, when the callback is needed,
01868             the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
01869    */
01870 }
01871 
01872 /**
01873   * @brief SAI error callback.
01874   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01875   *               the configuration information for SAI module.
01876   * @retval None
01877   */
01878 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
01879 {
01880   /* Prevent unused argument(s) compilation warning */
01881   UNUSED(hsai);
01882 
01883   /* NOTE : This function should not be modified, when the callback is needed,
01884             the HAL_SAI_ErrorCallback could be implemented in the user file
01885    */
01886 }
01887 
01888 /**
01889   * @}
01890   */
01891 
01892 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions
01893   * @brief    Peripheral State functions
01894   *
01895 @verbatim
01896  ===============================================================================
01897                 ##### Peripheral State and Errors functions #####
01898  ===============================================================================
01899   [..]
01900     This subsection permits to get in run-time the status of the peripheral
01901     and the data flow.
01902 
01903 @endverbatim
01904   * @{
01905   */
01906 
01907 /**
01908   * @brief  Return the SAI handle state.
01909   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01910   *               the configuration information for SAI module.
01911   * @retval HAL state
01912   */
01913 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai)
01914 {
01915   return hsai->State;
01916 }
01917 
01918 /**
01919   * @brief  Return the SAI error code.
01920   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01921   *              the configuration information for the specified SAI Block.
01922   * @retval SAI Error Code
01923   */
01924 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai)
01925 {
01926   return hsai->ErrorCode;
01927 }
01928 /**
01929   * @}
01930   */
01931 
01932 /**
01933   * @}
01934   */
01935 
01936 /** @addtogroup SAI_Private_Functions
01937   * @brief      Private functions
01938   * @{
01939   */
01940 
01941 /**
01942   * @brief  Initialize the SAI I2S protocol according to the specified parameters
01943   *         in the SAI_InitTypeDef and create the associated handle.
01944   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01945   *               the configuration information for SAI module.
01946   * @param  protocol one of the supported protocol.
01947   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize
01948   *                the configuration information for SAI module.
01949   * @param  nbslot number of slot minimum value is 2 and max is 16.
01950   *                    the value must be a multiple of 2.
01951   * @retval HAL status
01952   */
01953 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
01954 {
01955   hsai->Init.Protocol            = SAI_FREE_PROTOCOL;
01956   hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;
01957   /* Compute ClockStrobing according AudioMode */
01958   if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
01959   {
01960     /* Transmit */
01961     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_FALLINGEDGE;
01962   }
01963   else
01964   {
01965     /* Receive */
01966     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_RISINGEDGE;
01967   }
01968   hsai->FrameInit.FSDefinition   = SAI_FS_CHANNEL_IDENTIFICATION;
01969   hsai->SlotInit.SlotActive      = SAI_SLOTACTIVE_ALL;
01970   hsai->SlotInit.FirstBitOffset  = 0U;
01971   hsai->SlotInit.SlotNumber      = nbslot;
01972 
01973   /* in IS2 the number of slot must be even */
01974   if ((nbslot & 0x1U) != 0U)
01975   {
01976     return HAL_ERROR;
01977   }
01978 
01979   if (protocol == SAI_I2S_STANDARD)
01980   {
01981     hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
01982     hsai->FrameInit.FSOffset   = SAI_FS_BEFOREFIRSTBIT;
01983   }
01984   else
01985   {
01986     /* SAI_I2S_MSBJUSTIFIED or SAI_I2S_LSBJUSTIFIED */
01987     hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
01988     hsai->FrameInit.FSOffset   = SAI_FS_FIRSTBIT;
01989   }
01990 
01991   /* Frame definition */
01992   switch (datasize)
01993   {
01994     case SAI_PROTOCOL_DATASIZE_16BIT:
01995       hsai->Init.DataSize = SAI_DATASIZE_16;
01996       hsai->FrameInit.FrameLength = 32U * (nbslot / 2U);
01997       hsai->FrameInit.ActiveFrameLength = 16U * (nbslot / 2U);
01998       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
01999       break;
02000     case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
02001       hsai->Init.DataSize = SAI_DATASIZE_16;
02002       hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
02003       hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
02004       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
02005       break;
02006     case SAI_PROTOCOL_DATASIZE_24BIT:
02007       hsai->Init.DataSize = SAI_DATASIZE_24;
02008       hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
02009       hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
02010       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
02011       break;
02012     case SAI_PROTOCOL_DATASIZE_32BIT:
02013       hsai->Init.DataSize = SAI_DATASIZE_32;
02014       hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
02015       hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
02016       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
02017       break;
02018     default :
02019       return HAL_ERROR;
02020   }
02021   if (protocol == SAI_I2S_LSBJUSTIFIED)
02022   {
02023     if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
02024     {
02025       hsai->SlotInit.FirstBitOffset = 16U;
02026     }
02027     if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
02028     {
02029       hsai->SlotInit.FirstBitOffset = 8U;
02030     }
02031   }
02032   return HAL_OK;
02033 }
02034 
02035 /**
02036   * @brief  Initialize the SAI PCM protocol according to the specified parameters
02037   *         in the SAI_InitTypeDef and create the associated handle.
02038   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02039   *               the configuration information for SAI module.
02040   * @param  protocol one of the supported protocol
02041   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize
02042   * @param  nbslot number of slot minimum value is 1 and the max is 16.
02043   * @retval HAL status
02044   */
02045 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
02046 {
02047   hsai->Init.Protocol            = SAI_FREE_PROTOCOL;
02048   hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;
02049   /* Compute ClockStrobing according AudioMode */
02050   if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
02051   {
02052     /* Transmit */
02053     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_RISINGEDGE;
02054   }
02055   else
02056   {
02057     /* Receive */
02058     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_FALLINGEDGE;
02059   }
02060   hsai->FrameInit.FSDefinition   = SAI_FS_STARTFRAME;
02061   hsai->FrameInit.FSPolarity     = SAI_FS_ACTIVE_HIGH;
02062   hsai->FrameInit.FSOffset       = SAI_FS_BEFOREFIRSTBIT;
02063   hsai->SlotInit.FirstBitOffset  = 0U;
02064   hsai->SlotInit.SlotNumber      = nbslot;
02065   hsai->SlotInit.SlotActive      = SAI_SLOTACTIVE_ALL;
02066 
02067   if (protocol == SAI_PCM_SHORT)
02068   {
02069     hsai->FrameInit.ActiveFrameLength = 1;
02070   }
02071   else
02072   {
02073     /* SAI_PCM_LONG */
02074     hsai->FrameInit.ActiveFrameLength = 13;
02075   }
02076 
02077   switch (datasize)
02078   {
02079     case SAI_PROTOCOL_DATASIZE_16BIT:
02080       hsai->Init.DataSize = SAI_DATASIZE_16;
02081       hsai->FrameInit.FrameLength = 16U * nbslot;
02082       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
02083       break;
02084     case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
02085       hsai->Init.DataSize = SAI_DATASIZE_16;
02086       hsai->FrameInit.FrameLength = 32U * nbslot;
02087       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
02088       break;
02089     case SAI_PROTOCOL_DATASIZE_24BIT :
02090       hsai->Init.DataSize = SAI_DATASIZE_24;
02091       hsai->FrameInit.FrameLength = 32U * nbslot;
02092       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
02093       break;
02094     case SAI_PROTOCOL_DATASIZE_32BIT:
02095       hsai->Init.DataSize = SAI_DATASIZE_32;
02096       hsai->FrameInit.FrameLength = 32U * nbslot;
02097       hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
02098       break;
02099     default :
02100       return HAL_ERROR;
02101   }
02102 
02103   return HAL_OK;
02104 }
02105 
02106 /**
02107   * @brief  Fill the fifo.
02108   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02109   *               the configuration information for SAI module.
02110   * @retval None
02111   */
02112 static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
02113 {
02114   /* fill the fifo with data before to enabled the SAI */
02115   while (((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U))
02116   {
02117     if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
02118     {
02119       hsai->Instance->DR = (*hsai->pBuffPtr++);
02120     }
02121     else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
02122     {
02123       hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
02124       hsai->pBuffPtr += 2U;
02125     }
02126     else
02127     {
02128       hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
02129       hsai->pBuffPtr += 4U;
02130     }
02131     hsai->XferCount--;
02132   }
02133 }
02134 
02135 /**
02136   * @brief  Return the interrupt flag to set according the SAI setup.
02137   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02138   *               the configuration information for SAI module.
02139   * @param  mode SAI_MODE_DMA or SAI_MODE_IT
02140   * @retval the list of the IT flag to enable
02141  */
02142 static uint32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode)
02143 {
02144   uint32_t tmpIT = SAI_IT_OVRUDR;
02145 
02146   if (mode == SAI_MODE_IT)
02147   {
02148     tmpIT |= SAI_IT_FREQ;
02149   }
02150 
02151   if ((hsai->Init.Protocol == SAI_AC97_PROTOCOL) &&
02152       ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX)))
02153   {
02154     tmpIT |= SAI_IT_CNRDY;
02155   }
02156 
02157   if ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
02158   {
02159     tmpIT |= SAI_IT_AFSDET | SAI_IT_LFSDET;
02160   }
02161   else
02162   {
02163     /* hsai has been configured in master mode */
02164     tmpIT |= SAI_IT_WCKCFG;
02165   }
02166   return tmpIT;
02167 }
02168 
02169 /**
02170   * @brief  Disable the SAI and wait for the disabling.
02171   * @param  hsai  pointer to a SAI_HandleTypeDef structure that contains
02172   *               the configuration information for SAI module.
02173   * @retval None
02174   */
02175 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
02176 {
02177   uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock / 7U / 1000U);
02178   HAL_StatusTypeDef status = HAL_OK;
02179 
02180   /* Disable the SAI instance */
02181   __HAL_SAI_DISABLE(hsai);
02182 
02183   do
02184   {
02185     /* Check for the Timeout */
02186     if (count-- == 0U)
02187     {
02188       /* Update error code */
02189       hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
02190       status = HAL_TIMEOUT;
02191       break;
02192     }
02193   }
02194   while ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != RESET);
02195 
02196   return status;
02197 }
02198 
02199 /**
02200   * @brief  Tx Handler for Transmit in Interrupt mode 8-Bit transfer.
02201   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02202   *               the configuration information for SAI module.
02203   * @retval None
02204   */
02205 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
02206 {
02207   if (hsai->XferCount == 0U)
02208   {
02209     /* Handle the end of the transmission */
02210     /* Disable FREQ and OVRUDR interrupts */
02211     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
02212     hsai->State = HAL_SAI_STATE_READY;
02213 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02214     hsai->TxCpltCallback(hsai);
02215 #else
02216     HAL_SAI_TxCpltCallback(hsai);
02217 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
02218   }
02219   else
02220   {
02221     /* Write data on DR register */
02222     hsai->Instance->DR = (*hsai->pBuffPtr++);
02223     hsai->XferCount--;
02224   }
02225 }
02226 
02227 /**
02228   * @brief  Tx Handler for Transmit in Interrupt mode for 16-Bit transfer.
02229   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02230   *               the configuration information for SAI module.
02231   * @retval None
02232   */
02233 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
02234 {
02235   if (hsai->XferCount == 0U)
02236   {
02237     /* Handle the end of the transmission */
02238     /* Disable FREQ and OVRUDR interrupts */
02239     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
02240     hsai->State = HAL_SAI_STATE_READY;
02241 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02242     hsai->TxCpltCallback(hsai);
02243 #else
02244     HAL_SAI_TxCpltCallback(hsai);
02245 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
02246   }
02247   else
02248   {
02249     /* Write data on DR register */
02250     hsai->Instance->DR = *(uint16_t *)hsai->pBuffPtr;
02251     hsai->pBuffPtr += 2U;
02252     hsai->XferCount--;
02253   }
02254 }
02255 
02256 /**
02257   * @brief  Tx Handler for Transmit in Interrupt mode for 32-Bit transfer.
02258   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02259   *               the configuration information for SAI module.
02260   * @retval None
02261   */
02262 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
02263 {
02264   if (hsai->XferCount == 0U)
02265   {
02266     /* Handle the end of the transmission */
02267     /* Disable FREQ and OVRUDR interrupts */
02268     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
02269     hsai->State = HAL_SAI_STATE_READY;
02270 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02271     hsai->TxCpltCallback(hsai);
02272 #else
02273     HAL_SAI_TxCpltCallback(hsai);
02274 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
02275   }
02276   else
02277   {
02278     /* Write data on DR register */
02279     hsai->Instance->DR = *(uint32_t *)hsai->pBuffPtr;
02280     hsai->pBuffPtr += 4U;
02281     hsai->XferCount--;
02282   }
02283 }
02284 
02285 /**
02286   * @brief  Rx Handler for Receive in Interrupt mode 8-Bit transfer.
02287   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02288   *               the configuration information for SAI module.
02289   * @retval None
02290   */
02291 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
02292 {
02293   /* Receive data */
02294   (*hsai->pBuffPtr++) = hsai->Instance->DR;
02295   hsai->XferCount--;
02296 
02297   /* Check end of the transfer */
02298   if (hsai->XferCount == 0U)
02299   {
02300     /* Disable TXE and OVRUDR interrupts */
02301     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
02302 
02303     /* Clear the SAI Overrun flag */
02304     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
02305 
02306     hsai->State = HAL_SAI_STATE_READY;
02307 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02308     hsai->RxCpltCallback(hsai);
02309 #else
02310     HAL_SAI_RxCpltCallback(hsai);
02311 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
02312   }
02313 }
02314 
02315 /**
02316   * @brief  Rx Handler for Receive in Interrupt mode for 16-Bit transfer.
02317   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02318   *               the configuration information for SAI module.
02319   * @retval None
02320   */
02321 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
02322 {
02323   /* Receive data */
02324   *(uint16_t *)hsai->pBuffPtr = hsai->Instance->DR;
02325   hsai->pBuffPtr += 2U;
02326   hsai->XferCount--;
02327 
02328   /* Check end of the transfer */
02329   if (hsai->XferCount == 0U)
02330   {
02331     /* Disable TXE and OVRUDR interrupts */
02332     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
02333 
02334     /* Clear the SAI Overrun flag */
02335     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
02336 
02337     hsai->State = HAL_SAI_STATE_READY;
02338 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02339     hsai->RxCpltCallback(hsai);
02340 #else
02341     HAL_SAI_RxCpltCallback(hsai);
02342 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
02343   }
02344 }
02345 
02346 /**
02347   * @brief  Rx Handler for Receive in Interrupt mode for 32-Bit transfer.
02348   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02349   *               the configuration information for SAI module.
02350   * @retval None
02351   */
02352 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
02353 {
02354   /* Receive data */
02355   *(uint32_t *)hsai->pBuffPtr = hsai->Instance->DR;
02356   hsai->pBuffPtr += 4U;
02357   hsai->XferCount--;
02358 
02359   /* Check end of the transfer */
02360   if (hsai->XferCount == 0U)
02361   {
02362     /* Disable TXE and OVRUDR interrupts */
02363     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
02364 
02365     /* Clear the SAI Overrun flag */
02366     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
02367 
02368     hsai->State = HAL_SAI_STATE_READY;
02369 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02370     hsai->RxCpltCallback(hsai);
02371 #else
02372     HAL_SAI_RxCpltCallback(hsai);
02373 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
02374   }
02375 }
02376 
02377 /**
02378   * @brief DMA SAI transmit process complete callback.
02379   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02380   *               the configuration information for the specified DMA module.
02381   * @retval None
02382   */
02383 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
02384 {
02385   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
02386 
02387   if (hdma->Init.Mode != DMA_CIRCULAR)
02388   {
02389     hsai->XferCount = 0U;
02390 
02391     /* Disable SAI Tx DMA Request */
02392     hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
02393 
02394     /* Stop the interrupts error handling */
02395     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
02396 
02397     hsai->State = HAL_SAI_STATE_READY;
02398   }
02399 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02400   hsai->TxCpltCallback(hsai);
02401 #else
02402   HAL_SAI_TxCpltCallback(hsai);
02403 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
02404 }
02405 
02406 /**
02407   * @brief DMA SAI transmit process half complete callback.
02408   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02409   *               the configuration information for the specified DMA module.
02410   * @retval None
02411   */
02412 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
02413 {
02414   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
02415 
02416 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02417   hsai->TxHalfCpltCallback(hsai);
02418 #else
02419   HAL_SAI_TxHalfCpltCallback(hsai);
02420 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
02421 }
02422 
02423 /**
02424   * @brief DMA SAI receive process complete callback.
02425   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02426   *               the configuration information for the specified DMA module.
02427   * @retval None
02428   */
02429 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
02430 {
02431   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
02432 
02433   if (hdma->Init.Mode != DMA_CIRCULAR)
02434   {
02435     /* Disable Rx DMA Request */
02436     hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
02437     hsai->XferCount = 0U;
02438 
02439     /* Stop the interrupts error handling */
02440     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
02441 
02442     hsai->State = HAL_SAI_STATE_READY;
02443   }
02444 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02445   hsai->RxCpltCallback(hsai);
02446 #else
02447   HAL_SAI_RxCpltCallback(hsai);
02448 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
02449 }
02450 
02451 /**
02452   * @brief DMA SAI receive process half complete callback
02453   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02454   *               the configuration information for the specified DMA module.
02455   * @retval None
02456   */
02457 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
02458 {
02459   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
02460 
02461 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02462   hsai->RxHalfCpltCallback(hsai);
02463 #else
02464   HAL_SAI_RxHalfCpltCallback(hsai);
02465 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
02466 }
02467 
02468 /**
02469   * @brief DMA SAI communication error callback.
02470   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02471   *               the configuration information for the specified DMA module.
02472   * @retval None
02473   */
02474 static void SAI_DMAError(DMA_HandleTypeDef *hdma)
02475 {
02476   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
02477 
02478   /* Set SAI error code */
02479   hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
02480 
02481   if ((hsai->hdmatx->ErrorCode == HAL_DMA_ERROR_TE) || (hsai->hdmarx->ErrorCode == HAL_DMA_ERROR_TE))
02482   {
02483     /* Disable the SAI DMA request */
02484     hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
02485 
02486     /* Disable SAI peripheral */
02487     SAI_Disable(hsai);
02488 
02489     /* Set the SAI state ready to be able to start again the process */
02490     hsai->State = HAL_SAI_STATE_READY;
02491 
02492     /* Initialize XferCount */
02493     hsai->XferCount = 0U;
02494   }
02495   /* SAI error Callback */
02496 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02497   hsai->ErrorCallback(hsai);
02498 #else
02499   HAL_SAI_ErrorCallback(hsai);
02500 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
02501 }
02502 
02503 /**
02504   * @brief  DMA SAI Abort callback.
02505   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02506   *               the configuration information for the specified DMA module.
02507   * @retval None
02508   */
02509 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma)
02510 {
02511   SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
02512 
02513   /* Disable DMA request */
02514   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
02515 
02516   /* Disable all interrupts and clear all flags */
02517   hsai->Instance->IMR = 0U;
02518   hsai->Instance->CLRFR = 0xFFFFFFFFU;
02519 
02520   if (hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG)
02521   {
02522     /* Disable SAI peripheral */
02523     SAI_Disable(hsai);
02524 
02525     /* Flush the fifo */
02526     SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
02527   }
02528   /* Set the SAI state to ready to be able to start again the process */
02529   hsai->State = HAL_SAI_STATE_READY;
02530 
02531   /* Initialize XferCount */
02532   hsai->XferCount = 0U;
02533 
02534   /* SAI error Callback */
02535 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
02536   hsai->ErrorCallback(hsai);
02537 #else
02538   HAL_SAI_ErrorCallback(hsai);
02539 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
02540 }
02541 
02542 /**
02543   * @}
02544   */
02545 
02546 #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */
02547 #endif /* HAL_SAI_MODULE_ENABLED */
02548 /**
02549   * @}
02550   */
02551 
02552 /**
02553   * @}
02554   */
02555 
02556 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/