diff --git a/i2s_streaming_test/esp32_audio.wav b/i2s_streaming_test/esp32_audio.wav new file mode 100644 index 0000000..29649b1 Binary files /dev/null and b/i2s_streaming_test/esp32_audio.wav differ diff --git a/i2s_streaming_test/rk3568-i2s3-m0-inmp441.dts b/i2s_streaming_test/rk3568-i2s3-m0-inmp441.dts new file mode 100644 index 0000000..d47f8d5 --- /dev/null +++ b/i2s_streaming_test/rk3568-i2s3-m0-inmp441.dts @@ -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"; +}; diff --git a/i2s_streaming_test/rk3568-i2s3-m0-inmp441_dummy.dts b/i2s_streaming_test/rk3568-i2s3-m0-inmp441_dummy.dts new file mode 100644 index 0000000..07e3a9c --- /dev/null +++ b/i2s_streaming_test/rk3568-i2s3-m0-inmp441_dummy.dts @@ -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"; +}; diff --git a/i2s_streaming_test/serial_sound.py b/i2s_streaming_test/serial_sound.py new file mode 100644 index 0000000..72e4e82 --- /dev/null +++ b/i2s_streaming_test/serial_sound.py @@ -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(' + +#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); + } + } +} diff --git a/test.wav b/test.wav new file mode 100644 index 0000000..bf85b50 Binary files /dev/null and b/test.wav differ