TUKS MCU Introductory course / TUKS-COURSE-THERMOMETER

Fork of TUKS-COURSE-TIMER by TUKS MCU Introductory course

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32l4xx_hal_sai.c Source File

stm32l4xx_hal_sai.c

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