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

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