xref: /btstack/port/stm32-f4discovery-usb/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c (revision a8f7f3fcbcd51f8d2e92aca076b6a9f812db358c)
1 /**
2   ******************************************************************************
3   * @file    stm32f4xx_hal_sai.c
4   * @author  MCD Application Team
5   * @brief   SAI HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the Serial Audio Interface (SAI) peripheral:
8   *           + Initialization/de-initialization functions
9   *           + I/O operation functions
10   *           + Peripheral Control functions
11   *           + Peripheral State functions
12   *
13   @verbatim
14   ==============================================================================
15                   ##### How to use this driver #####
16   ==============================================================================
17 
18   [..]
19     The SAI HAL driver can be used as follows:
20 
21     (#) Declare a SAI_HandleTypeDef handle structure (eg. SAI_HandleTypeDef hsai).
22     (#) Initialize the SAI low level resources by implementing the HAL_SAI_MspInit() API:
23         (##) Enable the SAI interface clock.
24         (##) SAI pins configuration:
25             (+++) Enable the clock for the SAI GPIOs.
26             (+++) Configure these SAI pins as alternate function pull-up.
27         (##) NVIC configuration if you need to use interrupt process (HAL_SAI_Transmit_IT()
28              and HAL_SAI_Receive_IT() APIs):
29             (+++) Configure the SAI interrupt priority.
30             (+++) Enable the NVIC SAI IRQ handle.
31 
32         (##) DMA Configuration if you need to use DMA process (HAL_SAI_Transmit_DMA()
33              and HAL_SAI_Receive_DMA() APIs):
34             (+++) Declare a DMA handle structure for the Tx/Rx stream.
35             (+++) Enable the DMAx interface clock.
36             (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
37             (+++) Configure the DMA Tx/Rx Stream.
38             (+++) Associate the initialized DMA handle to the SAI DMA Tx/Rx handle.
39             (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the
40                 DMA Tx/Rx Stream.
41 
42     (#) The initialization can be done by two ways
43         (##) Expert mode : Initialize the structures Init, FrameInit and SlotInit and call HAL_SAI_Init().
44         (##) Simplified mode : Initialize the high part of Init Structure and call HAL_SAI_InitProtocol().
45 
46   [..]
47     (@) The specific SAI interrupts (FIFO request and Overrun underrun interrupt)
48         will be managed using the macros __HAL_SAI_ENABLE_IT() and __HAL_SAI_DISABLE_IT()
49         inside the transmit and receive process.
50 
51   [..]
52    (@) SAI Clock Source configuration is managed differently depending on the selected
53        STM32F4 devices :
54        (+@) For STM32F446xx devices, the configuration is managed through RCCEx_PeriphCLKConfig()
55             function in the HAL RCC drivers
56        (+@) For STM32F439xx/STM32F437xx/STM32F429xx/STM32F427xx devices, the configuration
57             is managed within HAL SAI drivers through HAL_SAI_Init() function using
58             ClockSource field of SAI_InitTypeDef structure.
59   [..]
60    (@) Make sure that either:
61        (+@) I2S PLL is configured or
62        (+@) SAI PLL is configured or
63        (+@) External clock source is configured after setting correctly
64             the define constant EXTERNAL_CLOCK_VALUE in the stm32f4xx_hal_conf.h file.
65   [..]
66     (@) In master Tx mode: enabling the audio block immediately generates the bit clock
67         for the external slaves even if there is no data in the FIFO, However FS signal
68         generation is conditioned by the presence of data in the FIFO.
69 
70   [..]
71     (@) In master Rx mode: enabling the audio block immediately generates the bit clock
72         and FS signal for the external slaves.
73 
74   [..]
75     (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior:
76         (+@) First bit Offset <= (SLOT size - Data size)
77         (+@) Data size <= SLOT size
78         (+@) Number of SLOT x SLOT size = Frame length
79         (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected.
80 
81   [..]
82     Three operation modes are available within this driver :
83 
84     *** Polling mode IO operation ***
85     =================================
86     [..]
87       (+) Send an amount of data in blocking mode using HAL_SAI_Transmit()
88       (+) Receive an amount of data in blocking mode using HAL_SAI_Receive()
89 
90     *** Interrupt mode IO operation ***
91     ===================================
92     [..]
93       (+) Send an amount of data in non-blocking mode using HAL_SAI_Transmit_IT()
94       (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
95           add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
96       (+) Receive an amount of data in non-blocking mode using HAL_SAI_Receive_IT()
97       (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
98           add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
99       (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
100           add his own code by customization of function pointer HAL_SAI_ErrorCallback()
101 
102     *** DMA mode IO operation ***
103     =============================
104     [..]
105       (+) Send an amount of data in non-blocking mode (DMA) using HAL_SAI_Transmit_DMA()
106       (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
107           add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
108       (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SAI_Receive_DMA()
109       (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
110           add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
111       (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
112           add his own code by customization of function pointer HAL_SAI_ErrorCallback()
113       (+) Pause the DMA Transfer using HAL_SAI_DMAPause()
114       (+) Resume the DMA Transfer using HAL_SAI_DMAResume()
115       (+) Stop the DMA Transfer using HAL_SAI_DMAStop()
116 
117     *** SAI HAL driver additional function list ***
118     ===============================================
119     [..]
120       Below the list the others API available SAI HAL driver :
121 
122       (+) HAL_SAI_EnableTxMuteMode(): Enable the mute in tx mode
123       (+) HAL_SAI_DisableTxMuteMode(): Disable the mute in tx mode
124       (+) HAL_SAI_EnableRxMuteMode(): Enable the mute in Rx mode
125       (+) HAL_SAI_DisableRxMuteMode(): Disable the mute in Rx mode
126       (+) HAL_SAI_FlushRxFifo(): Flush the rx fifo.
127       (+) HAL_SAI_Abort(): Abort the current transfer
128 
129     *** SAI HAL driver macros list ***
130     ==================================
131     [..]
132       Below the list of most used macros in SAI HAL driver :
133 
134       (+) __HAL_SAI_ENABLE(): Enable the SAI peripheral
135       (+) __HAL_SAI_DISABLE(): Disable the SAI peripheral
136       (+) __HAL_SAI_ENABLE_IT(): Enable the specified SAI interrupts
137       (+) __HAL_SAI_DISABLE_IT(): Disable the specified SAI interrupts
138       (+) __HAL_SAI_GET_IT_SOURCE(): Check if the specified SAI interrupt source is
139           enabled or disabled
140       (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not
141 
142     *** Callback registration ***
143     =============================
144     [..]
145     The compilation define USE_HAL_SAI_REGISTER_CALLBACKS when set to 1
146     allows the user to configure dynamically the driver callbacks.
147     Use functions HAL_SAI_RegisterCallback() to register a user callback.
148 
149     [..]
150     Function HAL_SAI_RegisterCallback() allows to register following callbacks:
151       (+) RxCpltCallback     : SAI receive complete.
152       (+) RxHalfCpltCallback : SAI receive half complete.
153       (+) TxCpltCallback     : SAI transmit complete.
154       (+) TxHalfCpltCallback : SAI transmit half complete.
155       (+) ErrorCallback      : SAI error.
156       (+) MspInitCallback    : SAI MspInit.
157       (+) MspDeInitCallback  : SAI MspDeInit.
158     [..]
159     This function takes as parameters the HAL peripheral handle, the callback ID
160     and a pointer to the user callback function.
161 
162     [..]
163     Use function HAL_SAI_UnRegisterCallback() to reset a callback to the default
164     weak (surcharged) function.
165     HAL_SAI_UnRegisterCallback() takes as parameters the HAL peripheral handle,
166     and the callback ID.
167     [..]
168     This function allows to reset following callbacks:
169       (+) RxCpltCallback     : SAI receive complete.
170       (+) RxHalfCpltCallback : SAI receive half complete.
171       (+) TxCpltCallback     : SAI transmit complete.
172       (+) TxHalfCpltCallback : SAI transmit half complete.
173       (+) ErrorCallback      : SAI error.
174       (+) MspInitCallback    : SAI MspInit.
175       (+) MspDeInitCallback  : SAI MspDeInit.
176 
177     [..]
178     By default, after the HAL_SAI_Init and if the state is HAL_SAI_STATE_RESET
179     all callbacks are reset to the corresponding legacy weak (surcharged) functions:
180     examples HAL_SAI_RxCpltCallback(), HAL_SAI_ErrorCallback().
181     Exception done for MspInit and MspDeInit callbacks that are respectively
182     reset to the legacy weak (surcharged) functions in the HAL_SAI_Init
183     and HAL_SAI_DeInit only when these callbacks are null (not registered beforehand).
184     If not, MspInit or MspDeInit are not null, the HAL_SAI_Init and HAL_SAI_DeInit
185     keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
186 
187     [..]
188     Callbacks can be registered/unregistered in READY state only.
189     Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
190     in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
191     during the Init/DeInit.
192     In that case first register the MspInit/MspDeInit user callbacks
193     using HAL_SAI_RegisterCallback before calling HAL_SAI_DeInit
194     or HAL_SAI_Init function.
195 
196     [..]
197     When the compilation define USE_HAL_SAI_REGISTER_CALLBACKS is set to 0 or
198     not defined, the callback registering feature is not available
199     and weak (surcharged) callbacks are used.
200 
201   @endverbatim
202   ******************************************************************************
203   * @attention
204   *
205   * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
206   * All rights reserved.</center></h2>
207   *
208   * This software component is licensed by ST under BSD 3-Clause license,
209   * the "License"; You may not use this file except in compliance with the
210   * License. You may obtain a copy of the License at:
211   *                        opensource.org/licenses/BSD-3-Clause
212   *
213   ******************************************************************************
214   */
215 
216 /* Includes ------------------------------------------------------------------*/
217 #include "stm32f4xx_hal.h"
218 
219 /** @addtogroup STM32F4xx_HAL_Driver
220   * @{
221   */
222 
223 /** @defgroup SAI SAI
224   * @brief SAI HAL module driver
225   * @{
226   */
227 
228 #ifdef HAL_SAI_MODULE_ENABLED
229 
230 #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\
231     defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) ||\
232     defined(STM32F423xx)
233 
234 /** @defgroup SAI_Private_Typedefs  SAI Private Typedefs
235   * @{
236   */
237 typedef enum {
238   SAI_MODE_DMA,
239   SAI_MODE_IT
240 }SAI_ModeTypedef;
241 /**
242   * @}
243   */
244 
245 /* Private define ------------------------------------------------------------*/
246 
247 /** @defgroup SAI_Private_Constants  SAI Private Constants
248   * @{
249   */
250 #define SAI_DEFAULT_TIMEOUT   4U /* 4ms */
251 /**
252   * @}
253   */
254 
255 /* Private macro -------------------------------------------------------------*/
256 /* Private variables ---------------------------------------------------------*/
257 /* Private function prototypes -----------------------------------------------*/
258 /** @defgroup SAI_Private_Functions  SAI Private Functions
259   * @{
260   */
261 static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
262 static uint32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode);
263 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
264 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
265 
266 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
267 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
268 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
269 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
270 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
271 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
272 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
273 
274 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
275 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
276 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
277 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
278 static void SAI_DMAError(DMA_HandleTypeDef *hdma);
279 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma);
280 /**
281   * @}
282   */
283 
284 /* Exported functions ---------------------------------------------------------*/
285 /** @defgroup SAI_Exported_Functions SAI Exported Functions
286   * @{
287   */
288 
289 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions
290   * @brief    Initialization and Configuration functions
291   *
292 @verbatim
293  ===============================================================================
294             ##### Initialization and de-initialization functions #####
295  ===============================================================================
296   [..]  This subsection provides a set of functions allowing to initialize and
297         de-initialize the SAIx peripheral:
298 
299       (+) User must implement HAL_SAI_MspInit() function in which he configures
300           all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
301 
302       (+) Call the function HAL_SAI_Init() to configure the selected device with
303           the selected configuration:
304         (++) Mode (Master/slave TX/RX)
305         (++) Protocol
306         (++) Data Size
307         (++) MCLK Output
308         (++) Audio frequency
309         (++) FIFO Threshold
310         (++) Frame Config
311         (++) Slot Config
312 
313       (+) Call the function HAL_SAI_DeInit() to restore the default configuration
314           of the selected SAI peripheral.
315 
316 @endverbatim
317   * @{
318   */
319 
320 /**
321   * @brief  Initialize the structure FrameInit, SlotInit and the low part of
322   *         Init according to the specified parameters and call the function
323   *         HAL_SAI_Init to initialize the SAI block.
324   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
325   *               the configuration information for SAI module.
326   * @param  protocol one of the supported protocol @ref SAI_Protocol
327   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize
328   *                   the configuration information for SAI module.
329   * @param  nbslot Number of slot.
330   * @retval HAL status
331   */
HAL_SAI_InitProtocol(SAI_HandleTypeDef * hsai,uint32_t protocol,uint32_t datasize,uint32_t nbslot)332 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
333 {
334   HAL_StatusTypeDef status = HAL_OK;
335 
336   /* Check the parameters */
337   assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));
338   assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));
339 
340   switch(protocol)
341   {
342   case SAI_I2S_STANDARD :
343   case SAI_I2S_MSBJUSTIFIED :
344   case SAI_I2S_LSBJUSTIFIED :
345     status = SAI_InitI2S(hsai, protocol, datasize, nbslot);
346     break;
347   case SAI_PCM_LONG :
348   case SAI_PCM_SHORT :
349     status = SAI_InitPCM(hsai, protocol, datasize, nbslot);
350     break;
351   default :
352     status = HAL_ERROR;
353     break;
354   }
355 
356   if(status == HAL_OK)
357   {
358     status = HAL_SAI_Init(hsai);
359   }
360 
361   return status;
362 }
363 
364 /**
365   * @brief  Initialize the SAI according to the specified parameters.
366   *         in the SAI_InitTypeDef structure and initialize the associated handle.
367   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
368   *               the configuration information for SAI module.
369   * @retval HAL status
370   */
HAL_SAI_Init(SAI_HandleTypeDef * hsai)371 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
372 {
373   uint32_t tmpregisterGCR = 0U;
374 
375   /* This variable used to store the SAI_CK_x (value in Hz) */
376   uint32_t freq = 0U;
377 
378   /* This variable is used to compute CKSTR bits of SAI CR1 according to
379      ClockStrobing and AudioMode fields */
380   uint32_t ckstr_bits = 0U;
381   uint32_t syncen_bits = 0U;
382 
383   /* Check the SAI handle allocation */
384   if(hsai == NULL)
385   {
386     return HAL_ERROR;
387   }
388 
389   /* check the instance */
390   assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance));
391 
392   /* Check the SAI Block parameters */
393   assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
394   assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
395   assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
396   assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));
397   assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
398   assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
399   assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
400   assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
401   assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
402   assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
403   assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
404   assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode));
405   assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));
406   assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));
407 
408   /* Check the SAI Block Frame parameters */
409   assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
410   assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
411   assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
412   assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
413   assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
414 
415   /* Check the SAI Block Slot parameters */
416   assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
417   assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
418   assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
419   assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
420 
421   if(hsai->State == HAL_SAI_STATE_RESET)
422   {
423     /* Allocate lock resource and initialize it */
424     hsai->Lock = HAL_UNLOCKED;
425 
426 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
427     /* Reset callback pointers to the weak predefined callbacks */
428     hsai->RxCpltCallback     = HAL_SAI_RxCpltCallback;
429     hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
430     hsai->TxCpltCallback     = HAL_SAI_TxCpltCallback;
431     hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
432     hsai->ErrorCallback      = HAL_SAI_ErrorCallback;
433 
434     /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
435     if (hsai->MspInitCallback == NULL)
436     {
437       hsai->MspInitCallback = HAL_SAI_MspInit;
438     }
439     hsai->MspInitCallback(hsai);
440 #else
441     /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
442     HAL_SAI_MspInit(hsai);
443 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
444   }
445 
446   hsai->State = HAL_SAI_STATE_BUSY;
447 
448   /* Disable the selected SAI peripheral */
449   SAI_Disable(hsai);
450 
451   /* SAI Block Synchro Configuration -----------------------------------------*/
452   SAI_BlockSynchroConfig(hsai);
453 
454   /* Configure Master Clock using the following formula :
455      MCLK_x = SAI_CK_x / (MCKDIV[3:0] * 2) with MCLK_x = 256 * FS
456      FS = SAI_CK_x / (MCKDIV[3:0] * 2) * 256
457      MCKDIV[3:0] = SAI_CK_x / FS * 512 */
458   if(hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)
459   {
460     /* Get SAI clock source based on Source clock selection from RCC */
461     freq = SAI_GetInputClock(hsai);
462 
463     /* (saiclocksource x 10) to keep Significant digits */
464     tmpregisterGCR = (((freq * 10U) / ((hsai->Init.AudioFrequency) * 512U)));
465 
466     hsai->Init.Mckdiv = tmpregisterGCR / 10U;
467 
468     /* Round result to the nearest integer */
469     if((tmpregisterGCR % 10U) > 8U)
470     {
471       hsai->Init.Mckdiv+= 1U;
472     }
473   }
474 
475   /* Check the SAI Block master clock divider parameter */
476   assert_param(IS_SAI_BLOCK_MASTER_DIVIDER(hsai->Init.Mckdiv));
477 
478   /* Compute CKSTR bits of SAI CR1 according to ClockStrobing and AudioMode */
479   if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
480   {
481     ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U: SAI_xCR1_CKSTR;
482   }
483   else
484   {
485     ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR: 0U;
486   }
487 
488   /* SAI Block Configuration -------------------------------------------------*/
489   switch(hsai->Init.Synchro)
490   {
491   case SAI_ASYNCHRONOUS :
492     {
493       syncen_bits = 0U;
494     }
495     break;
496   case SAI_SYNCHRONOUS :
497     {
498       syncen_bits = SAI_xCR1_SYNCEN_0;
499     }
500     break;
501   case SAI_SYNCHRONOUS_EXT_SAI1 :
502   case SAI_SYNCHRONOUS_EXT_SAI2 :
503     {
504       syncen_bits = SAI_xCR1_SYNCEN_1;
505     }
506     break;
507   default:
508     break;
509   }
510 
511   /* SAI CR1 Configuration */
512   hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG |  SAI_xCR1_DS |      \
513                            SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN |\
514                            SAI_xCR1_MONO | SAI_xCR1_OUTDRIV  | SAI_xCR1_DMAEN |  \
515                            SAI_xCR1_NODIV | SAI_xCR1_MCKDIV);
516 
517   hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol |           \
518                           hsai->Init.DataSize | hsai->Init.FirstBit  |           \
519                           ckstr_bits | syncen_bits |                             \
520                           hsai->Init.MonoStereoMode | hsai->Init.OutputDrive |   \
521                           hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20U));
522 
523   /* SAI CR2 Configuration */
524   hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL);
525   hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);
526 
527   /* SAI Frame Configuration -----------------------------------------*/
528   hsai->Instance->FRCR&=(~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \
529                            SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF));
530   hsai->Instance->FRCR|=((hsai->FrameInit.FrameLength - 1U) |
531                           hsai->FrameInit.FSOffset     |
532                           hsai->FrameInit.FSDefinition |
533                           hsai->FrameInit.FSPolarity   |
534                           ((hsai->FrameInit.ActiveFrameLength - 1U) << 8U));
535 
536   /* SAI Block_x SLOT Configuration ------------------------------------------*/
537   /* This register has no meaning in AC 97 and SPDIF audio protocol */
538   hsai->Instance->SLOTR &= ~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ | \
539                              SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN );
540 
541   hsai->Instance->SLOTR |=  hsai->SlotInit.FirstBitOffset |  hsai->SlotInit.SlotSize  | \
542                             (hsai->SlotInit.SlotActive << 16U) | ((hsai->SlotInit.SlotNumber - 1U) <<  8U);
543 
544   /* Initialize the error code */
545   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
546 
547   /* Initialize the SAI state */
548   hsai->State= HAL_SAI_STATE_READY;
549 
550   /* Release Lock */
551   __HAL_UNLOCK(hsai);
552 
553   return HAL_OK;
554 }
555 
556 /**
557   * @brief  DeInitialize the SAI peripheral.
558   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
559   *               the configuration information for SAI module.
560   * @retval HAL status
561   */
HAL_SAI_DeInit(SAI_HandleTypeDef * hsai)562 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
563 {
564   /* Check the SAI handle allocation */
565   if(hsai == NULL)
566   {
567     return HAL_ERROR;
568   }
569 
570   hsai->State = HAL_SAI_STATE_BUSY;
571 
572   /* Disabled All interrupt and clear all the flag */
573   hsai->Instance->IMR = 0U;
574   hsai->Instance->CLRFR = 0xFFFFFFFFU;
575 
576   /* Disable the SAI */
577   SAI_Disable(hsai);
578 
579   /* Flush the fifo */
580   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
581 
582   /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
583 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
584   if (hsai->MspDeInitCallback == NULL)
585   {
586     hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
587   }
588   hsai->MspDeInitCallback(hsai);
589 #else
590   HAL_SAI_MspDeInit(hsai);
591 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
592 
593   /* Initialize the error code */
594   hsai->ErrorCode = HAL_SAI_ERROR_NONE;
595 
596   /* Initialize the SAI state */
597   hsai->State = HAL_SAI_STATE_RESET;
598 
599   /* Release Lock */
600   __HAL_UNLOCK(hsai);
601 
602   return HAL_OK;
603 }
604 
605 /**
606   * @brief Initialize the SAI MSP.
607   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
608   *               the configuration information for SAI module.
609   * @retval None
610   */
HAL_SAI_MspInit(SAI_HandleTypeDef * hsai)611 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
612 {
613   /* Prevent unused argument(s) compilation warning */
614   UNUSED(hsai);
615 
616   /* NOTE : This function should not be modified, when the callback is needed,
617             the HAL_SAI_MspInit could be implemented in the user file
618    */
619 }
620 
621 /**
622   * @brief DeInitialize the SAI MSP.
623   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
624   *               the configuration information for SAI module.
625   * @retval None
626   */
HAL_SAI_MspDeInit(SAI_HandleTypeDef * hsai)627 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
628 {
629   /* Prevent unused argument(s) compilation warning */
630   UNUSED(hsai);
631 
632   /* NOTE : This function should not be modified, when the callback is needed,
633             the HAL_SAI_MspDeInit could be implemented in the user file
634    */
635 }
636 
637 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
638 /**
639   * @brief  Register a user SAI callback
640   *         to be used instead of the weak predefined callback.
641   * @param  hsai SAI handle.
642   * @param  CallbackID ID of the callback to be registered.
643   *         This parameter can be one of the following values:
644   *           @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
645   *           @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
646   *           @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
647   *           @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
648   *           @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
649   *           @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
650   *           @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
651   * @param  pCallback pointer to the callback function.
652   * @retval HAL status.
653   */
HAL_SAI_RegisterCallback(SAI_HandleTypeDef * hsai,HAL_SAI_CallbackIDTypeDef CallbackID,pSAI_CallbackTypeDef pCallback)654 HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef        *hsai,
655                                            HAL_SAI_CallbackIDTypeDef CallbackID,
656                                            pSAI_CallbackTypeDef      pCallback)
657 {
658   HAL_StatusTypeDef status = HAL_OK;
659 
660   if (pCallback == NULL)
661   {
662     /* update the error code */
663     hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
664     /* update return status */
665     status = HAL_ERROR;
666   }
667   else
668   {
669     if (HAL_SAI_STATE_READY == hsai->State)
670     {
671       switch (CallbackID)
672       {
673         case HAL_SAI_RX_COMPLETE_CB_ID :
674           hsai->RxCpltCallback = pCallback;
675           break;
676         case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
677           hsai->RxHalfCpltCallback = pCallback;
678           break;
679         case HAL_SAI_TX_COMPLETE_CB_ID :
680           hsai->TxCpltCallback = pCallback;
681           break;
682         case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
683           hsai->TxHalfCpltCallback = pCallback;
684           break;
685         case HAL_SAI_ERROR_CB_ID :
686           hsai->ErrorCallback = pCallback;
687           break;
688         case HAL_SAI_MSPINIT_CB_ID :
689           hsai->MspInitCallback = pCallback;
690           break;
691         case HAL_SAI_MSPDEINIT_CB_ID :
692           hsai->MspDeInitCallback = pCallback;
693           break;
694         default :
695           /* update the error code */
696           hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
697           /* update return status */
698           status = HAL_ERROR;
699           break;
700       }
701     }
702     else if (HAL_SAI_STATE_RESET == hsai->State)
703     {
704       switch (CallbackID)
705       {
706         case HAL_SAI_MSPINIT_CB_ID :
707           hsai->MspInitCallback = pCallback;
708           break;
709         case HAL_SAI_MSPDEINIT_CB_ID :
710           hsai->MspDeInitCallback = pCallback;
711           break;
712         default :
713           /* update the error code */
714           hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
715           /* update return status */
716           status = HAL_ERROR;
717           break;
718       }
719     }
720     else
721     {
722       /* update the error code */
723       hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
724       /* update return status */
725       status = HAL_ERROR;
726     }
727   }
728   return status;
729 }
730 
731 /**
732   * @brief  Unregister a user SAI callback.
733   *         SAI callback is redirected to the weak predefined callback.
734   * @param  hsai SAI handle.
735   * @param  CallbackID ID of the callback to be unregistered.
736   *         This parameter can be one of the following values:
737   *           @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
738   *           @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
739   *           @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
740   *           @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
741   *           @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
742   *           @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
743   *           @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
744   * @retval HAL status.
745   */
HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef * hsai,HAL_SAI_CallbackIDTypeDef CallbackID)746 HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef        *hsai,
747                                              HAL_SAI_CallbackIDTypeDef CallbackID)
748 {
749   HAL_StatusTypeDef status = HAL_OK;
750 
751   if (HAL_SAI_STATE_READY == hsai->State)
752   {
753     switch (CallbackID)
754     {
755       case HAL_SAI_RX_COMPLETE_CB_ID :
756         hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
757         break;
758       case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
759         hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
760         break;
761       case HAL_SAI_TX_COMPLETE_CB_ID :
762         hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
763         break;
764       case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
765         hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
766         break;
767       case HAL_SAI_ERROR_CB_ID :
768         hsai->ErrorCallback = HAL_SAI_ErrorCallback;
769         break;
770       case HAL_SAI_MSPINIT_CB_ID :
771         hsai->MspInitCallback = HAL_SAI_MspInit;
772         break;
773       case HAL_SAI_MSPDEINIT_CB_ID :
774         hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
775         break;
776       default :
777         /* update the error code */
778         hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
779         /* update return status */
780         status = HAL_ERROR;
781         break;
782     }
783   }
784   else if (HAL_SAI_STATE_RESET == hsai->State)
785   {
786     switch (CallbackID)
787     {
788       case HAL_SAI_MSPINIT_CB_ID :
789         hsai->MspInitCallback = HAL_SAI_MspInit;
790         break;
791       case HAL_SAI_MSPDEINIT_CB_ID :
792         hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
793         break;
794       default :
795         /* update the error code */
796         hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
797         /* update return status */
798         status = HAL_ERROR;
799         break;
800     }
801   }
802   else
803   {
804     /* update the error code */
805     hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
806     /* update return status */
807     status = HAL_ERROR;
808   }
809   return status;
810 }
811 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
812 
813 /**
814   * @}
815   */
816 
817 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions
818   * @brief    Data transfers functions
819   *
820 @verbatim
821   ==============================================================================
822                       ##### IO operation functions #####
823   ==============================================================================
824   [..]
825     This subsection provides a set of functions allowing to manage the SAI data
826     transfers.
827 
828     (+) There are two modes of transfer:
829       (++) Blocking mode : The communication is performed in the polling mode.
830            The status of all data processing is returned by the same function
831            after finishing transfer.
832       (++) No-Blocking mode : The communication is performed using Interrupts
833            or DMA. These functions return the status of the transfer startup.
834            The end of the data processing will be indicated through the
835            dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when
836            using DMA mode.
837 
838     (+) Blocking mode functions are :
839       (++) HAL_SAI_Transmit()
840       (++) HAL_SAI_Receive()
841 
842     (+) Non Blocking mode functions with Interrupt are :
843       (++) HAL_SAI_Transmit_IT()
844       (++) HAL_SAI_Receive_IT()
845 
846     (+) Non Blocking mode functions with DMA are :
847       (++) HAL_SAI_Transmit_DMA()
848       (++) HAL_SAI_Receive_DMA()
849 
850     (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
851       (++) HAL_SAI_TxCpltCallback()
852       (++) HAL_SAI_RxCpltCallback()
853       (++) HAL_SAI_ErrorCallback()
854 
855 @endverbatim
856   * @{
857   */
858 
859 /**
860   * @brief  Transmit an amount of data in blocking mode.
861   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
862   *               the configuration information for SAI module.
863   * @param  pData Pointer to data buffer
864   * @param  Size Amount of data to be sent
865   * @param  Timeout Timeout duration
866   * @retval HAL status
867   */
HAL_SAI_Transmit(SAI_HandleTypeDef * hsai,uint8_t * pData,uint16_t Size,uint32_t Timeout)868 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t* pData, uint16_t Size, uint32_t Timeout)
869 {
870   uint32_t tickstart = HAL_GetTick();
871 
872   if((pData == NULL ) || (Size == 0))
873   {
874     return  HAL_ERROR;
875   }
876 
877   if(hsai->State == HAL_SAI_STATE_READY)
878   {
879     /* Process Locked */
880     __HAL_LOCK(hsai);
881 
882     hsai->XferSize = Size;
883     hsai->XferCount = Size;
884     hsai->pBuffPtr = pData;
885     hsai->State = HAL_SAI_STATE_BUSY_TX;
886     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
887 
888     /* Check if the SAI is already enabled */
889     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
890     {
891       /* fill the fifo with data before to enabled the SAI */
892       SAI_FillFifo(hsai);
893       /* Enable SAI peripheral */
894       __HAL_SAI_ENABLE(hsai);
895     }
896 
897     while(hsai->XferCount > 0U)
898     {
899       /* Write data if the FIFO is not full */
900       if((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
901       {
902         if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
903         {
904           hsai->Instance->DR = (*hsai->pBuffPtr++);
905         }
906         else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
907         {
908           hsai->Instance->DR = *((uint16_t *)hsai->pBuffPtr);
909           hsai->pBuffPtr+= 2U;
910         }
911         else
912         {
913           hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
914           hsai->pBuffPtr+= 4U;
915         }
916         hsai->XferCount--;
917       }
918       else
919       {
920         /* Check for the Timeout */
921         if((Timeout != HAL_MAX_DELAY) && ((Timeout == 0U)||((HAL_GetTick() - tickstart) > Timeout)))
922         {
923           /* Update error code */
924           hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
925 
926           /* Clear all the flags */
927           hsai->Instance->CLRFR = 0xFFFFFFFFU;
928 
929           /* Disable SAI peripheral */
930           SAI_Disable(hsai);
931 
932           /* Flush the fifo */
933           SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
934 
935           /* Change the SAI state */
936           hsai->State = HAL_SAI_STATE_READY;
937 
938           /* Process Unlocked */
939           __HAL_UNLOCK(hsai);
940 
941           return HAL_ERROR;
942         }
943       }
944     }
945 
946     hsai->State = HAL_SAI_STATE_READY;
947 
948     /* Process Unlocked */
949     __HAL_UNLOCK(hsai);
950 
951     return HAL_OK;
952   }
953   else
954   {
955     return HAL_BUSY;
956   }
957 }
958 
959 /**
960   * @brief  Receive an amount of data in blocking mode.
961   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
962   *               the configuration information for SAI module.
963   * @param  pData Pointer to data buffer
964   * @param  Size Amount of data to be received
965   * @param  Timeout Timeout duration
966   * @retval HAL status
967   */
HAL_SAI_Receive(SAI_HandleTypeDef * hsai,uint8_t * pData,uint16_t Size,uint32_t Timeout)968 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
969 {
970   uint32_t tickstart = HAL_GetTick();
971 
972   if((pData == NULL ) || (Size == 0))
973   {
974     return  HAL_ERROR;
975   }
976 
977   if(hsai->State == HAL_SAI_STATE_READY)
978   {
979     /* Process Locked */
980     __HAL_LOCK(hsai);
981 
982     hsai->pBuffPtr = pData;
983     hsai->XferSize = Size;
984     hsai->XferCount = Size;
985     hsai->State = HAL_SAI_STATE_BUSY_RX;
986     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
987 
988     /* Check if the SAI is already enabled */
989     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
990     {
991       /* Enable SAI peripheral */
992       __HAL_SAI_ENABLE(hsai);
993     }
994 
995     /* Receive data */
996     while(hsai->XferCount > 0U)
997     {
998       if((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)
999       {
1000         if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1001         {
1002           (*hsai->pBuffPtr++) = hsai->Instance->DR;
1003         }
1004         else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
1005         {
1006           *((uint16_t*)hsai->pBuffPtr) = hsai->Instance->DR;
1007           hsai->pBuffPtr+= 2U;
1008         }
1009         else
1010         {
1011           *((uint32_t*)hsai->pBuffPtr) = hsai->Instance->DR;
1012           hsai->pBuffPtr+= 4U;
1013         }
1014         hsai->XferCount--;
1015       }
1016       else
1017       {
1018         /* Check for the Timeout */
1019         if((Timeout != HAL_MAX_DELAY) && ((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout)))
1020         {
1021           /* Update error code */
1022           hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1023 
1024           /* Clear all the flags */
1025           hsai->Instance->CLRFR = 0xFFFFFFFFU;
1026 
1027           /* Disable SAI peripheral */
1028           SAI_Disable(hsai);
1029 
1030           /* Flush the fifo */
1031           SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1032 
1033           /* Change the SAI state */
1034           hsai->State = HAL_SAI_STATE_READY;
1035 
1036           /* Process Unlocked */
1037           __HAL_UNLOCK(hsai);
1038 
1039           return HAL_ERROR;
1040         }
1041       }
1042     }
1043 
1044     hsai->State = HAL_SAI_STATE_READY;
1045 
1046     /* Process Unlocked */
1047     __HAL_UNLOCK(hsai);
1048 
1049     return HAL_OK;
1050   }
1051   else
1052   {
1053     return HAL_BUSY;
1054   }
1055 }
1056 
1057 /**
1058   * @brief  Transmit an amount of data in non-blocking mode with Interrupt.
1059   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1060   *               the configuration information for SAI module.
1061   * @param  pData Pointer to data buffer
1062   * @param  Size Amount of data to be sent
1063   * @retval HAL status
1064   */
HAL_SAI_Transmit_IT(SAI_HandleTypeDef * hsai,uint8_t * pData,uint16_t Size)1065 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1066 {
1067   if((pData == NULL) || (Size == 0))
1068   {
1069     return  HAL_ERROR;
1070   }
1071 
1072   if(hsai->State == HAL_SAI_STATE_READY)
1073   {
1074     /* Process Locked */
1075     __HAL_LOCK(hsai);
1076 
1077     hsai->pBuffPtr = pData;
1078     hsai->XferSize = Size;
1079     hsai->XferCount = Size;
1080     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1081     hsai->State = HAL_SAI_STATE_BUSY_TX;
1082 
1083     if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1084     {
1085       hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;
1086     }
1087     else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
1088     {
1089       hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;
1090     }
1091     else
1092     {
1093       hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;
1094     }
1095 
1096     /* Fill the fifo before starting the communication */
1097     SAI_FillFifo(hsai);
1098 
1099     /* Enable FRQ and OVRUDR interrupts */
1100     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1101 
1102     /* Check if the SAI is already enabled */
1103     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1104     {
1105       /* Enable SAI peripheral */
1106       __HAL_SAI_ENABLE(hsai);
1107     }
1108     /* Process Unlocked */
1109     __HAL_UNLOCK(hsai);
1110 
1111     return HAL_OK;
1112   }
1113   else
1114   {
1115     return HAL_BUSY;
1116   }
1117 }
1118 
1119 /**
1120   * @brief  Receive an amount of data in non-blocking mode with Interrupt.
1121   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1122   *               the configuration information for SAI module.
1123   * @param  pData Pointer to data buffer
1124   * @param  Size Amount of data to be received
1125   * @retval HAL status
1126   */
HAL_SAI_Receive_IT(SAI_HandleTypeDef * hsai,uint8_t * pData,uint16_t Size)1127 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1128 {
1129   if((pData == NULL) || (Size == 0))
1130   {
1131     return  HAL_ERROR;
1132   }
1133 
1134   if(hsai->State == HAL_SAI_STATE_READY)
1135   {
1136     /* Process Locked */
1137     __HAL_LOCK(hsai);
1138 
1139     hsai->pBuffPtr = pData;
1140     hsai->XferSize = Size;
1141     hsai->XferCount = Size;
1142     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1143     hsai->State = HAL_SAI_STATE_BUSY_RX;
1144 
1145     if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1146     {
1147       hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;
1148     }
1149     else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
1150     {
1151       hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;
1152     }
1153     else
1154     {
1155       hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;
1156     }
1157 
1158     /* Enable TXE and OVRUDR interrupts */
1159     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1160 
1161     /* Check if the SAI is already enabled */
1162     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1163     {
1164       /* Enable SAI peripheral */
1165       __HAL_SAI_ENABLE(hsai);
1166     }
1167 
1168     /* Process Unlocked */
1169     __HAL_UNLOCK(hsai);
1170 
1171     return HAL_OK;
1172   }
1173   else
1174   {
1175     return HAL_BUSY;
1176   }
1177 }
1178 
1179 /**
1180   * @brief Pause the audio stream playing from the Media.
1181   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1182   *               the configuration information for SAI module.
1183   * @retval HAL status
1184   */
HAL_SAI_DMAPause(SAI_HandleTypeDef * hsai)1185 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
1186 {
1187   /* Process Locked */
1188   __HAL_LOCK(hsai);
1189 
1190   /* Pause the audio file playing by disabling the SAI DMA requests */
1191   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1192 
1193   /* Process Unlocked */
1194   __HAL_UNLOCK(hsai);
1195 
1196   return HAL_OK;
1197 }
1198 
1199 /**
1200   * @brief Resume the audio stream playing from the Media.
1201   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1202   *               the configuration information for SAI module.
1203   * @retval HAL status
1204   */
HAL_SAI_DMAResume(SAI_HandleTypeDef * hsai)1205 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
1206 {
1207   /* Process Locked */
1208   __HAL_LOCK(hsai);
1209 
1210   /* Enable the SAI DMA requests */
1211   hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1212 
1213   /* If the SAI peripheral is still not enabled, enable it */
1214   if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1215   {
1216     /* Enable SAI peripheral */
1217     __HAL_SAI_ENABLE(hsai);
1218   }
1219 
1220   /* Process Unlocked */
1221   __HAL_UNLOCK(hsai);
1222 
1223   return HAL_OK;
1224 }
1225 
1226 /**
1227   * @brief Stop the audio stream playing from the Media.
1228   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1229   *               the configuration information for SAI module.
1230   * @retval HAL status
1231   */
HAL_SAI_DMAStop(SAI_HandleTypeDef * hsai)1232 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
1233 {
1234   HAL_StatusTypeDef status = HAL_OK;
1235 
1236   /* Process Locked */
1237   __HAL_LOCK(hsai);
1238 
1239   /* Disable the SAI DMA request */
1240   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1241 
1242   /* Abort the SAI Tx DMA Stream */
1243   if((hsai->hdmatx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_TX))
1244   {
1245     if(HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1246     {
1247       /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1248       if(hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1249       {
1250         status = HAL_ERROR;
1251         hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1252       }
1253     }
1254   }
1255 
1256   /* Abort the SAI Rx DMA Stream */
1257   if((hsai->hdmarx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_RX))
1258   {
1259     if(HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1260     {
1261       /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1262       if(hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1263       {
1264         status = HAL_ERROR;
1265         hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1266       }
1267     }
1268   }
1269 
1270   /* Disable SAI peripheral */
1271   SAI_Disable(hsai);
1272 
1273   /* Flush the fifo */
1274   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1275 
1276   /* Set hsai state to ready */
1277   hsai->State = HAL_SAI_STATE_READY;
1278 
1279   /* Process Unlocked */
1280   __HAL_UNLOCK(hsai);
1281 
1282   return status;
1283 }
1284 
1285 /**
1286   * @brief Abort the current transfer and disable the SAI.
1287   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1288   *               the configuration information for SAI module.
1289   * @retval HAL status
1290   */
HAL_SAI_Abort(SAI_HandleTypeDef * hsai)1291 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
1292 {
1293   HAL_StatusTypeDef status = HAL_OK;
1294 
1295   /* Process Locked */
1296   __HAL_LOCK(hsai);
1297 
1298   /* Check SAI DMA is enabled or not */
1299   if((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1300   {
1301     /* Disable the SAI DMA request */
1302     hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1303 
1304     /* Abort the SAI Tx DMA Stream */
1305     if((hsai->hdmatx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_TX))
1306     {
1307       if(HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1308       {
1309         /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1310         if(hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1311         {
1312           status = HAL_ERROR;
1313           hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1314         }
1315       }
1316     }
1317 
1318     /* Abort the SAI Rx DMA Stream */
1319     if((hsai->hdmarx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_RX))
1320     {
1321       if(HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1322       {
1323         /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1324         if(hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1325         {
1326           status = HAL_ERROR;
1327           hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1328         }
1329       }
1330     }
1331   }
1332 
1333   /* Disabled All interrupt and clear all the flag */
1334   hsai->Instance->IMR = 0U;
1335   hsai->Instance->CLRFR = 0xFFFFFFFFU;
1336 
1337   /* Disable SAI peripheral */
1338   SAI_Disable(hsai);
1339 
1340   /* Flush the fifo */
1341   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1342 
1343   /* Set hsai state to ready */
1344   hsai->State = HAL_SAI_STATE_READY;
1345 
1346   /* Process Unlocked */
1347   __HAL_UNLOCK(hsai);
1348 
1349   return status;
1350 }
1351 
1352 /**
1353   * @brief  Transmit an amount of data in non-blocking mode with DMA.
1354   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1355   *               the configuration information for SAI module.
1356   * @param  pData Pointer to data buffer
1357   * @param  Size Amount of data to be sent
1358   * @retval HAL status
1359   */
HAL_SAI_Transmit_DMA(SAI_HandleTypeDef * hsai,uint8_t * pData,uint16_t Size)1360 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1361 {
1362   if((pData == NULL) || (Size == 0))
1363   {
1364     return  HAL_ERROR;
1365   }
1366 
1367   if(hsai->State == HAL_SAI_STATE_READY)
1368   {
1369     /* Process Locked */
1370     __HAL_LOCK(hsai);
1371 
1372     hsai->pBuffPtr = pData;
1373     hsai->XferSize = Size;
1374     hsai->XferCount = Size;
1375     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1376     hsai->State = HAL_SAI_STATE_BUSY_TX;
1377 
1378     /* Set the SAI Tx DMA Half transfer complete callback */
1379     hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
1380 
1381     /* Set the SAI TxDMA transfer complete callback */
1382     hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
1383 
1384     /* Set the DMA error callback */
1385     hsai->hdmatx->XferErrorCallback = SAI_DMAError;
1386 
1387     /* Set the DMA Tx abort callback */
1388     hsai->hdmatx->XferAbortCallback = NULL;
1389 
1390     /* Enable the Tx DMA Stream */
1391     if(HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK)
1392     {
1393       __HAL_UNLOCK(hsai);
1394       return  HAL_ERROR;
1395     }
1396 
1397     /* Check if the SAI is already enabled */
1398     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1399     {
1400       /* Enable SAI peripheral */
1401       __HAL_SAI_ENABLE(hsai);
1402     }
1403 
1404     /* Enable the interrupts for error handling */
1405     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1406 
1407     /* Enable SAI Tx DMA Request */
1408     hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1409 
1410     /* Process Unlocked */
1411     __HAL_UNLOCK(hsai);
1412 
1413     return HAL_OK;
1414   }
1415   else
1416   {
1417     return HAL_BUSY;
1418   }
1419 }
1420 
1421 /**
1422   * @brief  Receive an amount of data in non-blocking mode with DMA.
1423   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1424   *               the configuration information for SAI module.
1425   * @param  pData Pointer to data buffer
1426   * @param  Size Amount of data to be received
1427   * @retval HAL status
1428   */
HAL_SAI_Receive_DMA(SAI_HandleTypeDef * hsai,uint8_t * pData,uint16_t Size)1429 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1430 {
1431   if((pData == NULL) || (Size == 0))
1432   {
1433     return  HAL_ERROR;
1434   }
1435 
1436   if(hsai->State == HAL_SAI_STATE_READY)
1437   {
1438     /* Process Locked */
1439     __HAL_LOCK(hsai);
1440 
1441     hsai->pBuffPtr = pData;
1442     hsai->XferSize = Size;
1443     hsai->XferCount = Size;
1444     hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1445     hsai->State = HAL_SAI_STATE_BUSY_RX;
1446 
1447     /* Set the SAI Rx DMA Half transfer complete callback */
1448     hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
1449 
1450     /* Set the SAI Rx DMA transfer complete callback */
1451     hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
1452 
1453     /* Set the DMA error callback */
1454     hsai->hdmarx->XferErrorCallback = SAI_DMAError;
1455 
1456     /* Set the DMA Rx abort callback */
1457     hsai->hdmarx->XferAbortCallback = NULL;
1458 
1459     /* Enable the Rx DMA Stream */
1460     if(HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK)
1461     {
1462       __HAL_UNLOCK(hsai);
1463       return  HAL_ERROR;
1464     }
1465 
1466     /* Enable the interrupts for error handling */
1467     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1468 
1469     /* Enable SAI Rx DMA Request */
1470     hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1471 
1472     /* Check if the SAI is already enabled */
1473     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1474     {
1475       /* Enable SAI peripheral */
1476       __HAL_SAI_ENABLE(hsai);
1477     }
1478 
1479     /* Process Unlocked */
1480     __HAL_UNLOCK(hsai);
1481 
1482     return HAL_OK;
1483   }
1484   else
1485   {
1486     return HAL_BUSY;
1487   }
1488 }
1489 
1490 /**
1491   * @brief  Enable the Tx mute mode.
1492   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1493   *               the configuration information for SAI module.
1494   * @param  val  value sent during the mute @ref SAI_Block_Mute_Value
1495   * @retval HAL status
1496   */
HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef * hsai,uint16_t val)1497 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
1498 {
1499   assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));
1500 
1501   if(hsai->State != HAL_SAI_STATE_RESET)
1502   {
1503     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1504     SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | val);
1505     return HAL_OK;
1506   }
1507   return HAL_ERROR;
1508 }
1509 
1510 /**
1511   * @brief  Disable the Tx mute mode.
1512   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1513   *               the configuration information for SAI module.
1514   * @retval HAL status
1515   */
HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef * hsai)1516 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
1517 {
1518   if(hsai->State != HAL_SAI_STATE_RESET)
1519   {
1520     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1521     return HAL_OK;
1522   }
1523   return HAL_ERROR;
1524 }
1525 
1526 /**
1527   * @brief  Enable the Rx mute detection.
1528   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1529   *               the configuration information for SAI module.
1530   * @param  callback function called when the mute is detected.
1531   * @param  counter number a data before mute detection max 63.
1532   * @retval HAL status
1533   */
HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef * hsai,SAIcallback callback,uint16_t counter)1534 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
1535 {
1536   assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));
1537 
1538   if(hsai->State != HAL_SAI_STATE_RESET)
1539   {
1540     /* set the mute counter */
1541     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);
1542     SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos));
1543     hsai->mutecallback = callback;
1544     /* enable the IT interrupt */
1545     __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);
1546     return HAL_OK;
1547   }
1548   return HAL_ERROR;
1549 }
1550 
1551 /**
1552   * @brief  Disable the Rx mute detection.
1553   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1554   *               the configuration information for SAI module.
1555   * @retval HAL status
1556   */
HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef * hsai)1557 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
1558 {
1559   if(hsai->State != HAL_SAI_STATE_RESET)
1560   {
1561     /* set the mutecallback to NULL */
1562     hsai->mutecallback = (SAIcallback)NULL;
1563     /* enable the IT interrupt */
1564     __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);
1565     return HAL_OK;
1566   }
1567   return HAL_ERROR;
1568 }
1569 
1570 /**
1571   * @brief  Handle SAI interrupt request.
1572   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1573   *               the configuration information for SAI module.
1574   * @retval None
1575   */
HAL_SAI_IRQHandler(SAI_HandleTypeDef * hsai)1576 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
1577 {
1578   if(hsai->State != HAL_SAI_STATE_RESET)
1579   {
1580     uint32_t itflags = hsai->Instance->SR;
1581     uint32_t itsources = hsai->Instance->IMR;
1582     uint32_t cr1config = hsai->Instance->CR1;
1583     uint32_t tmperror;
1584 
1585     /* SAI Fifo request interrupt occurred ------------------------------------*/
1586     if(((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ))
1587     {
1588       hsai->InterruptServiceRoutine(hsai);
1589     }
1590     /* SAI Overrun error interrupt occurred ----------------------------------*/
1591     else if(((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))
1592     {
1593       /* Clear the SAI Overrun flag */
1594       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
1595 
1596       /* Get the SAI error code */
1597       tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);
1598 
1599       /* Change the SAI error code */
1600       hsai->ErrorCode |= tmperror;
1601 
1602       /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1603 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1604       hsai->ErrorCallback(hsai);
1605 #else
1606       HAL_SAI_ErrorCallback(hsai);
1607 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1608     }
1609     /* SAI mutedet interrupt occurred ----------------------------------*/
1610     else if(((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))
1611     {
1612       /* Clear the SAI mutedet flag */
1613       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);
1614 
1615       /* call the call back function */
1616       if(hsai->mutecallback != (SAIcallback)NULL)
1617       {
1618         /* inform the user that an RX mute event has been detected */
1619         hsai->mutecallback();
1620       }
1621     }
1622     /* SAI AFSDET interrupt occurred ----------------------------------*/
1623     else if(((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET))
1624     {
1625       /* Clear the SAI AFSDET flag */
1626       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_AFSDET);
1627 
1628       /* Change the SAI error code */
1629       hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET;
1630 
1631       /* Check SAI DMA is enabled or not */
1632       if((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1633       {
1634         /* Abort the SAI DMA Streams */
1635         if(hsai->hdmatx != NULL)
1636         {
1637           /* Set the DMA Tx abort callback */
1638           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1639 
1640           /* Abort DMA in IT mode */
1641           HAL_DMA_Abort_IT(hsai->hdmatx);
1642         }
1643         else if(hsai->hdmarx != NULL)
1644         {
1645           /* Set the DMA Rx abort callback */
1646           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1647 
1648           /* Abort DMA in IT mode */
1649           HAL_DMA_Abort_IT(hsai->hdmarx);
1650         }
1651       }
1652       else
1653       {
1654         /* Abort SAI */
1655         HAL_SAI_Abort(hsai);
1656 
1657         /* Set error callback */
1658 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1659         hsai->ErrorCallback(hsai);
1660 #else
1661         HAL_SAI_ErrorCallback(hsai);
1662 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1663       }
1664     }
1665     /* SAI LFSDET interrupt occurred ----------------------------------*/
1666     else if(((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET))
1667     {
1668       /* Clear the SAI LFSDET flag */
1669       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_LFSDET);
1670 
1671       /* Change the SAI error code */
1672       hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET;
1673 
1674       /* Check SAI DMA is enabled or not */
1675       if((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1676       {
1677         /* Abort the SAI DMA Streams */
1678         if(hsai->hdmatx != NULL)
1679         {
1680           /* Set the DMA Tx abort callback */
1681           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1682 
1683           /* Abort DMA in IT mode */
1684           HAL_DMA_Abort_IT(hsai->hdmatx);
1685         }
1686         else if(hsai->hdmarx != NULL)
1687         {
1688           /* Set the DMA Rx abort callback */
1689           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1690 
1691           /* Abort DMA in IT mode */
1692           HAL_DMA_Abort_IT(hsai->hdmarx);
1693         }
1694       }
1695       else
1696       {
1697         /* Abort SAI */
1698         HAL_SAI_Abort(hsai);
1699 
1700         /* Set error callback */
1701 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1702         hsai->ErrorCallback(hsai);
1703 #else
1704         HAL_SAI_ErrorCallback(hsai);
1705 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1706       }
1707     }
1708     /* SAI WCKCFG interrupt occurred ----------------------------------*/
1709     else if(((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
1710     {
1711       /* Clear the SAI WCKCFG flag */
1712       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_WCKCFG);
1713 
1714       /* Change the SAI error code */
1715       hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG;
1716 
1717       /* Check SAI DMA is enabled or not */
1718       if((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1719       {
1720         /* Abort the SAI DMA Streams */
1721         if(hsai->hdmatx != NULL)
1722         {
1723           /* Set the DMA Tx abort callback */
1724           hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1725 
1726           /* Abort DMA in IT mode */
1727           HAL_DMA_Abort_IT(hsai->hdmatx);
1728         }
1729         else if(hsai->hdmarx != NULL)
1730         {
1731           /* Set the DMA Rx abort callback */
1732           hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1733 
1734           /* Abort DMA in IT mode */
1735           HAL_DMA_Abort_IT(hsai->hdmarx);
1736         }
1737       }
1738       else
1739       {
1740         /* If WCKCFG occurs, SAI audio block is automatically disabled */
1741         /* Disable all interrupts and clear all flags */
1742         hsai->Instance->IMR = 0U;
1743         hsai->Instance->CLRFR = 0xFFFFFFFFU;
1744 
1745         /* Set the SAI state to ready to be able to start again the process */
1746         hsai->State = HAL_SAI_STATE_READY;
1747 
1748         /* Initialize XferCount */
1749         hsai->XferCount = 0U;
1750 
1751         /* SAI error Callback */
1752 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1753         hsai->ErrorCallback(hsai);
1754 #else
1755         HAL_SAI_ErrorCallback(hsai);
1756 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1757       }
1758     }
1759     /* SAI CNRDY interrupt occurred ----------------------------------*/
1760     else if(((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY))
1761     {
1762       /* Clear the SAI CNRDY flag */
1763       __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY);
1764 
1765       /* Change the SAI error code */
1766       hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY;
1767 
1768       /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1769 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1770       hsai->ErrorCallback(hsai);
1771 #else
1772       HAL_SAI_ErrorCallback(hsai);
1773 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1774     }
1775     else
1776     {
1777       /* Nothing to do */
1778     }
1779   }
1780 }
1781 
1782 /**
1783   * @brief Tx Transfer completed callback.
1784   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1785   *                the configuration information for SAI module.
1786   * @retval None
1787   */
HAL_SAI_TxCpltCallback(SAI_HandleTypeDef * hsai)1788 __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
1789 {
1790   /* Prevent unused argument(s) compilation warning */
1791   UNUSED(hsai);
1792 
1793   /* NOTE : This function should not be modified, when the callback is needed,
1794             the HAL_SAI_TxCpltCallback could be implemented in the user file
1795    */
1796 }
1797 
1798 /**
1799   * @brief Tx Transfer Half completed callback.
1800   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1801   *               the configuration information for SAI module.
1802   * @retval None
1803   */
HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef * hsai)1804 __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
1805 {
1806   /* Prevent unused argument(s) compilation warning */
1807   UNUSED(hsai);
1808 
1809   /* NOTE : This function should not be modified, when the callback is needed,
1810             the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
1811    */
1812 }
1813 
1814 /**
1815   * @brief Rx Transfer completed callback.
1816   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1817   *               the configuration information for SAI module.
1818   * @retval None
1819   */
HAL_SAI_RxCpltCallback(SAI_HandleTypeDef * hsai)1820 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
1821 {
1822   /* Prevent unused argument(s) compilation warning */
1823   UNUSED(hsai);
1824 
1825   /* NOTE : This function should not be modified, when the callback is needed,
1826             the HAL_SAI_RxCpltCallback could be implemented in the user file
1827    */
1828 }
1829 
1830 /**
1831   * @brief Rx Transfer half completed callback.
1832   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1833   *               the configuration information for SAI module.
1834   * @retval None
1835   */
HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef * hsai)1836 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
1837 {
1838   /* Prevent unused argument(s) compilation warning */
1839   UNUSED(hsai);
1840 
1841   /* NOTE : This function should not be modified, when the callback is needed,
1842             the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
1843    */
1844 }
1845 
1846 /**
1847   * @brief SAI error callback.
1848   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1849   *               the configuration information for SAI module.
1850   * @retval None
1851   */
HAL_SAI_ErrorCallback(SAI_HandleTypeDef * hsai)1852 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
1853 {
1854   /* Prevent unused argument(s) compilation warning */
1855   UNUSED(hsai);
1856 
1857   /* NOTE : This function should not be modified, when the callback is needed,
1858             the HAL_SAI_ErrorCallback could be implemented in the user file
1859    */
1860 }
1861 
1862 /**
1863   * @}
1864   */
1865 
1866 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions
1867   * @brief    Peripheral State functions
1868   *
1869 @verbatim
1870  ===============================================================================
1871                 ##### Peripheral State and Errors functions #####
1872  ===============================================================================
1873   [..]
1874     This subsection permits to get in run-time the status of the peripheral
1875     and the data flow.
1876 
1877 @endverbatim
1878   * @{
1879   */
1880 
1881 /**
1882   * @brief  Return the SAI handle state.
1883   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1884   *               the configuration information for SAI module.
1885   * @retval HAL state
1886   */
HAL_SAI_GetState(SAI_HandleTypeDef * hsai)1887 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai)
1888 {
1889   return hsai->State;
1890 }
1891 
1892 /**
1893   * @brief  Return the SAI error code.
1894   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1895   *              the configuration information for the specified SAI Block.
1896   * @retval SAI Error Code
1897   */
HAL_SAI_GetError(SAI_HandleTypeDef * hsai)1898 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai)
1899 {
1900   return hsai->ErrorCode;
1901 }
1902 /**
1903   * @}
1904   */
1905 
1906 /**
1907   * @}
1908   */
1909 
1910 /** @addtogroup SAI_Private_Functions
1911   * @brief      Private functions
1912   * @{
1913   */
1914 
1915 /**
1916   * @brief  Initialize the SAI I2S protocol according to the specified parameters
1917   *         in the SAI_InitTypeDef and create the associated handle.
1918   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
1919   *               the configuration information for SAI module.
1920   * @param  protocol one of the supported protocol.
1921   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize
1922   *                the configuration information for SAI module.
1923   * @param  nbslot number of slot minimum value is 2 and max is 16.
1924   *                    the value must be a multiple of 2.
1925   * @retval HAL status
1926   */
SAI_InitI2S(SAI_HandleTypeDef * hsai,uint32_t protocol,uint32_t datasize,uint32_t nbslot)1927 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
1928 {
1929   hsai->Init.Protocol            = SAI_FREE_PROTOCOL;
1930   hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;
1931   /* Compute ClockStrobing according AudioMode */
1932   if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
1933   { /* Transmit */
1934     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_FALLINGEDGE;
1935   }
1936   else
1937   { /* Receive */
1938     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_RISINGEDGE;
1939   }
1940   hsai->FrameInit.FSDefinition   = SAI_FS_CHANNEL_IDENTIFICATION;
1941   hsai->SlotInit.SlotActive      = SAI_SLOTACTIVE_ALL;
1942   hsai->SlotInit.FirstBitOffset  = 0U;
1943   hsai->SlotInit.SlotNumber      = nbslot;
1944 
1945   /* in IS2 the number of slot must be even */
1946   if((nbslot & 0x1U) != 0U)
1947   {
1948     return HAL_ERROR;
1949   }
1950 
1951   if (protocol == SAI_I2S_STANDARD)
1952   {
1953     hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
1954     hsai->FrameInit.FSOffset   = SAI_FS_BEFOREFIRSTBIT;
1955   }
1956   else
1957   {
1958      /* SAI_I2S_MSBJUSTIFIED or SAI_I2S_LSBJUSTIFIED */
1959     hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
1960     hsai->FrameInit.FSOffset   = SAI_FS_FIRSTBIT;
1961   }
1962 
1963   /* Frame definition */
1964   switch(datasize)
1965   {
1966   case SAI_PROTOCOL_DATASIZE_16BIT:
1967     hsai->Init.DataSize = SAI_DATASIZE_16;
1968     hsai->FrameInit.FrameLength = 32U*(nbslot/2U);
1969     hsai->FrameInit.ActiveFrameLength = 16U*(nbslot/2U);
1970     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
1971     break;
1972   case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
1973     hsai->Init.DataSize = SAI_DATASIZE_16;
1974     hsai->FrameInit.FrameLength = 64U*(nbslot/2U);
1975     hsai->FrameInit.ActiveFrameLength = 32U*(nbslot/2U);
1976     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
1977     break;
1978   case SAI_PROTOCOL_DATASIZE_24BIT:
1979     hsai->Init.DataSize = SAI_DATASIZE_24;
1980     hsai->FrameInit.FrameLength = 64U*(nbslot/2U);
1981     hsai->FrameInit.ActiveFrameLength = 32U*(nbslot/2U);
1982     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
1983     break;
1984   case SAI_PROTOCOL_DATASIZE_32BIT:
1985     hsai->Init.DataSize = SAI_DATASIZE_32;
1986     hsai->FrameInit.FrameLength = 64U*(nbslot/2U);
1987     hsai->FrameInit.ActiveFrameLength = 32U*(nbslot/2U);
1988     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
1989     break;
1990   default :
1991     return HAL_ERROR;
1992   }
1993   if(protocol == SAI_I2S_LSBJUSTIFIED)
1994   {
1995     if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
1996     {
1997       hsai->SlotInit.FirstBitOffset = 16U;
1998     }
1999     if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
2000     {
2001       hsai->SlotInit.FirstBitOffset = 8U;
2002     }
2003   }
2004   return HAL_OK;
2005 }
2006 
2007 /**
2008   * @brief  Initialize the SAI PCM protocol according to the specified parameters
2009   *         in the SAI_InitTypeDef and create the associated handle.
2010   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2011   *               the configuration information for SAI module.
2012   * @param  protocol one of the supported protocol
2013   * @param  datasize one of the supported datasize @ref SAI_Protocol_DataSize
2014   * @param  nbslot number of slot minimum value is 1 and the max is 16.
2015   * @retval HAL status
2016   */
SAI_InitPCM(SAI_HandleTypeDef * hsai,uint32_t protocol,uint32_t datasize,uint32_t nbslot)2017 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2018 {
2019   hsai->Init.Protocol            = SAI_FREE_PROTOCOL;
2020   hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;
2021   /* Compute ClockStrobing according AudioMode */
2022   if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2023   { /* Transmit */
2024     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_RISINGEDGE;
2025   }
2026   else
2027   { /* Receive */
2028     hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_FALLINGEDGE;
2029   }
2030   hsai->FrameInit.FSDefinition   = SAI_FS_STARTFRAME;
2031   hsai->FrameInit.FSPolarity     = SAI_FS_ACTIVE_HIGH;
2032   hsai->FrameInit.FSOffset       = SAI_FS_BEFOREFIRSTBIT;
2033   hsai->SlotInit.FirstBitOffset  = 0U;
2034   hsai->SlotInit.SlotNumber      = nbslot;
2035   hsai->SlotInit.SlotActive      = SAI_SLOTACTIVE_ALL;
2036 
2037   if (protocol == SAI_PCM_SHORT)
2038   {
2039     hsai->FrameInit.ActiveFrameLength = 1;
2040   }
2041   else
2042   {
2043     /* SAI_PCM_LONG */
2044     hsai->FrameInit.ActiveFrameLength = 13;
2045   }
2046 
2047   switch(datasize)
2048   {
2049   case SAI_PROTOCOL_DATASIZE_16BIT:
2050     hsai->Init.DataSize = SAI_DATASIZE_16;
2051     hsai->FrameInit.FrameLength = 16U * nbslot;
2052     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2053     break;
2054   case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2055     hsai->Init.DataSize = SAI_DATASIZE_16;
2056     hsai->FrameInit.FrameLength = 32U * nbslot;
2057     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2058     break;
2059   case SAI_PROTOCOL_DATASIZE_24BIT :
2060     hsai->Init.DataSize = SAI_DATASIZE_24;
2061     hsai->FrameInit.FrameLength = 32U * nbslot;
2062     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2063     break;
2064   case SAI_PROTOCOL_DATASIZE_32BIT:
2065     hsai->Init.DataSize = SAI_DATASIZE_32;
2066     hsai->FrameInit.FrameLength = 32U * nbslot;
2067     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2068     break;
2069   default :
2070     return HAL_ERROR;
2071   }
2072 
2073   return HAL_OK;
2074 }
2075 
2076 /**
2077   * @brief  Fill the fifo.
2078   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2079   *               the configuration information for SAI module.
2080   * @retval None
2081   */
SAI_FillFifo(SAI_HandleTypeDef * hsai)2082 static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
2083 {
2084   /* fill the fifo with data before to enabled the SAI */
2085   while(((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U))
2086   {
2087     if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
2088     {
2089       hsai->Instance->DR = (*hsai->pBuffPtr++);
2090     }
2091     else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
2092     {
2093       hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
2094       hsai->pBuffPtr+= 2U;
2095     }
2096     else
2097     {
2098       hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
2099       hsai->pBuffPtr+= 4U;
2100     }
2101     hsai->XferCount--;
2102   }
2103 }
2104 
2105 /**
2106   * @brief  Return the interrupt flag to set according the SAI setup.
2107   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2108   *               the configuration information for SAI module.
2109   * @param  mode SAI_MODE_DMA or SAI_MODE_IT
2110   * @retval the list of the IT flag to enable
2111  */
SAI_InterruptFlag(SAI_HandleTypeDef * hsai,uint32_t mode)2112 static uint32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode)
2113 {
2114   uint32_t tmpIT = SAI_IT_OVRUDR;
2115 
2116   if(mode == SAI_MODE_IT)
2117   {
2118     tmpIT|= SAI_IT_FREQ;
2119   }
2120 
2121   if((hsai->Init.Protocol == SAI_AC97_PROTOCOL) &&
2122     ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX)))
2123   {
2124     tmpIT|= SAI_IT_CNRDY;
2125   }
2126 
2127   if((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2128   {
2129     tmpIT|= SAI_IT_AFSDET | SAI_IT_LFSDET;
2130   }
2131   else
2132   {
2133     /* hsai has been configured in master mode */
2134     tmpIT|= SAI_IT_WCKCFG;
2135   }
2136   return tmpIT;
2137 }
2138 
2139 /**
2140   * @brief  Disable the SAI and wait for the disabling.
2141   * @param  hsai  pointer to a SAI_HandleTypeDef structure that contains
2142   *               the configuration information for SAI module.
2143   * @retval None
2144   */
SAI_Disable(SAI_HandleTypeDef * hsai)2145 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
2146 {
2147   register uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock /7U/1000U);
2148   HAL_StatusTypeDef status = HAL_OK;
2149 
2150   /* Disable the SAI instance */
2151   __HAL_SAI_DISABLE(hsai);
2152 
2153   do
2154   {
2155     /* Check for the Timeout */
2156     if (count-- == 0U)
2157     {
2158       /* Update error code */
2159       hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
2160       status = HAL_TIMEOUT;
2161       break;
2162     }
2163   } while((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != RESET);
2164 
2165   return status;
2166 }
2167 
2168 /**
2169   * @brief  Tx Handler for Transmit in Interrupt mode 8-Bit transfer.
2170   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2171   *               the configuration information for SAI module.
2172   * @retval None
2173   */
SAI_Transmit_IT8Bit(SAI_HandleTypeDef * hsai)2174 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
2175 {
2176   if(hsai->XferCount == 0U)
2177   {
2178     /* Handle the end of the transmission */
2179     /* Disable FREQ and OVRUDR interrupts */
2180     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2181     hsai->State = HAL_SAI_STATE_READY;
2182 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2183     hsai->TxCpltCallback(hsai);
2184 #else
2185     HAL_SAI_TxCpltCallback(hsai);
2186 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2187   }
2188   else
2189   {
2190     /* Write data on DR register */
2191     hsai->Instance->DR = (*hsai->pBuffPtr++);
2192     hsai->XferCount--;
2193   }
2194 }
2195 
2196 /**
2197   * @brief  Tx Handler for Transmit in Interrupt mode for 16-Bit transfer.
2198   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2199   *               the configuration information for SAI module.
2200   * @retval None
2201   */
SAI_Transmit_IT16Bit(SAI_HandleTypeDef * hsai)2202 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
2203 {
2204   if(hsai->XferCount == 0U)
2205   {
2206     /* Handle the end of the transmission */
2207     /* Disable FREQ and OVRUDR interrupts */
2208     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2209     hsai->State = HAL_SAI_STATE_READY;
2210 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2211     hsai->TxCpltCallback(hsai);
2212 #else
2213     HAL_SAI_TxCpltCallback(hsai);
2214 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2215   }
2216   else
2217   {
2218     /* Write data on DR register */
2219     hsai->Instance->DR = *(uint16_t *)hsai->pBuffPtr;
2220     hsai->pBuffPtr+=2U;
2221     hsai->XferCount--;
2222   }
2223 }
2224 
2225 /**
2226   * @brief  Tx Handler for Transmit in Interrupt mode for 32-Bit transfer.
2227   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2228   *               the configuration information for SAI module.
2229   * @retval None
2230   */
SAI_Transmit_IT32Bit(SAI_HandleTypeDef * hsai)2231 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
2232 {
2233   if(hsai->XferCount == 0U)
2234   {
2235     /* Handle the end of the transmission */
2236     /* Disable FREQ and OVRUDR interrupts */
2237     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2238     hsai->State = HAL_SAI_STATE_READY;
2239 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2240     hsai->TxCpltCallback(hsai);
2241 #else
2242     HAL_SAI_TxCpltCallback(hsai);
2243 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2244   }
2245   else
2246   {
2247     /* Write data on DR register */
2248     hsai->Instance->DR = *(uint32_t *)hsai->pBuffPtr;
2249     hsai->pBuffPtr+=4U;
2250     hsai->XferCount--;
2251   }
2252 }
2253 
2254 /**
2255   * @brief  Rx Handler for Receive in Interrupt mode 8-Bit transfer.
2256   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2257   *               the configuration information for SAI module.
2258   * @retval None
2259   */
SAI_Receive_IT8Bit(SAI_HandleTypeDef * hsai)2260 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
2261 {
2262   /* Receive data */
2263   (*hsai->pBuffPtr++) = hsai->Instance->DR;
2264   hsai->XferCount--;
2265 
2266   /* Check end of the transfer */
2267   if(hsai->XferCount == 0U)
2268   {
2269     /* Disable TXE and OVRUDR interrupts */
2270     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2271 
2272     /* Clear the SAI Overrun flag */
2273     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2274 
2275     hsai->State = HAL_SAI_STATE_READY;
2276 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2277     hsai->RxCpltCallback(hsai);
2278 #else
2279     HAL_SAI_RxCpltCallback(hsai);
2280 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2281   }
2282 }
2283 
2284 /**
2285   * @brief  Rx Handler for Receive in Interrupt mode for 16-Bit transfer.
2286   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2287   *               the configuration information for SAI module.
2288   * @retval None
2289   */
SAI_Receive_IT16Bit(SAI_HandleTypeDef * hsai)2290 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
2291 {
2292   /* Receive data */
2293   *(uint16_t*)hsai->pBuffPtr = hsai->Instance->DR;
2294   hsai->pBuffPtr+=2U;
2295   hsai->XferCount--;
2296 
2297   /* Check end of the transfer */
2298   if(hsai->XferCount == 0U)
2299   {
2300     /* Disable TXE and OVRUDR interrupts */
2301     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2302 
2303     /* Clear the SAI Overrun flag */
2304     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2305 
2306     hsai->State = HAL_SAI_STATE_READY;
2307 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2308     hsai->RxCpltCallback(hsai);
2309 #else
2310     HAL_SAI_RxCpltCallback(hsai);
2311 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2312   }
2313 }
2314 
2315 /**
2316   * @brief  Rx Handler for Receive in Interrupt mode for 32-Bit transfer.
2317   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
2318   *               the configuration information for SAI module.
2319   * @retval None
2320   */
SAI_Receive_IT32Bit(SAI_HandleTypeDef * hsai)2321 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
2322 {
2323   /* Receive data */
2324   *(uint32_t*)hsai->pBuffPtr = hsai->Instance->DR;
2325   hsai->pBuffPtr+=4U;
2326   hsai->XferCount--;
2327 
2328   /* Check end of the transfer */
2329   if(hsai->XferCount == 0U)
2330   {
2331     /* Disable TXE and OVRUDR interrupts */
2332     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2333 
2334     /* Clear the SAI Overrun flag */
2335     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2336 
2337     hsai->State = HAL_SAI_STATE_READY;
2338 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2339     hsai->RxCpltCallback(hsai);
2340 #else
2341     HAL_SAI_RxCpltCallback(hsai);
2342 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2343   }
2344 }
2345 
2346 /**
2347   * @brief DMA SAI transmit process complete callback.
2348   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
2349   *               the configuration information for the specified DMA module.
2350   * @retval None
2351   */
SAI_DMATxCplt(DMA_HandleTypeDef * hdma)2352 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
2353 {
2354   SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef* )hdma)->Parent;
2355 
2356   if (hdma->Init.Mode != DMA_CIRCULAR)
2357   {
2358     hsai->XferCount = 0U;
2359 
2360     /* Disable SAI Tx DMA Request */
2361     hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2362 
2363     /* Stop the interrupts error handling */
2364     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2365 
2366     hsai->State= HAL_SAI_STATE_READY;
2367   }
2368 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2369   hsai->TxCpltCallback(hsai);
2370 #else
2371   HAL_SAI_TxCpltCallback(hsai);
2372 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2373 }
2374 
2375 /**
2376   * @brief DMA SAI transmit process half complete callback.
2377   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
2378   *               the configuration information for the specified DMA module.
2379   * @retval None
2380   */
SAI_DMATxHalfCplt(DMA_HandleTypeDef * hdma)2381 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
2382 {
2383   SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
2384 
2385 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2386   hsai->TxHalfCpltCallback(hsai);
2387 #else
2388   HAL_SAI_TxHalfCpltCallback(hsai);
2389 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2390 }
2391 
2392 /**
2393   * @brief DMA SAI receive process complete callback.
2394   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
2395   *               the configuration information for the specified DMA module.
2396   * @retval None
2397   */
SAI_DMARxCplt(DMA_HandleTypeDef * hdma)2398 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
2399 {
2400   SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
2401 
2402   if (hdma->Init.Mode != DMA_CIRCULAR)
2403   {
2404     /* Disable Rx DMA Request */
2405     hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2406     hsai->XferCount = 0U;
2407 
2408     /* Stop the interrupts error handling */
2409     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2410 
2411     hsai->State = HAL_SAI_STATE_READY;
2412   }
2413 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2414   hsai->RxCpltCallback(hsai);
2415 #else
2416   HAL_SAI_RxCpltCallback(hsai);
2417 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2418 }
2419 
2420 /**
2421   * @brief DMA SAI receive process half complete callback
2422   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
2423   *               the configuration information for the specified DMA module.
2424   * @retval None
2425   */
SAI_DMARxHalfCplt(DMA_HandleTypeDef * hdma)2426 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
2427 {
2428   SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
2429 
2430 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2431   hsai->RxHalfCpltCallback(hsai);
2432 #else
2433   HAL_SAI_RxHalfCpltCallback(hsai);
2434 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2435 }
2436 
2437 /**
2438   * @brief DMA SAI communication error callback.
2439   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
2440   *               the configuration information for the specified DMA module.
2441   * @retval None
2442   */
SAI_DMAError(DMA_HandleTypeDef * hdma)2443 static void SAI_DMAError(DMA_HandleTypeDef *hdma)
2444 {
2445   SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
2446 
2447   /* Set SAI error code */
2448   hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2449 
2450   if((hsai->hdmatx->ErrorCode == HAL_DMA_ERROR_TE) || (hsai->hdmarx->ErrorCode == HAL_DMA_ERROR_TE))
2451   {
2452     /* Disable the SAI DMA request */
2453     hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2454 
2455     /* Disable SAI peripheral */
2456     SAI_Disable(hsai);
2457 
2458     /* Set the SAI state ready to be able to start again the process */
2459     hsai->State = HAL_SAI_STATE_READY;
2460 
2461     /* Initialize XferCount */
2462     hsai->XferCount = 0U;
2463   }
2464   /* SAI error Callback */
2465 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2466   hsai->ErrorCallback(hsai);
2467 #else
2468   HAL_SAI_ErrorCallback(hsai);
2469 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2470 }
2471 
2472 /**
2473   * @brief  DMA SAI Abort callback.
2474   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
2475   *               the configuration information for the specified DMA module.
2476   * @retval None
2477   */
SAI_DMAAbort(DMA_HandleTypeDef * hdma)2478 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma)
2479 {
2480   SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
2481 
2482   /* Disable DMA request */
2483   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2484 
2485   /* Disable all interrupts and clear all flags */
2486   hsai->Instance->IMR = 0U;
2487   hsai->Instance->CLRFR = 0xFFFFFFFFU;
2488 
2489   if(hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG)
2490   {
2491     /* Disable SAI peripheral */
2492     SAI_Disable(hsai);
2493 
2494     /* Flush the fifo */
2495     SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
2496   }
2497   /* Set the SAI state to ready to be able to start again the process */
2498   hsai->State = HAL_SAI_STATE_READY;
2499 
2500   /* Initialize XferCount */
2501   hsai->XferCount = 0U;
2502 
2503   /* SAI error Callback */
2504 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2505   hsai->ErrorCallback(hsai);
2506 #else
2507   HAL_SAI_ErrorCallback(hsai);
2508 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2509 }
2510 
2511 /**
2512   * @}
2513   */
2514 
2515 #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */
2516 #endif /* HAL_SAI_MODULE_ENABLED */
2517 /**
2518   * @}
2519   */
2520 
2521 /**
2522   * @}
2523   */
2524 
2525 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
2526