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>© 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