I'm using Teensy 4.1 and trying to make a TRX, which converts 2ch monoral signals into 1ch I2S stereo signal.
I set SAI1 module as RX, receiving 2ch monorals from a source,
and SAI2 module as TX, sending 1ch stereo I2S.
Here is the problem I'm stucking on,
I don't understand how to synchronize RX and TX with source's clock (figure 1).
What I understand and have already checked:
- SAI1 module can receive 2ch monoral signals (not I2S) in slave mode (synchronizing with source's clock)
- SAI2 can send 1ch stereo I2S signal in master mode (using internal CCM)
What I don't understand:
- If both RX and TX can be slave mode
- How to synchronize SAI1 and SAI2 module with source's bit clock. Using "bit clock swap"?, Connecting the pin externally?...
Thi is the configration of RX/TX registers.
In the first place, Can SAI1 module be used as both RX and TX (figure 2)?
I'm using SAI1(RX) and SAI2(TX) separetely now though...
I'd appreciate if you kindly replied.
I set SAI1 module as RX, receiving 2ch monorals from a source,
and SAI2 module as TX, sending 1ch stereo I2S.
Here is the problem I'm stucking on,
I don't understand how to synchronize RX and TX with source's clock (figure 1).
What I understand and have already checked:
- SAI1 module can receive 2ch monoral signals (not I2S) in slave mode (synchronizing with source's clock)
- SAI2 can send 1ch stereo I2S signal in master mode (using internal CCM)
What I don't understand:
- If both RX and TX can be slave mode
- How to synchronize SAI1 and SAI2 module with source's bit clock. Using "bit clock swap"?, Connecting the pin externally?...
Thi is the configration of RX/TX registers.
Code:
//0:async, 1:sync
int rsync = 0;
int tsync = 1;
//SAI1 Clock Setting (RX)
I2S1_TMR = 0;
//I2S1_TCSR = (1<<25); //Reset
I2S1_TCR1 = I2S_TCR1_RFW(RX_watermark);
I2S1_TCR2 = I2S_TCR2_SYNC(tsync) | | I2S_TCR2_MSEL(1);
I2S1_TCR3 = I2S_TCR3_TCE;
I2S1_TCR4 = I2S_TCR4_FRSZ((2-1)) | I2S_TCR4_SYWD((16-1)) | I2S_TCR4_MF | I2S_TCR4_FSP | I2S_TCR4_FPACK;
I2S1_TCR5 = I2S_TCR5_WNW((16-1)) | I2S_TCR5_W0W((16-1)) | I2S_TCR5_FBT((16-1));
I2S1_RMR = 0;
//I2S1_RCSR = (1<<25); //Reset
I2S1_RCR1 = I2S_RCR1_RFW(RX_watermark);
I2S1_RCR2 = I2S_RCR2_SYNC(rsync) | I2S_RCR2_MSEL(1);
I2S1_RCR3 = I2S_RCR3_RCE;
I2S1_RCR4 = I2S_RCR4_FRSZ((2-1)) | I2S_RCR4_SYWD((16-1)) | I2S_RCR4_MF | I2S_RCR4_FSP | I2S_RCR4_FPACK;
I2S1_RCR5 = I2S_RCR5_WNW((16-1)) | I2S_RCR5_W0W((16-1)) | I2S_RCR5_FBT((16-1));
I2S1_TCSR |= I2S_TCSR_TE | I2S_TCSR_BCE | I2S_TCSR_FR; //Transmitter Enable, BCLK Enable, FIFO Reset, (FIFO Error Interrupt Enable)
I2S1_RCSR |= I2S_RCSR_RE | I2S_RCSR_BCE | I2S_RCSR_FR | 0x00000100; //Receiver Enable, BCLK Enable, FIFO Reset, FIFO Request Interrupt Enable
//SAI2 Clock Setting (TX)
I2S2_TMR = 0;
//I2S2_TCSR = (1<<25); //Reset
I2S2_TCR1 = I2S_TCR1_RFW(TX_watermark);
I2S2_TCR2 = I2S_TCR2_SYNC(tsync) | (I2S_TCR2_BCD | I2S_TCR2_MSEL(1)) | I2S_TCR2_DIV((1));
I2S2_TCR3 = I2S_TCR3_TCE;
I2S2_TCR4 = I2S_TCR4_FRSZ((2-1)) | I2S_TCR4_SYWD((16-1)) | I2S_TCR4_MF | I2S_TCR4_FSP| I2S_TCR4_FSD | I2S_TCR4_FPACK;
I2S2_TCR5 = I2S_TCR5_WNW((16-1)) | I2S_TCR5_W0W((16-1)) | I2S_TCR5_FBT((16-1));
I2S2_RMR = 0;
//I2S2_RCSR = (1<<25); //Reset
I2S2_RCR1 = I2S_RCR1_RFW(TX_watermark);
I2S2_RCR2 = I2S_RCR2_SYNC(rsync) | (I2S_RCR2_BCD | I2S_RCR2_MSEL(1)) | I2S_RCR2_DIV((1));
I2S2_RCR3 = I2S_RCR3_RCE;
I2S2_RCR4 = I2S_RCR4_FRSZ((2-1)) | I2S_RCR4_SYWD((16-1)) | I2S_RCR4_MF | I2S_RCR4_FSP| I2S_RCR4_FSD | I2S_RCR4_FPACK;
I2S2_RCR5 = I2S_RCR5_WNW((16-1)) | I2S_RCR5_W0W((16-1)) | I2S_RCR5_FBT((16-1)); //RX LRCLK
I2S2_TCSR |= I2S_TCSR_TE | I2S_TCSR_BCE | I2S_TCSR_FR | 0x00000100; //Transmitter Enable, BCLK Enable, FIFO Reset, FIFO Request Interrupt Enable
I2S2_RCSR |= I2S_RCSR_RE | I2S_RCSR_BCE | I2S_RCSR_FR; //Receiver Enable, BCLK Enable, FIFO Reset
//SAI1 Pin Connection
IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_11 = 3; //SAI1_RX_BCLK (pin 21)
IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_10 = 3; //SAI1_RX_SYNC (pin 20)
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_15 = 3; //SAI1_RX_Data0 (pin 8)
IOMUXC_SAI1_RX_BCLK_SELECT_INPUT = 1; // 1=GPIO_AD_B1_11_ALT3
IOMUXC_SAI1_RX_SYNC_SELECT_INPUT = 1; // 1=GPIO_AD_B1_10_ALT3
IOMUXC_SAI1_RX_DATA0_SELECT_INPUT = 2; // 2=GPIO_B0_15_ALT3
//SAI2 Pin Connection
IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_07 = 2; //SAI2_MCLK (pin 33)
IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_06 = 2; //SAI2_TX_BCLK (pin 4)
IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_05 = 2; //SAI2_TX_SYNC (pin 3)
IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_04 = 2; //SAI2_TX_DATA (pin 2)
In the first place, Can SAI1 module be used as both RX and TX (figure 2)?
I'm using SAI1(RX) and SAI2(TX) separetely now though...
I'd appreciate if you kindly replied.