Teensy 4.0 Alternate I2S Pins

Status
Not open for further replies.

jkoffman

Well-known member
Hi all,

I'd love a double check on this. I've been spending a bit of time learning about I2S on the Teensy 4.0. I understand that there are a maximum of 5 pins can can do I2S. I'm looking at going for quad in/quad out. By default this would use pins 8 and 6 for I2S data in, and 7 and 32 for I2S data out. This leaves pin 9 unused for I2S.

I believe the answer to this is no, but I just want to confirm that there isn't a way to swap pin 9 for pin 32 on the i2s_quad object, correct?

Alternatively, if I really wanted to avoid using pin 32 (it's a bit trickier to connect to), I could use the i2s_hex out and just ignore channels 3 and 4, correct?

Thank you!
 
I don't have any way to test this myself or I would check for you, but based on output_i2s_quad.cpp in the begin function (besides the corresponding pin configs) the parts in red are probably where you would set it up.
Code:
//from imxrt.h
#define I2S_TCR3_TCE_2CH		((uint32_t)0x30000)
Code:
#elif defined(__IMXRT1062__)
	const int pinoffset = 0; // TODO: make this configurable...
	memset(i2s_tx_buffer, 0, sizeof(i2s_tx_buffer));
	AudioOutputI2S::config_i2s();
[COLOR="#FF0000"]	I2S1_TCR3 = I2S_TCR3_TCE_2CH << pinoffset;[/COLOR]
	switch (pinoffset) {
	  case 0:
		CORE_PIN7_CONFIG  = 3;
		CORE_PIN32_CONFIG = 3;
		break;
	  case 1:
		CORE_PIN32_CONFIG = 3;
		CORE_PIN9_CONFIG  = 3;
		break;
	  case 2:
		CORE_PIN9_CONFIG  = 3;
		CORE_PIN6_CONFIG  = 3;
	}
	dma.TCD->SADDR = i2s_tx_buffer;
	dma.TCD->SOFF = 2;
	dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
	dma.TCD->NBYTES_MLOFFYES = DMA_TCD_NBYTES_DMLOE |
		DMA_TCD_NBYTES_MLOFFYES_MLOFF(-8) |
		DMA_TCD_NBYTES_MLOFFYES_NBYTES(4);
	dma.TCD->SLAST = -sizeof(i2s_tx_buffer);
	dma.TCD->DADDR = (void *)((uint32_t)&I2S1_TDR0 + 2 + pinoffset * 4);
	dma.TCD->DOFF = 4;
	dma.TCD->CITER_ELINKNO = AUDIO_BLOCK_SAMPLES * 2;
	dma.TCD->DLASTSGA = -8;
	dma.TCD->BITER_ELINKNO = AUDIO_BLOCK_SAMPLES * 2;
	dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
	dma.triggerAtHardwareEvent(DMAMUX_SOURCE_SAI1_TX);
	dma.enable();
	I2S1_RCSR |= I2S_RCSR_RE | I2S_RCSR_BCE;
	I2S1_TCSR = I2S_TCSR_TE | I2S_TCSR_BCE | I2S_TCSR_FRDE;
[COLOR="#FF0000"]	I2S1_TCR3 = I2S_TCR3_TCE_2CH << pinoffset;[/COLOR]
	update_responsibility = update_setup();
	dma.attachInterrupt(isr);
#endif

Bits 16-19 each correspond to one tx channel, ie bit 16 is Out1A bit 18 is Out1C, so what I would try is setting I2S1_TCR3 equal to ((uint32_t)0x50000) in the two red places and make sure you have the right configs for pins 7 and 9.
 
Well, I finally had enough time to play with this!

I started out by testing both hex and quad output with a simple sine wave object feeding them. That all worked well. Then I started hacking away...

Sadly...it didn't work. I changed the I2S1_TCR3 values as you suggested, and changed the config line for pin 9. I got no audio out of anything. I restored, and started playing with the pinoffset definition, and that definitely works.

I'm still chipping away at it. I'm looking at the hex object as well for ideas. I'll keep plugging away and update here if I make any progress.
 
Ok, I'm a bit stymied here. Based on the official combinations in output_i2s_quad.cpp (7 and 32, 32 and 9, or 9 and 6) it would appear the the two output channels need to be consecutive. This may be why a value of 0x50000 won't work for I2S1_TCR3.

In playing with it further, I tried dropping in a value of 0x70000, which is the value for 3 channels. I figured that maybe it would enable 3 channels but I'd only be transferring data for 2 channels, so one would just be silent. However, using this value also seems to result in no output.

I'm definitely stuck there.

I also can't figure out why I2S1_TCR3 seems to get assigned the same value...twice. That doesn't make much sense to me unless something else is manipulating it in the middle, but I can't see where.
 
Status
Not open for further replies.
Back
Top