]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M7_STM32F7_STM32756G-EVAL_IAR_Keil/ST_Library/stm32f7xx_hal_sai.c
Final V8.2.1 release ready for tagging:
[freertos] / FreeRTOS / Demo / CORTEX_M7_STM32F7_STM32756G-EVAL_IAR_Keil / ST_Library / stm32f7xx_hal_sai.c
1 /**\r
2   ******************************************************************************\r
3   * @file    stm32f7xx_hal_sai.c\r
4   * @author  MCD Application Team\r
5   * @version V1.0.0RC1\r
6   * @date    24-March-2015\r
7   * @brief   SAI HAL module driver.\r
8   *          This file provides firmware functions to manage the following \r
9   *          functionalities of the Serial Audio Interface (SAI) peripheral:\r
10   *           + Initialization/de-initialization functions\r
11   *           + I/O operation functions\r
12   *           + Peripheral Control functions \r
13   *           + Peripheral State functions\r
14   *         \r
15   @verbatim\r
16  ==============================================================================\r
17                   ##### How to use this driver #####\r
18   ==============================================================================\r
19            \r
20   [..]\r
21     The SAI HAL driver can be used as follows:\r
22     \r
23     (#) Declare a SAI_HandleTypeDef handle structure.\r
24     (#) Initialize the SAI low level resources by implementing the HAL_SAI_MspInit() API:\r
25         (##) Enable the SAI interface clock.                      \r
26         (##) SAI pins configuration:\r
27             (+++) Enable the clock for the SAI GPIOs.\r
28             (+++) Configure these SAI pins as alternate function pull-up.\r
29         (##) NVIC configuration if you need to use interrupt process (HAL_SAI_Transmit_IT()\r
30              and HAL_SAI_Receive_IT() APIs):\r
31             (+++) Configure the SAI interrupt priority.\r
32             (+++) Enable the NVIC SAI IRQ handle.\r
33 \r
34         (##) DMA Configuration if you need to use DMA process (HAL_SAI_Transmit_DMA()\r
35              and HAL_SAI_Receive_DMA() APIs):\r
36             (+++) Declare a DMA handle structure for the Tx/Rx stream.\r
37             (+++) Enable the DMAx interface clock.\r
38             (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.                \r
39             (+++) Configure the DMA Tx/Rx Stream.\r
40             (+++) Associate the initialized DMA handle to the SAI DMA Tx/Rx handle.\r
41             (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the \r
42                 DMA Tx/Rx Stream.\r
43   \r
44    (#) Program the SAI Mode, Standard, Data Format, MCLK Output, Audio frequency and Polarity\r
45        using HAL_SAI_Init() function.\r
46    \r
47    -@- The specific SAI interrupts (FIFO request and Overrun underrun interrupt)\r
48        will be managed using the macros __SAI_ENABLE_IT() and __SAI_DISABLE_IT()\r
49        inside the transmit and receive process.   \r
50 \r
51   [..]           \r
52    (@) SAI Clock Source, the configuration is managed through RCCEx_PeriphCLKConfig()\r
53             function in the HAL RCC drivers        \r
54   [..]           \r
55    (@) Make sure that either:\r
56        (+@) I2S PLL is configured or \r
57        (+@) SAI PLL is configured or \r
58        (+@) External clock source is configured after setting correctly \r
59             the define constant EXTERNAL_CLOCK_VALUE in the stm32f7xx_hal_conf.h file. \r
60                         \r
61   [..]           \r
62     (@) In master Tx mode: enabling the audio block immediately generates the bit clock \r
63         for the external slaves even if there is no data in the FIFO, However FS signal \r
64         generation is conditioned by the presence of data in the FIFO.\r
65                  \r
66   [..]           \r
67     (@) In master Rx mode: enabling the audio block immediately generates the bit clock \r
68         and FS signal for the external slaves. \r
69                 \r
70   [..]           \r
71     (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior: \r
72         (+@)  First bit Offset <= (SLOT size - Data size)\r
73         (+@)  Data size <= SLOT size\r
74         (+@)  Number of SLOT x SLOT size = Frame length\r
75         (+@)  The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected.  \r
76 \r
77   [..]         \r
78      Three operation modes are available within this driver :     \r
79   \r
80    *** Polling mode IO operation ***\r
81    =================================\r
82    [..]    \r
83      (+) Send an amount of data in blocking mode using HAL_SAI_Transmit() \r
84      (+) Receive an amount of data in blocking mode using HAL_SAI_Receive()\r
85    \r
86    *** Interrupt mode IO operation ***    \r
87    ===================================\r
88    [..]    \r
89      (+) Send an amount of data in non blocking mode using HAL_SAI_Transmit_IT() \r
90      (+) At transmission end of transfer HAL_SAI_TxCpltCallback is executed and user can \r
91          add his own code by customization of function pointer HAL_SAI_TxCpltCallback\r
92      (+) Receive an amount of data in non blocking mode using HAL_SAI_Receive_IT() \r
93      (+) At reception end of transfer HAL_SAI_RxCpltCallback is executed and user can \r
94          add his own code by customization of function pointer HAL_SAI_RxCpltCallback                                      \r
95      (+) In case of transfer Error, HAL_SAI_ErrorCallback() function is executed and user can \r
96          add his own code by customization of function pointer HAL_SAI_ErrorCallback\r
97 \r
98    *** DMA mode IO operation ***    \r
99    ==============================\r
100    [..] \r
101      (+) Send an amount of data in non blocking mode (DMA) using HAL_SAI_Transmit_DMA() \r
102      (+) At transmission end of transfer HAL_SAI_TxCpltCallback is executed and user can \r
103          add his own code by customization of function pointer HAL_SAI_TxCpltCallback\r
104      (+) Receive an amount of data in non blocking mode (DMA) using HAL_SAI_Receive_DMA() \r
105      (+) At reception end of transfer HAL_SAI_RxCpltCallback is executed and user can \r
106          add his own code by customization of function pointer HAL_SAI_RxCpltCallback                                  \r
107      (+) In case of transfer Error, HAL_SAI_ErrorCallback() function is executed and user can \r
108          add his own code by customization of function pointer HAL_SAI_ErrorCallback\r
109      (+) Pause the DMA Transfer using HAL_SAI_DMAPause()      \r
110      (+) Resume the DMA Transfer using HAL_SAI_DMAResume()  \r
111      (+) Stop the DMA Transfer using HAL_SAI_DMAStop()      \r
112    \r
113    *** SAI HAL driver macros list ***\r
114    ============================================= \r
115    [..]\r
116      Below the list of most used macros in USART HAL driver :\r
117        \r
118       (+) __HAL_SAI_ENABLE: Enable the SAI peripheral\r
119       (+) __HAL_SAI_DISABLE: Disable the SAI peripheral\r
120       (+) __HAL_SAI_ENABLE_IT : Enable the specified SAI interrupts\r
121       (+) __HAL_SAI_DISABLE_IT : Disable the specified SAI interrupts\r
122       (+) __HAL_SAI_GET_IT_SOURCE: Check if the specified SAI interrupt source is \r
123           enabled or disabled\r
124       (+) __HAL_SAI_GET_FLAG: Check whether the specified SAI flag is set or not\r
125   \r
126   @endverbatim\r
127   ******************************************************************************\r
128   * @attention\r
129   *\r
130   * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>\r
131   *\r
132   * Redistribution and use in source and binary forms, with or without modification,\r
133   * are permitted provided that the following conditions are met:\r
134   *   1. Redistributions of source code must retain the above copyright notice,\r
135   *      this list of conditions and the following disclaimer.\r
136   *   2. Redistributions in binary form must reproduce the above copyright notice,\r
137   *      this list of conditions and the following disclaimer in the documentation\r
138   *      and/or other materials provided with the distribution.\r
139   *   3. Neither the name of STMicroelectronics nor the names of its contributors\r
140   *      may be used to endorse or promote products derived from this software\r
141   *      without specific prior written permission.\r
142   *\r
143   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
144   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
145   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
146   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
147   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
148   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
149   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
150   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
151   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
152   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
153   *\r
154   ******************************************************************************\r
155   */ \r
156 \r
157 /* Includes ------------------------------------------------------------------*/\r
158 #include "stm32f7xx_hal.h"\r
159 \r
160 /** @addtogroup STM32F7xx_HAL_Driver\r
161   * @{\r
162   */\r
163 \r
164 /** @defgroup SAI SAI\r
165   * @brief SAI HAL module driver\r
166   * @{\r
167   */\r
168 \r
169 #ifdef HAL_SAI_MODULE_ENABLED\r
170 \r
171 /* Private typedef -----------------------------------------------------------*/\r
172 /** @defgroup SAI_Private_Typedefs  SAI Private Typedefs\r
173   * @{\r
174   */\r
175 typedef enum {\r
176   SAI_MODE_DMA,\r
177   SAI_MODE_IT\r
178 }SAI_ModeTypedef;\r
179 /**\r
180   * @}\r
181   */\r
182 /* Private define ------------------------------------------------------------*/\r
183 /** @defgroup SAI_Private_Constants  SAI Private Constants\r
184   * @{\r
185   */\r
186 #define SAI_FIFO_SIZE       8\r
187 #define SAI_DEFAULT_TIMEOUT 4\r
188 /**\r
189   * @}\r
190   */\r
191 \r
192 /* SAI registers Masks */\r
193 #define CR1_CLEAR_MASK            ((uint32_t)0xFF04C010)\r
194 #define FRCR_CLEAR_MASK           ((uint32_t)0xFFF88000)\r
195 #define SLOTR_CLEAR_MASK          ((uint32_t)0x0000F020)\r
196 \r
197 #define SAI_TIMEOUT_VALUE         10\r
198 /* Private macro -------------------------------------------------------------*/\r
199 /* Private variables ---------------------------------------------------------*/\r
200 /* Private function prototypes -----------------------------------------------*/\r
201 static void SAI_FillFifo(SAI_HandleTypeDef *hsai);\r
202 static uint32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode);\r
203 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);\r
204 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);\r
205 \r
206 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);\r
207 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);\r
208 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);\r
209 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);\r
210 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);\r
211 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);\r
212 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);\r
213 \r
214 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);\r
215 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);\r
216 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);\r
217 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);\r
218 static void SAI_DMAError(DMA_HandleTypeDef *hdma);\r
219 \r
220 /* Exported functions ---------------------------------------------------------*/\r
221 \r
222 /** @defgroup SAI_Exported_Functions  SAI Exported Functions\r
223   * @{\r
224   */\r
225 \r
226 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions \r
227  *  @brief    Initialization and Configuration functions \r
228  *\r
229 @verbatim    \r
230  ===============================================================================\r
231               ##### Initialization and de-initialization functions #####\r
232  ===============================================================================\r
233     [..]  This subsection provides a set of functions allowing to initialize and \r
234           de-initialize the SAIx peripheral:\r
235 \r
236       (+) User must implement HAL_SAI_MspInit() function in which he configures \r
237           all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).\r
238 \r
239       (+) Call the function HAL_SAI_Init() to configure the selected device with \r
240           the selected configuration:\r
241         (++) Mode (Master/slave TX/RX)\r
242         (++) Protocol \r
243         (++) Data Size\r
244         (++) MCLK Output\r
245         (++) Audio frequency\r
246         (++) FIFO Threshold\r
247         (++) Frame Config\r
248         (++) Slot Config\r
249 \r
250       (+) Call the function HAL_SAI_DeInit() to restore the default configuration \r
251           of the selected SAI peripheral.     \r
252 \r
253 @endverbatim\r
254   * @{\r
255   */\r
256 \r
257 /**\r
258   * @brief  Initializes the structure FrameInit, SlotInit and the low part of \r
259   *         Init according to the specified parameters and call the function\r
260   *         HAL_SAI_Init to initialize the SAI block.\r
261   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains \r
262   *               the configuration information for SAI module.\r
263   * @param  protocol : one of the supported protocol @ref SAI_Protocol\r
264   * @param  datasize : one of the supported datasize @ref SAI_Protocol_DataSize\r
265   *                the configuration information for SAI module.\r
266   * @param  nbslot   : Number of slot.\r
267   * @retval HAL status\r
268   */\r
269 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)\r
270 {\r
271   HAL_StatusTypeDef status = HAL_OK;\r
272   \r
273   /* Check the parameters */\r
274   assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));\r
275   assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));\r
276   \r
277   switch(protocol)\r
278   {\r
279   case SAI_I2S_STANDARD :\r
280   case SAI_I2S_MSBJUSTIFIED :\r
281   case SAI_I2S_LSBJUSTIFIED :\r
282     status = SAI_InitI2S(hsai, protocol, datasize, nbslot);\r
283     break;  \r
284   case SAI_PCM_LONG :\r
285   case SAI_PCM_SHORT :\r
286     status = SAI_InitPCM(hsai, protocol, datasize, nbslot);\r
287     break;\r
288   default :\r
289     status = HAL_ERROR;\r
290     break;\r
291   }\r
292   \r
293   if(status == HAL_OK)\r
294   {\r
295     status = HAL_SAI_Init(hsai);\r
296   }\r
297 \r
298   return status;\r
299 }\r
300 \r
301 /**\r
302   * @brief  Initializes the SAI according to the specified parameters \r
303   *         in the SAI_InitTypeDef and create the associated handle.\r
304   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
305   *                the configuration information for SAI module.\r
306   * @retval HAL status\r
307   */\r
308 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)\r
309\r
310   uint32_t tmpclock = 0;\r
311 \r
312   /* This variable used to store the SAI_CK_x (value in Hz) */\r
313   uint32_t freq = 0;\r
314   \r
315   /* Check the SAI handle allocation */\r
316   if(hsai == NULL)\r
317   {\r
318     return HAL_ERROR;\r
319   }\r
320   \r
321   /* Check the SAI Block parameters */\r
322   assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));  \r
323   assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));\r
324   assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));\r
325   assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));\r
326   assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));\r
327   assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));\r
328   assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));\r
329   assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));\r
330   assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));\r
331   assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));\r
332   assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));\r
333   assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode));\r
334   assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));\r
335   assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));\r
336   \r
337   /* Check the SAI Block Frame parameters */\r
338   assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));\r
339   assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));\r
340   assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));\r
341   assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));\r
342   assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));\r
343   \r
344   /* Check the SAI Block Slot parameters */\r
345   assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));\r
346   assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));\r
347   assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));\r
348   assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));\r
349   \r
350   if(hsai->State == HAL_SAI_STATE_RESET)\r
351   {\r
352     /* Allocate lock resource and initialize it */\r
353     hsai->Lock = HAL_UNLOCKED;\r
354     \r
355     /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */\r
356     HAL_SAI_MspInit(hsai);\r
357   }\r
358   \r
359   hsai->State = HAL_SAI_STATE_BUSY;\r
360   \r
361   /* Disable the selected SAI peripheral */\r
362   SAI_Disable(hsai);\r
363   \r
364   /* SAI Block Synchro Configuration -----------------------------------------*/\r
365   SAI_BlockSynchroConfig(hsai);\r
366     \r
367   /* Configure Master Clock using the following formula :\r
368      MCLK_x = SAI_CK_x / (MCKDIV[3:0] * 2) with MCLK_x = 256 * FS\r
369      FS = SAI_CK_x / (MCKDIV[3:0] * 2) * 256\r
370      MCKDIV[3:0] = SAI_CK_x / FS * 512 */\r
371   if(hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)\r
372   { \r
373   /* Get SAI clock source based on Source clock selection from RCC */\r
374   freq = SAI_GetInputClock(hsai);\r
375   \r
376     /* (saiclocksource x 10) to keep Significant digits */\r
377     tmpclock = (((freq * 10) / ((hsai->Init.AudioFrequency) * 512)));\r
378     \r
379     hsai->Init.Mckdiv = tmpclock / 10;\r
380     \r
381         /* Round result to the nearest integer */\r
382     if((tmpclock % 10) > 8) \r
383     {\r
384       hsai->Init.Mckdiv+= 1;\r
385     }\r
386   }\r
387 \r
388   /* SAI Block Configuration ------------------------------------------------------------*/\r
389   /* SAI CR1 Configuration */\r
390   hsai->Instance->CR1&=~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG |  SAI_xCR1_DS |      \\r
391                          SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN |\\r
392                          SAI_xCR1_MONO | SAI_xCR1_OUTDRIV  | SAI_xCR1_DMAEN |  \\r
393                          SAI_xCR1_NODIV | SAI_xCR1_MCKDIV);\r
394   \r
395   hsai->Instance->CR1|= (hsai->Init.AudioMode | hsai->Init.Protocol |           \\r
396                         hsai->Init.DataSize | hsai->Init.FirstBit  |           \\r
397                         hsai->Init.ClockStrobing | hsai->Init.Synchro |        \\r
398                         hsai->Init.MonoStereoMode | hsai->Init.OutputDrive |   \\r
399                         hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) | hsai->Init.CompandingMode);  \r
400   \r
401   /* SAI CR2 Configuration */\r
402   hsai->Instance->CR2&= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP);\r
403   hsai->Instance->CR2|=  (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);\r
404 \r
405 \r
406   /* SAI Frame Configuration -----------------------------------------*/\r
407   hsai->Instance->FRCR&=(~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \\r
408                            SAI_xFRCR_FSPO | SAI_xFRCR_FSOFF));\r
409   hsai->Instance->FRCR|=((hsai->FrameInit.FrameLength - 1)  | \r
410                             hsai->FrameInit.FSOffset | \r
411                             hsai->FrameInit.FSDefinition | \r
412                             hsai->FrameInit.FSPolarity   | \r
413                             ((hsai->FrameInit.ActiveFrameLength - 1) << 8));  \r
414   \r
415   /* SAI Block_x SLOT Configuration ------------------------------------------*/\r
416   /* This register has no meaning in AC\9297 and SPDIF audio protocol */\r
417   hsai->Instance->SLOTR&= (~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ |            \\r
418                              SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN ));\r
419   \r
420   hsai->Instance->SLOTR|=  hsai->SlotInit.FirstBitOffset |  hsai->SlotInit.SlotSize\r
421                           | hsai->SlotInit.SlotActive | ((hsai->SlotInit.SlotNumber - 1) <<  8);           \r
422   \r
423   /* Initialise the error code */\r
424   hsai->ErrorCode = HAL_SAI_ERROR_NONE;\r
425   \r
426   /* Initialize the SAI state */\r
427   hsai->State= HAL_SAI_STATE_READY;\r
428   \r
429   /* Release Lock */\r
430   __HAL_UNLOCK(hsai);\r
431   \r
432   return HAL_OK;\r
433 }\r
434 \r
435 /**\r
436   * @brief  DeInitializes the SAI peripheral. \r
437   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
438   *                the configuration information for SAI module.\r
439   * @retval HAL status\r
440   */\r
441 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)\r
442 {\r
443   /* Check the SAI handle allocation */\r
444   if(hsai == NULL)\r
445   {\r
446     return HAL_ERROR;\r
447   }\r
448 \r
449   hsai->State = HAL_SAI_STATE_BUSY;\r
450 \r
451   /* Disabled All interrupt and clear all the flag */\r
452   hsai->Instance->IMR = 0;\r
453   hsai->Instance->CLRFR = 0xFFFFFFFF;\r
454   \r
455   /* Disable the SAI */\r
456   SAI_Disable(hsai);\r
457 \r
458   /* Flush the fifo */\r
459   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);\r
460   \r
461   /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */\r
462   HAL_SAI_MspDeInit(hsai);\r
463 \r
464   /* Initialize the error code */\r
465   hsai->ErrorCode = HAL_SAI_ERROR_NONE;\r
466   \r
467   /* Initialize the SAI state */\r
468   hsai->State = HAL_SAI_STATE_RESET;\r
469 \r
470   /* Release Lock */\r
471   __HAL_UNLOCK(hsai);\r
472 \r
473   return HAL_OK;\r
474 }\r
475 \r
476 /**\r
477   * @brief SAI MSP Init.\r
478   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
479   *                the configuration information for SAI module.\r
480   * @retval None\r
481   */\r
482 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)\r
483 {\r
484   /* NOTE : This function Should not be modified, when the callback is needed,\r
485             the HAL_SAI_MspInit could be implemented in the user file\r
486    */ \r
487 }\r
488 \r
489 /**\r
490   * @brief SAI MSP DeInit.\r
491   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
492   *                the configuration information for SAI module.\r
493   * @retval None\r
494   */\r
495 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)\r
496 {\r
497   /* NOTE : This function Should not be modified, when the callback is needed,\r
498             the HAL_SAI_MspDeInit could be implemented in the user file\r
499    */ \r
500 }\r
501 \r
502 /**\r
503   * @}\r
504   */\r
505 \r
506 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions \r
507  *  @brief   Data transfers functions \r
508  *\r
509 @verbatim   \r
510   ===============================================================================\r
511                       ##### IO operation functions #####\r
512  ===============================================================================  \r
513     [..]\r
514     This subsection provides a set of functions allowing to manage the SAI data \r
515     transfers.\r
516 \r
517     (+) There are two modes of transfer:\r
518        (++) Blocking mode : The communication is performed in the polling mode. \r
519             The status of all data processing is returned by the same function \r
520             after finishing transfer.  \r
521        (++) No-Blocking mode : The communication is performed using Interrupts \r
522             or DMA. These functions return the status of the transfer startup.\r
523             The end of the data processing will be indicated through the \r
524             dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when \r
525             using DMA mode.\r
526 \r
527     (+) Blocking mode functions are :\r
528         (++) HAL_SAI_Transmit()\r
529         (++) HAL_SAI_Receive()\r
530         (++) HAL_SAI_TransmitReceive()\r
531         \r
532     (+) Non Blocking mode functions with Interrupt are :\r
533         (++) HAL_SAI_Transmit_IT()\r
534         (++) HAL_SAI_Receive_IT()\r
535         (++) HAL_SAI_TransmitReceive_IT()\r
536 \r
537     (+) Non Blocking mode functions with DMA are :\r
538         (++) HAL_SAI_Transmit_DMA()\r
539         (++) HAL_SAI_Receive_DMA()\r
540         (++) HAL_SAI_TransmitReceive_DMA()\r
541 \r
542     (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:\r
543         (++) HAL_SAI_TxCpltCallback()\r
544         (++) HAL_SAI_RxCpltCallback()\r
545         (++) HAL_SAI_ErrorCallback()\r
546 \r
547 @endverbatim\r
548   * @{\r
549   */\r
550 \r
551 /**\r
552   * @brief  Transmits an amount of data in blocking mode.\r
553   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
554   *                the configuration information for SAI module.\r
555   * @param  pData: Pointer to data buffer\r
556   * @param  Size: Amount of data to be sent\r
557   * @param  Timeout: Timeout duration\r
558   * @retval HAL status\r
559   */\r
560 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t* pData, uint16_t Size, uint32_t Timeout)\r
561 {\r
562   uint32_t tickstart = 0;\r
563   \r
564   if((pData == NULL ) || (Size == 0)) \r
565   {\r
566     return  HAL_ERROR;\r
567   }\r
568   \r
569   if(hsai->State == HAL_SAI_STATE_READY)\r
570   {  \r
571     /* Process Locked */\r
572     __HAL_LOCK(hsai);\r
573     \r
574     hsai->State = HAL_SAI_STATE_BUSY_TX;\r
575     hsai->ErrorCode = HAL_SAI_ERROR_NONE;\r
576     hsai->XferSize = Size;\r
577     hsai->XferCount = Size;\r
578     hsai->pBuffPtr = pData;\r
579     \r
580     /* Check if the SAI is already enabled */ \r
581     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != SAI_xCR1_SAIEN)\r
582     {\r
583       /* fill the fifo with data before to enabled the SAI */\r
584       SAI_FillFifo(hsai);      \r
585       /* Enable SAI peripheral */    \r
586       __HAL_SAI_ENABLE(hsai);\r
587     }\r
588     \r
589     while(hsai->XferCount > 0)\r
590     { \r
591       /* Write data if the FIFO is not full */\r
592       if((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)\r
593       {\r
594         if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))\r
595         {      \r
596           hsai->Instance->DR = (*hsai->pBuffPtr++);\r
597         }\r
598         else if(hsai->Init.DataSize <= SAI_DATASIZE_16)\r
599         {\r
600           hsai->Instance->DR = *((uint16_t *)hsai->pBuffPtr);\r
601           hsai->pBuffPtr+= 2;        \r
602         }\r
603         else\r
604         {\r
605           hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);\r
606           hsai->pBuffPtr+= 4;\r
607         }       \r
608         hsai->XferCount--; \r
609       }\r
610       else\r
611       {\r
612         /* Get tick */\r
613         tickstart = HAL_GetTick();      \r
614         /* Check for the Timeout */\r
615         if(Timeout != HAL_MAX_DELAY)\r
616         {\r
617           if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))\r
618           {\r
619             /* Update error code */\r
620             hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;\r
621             \r
622             /* Process Unlocked */\r
623             __HAL_UNLOCK(hsai);\r
624             \r
625             /* Change the SAI state */\r
626             hsai->State = HAL_SAI_STATE_TIMEOUT;\r
627             \r
628             return HAL_TIMEOUT;\r
629           }\r
630         } \r
631       }\r
632     }      \r
633     \r
634     hsai->State = HAL_SAI_STATE_READY; \r
635     \r
636     /* Process Unlocked */\r
637     __HAL_UNLOCK(hsai);\r
638     \r
639     return HAL_OK;\r
640   }\r
641   else\r
642   {\r
643     return HAL_BUSY;\r
644   }\r
645 }\r
646 \r
647 /**\r
648   * @brief  Receives an amount of data in blocking mode. \r
649   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
650   *                the configuration information for SAI module.\r
651   * @param  pData: Pointer to data buffer\r
652   * @param  Size: Amount of data to be received\r
653   * @param  Timeout: Timeout duration\r
654   * @retval HAL status\r
655   */\r
656 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)\r
657 {\r
658   uint32_t tickstart = 0;\r
659   \r
660   if((pData == NULL ) || (Size == 0)) \r
661   {\r
662     return  HAL_ERROR;\r
663   }\r
664   \r
665   if(hsai->State == HAL_SAI_STATE_READY)\r
666   { \r
667     /* Process Locked */\r
668     __HAL_LOCK(hsai);\r
669     \r
670     hsai->State = HAL_SAI_STATE_BUSY_RX;\r
671     hsai->ErrorCode = HAL_SAI_ERROR_NONE;\r
672     hsai->pBuffPtr = pData;\r
673     hsai->XferSize = Size;\r
674     hsai->XferCount = Size;\r
675     \r
676     /* Check if the SAI is already enabled */ \r
677     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != SAI_xCR1_SAIEN)\r
678     {\r
679       /* Enable SAI peripheral */    \r
680       __HAL_SAI_ENABLE(hsai);\r
681     }\r
682     \r
683     /* Receive data */\r
684     while(hsai->XferCount > 0)\r
685     {\r
686       \r
687       if((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)\r
688       {\r
689         if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))\r
690         {\r
691           (*hsai->pBuffPtr++) = hsai->Instance->DR;\r
692         }\r
693         else if(hsai->Init.DataSize <= SAI_DATASIZE_16)\r
694         {\r
695           *((uint16_t*)hsai->pBuffPtr) = hsai->Instance->DR;\r
696           hsai->pBuffPtr+= 2;\r
697         }\r
698         else\r
699         {\r
700           *((uint32_t*)hsai->pBuffPtr) = hsai->Instance->DR;\r
701           hsai->pBuffPtr+= 4;\r
702         }  \r
703         hsai->XferCount--; \r
704       }\r
705       else\r
706       {\r
707         /* Get tick */\r
708         tickstart = HAL_GetTick();\r
709         /* Check for the Timeout */\r
710         if(Timeout != HAL_MAX_DELAY)\r
711         {\r
712           if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))\r
713           {\r
714             /* Update error code */\r
715             hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;\r
716             \r
717             /* Process Unlocked */\r
718             __HAL_UNLOCK(hsai);\r
719             \r
720             /* Change the SAI state */\r
721             hsai->State = HAL_SAI_STATE_TIMEOUT;\r
722             \r
723             return HAL_TIMEOUT;\r
724           }\r
725         }\r
726       }\r
727     }      \r
728     \r
729     hsai->State = HAL_SAI_STATE_READY; \r
730     \r
731     /* Process Unlocked */\r
732     __HAL_UNLOCK(hsai);\r
733     \r
734     return HAL_OK;\r
735   }\r
736   else\r
737   {\r
738     return HAL_BUSY;\r
739   }\r
740 }\r
741 \r
742 /**\r
743   * @brief  Transmits an amount of data in no-blocking mode with Interrupt.\r
744   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
745   *                the configuration information for SAI module.\r
746   * @param  pData: Pointer to data buffer\r
747   * @param  Size: Amount of data to be sent\r
748   * @retval HAL status\r
749   */\r
750 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)\r
751 {  \r
752   if(hsai->State == HAL_SAI_STATE_READY)\r
753   {\r
754     if((pData == NULL) || (Size == 0)) \r
755     {\r
756       return  HAL_ERROR;\r
757     }\r
758     \r
759     hsai->pBuffPtr = pData;\r
760     hsai->XferSize = Size;\r
761     hsai->XferCount = Size;\r
762     \r
763     /* Process Locked */\r
764     __HAL_LOCK(hsai);\r
765     \r
766     hsai->State = HAL_SAI_STATE_BUSY_TX;\r
767     \r
768     if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))\r
769     {\r
770       hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;\r
771     }\r
772     else if(hsai->Init.DataSize <= SAI_DATASIZE_16)\r
773     {\r
774       hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;\r
775     }\r
776     else\r
777     {\r
778       hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;\r
779     }\r
780     \r
781     /* Enable FRQ and OVRUDR interrupts */\r
782     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));\r
783     \r
784     /* Check if the SAI is already enabled */ \r
785     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != SAI_xCR1_SAIEN)\r
786     {\r
787       /* Fill the fifo before starting the communication */\r
788       SAI_FillFifo(hsai);\r
789       \r
790       /* Enable SAI peripheral */    \r
791       __HAL_SAI_ENABLE(hsai);\r
792     }\r
793     /* Process Unlocked */\r
794     __HAL_UNLOCK(hsai);\r
795     \r
796     return HAL_OK;\r
797   }\r
798   else\r
799   {\r
800     return HAL_BUSY;\r
801   }\r
802 }\r
803 \r
804 /**\r
805   * @brief  Receives an amount of data in no-blocking mode with Interrupt.\r
806   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
807   *                the configuration information for SAI module.\r
808   * @param  pData: Pointer to data buffer\r
809   * @param  Size: Amount of data to be received\r
810   * @retval HAL status\r
811   */\r
812 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)\r
813 {\r
814   \r
815   if(hsai->State == HAL_SAI_STATE_READY)\r
816   {\r
817     if((pData == NULL) || (Size == 0)) \r
818     {\r
819       return  HAL_ERROR;\r
820     }\r
821     \r
822     hsai->pBuffPtr = pData;\r
823     hsai->XferSize = Size;\r
824     hsai->XferCount = Size;\r
825     \r
826     /* Process Locked */\r
827     __HAL_LOCK(hsai);\r
828     \r
829     hsai->State = HAL_SAI_STATE_BUSY_RX;\r
830     \r
831     if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))\r
832     {\r
833       hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;\r
834     }\r
835     else if(hsai->Init.DataSize <= SAI_DATASIZE_16)\r
836     {\r
837       hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;\r
838     }\r
839     else\r
840     {\r
841       hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;\r
842     }    \r
843     /* Enable TXE and OVRUDR interrupts */\r
844     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));\r
845     \r
846     /* Check if the SAI is already enabled */ \r
847     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != SAI_xCR1_SAIEN)\r
848     {\r
849       /* Enable SAI peripheral */    \r
850       __HAL_SAI_ENABLE(hsai);\r
851     }\r
852     \r
853     /* Process Unlocked */\r
854     __HAL_UNLOCK(hsai);\r
855     \r
856     return HAL_OK;\r
857   }\r
858   else\r
859   {\r
860     return HAL_BUSY; \r
861   } \r
862 }\r
863 \r
864 /**\r
865   * @brief Pauses the audio stream playing from the Media.\r
866   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
867   *                the configuration information for SAI module.\r
868   * @retval HAL status\r
869   */\r
870 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)\r
871 {\r
872   /* Process Locked */\r
873   __HAL_LOCK(hsai);\r
874   \r
875   /* Pause the audio file playing by disabling the SAI DMA requests */\r
876   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;\r
877   \r
878   /* Process Unlocked */\r
879   __HAL_UNLOCK(hsai);\r
880   \r
881   return HAL_OK; \r
882 }\r
883 \r
884 /**\r
885   * @brief Resumes the audio stream playing from the Media.\r
886   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
887   *                the configuration information for SAI module.\r
888   * @retval HAL status\r
889   */\r
890 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)\r
891 {\r
892   /* Process Locked */\r
893   __HAL_LOCK(hsai);\r
894   \r
895   /* Enable the SAI DMA requests */\r
896   hsai->Instance->CR1 |= SAI_xCR1_DMAEN;\r
897   \r
898   /* If the SAI peripheral is still not enabled, enable it */\r
899   if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)\r
900   {\r
901     /* Enable SAI peripheral */    \r
902     __HAL_SAI_ENABLE(hsai);\r
903   }\r
904   \r
905   /* Process Unlocked */\r
906   __HAL_UNLOCK(hsai);\r
907   \r
908   return HAL_OK;\r
909 }\r
910 \r
911 /**\r
912   * @brief Stops the audio stream playing from the Media.\r
913   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
914   *                the configuration information for SAI module.\r
915   * @retval HAL status\r
916   */\r
917 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)\r
918 {\r
919   /* Process Locked */\r
920   __HAL_LOCK(hsai);\r
921   \r
922   /* Disable the SAI DMA request */\r
923   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;\r
924   \r
925   /* Abort the SAI DMA Tx Stream */\r
926   if(hsai->hdmatx != NULL)\r
927   {\r
928     HAL_DMA_Abort(hsai->hdmatx);\r
929   }\r
930   /* Abort the SAI DMA Rx Stream */\r
931   if(hsai->hdmarx != NULL)\r
932   {  \r
933     HAL_DMA_Abort(hsai->hdmarx);\r
934   }\r
935 \r
936   /* Disable SAI peripheral */\r
937   SAI_Disable(hsai);\r
938   \r
939   hsai->State = HAL_SAI_STATE_READY;\r
940   \r
941   /* Process Unlocked */\r
942   __HAL_UNLOCK(hsai);\r
943   \r
944   return HAL_OK;\r
945 }\r
946 \r
947 /**\r
948   * @brief Abort the current transfer and disbaled the SAI.\r
949   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
950   *                the configuration information for SAI module.\r
951   * @retval HAL status\r
952   */\r
953 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)\r
954 {\r
955   /* Disable the SAI DMA request */\r
956   hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;\r
957   \r
958   /* Abort the SAI DMA Tx Stream */\r
959   if(hsai->hdmatx != NULL)\r
960   {\r
961     HAL_DMA_Abort(hsai->hdmatx);\r
962   }\r
963   /* Abort the SAI DMA Rx Stream */\r
964   if(hsai->hdmarx != NULL)\r
965   {  \r
966     HAL_DMA_Abort(hsai->hdmarx);\r
967   }\r
968 \r
969   /* Disabled All interrupt and clear all the flag */\r
970   hsai->Instance->IMR = 0;\r
971   hsai->Instance->CLRFR = 0xFFFFFFFF;\r
972   \r
973   /* Disable SAI peripheral */\r
974   SAI_Disable(hsai);\r
975   \r
976   /* Flush the fifo */\r
977   SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);\r
978   \r
979   hsai->State = HAL_SAI_STATE_READY;\r
980   \r
981   /* Process Unlocked */\r
982   __HAL_UNLOCK(hsai);\r
983   \r
984   return HAL_OK;\r
985 }\r
986 \r
987 /**\r
988   * @brief  Transmits an amount of data in no-blocking mode with DMA.\r
989   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
990   *                the configuration information for SAI module.\r
991   * @param  pData: Pointer to data buffer\r
992   * @param  Size: Amount of data to be sent\r
993   * @retval HAL status\r
994   */\r
995 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)\r
996 {\r
997   uint32_t *tmp;\r
998   \r
999   if((pData == NULL) || (Size == 0)) \r
1000   {\r
1001     return  HAL_ERROR;\r
1002   }\r
1003   \r
1004   if(hsai->State == HAL_SAI_STATE_READY)\r
1005   {  \r
1006     hsai->pBuffPtr = pData;\r
1007     hsai->XferSize = Size;\r
1008     hsai->XferCount = Size;\r
1009     \r
1010     /* Process Locked */\r
1011     __HAL_LOCK(hsai);\r
1012     \r
1013     hsai->State = HAL_SAI_STATE_BUSY_TX;\r
1014     \r
1015     /* Set the SAI Tx DMA Half transfer complete callback */\r
1016     hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;\r
1017     \r
1018     /* Set the SAI TxDMA transfer complete callback */\r
1019     hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;\r
1020     \r
1021     /* Set the DMA error callback */\r
1022     hsai->hdmatx->XferErrorCallback = SAI_DMAError;\r
1023     \r
1024     /* Enable the Tx DMA Stream */\r
1025     tmp = (uint32_t*)&pData;\r
1026     HAL_DMA_Start_IT(hsai->hdmatx, *(uint32_t*)tmp, (uint32_t)&hsai->Instance->DR, hsai->XferSize);\r
1027     \r
1028     /* Check if the SAI is already enabled */ \r
1029     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != SAI_xCR1_SAIEN)\r
1030     {\r
1031       /* Enable SAI peripheral */\r
1032       __HAL_SAI_ENABLE(hsai);\r
1033     }\r
1034     \r
1035     /* Enable the interrupts for error handling */\r
1036     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));\r
1037     \r
1038     /* Enable SAI Tx DMA Request */  \r
1039     hsai->Instance->CR1 |= SAI_xCR1_DMAEN;\r
1040     \r
1041     /* Process Unlocked */\r
1042     __HAL_UNLOCK(hsai);\r
1043     \r
1044     return HAL_OK;\r
1045   }\r
1046   else\r
1047   {\r
1048     return HAL_BUSY;\r
1049   }\r
1050 }\r
1051 \r
1052 /**\r
1053   * @brief  Receives an amount of data in no-blocking mode with DMA. \r
1054   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
1055   *                the configuration information for SAI module.\r
1056   * @param  pData: Pointer to data buffer\r
1057   * @param  Size: Amount of data to be received\r
1058   * @retval HAL status\r
1059   */\r
1060 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)\r
1061 {\r
1062   uint32_t *tmp;\r
1063   \r
1064   if((pData == NULL) || (Size == 0))\r
1065   {\r
1066     return  HAL_ERROR;\r
1067   } \r
1068   \r
1069   if(hsai->State == HAL_SAI_STATE_READY)\r
1070   {    \r
1071     hsai->pBuffPtr = pData;\r
1072     hsai->XferSize = Size;\r
1073     hsai->XferCount = Size;\r
1074     \r
1075     /* Process Locked */\r
1076     __HAL_LOCK(hsai);\r
1077     \r
1078     hsai->State = HAL_SAI_STATE_BUSY_RX;\r
1079     \r
1080     /* Set the SAI Rx DMA Half transfer complete callback */\r
1081     hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;\r
1082     \r
1083     /* Set the SAI Rx DMA transfer complete callback */\r
1084     hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;\r
1085     \r
1086     /* Set the DMA error callback */\r
1087     hsai->hdmarx->XferErrorCallback = SAI_DMAError;\r
1088     \r
1089     /* Enable the Rx DMA Stream */\r
1090     tmp = (uint32_t*)&pData;\r
1091     HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, *(uint32_t*)tmp, hsai->XferSize);\r
1092     \r
1093     /* Check if the SAI is already enabled */\r
1094     if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != SAI_xCR1_SAIEN)\r
1095     {\r
1096       /* Enable SAI peripheral */\r
1097       __HAL_SAI_ENABLE(hsai);\r
1098     }\r
1099     \r
1100     /* Enable the interrupts for error handling */\r
1101     __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));\r
1102     \r
1103     /* Enable SAI Rx DMA Request */\r
1104     hsai->Instance->CR1 |= SAI_xCR1_DMAEN;\r
1105     \r
1106     /* Process Unlocked */\r
1107     __HAL_UNLOCK(hsai);\r
1108     \r
1109     return HAL_OK;\r
1110   }\r
1111   else\r
1112   {\r
1113     return HAL_BUSY;\r
1114   }\r
1115 }\r
1116 \r
1117 /**\r
1118   * @brief  Enable the tx mute mode.\r
1119   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1120   *                the configuration information for SAI module.\r
1121   * @param  val :  value sent during the mute @ref SAI_Block_Mute_Value\r
1122   * @retval HAL status\r
1123   */\r
1124 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)\r
1125 {\r
1126   assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));\r
1127   \r
1128   if(hsai->State != HAL_SAI_STATE_RESET)\r
1129   {\r
1130     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);\r
1131     SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | val);\r
1132     return HAL_OK;\r
1133   }\r
1134   return HAL_ERROR;\r
1135 }\r
1136 \r
1137 /**\r
1138   * @brief  Disable the tx mute mode.\r
1139   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1140   *                the configuration information for SAI module.\r
1141   * @retval HAL status\r
1142   */\r
1143 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)\r
1144 {\r
1145   if(hsai->State != HAL_SAI_STATE_RESET)\r
1146   {\r
1147     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);\r
1148     return HAL_OK;\r
1149   }\r
1150   return HAL_ERROR;\r
1151 }\r
1152 \r
1153 /**\r
1154   * @brief  Enable the rx mute detection.\r
1155   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1156   *                the configuration information for SAI module.\r
1157   * @param  callback : function called when the mute is detected\r
1158   * @param  counter : number a data before mute detection max 63.\r
1159   * @retval HAL status\r
1160   */\r
1161 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)\r
1162 {\r
1163   assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));\r
1164   \r
1165   if(hsai->State != HAL_SAI_STATE_RESET)\r
1166   {\r
1167     /* set the mute counter */\r
1168     CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);\r
1169     SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << 6));\r
1170     hsai->mutecallback = callback;\r
1171     /* enable the IT interrupt */\r
1172     __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);\r
1173     return HAL_OK;\r
1174   }\r
1175   return HAL_ERROR;\r
1176 }\r
1177 \r
1178 /**\r
1179   * @brief  Disable the rx mute detection.\r
1180   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1181   *                the configuration information for SAI module.\r
1182   * @retval HAL status\r
1183   */\r
1184 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)\r
1185 {\r
1186   if(hsai->State != HAL_SAI_STATE_RESET)\r
1187   {\r
1188     /* set the mutecallback to NULL */\r
1189     hsai->mutecallback = (SAIcallback)NULL;\r
1190     /* enable the IT interrupt */\r
1191     __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);\r
1192     return HAL_OK;\r
1193   }\r
1194   return HAL_ERROR;\r
1195 }\r
1196 \r
1197 /**\r
1198   * @brief  This function handles SAI interrupt request.\r
1199   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
1200   *                the configuration information for SAI module.\r
1201   * @retval HAL status\r
1202   */\r
1203 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)\r
1204\r
1205   if(hsai->State != HAL_SAI_STATE_RESET)\r
1206   {\r
1207     uint32_t tmpFlag = hsai->Instance->SR;\r
1208     uint32_t tmpItSource = hsai->Instance->IMR; \r
1209     \r
1210     if(((tmpFlag & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((tmpItSource & SAI_IT_FREQ) == SAI_IT_FREQ))\r
1211     {\r
1212       hsai->InterruptServiceRoutine(hsai);\r
1213     }\r
1214     \r
1215     /* check the flag only if one of them is set */\r
1216     if(tmpFlag != 0x00000000)\r
1217     {\r
1218       /* SAI Overrun error interrupt occurred ----------------------------------*/\r
1219       if(((tmpFlag & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((tmpItSource & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))\r
1220       {\r
1221         /* Clear the SAI Overrun flag */\r
1222         __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);\r
1223         /* Change the SAI error code */\r
1224         hsai->ErrorCode = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);\r
1225         /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */\r
1226         HAL_SAI_ErrorCallback(hsai);\r
1227       }\r
1228       \r
1229       /* SAI mutedet interrupt occurred ----------------------------------*/\r
1230       if(((tmpFlag & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((tmpItSource & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))\r
1231       {\r
1232         /* Clear the SAI mutedet flag */\r
1233         __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);\r
1234         /* call the call back function */\r
1235         if(hsai->mutecallback != (SAIcallback)NULL)\r
1236         {\r
1237           /* inform the user that an RX mute event has been detected */\r
1238           hsai->mutecallback();\r
1239         }\r
1240       }\r
1241       \r
1242       /* SAI AFSDET interrupt occurred ----------------------------------*/\r
1243       if(((tmpFlag & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((tmpItSource & SAI_IT_AFSDET) == SAI_IT_AFSDET))\r
1244       {\r
1245         /* Change the SAI error code */\r
1246         hsai->ErrorCode = HAL_SAI_ERROR_AFSDET;\r
1247         HAL_SAI_Abort(hsai);\r
1248         HAL_SAI_ErrorCallback(hsai);\r
1249       }\r
1250       \r
1251       /* SAI LFSDET interrupt occurred ----------------------------------*/\r
1252       if(((tmpFlag & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((tmpItSource & SAI_IT_LFSDET) == SAI_IT_LFSDET))\r
1253       {\r
1254         /* Change the SAI error code */\r
1255         hsai->ErrorCode = HAL_SAI_ERROR_LFSDET;\r
1256         HAL_SAI_Abort(hsai);\r
1257         HAL_SAI_ErrorCallback(hsai);\r
1258       }\r
1259 \r
1260       /* SAI WCKCFG interrupt occurred ----------------------------------*/\r
1261       if(((tmpFlag & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((tmpItSource & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))\r
1262       {\r
1263         /* Change the SAI error code */\r
1264         hsai->ErrorCode = HAL_SAI_ERROR_WCKCFG;\r
1265         HAL_SAI_Abort(hsai);\r
1266         HAL_SAI_ErrorCallback(hsai);\r
1267       }\r
1268     }\r
1269   }\r
1270 }\r
1271 \r
1272 /**\r
1273   * @brief Tx Transfer completed callbacks.\r
1274   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
1275   *                the configuration information for SAI module.\r
1276   * @retval None\r
1277   */\r
1278  __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)\r
1279 {\r
1280   /* NOTE : This function Should not be modified, when the callback is needed,\r
1281             the HAL_SAI_TxCpltCallback could be implemented in the user file\r
1282    */ \r
1283 }\r
1284 \r
1285 /**\r
1286   * @brief Tx Transfer Half completed callbacks\r
1287   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
1288   *                the configuration information for SAI module.\r
1289   * @retval None\r
1290   */\r
1291  __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)\r
1292 {\r
1293   /* NOTE : This function Should not be modified, when the callback is needed,\r
1294             the HAL_SAI_TxHalfCpltCallback could be implemented in the user file\r
1295    */ \r
1296 }\r
1297 \r
1298 /**\r
1299   * @brief Rx Transfer completed callbacks.\r
1300   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
1301   *                the configuration information for SAI module.\r
1302   * @retval None\r
1303   */\r
1304 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)\r
1305 {\r
1306   /* NOTE : This function Should not be modified, when the callback is needed,\r
1307             the HAL_SAI_RxCpltCallback could be implemented in the user file\r
1308    */\r
1309 }\r
1310 \r
1311 /**\r
1312   * @brief Rx Transfer half completed callbacks\r
1313   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
1314   *                the configuration information for SAI module.\r
1315   * @retval None\r
1316   */\r
1317 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)\r
1318 {\r
1319   /* NOTE : This function Should not be modified, when the callback is needed,\r
1320             the HAL_SAI_RxCpltCallback could be implemented in the user file\r
1321    */\r
1322 }\r
1323 \r
1324 /**\r
1325   * @brief SAI error callbacks.\r
1326   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
1327   *                the configuration information for SAI module.\r
1328   * @retval None\r
1329   */\r
1330 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)\r
1331 {\r
1332   /* NOTE : This function Should not be modified, when the callback is needed,\r
1333             the HAL_SAI_ErrorCallback could be implemented in the user file\r
1334    */ \r
1335 }\r
1336 \r
1337 /**\r
1338   * @}\r
1339   */\r
1340 \r
1341 \r
1342 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions \r
1343  *  @brief   Peripheral State functions \r
1344  *\r
1345 @verbatim   \r
1346  ===============================================================================\r
1347                 ##### Peripheral State and Errors functions #####\r
1348  ===============================================================================  \r
1349     [..]\r
1350     This subsection permits to get in run-time the status of the peripheral \r
1351     and the data flow.\r
1352 \r
1353 @endverbatim\r
1354   * @{\r
1355   */\r
1356 \r
1357 /**\r
1358   * @brief  Returns the SAI state.\r
1359   * @param  hsai: pointer to a SAI_HandleTypeDef structure that contains\r
1360   *                the configuration information for SAI module.\r
1361   * @retval HAL state\r
1362   */\r
1363 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai)\r
1364 {\r
1365   return hsai->State;\r
1366 }\r
1367 \r
1368 /**\r
1369 * @brief  Return the SAI error code\r
1370 * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1371   *              the configuration information for the specified SAI Block.\r
1372 * @retval SAI Error Code\r
1373 */\r
1374 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai)\r
1375 {\r
1376   return hsai->ErrorCode;\r
1377 }\r
1378 /**\r
1379   * @}\r
1380   */\r
1381 \r
1382 /**\r
1383   * @brief  Initializes the SAI I2S protocol according to the specified parameters \r
1384   *         in the SAI_InitTypeDef and create the associated handle.\r
1385   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1386   *                the configuration information for SAI module.\r
1387   * @param  protocol : one of the supported protocol\r
1388   * @param  datasize : one of the supported datasize @ref SAI_Protocol_DataSize\r
1389   *                the configuration information for SAI module.\r
1390   * @param  nbslot : number of slot minimum value is 2 and max is 16. \r
1391   *                    the value must be a multiple of 2.\r
1392   * @retval HAL status\r
1393   */\r
1394 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)\r
1395 {\r
1396   /* Check the parameters */\r
1397   assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));\r
1398   assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));\r
1399   \r
1400   hsai->Init.Protocol            = SAI_FREE_PROTOCOL;\r
1401   hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;\r
1402   hsai->Init.ClockStrobing       = SAI_CLOCKSTROBING_FALLINGEDGE;\r
1403   hsai->FrameInit.FSDefinition   = SAI_FS_CHANNEL_IDENTIFICATION;\r
1404   hsai->SlotInit.SlotActive      = SAI_SLOTACTIVE_ALL;\r
1405   hsai->SlotInit.FirstBitOffset  = 0;\r
1406   hsai->SlotInit.SlotNumber      = nbslot;\r
1407   \r
1408   /* in IS2 the number of slot must be even */\r
1409   if((nbslot & 0x1) != 0 )\r
1410   {\r
1411     return HAL_ERROR;\r
1412   }\r
1413     \r
1414   switch(protocol)\r
1415   {\r
1416   case SAI_I2S_STANDARD :\r
1417     hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;\r
1418     hsai->FrameInit.FSOffset   = SAI_FS_BEFOREFIRSTBIT;\r
1419     break;\r
1420   case SAI_I2S_MSBJUSTIFIED :\r
1421   case SAI_I2S_LSBJUSTIFIED :\r
1422     hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;\r
1423     hsai->FrameInit.FSOffset   = SAI_FS_FIRSTBIT;\r
1424     break;\r
1425   default :\r
1426     return HAL_ERROR;\r
1427   }\r
1428    \r
1429   /* Frame definition */\r
1430   hsai->Init.DataSize = 0xFFFFFFFF;\r
1431   switch(datasize)\r
1432   {\r
1433   case SAI_PROTOCOL_DATASIZE_16BIT:\r
1434     hsai->Init.DataSize = SAI_DATASIZE_16;\r
1435     hsai->FrameInit.FrameLength = 32*(nbslot/2);\r
1436     hsai->FrameInit.ActiveFrameLength = 16*(nbslot/2);\r
1437     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;\r
1438     break; \r
1439   case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :\r
1440     if(hsai->Init.DataSize == 0xFFFFFFFF)\r
1441     {\r
1442       hsai->Init.DataSize = SAI_DATASIZE_16;\r
1443     }\r
1444     break; \r
1445   case SAI_PROTOCOL_DATASIZE_24BIT:\r
1446     if(hsai->Init.DataSize == 0xFFFFFFFF)\r
1447     {\r
1448       hsai->Init.DataSize = SAI_DATASIZE_24;\r
1449     }\r
1450     break;\r
1451   case SAI_PROTOCOL_DATASIZE_32BIT: \r
1452     if(hsai->Init.DataSize == 0xFFFFFFFF)\r
1453     {\r
1454       hsai->Init.DataSize = SAI_DATASIZE_32;\r
1455     }\r
1456     hsai->FrameInit.FrameLength = 64*(nbslot/2);\r
1457     hsai->FrameInit.ActiveFrameLength = 32*(nbslot/2);\r
1458     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;\r
1459     if(protocol == SAI_I2S_LSBJUSTIFIED)\r
1460     {\r
1461       if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)\r
1462       {\r
1463         hsai->SlotInit.FirstBitOffset = 16;\r
1464       }\r
1465       if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)\r
1466       {\r
1467         hsai->SlotInit.FirstBitOffset = 8;\r
1468       }\r
1469     }\r
1470     break;\r
1471   default :\r
1472     return HAL_ERROR;\r
1473   }\r
1474  \r
1475   return HAL_OK;\r
1476 }\r
1477 \r
1478 /**\r
1479   * @brief  Initializes the SAI PCM protocol according to the specified parameters \r
1480   *         in the SAI_InitTypeDef and create the associated handle.\r
1481   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1482   *                the configuration information for SAI module.\r
1483   * @param  protocol : one of the supported protocol\r
1484   * @param  datasize : one of the supported datasize @ref SAI_Protocol_DataSize\r
1485   * @param  nbslot : number of slot minimum value is 1 and the max is 16.\r
1486   * @retval HAL status\r
1487   */\r
1488 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)\r
1489 {\r
1490   /* Check the parameters */\r
1491   assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));\r
1492   assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));\r
1493 \r
1494   hsai->Init.Protocol            = SAI_FREE_PROTOCOL;\r
1495   hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;\r
1496   hsai->Init.ClockStrobing       = SAI_CLOCKSTROBING_FALLINGEDGE;\r
1497   hsai->FrameInit.FSDefinition   = SAI_FS_STARTFRAME;\r
1498   hsai->FrameInit.FSPolarity     = SAI_FS_ACTIVE_HIGH;\r
1499   hsai->FrameInit.FSOffset       = SAI_FS_BEFOREFIRSTBIT;\r
1500   hsai->SlotInit.FirstBitOffset  = 0;\r
1501   hsai->SlotInit.SlotNumber      = nbslot;\r
1502   hsai->SlotInit.SlotActive      = SAI_SLOTACTIVE_ALL;\r
1503   \r
1504   switch(protocol)\r
1505   {\r
1506   case SAI_PCM_SHORT :\r
1507     hsai->FrameInit.ActiveFrameLength = 1;\r
1508     break;\r
1509   case SAI_PCM_LONG :\r
1510     hsai->FrameInit.ActiveFrameLength = 13;\r
1511     break;\r
1512   default :\r
1513     return HAL_ERROR;\r
1514   }\r
1515  \r
1516   switch(datasize)\r
1517   {\r
1518   case SAI_PROTOCOL_DATASIZE_16BIT:\r
1519     hsai->Init.DataSize = SAI_DATASIZE_16;\r
1520     hsai->FrameInit.FrameLength = 16 * nbslot;\r
1521     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;\r
1522     break; \r
1523   case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :\r
1524     hsai->Init.DataSize = SAI_DATASIZE_16;\r
1525     hsai->FrameInit.FrameLength = 32 * nbslot;\r
1526     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;\r
1527     break;\r
1528     \r
1529   case SAI_PROTOCOL_DATASIZE_32BIT: \r
1530     hsai->Init.DataSize = SAI_DATASIZE_32;\r
1531     hsai->FrameInit.FrameLength = 32 * nbslot;\r
1532     hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;\r
1533     break;\r
1534   default :\r
1535     return HAL_ERROR;\r
1536   }\r
1537  \r
1538   return HAL_OK;\r
1539 }\r
1540 \r
1541 /**\r
1542   * @brief  Fill the fifo \r
1543   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1544   *                the configuration information for SAI module.\r
1545   * @retval None.\r
1546   */\r
1547 static void SAI_FillFifo(SAI_HandleTypeDef *hsai)\r
1548 {\r
1549   /* fill the fifo with data before to enabled the SAI */\r
1550   while((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)\r
1551   {\r
1552     if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))\r
1553     {\r
1554       hsai->Instance->DR = (*hsai->pBuffPtr++);\r
1555     }\r
1556     else if(hsai->Init.DataSize <= SAI_DATASIZE_16)\r
1557     {\r
1558       hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);\r
1559       hsai->pBuffPtr+= 2;\r
1560     }\r
1561     else\r
1562     {\r
1563       hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);\r
1564       hsai->pBuffPtr+= 4;\r
1565     }\r
1566     hsai->XferCount--;\r
1567   }\r
1568 }\r
1569 \r
1570 /**\r
1571   * @brief  return the interrupt flag to set according the SAI setup \r
1572   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1573   *                the configuration information for SAI module.\r
1574   * @param  mode : SAI_MODE_DMA or SAI_MODE_IT\r
1575   * @retval the list of the IT flag to enable\r
1576  */\r
1577 static uint32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode)\r
1578 {\r
1579   uint32_t tmpIT = SAI_IT_OVRUDR; \r
1580   \r
1581   if(mode == SAI_MODE_IT)\r
1582   {\r
1583     tmpIT|= SAI_IT_FREQ;\r
1584   }\r
1585   \r
1586   if((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))\r
1587   {\r
1588     tmpIT|= SAI_IT_AFSDET | SAI_IT_LFSDET;\r
1589   }\r
1590   else\r
1591   {\r
1592     /* hsai has been configured in master mode */\r
1593     tmpIT|= SAI_IT_WCKCFG;\r
1594   }\r
1595   return tmpIT;\r
1596 }\r
1597 \r
1598 /**\r
1599   * @brief  disable the SAI and wait the disabling\r
1600   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1601   *                the configuration information for SAI module.\r
1602   * @retval None.\r
1603   */\r
1604 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)\r
1605 {\r
1606   uint32_t tickstart = HAL_GetTick();\r
1607   HAL_StatusTypeDef status = HAL_OK;\r
1608   \r
1609   __HAL_SAI_DISABLE(hsai);\r
1610   while((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != RESET)\r
1611   {\r
1612     /* Check for the Timeout */\r
1613     if((HAL_GetTick() - tickstart ) > SAI_TIMEOUT_VALUE)\r
1614     {         \r
1615       /* Update error code */\r
1616       hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;\r
1617       \r
1618       status = HAL_TIMEOUT;\r
1619       \r
1620       /* Change the SAI state */\r
1621       HAL_SAI_ErrorCallback(hsai);\r
1622     }\r
1623   }\r
1624   return status;\r
1625 }\r
1626 \r
1627 /**\r
1628   * @brief  Tx Handler for Transmit in Interrupt mode 8Bit transfer\r
1629   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1630   *                the configuration information for SAI module.\r
1631   * @retval None.\r
1632   */\r
1633 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)\r
1634 {\r
1635   /* Write data on DR register */\r
1636   hsai->Instance->DR = (*hsai->pBuffPtr++);\r
1637   hsai->XferCount--;\r
1638   \r
1639   /* Handle the end of the transmission */\r
1640   if(hsai->XferCount == 0)\r
1641   {\r
1642     /* Disable FREQ and OVRUDR interrupts */\r
1643     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); \r
1644     hsai->State = HAL_SAI_STATE_READY;\r
1645     HAL_SAI_TxCpltCallback(hsai);\r
1646   }\r
1647 }\r
1648 \r
1649 /**\r
1650   * @brief  Tx Handler for Transmit in Interrupt mode for 16Bit transfer\r
1651   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1652   *                the configuration information for SAI module.\r
1653   * @retval None.\r
1654   */\r
1655 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)\r
1656 {\r
1657   /* Write data on DR register */\r
1658   hsai->Instance->DR = *(uint16_t *)hsai->pBuffPtr;\r
1659   hsai->pBuffPtr+=2;\r
1660   hsai->XferCount--;\r
1661   \r
1662   /* Handle the end of the transmission */\r
1663   if(hsai->XferCount == 0)\r
1664   {\r
1665     /* Disable FREQ and OVRUDR interrupts */\r
1666     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); \r
1667     hsai->State = HAL_SAI_STATE_READY;\r
1668     HAL_SAI_TxCpltCallback(hsai);\r
1669   }\r
1670 }\r
1671 \r
1672 /**\r
1673   * @brief  Tx Handler for Transmit in Interrupt mode for 32Bit transfer\r
1674   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1675   *                the configuration information for SAI module.\r
1676   * @retval None.\r
1677   */\r
1678 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)\r
1679 {\r
1680   /* Write data on DR register */\r
1681   hsai->Instance->DR = *(uint32_t *)hsai->pBuffPtr;\r
1682   hsai->pBuffPtr+=4;\r
1683   hsai->XferCount--;\r
1684   \r
1685   /* Handle the end of the transmission */\r
1686   if(hsai->XferCount == 0)\r
1687   {\r
1688     /* Disable FREQ and OVRUDR interrupts */\r
1689     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); \r
1690     hsai->State = HAL_SAI_STATE_READY;\r
1691     HAL_SAI_TxCpltCallback(hsai);\r
1692   }\r
1693 }\r
1694 \r
1695 /**\r
1696   * @brief  Rx Handler for Receive in Interrupt mode 8Bit transfer\r
1697   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1698   *                the configuration information for SAI module.\r
1699   * @retval None.\r
1700   */\r
1701 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)\r
1702 {\r
1703   /* Receive data */    \r
1704   (*hsai->pBuffPtr++) = hsai->Instance->DR;\r
1705   hsai->XferCount--;\r
1706   \r
1707   /* Check end of the transfer */  \r
1708   if(hsai->XferCount == 0)\r
1709   {    \r
1710     /* Disable TXE and OVRUDR interrupts */\r
1711     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));\r
1712     \r
1713     /* Clear the SAI Overrun flag */\r
1714     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);\r
1715     \r
1716     hsai->State = HAL_SAI_STATE_READY;\r
1717     HAL_SAI_RxCpltCallback(hsai); \r
1718   }\r
1719 }\r
1720 \r
1721 /**\r
1722   * @brief  Rx Handler for Receive in Interrupt mode for 16Bit transfer\r
1723   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1724   *                the configuration information for SAI module.\r
1725   * @retval None.\r
1726   */\r
1727 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)\r
1728 {\r
1729   /* Receive data */    \r
1730   *(uint16_t*)hsai->pBuffPtr = hsai->Instance->DR;\r
1731   hsai->pBuffPtr+=2;\r
1732   hsai->XferCount--;\r
1733   \r
1734   /* Check end of the transfer */  \r
1735   if(hsai->XferCount == 0)\r
1736   {    \r
1737     /* Disable TXE and OVRUDR interrupts */\r
1738     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));\r
1739     \r
1740     /* Clear the SAI Overrun flag */\r
1741     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);\r
1742     \r
1743     hsai->State = HAL_SAI_STATE_READY;\r
1744     HAL_SAI_RxCpltCallback(hsai); \r
1745   }\r
1746 }\r
1747 /**\r
1748   * @brief  Rx Handler for Receive in Interrupt mode for 32Bit transfer\r
1749   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains\r
1750   *                the configuration information for SAI module.\r
1751   * @retval None.\r
1752   */\r
1753 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)\r
1754 {\r
1755   /* Receive data */    \r
1756   *(uint32_t*)hsai->pBuffPtr = hsai->Instance->DR;\r
1757   hsai->pBuffPtr+=4;\r
1758   hsai->XferCount--;\r
1759   \r
1760   /* Check end of the transfer */  \r
1761   if(hsai->XferCount == 0)\r
1762   {    \r
1763     /* Disable TXE and OVRUDR interrupts */\r
1764     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));\r
1765     \r
1766     /* Clear the SAI Overrun flag */\r
1767     __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);\r
1768     \r
1769     hsai->State = HAL_SAI_STATE_READY;\r
1770     HAL_SAI_RxCpltCallback(hsai); \r
1771   }\r
1772 }\r
1773 \r
1774 /**\r
1775   * @brief DMA SAI transmit process complete callback.\r
1776   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains\r
1777   *                the configuration information for the specified DMA module.\r
1778   * @retval None\r
1779   */\r
1780 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)   \r
1781 {\r
1782   uint32_t tickstart = 0;\r
1783   \r
1784   SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef* )hdma)->Parent;\r
1785   \r
1786   if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)\r
1787   { \r
1788     hsai->XferCount = 0;\r
1789     \r
1790     /* Disable SAI Tx DMA Request */  \r
1791     hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);\r
1792     \r
1793     /* Get tick */\r
1794     tickstart = HAL_GetTick();\r
1795     \r
1796     /* Set timeout: 10 is the max delay to send the remaining data in the SAI FIFO */\r
1797     /* Wait until FIFO is empty */    \r
1798     while(__HAL_SAI_GET_FLAG(hsai, SAI_xSR_FLVL) != RESET)\r
1799     {\r
1800       /* Check for the Timeout */\r
1801       if((HAL_GetTick() - tickstart ) > SAI_TIMEOUT_VALUE)\r
1802       {         \r
1803         /* Update error code */\r
1804         hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;\r
1805         \r
1806         /* Change the SAI state */\r
1807         HAL_SAI_ErrorCallback(hsai);\r
1808       }\r
1809     } \r
1810     \r
1811     /* Stop the interrupts error handling */\r
1812     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));\r
1813     \r
1814     hsai->State= HAL_SAI_STATE_READY;\r
1815   }\r
1816   HAL_SAI_TxCpltCallback(hsai);\r
1817 }\r
1818 \r
1819 /**\r
1820   * @brief DMA SAI transmit process half complete callback \r
1821   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains\r
1822   *                the configuration information for the specified DMA module.\r
1823   * @retval None\r
1824   */\r
1825 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)\r
1826 {\r
1827   SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;\r
1828 \r
1829   HAL_SAI_TxHalfCpltCallback(hsai);\r
1830 }\r
1831 \r
1832 /**\r
1833   * @brief DMA SAI receive process complete callback. \r
1834   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains\r
1835   *                the configuration information for the specified DMA module.\r
1836   * @retval None\r
1837   */\r
1838 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)   \r
1839 {\r
1840   SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;\r
1841   if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)\r
1842   {\r
1843     /* Disable Rx DMA Request */\r
1844     hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);\r
1845     hsai->XferCount = 0;\r
1846     \r
1847     /* Stop the interrupts error handling */\r
1848     __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));\r
1849     \r
1850     hsai->State = HAL_SAI_STATE_READY;\r
1851   }\r
1852   HAL_SAI_RxCpltCallback(hsai); \r
1853 }\r
1854 \r
1855 /**\r
1856   * @brief DMA SAI receive process half complete callback \r
1857   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains\r
1858   *                the configuration information for the specified DMA module.\r
1859   * @retval None\r
1860   */\r
1861 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)\r
1862 {\r
1863   SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;\r
1864 \r
1865   HAL_SAI_RxHalfCpltCallback(hsai); \r
1866 }\r
1867 /**\r
1868   * @brief DMA SAI communication error callback. \r
1869   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains\r
1870   *                the configuration information for the specified DMA module.\r
1871   * @retval None\r
1872   */\r
1873 static void SAI_DMAError(DMA_HandleTypeDef *hdma)   \r
1874 {\r
1875   SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;\r
1876   \r
1877   /* Stop the DMA transfer */\r
1878   HAL_SAI_DMAStop(hsai);\r
1879   \r
1880   /* Set the SAI state ready to be able to start again the process */\r
1881   hsai->State= HAL_SAI_STATE_READY;\r
1882   HAL_SAI_ErrorCallback(hsai);\r
1883   \r
1884   hsai->XferCount = 0;\r
1885 }\r
1886 \r
1887 /**\r
1888   * @}\r
1889   */\r
1890 \r
1891 #endif /* HAL_SAI_MODULE_ENABLED */\r
1892 /**\r
1893   * @}\r
1894   */\r
1895 \r
1896 /**\r
1897   * @}\r
1898   */\r
1899 \r
1900 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/\r