• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2   ******************************************************************************
3   * @file    stm32f4xx_sai.c
4   * @author  MCD Application Team
5   * @version V1.4.0
6   * @date    04-August-2014
7   * @brief   This file provides firmware functions to manage the following
8   *          functionalities of the Serial Audio Interface (SAI):
9   *           + Initialization and Configuration
10   *           + Data transfers functions
11   *           + DMA transfers management
12   *           + Interrupts and flags management
13   *
14   @verbatim
15  ===============================================================================
16                      ##### How to use this driver #####
17  ===============================================================================
18     [..]
19 
20        (#) Enable peripheral clock using the following functions
21            RCC_APB2PeriphClockCmd(RCC_APB2Periph_SAI1, ENABLE) for SAI1
22 
23        (#) For each SAI Block A/B enable SCK, SD, FS and MCLK GPIO clocks
24            using RCC_AHB1PeriphClockCmd() function.
25 
26        (#) Peripherals alternate function:
27            (++) Connect the pin to the desired peripherals' Alternate
28                 Function (AF) using GPIO_PinAFConfig() function.
29            (++) Configure the desired pin in alternate function by:
30                 GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AF
31            (++) Select the type, pull-up/pull-down and output speed via
32                 GPIO_PuPd, GPIO_OType and GPIO_Speed members
33            (++) Call GPIO_Init() function
34            -@@- If an external clock source is used then the I2S CKIN pin should be
35                also configured in Alternate function Push-pull pull-up mode.
36 
37       (#) The SAI clock can be generated from different clock source :
38           PLL I2S, PLL SAI or external clock source.
39           (++) The PLL I2S is configured using the following functions RCC_PLLI2SConfig(),
40                RCC_PLLI2SCmd(ENABLE), RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY) and
41                RCC_SAIPLLI2SClkDivConfig() or;
42 
43           (++) The PLL SAI is configured using the following functions RCC_PLLSAIConfig(),
44                RCC_PLLSAICmd(ENABLE), RCC_GetFlagStatus(RCC_FLAG_PLLSAIRDY) and
45                RCC_SAIPLLSAIClkDivConfig()or;
46 
47           (++) External clock source is configured using the function
48                RCC_I2SCLKConfig(RCC_I2S2CLKSource_Ext) and after setting correctly the
49                define constant I2S_EXTERNAL_CLOCK_VAL in the stm32f4xx_conf.h file.
50 
51       (#) Each SAI Block A or B has its own clock generator to make these two blocks
52           completely independent. The Clock generator is configured using RCC_SAIBlockACLKConfig() and
53           RCC_SAIBlockBCLKConfig() functions.
54 
55       (#) Each SAI Block A or B can be configured separetely :
56           (++) Program the Master clock divider, Audio mode, Protocol, Data Length, Clock Strobing Edge,
57                Synchronous mode, Output drive and FIFO Thresold using SAI_Init() function.
58                In case of master mode, program the Master clock divider (MCKDIV) using
59                the following formula :
60                (+++) MCLK_x = SAI_CK_x / (MCKDIV * 2) with MCLK_x = 256 * FS
61                (+++) FS = SAI_CK_x / (MCKDIV * 2) * 256
62                (+++) MCKDIV = SAI_CK_x / FS * 512
63          (++) Program the Frame Length, Frame active Length, FS Definition, FS Polarity,
64               FS Offset using SAI_FrameInit() function.
65          (++) Program the Slot First Bit Offset, Slot Size, Slot Number, Slot Active
66               using SAI_SlotInit() function.
67 
68       (#) Enable the NVIC and the corresponding interrupt using the function
69           SAI_ITConfig() if you need to use interrupt mode.
70 
71       (#) When using the DMA mode
72           (++) Configure the DMA using DMA_Init() function
73           (++) Active the needed channel Request using SAI_DMACmd() function
74 
75       (#) Enable the SAI using the SAI_Cmd() function.
76 
77       (#) Enable the DMA using the DMA_Cmd() function when using DMA mode.
78 
79       (#) The SAI has some specific functions which can be useful depending
80           on the audio protocol selected.
81           (++) Enable Mute mode when the audio block is a transmitter using SAI_MuteModeCmd()
82                function and configure the value transmitted during mute using SAI_MuteValueConfig().
83           (++) Detect the Mute mode when audio block is a receiver using SAI_MuteFrameCounterConfig().
84           (++) Enable the MONO mode without any data preprocessing in memory when the number
85                of slot is equal to 2 using SAI_MonoModeConfig() function.
86           (++) Enable data companding algorithm (U law and A law) using SAI_CompandingModeConfig().
87           (++) Choose the behavior of the SD line in output when an inactive slot is sent
88                on the data line using SAI_TRIStateConfig() function.
89   [..]
90    (@)    In master TX mode: enabling the audio block immediately generates the bit clock
91           for the external slaves even if there is no data in the FIFO, However FS signal
92           generation is conditioned by the presence of data in the FIFO.
93 
94    (@)    In master RX mode: enabling the audio block immediately generates the bit clock
95           and FS signal for the external slaves.
96 
97    (@)    It is mandatory to respect the following conditions in order to avoid bad SAI behavior:
98             (+@)  First bit Offset <= (SLOT size - Data size)
99             (+@)  Data size <= SLOT size
100             (+@)  Number of SLOT x SLOT size = Frame length
101             (+@)  The number of slots should be even when bit FSDEF in the SAI_xFRCR is set.
102 
103     @endverbatim
104 
105   ******************************************************************************
106   * @attention
107   *
108   * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
109   *
110   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
111   * You may not use this file except in compliance with the License.
112   * You may obtain a copy of the License at:
113   *
114   *        http://www.st.com/software_license_agreement_liberty_v2
115   *
116   * Unless required by applicable law or agreed to in writing, software
117   * distributed under the License is distributed on an "AS IS" BASIS,
118   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
119   * See the License for the specific language governing permissions and
120   * limitations under the License.
121   *
122   ******************************************************************************
123   */
124 
125 /* Includes ------------------------------------------------------------------*/
126 #include "stm32f4xx_sai.h"
127 #include "stm32f4xx_rcc.h"
128 
129 /** @addtogroup STM32F4xx_StdPeriph_Driver
130   * @{
131   */
132 
133 /** @defgroup SAI
134   * @brief SAI driver modules
135   * @{
136   */
137 
138 /* Private typedef -----------------------------------------------------------*/
139 /* Private define ------------------------------------------------------------*/
140 
141 /* *SAI registers Masks */
142 #define CR1_CLEAR_MASK            ((uint32_t)0xFF07C010)
143 #define FRCR_CLEAR_MASK           ((uint32_t)0xFFF88000)
144 #define SLOTR_CLEAR_MASK          ((uint32_t)0x0000F020)
145 
146 /* Private macro -------------------------------------------------------------*/
147 /* Private variables ---------------------------------------------------------*/
148 /* Private function prototypes -----------------------------------------------*/
149 /* Private functions ---------------------------------------------------------*/
150 
151 /** @defgroup SAI_Private_Functions
152   * @{
153   */
154 
155 /** @defgroup SAI_Group1 Initialization and Configuration functions
156  *  @brief   Initialization and Configuration functions
157  *
158 @verbatim
159  ===============================================================================
160             ##### Initialization and Configuration functions #####
161  ===============================================================================
162   [..]
163   This section provides a set of functions allowing to initialize the SAI Audio
164   Block Mode, Audio Protocol, Data size, Synchronization between audio block,
165   Master clock Divider, Fifo threshold, Frame configuration, slot configuration,
166   Tristate mode, Companding mode and Mute mode.
167   [..]
168   The SAI_Init(), SAI_FrameInit() and SAI_SlotInit() functions follows the SAI Block
169   configuration procedures for Master mode and Slave mode (details for these procedures
170   are available in reference manual(RM0090).
171 
172 @endverbatim
173   * @{
174   */
175 
176 /**
177   * @brief  Deinitialize the SAIx peripheral registers to their default reset values.
178   * @param  SAIx: To select the SAIx peripheral, where x can be the different instances
179   *
180   * @retval None
181   */
SAI_DeInit(SAI_TypeDef * SAIx)182 void SAI_DeInit(SAI_TypeDef* SAIx)
183 {
184   /* Check the parameters */
185   assert_param(IS_SAI_PERIPH(SAIx));
186 
187   /* Enable SAI1 reset state */
188   RCC_APB2PeriphResetCmd(RCC_APB2Periph_SAI1, ENABLE);
189   /* Release SAI1 from reset state */
190   RCC_APB2PeriphResetCmd(RCC_APB2Periph_SAI1, DISABLE);
191 }
192 
193 /**
194   * @brief  Initializes the SAI Block x peripheral according to the specified
195   *         parameters in the SAI_InitStruct.
196   *
197   * @note   SAI clock is generated from a specific output of the PLLSAI or a specific
198   *         output of the PLLI2S or from an alternate function bypassing the PLL I2S.
199   *
200   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
201   * @param  SAI_InitStruct: pointer to a SAI_InitTypeDef structure that
202   *         contains the configuration information for the specified SAI Block peripheral.
203   * @retval None
204   */
SAI_Init(SAI_Block_TypeDef * SAI_Block_x,SAI_InitTypeDef * SAI_InitStruct)205 void SAI_Init(SAI_Block_TypeDef* SAI_Block_x, SAI_InitTypeDef* SAI_InitStruct)
206 {
207   uint32_t tmpreg = 0;
208 
209   /* Check the parameters */
210   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
211 
212   /* Check the SAI Block parameters */
213   assert_param(IS_SAI_BLOCK_MODE(SAI_InitStruct->SAI_AudioMode));
214   assert_param(IS_SAI_BLOCK_PROTOCOL(SAI_InitStruct->SAI_Protocol));
215   assert_param(IS_SAI_BLOCK_DATASIZE(SAI_InitStruct->SAI_DataSize));
216   assert_param(IS_SAI_BLOCK_FIRST_BIT(SAI_InitStruct->SAI_FirstBit));
217   assert_param(IS_SAI_BLOCK_CLOCK_STROBING(SAI_InitStruct->SAI_ClockStrobing));
218   assert_param(IS_SAI_BLOCK_SYNCHRO(SAI_InitStruct->SAI_Synchro));
219   assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(SAI_InitStruct->SAI_OUTDRIV));
220   assert_param(IS_SAI_BLOCK_NODIVIDER(SAI_InitStruct->SAI_NoDivider));
221   assert_param(IS_SAI_BLOCK_MASTER_DIVIDER(SAI_InitStruct->SAI_MasterDivider));
222   assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(SAI_InitStruct->SAI_FIFOThreshold));
223 
224   /* SAI Block_x CR1 Configuration */
225   /* Get the SAI Block_x CR1 value */
226   tmpreg = SAI_Block_x->CR1;
227   /* Clear MODE, PRTCFG, DS, LSBFIRST, CKSTR, SYNCEN, OUTDRIV, NODIV, and MCKDIV bits */
228   tmpreg &= CR1_CLEAR_MASK;
229   /* Configure SAI_Block_x: Audio mode, Protocol, Data Size, first transmitted bit, Clock strobing
230      edge, Synchronization mode, Output drive, Master Divider and FIFO level */
231   /* Set MODE bits according to SAI_AudioMode value       */
232   /* Set PRTCFG bits according to SAI_Protocol value      */
233   /* Set DS bits according to SAI_DataSize value          */
234   /* Set LSBFIRST bit according to SAI_FirstBit value     */
235   /* Set CKSTR bit according to SAI_ClockStrobing value   */
236   /* Set SYNCEN bit according to SAI_Synchro value        */
237   /* Set OUTDRIV bit according to SAI_OUTDRIV value       */
238   /* Set NODIV bit according to SAI_NoDivider value       */
239   /* Set MCKDIV bits according to SAI_MasterDivider value */
240   tmpreg |= (uint32_t)(SAI_InitStruct->SAI_AudioMode     | SAI_InitStruct->SAI_Protocol  |
241                        SAI_InitStruct->SAI_DataSize      | SAI_InitStruct->SAI_FirstBit  |
242                        SAI_InitStruct->SAI_ClockStrobing | SAI_InitStruct->SAI_Synchro   |
243                        SAI_InitStruct->SAI_OUTDRIV       | SAI_InitStruct->SAI_NoDivider |
244                        (uint32_t)((SAI_InitStruct->SAI_MasterDivider) << 20));
245   /* Write to SAI_Block_x CR1 */
246   SAI_Block_x->CR1 = tmpreg;
247 
248   /* SAI Block_x CR2 Configuration */
249   /* Get the SAIBlock_x CR2 value */
250   tmpreg = SAI_Block_x->CR2;
251   /* Clear FTH bits */
252   tmpreg &= ~(SAI_xCR2_FTH);
253   /* Configure the FIFO Level */
254   /* Set FTH bits according to SAI_FIFOThreshold value */
255   tmpreg |= (uint32_t)(SAI_InitStruct->SAI_FIFOThreshold);
256   /* Write to SAI_Block_x CR2 */
257   SAI_Block_x->CR2 = tmpreg;
258 }
259 
260 /**
261   * @brief  Initializes the SAI Block Audio frame according to the specified
262   *         parameters in the SAI_FrameInitStruct.
263   *
264   * @note   this function has no meaning if the AC'97 or SPDIF audio protocol
265   *         are selected.
266   *
267   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
268   * @param  SAI_FrameInitStruct: pointer to an SAI_FrameInitTypeDef structure that
269   *         contains the configuration of audio frame for a specified SAI Block
270   * @retval None
271   */
SAI_FrameInit(SAI_Block_TypeDef * SAI_Block_x,SAI_FrameInitTypeDef * SAI_FrameInitStruct)272 void SAI_FrameInit(SAI_Block_TypeDef* SAI_Block_x, SAI_FrameInitTypeDef* SAI_FrameInitStruct)
273 {
274   uint32_t tmpreg = 0;
275 
276   /* Check the parameters */
277   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
278 
279   /* Check the SAI Block frame parameters */
280   assert_param(IS_SAI_BLOCK_FRAME_LENGTH(SAI_FrameInitStruct->SAI_FrameLength));
281   assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(SAI_FrameInitStruct->SAI_ActiveFrameLength));
282   assert_param(IS_SAI_BLOCK_FS_DEFINITION(SAI_FrameInitStruct->SAI_FSDefinition));
283   assert_param(IS_SAI_BLOCK_FS_POLARITY(SAI_FrameInitStruct->SAI_FSPolarity));
284   assert_param(IS_SAI_BLOCK_FS_OFFSET(SAI_FrameInitStruct->SAI_FSOffset));
285 
286   /* SAI Block_x FRCR Configuration */
287   /* Get the SAI Block_x FRCR value */
288   tmpreg = SAI_Block_x->FRCR;
289   /* Clear FRL, FSALL, FSDEF, FSPOL, FSOFF bits */
290   tmpreg &= FRCR_CLEAR_MASK;
291   /* Configure SAI_Block_x Frame: Frame Length, Active Frame Length, Frame Synchronization
292      Definition, Frame Synchronization Polarity and Frame Synchronization Polarity */
293   /* Set FRL bits according to SAI_FrameLength value         */
294   /* Set FSALL bits according to SAI_ActiveFrameLength value */
295   /* Set FSDEF bit according to SAI_FSDefinition value       */
296   /* Set FSPOL bit according to SAI_FSPolarity value         */
297   /* Set FSOFF bit according to SAI_FSOffset value           */
298   tmpreg |= (uint32_t)((uint32_t)(SAI_FrameInitStruct->SAI_FrameLength - 1)  |
299                        SAI_FrameInitStruct->SAI_FSOffset     |
300                        SAI_FrameInitStruct->SAI_FSDefinition |
301                        SAI_FrameInitStruct->SAI_FSPolarity   |
302                        (uint32_t)((SAI_FrameInitStruct->SAI_ActiveFrameLength - 1) << 8));
303 
304   /* Write to SAI_Block_x FRCR */
305   SAI_Block_x->FRCR = tmpreg;
306 }
307 
308 /**
309   * @brief  Initializes the SAI Block audio Slot according to the specified
310   *         parameters in the SAI_SlotInitStruct.
311   *
312   * @note   this function has no meaning if the AC'97 or SPDIF audio protocol
313   *         are selected.
314   *
315   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
316   * @param  SAI_SlotInitStruct: pointer to an SAI_SlotInitTypeDef structure that
317   *         contains the configuration of audio slot for a specified SAI Block
318   * @retval None
319   */
SAI_SlotInit(SAI_Block_TypeDef * SAI_Block_x,SAI_SlotInitTypeDef * SAI_SlotInitStruct)320 void SAI_SlotInit(SAI_Block_TypeDef* SAI_Block_x, SAI_SlotInitTypeDef* SAI_SlotInitStruct)
321 {
322   uint32_t tmpreg = 0;
323 
324   /* Check the parameters */
325   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
326 
327   /* Check the SAI Block Slot parameters */
328   assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(SAI_SlotInitStruct->SAI_FirstBitOffset));
329   assert_param(IS_SAI_BLOCK_SLOT_SIZE(SAI_SlotInitStruct->SAI_SlotSize));
330   assert_param(IS_SAI_BLOCK_SLOT_NUMBER(SAI_SlotInitStruct->SAI_SlotNumber));
331   assert_param(IS_SAI_SLOT_ACTIVE(SAI_SlotInitStruct->SAI_SlotActive));
332 
333   /* SAI Block_x SLOTR Configuration */
334   /* Get the SAI Block_x SLOTR value */
335   tmpreg = SAI_Block_x->SLOTR;
336   /* Clear FBOFF, SLOTSZ, NBSLOT, SLOTEN bits */
337   tmpreg &= SLOTR_CLEAR_MASK;
338   /* Configure SAI_Block_x Slot: First bit offset, Slot size, Number of Slot in
339      audio frame and slots activated in audio frame */
340   /* Set FBOFF bits according to SAI_FirstBitOffset value  */
341   /* Set SLOTSZ bits according to SAI_SlotSize value       */
342   /* Set NBSLOT bits according to SAI_SlotNumber value     */
343   /* Set SLOTEN bits according to SAI_SlotActive value     */
344   tmpreg |= (uint32_t)(SAI_SlotInitStruct->SAI_FirstBitOffset |
345                        SAI_SlotInitStruct->SAI_SlotSize       |
346                        SAI_SlotInitStruct->SAI_SlotActive     |
347                        (uint32_t)((SAI_SlotInitStruct->SAI_SlotNumber - 1) <<  8));
348 
349   /* Write to SAI_Block_x SLOTR */
350   SAI_Block_x->SLOTR = tmpreg;
351 }
352 
353 /**
354   * @brief  Fills each SAI_InitStruct member with its default value.
355   * @param  SAI_InitStruct: pointer to a SAI_InitTypeDef structure which will
356   *         be initialized.
357   * @retval None
358   */
SAI_StructInit(SAI_InitTypeDef * SAI_InitStruct)359 void SAI_StructInit(SAI_InitTypeDef* SAI_InitStruct)
360 {
361   /* Reset SAI init structure parameters values */
362   /* Initialize the SAI_AudioMode member */
363   SAI_InitStruct->SAI_AudioMode = SAI_Mode_MasterTx;
364   /* Initialize the SAI_Protocol member */
365   SAI_InitStruct->SAI_Protocol = SAI_Free_Protocol;
366   /* Initialize the SAI_DataSize member */
367   SAI_InitStruct->SAI_DataSize = SAI_DataSize_8b;
368   /* Initialize the SAI_FirstBit member */
369   SAI_InitStruct->SAI_FirstBit = SAI_FirstBit_MSB;
370   /* Initialize the SAI_ClockStrobing member */
371   SAI_InitStruct->SAI_ClockStrobing = SAI_ClockStrobing_FallingEdge;
372   /* Initialize the SAI_Synchro member */
373   SAI_InitStruct->SAI_Synchro = SAI_Asynchronous;
374   /* Initialize the SAI_OUTDRIV member */
375   SAI_InitStruct->SAI_OUTDRIV = SAI_OutputDrive_Disabled;
376   /* Initialize the SAI_NoDivider member */
377   SAI_InitStruct->SAI_NoDivider = SAI_MasterDivider_Enabled;
378   /* Initialize the SAI_MasterDivider member */
379   SAI_InitStruct->SAI_MasterDivider = 0;
380   /* Initialize the SAI_FIFOThreshold member */
381   SAI_InitStruct->SAI_FIFOThreshold = SAI_Threshold_FIFOEmpty;
382 }
383 
384 /**
385   * @brief  Fills each SAI_FrameInitStruct member with its default value.
386   * @param  SAI_FrameInitStruct: pointer to a SAI_FrameInitTypeDef structure
387   *         which will be initialized.
388   * @retval None
389   */
SAI_FrameStructInit(SAI_FrameInitTypeDef * SAI_FrameInitStruct)390 void SAI_FrameStructInit(SAI_FrameInitTypeDef* SAI_FrameInitStruct)
391 {
392   /* Reset SAI Frame init structure parameters values */
393   /* Initialize the SAI_FrameLength member */
394   SAI_FrameInitStruct->SAI_FrameLength = 8;
395   /* Initialize the SAI_ActiveFrameLength member */
396   SAI_FrameInitStruct->SAI_ActiveFrameLength = 1;
397   /* Initialize the SAI_FSDefinition member */
398   SAI_FrameInitStruct->SAI_FSDefinition = SAI_FS_StartFrame;
399   /* Initialize the SAI_FSPolarity member */
400   SAI_FrameInitStruct->SAI_FSPolarity = SAI_FS_ActiveLow;
401   /* Initialize the SAI_FSOffset member */
402   SAI_FrameInitStruct->SAI_FSOffset = SAI_FS_FirstBit;
403 }
404 
405 /**
406   * @brief  Fills each SAI_SlotInitStruct member with its default value.
407   * @param  SAI_SlotInitStruct: pointer to a SAI_SlotInitTypeDef structure
408   *         which will be initialized.
409   * @retval None
410   */
SAI_SlotStructInit(SAI_SlotInitTypeDef * SAI_SlotInitStruct)411 void SAI_SlotStructInit(SAI_SlotInitTypeDef* SAI_SlotInitStruct)
412 {
413   /* Reset SAI Slot init structure parameters values */
414   /* Initialize the SAI_FirstBitOffset member */
415   SAI_SlotInitStruct->SAI_FirstBitOffset = 0;
416   /* Initialize the SAI_SlotSize member */
417   SAI_SlotInitStruct->SAI_SlotSize = SAI_SlotSize_DataSize;
418   /* Initialize the SAI_SlotNumber member */
419   SAI_SlotInitStruct->SAI_SlotNumber = 1;
420   /* Initialize the SAI_SlotActive member */
421   SAI_SlotInitStruct->SAI_SlotActive = SAI_Slot_NotActive;
422 
423 }
424 
425 /**
426   * @brief  Enables or disables the specified SAI Block peripheral.
427   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
428   * @param  NewState: new state of the SAI_Block_x peripheral.
429   *          This parameter can be: ENABLE or DISABLE.
430   * @retval None
431   */
SAI_Cmd(SAI_Block_TypeDef * SAI_Block_x,FunctionalState NewState)432 void SAI_Cmd(SAI_Block_TypeDef* SAI_Block_x, FunctionalState NewState)
433 {
434   /* Check the parameters */
435   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
436   assert_param(IS_FUNCTIONAL_STATE(NewState));
437   if (NewState != DISABLE)
438   {
439     /* Enable the selected SAI peripheral */
440     SAI_Block_x->CR1 |= SAI_xCR1_SAIEN;
441   }
442   else
443   {
444     /* Disable the selected SAI peripheral */
445     SAI_Block_x->CR1 &= ~(SAI_xCR1_SAIEN);
446   }
447 }
448 
449 /**
450   * @brief  Configures the mono mode for the selected SAI block.
451   *
452   * @note  This function has a meaning only when the number of slot is equal to 2.
453   *
454   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
455   * @param  SAI_MonoMode: specifies the SAI block mono mode.
456   *          This parameter can be one of the following values:
457   *            @arg SAI_MonoMode : Set mono audio mode
458   *            @arg SAI_StreoMode : Set streo audio mode
459   * @retval None
460   */
SAI_MonoModeConfig(SAI_Block_TypeDef * SAI_Block_x,uint32_t SAI_Mono_StreoMode)461 void SAI_MonoModeConfig(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_Mono_StreoMode)
462 {
463   /* Check the parameters */
464   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
465   assert_param(IS_SAI_BLOCK_MONO_STREO_MODE(SAI_MonoMode));
466   /* Clear MONO bit */
467   SAI_Block_x->CR1 &= ~(SAI_xCR1_MONO);
468   /* Set new Mono Mode value */
469   SAI_Block_x->CR1 |= SAI_MonoMode;
470 }
471 
472 /**
473   * @brief  Configures the TRIState managment on data line for the selected SAI block.
474   *
475   * @note  This function has a meaning only when the SAI block is configured in transmitter
476   *
477   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
478   * @param  SAI_TRIState: specifies the SAI block TRIState management.
479   *          This parameter can be one of the following values:
480   *            @arg SAI_Output_NotReleased : SD output line is still drived by the SAI.
481   *            @arg SAI_Output_Released : SD output line is released (HI-Z)
482   * @retval None
483   */
SAI_TRIStateConfig(SAI_Block_TypeDef * SAI_Block_x,uint32_t SAI_TRIState)484 void SAI_TRIStateConfig(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_TRIState)
485 {
486   /* Check the parameters */
487   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
488   assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(SAI_TRIState));
489   /* Clear MONO bit */
490   SAI_Block_x->CR1 &= ~(SAI_xCR1_MONO);
491   /* Set new Mono Mode value */
492   SAI_Block_x->CR1 |= SAI_MonoMode;
493 
494 }
495 
496 /**
497   * @brief  Configures the companding mode for the selected SAI block.
498   *
499   * @note  The data expansion or data compression are determined by the state of
500   *        SAI block selected (transmitter or receiver).
501 
502   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
503   * @param  SAI_CompandingMode: specifies the SAI block companding mode.
504   *          This parameter can be one of the following values:
505   *            @arg SAI_NoCompanding : no companding algorithm set
506   *            @arg SAI_ULaw_1CPL_Companding : Set U law (algorithm 1's complement representation)
507   *            @arg SAI_ALaw_1CPL_Companding : Set A law (algorithm 1's complement repesentation)
508   *            @arg SAI_ULaw_2CPL_Companding : Set U law (algorithm 2's complement representation)
509   *            @arg SAI_ALaw_2CPL_Companding : Set A law (algorithm 2's complement repesentation)
510   * @retval None
511   */
SAI_CompandingModeConfig(SAI_Block_TypeDef * SAI_Block_x,uint32_t SAI_CompandingMode)512 void SAI_CompandingModeConfig(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_CompandingMode)
513 {
514   /* Check the parameters */
515   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
516   assert_param(IS_SAI_BLOCK_COMPANDING_MODE(SAI_CompandingMode));
517   /* Clear Companding Mode bits */
518   SAI_Block_x->CR2 &= ~(SAI_xCR2_COMP);
519   /* Set new Companding Mode value */
520   SAI_Block_x->CR2 |= SAI_CompandingMode;
521 }
522 
523 /**
524   * @brief  Enables or disables the Mute mode for the selected SAI block.
525   *
526   * @note   This function has a meaning only when the audio block is transmitter
527   * @note   Mute mode is applied for an entire frame for all the valid slot
528   *         It becomes active at the end of an audio frame when set somewhere in a frame.
529   *         Mute mode exit occurs at the end of the frame in which the bit MUTE has been set.
530   *
531   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
532   * @param  NewState: new state of the SAIx block.
533   *          This parameter can be: ENABLE or DISABLE.
534   * @retval None
535   */
SAI_MuteModeCmd(SAI_Block_TypeDef * SAI_Block_x,FunctionalState NewState)536 void SAI_MuteModeCmd(SAI_Block_TypeDef* SAI_Block_x, FunctionalState NewState)
537 {
538   /* Check the parameters */
539   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
540   assert_param(IS_FUNCTIONAL_STATE(NewState));
541   if (NewState != DISABLE)
542   {
543     /* Enable the selected SAI block mute mode */
544     SAI_Block_x->CR2 |= SAI_xCR2_MUTE;
545   }
546   else
547   {
548     /* Disable the selected SAI SS output */
549     SAI_Block_x->CR2 &= ~(SAI_xCR2_MUTE);
550   }
551 }
552 
553 /**
554   * @brief  Configure the mute value for the selected SAI block.
555   *
556   * @note   This function has a meaning only when the audio block is transmitter
557   * @note   the configuration last value sent during mute mode has only a meaning
558   *          when the number of slot is lower or equal to 2 and if the MUTE bit is set.
559   *
560   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
561   * @param  SAI_MuteValue: specifies the SAI block mute value.
562   *          This parameter can be one of the following values:
563   *            @arg SAI_ZeroValue : bit value 0 is sent during Mute Mode
564   *            @arg SAI_LastSentValue : Last value is sent during Mute Mode
565   * @retval None
566   */
SAI_MuteValueConfig(SAI_Block_TypeDef * SAI_Block_x,uint32_t SAI_MuteValue)567 void SAI_MuteValueConfig(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_MuteValue)
568 {
569   /* Check the parameters */
570   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
571   assert_param(IS_SAI_BLOCK_MUTE_VALUE(SAI_MuteValue));
572 
573   /* Clear Mute value bits */
574   SAI_Block_x->CR2 &= ~(SAI_xCR2_MUTEVAL);
575   /* Set new Mute value */
576   SAI_Block_x->CR2 |= SAI_MuteValue;
577 }
578 
579 /**
580   * @brief  Enables or disables the Mute mode for the selected SAI block.
581   *
582   * @note   This function has a meaning only when the audio block is Receiver
583   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
584   * @param  SAI_MuteCounter: specifies the SAI block mute value.
585   *         This parameter can be a number between 0 and 63.
586 
587   * @retval None
588   */
SAI_MuteFrameCounterConfig(SAI_Block_TypeDef * SAI_Block_x,uint32_t SAI_MuteCounter)589 void SAI_MuteFrameCounterConfig(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_MuteCounter)
590 {
591   /* Check the parameters */
592   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
593   assert_param(IS_SAI_BLOCK_MUTE_COUNTER(SAI_MuteCounter));
594 
595   /* Clear Mute value bits */
596   SAI_Block_x->CR2 &= ~(SAI_xCR2_MUTECNT);
597   /* Set new Mute value */
598   SAI_Block_x->CR2 |= (SAI_MuteCounter << 7);
599 }
600 
601 /**
602   * @brief  Reinitialize the FIFO pointer
603   *
604   * @note   The FIFO pointers can be reinitialized at anytime The data present
605   *         into the FIFO, if it is not empty, will be lost.
606   *
607   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
608   * @param  NewState: new state of the selected SAI TI communication mode.
609   *          This parameter can be: ENABLE or DISABLE.
610   * @retval None
611   */
SAI_FlushFIFO(SAI_Block_TypeDef * SAI_Block_x)612 void SAI_FlushFIFO(SAI_Block_TypeDef* SAI_Block_x)
613 {
614   /* Check the parameters */
615   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
616 
617   /* FIFO flush */
618   SAI_Block_x->CR2 |= SAI_xCR2_FFLUSH;
619 }
620 
621 /**
622   * @}
623   */
624 
625 /** @defgroup SAI_Group2 Data transfers functions
626  *  @brief   Data transfers functions
627  *
628 @verbatim
629  ===============================================================================
630                        ##### Data transfers functions #####
631  ===============================================================================
632   [..]
633   This section provides a set of functions allowing to manage the SAI data transfers.
634   [..]
635   In reception, data are received and then stored into an internal FIFO while
636   In transmission, data are first stored into an internal FIFO before being
637   transmitted.
638   [..]
639   The read access of the SAI_xDR register can be done using the SAI_ReceiveData()
640   function and returns the Rx buffered value. Whereas a write access to the SAI_DR
641   can be done using SAI_SendData() function and stores the written data into
642   Tx buffer.
643 
644 @endverbatim
645   * @{
646   */
647 
648 /**
649   * @brief  Returns the most recent received data by the SAI block x peripheral.
650   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
651   *
652   * @retval The value of the received data.
653   */
SAI_ReceiveData(SAI_Block_TypeDef * SAI_Block_x)654 uint32_t SAI_ReceiveData(SAI_Block_TypeDef* SAI_Block_x)
655 {
656   /* Check the parameters */
657   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
658 
659   /* Return the data in the DR register */
660   return SAI_Block_x->DR;
661 }
662 
663 /**
664   * @brief  Transmits a Data through the SAI block x peripheral.
665   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
666   *
667   * @param  Data: Data to be transmitted.
668   * @retval None
669   */
SAI_SendData(SAI_Block_TypeDef * SAI_Block_x,uint32_t Data)670 void SAI_SendData(SAI_Block_TypeDef* SAI_Block_x, uint32_t Data)
671 {
672   /* Check the parameters */
673   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
674 
675   /* Write in the DR register the data to be sent */
676   SAI_Block_x->DR = Data;
677 }
678 
679 /**
680   * @}
681   */
682 
683 /** @defgroup SAI_Group3 DMA transfers management functions
684  *  @brief   DMA transfers management functions
685   *
686 @verbatim
687  ===============================================================================
688                   ##### DMA transfers management functions #####
689  ===============================================================================
690 
691 @endverbatim
692   * @{
693   */
694 
695 /**
696   * @brief  Enables or disables the SAI Block x DMA interface.
697   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
698   * @param  NewState: new state of the selected SAI block DMA transfer request.
699   *          This parameter can be: ENABLE or DISABLE.
700   * @retval None
701   */
SAI_DMACmd(SAI_Block_TypeDef * SAI_Block_x,FunctionalState NewState)702 void SAI_DMACmd(SAI_Block_TypeDef* SAI_Block_x, FunctionalState NewState)
703 {
704   /* Check the parameters */
705   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
706   assert_param(IS_FUNCTIONAL_STATE(NewState));
707 
708   if (NewState != DISABLE)
709   {
710     /* Enable the selected SAI block mute mode */
711     SAI_Block_x->CR1 |= SAI_xCR1_DMAEN;
712   }
713   else
714   {
715     /* Disable the selected SAI SS output */
716     SAI_Block_x->CR1 &= ~(SAI_xCR1_DMAEN);
717   }
718 }
719 
720 /**
721   * @}
722   */
723 
724 /** @defgroup SAI_Group4 Interrupts and flags management functions
725  *  @brief   Interrupts and flags management functions
726   *
727 @verbatim
728  ===============================================================================
729             ##### Interrupts and flags management functions #####
730  ===============================================================================
731   [..]
732   This section provides a set of functions allowing to configure the SAI Interrupts
733   sources and check or clear the flags or pending bits status.
734   The user should identify which mode will be used in his application to manage
735   the communication: Polling mode, Interrupt mode or DMA mode.
736 
737   *** Polling Mode ***
738   ====================
739   [..]
740   In Polling Mode, the SAI communication can be managed by 7 flags:
741      (#) SAI_FLAG_FREQ : to indicate if there is a FIFO Request to write or to read.
742      (#) SAI_FLAG_MUTEDET : to indicate if a MUTE frame detected
743      (#) SAI_FLAG_OVRUDR : to indicate if an Overrun or Underrun error occur
744      (#) SAI_FLAG_AFSDET : to indicate if there is the detection of a audio frame
745                           synchronisation (FS) earlier than expected
746      (#) SAI_FLAG_LFSDET : to indicate if there is the detection of a audio frame
747                           synchronisation (FS) later than expected
748      (#) SAI_FLAG_CNRDY : to indicate if  the codec is not ready to communicate during
749                          the reception of the TAG 0 (slot0) of the AC97 audio frame
750      (#) SAI_FLAG_WCKCFG: to indicate if wrong clock configuration in master mode
751                          error occurs.
752   [..]
753   In this Mode it is advised to use the following functions:
754      (+) FlagStatus SAI_GetFlagStatus(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_FLAG);
755      (+) void SAI_ClearFlag(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_FLAG);
756 
757   *** Interrupt Mode ***
758   ======================
759   [..]
760   In Interrupt Mode, the SAI communication can be managed by 7 interrupt sources
761   and 7 pending bits:
762   (+) Pending Bits:
763      (##) SAI_IT_FREQ : to indicate if there is a FIFO Request to write or to read.
764      (##) SAI_IT_MUTEDET : to indicate if a MUTE frame detected.
765      (##) SAI_IT_OVRUDR : to indicate if an Overrun or Underrun error occur.
766      (##) SAI_IT_AFSDET : to indicate if there is the detection of a audio frame
767                           synchronisation (FS) earlier than expected.
768      (##) SAI_IT_LFSDET : to indicate if there is the detection of a audio frame
769                           synchronisation (FS) later than expected.
770      (##) SAI_IT_CNRDY : to indicate if  the codec is not ready to communicate during
771                          the reception of the TAG 0 (slot0) of the AC97 audio frame.
772      (##) SAI_IT_WCKCFG: to indicate if wrong clock configuration in master mode
773                          error occurs.
774 
775   (+) Interrupt Source:
776      (##) SAI_IT_FREQ : specifies the interrupt source for FIFO Request.
777      (##) SAI_IT_MUTEDET : specifies the interrupt source for MUTE frame detected.
778      (##) SAI_IT_OVRUDR : specifies the interrupt source for overrun or underrun error.
779      (##) SAI_IT_AFSDET : specifies the interrupt source for anticipated frame synchronization
780                           detection interrupt.
781      (##) SAI_IT_LFSDET : specifies the interrupt source for late frame synchronization
782                           detection interrupt.
783      (##) SAI_IT_CNRDY : specifies the interrupt source for codec not ready interrupt
784      (##) SAI_IT_WCKCFG: specifies the interrupt source for wrong clock configuration
785                          interrupt.
786   [..]
787   In this Mode it is advised to use the following functions:
788      (+) void SAI_ITConfig(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_IT, FunctionalState NewState);
789      (+) ITStatus SAI_GetITStatus(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_IT);
790      (+) void SAI_ClearITPendingBit(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_IT);
791 
792   *** DMA Mode ***
793   ================
794   [..]
795   In DMA Mode, each SAI audio block has an independent DMA interface in order to
796   read or to write into the SAI_xDR register (to hit the internal FIFO).
797   There is one DMA channel by audio block following basic DMA request/acknowledge
798   protocol.
799   [..]
800   In this Mode it is advised to use the following function:
801     (+) void SAI_DMACmd(SAI_Block_TypeDef* SAI_Block_x, FunctionalState NewState);
802   [..]
803   This section provides also functions allowing to
804    (+) Check the SAI Block enable status
805    (+)Check the FIFO status
806 
807   *** SAI Block Enable status ***
808   ===============================
809   [..]
810   After disabling a SAI Block, it is recommended to check (or wait until) the SAI Block
811   is effectively disabled. If a Block is disabled while an audio frame transfer is ongoing
812   the current frame will be transferred and the block will be effectively disabled only at
813   the end of audio frame.
814   To monitor this state it is possible to use the following function:
815     (+) FunctionalState SAI_GetCmdStatus(SAI_Block_TypeDef* SAI_Block_x);
816 
817   *** SAI Block FIFO status ***
818   =============================
819   [..]
820   It is possible to monitor the FIFO status when a transfer is ongoing using the following
821   function:
822     (+) uint32_t SAI_GetFIFOStatus(SAI_Block_TypeDef* SAI_Block_x);
823 
824 @endverbatim
825   * @{
826   */
827 
828 /**
829   * @brief  Enables or disables the specified SAI Block interrupts.
830   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
831   * @param  SAI_IT: specifies the SAI interrupt source to be enabled or disabled.
832   *          This parameter can be one of the following values:
833   *            @arg SAI_IT_FREQ: FIFO Request interrupt mask
834   *            @arg SAI_IT_MUTEDET: MUTE detection interrupt mask
835   *            @arg SAI_IT_OVRUDR: overrun/underrun interrupt mask
836   *            @arg SAI_IT_AFSDET: anticipated frame synchronization detection
837   *                                interrupt mask
838   *            @arg SAI_IT_LFSDET: late frame synchronization detection interrupt
839   *                                mask
840   *            @arg SAI_IT_CNRDY: codec not ready interrupt mask
841   *            @arg SAI_IT_WCKCFG: wrong clock configuration interrupt mask
842   * @param  NewState: new state of the specified SAI interrupt.
843   *          This parameter can be: ENABLE or DISABLE.
844   * @retval None
845   */
SAI_ITConfig(SAI_Block_TypeDef * SAI_Block_x,uint32_t SAI_IT,FunctionalState NewState)846 void SAI_ITConfig(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_IT, FunctionalState NewState)
847 {
848   /* Check the parameters */
849   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
850   assert_param(IS_FUNCTIONAL_STATE(NewState));
851   assert_param(IS_SAI_BLOCK_CONFIG_IT(SAI_IT));
852 
853   if (NewState != DISABLE)
854   {
855     /* Enable the selected SAI Block interrupt */
856     SAI_Block_x->IMR |= SAI_IT;
857   }
858   else
859   {
860     /* Disable the selected SAI Block interrupt */
861     SAI_Block_x->IMR &= ~(SAI_IT);
862   }
863 }
864 
865 /**
866   * @brief  Checks whether the specified SAI block x flag is set or not.
867   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
868   * @param  SAI_FLAG: specifies the SAI block flag to check.
869   *          This parameter can be one of the following values:
870   *            @arg SAI_FLAG_FREQ: FIFO Request flag.
871   *            @arg SAI_FLAG_MUTEDET: MUTE detection flag.
872   *            @arg SAI_FLAG_OVRUDR: overrun/underrun flag.
873   *            @arg SAI_FLAG_WCKCFG: wrong clock configuration flag.
874   *            @arg SAI_FLAG_CNRDY: codec not ready flag.
875   *            @arg SAI_FLAG_AFSDET: anticipated frame synchronization detection flag.
876   *            @arg SAI_FLAG_LFSDET: late frame synchronization detection flag.
877   * @retval The new state of SAI_FLAG (SET or RESET).
878   */
SAI_GetFlagStatus(SAI_Block_TypeDef * SAI_Block_x,uint32_t SAI_FLAG)879 FlagStatus SAI_GetFlagStatus(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_FLAG)
880 {
881   FlagStatus bitstatus = RESET;
882 
883   /* Check the parameters */
884   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
885   assert_param(IS_SAI_BLOCK_GET_FLAG(SAI_FLAG));
886 
887   /* Check the status of the specified SAI flag */
888   if ((SAI_Block_x->SR & SAI_FLAG) != (uint32_t)RESET)
889   {
890     /* SAI_FLAG is set */
891     bitstatus = SET;
892   }
893   else
894   {
895     /* SAI_FLAG is reset */
896     bitstatus = RESET;
897   }
898   /* Return the SAI_FLAG status */
899   return  bitstatus;
900 }
901 
902 /**
903   * @brief  Clears the specified SAI Block x flag.
904   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
905   * @param  SAI_FLAG: specifies the SAI block flag to check.
906   *          This parameter can be one of the following values:
907   *            @arg SAI_FLAG_MUTEDET: MUTE detection flag.
908   *            @arg SAI_FLAG_OVRUDR: overrun/underrun flag.
909   *            @arg SAI_FLAG_WCKCFG: wrong clock configuration flag.
910   *            @arg SAI_FLAG_CNRDY: codec not ready flag.
911   *            @arg SAI_FLAG_AFSDET: anticipated frame synchronization detection flag.
912   *            @arg SAI_FLAG_LFSDET: late frame synchronization detection flag.
913   *
914   * @note    FREQ (FIFO Request) flag is cleared :
915   *          - When the audio block is transmitter and the FIFO is full or the FIFO
916   *            has one data (one buffer mode) depending the bit FTH in the
917   *            SAI_xCR2 register.
918   *          - When the audio block is receiver and the FIFO is not empty
919   *
920   * @retval None
921   */
SAI_ClearFlag(SAI_Block_TypeDef * SAI_Block_x,uint32_t SAI_FLAG)922 void SAI_ClearFlag(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_FLAG)
923 {
924   /* Check the parameters */
925   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
926   assert_param(IS_SAI_BLOCK_CLEAR_FLAG(SAI_FLAG));
927 
928   /* Clear the selected SAI Block flag */
929   SAI_Block_x->CLRFR |= SAI_FLAG;
930 }
931 
932 /**
933   * @brief  Checks whether the specified SAI Block x interrupt has occurred or not.
934   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
935   * @param  SAI_IT: specifies the SAI interrupt source to be enabled or disabled.
936   *          This parameter can be one of the following values:
937   *            @arg SAI_IT_FREQ: FIFO Request interrupt
938   *            @arg SAI_IT_MUTEDET: MUTE detection interrupt
939   *            @arg SAI_IT_OVRUDR: overrun/underrun interrupt
940   *            @arg SAI_IT_AFSDET: anticipated frame synchronization detection interrupt
941   *            @arg SAI_IT_LFSDET: late frame synchronization detection interrupt
942   *            @arg SAI_IT_CNRDY: codec not ready interrupt
943   *            @arg SAI_IT_WCKCFG: wrong clock configuration interrupt
944   *
945   * @retval The new state of SAI_IT (SET or RESET).
946   */
SAI_GetITStatus(SAI_Block_TypeDef * SAI_Block_x,uint32_t SAI_IT)947 ITStatus SAI_GetITStatus(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_IT)
948 {
949   ITStatus bitstatus = RESET;
950   uint32_t  enablestatus = 0;
951 
952   /* Check the parameters */
953   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
954   assert_param(IS_SAI_BLOCK_CONFIG_IT(SAI_IT));
955 
956   /* Get the SAI_IT enable bit status */
957   enablestatus = (SAI_Block_x->IMR & SAI_IT) ;
958 
959   /* Check the status of the specified SAI interrupt */
960   if (((SAI_Block_x->SR & SAI_IT) != (uint32_t)RESET) && (enablestatus != (uint32_t)RESET))
961   {
962     /* SAI_IT is set */
963     bitstatus = SET;
964   }
965   else
966   {
967     /* SAI_IT is reset */
968     bitstatus = RESET;
969   }
970   /* Return the SAI_IT status */
971   return bitstatus;
972 }
973 
974 /**
975   * @brief  Clears the SAI Block x interrupt pending bit.
976   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
977   * @param  SAI_IT: specifies the SAI Block interrupt pending bit to clear.
978   *          This parameter can be one of the following values:
979   *            @arg SAI_IT_MUTEDET: MUTE detection interrupt.
980   *            @arg SAI_IT_OVRUDR: overrun/underrun interrupt.
981   *            @arg SAI_IT_WCKCFG: wrong clock configuration interrupt.
982   *            @arg SAI_IT_CNRDY: codec not ready interrupt.
983   *            @arg SAI_IT_AFSDET: anticipated frame synchronization detection interrupt.
984   *            @arg SAI_IT_LFSDET: late frame synchronization detection interrupt.
985   *
986   * @note    FREQ (FIFO Request) flag is cleared :
987   *          - When the audio block is transmitter and the FIFO is full or the FIFO
988   *            has one data (one buffer mode) depending the bit FTH in the
989   *            SAI_xCR2 register.
990   *          - When the audio block is receiver and the FIFO is not empty
991   *
992   * @retval None
993   */
SAI_ClearITPendingBit(SAI_Block_TypeDef * SAI_Block_x,uint32_t SAI_IT)994 void SAI_ClearITPendingBit(SAI_Block_TypeDef* SAI_Block_x, uint32_t SAI_IT)
995 {
996   /* Check the parameters */
997   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
998   assert_param(IS_SAI_BLOCK_CONFIG_IT(SAI_IT));
999 
1000   /* Clear the selected SAI Block x interrupt pending bit */
1001   SAI_Block_x->CLRFR |= SAI_IT;
1002 }
1003 
1004 /**
1005   * @brief  Returns the status of EN bit for the specified SAI Block x.
1006   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
1007   *
1008   * @note    After disabling a SAI Block, it is recommended to check (or wait until)
1009   *          the SAI Block is effectively disabled. If a Block is disabled while
1010   *          an audio frame transfer is ongoing, the current frame will be
1011   *          transferred and the block will be effectively disabled only at
1012   *          the end of audio frame.
1013   *
1014   * @retval Current state of the DMAy Streamx (ENABLE or DISABLE).
1015   */
SAI_GetCmdStatus(SAI_Block_TypeDef * SAI_Block_x)1016 FunctionalState SAI_GetCmdStatus(SAI_Block_TypeDef* SAI_Block_x)
1017 {
1018   FunctionalState state = DISABLE;
1019 
1020   /* Check the parameters */
1021   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
1022   if ((SAI_Block_x->CR1 & (uint32_t)SAI_xCR1_SAIEN) != 0)
1023   {
1024     /* The selected SAI Block x EN bit is set (audio frame transfer is ongoing) */
1025     state = ENABLE;
1026   }
1027   else
1028   {
1029     /* The selected SAI Block x EN bit is cleared (SAI Block is disabled and
1030         all transfers are complete) */
1031     state = DISABLE;
1032   }
1033   return state;
1034 }
1035 
1036 /**
1037   * @brief  Returns the current SAI Block x FIFO filled level.
1038   * @param  SAI_Block_x: where x can be A or B to select the SAI Block peripheral.
1039   *
1040   * @retval The FIFO filling state.
1041   *           - SAI_FIFOStatus_Empty: when FIFO is empty
1042   *           - SAI_FIFOStatus_Less1QuarterFull: when FIFO is less than 1 quarter-full
1043   *                                               and not empty.
1044   *           - SAI_FIFOStatus_1QuarterFull: if more than 1 quarter-full.
1045   *           - SAI_FIFOStatus_HalfFull: if more than 1 half-full.
1046   *           - SAI_FIFOStatus_3QuartersFull: if more than 3 quarters-full.
1047   *           - SAI_FIFOStatus_Full: when FIFO is full
1048   */
SAI_GetFIFOStatus(SAI_Block_TypeDef * SAI_Block_x)1049 uint32_t SAI_GetFIFOStatus(SAI_Block_TypeDef* SAI_Block_x)
1050 {
1051   uint32_t tmpreg = 0;
1052 
1053   /* Check the parameters */
1054   assert_param(IS_SAI_BLOCK_PERIPH(SAI_Block_x));
1055 
1056   /* Get the FIFO level bits */
1057   tmpreg = (uint32_t)((SAI_Block_x->SR & SAI_xSR_FLVL));
1058 
1059   return tmpreg;
1060 }
1061 
1062 
1063 /**
1064   * @}
1065   */
1066 
1067 /**
1068   * @}
1069   */
1070 
1071 /**
1072   * @}
1073   */
1074 
1075 /**
1076   * @}
1077   */
1078 
1079 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
1080