MCUXpresso SDK API Reference Manual  Rev. 0
NXP Semiconductors
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
I2S: I2S Driver

Modules

 I2S DMA Driver
 
 I2S Driver
 

Detailed Description

The MCUXpresso SDK provides the peripheral driver for the I2S function of FLEXCOMM module of MCUXpresso SDK devices.

The I2S module is used to transmit or receive digital audio data. Only transmit or receive is enabled at one time in one module.
Driver currently supports one (primary) channel pair per one I2S enabled FLEXCOMM module only.

I2S Driver Initialization and Configuration

I2S_TxInit() and I2S_RxInit() functions ungate the clock for the FLEXCOMM module, assign I2S function to FLEXCOMM module and configure audio data format and other I2S operational settings. I2S_TxInit() is used when I2S should transmit data, I2S_RxInit() when it should receive data.

I2S_TxGetDefaultConfig() and I2S_RxGetDefaultConfig() functions can be used to set the module configuration structure with default values for transmit and receive function, respectively.

I2S_Deinit() function resets the FLEXCOMM module.

I2S_TxTransferCreateHandle() function creates transactional handle for transmit in interrupt mode.

I2S_RxTransferCreateHandle() function creates transactional handle for receive in interrupt mode.

I2S_TxTransferCreateHandleDMA() function creates transactional handle for transmit in DMA mode.

I2S_RxTransferCreateHandleDMA() function creates transactional handle for receive in DMA mode.

I2S Transmit Data

I2S_TxTransferNonBlocking() function is used to add data buffer to transmit in interrupt mode. It also begins transmission if not transmitting yet.

I2S_RxTransferNonBlocking() function is used to add data buffer to receive data into in interrupt mode. It also begins reception if not receiving yet.

I2S_TxTransferSendDMA() function is used to add data buffer to transmit in DMA mode. It also begins transmission if not transmitting yet.

I2S_RxTransferReceiveDMA() function is used to add data buffer to receive data into in DMA mode. It also begins reception if not receiving yet.

The transfer of data will be stopped automatically when all data buffers queued using the above functions will be processed and no new data buffer is enqueued meanwhile. If the above functions are not called frequently enough, I2S stop followed by restart may keep occurring resulting in drops audio stream.

I2S Interrupt related functions

I2S_EnableInterrupts() function is used to enable interrupts in FIFO interrupt register. Regular use cases do not require this function to be called from application code.

I2S_DisableInterrupts() function is used to disable interrupts in FIFO interrupt register. Regular use cases do not require this function to be called from application code.

I2S_GetEnabledInterrupts() function returns interrupts enabled in FIFO interrupt register. Regular use cases do not require this function to be called from application code.

I2S_TxHandleIRQ() and I2S_RxHandleIRQ() functions are called from ISR which is invoked when actual FIFO level decreases to configured watermark value.

I2S_DMACallback() function is called from ISR which is invoked when DMA transfer (actual descriptor) finishes.

I2S Other functions

I2S_Enable() function enables I2S function in FLEXCOMM module. Regular use cases do not require this function to be called from application code.

I2S_Disable() function disables I2S function in FLEXCOMM module. Regular use cases do not require this function to be called from application code.

I2S_TransferGetErrorCount() function returns the number of FIFO underruns or overruns in interrupt mode.

I2S_TransferGetCount() function returns the number of bytes transferred in interrupt mode.

I2S_TxTransferAbort() function aborts trasmit operation in interrupt mode.

I2S_RxTransferAbort() function aborts receive operation in interrupt mode.

I2S_TransferAbortDMA() function aborts transmit or receive operation in DMA mode.

I2S Data formats

DMA mode

Length of buffer for transmit or receive has to be multiply of 4 bytes. Buffer address has to be aligned to 4-bytes. Data are put into or taken from FIFO unaltered in DMA mode so buffer has to be prepared according to following information. If oneChannel is enabled, then the buffer should contain valid data only, that is to say, audio data should be put continuously in the buffer Take 8 bit data as example:

LSB

L07

L06

L05

L04

L03

L02

L01

L00

L07

L06

L05

L04

L03

L02

L01

L00

L07

L06

L05

L04

L03

L02

L01

L00

L07

L06

L05

L04

L03

L02

L01

L00

If i2s_config_t.dataLength (channel bit width) is between 4 and 16, every word in buffer should contain data for left and right channels.

MSB LSB
R15 R14 R13 R12 R11 R10 R09 R08 R07 R06 R05 R04 R03 R02 R01 R00 L15 L14 L13 L12 L11 L10 L09 L08 L07 L06 L05 L04 L03 L02 L01 L00

Rnn - right channel bit nn
Lnn - left channel bit nn
Note that for example if i2s_config_t.dataLength = 7, bits on positions R07-R15 and L07-L15 are ignored (buffer "wastes space").

If i2s_config_t.dataLength (channel bit width) is between 17 and 24 and i2s_config_t.pack48 = false:

Even words (counting from zero):

MSB LSB
L23 L22 L21 L20 L19 L18 L17 L16 L15 L14 L13 L12 L11 L10 L09 L08 L07 L06 L05 L04 L03 L02 L01 L00

Odd words (counting from zero):

MSB LSB
R23 R22 R21 R20 R19 R18 R17 R16 R15 R14 R13 R12 R11 R10 R09 R08 R07 R06 R05 R04 R03 R02 R01 R00

If i2s_config_t.dataLength (channel bit width) is between 17 and 24 and i2s_config_t.pack48 = true:

Even words (counting from zero):

MSB LSB
R07 R06 R05 R04 R03 R02 R01 R00 L23 L22 L21 L20 L19 L18 L17 L16 L15 L14 L13 L12 L11 L10 L09 L08 L07 L06 L05 L04 L03 L02 L01 L00

Odd words (counting from zero):

MSB LSB
R23 R22 R21 R20 R19 R18 R17 R16 R15 R14 R13 R12 R11 R10 R09 R08

If i2s_config_t.dataLength (channel bit width) is between 25 and 32:

Even words (counting from zero):

MSB LSB
L31 L30 L29 L28 L27 L26 L25 L24 L23 L22 L21 L20 L19 L18 L17 L16 L15 L14 L13 L12 L11 L10 L09 L08 L07 L06 L05 L04 L03 L02 L01 L00

Odd words (counting from zero):

MSB LSB
R31 R30 R29 R28 R27 R26 R25 R24 R23 R22 R21 R20 R19 R18 R17 R16 R15 R14 R13 R12 R11 R10 R09 R08 R07 R06 R05 R04 R03 R02 R01 R00

Interrupt mode

If i2s_config_t.dataLength (channel bit width) is 4:

Buffer does not need to be aligned (buffer is read / written by single bytes, each byte contain left and right channel):

MSB LSB
R03 R02 R01 R00 L03 L02 L01 L00

If i2s_config_t.dataLength (channel bit width) is between 5 and 8:

Length of buffer for transmit or receive has to be multiply of 2 bytes. Buffer address has to be aligned to 2-bytes.

MSB LSB
R07 R06 R05 R04 R03 R02 R01 R00 L07 L06 L05 L04 L03 L02 L01 L00

If i2s_config_t.dataLength (channel bit width) is between 9 and 16:

Length of buffer for transmit or receive has to be multiply of 4 bytes. Buffer address has to be aligned to 4-bytes.

MSB LSB
R15 R14 R13 R12 R11 R10 R09 R08 R07 R06 R05 R04 R03 R02 R01 R00 L15 L14 L13 L12 L11 L10 L09 L08 L07 L06 L05 L04 L03 L02 L01 L00

If i2s_config_t.dataLength (channel bit width) is between 17 and 24 and i2s_config_t.pack48 = false(mono channel audio data is supported):

Length of buffer for transmit or receive has to be multiply of 6 bytes.

MSB LSB
R23 R22 R21 R20 R19 R18 R17 R16 R15 R14 R13 R12 R11 R10 R09 R08 R07 R06 R05 R04 R03 R02 R01 R00 L23 L22 L21 L20 L19 L18 L17 L16 L15 L14 L13 L12 L11 L10 L09 L08 L07 L06 L05 L04 L03 L02 L01 L00

If i2s_config_t.dataLength (channel bit width) is between 17 and 24 and i2s_config_t.pack48 = true:

Length of buffer for transmit or receive has to be multiply of 6 bytes. Buffer address has to be aligned to 4-bytes.

MSB LSB
R23 R22 R21 R20 R19 R18 R17 R16 R15 R14 R13 R12 R11 R10 R09 R08 R07 R06 R05 R04 R03 R02 R01 R00 L23 L22 L21 L20 L19 L18 L17 L16 L15 L14 L13 L12 L11 L10 L09 L08 L07 L06 L05 L04 L03 L02 L01 L00

If i2s_config_t.dataLength (channel bit width) is between 25 and 32 and i2s_config_t.oneChannel = false:

Buffer for transmit or receive has to be multiply of 8 bytes. Buffer address has to be aligned to 4-bytes.

Even words (counting from zero):

MSB LSB
L31 L30 L29 L28 L27 L26 L25 L24 L23 L22 L21 L20 L19 L18 L17 L16 L15 L14 L13 L12 L11 L10 L09 L08 L07 L06 L05 L04 L03 L02 L01 L00

Odd words (counting from zero):

MSB LSB
R31 R30 R29 R28 R27 R26 R25 R24 R23 R22 R21 R20 R19 R18 R17 R16 R15 R14 R13 R12 R11 R10 R09 R08 R07 R06 R05 R04 R03 R02 R01 R00

If i2s_config_t.dataLength (channel bit width) is between 25 and 32 and i2s_config_t.oneChannel = true:

Buffer for transmit or receive has to be multiply of 4 bytes. Buffer address has to be aligned to 4-bytes.

MSB LSB
L31 L30 L29 L28 L27 L26 L25 L24 L23 L22 L21 L20 L19 L18 L17 L16 L15 L14 L13 L12 L11 L10 L09 L08 L07 L06 L05 L04 L03 L02 L01 L00

I2S Driver Examples

Interrupt mode examples

Transmit example

void StartTransfer(void)
{
i2s_config_t config;
i2s_transfer_t transfer;
i2s_handle_t handle;
config.divider = 32; /* clock frequency/audio sample frequency/channels/channel bit depth */
I2S_TxInit(I2S0, &config);
I2S_TxTransferCreateHandle(I2S0, &handle, TxCallback, NULL);
transfer.data = buffer;
transfer.dataSize = sizeof(buffer);
I2S_TxTransferNonBlocking(I2S0, &handle, transfer);
/* Enqueue next buffer right away so there is no drop in audio data stream when the first buffer finishes */
I2S_TxTransferNonBlocking(I2S0, &handle, someTransfer);
}
void TxCallback(I2S_Type *base, i2s_handle_t *handle, status_t completionStatus, void *userData)
{
i2s_tranfer_t transfer;
if (completionStatus == kStatus_I2S_BufferComplete)
{
/* Enqueue next buffer */
transfer.data = buffer;
transfer.dataSize = sizeof(buffer);
I2S_TxTransferNonBlocking(base, handle, transfer);
}
}

Receive example

void StartTransfer(void)
{
i2s_config_t config;
i2s_transfer_t transfer;
i2s_handle_t handle;
config.divider = 32; /* clock frequency/audio sample frequency/channels/channel bit depth */
I2S_RxInit(I2S0, &config);
I2S_RxTransferCreateHandle(I2S0, &handle, RxCallback, NULL);
transfer.data = buffer;
transfer.dataSize = sizeof(buffer);
I2S_RxTransferNonBlocking(I2S0, &handle, transfer);
/* Enqueue next buffer right away so there is no drop in audio data stream when the first buffer finishes */
I2S_RxTransferNonBlocking(I2S0, &handle, someTransfer);
}
void RxCallback(I2S_Type *base, i2s_handle_t *handle, status_t completionStatus, void *userData)
{
i2s_tranfer_t transfer;
if (completionStatus == kStatus_I2S_BufferComplete)
{
/* Enqueue next buffer */
transfer.data = buffer;
transfer.dataSize = sizeof(buffer);
I2S_RxTransferNonBlocking(base, handle, transfer);
}
}

DMA mode examples

Transmit example

void StartTransfer(void)
{
i2s_config_t config;
i2s_transfer_t transfer;
i2s_dma_handle_t handle;
config.divider = 32; /* clock frequency/audio sample frequency/channels/channel bit depth */
I2S_TxInit(I2S0, &config);
I2S_TxTransferCreateHandleDMA(I2S0, &handle, TxCallback, NULL);
transfer.data = buffer;
transfer.dataSize = sizeof(buffer);
I2S_TxTransferNonBlockingDMA(I2S0, &handle, transfer);
/* Enqueue next buffer right away so there is no drop in audio data stream when the first buffer finishes */
I2S_TxTransferNonBlockingDMA(I2S0, &handle, someTransfer);
}
void TxCallback(I2S_Type *base, i2s_dma_handle_t *handle, status_t completionStatus, void *userData)
{
i2s_tranfer_t transfer;
if (completionStatus == kStatus_I2S_BufferComplete)
{
/* Enqueue next buffer */
transfer.data = buffer;
transfer.dataSize = sizeof(buffer);
I2S_TxTransferNonBlockingDMA(base, handle, transfer);
}
}

Receive example

void StartTransfer(void)
{
i2s_config_t config;
i2s_transfer_t transfer;
i2s_dma_handle_t handle;
config.divider = 32; /* clock frequency/audio sample frequency/channels/channel bit depth */
I2S_RxInit(I2S0, &config);
I2S_RxTransferCreateHandleDMA(I2S0, &handle, RxCallback, NULL);
transfer.data = buffer;
transfer.dataSize = sizeof(buffer);
I2S_RxTransferNonBlockingDMA(I2S0, &handle, transfer);
/* Enqueue next buffer right away so there is no drop in audio data stream when the first buffer finishes */
I2S_RxTransferNonBlockingDMA(I2S0, &handle, someTransfer);
}
void RxCallback(I2S_Type *base, i2s_dma_handle_t *handle, status_t completionStatus, void *userData)
{
i2s_tranfer_t transfer;
if (completionStatus == kStatus_I2S_BufferComplete)
{
/* Enqueue next buffer */
transfer.data = buffer;
transfer.dataSize = sizeof(buffer);
I2S_RxTransferNonBlockingDMA(base, handle, transfer);
}
}