STM32F439xx 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   @endverbatim
00143   ******************************************************************************
00144   * @attention
00145   *
00146   * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
00147   *
00148   * Redistribution and use in source and binary forms, with or without modification,
00149   * are permitted provided that the following conditions are met:
00150   *   1. Redistributions of source code must retain the above copyright notice,
00151   *      this list of conditions and the following disclaimer.
00152   *   2. Redistributions in binary form must reproduce the above copyright notice,
00153   *      this list of conditions and the following disclaimer in the documentation
00154   *      and/or other materials provided with the distribution.
00155   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00156   *      may be used to endorse or promote products derived from this software
00157   *      without specific prior written permission.
00158   *
00159   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00160   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00161   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00162   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00163   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00164   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00165   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00166   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00167   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00168   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00169   *
00170   ******************************************************************************
00171   */
00172 
00173 /* Includes ------------------------------------------------------------------*/
00174 #include "stm32f4xx_hal.h"
00175 
00176 /** @addtogroup STM32F4xx_HAL_Driver
00177   * @{
00178   */
00179 
00180 /** @defgroup SAI SAI
00181   * @brief SAI HAL module driver
00182   * @{
00183   */
00184 
00185 #ifdef HAL_SAI_MODULE_ENABLED
00186 
00187 #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\
00188     defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) ||\
00189     defined(STM32F423xx)
00190 
00191 /** @defgroup SAI_Private_Typedefs  SAI Private Typedefs
00192   * @{
00193   */
00194 typedef enum {
00195   SAI_MODE_DMA,
00196   SAI_MODE_IT
00197 }SAI_ModeTypedef;
00198 /**
00199   * @}
00200   */
00201 
00202 /* Private define ------------------------------------------------------------*/
00203 
00204 /** @defgroup SAI_Private_Constants  SAI Private Constants
00205   * @{
00206   */
00207 #define SAI_FIFO_SIZE         8U
00208 #define SAI_DEFAULT_TIMEOUT   4U /* 4ms */
00209 /**
00210   * @}
00211   */
00212 
00213 /* Private macro -------------------------------------------------------------*/
00214 /* Private variables ---------------------------------------------------------*/
00215 /* Private function prototypes -----------------------------------------------*/
00216 
00217 /** @defgroup SAI_Private_Functions  SAI Private Functions
00218   * @{
00219   */
00220 static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
00221 static uint32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode);
00222 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
00223 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
00224 
00225 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
00226 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
00227 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
00228 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
00229 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
00230 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
00231 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
00232 
00233 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
00234 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
00235 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
00236 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
00237 static void SAI_DMAError(DMA_HandleTypeDef *hdma);
00238 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma);
00239 /**
00240   * @}
00241   */
00242 
00243 /* Exported functions ---------------------------------------------------------*/
00244 
00245 /** @defgroup SAI_Exported_Functions SAI Exported Functions
00246   * @{
00247   */
00248 
00249 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions
00250  *  @brief    Initialization and Configuration functions
00251  *
00252 @verbatim
00253  ===============================================================================
00254             ##### Initialization and de-initialization functions #####
00255  ===============================================================================
00256   [..]  This subsection provides a set of functions allowing to initialize and
00257         de-initialize the SAIx peripheral:
00258 
00259       (+) User must implement HAL_SAI_MspInit() function in which he configures
00260           all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
00261 
00262       (+) Call the function HAL_SAI_Init() to configure the selected device with
00263           the selected configuration:
00264         (++) Mode (Master/slave TX/RX)
00265         (++) Protocol
00266         (++) Data Size
00267         (++) MCLK Output
00268         (++) Audio frequency
00269         (++) FIFO Threshold
00270         (++) Frame Config
00271         (++) Slot Config
00272 
00273       (+) Call the function HAL_SAI_DeInit() to restore the default configuration
00274           of the selected SAI peripheral.
00275 
00276 @endverbatim
00277   * @{
00278   */
00279 
00280 /**
00281   * @brief  Initialize the structure FrameInit, SlotInit and the low part of
00282   *         Init according to the specified parameters and call the function
00283   *         HAL_SAI_Init to initialize the SAI block.
00284   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00285   *               the configuration information for SAI module.
00286   * @param  protocol one of the supported protocol @ref SAI_Protocol
00287   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize
00288   *                   the configuration information for SAI module.
00289   * @param  nbslot Number of slot.
00290   * @retval HAL status
00291   */
00292 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
00293 {
00294   HAL_StatusTypeDef status = HAL_OK;
00295 
00296   /* Check the parameters */
00297   assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));
00298   assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));
00299 
00300   switch(protocol)
00301   {
00302   case SAI_I2S_STANDARD :
00303   case SAI_I2S_MSBJUSTIFIED :
00304   case SAI_I2S_LSBJUSTIFIED :
00305     status = SAI_InitI2S(hsai, protocol, datasize, nbslot);
00306     break;
00307   case SAI_PCM_LONG :
00308   case SAI_PCM_SHORT :
00309     status = SAI_InitPCM(hsai, protocol, datasize, nbslot);
00310     break;
00311   default :
00312     status = HAL_ERROR;
00313     break;
00314   }
00315   
00316   if(status == HAL_OK)
00317   {
00318     status = HAL_SAI_Init(hsai);
00319   }
00320 
00321   return status;
00322 }
00323 
00324 /**
00325   * @brief  Initialize the SAI according to the specified parameters.
00326   *         in the SAI_InitTypeDef structure and initialize the associated handle.
00327   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00328   *               the configuration information for SAI module.
00329   * @retval HAL status
00330   */
00331 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
00332 { 
00333   uint32_t tmpregisterGCR = 0U;
00334 
00335   /* This variable used to store the SAI_CK_x (value in Hz) */
00336   uint32_t freq = 0U;
00337 
00338   /* This variable is used to compute CKSTR bits of SAI CR1 according to
00339      ClockStrobing and AudioMode fields */
00340   uint32_t ckstr_bits = 0U;
00341   uint32_t syncen_bits = 0U;
00342 
00343   /* Check the SAI handle allocation */
00344   if(hsai == NULL)
00345   {
00346     return HAL_ERROR;
00347   }
00348 
00349   /* check the instance */
00350   assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance));
00351 
00352   /* Check the SAI Block parameters */
00353   assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
00354   assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
00355   assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
00356   assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));
00357   assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
00358   assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
00359   assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
00360   assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
00361   assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
00362   assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
00363   assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
00364   assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode));
00365   assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));
00366   assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));
00367 
00368   /* Check the SAI Block Frame parameters */
00369   assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
00370   assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
00371   assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
00372   assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
00373   assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
00374 
00375   /* Check the SAI Block Slot parameters */
00376   assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
00377   assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
00378   assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
00379   assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
00380 
00381   if(hsai->State == HAL_SAI_STATE_RESET)
00382   {
00383     /* Allocate lock resource and initialize it */
00384     hsai->Lock = HAL_UNLOCKED;
00385 
00386     /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
00387     HAL_SAI_MspInit(hsai);
00388   }
00389 
00390   hsai->State = HAL_SAI_STATE_BUSY;
00391 
00392   /* Disable the selected SAI peripheral */
00393   SAI_Disable(hsai);
00394 
00395   /* SAI Block Synchro Configuration -----------------------------------------*/
00396   SAI_BlockSynchroConfig(hsai);
00397 
00398   /* Configure Master Clock using the following formula :
00399      MCLK_x = SAI_CK_x / (MCKDIV[3:0] * 2) with MCLK_x = 256 * FS
00400      FS = SAI_CK_x / (MCKDIV[3:0] * 2) * 256
00401      MCKDIV[3:0] = SAI_CK_x / FS * 512 */
00402   if(hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)
00403   { 
00404     /* Get SAI clock source based on Source clock selection from RCC */
00405     freq = SAI_GetInputClock(hsai);
00406 
00407     /* (saiclocksource x 10) to keep Significant digits */
00408     tmpregisterGCR = (((freq * 10U) / ((hsai->Init.AudioFrequency) * 512U)));
00409 
00410     hsai->Init.Mckdiv = tmpregisterGCR / 10U;
00411 
00412     /* Round result to the nearest integer */
00413     if((tmpregisterGCR % 10U) > 8U) 
00414     {
00415       hsai->Init.Mckdiv+= 1U;
00416     }
00417   }
00418 
00419   /* Compute CKSTR bits of SAI CR1 according to ClockStrobing and AudioMode */
00420   if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
00421   {
00422     ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U: SAI_xCR1_CKSTR;
00423   }
00424   else
00425   {
00426     ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR: 0U;
00427   }
00428 
00429   /* SAI Block Configuration -------------------------------------------------*/
00430   switch(hsai->Init.Synchro)
00431   {
00432   case SAI_ASYNCHRONOUS :
00433     {
00434       syncen_bits = 0U;
00435     }
00436     break;
00437   case SAI_SYNCHRONOUS :
00438     {
00439       syncen_bits = SAI_xCR1_SYNCEN_0;
00440     }
00441     break;
00442   case SAI_SYNCHRONOUS_EXT_SAI1 :
00443   case SAI_SYNCHRONOUS_EXT_SAI2 :
00444     {
00445       syncen_bits = SAI_xCR1_SYNCEN_1;
00446     }
00447     break;
00448   default:
00449     break;
00450   }
00451   /* SAI CR1 Configuration */
00452   hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG |  SAI_xCR1_DS |      \
00453                            SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN |\
00454                            SAI_xCR1_MONO | SAI_xCR1_OUTDRIV  | SAI_xCR1_DMAEN |  \
00455                            SAI_xCR1_NODIV | SAI_xCR1_MCKDIV);
00456 
00457   hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol |           \
00458                           hsai->Init.DataSize | hsai->Init.FirstBit  |           \
00459                           ckstr_bits | syncen_bits |                             \
00460                           hsai->Init.MonoStereoMode | hsai->Init.OutputDrive |   \
00461                           hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20U));
00462 
00463   /* SAI CR2 Configuration */
00464   hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL);
00465   hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);
00466 
00467   /* SAI Frame Configuration -----------------------------------------*/
00468   hsai->Instance->FRCR&=(~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \
00469                            SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF));
00470   hsai->Instance->FRCR|=((hsai->FrameInit.FrameLength - 1U) |
00471                           hsai->FrameInit.FSOffset     |
00472                           hsai->FrameInit.FSDefinition |
00473                           hsai->FrameInit.FSPolarity   |
00474                           ((hsai->FrameInit.ActiveFrameLength - 1U) << 8U));
00475 
00476   /* SAI Block_x SLOT Configuration ------------------------------------------*/
00477   /* This register has no meaning in AC 97 and SPDIF audio protocol */
00478   hsai->Instance->SLOTR &= ~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ | \
00479                              SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN );
00480 
00481   hsai->Instance->SLOTR |=  hsai->SlotInit.FirstBitOffset |  hsai->SlotInit.SlotSize  | \
00482                             (hsai->SlotInit.SlotActive << 16U) | ((hsai->SlotInit.SlotNumber - 1U) <<  8U);
00483 
00484   /* Initialize the error code */
00485   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00486 
00487   /* Initialize the SAI state */
00488   hsai->State= HAL_SAI_STATE_READY;
00489 
00490   /* Release Lock */
00491   __HAL_UNLOCK(hsai);
00492 
00493   return HAL_OK;
00494 }
00495 
00496 /**
00497   * @brief  DeInitialize the SAI peripheral.
00498   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00499   *               the configuration information for SAI module.
00500   * @retval HAL status
00501   */
00502 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
00503 {
00504   /* Check the SAI handle allocation */
00505   if(hsai == NULL)
00506   {
00507     return HAL_ERROR;
00508   }
00509 
00510   hsai->State = HAL_SAI_STATE_BUSY;
00511 
00512   /* Disabled All interrupt and clear all the flag */
00513   hsai->Instance->IMR = 0U;
00514   hsai->Instance->CLRFR = 0xFFFFFFFFU;
00515 
00516   /* Disable the SAI */
00517   SAI_Disable(hsai);
00518 
00519   /* Flush the fifo */
00520   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
00521 
00522   /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
00523   HAL_SAI_MspDeInit(hsai);
00524 
00525   /* Initialize the error code */
00526   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00527 
00528   /* Initialize the SAI state */
00529   hsai->State = HAL_SAI_STATE_RESET;
00530 
00531   /* Release Lock */
00532   __HAL_UNLOCK(hsai);
00533 
00534   return HAL_OK;
00535 }
00536 
00537 /**
00538   * @brief Initialize the SAI MSP.
00539   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00540   *               the configuration information for SAI module.
00541   * @retval None
00542   */
00543 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
00544 {
00545   /* Prevent unused argument(s) compilation warning */
00546   UNUSED(hsai);
00547 
00548   /* NOTE : This function should not be modified, when the callback is needed,
00549             the HAL_SAI_MspInit could be implemented in the user file
00550    */
00551 }
00552 
00553 /**
00554   * @brief DeInitialize the SAI MSP.
00555   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00556   *               the configuration information for SAI module.
00557   * @retval None
00558   */
00559 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
00560 {
00561   /* Prevent unused argument(s) compilation warning */
00562   UNUSED(hsai);
00563 
00564   /* NOTE : This function should not be modified, when the callback is needed,
00565             the HAL_SAI_MspDeInit could be implemented in the user file
00566    */
00567 }
00568 
00569 /**
00570   * @}
00571   */
00572 
00573 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions
00574  *  @brief    Data transfers functions
00575  *
00576 @verbatim
00577   ==============================================================================
00578                       ##### IO operation functions #####
00579   ==============================================================================
00580   [..]
00581     This subsection provides a set of functions allowing to manage the SAI data
00582     transfers.
00583 
00584     (+) There are two modes of transfer:
00585       (++) Blocking mode : The communication is performed in the polling mode.
00586            The status of all data processing is returned by the same function
00587            after finishing transfer.
00588       (++) No-Blocking mode : The communication is performed using Interrupts
00589            or DMA. These functions return the status of the transfer startup.
00590            The end of the data processing will be indicated through the
00591            dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when
00592            using DMA mode.
00593 
00594     (+) Blocking mode functions are :
00595       (++) HAL_SAI_Transmit()
00596       (++) HAL_SAI_Receive()
00597 
00598     (+) Non Blocking mode functions with Interrupt are :
00599       (++) HAL_SAI_Transmit_IT()
00600       (++) HAL_SAI_Receive_IT()
00601 
00602     (+) Non Blocking mode functions with DMA are :
00603       (++) HAL_SAI_Transmit_DMA()
00604       (++) HAL_SAI_Receive_DMA()
00605 
00606     (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
00607       (++) HAL_SAI_TxCpltCallback()
00608       (++) HAL_SAI_RxCpltCallback()
00609       (++) HAL_SAI_ErrorCallback()
00610 
00611 @endverbatim
00612   * @{
00613   */
00614 
00615 /**
00616   * @brief  Transmit an amount of data in blocking mode.
00617   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00618   *               the configuration information for SAI module.
00619   * @param  pData Pointer to data buffer
00620   * @param  Size Amount of data to be sent
00621   * @param  Timeout Timeout duration
00622   * @retval HAL status
00623   */
00624 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t* pData, uint16_t Size, uint32_t Timeout)
00625 {
00626   uint32_t tickstart = HAL_GetTick();
00627 
00628   if((pData == NULL ) || (Size == 0))
00629   {
00630     return  HAL_ERROR;
00631   }
00632 
00633   if(hsai->State == HAL_SAI_STATE_READY)
00634   {
00635     /* Process Locked */
00636     __HAL_LOCK(hsai);
00637 
00638     hsai->XferSize = Size;
00639     hsai->XferCount = Size;
00640     hsai->pBuffPtr = pData;
00641     hsai->State = HAL_SAI_STATE_BUSY_TX;
00642     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00643 
00644     /* Check if the SAI is already enabled */
00645     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
00646     {
00647       /* fill the fifo with data before to enabled the SAI */
00648       SAI_FillFifo(hsai);
00649       /* Enable SAI peripheral */
00650       __HAL_SAI_ENABLE(hsai);
00651     }
00652 
00653     while(hsai->XferCount > 0U)
00654     {
00655       /* Write data if the FIFO is not full */
00656       if((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
00657       {
00658         if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
00659         {
00660           hsai->Instance->DR = (*hsai->pBuffPtr++);
00661         }
00662         else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
00663         {
00664           hsai->Instance->DR = *((uint16_t *)hsai->pBuffPtr);
00665           hsai->pBuffPtr+= 2U;
00666         }
00667         else
00668         {
00669           hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
00670           hsai->pBuffPtr+= 4U;
00671         }
00672         hsai->XferCount--;
00673       }
00674       else
00675       {
00676         /* Check for the Timeout */
00677         if((Timeout != HAL_MAX_DELAY) && ((Timeout == 0U)||((HAL_GetTick() - tickstart) > Timeout)))
00678         {
00679           /* Update error code */
00680           hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
00681 
00682           /* Clear all the flags */
00683           hsai->Instance->CLRFR = 0xFFFFFFFFU;
00684 
00685           /* Disable SAI peripheral */
00686           SAI_Disable(hsai);
00687 
00688           /* Flush the fifo */
00689           SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
00690 
00691           /* Change the SAI state */
00692           hsai->State = HAL_SAI_STATE_READY;
00693 
00694           /* Process Unlocked */
00695           __HAL_UNLOCK(hsai);
00696 
00697           return HAL_ERROR;
00698         }
00699       }
00700     }
00701 
00702     hsai->State = HAL_SAI_STATE_READY;
00703 
00704     /* Process Unlocked */
00705     __HAL_UNLOCK(hsai);
00706 
00707     return HAL_OK;
00708   }
00709   else
00710   {
00711     return HAL_BUSY;
00712   }
00713 }
00714 
00715 /**
00716   * @brief  Receive an amount of data in blocking mode.
00717   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00718   *               the configuration information for SAI module.
00719   * @param  pData Pointer to data buffer
00720   * @param  Size Amount of data to be received
00721   * @param  Timeout Timeout duration
00722   * @retval HAL status
00723   */
00724 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
00725 {
00726   uint32_t tickstart = HAL_GetTick();
00727 
00728   if((pData == NULL ) || (Size == 0)) 
00729   {
00730     return  HAL_ERROR;
00731   }
00732 
00733   if(hsai->State == HAL_SAI_STATE_READY)
00734   {
00735     /* Process Locked */
00736     __HAL_LOCK(hsai);
00737 
00738     hsai->pBuffPtr = pData;
00739     hsai->XferSize = Size;
00740     hsai->XferCount = Size;
00741     hsai->State = HAL_SAI_STATE_BUSY_RX;
00742     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00743 
00744     /* Check if the SAI is already enabled */
00745     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
00746     {
00747       /* Enable SAI peripheral */
00748       __HAL_SAI_ENABLE(hsai);
00749     }
00750 
00751     /* Receive data */
00752     while(hsai->XferCount > 0U)
00753     {
00754       if((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)
00755       {
00756         if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
00757         {
00758           (*hsai->pBuffPtr++) = hsai->Instance->DR;
00759         }
00760         else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
00761         {
00762           *((uint16_t*)hsai->pBuffPtr) = hsai->Instance->DR;
00763           hsai->pBuffPtr+= 2U;
00764         }
00765         else
00766         {
00767           *((uint32_t*)hsai->pBuffPtr) = hsai->Instance->DR;
00768           hsai->pBuffPtr+= 4U;
00769         }
00770         hsai->XferCount--;
00771       }
00772       else
00773       {
00774         /* Check for the Timeout */
00775         if((Timeout != HAL_MAX_DELAY) && ((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout)))
00776         {
00777           /* Update error code */
00778           hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
00779 
00780           /* Clear all the flags */
00781           hsai->Instance->CLRFR = 0xFFFFFFFFU;
00782 
00783           /* Disable SAI peripheral */
00784           SAI_Disable(hsai);
00785 
00786           /* Flush the fifo */
00787           SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
00788 
00789           /* Change the SAI state */
00790           hsai->State = HAL_SAI_STATE_READY;
00791 
00792           /* Process Unlocked */
00793           __HAL_UNLOCK(hsai);
00794 
00795           return HAL_ERROR;
00796         }
00797       }
00798     }
00799 
00800     hsai->State = HAL_SAI_STATE_READY;
00801 
00802     /* Process Unlocked */
00803     __HAL_UNLOCK(hsai);
00804 
00805     return HAL_OK;
00806   }
00807   else
00808   {
00809     return HAL_BUSY;
00810   }
00811 }
00812 
00813 /**
00814   * @brief  Transmit an amount of data in non-blocking mode with Interrupt.
00815   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00816   *               the configuration information for SAI module.
00817   * @param  pData Pointer to data buffer
00818   * @param  Size Amount of data to be sent
00819   * @retval HAL status
00820   */
00821 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
00822 {
00823   if((pData == NULL) || (Size == 0))
00824   {
00825     return  HAL_ERROR;
00826   }
00827 
00828   if(hsai->State == HAL_SAI_STATE_READY)
00829   {
00830     /* Process Locked */
00831     __HAL_LOCK(hsai);
00832 
00833     hsai->pBuffPtr = pData;
00834     hsai->XferSize = Size;
00835     hsai->XferCount = Size;
00836     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00837     hsai->State = HAL_SAI_STATE_BUSY_TX;
00838 
00839     if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
00840     {
00841       hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;
00842     }
00843     else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
00844     {
00845       hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;
00846     }
00847     else
00848     {
00849       hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;
00850     }
00851 
00852     /* Fill the fifo before starting the communication */
00853     SAI_FillFifo(hsai);
00854 
00855     /* Enable FRQ and OVRUDR interrupts */
00856     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
00857 
00858     /* Check if the SAI is already enabled */
00859     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
00860     {
00861       /* Enable SAI peripheral */
00862       __HAL_SAI_ENABLE(hsai);
00863     }
00864     /* Process Unlocked */
00865     __HAL_UNLOCK(hsai);
00866 
00867     return HAL_OK;
00868   }
00869   else
00870   {
00871     return HAL_BUSY;
00872   }
00873 }
00874 
00875 /**
00876   * @brief  Receive an amount of data in non-blocking mode with Interrupt.
00877   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00878   *               the configuration information for SAI module.
00879   * @param  pData Pointer to data buffer
00880   * @param  Size Amount of data to be received
00881   * @retval HAL status
00882   */
00883 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
00884 {
00885   if((pData == NULL) || (Size == 0))
00886   {
00887     return  HAL_ERROR;
00888   }
00889 
00890   if(hsai->State == HAL_SAI_STATE_READY)
00891   {
00892     /* Process Locked */
00893     __HAL_LOCK(hsai);
00894 
00895     hsai->pBuffPtr = pData;
00896     hsai->XferSize = Size;
00897     hsai->XferCount = Size;
00898     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
00899     hsai->State = HAL_SAI_STATE_BUSY_RX;
00900 
00901     if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
00902     {
00903       hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;
00904     }
00905     else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
00906     {
00907       hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;
00908     }
00909     else
00910     {
00911       hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;
00912     }
00913 
00914     /* Enable TXE and OVRUDR interrupts */
00915     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
00916 
00917     /* Check if the SAI is already enabled */
00918     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
00919     {
00920       /* Enable SAI peripheral */
00921       __HAL_SAI_ENABLE(hsai);
00922     }
00923 
00924     /* Process Unlocked */
00925     __HAL_UNLOCK(hsai);
00926 
00927     return HAL_OK;
00928   }
00929   else
00930   {
00931     return HAL_BUSY;
00932   }
00933 }
00934 
00935 /**
00936   * @brief Pause the audio stream playing from the Media.
00937   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00938   *               the configuration information for SAI module.
00939   * @retval HAL status
00940   */
00941 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
00942 {
00943   /* Process Locked */
00944   __HAL_LOCK(hsai);
00945 
00946   /* Pause the audio file playing by disabling the SAI DMA requests */
00947   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
00948 
00949   /* Process Unlocked */
00950   __HAL_UNLOCK(hsai);
00951 
00952   return HAL_OK;
00953 }
00954 
00955 /**
00956   * @brief Resume the audio stream playing from the Media.
00957   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00958   *               the configuration information for SAI module.
00959   * @retval HAL status
00960   */
00961 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
00962 {
00963   /* Process Locked */
00964   __HAL_LOCK(hsai);
00965 
00966   /* Enable the SAI DMA requests */
00967   hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
00968 
00969   /* If the SAI peripheral is still not enabled, enable it */
00970   if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
00971   {
00972     /* Enable SAI peripheral */
00973     __HAL_SAI_ENABLE(hsai);
00974   }
00975 
00976   /* Process Unlocked */
00977   __HAL_UNLOCK(hsai);
00978 
00979   return HAL_OK;
00980 }
00981 
00982 /**
00983   * @brief Stop the audio stream playing from the Media.
00984   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
00985   *               the configuration information for SAI module.
00986   * @retval HAL status
00987   */
00988 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
00989 {
00990   /* Process Locked */
00991   __HAL_LOCK(hsai);
00992 
00993   /* Disable the SAI DMA request */
00994   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
00995 
00996   /* Abort the SAI DMA Streams */
00997   if(hsai->hdmatx != NULL)
00998   {
00999     if(HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
01000     {
01001       return HAL_ERROR;
01002     }
01003   }
01004 
01005   if(hsai->hdmarx != NULL)
01006   {
01007     if(HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
01008     {
01009       return HAL_ERROR;
01010     }
01011   }
01012 
01013   /* Disable SAI peripheral */
01014   SAI_Disable(hsai);
01015 
01016   /* Flush the fifo */
01017   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
01018 
01019   hsai->State = HAL_SAI_STATE_READY;
01020 
01021   /* Process Unlocked */
01022   __HAL_UNLOCK(hsai);
01023 
01024   return HAL_OK;
01025 }
01026 
01027 /**
01028   * @brief Abort the current transfer and disable the SAI.
01029   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01030   *               the configuration information for SAI module.
01031   * @retval HAL status
01032   */
01033 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
01034 {
01035   /* Process Locked */
01036   __HAL_LOCK(hsai);
01037 
01038   /* Check SAI DMA is enabled or not */
01039   if((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
01040   {
01041     /* Disable the SAI DMA request */
01042     hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
01043     
01044     /* Abort the SAI DMA Streams */
01045     if(hsai->hdmatx != NULL)
01046     {
01047       if(HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
01048       {
01049         return HAL_ERROR;
01050       }
01051     }
01052     
01053     if(hsai->hdmarx != NULL)
01054     {
01055       if(HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
01056       {
01057         return HAL_ERROR;
01058       }
01059     }
01060   }
01061 
01062   /* Disabled All interrupt and clear all the flag */
01063   hsai->Instance->IMR = 0U;
01064   hsai->Instance->CLRFR = 0xFFFFFFFFU;
01065 
01066   /* Disable SAI peripheral */
01067   SAI_Disable(hsai);
01068 
01069   /* Flush the fifo */
01070   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
01071 
01072   hsai->State = HAL_SAI_STATE_READY;
01073 
01074   /* Process Unlocked */
01075   __HAL_UNLOCK(hsai);
01076 
01077   return HAL_OK;
01078 }
01079 
01080 /**
01081   * @brief  Transmit an amount of data in non-blocking mode with DMA.
01082   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01083   *               the configuration information for SAI module.
01084   * @param  pData Pointer to data buffer
01085   * @param  Size Amount of data to be sent
01086   * @retval HAL status
01087   */
01088 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
01089 {
01090   if((pData == NULL) || (Size == 0)) 
01091   {
01092     return  HAL_ERROR;
01093   }
01094 
01095   if(hsai->State == HAL_SAI_STATE_READY)
01096   {
01097     /* Process Locked */
01098     __HAL_LOCK(hsai);
01099 
01100     hsai->pBuffPtr = pData;
01101     hsai->XferSize = Size;
01102     hsai->XferCount = Size;
01103     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
01104     hsai->State = HAL_SAI_STATE_BUSY_TX;
01105 
01106     /* Set the SAI Tx DMA Half transfer complete callback */
01107     hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
01108 
01109     /* Set the SAI TxDMA transfer complete callback */
01110     hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
01111 
01112     /* Set the DMA error callback */
01113     hsai->hdmatx->XferErrorCallback = SAI_DMAError;
01114 
01115     /* Set the DMA Tx abort callback */
01116     hsai->hdmatx->XferAbortCallback = NULL;
01117 
01118     /* Enable the Tx DMA Stream */
01119     if(HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK)
01120     {
01121       __HAL_UNLOCK(hsai);
01122       return  HAL_ERROR;
01123     }
01124 
01125     /* Check if the SAI is already enabled */
01126     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
01127     {
01128       /* Enable SAI peripheral */
01129       __HAL_SAI_ENABLE(hsai);
01130     }
01131 
01132     /* Enable the interrupts for error handling */
01133     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
01134 
01135     /* Enable SAI Tx DMA Request */
01136     hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
01137 
01138     /* Process Unlocked */
01139     __HAL_UNLOCK(hsai);
01140 
01141     return HAL_OK;
01142   }
01143   else
01144   {
01145     return HAL_BUSY;
01146   }
01147 }
01148 
01149 /**
01150   * @brief  Receive an amount of data in non-blocking mode with DMA.
01151   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01152   *               the configuration information for SAI module.
01153   * @param  pData Pointer to data buffer
01154   * @param  Size Amount of data to be received
01155   * @retval HAL status
01156   */
01157 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
01158 {
01159   if((pData == NULL) || (Size == 0))
01160   {
01161     return  HAL_ERROR;
01162   }
01163 
01164   if(hsai->State == HAL_SAI_STATE_READY)
01165   {
01166     /* Process Locked */
01167     __HAL_LOCK(hsai);
01168 
01169     hsai->pBuffPtr = pData;
01170     hsai->XferSize = Size;
01171     hsai->XferCount = Size;
01172     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
01173     hsai->State = HAL_SAI_STATE_BUSY_RX;
01174 
01175     /* Set the SAI Rx DMA Half transfer complete callback */
01176     hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
01177 
01178     /* Set the SAI Rx DMA transfer complete callback */
01179     hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
01180 
01181     /* Set the DMA error callback */
01182     hsai->hdmarx->XferErrorCallback = SAI_DMAError;
01183 
01184     /* Set the DMA Rx abort callback */
01185     hsai->hdmarx->XferAbortCallback = NULL;
01186 
01187     /* Enable the Rx DMA Stream */
01188     if(HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK)
01189     {
01190       __HAL_UNLOCK(hsai);
01191       return  HAL_ERROR;
01192     }
01193 
01194     /* Check if the SAI is already enabled */
01195     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
01196     {
01197       /* Enable SAI peripheral */
01198       __HAL_SAI_ENABLE(hsai);
01199     }
01200 
01201     /* Enable the interrupts for error handling */
01202     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
01203 
01204     /* Enable SAI Rx DMA Request */
01205     hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
01206 
01207     /* Process Unlocked */
01208     __HAL_UNLOCK(hsai);
01209 
01210     return HAL_OK;
01211   }
01212   else
01213   {
01214     return HAL_BUSY;
01215   }
01216 }
01217 
01218 /**
01219   * @brief  Enable the Tx mute mode.
01220   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01221   *               the configuration information for SAI module.
01222   * @param  val  value sent during the mute @ref SAI_Block_Mute_Value
01223   * @retval HAL status
01224   */
01225 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
01226 {
01227   assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));
01228 
01229   if(hsai->State != HAL_SAI_STATE_RESET)
01230   {
01231     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
01232     SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | val);
01233     return HAL_OK;
01234   }
01235   return HAL_ERROR;
01236 }
01237 
01238 /**
01239   * @brief  Disable the Tx mute mode.
01240   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01241   *               the configuration information for SAI module.
01242   * @retval HAL status
01243   */
01244 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
01245 {
01246   if(hsai->State != HAL_SAI_STATE_RESET)
01247   {
01248     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
01249     return HAL_OK;
01250   }
01251   return HAL_ERROR;
01252 }
01253 
01254 /**
01255   * @brief  Enable the Rx mute detection.
01256   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01257   *               the configuration information for SAI module.
01258   * @param  callback function called when the mute is detected.
01259   * @param  counter number a data before mute detection max 63.
01260   * @retval HAL status
01261   */
01262 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
01263 {
01264   assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));
01265 
01266   if(hsai->State != HAL_SAI_STATE_RESET)
01267   {
01268     /* set the mute counter */
01269     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);
01270     SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos));
01271     hsai->mutecallback = callback;
01272     /* enable the IT interrupt */
01273     __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);
01274     return HAL_OK;
01275   }
01276   return HAL_ERROR;
01277 }
01278 
01279 /**
01280   * @brief  Disable the Rx mute detection.
01281   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01282   *               the configuration information for SAI module.
01283   * @retval HAL status
01284   */
01285 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
01286 {
01287   if(hsai->State != HAL_SAI_STATE_RESET)
01288   {
01289     /* set the mutecallback to NULL */
01290     hsai->mutecallback = (SAIcallback)NULL;
01291     /* enable the IT interrupt */
01292     __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);
01293     return HAL_OK;
01294   }
01295   return HAL_ERROR;
01296 }
01297 
01298 /**
01299   * @brief  Handle SAI interrupt request.
01300   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01301   *               the configuration information for SAI module.
01302   * @retval None
01303   */
01304 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
01305 {
01306   if(hsai->State != HAL_SAI_STATE_RESET)
01307   {
01308     uint32_t itflags = hsai->Instance->SR;
01309     uint32_t itsources = hsai->Instance->IMR;
01310     uint32_t cr1config = hsai->Instance->CR1;
01311     uint32_t tmperror;
01312 
01313     /* SAI Fifo request interrupt occured ------------------------------------*/
01314     if(((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ))
01315     {
01316       hsai->InterruptServiceRoutine(hsai);
01317     }
01318     /* SAI Overrun error interrupt occurred ----------------------------------*/
01319     else if(((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))
01320     {
01321       /* Clear the SAI Overrun flag */
01322       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
01323 
01324       /* Get the SAI error code */
01325       tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);
01326 
01327       /* Change the SAI error code */
01328       hsai->ErrorCode |= tmperror;
01329 
01330       /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
01331       HAL_SAI_ErrorCallback(hsai);
01332     }
01333     /* SAI mutedet interrupt occurred ----------------------------------*/
01334     else if(((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))
01335     {
01336       /* Clear the SAI mutedet flag */
01337       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);
01338 
01339       /* call the call back function */
01340       if(hsai->mutecallback != (SAIcallback)NULL)
01341       {
01342         /* inform the user that an RX mute event has been detected */
01343         hsai->mutecallback();
01344       }
01345     }
01346     /* SAI AFSDET interrupt occurred ----------------------------------*/
01347     else if(((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET))
01348     {
01349       /* Change the SAI error code */
01350       hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET;
01351 
01352       /* Check SAI DMA is enabled or not */
01353       if((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
01354       {
01355         /* Abort the SAI DMA Streams */
01356         if(hsai->hdmatx != NULL)
01357         {
01358           /* Set the DMA Tx abort callback */
01359           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
01360 
01361           /* Abort DMA in IT mode */
01362           HAL_DMA_Abort_IT(hsai->hdmatx);
01363         }
01364         else if(hsai->hdmarx != NULL)
01365         {
01366           /* Set the DMA Rx abort callback */
01367           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
01368 
01369           /* Abort DMA in IT mode */
01370           HAL_DMA_Abort_IT(hsai->hdmarx);
01371         }
01372       }
01373       else
01374       {
01375         /* Abort SAI */ 
01376         HAL_SAI_Abort(hsai);
01377 
01378         /* Set error callback */
01379         HAL_SAI_ErrorCallback(hsai);
01380       }
01381     }
01382     /* SAI LFSDET interrupt occurred ----------------------------------*/
01383     else if(((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET))
01384     {
01385       /* Change the SAI error code */
01386       hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET;
01387 
01388       /* Check SAI DMA is enabled or not */
01389       if((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
01390       {
01391         /* Abort the SAI DMA Streams */
01392         if(hsai->hdmatx != NULL)
01393         {
01394           /* Set the DMA Tx abort callback */
01395           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
01396 
01397           /* Abort DMA in IT mode */
01398           HAL_DMA_Abort_IT(hsai->hdmatx);
01399         }
01400         else if(hsai->hdmarx != NULL)
01401         {
01402           /* Set the DMA Rx abort callback */
01403           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
01404 
01405           /* Abort DMA in IT mode */
01406           HAL_DMA_Abort_IT(hsai->hdmarx);
01407         }
01408       }
01409       else
01410       {
01411         /* Abort SAI */
01412         HAL_SAI_Abort(hsai);
01413 
01414         /* Set error callback */
01415         HAL_SAI_ErrorCallback(hsai);
01416       }
01417     }
01418     /* SAI WCKCFG interrupt occurred ----------------------------------*/
01419     else if(((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
01420     {
01421       /* Change the SAI error code */
01422       hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG;
01423 
01424       /* Check SAI DMA is enabled or not */
01425       if((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
01426       {
01427         /* Abort the SAI DMA Streams */
01428         if(hsai->hdmatx != NULL)
01429         {
01430           /* Set the DMA Tx abort callback */
01431           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
01432 
01433           /* Abort DMA in IT mode */
01434           HAL_DMA_Abort_IT(hsai->hdmatx);
01435         }
01436         else if(hsai->hdmarx != NULL)
01437         {
01438           /* Set the DMA Rx abort callback */
01439           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
01440 
01441           /* Abort DMA in IT mode */
01442           HAL_DMA_Abort_IT(hsai->hdmarx);
01443         }
01444       }
01445       else
01446       {
01447         /* If WCKCFG occurs, SAI audio block is automatically disabled */
01448         /* Disable all interrupts and clear all flags */
01449         hsai->Instance->IMR = 0U;
01450         hsai->Instance->CLRFR = 0xFFFFFFFFU;
01451 
01452         /* Set the SAI state to ready to be able to start again the process */
01453         hsai->State = HAL_SAI_STATE_READY;
01454 
01455         /* Initialize XferCount */
01456         hsai->XferCount = 0U;
01457 
01458         /* SAI error Callback */
01459         HAL_SAI_ErrorCallback(hsai);
01460       }
01461     }
01462     /* SAI CNRDY interrupt occurred ----------------------------------*/
01463     else if(((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY))
01464     {
01465       /* Clear the SAI CNRDY flag */
01466       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY);
01467 
01468       /* Change the SAI error code */
01469       hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY;
01470 
01471       /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
01472       HAL_SAI_ErrorCallback(hsai);
01473     }
01474     else
01475     {
01476       /* Nothing to do */
01477     }
01478   }
01479 }
01480 
01481 /**
01482   * @brief Tx Transfer completed callback.
01483   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01484   *                the configuration information for SAI module.
01485   * @retval None
01486   */
01487 __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
01488 {
01489   /* Prevent unused argument(s) compilation warning */
01490   UNUSED(hsai);
01491 
01492   /* NOTE : This function should not be modified, when the callback is needed,
01493             the HAL_SAI_TxCpltCallback could be implemented in the user file
01494    */
01495 }
01496 
01497 /**
01498   * @brief Tx Transfer Half completed callback.
01499   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01500   *               the configuration information for SAI module.
01501   * @retval None
01502   */
01503  __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
01504 {
01505   /* Prevent unused argument(s) compilation warning */
01506   UNUSED(hsai);
01507 
01508   /* NOTE : This function should not be modified, when the callback is needed,
01509             the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
01510    */
01511 }
01512 
01513 /**
01514   * @brief Rx Transfer completed callback.
01515   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01516   *               the configuration information for SAI module.
01517   * @retval None
01518   */
01519 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
01520 {
01521   /* Prevent unused argument(s) compilation warning */
01522   UNUSED(hsai);
01523 
01524   /* NOTE : This function should not be modified, when the callback is needed,
01525             the HAL_SAI_RxCpltCallback could be implemented in the user file
01526    */
01527 }
01528 
01529 /**
01530   * @brief Rx Transfer half completed callback.
01531   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01532   *               the configuration information for SAI module.
01533   * @retval None
01534   */
01535 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
01536 {
01537   /* Prevent unused argument(s) compilation warning */
01538   UNUSED(hsai);
01539 
01540   /* NOTE : This function should not be modified, when the callback is needed,
01541             the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
01542    */
01543 }
01544 
01545 /**
01546   * @brief SAI error callback.
01547   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01548   *               the configuration information for SAI module.
01549   * @retval None
01550   */
01551 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
01552 {
01553   /* Prevent unused argument(s) compilation warning */
01554   UNUSED(hsai);
01555 
01556   /* NOTE : This function should not be modified, when the callback is needed,
01557             the HAL_SAI_ErrorCallback could be implemented in the user file
01558    */
01559 }
01560 
01561 /**
01562   * @}
01563   */
01564 
01565 
01566 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions
01567  *  @brief   Peripheral State functions
01568  *
01569 @verbatim
01570  ===============================================================================
01571                 ##### Peripheral State and Errors functions #####
01572  ===============================================================================
01573   [..]
01574     This subsection permits to get in run-time the status of the peripheral
01575     and the data flow.
01576 
01577 @endverbatim
01578   * @{
01579   */
01580 
01581 /**
01582   * @brief  Return the SAI handle state.
01583   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01584   *               the configuration information for SAI module.
01585   * @retval HAL state
01586   */
01587 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai)
01588 {
01589   return hsai->State;
01590 }
01591 
01592 /**
01593 * @brief  Return the SAI error code.
01594 * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01595   *             the configuration information for the specified SAI Block.
01596 * @retval SAI Error Code
01597 */
01598 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai)
01599 {
01600   return hsai->ErrorCode;
01601 }
01602 /**
01603   * @}
01604   */
01605 
01606 /**
01607   * @}
01608   */
01609 
01610 /** @addtogroup SAI_Private_Functions
01611  *  @brief      Private functions
01612   * @{
01613   */
01614 
01615 /**
01616   * @brief  Initialize the SAI I2S protocol according to the specified parameters
01617   *         in the SAI_InitTypeDef and create the associated handle.
01618   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01619   *               the configuration information for SAI module.
01620   * @param  protocol one of the supported protocol.
01621   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize
01622   *                the configuration information for SAI module.
01623   * @param  nbslot number of slot minimum value is 2 and max is 16.
01624   *                    the value must be a multiple of 2.
01625   * @retval HAL status
01626   */
01627 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
01628 {
01629   hsai->Init.Protocol            = SAI_FREE_PROTOCOL;
01630   hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;
01631   /* Compute ClockStrobing according AudioMode */
01632   if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
01633   { /* Transmit */
01634     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_FALLINGEDGE;
01635   }
01636   else
01637   { /* Receive */
01638     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_RISINGEDGE;
01639   }
01640   hsai->FrameInit.FSDefinition   = SAI_FS_CHANNEL_IDENTIFICATION;
01641   hsai->SlotInit.SlotActive      = SAI_SLOTACTIVE_ALL;
01642   hsai->SlotInit.FirstBitOffset  = 0U;
01643   hsai->SlotInit.SlotNumber      = nbslot;
01644 
01645   /* in IS2 the number of slot must be even */
01646   if((nbslot & 0x1U) != 0U)
01647   {
01648     return HAL_ERROR;
01649   }
01650 
01651   switch(protocol)
01652   {
01653   case SAI_I2S_STANDARD :
01654     hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
01655     hsai->FrameInit.FSOffset   = SAI_FS_BEFOREFIRSTBIT;
01656     break;
01657   case SAI_I2S_MSBJUSTIFIED :
01658   case SAI_I2S_LSBJUSTIFIED :
01659     hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
01660     hsai->FrameInit.FSOffset   = SAI_FS_FIRSTBIT;
01661     break;
01662   default :
01663     return HAL_ERROR;
01664   }
01665 
01666   /* Frame definition */
01667   switch(datasize)
01668   {
01669   case SAI_PROTOCOL_DATASIZE_16BIT:
01670     hsai->Init.DataSize = SAI_DATASIZE_16;
01671     hsai->FrameInit.FrameLength = 32U*(nbslot/2U);
01672     hsai->FrameInit.ActiveFrameLength = 16U*(nbslot/2U);
01673     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
01674     break;
01675   case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
01676     hsai->Init.DataSize = SAI_DATASIZE_16;
01677     hsai->FrameInit.FrameLength = 64U*(nbslot/2U);
01678     hsai->FrameInit.ActiveFrameLength = 32U*(nbslot/2U);
01679     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
01680     break;
01681   case SAI_PROTOCOL_DATASIZE_24BIT:
01682     hsai->Init.DataSize = SAI_DATASIZE_24;
01683     hsai->FrameInit.FrameLength = 64U*(nbslot/2U);
01684     hsai->FrameInit.ActiveFrameLength = 32U*(nbslot/2U);
01685     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
01686     break;
01687   case SAI_PROTOCOL_DATASIZE_32BIT:
01688     hsai->Init.DataSize = SAI_DATASIZE_32;
01689     hsai->FrameInit.FrameLength = 64U*(nbslot/2U);
01690     hsai->FrameInit.ActiveFrameLength = 32U*(nbslot/2U);
01691     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
01692     break;
01693   default :
01694     return HAL_ERROR;
01695   }
01696   if(protocol == SAI_I2S_LSBJUSTIFIED)
01697   {
01698     if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
01699     {
01700       hsai->SlotInit.FirstBitOffset = 16U;
01701     }
01702     if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
01703     {
01704       hsai->SlotInit.FirstBitOffset = 8U;
01705     }
01706   }
01707   return HAL_OK;
01708 }
01709 
01710 /**
01711   * @brief  Initialize the SAI PCM protocol according to the specified parameters
01712   *         in the SAI_InitTypeDef and create the associated handle.
01713   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01714   *               the configuration information for SAI module.
01715   * @param  protocol one of the supported protocol
01716   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize
01717   * @param  nbslot number of slot minimum value is 1 and the max is 16.
01718   * @retval HAL status
01719   */
01720 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
01721 {
01722   hsai->Init.Protocol            = SAI_FREE_PROTOCOL;
01723   hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;
01724   /* Compute ClockStrobing according AudioMode */
01725   if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
01726   { /* Transmit */
01727     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_RISINGEDGE;
01728   }
01729   else
01730   { /* Receive */
01731     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_FALLINGEDGE;
01732   }
01733   hsai->FrameInit.FSDefinition   = SAI_FS_STARTFRAME;
01734   hsai->FrameInit.FSPolarity     = SAI_FS_ACTIVE_HIGH;
01735   hsai->FrameInit.FSOffset       = SAI_FS_BEFOREFIRSTBIT;
01736   hsai->SlotInit.FirstBitOffset  = 0U;
01737   hsai->SlotInit.SlotNumber      = nbslot;
01738   hsai->SlotInit.SlotActive      = SAI_SLOTACTIVE_ALL;
01739 
01740   switch(protocol)
01741   {
01742   case SAI_PCM_SHORT :
01743     hsai->FrameInit.ActiveFrameLength = 1U;
01744     break;
01745   case SAI_PCM_LONG :
01746     hsai->FrameInit.ActiveFrameLength = 13U;
01747     break;
01748   default :
01749     return HAL_ERROR;
01750   }
01751 
01752   switch(datasize)
01753   {
01754   case SAI_PROTOCOL_DATASIZE_16BIT:
01755     hsai->Init.DataSize = SAI_DATASIZE_16;
01756     hsai->FrameInit.FrameLength = 16U * nbslot;
01757     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
01758     break;
01759   case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
01760     hsai->Init.DataSize = SAI_DATASIZE_16;
01761     hsai->FrameInit.FrameLength = 32U * nbslot;
01762     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
01763     break;
01764   case SAI_PROTOCOL_DATASIZE_24BIT :
01765     hsai->Init.DataSize = SAI_DATASIZE_24;
01766     hsai->FrameInit.FrameLength = 32U * nbslot;
01767     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
01768     break;
01769   case SAI_PROTOCOL_DATASIZE_32BIT:
01770     hsai->Init.DataSize = SAI_DATASIZE_32;
01771     hsai->FrameInit.FrameLength = 32U * nbslot;
01772     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
01773     break;
01774   default :
01775     return HAL_ERROR;
01776   }
01777 
01778   return HAL_OK;
01779 }
01780 
01781 /**
01782   * @brief  Fill the fifo.
01783   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01784   *               the configuration information for SAI module.
01785   * @retval None
01786   */
01787 static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
01788 {
01789   /* fill the fifo with data before to enabled the SAI */
01790   while(((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U))
01791   {
01792     if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
01793     {
01794       hsai->Instance->DR = (*hsai->pBuffPtr++);
01795     }
01796     else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
01797     {
01798       hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
01799       hsai->pBuffPtr+= 2U;
01800     }
01801     else
01802     {
01803       hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
01804       hsai->pBuffPtr+= 4U;
01805     }
01806     hsai->XferCount--;
01807   }
01808 }
01809 
01810 /**
01811   * @brief  Return the interrupt flag to set according the SAI setup.
01812   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01813   *               the configuration information for SAI module.
01814   * @param  mode SAI_MODE_DMA or SAI_MODE_IT
01815   * @retval the list of the IT flag to enable
01816  */
01817 static uint32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode)
01818 {
01819   uint32_t tmpIT = SAI_IT_OVRUDR;
01820 
01821   if(mode == SAI_MODE_IT)
01822   {
01823     tmpIT|= SAI_IT_FREQ;
01824   }
01825 
01826   if((hsai->Init.Protocol == SAI_AC97_PROTOCOL) &&
01827     ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX)))
01828   {
01829     tmpIT|= SAI_IT_CNRDY;
01830   }
01831 
01832   if((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
01833   {
01834     tmpIT|= SAI_IT_AFSDET | SAI_IT_LFSDET;
01835   }
01836   else
01837   {
01838     /* hsai has been configured in master mode */
01839     tmpIT|= SAI_IT_WCKCFG;
01840   }
01841   return tmpIT;
01842 }
01843 
01844 /**
01845   * @brief  Disable the SAI and wait for the disabling.
01846   * @param  hsai  pointer to a SAI_HandleTypeDef structure that contains
01847   *               the configuration information for SAI module.
01848   * @retval None
01849   */
01850 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
01851 {
01852   register uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock /7U/1000U);
01853   HAL_StatusTypeDef status = HAL_OK;
01854 
01855   /* Disable the SAI instance */
01856   __HAL_SAI_DISABLE(hsai);
01857 
01858   do
01859   {
01860     /* Check for the Timeout */
01861     if (count-- == 0U)
01862     {         
01863       /* Update error code */
01864       hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
01865       status = HAL_TIMEOUT;
01866       break;
01867     }
01868   } while((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != RESET);
01869 
01870   return status;
01871 }
01872 
01873 /**
01874   * @brief  Tx Handler for Transmit in Interrupt mode 8-Bit transfer.
01875   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01876   *               the configuration information for SAI module.
01877   * @retval None
01878   */
01879 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
01880 {
01881   if(hsai->XferCount == 0U)
01882   {
01883     /* Handle the end of the transmission */
01884     /* Disable FREQ and OVRUDR interrupts */
01885     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
01886     hsai->State = HAL_SAI_STATE_READY;
01887     HAL_SAI_TxCpltCallback(hsai);
01888   }
01889   else
01890   {
01891     /* Write data on DR register */
01892     hsai->Instance->DR = (*hsai->pBuffPtr++);
01893     hsai->XferCount--;
01894   }
01895 }
01896 
01897 /**
01898   * @brief  Tx Handler for Transmit in Interrupt mode for 16-Bit transfer.
01899   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01900   *               the configuration information for SAI module.
01901   * @retval None
01902   */
01903 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
01904 {
01905   if(hsai->XferCount == 0U)
01906   {
01907     /* Handle the end of the transmission */
01908     /* Disable FREQ and OVRUDR interrupts */
01909     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
01910     hsai->State = HAL_SAI_STATE_READY;
01911     HAL_SAI_TxCpltCallback(hsai);
01912   }
01913   else
01914   {
01915     /* Write data on DR register */
01916     hsai->Instance->DR = *(uint16_t *)hsai->pBuffPtr;
01917     hsai->pBuffPtr+=2U;
01918     hsai->XferCount--;
01919   }
01920 }
01921 
01922 /**
01923   * @brief  Tx Handler for Transmit in Interrupt mode for 32-Bit transfer.
01924   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01925   *               the configuration information for SAI module.
01926   * @retval None
01927   */
01928 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
01929 {
01930   if(hsai->XferCount == 0U)
01931   {
01932     /* Handle the end of the transmission */
01933     /* Disable FREQ and OVRUDR interrupts */
01934     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
01935     hsai->State = HAL_SAI_STATE_READY;
01936     HAL_SAI_TxCpltCallback(hsai);
01937   }
01938   else
01939   {
01940     /* Write data on DR register */
01941     hsai->Instance->DR = *(uint32_t *)hsai->pBuffPtr;
01942     hsai->pBuffPtr+=4U;
01943     hsai->XferCount--;
01944   }
01945 }
01946 
01947 /**
01948   * @brief  Rx Handler for Receive in Interrupt mode 8-Bit transfer.
01949   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01950   *               the configuration information for SAI module.
01951   * @retval None
01952   */
01953 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
01954 {
01955   /* Receive data */
01956   (*hsai->pBuffPtr++) = hsai->Instance->DR;
01957   hsai->XferCount--;
01958 
01959   /* Check end of the transfer */
01960   if(hsai->XferCount == 0U)
01961   {
01962     /* Disable TXE and OVRUDR interrupts */
01963     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
01964 
01965     /* Clear the SAI Overrun flag */
01966     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
01967 
01968     hsai->State = HAL_SAI_STATE_READY;
01969     HAL_SAI_RxCpltCallback(hsai);
01970   }
01971 }
01972 
01973 /**
01974   * @brief  Rx Handler for Receive in Interrupt mode for 16-Bit transfer.
01975   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
01976   *               the configuration information for SAI module.
01977   * @retval None
01978   */
01979 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
01980 {
01981   /* Receive data */
01982   *(uint16_t*)hsai->pBuffPtr = hsai->Instance->DR;
01983   hsai->pBuffPtr+=2U;
01984   hsai->XferCount--;
01985 
01986   /* Check end of the transfer */
01987   if(hsai->XferCount == 0U)
01988   {
01989     /* Disable TXE and OVRUDR interrupts */
01990     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
01991 
01992     /* Clear the SAI Overrun flag */
01993     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
01994 
01995     hsai->State = HAL_SAI_STATE_READY;
01996     HAL_SAI_RxCpltCallback(hsai);
01997   }
01998 }
01999 
02000 /**
02001   * @brief  Rx Handler for Receive in Interrupt mode for 32-Bit transfer.
02002   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
02003   *               the configuration information for SAI module.
02004   * @retval None
02005   */
02006 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
02007 {
02008   /* Receive data */
02009   *(uint32_t*)hsai->pBuffPtr = hsai->Instance->DR;
02010   hsai->pBuffPtr+=4U;
02011   hsai->XferCount--;
02012 
02013   /* Check end of the transfer */
02014   if(hsai->XferCount == 0U)
02015   {
02016     /* Disable TXE and OVRUDR interrupts */
02017     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
02018 
02019     /* Clear the SAI Overrun flag */
02020     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
02021 
02022     hsai->State = HAL_SAI_STATE_READY;
02023     HAL_SAI_RxCpltCallback(hsai);
02024   }
02025 }
02026 
02027 /**
02028   * @brief DMA SAI transmit process complete callback.
02029   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02030   *               the configuration information for the specified DMA module.
02031   * @retval None
02032   */
02033 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
02034 {
02035   SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef* )hdma)->Parent;
02036 
02037   if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U)
02038   {
02039     hsai->XferCount = 0U;
02040 
02041     /* Disable SAI Tx DMA Request */
02042     hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
02043 
02044     /* Stop the interrupts error handling */
02045     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
02046 
02047     hsai->State= HAL_SAI_STATE_READY;
02048   }
02049   HAL_SAI_TxCpltCallback(hsai);
02050 }
02051 
02052 /**
02053   * @brief DMA SAI transmit process half complete callback.
02054   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02055   *               the configuration information for the specified DMA module.
02056   * @retval None
02057   */
02058 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
02059 {
02060   SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
02061 
02062   HAL_SAI_TxHalfCpltCallback(hsai);
02063 }
02064 
02065 /**
02066   * @brief DMA SAI receive process complete callback.
02067   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02068   *               the configuration information for the specified DMA module.
02069   * @retval None
02070   */
02071 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
02072 {
02073   SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
02074   if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U)
02075   {
02076     /* Disable Rx DMA Request */
02077     hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
02078     hsai->XferCount = 0U;
02079 
02080     /* Stop the interrupts error handling */
02081     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
02082 
02083     hsai->State = HAL_SAI_STATE_READY;
02084   }
02085   HAL_SAI_RxCpltCallback(hsai);
02086 }
02087 
02088 /**
02089   * @brief DMA SAI receive process half complete callback 
02090   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02091   *               the configuration information for the specified DMA module.
02092   * @retval None
02093   */
02094 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
02095 {
02096   SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
02097 
02098   HAL_SAI_RxHalfCpltCallback(hsai);
02099 }
02100 
02101 /**
02102   * @brief DMA SAI communication error callback.
02103   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02104   *               the configuration information for the specified DMA module.
02105   * @retval None
02106   */
02107 static void SAI_DMAError(DMA_HandleTypeDef *hdma)
02108 {
02109   SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
02110 
02111   /* Set SAI error code */
02112   hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
02113 
02114   if((hsai->hdmatx->ErrorCode == HAL_DMA_ERROR_TE) || (hsai->hdmarx->ErrorCode == HAL_DMA_ERROR_TE))
02115   {
02116     /* Disable the SAI DMA request */
02117     hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
02118 
02119     /* Disable SAI peripheral */
02120     SAI_Disable(hsai);
02121     
02122     /* Set the SAI state ready to be able to start again the process */
02123     hsai->State = HAL_SAI_STATE_READY;
02124 
02125     /* Initialize XferCount */
02126     hsai->XferCount = 0U;
02127   }
02128   /* SAI error Callback */ 
02129   HAL_SAI_ErrorCallback(hsai);
02130 }
02131 
02132 /**
02133   * @brief DMA SAI Abort callback.
02134   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
02135   *               the configuration information for the specified DMA module.
02136   * @retval None
02137   */
02138 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma)   
02139 {
02140   SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
02141 
02142   /* Disable DMA request */
02143   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
02144 
02145   /* Disable all interrupts and clear all flags */
02146   hsai->Instance->IMR = 0U;
02147   hsai->Instance->CLRFR = 0xFFFFFFFFU;
02148 
02149   if(hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG)
02150   {
02151     /* Disable SAI peripheral */
02152     SAI_Disable(hsai);
02153 
02154     /* Flush the fifo */
02155     SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
02156   }
02157   /* Set the SAI state to ready to be able to start again the process */
02158   hsai->State = HAL_SAI_STATE_READY;
02159   
02160   /* Initialize XferCount */
02161   hsai->XferCount = 0U;  
02162 
02163   /* SAI error Callback */ 
02164   HAL_SAI_ErrorCallback(hsai);
02165 }
02166 
02167 /**
02168   * @}
02169   */
02170 
02171 #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */
02172 #endif /* HAL_SAI_MODULE_ENABLED */
02173 /**
02174   * @}
02175   */
02176 
02177 /**
02178   * @}
02179   */
02180 
02181 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/