Created
December 29, 2021 13:05
-
-
Save xdsopl/ecb4324d7904333244916a613129d8a9 to your computer and use it in GitHub Desktop.
PDM MEMS microphone to 16 bit at 16 kHz PCM using a 2 MHz crystal oscillator and a logic analyzer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| 2 MHz clock goes to the PDM MEMS microphone and channel 0 of the logic analyzer. | |
| The logic analyzer needs at least a 6 MHz sample rate or three times the clock rate. | |
| Data signal from the microphone goes to channel 4 of the logic analyzer. | |
| Tested using a MP34DT01-M with select connected to ground. | |
| compile: | |
| gcc -Ofast -Wall -o pdm pdm.c | |
| stream to speakers: | |
| sigrok-cli -d fx2lafw --continuous --config samplerate=8MHz -O binary | ./pdm | aplay -t raw -f S16_LE -r 16000 -c 1 - | |
| record to wav file: | |
| sigrok-cli -d fx2lafw --continuous --config samplerate=8MHz -O binary | ./pdm | sox -t raw -r 16000 -b 16 -c 1 -L -e signed-integer - record.wav | |
| */ | |
| #include <stdio.h> | |
| #include <limits.h> | |
| int integrator_cascade(int x) | |
| { | |
| static int sum0, sum1, sum2; | |
| return sum2 += (sum1 += (sum0 += x)); | |
| } | |
| int comb_cascade(int x) | |
| { | |
| static int prv2, prv1, prv0; | |
| int tmp = x; | |
| tmp -= prv0; prv0 = x; x = tmp; | |
| tmp -= prv1; prv1 = x; x = tmp; | |
| tmp -= prv2; prv2 = x; x = tmp; | |
| return x; | |
| } | |
| int block_dc(int x) | |
| { | |
| static int avg; | |
| avg = (15 * avg + x) / 16; | |
| return x - avg; | |
| } | |
| int clamp(int x) | |
| { | |
| return x < SHRT_MIN ? SHRT_MIN : x > SHRT_MAX ? SHRT_MAX : x; | |
| } | |
| int main() | |
| { | |
| for (int chr = 0, pclk = 0, pdat = 0, num = 0; chr >= 0; chr = getchar()) { | |
| int sel = 0; | |
| int clk = (chr & 1) ^ sel; | |
| int dat = (chr >> 4) & 1; | |
| if (!pclk && clk) { | |
| int intp = integrator_cascade(pdat); | |
| if (++num == 125) { | |
| num = 0; | |
| int norm = clamp(block_dc(comb_cascade(intp))); | |
| putchar(norm & 255); | |
| putchar((norm >> 8) & 255); | |
| } | |
| } | |
| pclk = clk; | |
| pdat = dat; | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment