First slot / channel missing in FIFO for I2S in TDM/DSP mode (16-channels / 32-bit / 48 kHz)
Closed this issue · 3 comments
Using the EVK MIMXRT685
as I2S
SLAVE configured as:
- TDM / DSP mode A (mono)
- 48kHz (SCK at ~25MHz)
- 16 slots (channels) per frame
- 512 SCK per frame
- 32 SCK per slot
- 32 bits of audio data per slot, left aligned
- WS pulsed for one SCK time
- Data sampled on WS rising edge
Let's take as example the transmission as depicted here:
0x000001FF
on channel 10x00000200
on channel 20x000003FF
on channel 3- ...
0x00001000
on channel 16
I2S
is configured in interrupt mode, as follows:
static void RxCallback(I2S_Type *base, i2s_handle_t *handle, status_t completionStatus, void *userData)
{
i2s_transfer_t *transfer = (i2s_transfer_t *)userData;
I2S_RxTransferNonBlocking(base, handle, *transfer);
}
void I2S_Setup(void)
{
I2S_RxGetDefaultConfig(&s_RxConfig);
s_RxConfig.masterSlave = kI2S_MasterSlaveNormalSlave; /* Normal Slave */
s_RxConfig.mode = kI2S_ModeDspWsShort; /* DSP mode, WS having one clock long pulse */
s_RxConfig.leftJust = true; /* Left Justified */
s_RxConfig.divider = 1; /* As slave, divider need to set to 1 according to the spec. */
s_RxConfig.oneChannel = true; /* I2S data for this channel pair is treated as a single channel */
s_RxConfig.dataLength = 32;
s_RxConfig.frameLength = 32;
I2S_RxInit(I2S_RX, &s_RxConfig);
s_RxTransfer.data = &s_Buffer[0];
s_RxTransfer.dataSize = sizeof(s_Buffer);
I2S_RxTransferCreateHandle(I2S_RX, &s_RxHandle, RxCallback, (void *)&s_RxTransfer);
I2S_RxTransferNonBlocking(I2S_RX, &s_RxHandle, s_RxTransfer);
}
Warning
The problem is that the buffer is consistently missing the data of the first channel 0x000001FF
when starting the capture. If I look at the content of FIFORD
on the very first interrupt, the content is 0x00000200
instead of the data of the first channel.
Hi @carlocaione, thanks for reporting the issues, I have also assigned developer to check the issues internally. Feedback may be delayed, appreciate for your patience.
This is due to a misconfiguration of the I2S instance on my side.
To read 16-channels we need at least I2S instances (for example I2S4
and I2S5
), configured as follows:
s_RxConfig.masterSlave = kI2S_MasterSlaveNormalSlave;
s_RxConfig.mode = kI2S_ModeDspWsShort;
s_RxConfig.dataLength = 32;
s_RxConfig.frameLength = 32 * 16U;
s_RxConfig.position = 0;
I2S_RxInit(I2S5, &s_RxConfig);
I2S_EnableSecondaryChannel(I2S5, kI2S_SecondaryChannel1, false, (64 * 1));
I2S_EnableSecondaryChannel(I2S5, kI2S_SecondaryChannel2, false, (64 * 2));
I2S_EnableSecondaryChannel(I2S5, kI2S_SecondaryChannel3, false, (64 * 3));
s_RxConfig.position = 256;
I2S_RxInit(I2S4, &s_RxConfig);
I2S_EnableSecondaryChannel(I2S4, kI2S_SecondaryChannel1, false, 256 + (64 * 1));
I2S_EnableSecondaryChannel(I2S4, kI2S_SecondaryChannel2, false, 256 + (64 * 2));
I2S_EnableSecondaryChannel(I2S4, kI2S_SecondaryChannel3, false, 256 + (64 * 3));
To be perfectly honest the user manual is not crystal clear about how and when to use multiple instances and channels pairs. Thank you @frankybkimz for your support.
Closing this down.