Teensy 3.2 Multiple I2S Input

Status
Not open for further replies.

operator

Member
I am currently in the process of designing a Bluetooth voice modulator.

Project GitHub
Project Site documenting test boards.

Hardware in use:
Teensy 3.2 - PJRC
Audio Adaptor Board for Teensy - PJRC
Silicon Labs WT32i (datasheet here).

The proposed functionality is as follows:
  1. The Teensy will act as the I2S Master, generating all clocks.
  2. The SGTL5000 on the Audio Adaptor Board will act as a slave, receiving its clock signals from the Teensy.
  3. The WT32i will act as a slave, receiving its clock signals from the Teensy.
  4. The Teensy will pass the data from the WT32i I2S to the SGTL5000 which will play this audio through the headphone out of the Audio Adaptor Board.
  5. The Teensy, upon receiving a PMW signal or GPIO state, will read a WAV file from a SanDisk SD card on the Audio Adaptor Board.
  6. The Teensy will play this WAV file through the headphone out of the Audio Adaptor Board.
(Note that WT32i audio and WAV audio need not necessarily be simultaneous, though this is preferable.)

This configuration would seem to require that the Teensy act as a Master to two I2S slave devices (the SGTL5000 on the Audio Adaptor Board and the WT32i).
This would seem somewhat akin to the quad-channel audio mentioned in this post.
Documented on Sparkfun (although this is for quad-output which doesn't seem to be what I need).
And, of course, possibly the very little documentation provided with the AudioInputI2SQuad (i2s_quad) function of the Teensy Audio Library.
Indeed, the description of this function states:
Receive 16 bit quad (4) channel audio from two audio shields or another I2S devices, using I2S master mode.​

Here is a simplified diagram that is representative of the proposed configuration:
TeensyAudio.png

As per the audio tutorial and Audio Library tutorial video, the Teensy is perfectly capable of reading a WAV file from an SD card upon a GPIO event and playing this audio through the headphone out of the Audio Adaptor Board.
This satisfies points 1, 2, 5, and 6 of the above-listed proposed functionality list, leaving only points 3 and 4:
3. The WT32i will act as a slave, receiving its clock signals from the Teensy.
4. The Teensy will pass the data from the WT32i I2S to the SGTL5000 which will play this audio through the headphone out of the Audio Adaptor Board.

From section 9.3 of the WT32i's datasheet regarding the I2S interface:

The digital audio interface supports the industry standard formats for I2S, left-justified or righ justified.
The interface shares the same pins as the PCM interface, which means each audio bus is mutually exclusive in its usage.
The internal representation of audio samples within WT32i is 16-bit and data on SD_OUT is limited to 16-bit per channel.
WT32i is not capable of generating the master clock for I2S, so it can only be used as a master with a codec that is capable of producing the master clock from the SCK.​

So the WT32i is perfectly capable of acting as a slave and receiving clocks from an outside source.

The pinout on the WT32i is as such:
View attachment 8030

(Note that earlier versions of the datasheet, like those on Mouser, have the pins incorrectly numbered. The most recent datasheet can be found here.)

The WT32i documentation uses different vernacular for its I2S signals than Teensy does.
From the I2S Wiki page it would seem that the I2S Word Select line on the WT32i corresponds to the LRCLK line of the Teensy:
Word clock line - also called word select (WS) or left right clock (LRCLK)​

And that the the WT32i's "I2S Clock" would correspond to the Teensy's Bit Clock (BCLK).

Here is my best guess at a netlist:
WT32iSGTL5000Teensy
I2S_IN (27) I2S Data InputNot connectedNot Connected
I2S_OUT (28) I2s Data OutputI2S_DIN (26)RX (13)
I2S_WS (29) I2S Word SelectI2S_LRCLK (23)LRCLK (23)
I2S_SCK (30) I2S ClockI2S_SCLK (24)BCLK (9)

QUESTIONS:

Are there any particularly well documented examples of using the Teensy to read data from an external I2S slave (along with or other than the SGTL5000)?

Can the clock signals from an I2S Master (The Teensy) simply be tied to multiple Slaves (WT32i and SGTL5000) or is some other configuration required?
It would seem so, but I'm having a difficult time confirming this absolutely.
The Teensy to Audio Adaptor Board connections are fine. I essentially need to figure out where to route the WT32i's connections.

Is the Teensy expecting the I2S data to be left or right justified?

Can the WT32i's "I2s Data Output" line be connected to the Teensy's RX (13) pin or would it need it's own dedicated pin?
I'm thinking that the Teensy will probably require a unique pin for each I2S Slave (WT32i and SGTL5000) but perhaps I'm over complicating the matter entirely.
I would guess that perhaps the WT32i's "I2S Data Output" pin might need to be routed to Teensy pin 30 on the underside of the board as it is shown as the secondary RX in the AudioInputI2SQuad function.

What might the Teensy Audio System Design Tool configuration function blocks and their connections look like for this type of setup?
Presumably it will require an AudioControlSGTL5000 (sgtl5000) object and a AudioOutputI2S (i2s) object for headphone output as well as an AudioPlaySdWav (playSdWav) object for reading from the SD card.
I would think that I could get away with a single AudioInputI2S (i2s) function to read from the WT32i but perhaps I'm missing something that might require AudioInputI2SQuad (i2s_quad) instead?
My apologies for the confusion, it just doesn't seem terribly well documented anywhere that I can seem to located.

It is quite possible that I am making mountains out of molehills but I'm having a rather difficult time finding appropriate documentation to check my work.

Any assistance or recommendations that anyone can provide would be greatly appreciated!
 
Last edited:
I am currently in the process of designing a Bluetooth voice modulator.

Somehow I miss the expected functionality (I don't know what you mean by voice modulator)
So, I put first my questions, and put then my suggestion for the most complicated configuration using the possibilities of teensy

why do you need a teensy?
I understand the WT32i can do all alone (audio in/out basic dsp, BT in/out).
Is it only to access uSD Card, or WT32i has no headphone output?

Is the teensy expected to do some special signal processing before putting data to sgtl5000?
Do you wanted also to stream audio from BT to uSD card or viceversa, or only from uSD to SGTL5000?

Why do you need the WT32i?
if you only receive audio stream via BT, you could only use a BT module.
Same is true if you wanted to transmit audio from sgtl5000.
or is it that audio-BT interface you are interested?

Do you only wanted to replicate Figure 34 in datasheet replacing the TLV320AIC32 with a SGTL5000?
in that case you need (you will figure out the pin numbers)
- MCLK for SGTL5000 from Teensy.
- Bitclock for both from Teensy
- LR sync for both from Teensy
- data directly between SGTL and WT32i (as in Figure 34)

To have additional uSD playback possibility I would
MCLK: teensy -> SGTL
BitClock: teensy -> SGTL and WT32i

Using Teensy quad I2S (dual stereo) (you will figure out the pin numbers)
1)WT32i: I2S_TX -> Teensy:I2S_RX1
2)WT32i: I2S_RX -> Teensy:I2S_TX1
3)SGTL: I2S_TX -> Teensy: I2S_RX0
4)SGTL: I2S_RX -> Teensy: I2S_TX0

with that you can
-receive from WT32i and play on SGTL: (1)+(4)
-receive on SGTL and send with WT32i: (3)+(2)
-play uSDcard on WT32i: (2)
-record onuSDcard from WT32i: (1)
-play uSDcard on SGTL: (4)
-record onuSDcard from SGTL: (3)

You may control functionalities using GPIO buttons, or touch screen.

To use PJRC's audiotool you may survive without writing a own WT32i node

Note: 2nd I2S data port cannot be accesses independently of primary data port
So SW may be a little bit tricky.
 
Last edited:
Hello WMXZ, thank you very much for taking the time to reply to my post.

Somehow I miss the expected functionality (I don't know what you mean by voice modulator)
So, I put first my questions, and put then my suggestion for the most complicated configuration using the possibilities of teensy

No problem, I appreciate you replying at all!

To summarize from my GitHub:
A voice modulator is device for altering (or modulating) the sound of one's voice.
Specifically, this project aims to recreate the effect of ring modulation, whereby two signals are mixed together (i.e. - multiplied).
The first of these signals is a voice and the second is a sine wave at a frequency of about 30Hz.
This is similar to the functionality of a Moog Ring Modulator.​

I have played with the multiplication and distortion functions and they are working as expected when playing audio from a WAV file.
I would like to do the same using audio data read from the WT32i's I2S.

why do you need a teensy?
I understand the WT32i can do all alone (audio in/out basic dsp, BT in/out).
Is it only to access uSD Card, or WT32i has no headphone output?

Great question!

I actually tried a few other uControllers and settled in on the Teensy.
The fact that the Teensy and Audio Adaptor Board are already capable of playing WAV files from an SD card and the necessary libraries already exist to handle the distortion and multiplication of audio I require are probably the main points.

There is actually quite a bit more going on here but I did not want to weigh down my post with a lot of extraneous information not related to the problem at hand.
Additional I/O is required to read from some pots, there is an isolated PWM input from an RC receiver, a couple of MOSFETs to drive some high-power LEDs, a power supply, an external amplifier, etc., etc.
All of this additional functionality is already working and I don't foresee too many issues integrating all of it once I am able to sort out the I2S issues I seem to be having.
I am attempting to solve the problem in its simplest form (just getting the Teensy to read I2S data from the WT32i) without complicating matters related to the rest of the design.

While the WT32i does have basic DSP functionality, it is extremely convoluted compared to the simplicity of working with Teensy's libraries.

Is the teensy expected to do some special signal processing before putting data to sgtl5000?
Do you wanted also to stream audio from BT to uSD card or viceversa, or only from uSD to SGTL5000?

That is correct, the Teensy will process the audio data by applying several effects and performing some basic FFT.
This processing is relatively simple given the great libraries already available for Teensy but only if I can read the I2S data to begin with.

I have no need to write to the SD card from the Teensy at all.
The SD card will simply hold a WAV file that is played upon a GPIO event (which already works quiet well).
This WAV file requires no additional processing and is very much akin to the example code provided for playing WAV files from SD cards.

Why do you need the WT32i?
if you only receive audio stream via BT, you could only use a BT module.
Same is true if you wanted to transmit audio from sgtl5000.
or is it that audio-BT interface you are interested?

The WT32i was chosen for a number of reasons, not the least of which being that I have worked with it before.
It is a Bluetooth Classic (3.0) audio module with well developed firmware, has great range, supports HSP and A2DP Sink profiles, and pairs easily with a number of headsets I have tried.
Somewhat inconsequentially, I also happen to have a fairly good relationship with some of the folks at Silicon Labs.

You are correct in noting that it is the audio-BT interface that I am interested in.
As a matter of fact, this audio/BT interface is already working.

The WT32i does support single-ended line out which is working and can be read from the Audio Adaptor Board's line-in.
While I could just stick with this analog signal, it seems somewhat over-complicated to go out the WT32i's DAC then right back into the SGTL5000's ADC then pass the audio along to the Teensy.
Not to mention the additional components and board space required for the analog filtering and the care that must be taken when routing analog signals.

If I am able to simply read the audio data from the WT32i's I2S bus directly into the Teensy, this would seem like a far more elegant solution.

Do you only wanted to replicate Figure 34 in datasheet replacing the TLV320AIC32 with a SGTL5000?
in that case you need (you will figure out the pin numbers)
- MCLK for SGTL5000 from Teensy.
- Bitclock for both from Teensy
- LR sync for both from Teensy
- data directly between SGTL and WT32i (as in Figure 34)

Figure 34 shows the WT32i connected to the TLV320AIC32 via I2S.
I would like to connect the WT32i to the Teensy via I2S.

From you description it would seem as though the BitClock and LRCLK can indeed be shared on common buses between the Teensy (Master), and WT32i and SGTL5000 (both Slaves).
Is this correct?

The data line from the WT32i would need to connect to the Teensy as the Teensy is responsible for handling the audio processing in my proposed configuration.

Just for the sake of folks visiting this thread later, here is the relevant portion of Figure 34:
Screenshot from 2016-09-05 10:33:25.png

The TLV320AIC32 is a stereo codec from TI, similar in many ways to the SGTL5000 from NXP.

To have additional uSD playback possibility I would
MCLK: teensy -> SGTL
BitClock: teensy -> SGTL and WT32i

This seems like what I was expecting, which is great.

Figure 34 above seems to show that the WT32i does not require the MCLK to be provided.
The SGTL5000 does require this clock which is generated by the Teensy and this signal is already routed on the Audio Adaptor Board, so I think we're good there.

The BitClock is also generated by the Teensy and is provided to both the SGTL5000 and WT32i, which also seems to make sense.
Can this simply be done on a common bus by just tying the pins together?

Using Teensy quad I2S (dual stereo) (you will figure out the pin numbers)
1)WT32i: I2S_TX -> Teensy:I2S_RX1
2)WT32i: I2S_RX -> Teensy:I2S_TX1
3)SGTL: I2S_TX -> Teensy: I2S_RX0
4)SGTL: I2S_RX -> Teensy: I2S_TX0

Ah, this is the sort of thing I think I need.

Here is a stab at pin numbers for the respective ICs based upon your suggestion:
1)WT32i: I2S_TX (WT32i Pin 28) -> Teensy:I2S_RX1 (Teensy Pin 30?)
2)WT32i: I2S_RX (WT32i Pin 27) -> Teensy:I2S_TX1 (Teensy Pin ?)
3)SGTL: I2S_TX (SGTL Pin 26) -> Teensy: I2S_RX0 (Teensy Pin 13)
4)SGTL: I2S_RX (SGTL Pin 25) -> Teensy: I2S_TX0 (Teensy Pin 22)

The SGTL5000 to Teensy pins (3 & 4 above) are consistent with those present on the Audio Adaptor Board, so these make sense.

The WT32i to Teensy connections are still a bit unclear to me.
I presume that the WT32i to Teensy:I2S_RX pin could be Teensy pin 30?
I take this both from the Sparkfun article that appears to use pin 30 for the secondary RX in their quad-channel audio setup,
as well as from input_i2s_quad.cpp which shows pins 13 and 30 configured as I2S RX0 and RX1 respectively:
(By default, assuming I do not modify this code)
Code:
CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0
CORE_PIN30_CONFIG = PORT_PCR_MUX(4); // pin 30, PTC11, I2S0_RXD1

Do I even need to connect the WT32i's I2S_RX to anything on the Teensy?
If so, where can this pin be configured?
If not, can I just leave it floating on the WT32i?

with that you can
-receive from WT32i and play on SGTL: (1)+(4)
-receive on SGTL and send with WT32i: (3)+(2)
-play uSDcard on WT32i: (2)
-record onuSDcard from WT32i: (1)
-play uSDcard on SGTL: (4)
-record onuSDcard from SGTL: (3)

This sounds great. It's actually quite a bit more than I need to do.
I only need to be able to:
-receive from WT32i (then process on Teensy) and play on SGTL
-play uSDcard on SGTL

You may control functionalities using GPIO buttons, or touch screen.

This is pretty much the plan. Playing of the WAV file will be triggered with a PWM signal from an RC receiver and parameters of the distortion and mixing of the audio received from the WT32i will be controlled with pots.
No need for any touch screen, this design involves absolutely minimal user interaction or configurability beyond what has already been mentioned.

To use PJRC's audiotool you may survive without writing a own WT32i node

I am afraid that I do not follow.
I do plan to use the Audio System Design Tool to generate the bulk of the setup code then make minor modifications where necessary.

Note: 2nd I2S data port cannot be accesses independently of primary data port
So SW may be a little bit tricky.

I apologize for my confusion but I do not understand what you mean by this.
Would you please be so kind as to clarify and/or elaborate?


One point that is still quite confusing to me is what sort of I2S data Teensy is expecting to see.

The WT32i's I2S can be configured through a series of registers as seen in section 10.3 of the datasheet:
Screenshot from 2016-09-05 12:35:43.png

I can probably sort out the bit masking but I have no clue which parameters to configure to provide the Teensy with the data it is expecting to see.
(i.e. - left or right justified? Attenuation? Resolution? Bit cropping?)

The SGTL5000 has similar control registers which are configured in control_sgtl5000.cpp, though I seem to be having some trouble understanding exactly what parameter values is has configured.

From the iWrap 6.0.0 user guide (the firmware used on the WT32i):
- IWRAP is flexible about the bitdepth when configured as I2S SLAVE. The bitdepth per channel
can be anything between 16 and 32. The BCLK for CVSD should then be between 256 kHz
(8kHz*2*16 ) and 512 kHz (8kHz*2*32) and for WBS/MSBC between 512 kHz (16kHz*2*16)
and 1024 kHz (16kHz*2*32).​

Despite my best efforts I cannot seem to sort out what bit-depth I might need.
I know that the Teensy Audio Board supports 16 bit, 44.1 kHz sample rate audio. Is that per channel or total?

Thank you again for your thoughtful and thorough response.
I very much appreciate your time and effort.
 
I know it's generally poor form to reply to one's own posts but I wanted to provide additional data that may be helpful.

Here are the four signals between the Teensy and WT32i when a Bluetooth audio stream is NOT active.

CH1 -> Teensy LRCLK (WT32i Word Clock)
CH2 -> Teensy BCLK (WT32i I2S Clock)
CH3 -> WT32i I2S In
CH4 -> WT32i I2S Out

(Note: The voltage scaling differs between signals and is shown on the bottom of the screen. This was necessary to get them all in the same shot.)
DS1Z_QuickPrint8.png

Enabling the audio stream results in the WT32i's I2S output flattening out:
DS1Z_QuickPrint9.png

Here is a cleaner shot of the CH4 WT32i I2S output when a Bluetooth audio connection is NOT active:
DS1Z_QuickPrint13.png

And when a Bluetooth audio connection IS active:
DS1Z_QuickPrint14.png

I would expect to see something more akin to Figure 24 in the WT32i datasheet but it does not appear to reflect this.
Perhaps there is something on the WT32i that needs to be configured. I will go check on the SiLabs forums for this piece of the puzzle.
Screenshot from 2016-09-05 15:37:28.png

CH1 and CH2 are indeed clock signals generated by the Teensy as they are present when the WT32i is removed from the circuit.
DS1Z_QuickPrint10.png

The Teensy audio board page specs the LRCLK to be @ 44.1 kHz and BCLK to be @ 1.41 MHz
My scope measures LRCLK to be @ 44.2 kHz and BCLK to be @ 1.25 MHz
DS1Z_QuickPrint11.png
 
Are there any particularly well documented examples of using the Teensy to read data from an external I2S slave (along with or other than the SGTL5000)?

Not really. A little work has been done with other chips, but mostly as outputs.


Can the clock signals from an I2S Master (The Teensy) simply be tied to multiple Slaves (WT32i and SGTL5000) or is some other configuration required?
It would seem so, but I'm having a difficult time confirming this absolutely.

I'm going to stop short of saying "absolutely", but will go with "really ought to work". Maybe after you've done this you can post a followup to fill in the "absolutely" blank?

In theory any of the I2S master mode objects ought to work together. But mixing the quad and stereo ones is a path not traveled much (in fact, it's probably never been tested). If you need both input and output, I recommend using both quad objects. If you only need stereo output, just leave two of the signals unconnected on the quad output object. Then again, maybe after you've got it all working, give the stereo only output a try to see if it works? (and post a bug report if it doesn't....)

Is the Teensy expecting the I2S data to be left or right justified?

I2S always uses a clearly alignment where the bits are aligned 1 BCLK cycle before LRCLK changes.

Many chips support I2S and a variety of left & right aligned formats. The choice should be mutually exclusive. When using I2S, there should not be any options about left vs right, because I2S uses its own well defined alignment.

Looks like you're on the right track with the clock signals. Yeah, it's a bit confusing when every chip uses slightly different names for the same signals.

Here is a stab at pin numbers for the respective ICs based upon your suggestion:
1)WT32i: I2S_TX (WT32i Pin 28) -> Teensy:I2S_RX1 (Teensy Pin 30?)
2)WT32i: I2S_RX (WT32i Pin 27) -> Teensy:I2S_TX1 (Teensy Pin ?)
3)SGTL: I2S_TX (SGTL Pin 26) -> Teensy: I2S_RX0 (Teensy Pin 13)
4)SGTL: I2S_RX (SGTL Pin 25) -> Teensy: I2S_TX0 (Teensy Pin 22)

Yes, this looks like you're on the right track. Each data pin communicates a stereo stream in 1 direction.

Teensy: I2S_RX1 is Teensy Pin 30
Teensy: I2S_TX1 is Teensy Pin 15
Teensy: I2S_RX0 is Teensy Pin 13
Teensy: I2S_TX0 is Teensy Pin 22

One minor gotcha is the 0.1 uF capacitor on pin 15 of the audio shield. If connect pin 15 to both the shield and your WT32i, with the expectation that the audio shield will ignore pin 15, be sure to desolder than 0.1 uF capacitor so it doesn't create a huge capacitive load Teensy 3.2 to drive when trying to send the data.

The WT32i to Teensy connections are still a bit unclear to me.
I presume that the WT32i to Teensy:I2S_RX pin could be Teensy pin 30?

Assuming you've connected the clocks correctly and put the WT32i into the mode where it transmits I2S data, you can connect its data output pin to either pin 13 or 30 on Teensy. Obviously if using pin 13, you must not have the SGTL5000 also connected to 13, because 2 logic output driving the same wire is a conflict which at best results in corrupted data and in the worst case stresses or damages the output buffers in both devices.

The Teensy audio library doesn't know or care if you connect the I2S data to 13 or 30. Using the quad input object, if you connect to 13 the sound will come into the first 2 terminals in the design tool, or if using pin 30 it'll come into the second pair. Or if you short the pin to ground, every audio sample on both channels will be 0, or if you short it to 3.3V every sample will be integer -1 (or -0.00003 if printed as float on an audio +1.0 to -1.0 scale). It's really nothing magical... the hardware simply reads whatever voltage happens to be on that data pin at the moment BCLK changes (plus or minus slight setup & hold time, if you're pedantic about digital logic design). When you connect an I2S device that's sending a bit stream in sync to the BCLK output Teensy generates, it's data gets read in and becomes a pair of connections you can use in the audio library.

Do I even need to connect the WT32i's I2S_RX to anything on the Teensy?

If you only want the WT32i to send to Teensy, then probably not. You could just short it to ground. Or you could connect it to pin 15 on Teensy. But if you're using the quad output object without signals connected to the second pair of terminals in the design tool, the quad output object automatically transmits zeros. So pin 15 will just stay at ground. Remember, I2S isn't magic... it's just voltages on a wire representing your audio data at each moment BCLK changes, so when all the bits happen to be zero, the data signal just stays low all the time.

If not, can I just leave it floating on the WT32i?

Yes, you probably can, if you're ok with it hearing random input. But generally isn't not good practice to leave digital logic inputs floating. The reason why involves voltages near the logic switching threshold. Some digital logic inputs consume more power when the voltage is near the threshold, which it should normally be for only the briefest of moments as logic signals quickly change.

One point that is still quite confusing to me is what sort of I2S data Teensy is expecting to see.

The WT32i's I2S can be configured through a series of registers as seen in section 10.3 of the datasheet:
View attachment 8037

I believe CONFIG_LEFT_JUSTIFY_DELAY is the most likely to correspond to I2S.

You probably also want CONFIG_JUSTIFT_RESOLUTION to be 16 bits, through my guess is this setting will have no effect if programmed incorrectly.

I know that the Teensy Audio Board supports 16 bit, 44.1 kHz sample rate audio. Is that per channel or total?

Every channel is 16 bits, 44.1 kHz. When you draw in the design tool, each wire you create is a stream of 16 bit data at 44.1 kHz.

Hopefully these answers help. I'm curios to know if this works out, so I hope you'll post a followup with the results. ;)
 
It's great that you're researching everything so throughly, but it might also be worthwhile to just experiment a bit. The main thing you want to avoid is connecting any 2 logic outputs to each other, since that creates a conflict which can stress the hardware. But as far as data format settings, getting things wrong will often "work" with bad results like the sound too quiet, or badly distorted, or horrible white-ish noise.

Experimenting can be much more fun, and ultimately you will need to anyway.
 
Holy cow Paul, you rock!

This is excellent information and I will take it all into account while experimenting further.

I have also posted over on the SiLabs forums to ensure that I haven't missed anything obvious on the WT32i side of things.
Someone over there has gotten I2S output working for certain (and it's the correct forum to ask about the WT32i) so I want to ensure nothing there is goofy.
I'll try to stick to the Teensy side of things on your forum but will update all of the information on both sides accordingly.

Of course, I will continue to post any progress of refined questions I may encounter here as well as document any success for those who may come along later.

Thank you again so very much!
 
Updating my post to include information also posted over on the SiLabs forum for the sake of continuity.

As an experiment I reconfigured the WT32i as an I2S Master instead of a Slave and disconnected it entirely from the Teensy.

The WT32i now generates its own clock signals as one would expect:
DS1Z_QuickPrint17.png

The LRCLK (Word Select Clock) @ 8 kHz and the BCLK (I2S Clock) @ 333kHz.

The interesting thing here is that the WT32i also began to output data (@ ~16.1 kHz) when an active Bluetooth connection was established:
DS1Z_QuickPrint18.png

We also know that the Word Clock and Bit Clock generated by the Teensy are approximately 44.1 kHz and 1.25 MHz respectively.
Are these in any way easily adjustable?
I would think not but it is worth asking...

My current working theory is that either the WT32i is missing some configuration which would allow it to clock out data in I2S Slave mode when receiving clocks from the Teensy or that the Teensy generated clocks are simply too fast for the WT32i to handle.
Waiting to see what feedback SiLabs comes back with and will update here accordingly.

As an aside, just for giggles I did connect the WT32i in I2S Master mode to the Teensy (which is, of course, also in I2S Master mode).
Using the bottom two outputs of a QuadI2SInput object (corresponding to pin 30 which I have connected to the WT32i's I2S data out pin) connected to the top two inputs of a QuadI2SOutput object.

It produces some god awful noise as would be expected considering that clocks are colliding and each device is clocked differently.
Nonetheless, amidst the shrieking noise I am able to make out taps on the microphone and feedback is readily identifiable when placing the microphone next to a headphone connected to the Teensy Audio Board's headphone out jack.

Clearly, this is not yet a desirable situation however, albeit in a badly garbled form, some of the audio data does appear to be making it through.
At the very least it does provide a starting point should I be able to get the WT32i clocking out data correctly in Slave mode.
 
concerning quad I2S operation:

what I mean is that in using the quad I2S functionality you always read/write all four channels in a fixed sequence, L0,L1,R0,R1, or (ch1,ch3,ch2,ch4).
This implies that if you use quad to connect I2S_TX(0,1) to RX of (SGTL, WT32i) then both devices will receive data (clock, FS, data)

So if you wanted to output to SGTL, also WT32i will get data.
You must either have a means to switch off BT while you sending data to SGTL or be happy that WT32i transmits also (zeros, ones or what ever is in or coming to the I2S_TX1 dataport). (OK, I have no knowledge about how BT works).
On the other side, sending processed data back to the source could generate interesting effects.

While this sounds complicated, the good news is that the audio library takes care of it (from quad I2S you het the 4 channels already properly de-multiplexed)
and when you skip initially teensy processing, it should be trivial to do testing, but I suspect you are already doing it.
 
concerning quad I2S operation:

what I mean is that in using the quad I2S functionality you always read/write all four channels in a fixed sequence, L0,L1,R0,R1, or (ch1,ch3,ch2,ch4).
This implies that if you use quad to connect I2S_TX(0,1) to RX of (SGTL, WT32i) then both devices will receive data (clock, FS, data)

So if you wanted to output to SGTL, also WT32i will get data.
You must either have a means to switch off BT while you sending data to SGTL or be happy that WT32i transmits also (zeros, ones or what ever is in or coming to the I2S_TX1 dataport). (OK, I have no knowledge about how BT works).
On the other side, sending processed data back to the source could generate interesting effects.

While this sounds complicated, the good news is that the audio library takes care of it (from quad I2S you het the 4 channels already properly de-multiplexed)
and when you skip initially teensy processing, it should be trivial to do testing, but I suspect you are already doing it.

Ah, I think I understand what you mean now WMXZ. Thank you for the input.

In case I had not clearly conveyed it before, the data flow from the WT32i is unidirectional.
At present its sole responsibility is to receive audio data from a Bluetooth connection and output it over I2S.
It neither needs to receive data over I2S nor transmit any audio data over Bluetooth. Hopefully this simplifies matters a fair bit.
 
Last edited:
Hello Paul, thanks for following up.

Despite playing around with various configurations nothing has produced any solid results thus far.
I have yet to hear anything back from the SiLabs folks who are most likely to have the information required.

I have not given up on the research front though.
As it turns out, BlueGiga, prior to the SiLabs acquisition, used CSR silicon in the WT32i; specifically the CSR BlueCore®5-Multimedia External (BC05-MM BC57E687C or similar).
(The datasheet for which can be found in the sorts of places that I won't sully your forum with.)

As a matter of fact, it appears as though chunks of the WT32i datasheet are identical to the CSR datasheet, which makes perfect sense.
While the WT32i datasheet is somewhat abridged with regards to the I2S interface, the CSR documentation goes into a fair bit more detail.
In particular, it lists maximum WS (LRCLK) and SCK (BCLK) frequencies of 96 kHz and 6.2 MHz respectively.
Teensy's generated clocks are well within these bounds, so it ought to be possible.

My suspicion is that I need to tweek some PSKEY audio configuration registers somewhere so I'm digging into that at the moment.

One would expect that the SGTL5000 being an NXP part (formerly Philips who developed the I2S protocol), would have implemented it correctly.
Since the Teensy can talk to it just fine I'm assuming the implementation is perfectly sound and that this is a configuration issue.
 
Progress!

I had a few WT32i configuration tool issues that I manged to resolve.

Additionally, and not all too surprisingly, my scope loses some precision when multiple channels are active so I re-measured all clocks with only a single channel active.

The clocks generated by the WT32i in I2S Master mode are more approximately:
LRCLK (Word Select Clock) - 8.00 kHz
BCLK (Bit Clock) - 385 kHz

The clocks generated by the microcontroller in I2S Master mode are approximately:
LRCLK (Word Select Clock) - 44.1.00 kHz
BCLK (Bit Clock) - 1.41 MHz

These numbers make a fair bit more sense as:
8 kHz sample frequency x 24 bit default precision x 2 channels = 384k
and
44.1 kHz sample frequency x 16 bit precision x 2 channels = 1.4112M
(Which corresponds nicely to the numbers cited in the "Signals to Teensy" section of the Audio Adaptor Board for Teensy page.)

Instead of feeding the WT32i the 44.1 kHz and 1.41 MHz clocks from the Teensy to the WT32i, I had the Teensy generate square waves at 8 kHz and 385 kHz (The frequencies output by default when the WT32i is in master mode).
Simply using:
Code:
void setup() {
  analogWriteFrequency(4, 385000);
  analogWrite(4, 128);
  analogWriteFrequency(5, 8000);
  analogWrite(5, 128);
}

While I'm not entirely sure that it's necessary, it didn't seem to hurt anything to set the duty cycle to 50% just be certain.

Here is a comparison of the WT32i LRCLK (Word Select Clock) when in master mode (CH1) and the square wave generated by the Teensy (CH2):
DS1Z_QuickPrint25.png

As well as the WT32i Bit Clock when in master mode (CH1) and the square wave generated by the Teensy (CH2):
DS1Z_QuickPrint28.png

While the signals aren't perfectly synchronous and there is a bit of drift in one or both signals, feeding these generated clocks into the WT32i (in I2S Slave mode) does indeed produce output on the WT32i's I2S TX line when an active Bluetooth connection is established.

When relatively silent:
DS1Z_QuickPrint30.png

When speaking:
DS1Z_QuickPrint31.png

It would seem I now simply need to figure out how to configure the WT32i to work with a 44.1 kHz LRCLK (Word Select Clock) and 1.41 MHz Bit Clock with 16 bits of precision per channel.

If nothing else, this would all seem to validate that everything is hooked up properly and that neither the WT32i nor Teensy is broken.
 
So as it turns out, somewhat disappointingly but not all that surprisingly, the WT32i is simply not capable of outputting I2S data any faster than the input data.
The word clock is limited to 8kHz or, at best, 16kHz in Wide Band Speech mode.

The good news is the data does have 16 bits of precision which is exactly what the Teensy audio library uses.
The other good news is that, as per my above post, the Teensy has no problem generating the clocks (simply square waves) required to get the WT32i to pipe out data.
It simply will not do so at 44.1kHz :(

One point of potential trouble that I see is that input_i2s / input_i2s_quad and output_i2s / output_i2s_quad all rely upon AudioStream.h which appears to be where AUDIO_SAMPLE_RATE is #defined so it would presumably be difficult to adjust the sample rate of one input without messing with everything else.

Might it be possible to store the 8kHz or 16kHz audio data in a buffer then upsample/interpolate it to 44.1kHz?
Or perhaps even simpler and less computationally intensive, since the audio data is effectively mono might it be possible to "oversample" the data from a single channel (in the sense that the frame would simply repeat itself several times) then copy this data into the left and right channels of the input_i2s audio block so that it can then be used by the other audio library functions?

I may be grasping at straws here so I would most certainly appreciate any suggestions or recommendations.

Thanks!
 
With quite a lot of programming effort, you could try creating an alternate I2S object which uses 8 kHz LRCLK and converts the data to 44.1 kHz.

You could also try just running the whole audio lib at 8 kHz, which would also require a bit of hacking to reconfigure the I2S clocks. This is probably much easier, but not just a simple matter of editing the #define for the sample rate. Code inside the I2S and other input/output objects is written to configure the hardware for only 44.1 kHz.

But something you can't do is I2S inputs or outputs running at different speeds. The same LRCLK and BCLK signals are shared by all 4 channels, so all 4 have to run at the same sample rate.

It might be possible to have I2S input and output running at different sample rates, as long as all 4 inputs are the same, and all 4 outputs are the same. The chip has separate LRCLK and BCLK signals for transmit and receive. So far, we've always used only the transmit ones and configured the I2S receiver to sync to the transmit clocks. If you edit the input object to not sync to the output's clocks, maybe it could run at a different speed? Honestly, I've never tried this, so I don't know if it would really work, but it seems like the hardware might be able to do it. Of course, if the data is at a different speed, code would need to resample it if you're going to connect it with the rest of the audio lib.
 
Well just want to mention that I am working on a similar setup. I am testing a configuration where I do have a WT32 (not the i version) then the Teensy and then another WT32. Something like this:

Mobile -> WT32 -> Teensy -> WT32 -> Speaker

I read this thread and I want to share with you my findings. Like "operator" I am not successful yet, however my scope shows different values.

DS1Z_QuickPrint1.png
Yellow is the LRCLK, Green is SCK, Purple is i2s data

DS1Z_QuickPrint2.png
LRCLK = is at 44.1kHz, SCK = is at approx. 2.1MHz

DS1Z_QuickPrint3.png
Just the SCK

While doing this screenshots I connected the two WT32 directly while the Audio Sink is I2S-Slave and the Audio Source is I2S-Master. As you can imagine as soon as I put the Teensy in between, (while reconfiguring the Audio Source WT32 as Slave) nothing works anymore.

I didn't gave up here...let's see.
Mike
 
Hi Operator/Maxs ..
Have you had any progress in your projects? I am working on a project where I want to do something similar to what you are doing.
Did you have a look at other BT modules (BC127 or RN-52)?
Or did you manage to receive audio from the WT32i using an alternate I2S input or the quad input object?

RN-52 with newest firmware (1.16) is stuck at 24bit and 44.1k.
BC127 requires 64 bit clock for each world clock, but can be set to 16bit 44.1k.
 
Last edited:
I went ahead and tested teensy with the WT32i bluetooth and A2DP I2S today and it's working perfectly alongside SGTL5000 and quad in/out.
 
Status
Not open for further replies.
Back
Top