added i2s Device Tree Files and i2s streaming test (esp32->python)
parent
6330d452c1
commit
ee92e1a484
Binary file not shown.
|
|
@ -0,0 +1,53 @@
|
||||||
|
/dts-v1/;
|
||||||
|
/plugin/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
metadata {
|
||||||
|
title = "Enable I2S3-M0 INMP441";
|
||||||
|
compatible = "radxa,rock-3c", "radxa,zero3";
|
||||||
|
category = "audio";
|
||||||
|
description = "Enable INMP441 on I2S3-M0";
|
||||||
|
/* Hard-coded GPIO numbers for GPIO3_A3/A4/A5/A6 */
|
||||||
|
exclusive = "99", "100", "102", "101", "i2s3_2ch";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&{/} {
|
||||||
|
dummy_codec: dummy-codec {
|
||||||
|
compatible = "rockchip,dummy-codec";
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
dummy_sound: dummy-sound {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
compatible = "simple-audio-card";
|
||||||
|
simple-audio-card,format = "i2s";
|
||||||
|
simple-audio-card,bitclock-master = <&i2s3_2ch>;
|
||||||
|
simple-audio-card,frame-master = <&i2s3_2ch>;
|
||||||
|
simple-audio-card,mclk-fs = <256>;
|
||||||
|
simple-audio-card,name = "i2s3-inmp441";
|
||||||
|
simple-audio-card,dai-link@0 {
|
||||||
|
reg = <0>;
|
||||||
|
format = "i2s";
|
||||||
|
cpu {
|
||||||
|
sound-dai = <&i2s3_2ch>;
|
||||||
|
};
|
||||||
|
codec {
|
||||||
|
sound-dai = <&dummy_codec>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&i2s3_2ch {
|
||||||
|
pinctrl-0 = <&i2s3m0_sclk
|
||||||
|
&i2s3m0_lrck
|
||||||
|
&i2s3m0_sdi
|
||||||
|
&i2s3m0_sdo>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&i2c3 {
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
/dts-v1/;
|
||||||
|
/plugin/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
metadata {
|
||||||
|
title = "Enable I2S3-M0 INMP441";
|
||||||
|
compatible = "radxa,rock-3c", "radxa,zero3";
|
||||||
|
category = "audio";
|
||||||
|
description = "Enable INMP441 on I2S3-M0";
|
||||||
|
/* Hard-coded GPIO numbers for GPIO3_A3/A4/A5/A6 */
|
||||||
|
exclusive = "99", "100", "102", "101", "i2s3_2ch";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&{/} {
|
||||||
|
dummy_codec: dummy-codec {
|
||||||
|
compatible = "rockchip,dummy-codec";
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
dummy_sound: dummy-sound {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
compatible = "simple-audio-card";
|
||||||
|
simple-audio-card,format = "i2s";
|
||||||
|
simple-audio-card,mclk-fs = <256>;
|
||||||
|
simple-audio-card,name = "i2s3-inmp441";
|
||||||
|
simple-audio-card,dai-link@0 {
|
||||||
|
reg = <0>;
|
||||||
|
format = "i2s";
|
||||||
|
cpu {
|
||||||
|
sound-dai = <&i2s3_2ch>;
|
||||||
|
};
|
||||||
|
codec {
|
||||||
|
sound-dai = <&dummy_codec>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&i2s3_2ch {
|
||||||
|
pinctrl-0 = <&i2s3m0_sclk
|
||||||
|
&i2s3m0_lrck
|
||||||
|
&i2s3m0_sdi
|
||||||
|
&i2s3m0_sdo>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&i2c3 {
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
import serial
|
||||||
|
import wave
|
||||||
|
import struct
|
||||||
|
|
||||||
|
# === CONFIGURATION ===
|
||||||
|
SERIAL_PORT = 'COM7' # Update this to match your system
|
||||||
|
BAUD_RATE = 1000000
|
||||||
|
SAMPLE_RATE = 8000
|
||||||
|
DURATION_SECONDS = 5
|
||||||
|
OUTPUT_FILE = 'esp32_audio.wav'
|
||||||
|
|
||||||
|
# === SETUP SERIAL ===
|
||||||
|
ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=0.01)
|
||||||
|
|
||||||
|
# === PREPARE TO CAPTURE ===
|
||||||
|
print(f"Recording {DURATION_SECONDS} seconds of audio...")
|
||||||
|
|
||||||
|
samples = []
|
||||||
|
max_samples = SAMPLE_RATE * DURATION_SECONDS
|
||||||
|
chunk_size = 4096 # bytes
|
||||||
|
|
||||||
|
# === CAPTURE LOOP ===
|
||||||
|
while len(samples) < max_samples:
|
||||||
|
data = ser.read(chunk_size)
|
||||||
|
for i in range(0, len(data) - 1, 2):
|
||||||
|
sample = int.from_bytes(data[i:i+2], byteorder='little', signed=True)
|
||||||
|
samples.append(sample)
|
||||||
|
if len(samples) % 1000 == 0:
|
||||||
|
print(f"{len(samples)} samples captured")
|
||||||
|
|
||||||
|
ser.close()
|
||||||
|
|
||||||
|
# === NORMALIZE AUDIO ===
|
||||||
|
peak = max(abs(s) for s in samples)
|
||||||
|
scale = 32767 / peak if peak > 0 else 1.0
|
||||||
|
normalized = [int(max(-32768, min(32767, s * scale))) for s in samples]
|
||||||
|
|
||||||
|
# === WRITE TO WAV FILE ===
|
||||||
|
with wave.open(OUTPUT_FILE, 'w') as wav:
|
||||||
|
wav.setnchannels(1)
|
||||||
|
wav.setsampwidth(2) # 16-bit
|
||||||
|
wav.setframerate(SAMPLE_RATE)
|
||||||
|
for sample in normalized:
|
||||||
|
wav.writeframes(struct.pack('<h', sample))
|
||||||
|
|
||||||
|
print(f"Saved normalized audio to {OUTPUT_FILE}")
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include <driver/i2s.h>
|
||||||
|
|
||||||
|
#define I2S_WS 6 // LRCL (Word Select)
|
||||||
|
#define I2S_SCK 7 // BCLK (Serial Clock)
|
||||||
|
#define I2S_SD 8 // DOUT (Serial Data from mic)
|
||||||
|
|
||||||
|
#define I2S_PORT I2S_NUM_0
|
||||||
|
#define BUFFER_SIZE 2048 // Larger buffer = fewer calls
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(1000000); // High-speed serial for streaming audio
|
||||||
|
|
||||||
|
// I2S configuration
|
||||||
|
const i2s_config_t i2s_config = {
|
||||||
|
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
|
||||||
|
.sample_rate = 8000,
|
||||||
|
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
|
||||||
|
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
|
||||||
|
.communication_format = I2S_COMM_FORMAT_I2S,
|
||||||
|
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||||
|
.dma_buf_count = 4,
|
||||||
|
.dma_buf_len = BUFFER_SIZE / 4,
|
||||||
|
.use_apll = false,
|
||||||
|
.tx_desc_auto_clear = false,
|
||||||
|
.fixed_mclk = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
const i2s_pin_config_t pin_config = {
|
||||||
|
.bck_io_num = I2S_SCK,
|
||||||
|
.ws_io_num = I2S_WS,
|
||||||
|
.data_out_num = I2S_PIN_NO_CHANGE,
|
||||||
|
.data_in_num = I2S_SD
|
||||||
|
};
|
||||||
|
|
||||||
|
i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
|
||||||
|
i2s_set_pin(I2S_PORT, &pin_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
uint8_t buffer[BUFFER_SIZE];
|
||||||
|
size_t bytes_read;
|
||||||
|
|
||||||
|
if (i2s_read(I2S_PORT, &buffer, BUFFER_SIZE, &bytes_read, portMAX_DELAY) == ESP_OK && bytes_read > 0) {
|
||||||
|
for (int i = 0; i < bytes_read; i += 4) {
|
||||||
|
int32_t sample_32 = *(int32_t*)&buffer[i];
|
||||||
|
int16_t sample_16 = sample_32 >> 12; // Less aggressive shift
|
||||||
|
|
||||||
|
Serial.write((uint8_t*)&sample_16, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue