adiblol
Posts: 5
Joined: Mon Sep 16, 2013 6:53 pm

Multiple I2S input

Mon Sep 16, 2013 8:17 pm

---BEGIN OF BORING STUFF---

I want to record multiple (>=8) audio tracks at once. However, USB audio interfaces with multiple input channels are too expensive for me so I decided to make multi-ADC audio interface or hard disk recorder myself.
I want to use WM8782 ADCs http://www.wolfsonmicro.com/products/adcs/WM8782/ which has 2 analog inputs and digital serial output (I2S, RJ or LJ).
I want to keep digital part of the circuit as inexpensive as possible.
The problem is interfacing multiple I2S inputs. FPGA would be ideal but there aren't any open source "compilers" for those circuits and I don't have any experience with programmable logic. And development boards are rather expensive.
So I thought of using Pi and its GPIO for interfacing I2S.

---END OF BORING STUFF---

The ADC chips will work in slave mode so each chip will output data stream synchronized by BCLK (see WM8782 datasheet, page 12).
My idea is to use DMA to dump state of GPIO to buffer in RAM every BCLK period. It could be then processed and saved to WAV of FLAC files on USB hard drive, by userspace process.
At 48kHz, 24bit, each ADC produces serial data stream of 2304kb/s, so the BCLK should be at least 2304kHz (I assume that BCLK doesn't have to be phase aligned to MCLK, if it does, we need 3072kHz).
WM8782 requires MCLK (Master Clock) of 6144kHz or multiply of it. I want to generate it using GPIO clock output (as P**** transmitter does) by changing PLL frequency, disabling MASH and using integer divider (to avoid jitter, see http://www.raspberrypi.org/phpBB3/viewt ... 44#p232244 ). Output clock source can be changed to any PLL, and ARM PLL can be set to arbitrary value in config.txt ( http://elinux.org/RPiconfig#Overclocking ). For example PLL=725MHz, divider=59, so 12.288136MHz will appear on clock output, which is about 11ppm error.

The question is: Is DMA fast enough to copy GPIO register into buffer in RAM at about 3MHz?

3MHz means that period is 0.33µs. The lowest period I have seen was 4.54µs in P*** https://****

If it is possible, we will be able to build probably the cheapest digital multitrack recorder on Earth, haha.

vadim
Posts: 129
Joined: Wed Sep 18, 2013 1:47 pm
Location: Nottingham

Re: Multiple I2S input

Wed Sep 18, 2013 2:23 pm

I have a less ambitious objective: just one ADC (WM8783 which is very much like WM8782) and this already is not easy.

I don't believe you will be ever able to make a userspace process that will do anything monotonically with frequency of more than 500Hz. I don't understand what is that you want to read with DMA on every BCLK but I have good news for you. I2S input (stereo) is already implemented in BCM2835. Florian Meier has written an asoc driver for it. There is already an asoc driver for WM8782. Yesterday I wrote a driver for WM8783 based on WM8782 driver. You don't even have to do that.

What you need to do is to write the "machine driver" specifying how the cpu and WM8782 are connected, any link limitations AND implementing correct MCLK through GPCLK pin. Well, I'm not aware of any successful attempt to supply stable MCLK from RPi to ADC/DAC. This is my focus area for the next couple of days (hopefully). I can share the code if it works. If not, will have to implement a hardware clock generator and thus limit sample rates.

But remember, only stereo in is possible. But then again, you can link 64 RPi and have 128 inputs, about 2TB of storage (with 32GB cards). Still the power conditioning and input preamps might in the end cost more than the computers themselves.

adiblol
Posts: 5
Joined: Mon Sep 16, 2013 6:53 pm

Re: Multiple I2S input

Wed Sep 18, 2013 5:50 pm

I will connect it to mixer (Behringer 3242MX to be exact), not microphones, so cheap NE5532 or even cheaper TL072 op-amps are enough.

2 channels don't satisfy me; I want to record live concerts on separate channels.
I don't believe you will be ever able to make a userspace process that will do anything monotonically with frequency of more than 500Hz.
In theory it is possible (you have to disable interrupts, but then all peripherals stop working so I don't want it because I need Ethernet or USB).
But I don't want user space process to read GPIO. DMA will do it. User space process will read buffer (it's not time-critical).
I don't understand what is that you want to read with DMA on every BCLK
DMA controller will dump GPIO into buffer in RAM every BCLK.
Well, I'm not aware of any successful attempt to supply stable MCLK from RPi to ADC/DAC. This is my focus area for the next couple of days (hopefully). I can share the code if it works. If not, will have to implement a hardware clock generator and thus limit sample rates.
As I've read, Pi can be I2S slave (using hardware I2S). It means that we can implement external clock using high-quality quartz generator. It should give better stability than PLL.

Because I want multiple inputs, I have to bit-bang. External clock would be nice. So the following DMA code (inspired by P***) comes to my mind:
* copy GPIO into RAM location
* read from/write to hardware I2S, or hardware PWM
* copy GPIO into subsequent RAM location
... repeat...

The hardware read/write is only to make DMA run at fixed speed, as P*** and PiBlaster do.
I2S or PWM will be configured to run from external clock, or precise internal clock if possible.
I wonder if hardware I2S can be fooled to run at 3MHz, would be nice. ;)

When my Pi and ADCs get delivered, I will test it. Fortunately I can reuse PI*** code (it's GPL).

vadim
Posts: 129
Joined: Wed Sep 18, 2013 1:47 pm
Location: Nottingham

Re: Multiple I2S input

Wed Sep 18, 2013 8:39 pm

I don't think that is feasible without hardware FIFO that would take care of reading and temporarily storing input values.
Because I want multiple inputs, I have to bit-bang. External clock would be nice. So the following DMA code (inspired by P***) comes to my mind:
* copy GPIO into RAM location
* read from/write to hardware I2S, or hardware PWM
* copy GPIO into subsequent RAM location
... repeat...

vadim
Posts: 129
Joined: Wed Sep 18, 2013 1:47 pm
Location: Nottingham

Re: Multiple I2S input

Sun Sep 22, 2013 7:40 pm

I've managed to write a driver and use WM ADC. It actually required to edit bcm2708-i2s driver. Looks like this ADC can happily receive MCLK from RPi's general purpose clock driven by PLLD. Haven't tested 24/96 yet as for my application I need just 16/32.

When your Pi's and ADC are due to arrive? Let us know about your results, successful or not.

adiblol
Posts: 5
Joined: Mon Sep 16, 2013 6:53 pm

Re: Multiple I2S input

Mon Sep 23, 2013 2:48 am

vadim wrote:this ADC can happily receive MCLK from RPi's general purpose clock driven by PLLD. Haven't tested 24/96 yet as for my application I need just 16/32.
32kHz isn't typical sampling rate for audio. Have you changed PLLD frequency? Could you test 44.1 or 48kHz?
When your Pi's and ADC are due to arrive? Let us know about your results, successful or not.
Unfortunately in about 3 weeks - I ordered Pi+SD set at Farnell - currently out of stock.

vadim
Posts: 129
Joined: Wed Sep 18, 2013 1:47 pm
Location: Nottingham

Re: Multiple I2S input

Mon Sep 23, 2013 5:25 pm

Since WM8783 recreates own BCLK from LRCLK and all the clocks should be in sync I run into problems at higher rates. In my case codec's MCLK and Pi's BCLK are generated independently although from one PLLD. At higher rates the jitter and phase shifts create nice :twisted: white noise masking the incoming signal.
WM8782 should behave better as it would have BCLK coming in from RPi.
To sum up, chips that need MCLK should get it from an external controllable generator. If the chip wants specific frequency relationships to BCLK and LRCLK then those should be generated as well. RPi then would act as a slave to all clocks.

It's a pity that RPi cannot output it's MCLK. :(

adiblol
Posts: 5
Joined: Mon Sep 16, 2013 6:53 pm

Re: Multiple I2S input

Mon Sep 23, 2013 6:30 pm

You can try to use WM in master mode, send only MCLK and receive LRCLK and BCLK.
// edit: Sorry, I see it's impossible with 8783.
To sum up, chips that need MCLK should get it from an external controllable generator. If the chip wants specific frequency relationships to BCLK and LRCLK then those should be generated as well. RPi then would act as a slave to all clocks.
Do you know how to make Pi act as a slave? By removing quartz oscillator :mrgreen: and connecting external clock instead of it?
It's a pity that RPi cannot output it's MCLK. :(
What about outputting clock on GPIO pin?

vadim
Posts: 129
Joined: Wed Sep 18, 2013 1:47 pm
Location: Nottingham

Re: Multiple I2S input

Mon Sep 23, 2013 9:39 pm

adiblol wrote: Do you know how to make Pi act as a slave? By removing quartz oscillator :mrgreen: and connecting external clock instead of it?
What about outputting clock on GPIO pin?
Pi can be a slave and that's probably the best configuration. It doesn't need MCLK in as some codecs do.

In my test the MCLK was coming out of GPIO4 switched to general purpose clock function. That works only for low frequencies. With high frequencies I see no way of making sure that LRCLK switches on low MCLK and there is no more than 8 MCLK cycles error on LRCLK. The ADC was designed for more deterministic environment :? I will try to improve stability of this setup after my holiday in Spain. I hope by that time you will have some results. Good luck!

adiblol
Posts: 5
Joined: Mon Sep 16, 2013 6:53 pm

Re: Multiple I2S input

Mon Sep 23, 2013 10:29 pm

Well, luckily in my configuration I need to output only MCLK because I will configure one of ADCs to work as master.

My biggest problem will be soldering SMD, I have never done it before :lol:

8783 doesn't support master so you can use ATTINY for generating BCLK and LRCLK.

vadim
Posts: 129
Joined: Wed Sep 18, 2013 1:47 pm
Location: Nottingham

Re: Multiple I2S input

Tue Sep 24, 2013 9:37 pm

adiblol wrote:Well, luckily in my configuration I need to output only MCLK because I will configure one of ADCs to work as master.

My biggest problem will be soldering SMD, I have never done it before :lol:
joy, oh joy! sounds like fun. soic-8 was difficult enough for me.good luck with wm8782! btw, from my memory mclk is input on wm8782. what will be your master?

vadim
Posts: 129
Joined: Wed Sep 18, 2013 1:47 pm
Location: Nottingham

Re: Multiple I2S input

Mon Oct 21, 2013 3:36 pm

any news? ;)

koalo
Posts: 121
Joined: Mon Feb 04, 2013 4:02 pm

Re: Multiple I2S input

Tue Oct 29, 2013 6:17 am

There are already some ideas about that by using an external (cheap) CPLD. This thread might be interesting:

https://github.com/Guzunty/Pi/issues/11

mhelin
Posts: 128
Joined: Wed Oct 17, 2012 7:18 pm

Re: Multiple I2S input

Wed Nov 13, 2013 9:49 pm

koalo wrote:There are already some ideas about that by using an external (cheap) CPLD. This thread might be interesting:

https://github.com/Guzunty/Pi/issues/11
Using a CPLD or an FPGA makes many things possible. However, the problem is that you eventually have to embed the frame information into the audio data. Pi can output 32-bit frames and the good converters are usually 24-bit ones so you have extra 8 bits (32-24) left for framing information. In FPGA code you have to implement usual PCM (why use I2S here, it makes no sense, you need it only for converter interfaces not for multiplexer interface) receiver/transmitter which works at higher/lower sample rate compared to intermediate channel rate. Then in ALSA (ASoC) driver's transmit implementation mark the frames with LSB's when multiplexing and sending data to PCM output, and de-multiplex the data in FPGA and output in lower rate to DAC's (receiver use case is reverted). So you could output (or input) 4x stereo (L/R, 2ch) channels of 24 bit /48 kHz data using a 2ch 32 bit /192 kHz physical channel between Pi and FPGA (don't know if CLPD can be used). Driver will anyway be quite a different so it would make sense to fork a new one from the existing sources.

Now as there could be actually extra bits available then why not implement something like I2C using the extra bits. For framing you need just three bits (channel number 0-7), so you could send also some control data to converters for volume control, textual data for LCD display, control power (on/off) for the amplifiers etc. using the same PCM interface.

If you want a simple way to increase channel count then just patch the driver so that it uses 32-bit words but packs two 16-bit samples into one. Then you don't have to do anything else that use one DAC with left justified data and another with right justfied. If you cannot find ones which accept 16-bit word in 32-bit frame you have to do something else which might be possible using CLPD's (shift clocks / data, zero some bits etc.) or even using discrete logic chips.

mhelin
Posts: 128
Joined: Wed Oct 17, 2012 7:18 pm

Re: Multiple I2S input

Mon Nov 25, 2013 11:59 am

For multi-channel output (or input) it would be easiest just to use TDM/DSP format for the D/A and the A/D converters. For an example of such device is the WM8768 DAC (http://www.wolfsonmicro.com/products/dacs/WM8768/).

To generate TDM frame sync of I2S LRCK you for an example need to set the two LSB's in the last 32-bit sample of a frame and sample this data output using D-type flip flop (data to D input and LRCK to CK input, Q is the frame sync output). If you want be absolutely sure that the data output is valid at the raising edge of the LRCK just use another D-FF to sample the data out on rising bit clock first (maybe not necessary at all, I guess the data output is not changed until the next zero is output). The NL17SZ74 is a good one (fast enough) for FF chip (http://www.onsemi.com/PowerSolutions/pr ... d=NL17SZ74).

There are also many TDM/DSP compatible AD converters available, WM8786 (http://www.wolfsonmicro.com/products/adcs/WM8786/) though being a stereo one, is one example.

You will also need an external MCLK, and if it's frequency must be bigger than bit clock's you need a divider circuit (same part is OK, but connect as divider, 24.567MHz into CK, /Q to D and Q is the 12.288 MHz output).

mhelin
Posts: 128
Joined: Wed Oct 17, 2012 7:18 pm

Re: Multiple I2S input

Tue Nov 26, 2013 1:16 pm

Checked the BCM2835 docs and it seems to support any channel framing between 0 to 1024 bits so in theory TDM/DSP format is also supported. Only drawback is that there are only two channels supported inside a frame so multichannel ADC's supporting TDM cannot be used.

However, regarding the WM8782 ADC for an example you could easily combine outputs of two ADCs (using an OR gate) so that Rasberry could read all four channels converted - there is still a limitation that only 16-bit words can be used. The trick is to configure the first ADC to left justified PCM mode and the other ADC to right justified one, both with 16 bit word sizes. Now Rasperry should be configured to read 32 bit data in PCM mode ("normal" LRCLK phase, no delay between frame sync and MSB data bit ). Then you would have in any received 32 bit word in the 16 MSBs the output from the first converter and in the 16 LSBs the output (16 bits) from the second converter.

renne
Posts: 11
Joined: Sun Apr 27, 2014 9:32 am

Re: Multiple I2S input

Tue Aug 11, 2015 11:21 am

If the I2S can handle 15 Mbit/s it may be possible to attach an optical TOTX147- or TORX147-transceiver and connect an ADAT audio-interface with 8x 24bit@48000 Hz like the Behringer ULTRAGAIN DIGITAL ADA8200.

This would make the RPi an audiophile 7.1-surround media-player. ;)

derhoch
Posts: 6
Joined: Fri Dec 28, 2012 9:15 pm

Re: Multiple I2S input

Thu Oct 01, 2015 12:49 pm

Any news on this topic? I am interested in a way to record and play 6-channel 8kHz 16bit audio on the pi for a voice application.

henrix
Posts: 6
Joined: Mon Jul 20, 2015 6:15 pm

Re: Multiple I2S input

Fri Oct 02, 2015 4:20 pm

Hi,

currently, I'm trying to modify the bcm2708-i2s ASoC platform driver, that it supports TDM. My audio codec is driven by an external oscillator with 12,288MHz and supports up to 4 stereo channels in TDM mode (1 word is 32 Bit => DAC1L, DAC1R, ... DAC4L, DAC4R = 8 * 32 = 256 Bit). I've already figured how to set the frame length to 256 Bit and the channel positions to 0 and 32 (DAC1L, DAC1R) in the bcm2708-i2s driver and it works (so there are 6 unused slots now). Now my problem is, how can I modify the bcm2708-i2s driver to accept up to 4 ALSA stereo channels and to embed them in one PCM stream to fill all unused slots?
Does anybody has some experience with this subject and can help me?

Thanks!

derhoch
Posts: 6
Joined: Fri Dec 28, 2012 9:15 pm

Re: Multiple I2S input

Wed Oct 07, 2015 10:30 am

Wow henrix, this is awesome! Can you be more specific on what codec you use and do you have any sourcecode you can share?
I found a commit that patches the blackfin i2s driver to support TDM, maybe this is helpful:
http://git.kernel.org/cgit/linux/kernel ... e0202bae18

mhelin
Posts: 128
Joined: Wed Oct 17, 2012 7:18 pm

Re: Multiple I2S input

Tue Oct 13, 2015 8:45 am

Regarding TDM one option would be to use a mode with CLKM = 1 , FSM = 0 (see the BCM2835 ARM Peripherals datasheet, MODE_A registers). Set the PCM to output and input data using two channels. Connect the 12.2880 MHz clock to PCM/I2S bitclock, and set the frame length for 32 bits: FRXP = FTXP = 0 for 32-bit frames, FLEN = 63, FSLEN = 32. Set also the RXC_A and TXC_A registers properly. Now you should build a circuit which a) can be reset by driver code using a GPIO pin connected to reset pin of the divider (eg. 74HC74 flip-flop, two stages in series for div by 4 circuit) and b) divides the frame sync by 4. Modify the drivers properly. After clearing the FIFO's (anywhere in driver code) also reset the external FS divider circuit. I think Florian added a comment in driver code about the two PCM clock wait problem in case of external sync, please take it into account. I can check the driver implementation (though I'm quite busy right now). Just build the FS divider circuit first and test it. This is needed because BCM2835 doesn't support multichannel (more that two channels anyway) PCM in any format.

mschuster91
Posts: 8
Joined: Sat Nov 21, 2015 10:01 pm

Re: Multiple I2S input

Wed Dec 02, 2015 12:30 am

mhelin wrote:Regarding TDM one option would be to use a mode with CLKM = 1 , FSM = 0 (see the BCM2835 ARM Peripherals datasheet, MODE_A registers). Set the PCM to output and input data using two channels. Connect the 12.2880 MHz clock to PCM/I2S bitclock, and set the frame length for 32 bits: FRXP = FTXP = 0 for 32-bit frames, FLEN = 63, FSLEN = 32. Set also the RXC_A and TXC_A registers properly. Now you should build a circuit which a) can be reset by driver code using a GPIO pin connected to reset pin of the divider (eg. 74HC74 flip-flop, two stages in series for div by 4 circuit) and b) divides the frame sync by 4. Modify the drivers properly. After clearing the FIFO's (anywhere in driver code) also reset the external FS divider circuit. I think Florian added a comment in driver code about the two PCM clock wait problem in case of external sync, please take it into account. I can check the driver implementation (though I'm quite busy right now). Just build the FS divider circuit first and test it. This is needed because BCM2835 doesn't support multichannel (more that two channels anyway) PCM in any format.
What about the Pi 2? It should carry some more processing power. I'm thinking of building a TI PCM1606 (6-ch DAC) board... the question is: as P5 only provides one I2S data lane, can I adapt two of the GPIOs to work as data lanes?

From a quick look at the kernel source for the existing I2S stuff (https://github.com/raspberrypi/linux/co ... eab05b5a62) it works via DMA access to the GPIO pins, so in theory it should work, but I lack the expertise to actually know ;)

henrix
Posts: 6
Joined: Mon Jul 20, 2015 6:15 pm

Re: Multiple I2S input

Sun Feb 14, 2016 11:16 pm

We've developed a multichannel I2S (TDM) soundcard based on the AD1938 audio codec by Analog Devices.
Unfortunately the I2S/PCM interface of the RPi 2 can only support 2 audio channels.
Therefore, we decided to use the BeagleBone Green as alternative platform.
The project is open source and can be found here.
We hope to find a more powerful platform in the future, so any suggestions are welcome.

User avatar
flatmax
Posts: 346
Joined: Thu May 26, 2016 10:36 pm

Re: Multiple I2S input

Thu Oct 13, 2016 6:41 am

Hey there,

I have just manged to crack this walnut ! ... Now got surround sound hat working ...
Was wondering if you could give me feedback on my kickstarter campaign before I launch it ?
https://www.kickstarter.com/projects/12 ... n=e465b540

thanks
Matt
Discuss hearing, acoustics, audio injector products, - https://lists.audioinjector.net/mailman/listinfo/people
Sound card for the Raspberry Pi with inbuilt microphone : www.audioinjector.net
Audio Inector Octo multitrack GPIO sound card

henrix
Posts: 6
Joined: Mon Jul 20, 2015 6:15 pm

Re: Multiple I2S input

Fri Oct 14, 2016 7:36 am

Hi Matt,

nice! How did you get more than 2 audio channels working with PCM interface of RPi? I have checked your ASoC Machine Driver (https://github.com/flatmax/linux/blob/r ... oundcard.c) and it uses the old bcm2835-i2s driver, which only supports 2 audio channels.

Bests

Return to “Interfacing (DSI, CSI, I2C, etc.)”