1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2022 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8 #ifndef _FSL_I2S_H_
9 #define _FSL_I2S_H_
10
11 #include "fsl_device_registers.h"
12 #include "fsl_common.h"
13 #include "fsl_flexcomm.h"
14
15 /*******************************************************************************
16 * Definitions
17 ******************************************************************************/
18
19 /*!
20 * @addtogroup i2s_driver
21 * @{
22 */
23
24 /*! @file */
25
26 /*! @name Driver version */
27 /*@{*/
28
29 /*! @brief I2S driver version 2.3.2. */
30 #define FSL_I2S_DRIVER_VERSION (MAKE_VERSION(2, 3, 2))
31 /*@}*/
32
33 #ifndef I2S_NUM_BUFFERS
34
35 /*! @brief Number of buffers . */
36 #define I2S_NUM_BUFFERS (4U)
37
38 #endif
39
40 /*! @brief _i2s_status I2S status codes. */
41 enum
42 {
43 kStatus_I2S_BufferComplete =
44 MAKE_STATUS(kStatusGroup_I2S, 0), /*!< Transfer from/into a single buffer has completed */
45 kStatus_I2S_Done = MAKE_STATUS(kStatusGroup_I2S, 1), /*!< All buffers transfers have completed */
46 kStatus_I2S_Busy =
47 MAKE_STATUS(kStatusGroup_I2S, 2), /*!< Already performing a transfer and cannot queue another buffer */
48 };
49
50 /*!
51 * @brief I2S flags.
52 *
53 * @note These enums are meant to be OR'd together to form a bit mask.
54 */
55 typedef enum _i2s_flags
56 {
57 kI2S_TxErrorFlag = I2S_FIFOINTENSET_TXERR_MASK, /*!< TX error interrupt */
58 kI2S_TxLevelFlag = I2S_FIFOINTENSET_TXLVL_MASK, /*!< TX level interrupt */
59 kI2S_RxErrorFlag = I2S_FIFOINTENSET_RXERR_MASK, /*!< RX error interrupt */
60 kI2S_RxLevelFlag = I2S_FIFOINTENSET_RXLVL_MASK /*!< RX level interrupt */
61 } i2s_flags_t;
62
63 /*! @brief Master / slave mode. */
64 typedef enum _i2s_master_slave
65 {
66 kI2S_MasterSlaveNormalSlave = 0x0, /*!< Normal slave */
67 kI2S_MasterSlaveWsSyncMaster = 0x1, /*!< WS synchronized master */
68 kI2S_MasterSlaveExtSckMaster = 0x2, /*!< Master using existing SCK */
69 kI2S_MasterSlaveNormalMaster = 0x3 /*!< Normal master */
70 } i2s_master_slave_t;
71
72 /*! @brief I2S mode. */
73 typedef enum _i2s_mode
74 {
75 kI2S_ModeI2sClassic = 0x0, /*!< I2S classic mode */
76 kI2S_ModeDspWs50 = 0x1, /*!< DSP mode, WS having 50% duty cycle */
77 kI2S_ModeDspWsShort = 0x2, /*!< DSP mode, WS having one clock long pulse */
78 kI2S_ModeDspWsLong = 0x3 /*!< DSP mode, WS having one data slot long pulse */
79 } i2s_mode_t;
80
81 /*! @brief _i2s_secondary_channel I2S secondary channel. */
82 enum
83 {
84 kI2S_SecondaryChannel1 = 0U, /*!< secondary channel 1 */
85 kI2S_SecondaryChannel2 = 1U, /*!< secondary channel 2 */
86 kI2S_SecondaryChannel3 = 2U, /*!< secondary channel 3 */
87 };
88
89 /*! @brief I2S configuration structure. */
90 typedef struct _i2s_config
91 {
92 i2s_master_slave_t masterSlave; /*!< Master / slave configuration */
93 i2s_mode_t mode; /*!< I2S mode */
94 bool rightLow; /*!< Right channel data in low portion of FIFO */
95 bool leftJust; /*!< Left justify data in FIFO */
96 #if (defined(FSL_FEATURE_FLEXCOMM_I2S_HAS_DMIC_INTERCONNECTION) && FSL_FEATURE_FLEXCOMM_I2S_HAS_DMIC_INTERCONNECTION)
97 bool pdmData; /*!< Data source is the D-Mic subsystem */
98 #endif
99 bool sckPol; /*!< SCK polarity */
100 bool wsPol; /*!< WS polarity */
101 uint16_t divider; /*!< Flexcomm function clock divider (1 - 4096) */
102 bool oneChannel; /*!< true mono, false stereo */
103 uint8_t dataLength; /*!< Data length (4 - 32) */
104 uint16_t frameLength; /*!< Frame width (4 - 512) */
105 uint16_t position; /*!< Data position in the frame */
106 uint8_t watermark; /*!< FIFO trigger level */
107 bool txEmptyZero; /*!< Transmit zero when buffer becomes empty or last item */
108 bool pack48; /*!< Packing format for 48-bit data (false - 24 bit values, true - alternating 32-bit and 16-bit
109 values) */
110 } i2s_config_t;
111
112 /*! @brief Buffer to transfer from or receive audio data into. */
113 typedef struct _i2s_transfer
114 {
115 uint8_t *data; /*!< Pointer to data buffer. */
116 size_t dataSize; /*!< Buffer size in bytes. */
117 } i2s_transfer_t;
118
119 /*! @brief Transactional state of the intialized transfer or receive I2S operation. */
120 typedef struct _i2s_handle i2s_handle_t;
121
122 /*!
123 * @brief Callback function invoked from transactional API
124 * on completion of a single buffer transfer.
125 *
126 * @param base I2S base pointer.
127 * @param handle pointer to I2S transaction.
128 * @param completionStatus status of the transaction.
129 * @param userData optional pointer to user arguments data.
130 */
131 typedef void (*i2s_transfer_callback_t)(I2S_Type *base,
132 i2s_handle_t *handle,
133 status_t completionStatus,
134 void *userData);
135
136 /*! @brief Members not to be accessed / modified outside of the driver. */
137 struct _i2s_handle
138 {
139 volatile uint32_t state; /*!< State of transfer */
140 i2s_transfer_callback_t completionCallback; /*!< Callback function pointer */
141 void *userData; /*!< Application data passed to callback */
142 bool oneChannel; /*!< true mono, false stereo */
143 uint8_t dataLength; /*!< Data length (4 - 32) */
144 bool pack48; /*!< Packing format for 48-bit data (false - 24 bit values, true - alternating 32-bit and 16-bit
145 values) */
146 uint8_t watermark; /*!< FIFO trigger level */
147 bool useFifo48H; /*!< When dataLength 17-24: true use FIFOWR48H, false use FIFOWR */
148
149 volatile i2s_transfer_t i2sQueue[I2S_NUM_BUFFERS]; /*!< Transfer queue storing transfer buffers */
150 volatile uint8_t queueUser; /*!< Queue index where user's next transfer will be stored */
151 volatile uint8_t queueDriver; /*!< Queue index of buffer actually used by the driver */
152 volatile uint32_t errorCount; /*!< Number of buffer underruns/overruns */
153 volatile uint32_t transferCount; /*!< Number of bytes transferred */
154 };
155
156 /*******************************************************************************
157 * API
158 ******************************************************************************/
159
160 #if defined(__cplusplus)
161 extern "C" {
162 #endif
163
164 /*!
165 * @name Initialization and deinitialization
166 * @{
167 */
168
169 /*!
170 * @brief Initializes the FLEXCOMM peripheral for I2S transmit functionality.
171 *
172 * Ungates the FLEXCOMM clock and configures the module
173 * for I2S transmission using a configuration structure.
174 * The configuration structure can be custom filled or set with default values by
175 * I2S_TxGetDefaultConfig().
176 *
177 * @note This API should be called at the beginning of the application to use
178 * the I2S driver.
179 *
180 * @param base I2S base pointer.
181 * @param config pointer to I2S configuration structure.
182 */
183 void I2S_TxInit(I2S_Type *base, const i2s_config_t *config);
184
185 /*!
186 * @brief Initializes the FLEXCOMM peripheral for I2S receive functionality.
187 *
188 * Ungates the FLEXCOMM clock and configures the module
189 * for I2S receive using a configuration structure.
190 * The configuration structure can be custom filled or set with default values by
191 * I2S_RxGetDefaultConfig().
192 *
193 * @note This API should be called at the beginning of the application to use
194 * the I2S driver.
195 *
196 * @param base I2S base pointer.
197 * @param config pointer to I2S configuration structure.
198 */
199 void I2S_RxInit(I2S_Type *base, const i2s_config_t *config);
200
201 /*!
202 * @brief Sets the I2S Tx configuration structure to default values.
203 *
204 * This API initializes the configuration structure for use in I2S_TxInit().
205 * The initialized structure can remain unchanged in I2S_TxInit(), or it can be modified
206 * before calling I2S_TxInit().
207 * Example:
208 @code
209 i2s_config_t config;
210 I2S_TxGetDefaultConfig(&config);
211 @endcode
212 *
213 * Default values:
214 * @code
215 * config->masterSlave = kI2S_MasterSlaveNormalMaster;
216 * config->mode = kI2S_ModeI2sClassic;
217 * config->rightLow = false;
218 * config->leftJust = false;
219 * config->pdmData = false;
220 * config->sckPol = false;
221 * config->wsPol = false;
222 * config->divider = 1;
223 * config->oneChannel = false;
224 * config->dataLength = 16;
225 * config->frameLength = 32;
226 * config->position = 0;
227 * config->watermark = 4;
228 * config->txEmptyZero = true;
229 * config->pack48 = false;
230 * @endcode
231 *
232 * @param config pointer to I2S configuration structure.
233 */
234 void I2S_TxGetDefaultConfig(i2s_config_t *config);
235
236 /*!
237 * @brief Sets the I2S Rx configuration structure to default values.
238 *
239 * This API initializes the configuration structure for use in I2S_RxInit().
240 * The initialized structure can remain unchanged in I2S_RxInit(), or it can be modified
241 * before calling I2S_RxInit().
242 * Example:
243 @code
244 i2s_config_t config;
245 I2S_RxGetDefaultConfig(&config);
246 @endcode
247 *
248 * Default values:
249 * @code
250 * config->masterSlave = kI2S_MasterSlaveNormalSlave;
251 * config->mode = kI2S_ModeI2sClassic;
252 * config->rightLow = false;
253 * config->leftJust = false;
254 * config->pdmData = false;
255 * config->sckPol = false;
256 * config->wsPol = false;
257 * config->divider = 1;
258 * config->oneChannel = false;
259 * config->dataLength = 16;
260 * config->frameLength = 32;
261 * config->position = 0;
262 * config->watermark = 4;
263 * config->txEmptyZero = false;
264 * config->pack48 = false;
265 * @endcode
266 *
267 * @param config pointer to I2S configuration structure.
268 */
269 void I2S_RxGetDefaultConfig(i2s_config_t *config);
270
271 /*!
272 * @brief De-initializes the I2S peripheral.
273 *
274 * This API gates the FLEXCOMM clock. The I2S module can't operate unless I2S_TxInit
275 * or I2S_RxInit is called to enable the clock.
276 *
277 * @param base I2S base pointer.
278 */
279 void I2S_Deinit(I2S_Type *base);
280
281 /*!
282 * @brief Transmitter/Receiver bit clock rate configurations.
283 *
284 * @param base SAI base pointer.
285 * @param sourceClockHz bit clock source frequency.
286 * @param sampleRate audio data sample rate.
287 * @param bitWidth audio data bitWidth.
288 * @param channelNumbers audio channel numbers.
289 */
290 void I2S_SetBitClockRate(
291 I2S_Type *base, uint32_t sourceClockHz, uint32_t sampleRate, uint32_t bitWidth, uint32_t channelNumbers);
292
293 /*! @} */
294
295 /*!
296 * @name Non-blocking API
297 * @{
298 */
299
300 /*!
301 * @brief Initializes handle for transfer of audio data.
302 *
303 * @param base I2S base pointer.
304 * @param handle pointer to handle structure.
305 * @param callback function to be called back when transfer is done or fails.
306 * @param userData pointer to data passed to callback.
307 */
308 void I2S_TxTransferCreateHandle(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_callback_t callback, void *userData);
309
310 /*!
311 * @brief Begins or queue sending of the given data.
312 *
313 * @param base I2S base pointer.
314 * @param handle pointer to handle structure.
315 * @param transfer data buffer.
316 *
317 * @retval kStatus_Success
318 * @retval kStatus_I2S_Busy if all queue slots are occupied with unsent buffers.
319 */
320 status_t I2S_TxTransferNonBlocking(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_t transfer);
321
322 /*!
323 * @brief Aborts sending of data.
324 *
325 * @param base I2S base pointer.
326 * @param handle pointer to handle structure.
327 */
328 void I2S_TxTransferAbort(I2S_Type *base, i2s_handle_t *handle);
329
330 /*!
331 * @brief Initializes handle for reception of audio data.
332 *
333 * @param base I2S base pointer.
334 * @param handle pointer to handle structure.
335 * @param callback function to be called back when transfer is done or fails.
336 * @param userData pointer to data passed to callback.
337 */
338 void I2S_RxTransferCreateHandle(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_callback_t callback, void *userData);
339
340 /*!
341 * @brief Begins or queue reception of data into given buffer.
342 *
343 * @param base I2S base pointer.
344 * @param handle pointer to handle structure.
345 * @param transfer data buffer.
346 *
347 * @retval kStatus_Success
348 * @retval kStatus_I2S_Busy if all queue slots are occupied with buffers which are not full.
349 */
350 status_t I2S_RxTransferNonBlocking(I2S_Type *base, i2s_handle_t *handle, i2s_transfer_t transfer);
351
352 /*!
353 * @brief Aborts receiving of data.
354 *
355 * @param base I2S base pointer.
356 * @param handle pointer to handle structure.
357 */
358 void I2S_RxTransferAbort(I2S_Type *base, i2s_handle_t *handle);
359
360 /*!
361 * @brief Returns number of bytes transferred so far.
362 *
363 * @param base I2S base pointer.
364 * @param handle pointer to handle structure.
365 * @param[out] count number of bytes transferred so far by the non-blocking transaction.
366 *
367 * @retval kStatus_Success
368 * @retval kStatus_NoTransferInProgress there is no non-blocking transaction currently in progress.
369 */
370 status_t I2S_TransferGetCount(I2S_Type *base, i2s_handle_t *handle, size_t *count);
371
372 /*!
373 * @brief Returns number of buffer underruns or overruns.
374 *
375 * @param base I2S base pointer.
376 * @param handle pointer to handle structure.
377 * @param[out] count number of transmit errors encountered so far by the non-blocking transaction.
378 *
379 * @retval kStatus_Success
380 * @retval kStatus_NoTransferInProgress there is no non-blocking transaction currently in progress.
381 */
382 status_t I2S_TransferGetErrorCount(I2S_Type *base, i2s_handle_t *handle, size_t *count);
383
384 /*! @} */
385
386 /*!
387 * @name Enable / disable
388 * @{
389 */
390
391 /*!
392 * @brief Enables I2S operation.
393 *
394 * @param base I2S base pointer.
395 */
I2S_Enable(I2S_Type * base)396 static inline void I2S_Enable(I2S_Type *base)
397 {
398 base->CFG1 |= I2S_CFG1_MAINENABLE(1U);
399 }
400
401 #if (defined(FSL_FEATURE_I2S_SUPPORT_SECONDARY_CHANNEL) && FSL_FEATURE_I2S_SUPPORT_SECONDARY_CHANNEL)
402 /*!
403 * @brief Enables I2S secondary channel.
404 *
405 * @param base I2S base pointer.
406 * @param channel seondary channel channel number, reference _i2s_secondary_channel.
407 * @param oneChannel true is treated as single channel, functionality left channel for this pair.
408 * @param position define the location within the frame of the data, should not bigger than 0x1FFU.
409 */
410 void I2S_EnableSecondaryChannel(I2S_Type *base, uint32_t channel, bool oneChannel, uint32_t position);
411
412 /*!
413 * @brief Disables I2S secondary channel.
414 *
415 * @param base I2S base pointer.
416 * @param channel seondary channel channel number, reference _i2s_secondary_channel.
417 */
I2S_DisableSecondaryChannel(I2S_Type * base,uint32_t channel)418 static inline void I2S_DisableSecondaryChannel(I2S_Type *base, uint32_t channel)
419 {
420 #if defined FSL_FEATURE_FLEXCOMM_INSTANCE_I2S_SUPPORT_SECONDARY_CHANNELn
421 assert(FSL_FEATURE_FLEXCOMM_INSTANCE_I2S_SUPPORT_SECONDARY_CHANNELn((FLEXCOMM_Type *)(uint32_t)base) == 1);
422 #endif
423
424 base->SECCHANNEL[channel].PCFG1 &= ~I2S_CFG1_MAINENABLE_MASK;
425 }
426 #endif
427 /*!
428 * @brief Disables I2S operation.
429 *
430 * @param base I2S base pointer.
431 */
I2S_Disable(I2S_Type * base)432 static inline void I2S_Disable(I2S_Type *base)
433 {
434 base->CFG1 &= (~I2S_CFG1_MAINENABLE(1U));
435 }
436
437 /*! @} */
438
439 /*!
440 * @name Interrupts
441 * @{
442 */
443
444 /*!
445 * @brief Enables I2S FIFO interrupts.
446 *
447 * @param base I2S base pointer.
448 * @param interruptMask bit mask of interrupts to enable. See #i2s_flags_t for the set
449 * of constants that should be OR'd together to form the bit mask.
450 */
I2S_EnableInterrupts(I2S_Type * base,uint32_t interruptMask)451 static inline void I2S_EnableInterrupts(I2S_Type *base, uint32_t interruptMask)
452 {
453 base->FIFOINTENSET = interruptMask;
454 }
455
456 /*!
457 * @brief Disables I2S FIFO interrupts.
458 *
459 * @param base I2S base pointer.
460 * @param interruptMask bit mask of interrupts to enable. See #i2s_flags_t for the set
461 * of constants that should be OR'd together to form the bit mask.
462 */
I2S_DisableInterrupts(I2S_Type * base,uint32_t interruptMask)463 static inline void I2S_DisableInterrupts(I2S_Type *base, uint32_t interruptMask)
464 {
465 base->FIFOINTENCLR = interruptMask;
466 }
467
468 /*!
469 * @brief Returns the set of currently enabled I2S FIFO interrupts.
470 *
471 * @param base I2S base pointer.
472 *
473 * @return A bitmask composed of #i2s_flags_t enumerators OR'd together
474 * to indicate the set of enabled interrupts.
475 */
I2S_GetEnabledInterrupts(I2S_Type * base)476 static inline uint32_t I2S_GetEnabledInterrupts(I2S_Type *base)
477 {
478 return base->FIFOINTENSET;
479 }
480
481 /*!
482 * @brief Flush the valid data in TX fifo.
483 *
484 * @param base I2S base pointer.
485 * @return kStatus_Fail empty TX fifo failed, kStatus_Success empty tx fifo success.
486 */
487 status_t I2S_EmptyTxFifo(I2S_Type *base);
488
489 /*!
490 * @brief Invoked from interrupt handler when transmit FIFO level decreases.
491 *
492 * @param base I2S base pointer.
493 * @param handle pointer to handle structure.
494 */
495 void I2S_TxHandleIRQ(I2S_Type *base, i2s_handle_t *handle);
496
497 /*!
498 * @brief Invoked from interrupt handler when receive FIFO level decreases.
499 *
500 * @param base I2S base pointer.
501 * @param handle pointer to handle structure.
502 */
503 void I2S_RxHandleIRQ(I2S_Type *base, i2s_handle_t *handle);
504
505 /*! @} */
506
507 /*! @} */
508
509 #if defined(__cplusplus)
510 }
511 #endif
512
513 #endif /* _FSL_I2S_H_ */
514