Rolerex
Posts: 2
Joined: Fri Aug 30, 2019 9:39 am

Re: STICKY: The I2S sound thread.

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 ;)

piright
Posts: 1
Joined: Mon Oct 21, 2019 12:05 pm

Re: STICKY: The I2S sound thread.

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 ;)

pkuhar
Posts: 2
Joined: Wed Jul 24, 2019 4:36 pm

Re: STICKY: The I2S sound thread.

Sat Dec 14, 2019 6:52 pm

Does anyone know if this PDM fix will work with RPI 4

hipgnosis
Posts: 2
Joined: Wed Dec 25, 2019 4:43 pm

Re: STICKY: The I2S sound thread.

Thu Dec 26, 2019 10:40 am

Hi,
i'm Raspy beginner ia have a question: i' ve read in the BCM 2835 datasheet "Jitter is therefore reduced by increasing the source clock frequency. In applications where
jitter is a concern, the fastest available clock source should be used."
I' ve found o a Isotemp OCXO Clock but the frequency is 19.44 Mhz not 19.2 Mhz, In your opinion is it possible to use it instead of the crappy 19.2 Mhz original raspy oscillator?

HiassofT
Posts: 226
Joined: Fri Jun 30, 2017 10:07 pm
Location: Salzburg, Austria
Contact: Website

Re: STICKY: The I2S sound thread.

Thu Dec 26, 2019 8:16 pm

hipgnosis wrote:
Thu Dec 26, 2019 10:40 am
i'm Raspy beginner ia have a question: i' ve read in the BCM 2835 datasheet "Jitter is therefore reduced by increasing the source clock frequency. In applications where
jitter is a concern, the fastest available clock source should be used."
I' ve found o a Isotemp OCXO Clock but the frequency is 19.44 Mhz not 19.2 Mhz, In your opinion is it possible to use it instead of the crappy 19.2 Mhz original raspy oscillator?
If you are concerned about jitter then it's best to not use the RPi as a I2S clock master but use two switchable oscillators (one for the 44.1kHz family of sample rates and another one for the 48kHz family) on the soundcard and configure the RPi as a clock slave.

Replacing the 19.2MHz oscillator with a differrent freuqency one quite certainly won't work without modifications of the closed source firmware. Also it won't help you much in respect to jitter as the I2S clock would still be derived from the 500MHz PLL via a fractional divider.

so long,

Hias

alexjaw
Posts: 4
Joined: Tue Dec 24, 2019 7:46 am

Re: STICKY: The I2S sound thread.

Sun Dec 29, 2019 8:08 am

I am trying to understand how machine drivers and codecs for raspberry are connected together. It's simple for a rs proto board https://www.mikroe.com/audio-codec-proto-board. Machine driver is snd_soc_rpi_proto and corresponing codec is snd_soc_wm8731. But how is for a board such as the mbed RS audio codec https://os.mbed.com/cookbook/RS-Audio-Codec? Earlier I think that it was managed by the machine driver rpi-dac, but now it's rpi-simple-soundcard, which defines a link to rpi-dac. But then, why is it linked to the codec pcm1794a when there is a specific tlv320 codec, tlv320aic23? Is it because rpi-simple-soundcard is a minimalistic driver that does not use all the bells and whistles provided by tlv320aic23?

I am working on a dsp codec project (based on adau1467) with playback, recording and i2c control. It is supposed to be interfaced with a raspberry. Therefore I really need to understand all details of ASoC.

Let me also express my gratitude to HiassofT for his engagement in this thread and sharing his knowledge with us.

Happy new year,
A.

Morocco_Bama
Posts: 10
Joined: Fri May 11, 2018 4:47 am

Re: STICKY: The I2S sound thread.

Wed Jan 08, 2020 2:37 am

Hi everyone,

Bear with me, I am currently trying to cycle through this entire thread to see if all my questions have been answered. I'm about 30% through.

I'm trying to make an audio sampler / looper / live-playback pedal using the Raspberry Pi. The ADC/DAC hat I've been using (or trying to use) is the PMOD I2S2 https://store.digilentinc.com/pmod-i2s2 ... nd-output/.

I thought it would be a fun challenge for me to implement my project at the register level from scratch, but after getting stuck with the PCM setup and coming here I'm starting to wonder if this is way beyond the scope of what I know (I'm pretty familiar with ARM and CPU programming, but not so much OS and kernel). I have the Pi in slave mode for PCM, as the PMOD can generate its own PCM_CLK and PCM_FS signals.

I had no troubles setting up the clock registers and (from what I can tell by debugging) I have set all the bits in the PCM control, mode, etc. registers correctly. But then I tried using DMA mode, and... well, looks like I'm not the only one who had troubles here.

Some questions:

Do I have the right approach here for DMA, or am I way off?

I set up 2 DMA channels.
One channel has a control block with SRC_ADDR = PCM_FIFO, and DEST_ADDR = &my_buffer, and is set up to listen for SRC_DREQ, which is set to the RX DREQ in the PERMAP bits (this is my RX DMA control block).
The other channel has a control block with SRC_ADDR = &my_buffer, DEST_ADDR = PCM_FIFO, DEST_DREQ, TX DREQ in PERMAP (TX DMA control block).
Both control blocks point back to themselves.
My thought process was that both RX and TX processes, since they're dictated by DREQ signals in DMA mode, are independent of each other, so they can be operated by seperate DMA registers. It sounds like I have to be careful to have &my_buffer be an address in uncached memory?

Duplex mode not possible?

Is it because there's only one PCM_FIFO? Can I not have TXON and RXON simultaneously? Will I have to "listen" for when DMA is writing or reading and set TXON or RXON accordingly each time? Can I not do both TXON and RXON at all?

Can I successfully get DMA mode running just by setting up my controllers, buffer and PCM interface properly at the register level? If not, what else do I need?

This is where the discussions in this thread start going over my head a bit. Are there default processes on the Pi that keep the DMA from operating / things that need to be switched off / things that need to be switched on? Do I have to modify the kernel itself in some manner (wouldn't know where to start)? Do I need to define a device tree overlay for the PMOD I2S2? I've seen a lot of comments about "ALSA drivers". I'm familiar with ALSA - my definition of a driver is just code that "drives" hardware? So if I write register-level code for PCM, isn't that just driver code? Do I need to use some set of ALSA libraries or something?

***

Anyways, sorry, if any or all of my above questions have already been answered. There's a lot to navigate in this thread. I'd love an abridged guide or tutorial on I2S setup for the Pi, if anybody has a link to an existing one?

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