-
Notifications
You must be signed in to change notification settings - Fork 0
/
pdm3.ino
120 lines (101 loc) · 3.63 KB
/
pdm3.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "driver/i2s.h"
#include "dsps_fft2r.h"
#define READ_DELAY 3000 // millisec
const i2s_port_t I2S_PORT = I2S_NUM_0;
const int BLOCK_SIZE = 512;
int samples[BLOCK_SIZE];
#define SAMPLE_RATE 24000
long total_read = 0;
// http://www.schwietering.com/jayduino/filtuino/index.php?characteristic=be&passmode=hp&order=2&usesr=usesr&sr=24000&frequencyLow=100¬eLow=¬eHigh=&pw=pw&calctype=float&run=Send
//High pass bessel filter order=2 alpha1=0.0041666666666667
class FilterBeHp2
{
public:
FilterBeHp2()
{
v[0]=0.0;
v[1]=0.0;
}
private:
float v[3];
public:
float step(float x) //class II
{
v[0] = v[1];
v[1] = v[2];
v[2] = (9.823849154958753660e-1 * x)
+ (-0.96497792085018785357 * v[0])
+ (1.96456174113331383246 * v[1]);
return
(v[0] + v[2])
- 2 * v[1];
}
};
FilterBeHp2 filter;
void init_pdm() {
esp_err_t err;
i2s_config_t audio_in_i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM),
.sample_rate = SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, // although the SEL config should be left, it seems to transmit on right
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_LSB),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // high interrupt priority
.dma_buf_count = 4,
.dma_buf_len = BLOCK_SIZE
};
// This function must be called before any I2S driver read/write operations.
err = i2s_driver_install(I2S_PORT, &audio_in_i2s_config, 0, NULL);
if (err != ESP_OK) {
Serial.printf("Failed installing driver: %d\n", err);
while (true);
}
// configure which pin on the ESP32 is connected to which pin on the mic:
i2s_pin_config_t audio_in_pin_config = {
.bck_io_num = I2S_PIN_NO_CHANGE, // not used
.ws_io_num = 15, // IO 15 clock pin
.data_out_num = I2S_PIN_NO_CHANGE, // Not used
.data_in_num = 16 // data pin
};
err = i2s_set_pin(I2S_PORT, &audio_in_pin_config);
if (err != ESP_OK) {
Serial.printf("Failed setting pin: %d\n", err);
while (true);
}
}
void setup() {
Serial.begin(2000000);
// Initialize the I2S peripheral
init_pdm();
// Create a task that will read the data
xTaskCreatePinnedToCore(process_samples, "PDM_reader", 2048, NULL, 1, NULL, 1);
}
void process_samples(void *pvParameters) {
while(1){
int num_bytes_read = i2s_read(I2S_PORT,
(char *)samples,
BLOCK_SIZE, // the doc says bytes, but its elements.
portMAX_DELAY); // no timeout
if (num_bytes_read > 0) {
int samples_read = num_bytes_read / 4;
total_read += samples_read;
float sample;
for(int i=0; i < samples_read; i++) {
sample = filter.step((float)samples[i] / INT_MAX);
//sample = (float)samples[i] / INT_MAX;
Serial.println((short)(sample * SHRT_MAX));
}
// float rms = 0;
// for(int i=0; i < nsamples; i++) {
// float p = samples[i * 2 + 1] - avg;
// rms = p * p;
// }
// float spl = 20 * log10f(sqrtf(rms / nsamples));
// Serial.println(spl);
}
}
}
void loop() {
delay(READ_DELAY);
// Read multiple samples at once and calculate the sound pressure
}