tkbossert
Posts: 6
Joined: Sat Mar 07, 2015 5:19 pm

Re: STICKY: The I2S sound thread. [I2S works]

Thu Jan 07, 2021 7:26 pm

In case anybody comes searching this thread like I did for tips on getting a simple i2s capture or playback device working, here's some simple to use overlays that seem pretty good to me. No kernel module compiling necessary.

https://github.com/AkiyukiOkayasu/Raspb ... I2S_Master for using the pi as master, or https://github.com/AkiyukiOkayasu/RaspberryPi_I2S_Slave for the pi as slave

The only other thing needed to get the PCM1808 I'm using or other simple i2s devices working may be the SCKI system clock. This can easily be done using the information from https://www.raspberrypi.org/documentati ... uration.md or https://www.tablix.org/~avian/blog/arch ... n_bcm2835/

Using the pi as master, I had to adjust GPCLK0 a few hertz from the desired 12.288MHz to get SCKI synchronization with BCK.
Last edited by tkbossert on Thu Feb 04, 2021 3:24 pm, edited 1 time in total.

phofman
Posts: 35
Joined: Mon Oct 07, 2019 1:37 pm

Re: STICKY: The I2S sound thread. [I2S works]

Thu Jan 07, 2021 7:38 pm

tkbossert: Extremely useful, thanks a lot. The DTS examples will save me lots of time :-)

emuman100
Posts: 1
Joined: Sat Mar 13, 2021 4:40 am

Re: STICKY: The I2S sound thread. [I2S works]

Sat Mar 13, 2021 4:45 am

Hi Ben,

I'm trying the same thing. Did you use a crystal for the MCLK or the internal PLL? Have you been able to get working? I know configuring the registers seems to be a pain.

Jonathan
Ben123 wrote:
Wed Sep 02, 2020 12:26 pm
Hello all.
Over the last month I have been working on connecting a TI ADC (tlv320adc6140) with a RPI CM3+ with mixed success. I have enabled the necessary I2C and I2S pins in the Device Tree and created a simple DT overlay. The ADC is rather new and the codec driver was only very recently released in the latest kernel update (5.8) and boasts a lot of features. The codec drivers Probe functions are called correctly and when recording with Audacity or arecord, the DAPM works and powers the appropriate parts of the ADC as expected. The driver supports the ADC as both slave or master, however both modes fail to record anything but noise.

Pins are connected as follows:
RPI - ADC
GPIO 28 (PCM_CLK) - BCLK
GPIO 29 (PCM_FS) - FS
GPIO 30 (PCM_DIN) - DOUT
GPIO 31 (PCM_DOUT) - DIN

The ADC has the option of accepting an external MCLK, however it should not be required.

When tested with an oscilloscope, with RPI as the master, a sensible BCLK and FS are generated (3MHz and 48kHz respectively), however the ADC fails to recognize the correct BCLK/FS ratio (it supports automatic clock configuration) and DOUT looks very strange.
With the ADC as master, BCLK is 2,3MHz and FS is 9kHz, however the DOUT looks better.

Here my DT overlay for running the RPI as a slave:

Code: Select all

/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2835";
    
    fragment@0 {
        target = <&sound>;
        __overlay__ {
            compatible = "simple-audio-card";
            i2s-controller = <&i2s>;
            status = "okay";
            
            simple-audio-card,format = "i2s";
            simple-audio-card,name = "soundcard";
            simple-audio-card,bitclock-master = <&sound_master>;
            simple-audio-card,frame-master = <&sound_master>;
            
            simple-audio-card,cpu {
                sound-dai = <&i2s>;
            };
            sound_master: simple-audio-card,codec {
                sound-dai = <&codec>;
            };
        };
    };

    fragment@1 {
        target = <&i2s>;
        __overlay__ {
            status = "okay";
        };
    };

    fragment@2 {
        target = <&i2c0>;
        __overlay__ {
            #address-cells = <1>;
            #size-cells = <0>;
            status = "okay";
            codec: codec@4c {
                #sound-dai-cells = <0>;
                compatible = "ti,tlv320adc6140";
                reg = <0x4c>; 
                ti,gpi-config = <1 0 0 0>;
                ti,mic-bias-source = <6>; 
            };  
        };
    };
};
Here the register states (in hex) of the ADC during recording (audacity, 44.1kHz):

Code: Select all

                         REGISTER   (DEFAULT)    CURRENT
[17607.181413] PAGE_CFG (Def: 0)- Val: 0
[17607.181867] SW_RESET (Def: 0)- Val: 0
[17607.186238] SLEEP_CFG (Def: 0)- Val: 81 CHANGED!
[17607.191802] SHDN_CFG (Def: 5)- Val: 5
[17607.197158] ASI_CFG0 (Def: 30)- Val: 70 CHANGED!
[17607.201655] ASI_CFG1 (Def: 0)- Val: 0
[17607.207089] ASI_CFG2 (Def: 0)- Val: 0
[17607.211551] ASI_CH1 (Def: 0)- Val: 0
[17607.215997] ASI_CH2 (Def: 1)- Val: 1
[17607.220393] ASI_CH3 (Def: 2)- Val: 2
[17607.224770] ASI_CH4 (Def: 3)- Val: 3
[17607.229060] ASI_CH5 (Def: 4)- Val: 4
[17607.233507] ASI_CH6 (Def: 5)- Val: 5
[17607.237848] ASI_CH7 (Def: 6)- Val: 6
[17607.242169] ASI_CH8 (Def: 7)- Val: 7
[17607.246525] MST_CFG0 (Def: 2)- Val: 82 CHANGED!
[17607.251017] MST_CFG1 (Def: 48)- Val: 48
[17607.256806] ASI_STS (Def: ff)- Val: F8 CHANGED!
[17607.261455] CLK_SRC (Def: 10)- Val: 10
[17607.266818] PDMCLK_CFG (Def: 40)- Val: 40
[17607.271357] PDMIN_CFG (Def: 0)- Val: 0
[17607.276203] GPIO_CFG0 (Def: 22)- Val: 22
[17607.280803] GPO_CFG0 (Def: 0)- Val: 0
[17607.285535] GPO_CFG1 (Def: 0)- Val: 0
[17607.289972] GPO_CFG2 (Def: 0)- Val: 0
[17607.294443] GPO_CFG3 (Def: 0)- Val: 0
[17607.298821] GPO_VAL (Def: 0)- Val: 0
[17607.303255] GPIO_MON (Def: 0)- Val: 0
[17607.307648] GPI_CFG0 (Def: 0)- Val: 10 CHANGED!
[17607.312093] GPI_CFG1 (Def: 0)- Val: 0
[17607.317532] GPI_MON (Def: 0)- Val: 0
[17607.322108] INT_CFG (Def: 0)- Val: 0
[17607.326451] INT_MASK0 (Def: ff)- Val: FF
[17607.330818] INT_LTCH0 (Def: 0)- Val: 0
[17607.335555] BIAS_CFG (Def: 0)- Val: 60 CHANGED!
[17607.340093] CH1_CFG0 (Def: 0)- Val: 0
[17607.345464] CH1_CFG1 (Def: 0)- Val: A0 CHANGED!
[17607.349889] CH1_CFG2 (Def: c9)- Val: C9
[17607.355208] CH1_CFG3 (Def: 80)- Val: 80
[17607.359752] CH1_CFG4 (Def: 0)- Val: 0
[17607.364431] CH2_CFG0 (Def: 0)- Val: 0
[17607.368794] CH2_CFG1 (Def: 0)- Val: 0
[17607.373193] CH2_CFG2 (Def: c9)- Val: C9
[17607.377715] CH2_CFG3 (Def: 80)- Val: 80
[17607.382359] CH2_CFG4 (Def: 0)- Val: 0
[17607.386971] CH3_CFG0 (Def: 0)- Val: 0
[17607.391495] CH3_CFG1 (Def: 0)- Val: 8 CHANGED!
[17607.395958] CH3_CFG2 (Def: c9)- Val: C9
[17607.401199] CH3_CFG3 (Def: 80)- Val: 80
[17607.405816] CH3_CFG4 (Def: 0)- Val: 0
[17607.410447] CH4_CFG0 (Def: 0)- Val: 0
[17607.414933] CH4_CFG1 (Def: 0)- Val: 0
[17607.419674] CH4_CFG2 (Def: c9)- Val: C9
[17607.424145] CH4_CFG3 (Def: 80)- Val: 80
[17607.428764] CH4_CFG4 (Def: 0)- Val: 0
[17607.433362] CH5_CFG2 (Def: c9)- Val: C9
[17607.437814] CH5_CFG3 (Def: 80)- Val: 80
[17607.442584] CH5_CFG4 (Def: 0)- Val: 0
[17607.447205] CH6_CFG2 (Def: c9)- Val: C9
[17607.452115] CH6_CFG3 (Def: 80)- Val: 80
[17607.456669] CH6_CFG4 (Def: 0)- Val: 0
[17607.461305] CH7_CFG2 (Def: c9)- Val: C9
[17607.465799] CH7_CFG3 (Def: 80)- Val: 80
[17607.470808] CH7_CFG4 (Def: 0)- Val: 0
[17607.475363] CH8_CFG2 (Def: c9)- Val: C9
[17607.479726] CH8_CFG3 (Def: 80)- Val: 80
[17607.484383] CH8_CFG4 (Def: 0)- Val: 0
[17607.488981] DSP_CFG0 (Def: 1)- Val: 1
[17607.493447] DSP_CFG1 (Def: 40)- Val: 40
[17607.497866] DRE_CFG0 (Def: 7b)- Val: 7B
[17607.502443] AGC_CFG0 (Def: e7)- Val: EC CHANGED!
[17607.507104] IN_CH_EN (Def: f0)- Val: F0
[17607.512563] ASI_OUT_CH_EN (Def: 0)- Val: 80 CHANGED!
[17607.517185] PWR_CFG (Def: 0)- Val: E0 CHANGED!
[17607.523650] DEV_STS0 (Def: 0)- Val: 0
If anyone has any ideas on what I might be doing wrong, any help is greatly appreciated,
Ben

christofer_hc
Posts: 4
Joined: Fri Feb 05, 2021 7:11 pm

Re: STICKY: The I2S sound thread. [I2S works]

Wed Mar 24, 2021 6:31 pm

Greetings,

I'm trying to read some I2S samples from a I2S master. I tried the procedure for pi as slave, according to the quoted post below.

I also noticed that those procedures were developed for RPI 3, however, i'm working on a RPI 4 Model B.

Did anyone managed to make it work in the RPI 4? And in this case how is it possible to read those samples?

Thanks!



tkbossert wrote:
Thu Jan 07, 2021 7:26 pm
In case anybody comes searching this thread like I did for tips on getting a simple i2s capture or playback device working, here's some simple to use overlays that seem pretty good to me. No kernel module compiling necessary.

https://github.com/AkiyukiOkayasu/Raspb ... I2S_Master for using the pi as master, or https://github.com/AkiyukiOkayasu/RaspberryPi_I2S_Slave for the pi as slave

The only other thing needed to get the PCM1808 I'm using or other simple i2s devices working may be the SCKI system clock. This can easily be done using the information from https://www.raspberrypi.org/documentati ... uration.md or https://www.tablix.org/~avian/blog/arch ... n_bcm2835/

Using the pi as master, I had to adjust GPCLK0 a few hertz from the desired 12.288MHz to get SCKI synchronization with BCK.

KillerBerthier
Posts: 39
Joined: Thu May 05, 2016 4:28 pm

Re: STICKY: The I2S sound thread. [I2S works]

Sun Mar 28, 2021 10:34 am

I wrote from scratch a small module to drive a Cirrus Logic CS4272 with I2S + DMA (+ I2C for the codec init). This is not a “system driver”, but I’m using it as such, to play and record audio from my application (multi-effect pedalboard). I use it with a custom audio board, but I think it can be used with other codecs and configurations with minor changes.

– CS4272 is communicating with the RPi4 using I2S and I2C and two additional GPIO pins
– Bidirectional (rec + play) 24-bit stereo audio at 44.1 and 48 kHz
– The codec is bitclock and wordclock-master
– The master clock is generated with a MK2703B PLL driven by a 27 MHz crystal. The sampling rate selection is done with a single GPIO pin.
– The second GPIO pin resets the codec
– Requires root privileges because of the use of mmap().
– Processing is done in a SCHED_FIFO thread with real-time priority, but does not requires the kernel to be RT-patched.

I don’t know if I did everything right, and there are still a few things I don’t understand well, but the overall result is satisfying: everything stays stable and the buffer size can be set down to 4 sample frames (1.12 ms roundtrip latency, measured). There are occasional channel swapping, but this is very rare, it happens under heavy stress tests with repeated buffer underruns + driver restarts. If someone has an idea on how to avoid this issue in a reliable manner, I would be glad to read it.

I struggled to make everything work, so here is my code, if it can help anyone jumping in the same adventure:
header & code
There are some dependencies elsewhere in the repository.

I first wrote a driver in polling mode which was working well, but a recent RPi OS system update made it unstable, so I tried to implement the DMA to release the pressure on the timing. In the meantime I found out that real-time priority threads are not allowed to run > 95 % of the CPU time (according to /proc/sys/kernel/sched_rt_runtime_us), but for some reasons this feature was not effective in previous RPi OS releases and the kernel let me use all the CPU I needed. Anyway my DMA driver is now immune to this limit.

scoot89
Posts: 3
Joined: Wed Apr 07, 2021 2:35 pm

Re: STICKY: The I2S sound thread.

Thu Apr 08, 2021 1:59 pm

Rolerex wrote:
Fri Aug 30, 2019 10:07 am
Hello everyone,

@KittyLitter
Does anyone have any ideas of what may be going wrong?
I'm also trying to use a PDM Microphone myself. I went throught the BCM2835 Datasheet to look at some of the features:
https://cdn-shop.adafruit.com/product-f ... asheet.pdf
And it's indeed capable of using a CIC decimation filter. I suppose your hack involve some registers modifications. If you want to switch from 32 to 16 decimation, have you seen the 8.6 PDM Input Mode Operation section ?
It's seems you have to modify the PDMN register and the OSR , which stands for Over Sampling Rate. This OSR seems to be a software parameter and change with the decimation.

Is it possible to know what did you modify in the bcm2835-i2s module ?

I'm trying to use a microphone to get a 48kHz signal, with a 3.072MHz Clock, whatever the decimation, but 32 would be great. Hit me if you have some info.

scoot89
Posts: 3
Joined: Wed Apr 07, 2021 2:35 pm

Re: STICKY: The I2S sound thread.

Thu Apr 08, 2021 4:50 pm

Hi Rolerex and piright

I've been trying to replicate your process in order to interface a PDM mic (working at 3.072Meg) on a rpi4.
I've documented all my steps to get to your result and am able to record audio (I'm going for the 20/32bits result): https://github.com/imec-int/klankentapp ... nux-driver
Yet I notice the pitch is off when recording with:

Code: Select all

arecord -D plughw:1 -c1 -r 48000 -f S16_LE -d 60 -t wav -V mono -v test.wav
Is this (wrong pitch) something you guys encountered? I can recognize the original audio, yet it is clearly a couple of octaves lower.
When using a scope, I can see my pdm clock is about 3.1Meg, which is in range of my microphone. I saw in a previous post that your clock rate also was supposed to be 3.072Meg, why did you then adapt the linux bcm driver to a bclk_rate of 1536000?

Already lots of thanks for the initial flow!

Sincerely
Wouter
piright wrote:
Mon Oct 21, 2019 12:17 pm
Hi @Rolerex, I would like to follow your steps so that I can record 16-bit. I've made necessary adjustments to the source file in https://github.com/torvalds/linux/blob/ ... 2835-i2s.c . However when I try to compile with

Code: Select all

make -C /lib/modules/$(uname -r )/build M=$(pwd) modules
I encounter the following error
snd-soc-bcm2835-i2s.c:855:9: error: implicit declaration of function ‘devm_platform_ioremap_resource’; did you mean ‘devm_ioremap_resource’? [-Werror=implicit-function-declaration]
base = devm_platform_ioremap_resource(pdev, 0);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
devm_ioremap_resource
snd-soc-bcm2835-i2s.c:855:7: warning: assignment to ‘void *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
base = devm_platform_ioremap_resource(pdev, 0);
I've tried removing warning flags when compiling with -Wno-error but no success. I'm nervous to make any additional modifications to the original source file. I wonder if you encountered the same problem, if so how did you overcome it.

UPDATE: I've managed to compile by reverting to an older version of the source file. However, I'm trying to record at 16-bit 44100Hz but the recorded file is full of noise. I can't get any proper sound, I've commented out mode |= BCM2835_I2S_PDMN and I'm only using mode |= BCM2835_I2S_PDME

UPDATE2: I can now successfully record sound with a PDM microphone on a RPI. I uncommented mode |= BCM2835_I2S_PDMN. Using the following code I can record 16-bit at 48000Hz.


UPDATE3: I found out it was a current problem. My power supply didn't have enough current. I still get that initial pop sound when recording starts but other than that, everything is working. Thanks @Rolerex and every one else on this thread for your input.

Code: Select all

arecord -D plughw:1 -c1 -r 48000 -f S16_LE -d 60 -t wav -V mono -v test.wav
But now I keep hearing a popping/clicking sound on all my recordings? I'm not sure if it is the microphone or something related to ALSA? Anyone has an idea?
Rolerex wrote:
Tue Sep 17, 2019 10:42 am
Hello again,

I finally managed to record with a pdm microphone a 16 bits pcm, 192000Hz, mono channel signal and a 32 bits pcm, 96000Hz, mono channel signal. I'm using a RPi 3.B
Here are the steps:
1/ I picked this loader to have a soundcard showing up in alsa. https://github.com/PaulCreaser/rpi-i2s-audio. I compiled it and put it in /lib/modules/$(uname -r) which is 4.14.79-v7+ for me. I added "my_loader" in /etc/modules which is the name of the .ko file compiled. I also added "snd-bcm2835", i'm not sure if it's necessary but i did it anyway.
2/ I modified bcm2835-i2s.c to fix the clock rate (bclk_rate) at 1536000 somewhere after the 380th line. You also have to add the following lines before it writes it in the register.

Code: Select all

	mode |= BCM2835_I2S_PDMN; // 32 bits
	mode |= BCM2835_I2S_PDME;
	
	regmap_write(dev->i2s_regmap, BCM2835_I2S_MODE_A_REG, mode);
Be carefull, the PDMN is only for 32bits, you can comment it or put a condition to get a 16 bits signal.
Then I compiled it and replace /lib/modules/$(uname -r)/kernel/sound/soc/bcm/snd-soc_bcm2538-i2s.ko with this new module.
3/ The output format is either 16 bit unsigned (for 16 bits) and 20 bits unsigned (for 32 bits). So you have to create a program which delete the offset -32767 (for 16 bits) and -524287 (for 32 bits). This allows you to convert the signal in signed signal, to be able to observe it in audacity.

If you consider modifying the sampling_rate, you can either switch from 16 bits to 32 bits or change the bclk_rate. This depends on the hardware you are using.
I think this is some kind of cheesy way to do it, but it works fine for me.
By the way, if you want to record the 20 bits signal, you can record it in 32 bits by shifting the bits of each sample by 12 (or multiply by 4096), otherwise your signal will be super small in audacity.

I hope this could help you ;)

DigiSnapMark
Posts: 1
Joined: Sun Apr 11, 2021 5:11 pm

New design codec choices

Sun Apr 11, 2021 5:26 pm

The current availability of audio codec chips is abysmal. If you look at any of the WM series from Cirrus logic for instance, there just aren't any in-stock at the normal distributors, and they don't expect supply until the end of the year. Crazy.

I'm embarking on a design of a carrier board for the CM4 to be used in an underwater camera. We'll connect to a hydrophone, and will have a preamp on board to amplify it and raise the signal level. The next step is to sample the audio in. I'm not convinced we need audio output, but if it were already available, maybe we can find a use.

I've seen PDM mics, but using a PDM modulator don't seem to have any real advantage over using an I2S CODEC or ADC chip. The tough part is picking a chip that :
1) Is actually available
2) Already has code developed for the RPI4 or CM4

The TLV320AIC23 is high on my list for the above reasons, but it's big and old. If anyone has a better suggestion, I'd love to hear it!
TIA

scoot89
Posts: 3
Joined: Wed Apr 07, 2021 2:35 pm

Re: STICKY: The I2S sound thread.

Wed Apr 14, 2021 2:55 pm

For future reference, if others want to use a PDM microphone with the raspberry pi, I've documented my steps.
I've got it working with a bit clock of about 1.4Meg, when raising the bitclock (bclk_rate) in the linux driver as suggested below, my samplerate is all messed up. I've got to dig deeper for that issue, yet it works already as a start:
https://github.com/imec-int/Raspberry-P ... r-Scripts

Sincerely
scoot89 wrote:
Thu Apr 08, 2021 4:50 pm
Hi Rolerex and piright

I've been trying to replicate your process in order to interface a PDM mic (working at 3.072Meg) on a rpi4.
I've documented all my steps to get to your result and am able to record audio (I'm going for the 20/32bits result): https://github.com/imec-int/klankentapp ... nux-driver
Yet I notice the pitch is off when recording with:

Code: Select all

arecord -D plughw:1 -c1 -r 48000 -f S16_LE -d 60 -t wav -V mono -v test.wav
Is this (wrong pitch) something you guys encountered? I can recognize the original audio, yet it is clearly a couple of octaves lower.
When using a scope, I can see my pdm clock is about 3.1Meg, which is in range of my microphone. I saw in a previous post that your clock rate also was supposed to be 3.072Meg, why did you then adapt the linux bcm driver to a bclk_rate of 1536000?

Already lots of thanks for the initial flow!

Sincerely
Wouter
piright wrote:
Mon Oct 21, 2019 12:17 pm
Hi @Rolerex, I would like to follow your steps so that I can record 16-bit. I've made necessary adjustments to the source file in https://github.com/torvalds/linux/blob/ ... 2835-i2s.c . However when I try to compile with

Code: Select all

make -C /lib/modules/$(uname -r )/build M=$(pwd) modules
I encounter the following error
snd-soc-bcm2835-i2s.c:855:9: error: implicit declaration of function ‘devm_platform_ioremap_resource’; did you mean ‘devm_ioremap_resource’? [-Werror=implicit-function-declaration]
base = devm_platform_ioremap_resource(pdev, 0);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
devm_ioremap_resource
snd-soc-bcm2835-i2s.c:855:7: warning: assignment to ‘void *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
base = devm_platform_ioremap_resource(pdev, 0);
I've tried removing warning flags when compiling with -Wno-error but no success. I'm nervous to make any additional modifications to the original source file. I wonder if you encountered the same problem, if so how did you overcome it.

UPDATE: I've managed to compile by reverting to an older version of the source file. However, I'm trying to record at 16-bit 44100Hz but the recorded file is full of noise. I can't get any proper sound, I've commented out mode |= BCM2835_I2S_PDMN and I'm only using mode |= BCM2835_I2S_PDME

UPDATE2: I can now successfully record sound with a PDM microphone on a RPI. I uncommented mode |= BCM2835_I2S_PDMN. Using the following code I can record 16-bit at 48000Hz.


UPDATE3: I found out it was a current problem. My power supply didn't have enough current. I still get that initial pop sound when recording starts but other than that, everything is working. Thanks @Rolerex and every one else on this thread for your input.

Code: Select all

arecord -D plughw:1 -c1 -r 48000 -f S16_LE -d 60 -t wav -V mono -v test.wav
But now I keep hearing a popping/clicking sound on all my recordings? I'm not sure if it is the microphone or something related to ALSA? Anyone has an idea?
Rolerex wrote:
Tue Sep 17, 2019 10:42 am
Hello again,

I finally managed to record with a pdm microphone a 16 bits pcm, 192000Hz, mono channel signal and a 32 bits pcm, 96000Hz, mono channel signal. I'm using a RPi 3.B
Here are the steps:
1/ I picked this loader to have a soundcard showing up in alsa. https://github.com/PaulCreaser/rpi-i2s-audio. I compiled it and put it in /lib/modules/$(uname -r) which is 4.14.79-v7+ for me. I added "my_loader" in /etc/modules which is the name of the .ko file compiled. I also added "snd-bcm2835", i'm not sure if it's necessary but i did it anyway.
2/ I modified bcm2835-i2s.c to fix the clock rate (bclk_rate) at 1536000 somewhere after the 380th line. You also have to add the following lines before it writes it in the register.

Code: Select all

	mode |= BCM2835_I2S_PDMN; // 32 bits
	mode |= BCM2835_I2S_PDME;
	
	regmap_write(dev->i2s_regmap, BCM2835_I2S_MODE_A_REG, mode);
Be carefull, the PDMN is only for 32bits, you can comment it or put a condition to get a 16 bits signal.
Then I compiled it and replace /lib/modules/$(uname -r)/kernel/sound/soc/bcm/snd-soc_bcm2538-i2s.ko with this new module.
3/ The output format is either 16 bit unsigned (for 16 bits) and 20 bits unsigned (for 32 bits). So you have to create a program which delete the offset -32767 (for 16 bits) and -524287 (for 32 bits). This allows you to convert the signal in signed signal, to be able to observe it in audacity.

If you consider modifying the sampling_rate, you can either switch from 16 bits to 32 bits or change the bclk_rate. This depends on the hardware you are using.
I think this is some kind of cheesy way to do it, but it works fine for me.
By the way, if you want to record the 20 bits signal, you can record it in 32 bits by shifting the bits of each sample by 12 (or multiply by 4096), otherwise your signal will be super small in audacity.

I hope this could help you ;)

carla_sch
Posts: 18
Joined: Wed Mar 18, 2015 5:23 pm

Re: New design codec choices

Mon Apr 19, 2021 1:54 pm

DigiSnapMark wrote:
Sun Apr 11, 2021 5:26 pm
The current availability of audio codec chips is abysmal. If you look at any of the WM series from Cirrus logic for instance, there just aren't any in-stock at the normal distributors, and they don't expect supply until the end of the year. Crazy.

I'm embarking on a design of a carrier board for the CM4 to be used in an underwater camera. We'll connect to a hydrophone, and will have a preamp on board to amplify it and raise the signal level. The next step is to sample the audio in. I'm not convinced we need audio output, but if it were already available, maybe we can find a use.

I've seen PDM mics, but using a PDM modulator don't seem to have any real advantage over using an I2S CODEC or ADC chip. The tough part is picking a chip that :
1) Is actually available
2) Already has code developed for the RPI4 or CM4

The TLV320AIC23 is high on my list for the above reasons, but it's big and old. If anyone has a better suggestion, I'd love to hear it!
TIA
The CJMCU PCM1802 is available at Aliexpress and Banggood.
Since the PCM1803 Board is no longer availble I used this Board with the modified simple card kernel module
from a few years ago, discussed in this forum.
I used the GPCLK0 from the raspberry to provide the System Clock for the Board, and it works.
The Problem is that this is an old version of Linux (4.9...) on the Raspberry, for using an actual version
the kernel module has to be recompiled and maybe modified, if possible at all...
Is there an easier way now ?

phofman
Posts: 35
Joined: Mon Oct 07, 2019 1:37 pm

Re: STICKY: The I2S sound thread. [I2S works]

Fri May 14, 2021 2:29 pm

Hi HiassofT,

I am trying to output 24bit I2S (=48bits per frame), I2S DAI slave for bitclock as well as frame clock (both clocks are provided by my external clock circuit). Somewhere I read that the bcm2835 I2S format is decided by sample format width - IMO here https://github.com/raspberrypi/linux/bl ... i2s.c#L355 . However the i2s driver does not include SNDRV_PCM_FMTBIT_S24_3LE in https://github.com/raspberrypi/linux/bl ... i2s.c#L771 . So I added this format to that config in bcm2835-i2s.c as well as to my codec config (using modified hifiberry-dac=rpi_simple_soundcard.c + pcm5102a.c).

Now the I2S accepts the 24bit format S24_3LE (verified in /proc/asound/sndrpihifiberry/pcm0p/sub0/hw_params), but I2S output pin data are incorrect, flipping channels (seemingly randomly, but most likely there is a very deterministic cause).

This is playback of LSB=1 in one channel, LSB=0 in second channel (sox generating square signal period 1 second gain -144dB no dither,

Code: Select all

sox -D -V -r 48000 -n -c 2 -b 24 -t wavpcm out.wav synth 1000 square 1 gain -144 remix 1 0
Wav checked to contain just 1 LSB in one 24bit channel and zeros in the second channel for the positive half of the square wave:

Code: Select all

 dd if=out.wav skip=44 bs=1 | xxd  | head
00000000: 0100 0000 0000 0100 0000 0000 0100 0000  ................
00000010: 0000 0100 0000 0000 0100 0000 0000 0100  ................
00000020: 0000 0000 0100 0000 0000 0100 0000 0000  ................
00000030: 0100 0000 0000 0100 0000 0000 0100 0000  ................
00000040: 0000 0100 0000 0000 0100 0000 0000 0100  ................
00000050: 0000 0000 0100 0000 0000 0100 0000 0000  ................
00000060: 0100 0000 0000 0100 0000 0000 0100 0000  ................
00000070: 0000 0100 0000 0000 0100 0000 0000 0100  ................
00000080: 0000 0000 0100 0000 0000 0100 0000 0000  ................
00000090: 0100 0000 0000 0100 0000 0000 0100 0000  ................
Yet the scope capture is this (taken at samplerate 192kHz, but 48kHz looks identical). Please notice the incorrect code and data flipping between the first and second channels.
NewFile1.png
NewFile1.png (41.91 KiB) Viewed 561 times

Two questions:

A) Please do we have a code for listing current BCM2835 I2S registers somewhere in /sys?

B) Please what is the correct method for outputting 24bit I2S format? My dai_fmt is

.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM

Thank you very much for your help.

Best regards,

Pavel.

phofman
Posts: 35
Joined: Mon Oct 07, 2019 1:37 pm

Re: STICKY: The I2S sound thread. [I2S works]

Fri May 14, 2021 2:48 pm

HiassofT: This is debugfs for the i2s driver:

Code: Select all

[  466.237888] bcm2835-i2s fe203000.i2s: slots: 2 width: 24 rx mask: 0x03 tx_mask: 0x03
[  466.237921] bcm2835-i2s fe203000.i2s: frame len: 48 sync len: 24 data len: 24
[  466.237935] bcm2835-i2s fe203000.i2s: rx pos: 1,25 tx pos: 1,25
[  466.237948] bcm2835-i2s fe203000.i2s: sampling rate: 48000 bclk rate: 2304000
[  466.237961] bcm2835-i2s fe203000.i2s: CLKM: 1 CLKI: 1 FSM: 1 FSI: 1 frame start: falling edge
I see this commit of yours https://github.com/raspberrypi/linux/co ... 8375acfdea but that added 24bits in 32bit wrapper (S24_LE) and outputs thus 64bits in frame.

phofman
Posts: 35
Joined: Mon Oct 07, 2019 1:37 pm

Re: STICKY: The I2S sound thread. [I2S works]

Fri May 14, 2021 3:11 pm

Now this is interesting:

Playback of S24_LE (i.e. physical 32bit, valid 24bit)

Code: Select all

cat /proc/asound/sndrpihifiberry/pcm0p/sub0/hw_params 
access: RW_INTERLEAVED
format: S24_LE
subformat: STD
channels: 2
rate: 48000 (48000/1)
period_size: 1024
buffer_size: 8192
yields:

Code: Select all

[ 1462.994511] bcm2835-i2s fe203000.i2s: slots: 2 width: 32 rx mask: 0x03 tx_mask: 0x03
[ 1462.994550] bcm2835-i2s fe203000.i2s: frame len: 64 sync len: 32 data len: 24
[ 1462.994568] bcm2835-i2s fe203000.i2s: rx pos: 1,33 tx pos: 1,33
[ 1462.994586] bcm2835-i2s fe203000.i2s: sampling rate: 48000 bclk rate: 3072000
[ 1462.994602] bcm2835-i2s fe203000.i2s: CLKM: 1 CLKI: 1 FSM: 1 FSI: 1 frame start: falling edge

phofman
Posts: 35
Joined: Mon Oct 07, 2019 1:37 pm

Re: STICKY: The I2S sound thread. [I2S works]

Fri May 14, 2021 8:04 pm

I think I found it. The I2S DMA runs at 32 bits, therefore only 16-bit aligned physical formats work (hence no S24_3LE listed by the driver).

Because hifiberry_dac does not define field fixed_bclk_ratio in drvdata_hifiberry_dac struct https://github.com/raspberrypi/linux/bl ... ard.c#L272 , snd_pcm_format_physical_width() is used in https://github.com/raspberrypi/linux/bl ... ard.c#L140 - hence the 32 x 2 = 64 bit slot width for S24_LE. When setting the field to 48, the I2S starts working with S24_LE perfectly. BTW this is 768kHz samplerate with the -144dB square (positive half-wave) in one channel only. Thanks for your patience!
NewFile2.png
NewFile2.png (39.79 KiB) Viewed 525 times

phofman
Posts: 35
Joined: Mon Oct 07, 2019 1:37 pm

Re: STICKY: The I2S sound thread. [I2S works]

Fri May 14, 2021 8:32 pm

I do not have a 1,536kHz DAC, but I2S signal would be available :-)
Attachments
NewFile3.png
NewFile3.png (39.78 KiB) Viewed 519 times

phofman
Posts: 35
Joined: Mon Oct 07, 2019 1:37 pm

Re: STICKY: The I2S sound thread. [I2S works]

Sat May 15, 2021 9:38 am

sine 150kHz -6dB @768kHz samplerate, AK4493
NewFile4.png
NewFile4.png (40.5 KiB) Viewed 504 times
Now to test bitperfection with HW I2S loopback...

phofman
Posts: 35
Joined: Mon Oct 07, 2019 1:37 pm

Re: STICKY: The I2S sound thread. [I2S works]

Sun May 16, 2021 12:26 pm

Just an info - I2S out -> IN connected on the pin header (on my shield board), bitperfect up to 1,024kHz samplerate/48bits frame size. This is spectrogram of recorded 341kHz sine @1024kHz I2S loopback
spectrogram.png
spectrogram.png (6.86 KiB) Viewed 488 times
Both playback and capture running at 1024000/24bits:

Code: Select all

access: RW_INTERLEAVED
format: S24_LE
subformat: STD
channels: 2
rate: 1024000 (1024000/1)
period_size: 1024
buffer_size: 8192
Period size left at SoX default 1024 samples which means IRQ every 1ms, safe operation, no xruns. Raspbian64. kernel 5.12 64bit.

Loopback at 1,536kHz samplerate was corrupted, maybe CM4 with extra short traces would work, but regular RPi4 does not.

IMO the rate_max fields at https://github.com/raspberrypi/linux/bl ... i2s.c#L770 could safely be raised to 768000 in the official kernel for RPi4 (no provision for model selection though).

phofman
Posts: 35
Joined: Mon Oct 07, 2019 1:37 pm

Re: STICKY: The I2S sound thread. [I2S works]

Sun May 16, 2021 8:18 pm

FYI: 1536kHz @16bits sample size = 32bit frame size => the already tested 49MHz bitclock.

Code: Select all

access: RW_INTERLEAVED
format: S16_LE
subformat: STD
channels: 2
rate: 1536000 (1536000/1)
period_size: 2048
buffer_size: 16384
And the bitperfect I2S loopback of 700kHz sine @1536kHz/16bit/2ch
spectrogram.png
spectrogram.png (7.5 KiB) Viewed 466 times

christofer_hc
Posts: 4
Joined: Fri Feb 05, 2021 7:11 pm

Re: STICKY: The I2S sound thread. [I2S works]

Tue Jun 08, 2021 5:24 pm

Hello everyone,

I've tried streaming Audio & video in this chinese CSI HDMI Bridge, via UDP from RPI to another PC a few months ago. But I couldn't manage to make it work. I tried to make the "patch" but still didn't work.

I've recently acquired a Raspberry 4 Compute Module and it's IO Board, alongside with an Auvidea B102. I'm still having problems with the sound. I've also tried to follow the manual available at the Auvidea site, didn't work for me.

I put as much info as possible. I'm not a Linux expert though.

This is my current setup:

/boot/config.txt

Code: Select all

# For more options and information see
# http://rpf.io/configtxt
# Some settings may impact device functionality. See link above for details

# uncomment if you get no picture on HDMI for a default "safe" mode
#hdmi_safe=1

# uncomment this if your display has a black border of unused pixels visible
# and your display can output without overscan
disable_overscan=1

# uncomment the following to adjust overscan. Use positive numbers if console
# goes off screen, and negative if there is too much border
#overscan_left=16
#overscan_right=16
#overscan_top=16
#overscan_bottom=16

# uncomment to force a console size. By default it will be display's size minus
# overscan.
#framebuffer_width=1280
#framebuffer_height=720

# uncomment if hdmi display is not detected and composite is being output
hdmi_force_hotplug=1

# uncomment to force a specific HDMI mode (this will force VGA)
hdmi_group=2
hdmi_mode=85

# uncomment to force a HDMI mode rather than DVI. This can make audio work in
# DMT (computer monitor) modes
#hdmi_drive=2

# uncomment to increase signal to HDMI, if you have interference, blanking, or
# no display
#config_hdmi_boost=4

# uncomment for composite PAL
#sdtv_mode=2

#uncomment to overclock the arm. 700 MHz is the default.
#arm_freq=800

# Uncomment some or all of these to enable the optional hardware interfaces
dtparam=i2c_arm=on
dtparam=i2s=on
dtparam=spi=on

# Uncomment this to enable infrared communication.
#dtoverlay=gpio-ir,gpio_pin=17
#dtoverlay=gpio-ir-tx,gpio_pin=18

# Additional overlays and parameters are documented /boot/overlays/README
dtparam=i2c_vc=on
#dtoverlay=dwc2,dr_mode=host
dtoverlay=dwc2
#dtoverlay=tc358743
dtoverlay=tc358743,4lane=1
#dtoverlay=tc358743,4lane=1,link-frequency=297000000
dtoverlay=tc358743-audio

# Enable audio (loads snd_bcm2835)
dtparam=audio=on

[pi4]
# Enable DRM VC4 V3D driver on top of the dispmanx display stack
dtoverlay=vc4-fkms-v3d
max_framebuffers=3

[all]
#dtoverlay=vc4-fkms-v3d
start_x=1
gpu_mem=128
Accordingly to previous posts, I've supposed the boards should be connected like:

Code: Select all

           B102    RPI (J8)
A-DATA     5       38 (GPIO20)
A-BCK      6       12 (GPIO18)
A-LRCK     7       35 (GPIO19)

The flat cable I connected to CAM1 (I read somewhere that it shouldn't be connected to CAM1, instead of CAM0 for some reason).
I didn't find neither if the RPI requires MCK to be connected nor a pin for that signal. Didn't found anything about the other B102 IOs (RESET, CABLE)

I've downloaded the EDID provided by 6by9 (at https://github.com/6by9/CSI2_device_config). And tried to run with the following commands:

Code: Select all

v4l2-ctl --set-edid=file=/home/pi/Documents/1080P60EDID.txt --fix-edid-checksums
v4l2-ctl --set-edid=type=hdmi
v4l2-ctl --set-dv-bt-timings query
v4l2-ctl -v height=1280,width=720,pixelformat=UYVY
EDID file used in previous step

Code: Select all

00ffffffffffff005262888800888888
1c150103800000780aEE91A3544C9926
0F505400000001010101010101010101
010101010101011d007251d01e206e28
5500c48e2100001e8c0ad08a20e02d10
103e9600138e2100001e000000fc0054
6f73686962612d4832430a20000000FD
003b3d0f2e0f1e0a202020202020014f
020322444f841303021211012021223c
3d3e101f2309070766030c00300080E3
007F8c0ad08a20e02d10103e9600c48e
210000188c0ad08a20e02d10103e9600
138e210000188c0aa01451f01600267c
4300138e210000980000000000000000
00000000000000000000000000000000
00000000000000000000000000000015
When I stream video only, the following command works.

Code: Select all

# STREAM VIDEO ONLY. TOPS 15 fps @ 720p
ffmpeg -f v4l2 -thread_queue_size 5k -input_format mjpeg -pix_fmt uyvy422 -s 1280x720 -framerate 30 -probesize 42M -i /dev/video0 -b:v 20M -c:v h264_omx -f mpegts udp://192.168.1.4:5000?pkt_size=1316

I've tried this command to stream Audio & video, but didn't work.

Code: Select all

ffmpeg -f v4l2 -thread_queue_size 5k -input_format mjpeg -pix_fmt uyvy422 -s 1280x720 -framerate 30 -probesize 42M -i /dev/video0 -f alsa -thread_queue_size 4096 -i plughw:tc358743 -acodec pcm_s16le -ac 2 -ar 44100 -copytb 1 -use_wallclock_as_timestamps 1 -c:a aac -b:a 128k -ar 44100 -b:v 20M -c:v h264_omx -f mpegts udp://192.168.1.4:5000?pkt_size=1316
This previous command hangs with the following log (it doesn't return to terminal).

Code: Select all

[video4linux2,v4l2 @ 0x16b63d0] ioctl(VIDIOC_G_PARM): Inappropriate ioctl for device
[video4linux2,v4l2 @ 0x16b63d0] Time per frame unknown
Input #0, video4linux2,v4l2, from '/dev/video0':
  Duration: N/A, start: 336.957592, bitrate: N/A
    Stream #0:0: Video: rawvideo (UYVY / 0x59565955), uyvy422, 1280x720, 60 tbr, 1000k tbn, 1000k tbc
When I press CTRL+C I get some additional output

Code: Select all

Guessed Channel Layout for Input Stream #1.0 : stereo
Input #1, alsa, from 'plughw:tc358743':
  Duration: N/A, bitrate: 1536 kb/s
    Stream #1:0: Audio: pcm_s16le, 48000 Hz, stereo, s16, 1536 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (h264_omx))
  Stream #1:0 -> #0:1 (pcm_s16le (native) -> aac (native))
Press [q] to stop, [?] for help
But neither 'q' nor '?' works. I need to CTRL+C again to return to terminal.


Another thing I've tried was to record audio with the 'arecord' command:

Code: Select all

pi@raspberrypi:~ $ sudo arecord -Dhw:1,0 -d 10 -f cd -t wav test.wav
Recording WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
arecord: pcm_read:2145: read error: Input/output error
Device List

Code: Select all

pi@raspberrypi:~ $ arecord -l
**** List of CAPTURE Hardware Devices ****
card 1: tc358743 [tc358743], device 0: bcm2835-i2s-dir-hifi dir-hifi-0 [bcm2835-i2s-dir-hifi dir-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
pi@raspberrypi:~ $

Can anyone spot something wrong here?

Many thanks, and sorry for the long post.

--
Chrístofer

RootKiiit
Posts: 15
Joined: Wed Nov 20, 2013 6:52 pm

Re: New design codec choices

Mon Jun 14, 2021 1:31 pm

carla_sch wrote:
Mon Apr 19, 2021 1:54 pm

...
The CJMCU PCM1802 is available at Aliexpress and Banggood.
Since the PCM1803 Board is no longer availble I used this Board with the modified simple card kernel module
from a few years ago, discussed in this forum.
I used the GPCLK0 from the raspberry to provide the System Clock for the Board, and it works.
The Problem is that this is an old version of Linux (4.9...) on the Raspberry, for using an actual version
the kernel module has to be recompiled and maybe modified, if possible at all...
Is there an easier way now ?
Did You used GPCLK0? I have a PCM1808 codec soldering in a slave mode and having pin for MCLK... I don't know how I to make it... :cry:

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