I have the SAI driver from the KSDK v2.0 working for the KL27Z. The problem that I have is that the SAI is configured for 2 16-bit words in stereo mode. I only see 1 channel out on the I2S bus. The api writes 2 words into TDR which I believe causes the first word to be overwritten. Since the FIFO is only 1 word deep the first channel is overwritten by the second and 0x0 is transmitted in its place.
I attempted to enable the FIFO bit packing but was not successful. Does anyone have code to enable the bit packing on the KL27z? Or do I need to loop waiting for the fifo empty flag before sending in the second word?
I have checked the data sheet of TLV320DAC3120_10, it says that "
The audio bus of the TLV320DAC3120 can be configured for left- or right-justified, I2S, DSP, or TDM
modes of operation, where communication with standard telephony PCM interfaces is supported within the
TDM mode. These modes are all MSB-first, with data width programmable as 16, 20, 24, or 32 bits by
configuring page 0 / register 27, bits D5–D4.".
It means the slot length can be 16, 20,24,32. It is okay if you want to use 16 bits slot length and use the SAI module of Kl27 as master mode(bit clock and frame clock are from SAI of Kl27).
If you use 16 bits mode and master mode, you can configure the SAI as following:
If you use 16 bits mode, you can use the setting in SAI register:
base->TCR5 = I2S_TCR5_WNW(15U) | I2S_TCR5_W0W(15U) | I2S_TCR5_FBT(15U);
with MSB first by setting the MF bit in I2Sx_TCR4.
Because the I2Sx_TDR register is 32 bits, you just write a 16 bits data to the low 16 bits of I2Sx_TDR register, it is okay.
Regarding the SAI driver, you can use corresponging emurator.
thank you for approving that values. I'm using K64, but I think the SAI - module of K27 and K64 are equal. Are'nt they?
In KSDK2.0 the SAI driver ("fsl_sai.c" SAI_TxSetFormat() ) gets the pointer to sai_transfer_format_t with the Information "format->bitWidth" but in the source code it is hard coded to 32bits. The bitWith of the data - stream is ignored.
I think this is a error in SAI-driver implementation. --> you should review this piece of code.
I think the code has disadvantage, anyway, the SAI_TxSetFormat() should write the I2S_TCR5_WNW and I2S_TCR5_W0W based on the slot length, in your case, the two components should be 15 in decimal for your application, they can not be written with a fixed value 31.
As an workaround, if you do want to call the driver, you can change the SAI register directly after you call the driver.
the SAI module for the Kl27 and k64F are the same, maybe they have different based address for the modules.
thank you for your answer.
I changed the SAI_TxSetFormat() function to use the bitWith as information for the output slot length. --> I2S_TCR5_WNW and I2S_TCR5_W0W = (bitWith-1)
Hi xiangjun.rong, Andrew DeLiso,
we use KSDK2.0 with K64 in a design with TLV320DAC3120 (Sound: Mono Audio DAC with amplifier).
I have a working code with SDK1.3. --> Hardware and setup of the codec are working.
But with KSDK2.0 I have real Problems to set up an I2S audio data stream.
I want to use the following setup:
config.protocol = kSAI_BusI2S;
config.syncMode = kSAI_ModeAsync;
config.mclkOutputEnable = true;
config.mclkSource = kSAI_MclkSourceSysclk;
config.bclkSource = kSAI_BclkSourceMclkDiv;
config.masterSlave = kSAI_Master;
format.sampleRate_Hz = kSAI_SampleRate16KHz;
format.bitWidth = kSAI_WordWidth16bits;
format.Stereo = kSAI_MonoLeft;
format.masterClockHz = 6144000;
format.watermark = 4;
format.channel = 0;
format.protocol = kSAI_BusI2S;
When I send out data with SAI_TransferTxSetFormatEDMA(...), there is no Information on I2S0_TXD0.
I changed "fsl_sai.c" SAI_TxSetFormat() as suggested by Andrew DeLiso.
I think, there is an additional error in SAI - setup SAI - module I2S_TCR4_SYWD.
SYWD is set to 0x1f regardless of the real bitWith of the sound - data. I think SYWD should be set to bitWith-1.
- Can you provide a newer Version of fsl_sai.c?
- Has anyone get the I2S Hardware on K64 running with KSDK2.0? -- and probably share his knowledge about erros in fsl_sai.c?
The SYWD is correct. When running in I2S you always have a Left and Right channel. I have my system working well with only that one change (Also reflected the same with Rx). I am also using the DMA without issue. I don't have much else I can add. I would check to see if you clocks are on the I2S correct, I was running the KL27 as a slave so my clocks were externally generated.
thank you for your answer.
The data output of my K64 only works with SYWD set to 0x0f ( ==bitWith-1).
I will have to look a bit deeper into KSKS1.3 SAI Driver.
After looking at this deeper, it may be an issue with setting the word sizes, not FIFO controls.
In the file fsl_sai.c
@@ -551,11 +551,11 @@ void SAI_TxSetFormat(I2S_Type *base,
base->TCR5 = I2S_TCR5_WNW(31U) | I2S_TCR5_W0W(31U) | I2S_TCR5_FBT(31U);
- base->TCR5 = I2S_TCR5_WNW(31U) | I2S_TCR5_W0W(31U) | I2S_TCR5_FBT(format->bitWidth - 1);
+ base->TCR5 = I2S_TCR5_WNW(format->bitWidth - 1) | I2S_TCR5_W0W(format->bitWidth - 1) | I2S_TCR5_FBT(format->bitWidth - 1); }
/* Set mono or stereo */
base->TMR = (uint32_t)format->stereo;
Can someone confirm this bug?
I want to confirm with you about the I2S timing you desired. For the I2S timing, one transmit line can transmit two channels, for example SAI_TX_DATA0 pin can transmit two channels in I2S timing, when the SAI_TX_SYNC is HIGH logic( slot0), the channel0 is transmitted, when the SAI_TX_SYNC is low(slot1), channel1 is transmitted, in other words, I2S timing has two slots:slot0 and slot1, every slot length can be 32 bits, 24 bits or 16 bits, it is programmable. For your case, it is okay to set the slot length as 16 bits instead of 32 bits.
BTW, it seems that the Kl27Z does not have SAI module, it has FlexIO module which can simulate the I2S timing, am I right?