Bit-bang multiple I2S inputs simultaneously

Status
Not open for further replies.

manatok

Member
I guys, I need some advice please.

I have just ordered my Teensy 3.1 and would like to use it for a sound localisation project. I need to be able to sample multiple (probably 3 or 4) microphones simultaneously. I was thinking of using the following MEMS microphone: http://www.invensense.com/products/digital/ics-43432/ because it takes care of the analog/ADC part internally and outputs I2S.

I know that the Teensy 3.1 has a I2S pin, but I need to sample multiple simultaneously, so I suspect some bit banging is required. I was thinking of just connecting the MEMS I2S outputs to different pins on the same port and then reading in the entire port repeatedly. The part that I am not too sure about is the SCK pulse that I would supply to the MEMS.

I imagine I would just tie all of the SCK pins together and toggle it programatically from the Teensy?

I would like to sample the audio as fast as possible, if my calculations are correct to sample at 96KHz, I would need to read at a rate of(96K * 32 = approx 3MHz. Since this MEMS uses 32 bits per word (They seem to pad up the 24 bit sample resolution to 32 bits, not sure why). Is 3MHz attainable with the Teensy 3.1?

Once my buffer fills up I am going to flush this data to a raspberry pi 2 over UART before starting the read cycle again.

Any comments or suggestions would be most appreciated.

Thanks a mill
 
Bitbang I2S is not feasible.

Probably your best path is trying to use the other I2S receive pin. Normally, we receive I2S on pin 13, with is native port PTC5 (the pin mapping is on the schematic). If you look at the giant pin features table in the Freescale reference manual, on page 209 you'll see the ALT4 function of pin PTC5 is "I2S0_RXD0". If you look down a few rows, you'll notice PTC11 (which is pin 30 on the bottom side of Teensy 3.1) has ALT4 function "I2S0_RXD1".

I2S0_RXD1 is by far your best chance to receive 4 audio channels using I2S protocol. I'm going to mention a couple other ideas that are not nearly so good, but please understand I2S0_RXD1 is almost certainly the best way.

If you didn't have I2S0_RXD1, another approach might involve using some (very fast) digital logic to try multiplexing 4 channels onto I2S0_RXD0. If each chip transmits 16 bit data, in theory a digital circuit might be able to multiplex both 16 bit numbers onto a 32 bit I2S frame. You'd need to change the software to receive 32 bits instead of 16 for each channel, and then pick out the pairs of numbers. The tricky part would be designing the digital logic to accomplish this, without too much signal delay.

I should probably mention, for completeness, that some audio codec chips have a non-I2S protocol called TDM. The LRCLK signal is replaced by a short pulse that marks the beginning of a frame, rather than a 50% duty cycle where high means one channel and low means the other. With TDM, each chip can be configured to drive its transmitter during on certain numbers of cycles following the sync pulse. It's basically like the digital logic approach, but already build into the chip. I'm not aware of any MEMS microphones with this feature... I'm mostly mentioning this in anticipation of other people someday finding this thread through search. Well, and also because the I2S peripheral in Teensy 3.1 is supposed to be able to implement TDM protocol, theoretically implementing up to 32 audio channels! :)

Yet another idea might involve using SPI. Many I2S chips will tolerate the bit clock having timing not in sync with MCLK or LRCLK, as long as at least the correct number of BCLK transitions happen on each phase of LRCLK. The Open Music Labs Codec Shield uses this approach to do I2S on ordinary AVR chips. The obvious downside is high CPU usage with little tolerance for interrupt latency, so you're highly constrained on being able to actually *do* much with the data.

Of course, I2S0_RXD1 is just sitting there as ALT4 functionality on pin 30. So far, nobody has tried to actually use it (at least nobody who's told me... admittedly, quite a good number of people use Teensy to make proprietary projects). According to the reference manual, I2S0_RXD1 certainly seems like it could be used to get 2 more channels, as long the same MCLK, BCLK and LRCLK can be used. The obvious caveat is this wants to be I2S master mode (where Teensy creates all the clocks)... it couldn't possibly work where 2 different I2S chips each create their own BCLK and LRCLK that aren't in sync with each other.

The latest version of the audio shield has pairs of solder pads to cut apart for the I2S RXD and TXD signals, and a set of 3 pads that can be cut and soldered to reconfigure the SGTL5000 for a different I2C address. The idea was to someday experiment with using 2 audio boards, for 4 channel input and 4 channel output... where the 2nd board would need some wires added from those pads to route its RXD signal to pin 30, and its TXD signal to pin 15.

In theory, Teensy 3.1 should be able to support quad channel I2S audio. All that's needed it slight hardware mods and work on the software side! Hopefully this detailed writeup at least helps get you started?
 
Last edited:
Thanks Paul for the great response, it certainly gives me a lot to think about!

I2S0_RXD1 seems like a great idea, so in principle I would just break the link to Vcc and solder on a new connection to pin 30? I might be out of my depth but I am happy to try. I just need a little bit more of a kick in the right direction. Would I use something like this and modify it for the 32 bits/word and the new I2S0_RXD1 pin: https://github.com/hughpyle/teensy-i2s/blob/master/i2s.cpp ?

I would want the Teensy to be the master, so I should be able to tie the BCLK's and LRCLK's together on the MEMS and drive though from the Teensy?

Just out of curiosity, why do you say that the bitbang approach is not feasible? Would I be getting a low sample rate? For my app, the only thing the Teensy will be doing is reading in the I2S data and then when the buffer is full it will stop recording and hand off the data to the PI, and then it will clear its buffer and start recording again, wash rinse repeat.

Thanks a mill!
 
If you're going to try this, definitely start with the Teensy Audio Library. It's by far the most mature and flexible code. That very old code might help as a reference, maybe.

There's 2 parts to this project... first, convert from a 16 to 32 bit word format your microphones require. For an example, you might look at Frank's recent S/PDIF output object, which transmits 32 bit words. Even though you're looking to receive, looking at the difference between the normal 16 bit output and Frank's 32 bit output can help you make sense of the I2S config registers. Of course, read the reference manual too as you read the code, especially the config_SPDIF() function near the end which actually sets up the I2S registers. The transmit and receive register setup is pretty much the same.

Then the 2nd part would be duplicating the setup from I2S0_RXD0 to I2S0_RXD1. For that, you're not going to find any existing code. There's an extra register to write, which should work the same way as the one for I2S0_RXD0. Then you're going to need to edit the interrupt and DMA stuff to transfer twice as much data, and add some code to sort it out into 4 buffers to interface with the rest of the library. There's already very well tested code for 2 channels, so focus on reusing what you can.

I'm not going to comment more on bitbang or other approaches. I think I've already written quite enough here. You're welcome to try if you like, but it would be foolish not to try using the I2S hardware that's already present and try reusing the already very stable audio library code as much as possible.
 
Ok thank you very much. I will start by trying to wrap my head around the Audio lib so that when my Teensy arrives I can begin tinkering.
 
I am interested in taking input from at least 3 microphones (again, to localise the source of the sound). That's a bit different from the 2 sources x 2 channels described here.

How would I approach getting a Teensy 3.1 to consume i2s from 3 or 4 teensy audio boards at once? I have lots of Teensy audio boards to play with as a result of a recent rash purchase...
 
I am interested in taking input from at least 3 microphones (again, to localise the source of the sound). That's a bit different from the 2 sources x 2 channels described here.

How would I approach getting a Teensy 3.1 to consume i2s from 3 or 4 teensy audio boards at once? I have lots of Teensy audio boards to play with as a result of a recent rash purchase...

If you were to take 3 MEMS I2S phones, then you could tell two phones to be left or right channel and the third channel to be either left or right and use both RXD0 and RXD1. I would add a 4th hydrophone as this does not increase bandwidth or memory usage, but provides redundancy or even better localization.

If you wanted to use two audio boards, there must be a way to use two in parallel, but here you have to ask Paul.
 
For localisation, you need separation between the microphones.
As I understand it, i2s is very short-range, so it would not work for i2s microphones located far apart. I haven't found a distance specified anywhere but the implication is that it is within a circuit board.
My intent was to use analog microphones on 'long wires' back to Teensy audio boards. Each Teensy audio board has only one mono microphone input...
Through maybe the answer is to pre-amplify the microphone output to Line In levels so two microphones can feed Line In left & right channels. Then I need only 2 audio boards to handle 2 or 4 microphones.. .
 
For localisation, you need separation between the microphones.
My intent was to use analog microphones on 'long wires' back to Teensy audio boards. Each Teensy audio board has only one mono microphone input...
Through maybe the answer is to pre-amplify the microphone output to Line In levels so two microphones can feed Line In left & right channels. Then I need only 2 audio boards to handle 2 or 4 microphones.. .

If you are going to use analog microphones, than yes you should (must) pre-amplify. This should be no big deal if microphones have already the FET included, so that they become low impedance devices allowing long distances, so you need only a coupling capacitor and a resistor at the line-in. I guess, you know all this.

I don't know (or recall) your application, but direction finding over large bases may becoming difficult, especially if the signal is repetitive. If the signal to noise ration is large, you may consider phase processing with closely spaced microphones.
 
Last edited:
Question:
Is it correct that, in order to use two audio cards, I have to cut the traces in RX/TX/ADDR lines, solder ADDR to 3.3V, attach two wires to RX/TX and connect to the I2S RX1/TX1 pins at bottom of Teensy?

Yes, correct, except I2S TXD1 is reachable on both sides; it's pin 15.

I2S RXD1 is pin 30, only accessible on the bottom.

You also need to remove this tiny 0.1 uF capacitor on both boards, because it's connected to pin 15.

teensy3_audio_front.jpg

Of course, this is only the hardware side. Much work is still needed in the software to enable this to actually work.
 
Last edited:
Yes, correct, except I2S TXD1 is reachable on both sides; it's pin 15.

I2S RXD1 is pin 30, only accessible on the bottom.

You also need to remove this tiny 0.1 uF capacitor on both boards, because it's connected to pin 15.

Paul, only to double check
I have using Freescale Ref. manual V1.1

RXD0: PTC5 Pin13
RXD1: PTC11 Pad30

TXD0: PTC1 Pad22/A8 or PTA12 Pin 3
TXD1: PTC0 Pin15/A1

TXD0 has two options (Pad and Pin)
of course, Pins can be accessed from both sides, but Pads only from below.
 
Hello Manatok,
have you had a look at our project description here in the forum?
I think there are at least 3 issues at hand which complicate your project if you decide to go for I2S instead of 4 analog microphones:

- lacking 24 bit microphone support
(most I2S mics are 24 bit, the standard teensy audio library by Paul can't handle that (for the foreseeable future). Pure sound data receiving can be done with alternate libraries, but you lose a lot of features. May not be that bad in your case, though.)
- microphone cabling and placement
(as has been said, I2S wasn't designed for off-pcb-connections / long distances. We succesfully use it over a re-purposed USB cable at lengths of well over 50cm and it works, but electromagnetic interference may be an issue for professional applications)
- using both I2S dual-channel receivers
(AFAIK, there has been no proof-of-concept for this, although it is a very interesting capability to have)

The ICS-43432 delivers good performance and has some better characteristics than earlier I2S mics, e.g. in noise suppression from the power supply line, which is important in such a long-distance design.
 
Last edited:
Why not use multiple Teensy and audio boards?

For this project, wouldn't be more appropriate to use 3 sets of Teensy + audio board, keeping them in sync with digital communication, maybe with a fourth Teensy acting as master for the cluster? Considering the price of the boards it would not really cost that much, you would be able to use standard libraries and code, and you can keep both analog and digital audio pathways nice and short.

Of course it is interesting and potentially useful for others exploring the possibilities of using dual audio boards, I just think a multi board solution could serve you better.
 
... multiple input channels... any chance of that happening?

Sure.

You could help speed this up with a compelling idea for a demo/test sketch to go into the HardwareTesting > SGTL5000 examples folder. Or better yet, a stereo version that could be easily expanded to quad channel, and end up doing something pretty meaningful with 4 channels rather than just 2.
 
I was wondering if it was possible to use the line out and headphone outs seperately?

No, not really.

If you read the SGGL5000 datasheet, the diagram on the first page looks like you might be able to use lineout and maybe connect the headphones to one of the analog inputs. Maybe.

But there's certainly no support in the hardware for sending different digital data to both. The diagram pretty clearly shows the line out always gets the digital to analog conversion, and the headphones get either that, or a path from the analog line in.
 
No, not really.

If you read the SGGL5000 datasheet, the diagram on the first page looks like you might be able to use lineout and maybe connect the headphones to one of the analog inputs. Maybe.

But there's certainly no support in the hardware for sending different digital data to both. The diagram pretty clearly shows the line out always gets the digital to analog conversion, and the headphones get either that, or a path from the analog line in.

The data sheet is why I asked, just looked it over. I think it could actually be useful to have any possible routing options, I was just thinking of two good uses:
1 ) a dj style que mix so you can hear the input before mixing it in to the other output
2) ability to hear your voice as you sing into the mic with headphones on
 
Status
Not open for further replies.
Back
Top