From 0572a61c93c93b99e381379af62102342ae4238a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 22:27:13 +0000 Subject: [PATCH 1/6] Initial plan From 11d990d8875bebe281faad5159f93991288cd073 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 22:37:59 +0000 Subject: [PATCH 2/6] Add ES7210 microphone support for M5Stack CoreS3 Co-authored-by: meganetaaan <1918755+meganetaaan@users.noreply.github.com> --- .../targets/m5stack_cores3/manifest.json | 11 ++- .../targets/m5stack_cores3/setup-target.js | 5 + modules/drivers/peripherals/es7210/es7210.js | 98 +++++++++++++++++++ .../drivers/peripherals/es7210/manifest.json | 8 ++ modules/io/audioin/esp32/audioin.c | 5 +- 5 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 modules/drivers/peripherals/es7210/es7210.js create mode 100644 modules/drivers/peripherals/es7210/manifest.json diff --git a/build/devices/esp32/targets/m5stack_cores3/manifest.json b/build/devices/esp32/targets/m5stack_cores3/manifest.json index 93f4f618a..a727aa681 100644 --- a/build/devices/esp32/targets/m5stack_cores3/manifest.json +++ b/build/devices/esp32/targets/m5stack_cores3/manifest.json @@ -10,10 +10,12 @@ "include": [ "$(MODDABLE)/modules/io/manifest.json", "$(MODDABLE)/modules/io/audioout/manifest.json", + "$(MODDABLE)/modules/io/audioin/manifest.json", "$(MODDABLE)/modules/drivers/ili9341/manifest.json", "$(MODDABLE)/modules/drivers/sensors/ft6206/manifest.json", "$(MODDABLE)/modules/drivers/peripherals/axp2101/manifest.json", - "$(MODDABLE)/modules/drivers/peripherals/bm8563/manifest.json" + "$(MODDABLE)/modules/drivers/peripherals/bm8563/manifest.json", + "$(MODDABLE)/modules/drivers/peripherals/es7210/manifest.json" ], "config": { "screen": "ili9341", @@ -114,13 +116,16 @@ } }, "audioIn": { - "sampleRate": 11025, + "sampleRate": 16000, "bitsPerSample": 16, + "numChannels": 2, "i2s": { + "num": 1, "bck_pin": 34, "lr_pin": 33, "datain": 14, - "pdm": 1 + "pdm": 0, + "slot": "I2S_STD_SLOT_RIGHT" } }, "camera": { diff --git a/build/devices/esp32/targets/m5stack_cores3/setup-target.js b/build/devices/esp32/targets/m5stack_cores3/setup-target.js index 4c4b67b89..9ec9decf2 100644 --- a/build/devices/esp32/targets/m5stack_cores3/setup-target.js +++ b/build/devices/esp32/targets/m5stack_cores3/setup-target.js @@ -23,6 +23,7 @@ import config from "mc/config"; import Timer from "timer"; import AXP2101 from "embedded:peripheral/Power/axp2101"; +import ES7210 from "embedded:peripheral/Audio/es7210"; import AudioOut from "embedded:io/audio/out"; const state = { @@ -67,6 +68,10 @@ export default function (done) { // power globalThis.power = new Power({sensor: { ...device.I2C.internal, io: device.io.SMBus }}); globalThis.amp = new AW88298({sensor: { ...device.I2C.internal, io: device.io.SMBus }}); + + // microphone ADC + globalThis.mic = new ES7210({sensor: { ...device.I2C.internal, io: device.io.SMBus }}); + globalThis.mic.initialize(); // start-up sound if (config.startupSound) { diff --git a/modules/drivers/peripherals/es7210/es7210.js b/modules/drivers/peripherals/es7210/es7210.js new file mode 100644 index 000000000..6479a940d --- /dev/null +++ b/modules/drivers/peripherals/es7210/es7210.js @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2024 Moddable Tech, Inc. + * + * This file is part of the Moddable SDK Runtime. + * + * The Moddable SDK Runtime is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Moddable SDK Runtime is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the Moddable SDK Runtime. If not, see . + * + */ + +/** + * ES7210 ADC driver for M5Stack CoreS3 microphone + * Based on M5Unified implementation + */ +class ES7210 { + #io; + + constructor(options) { + this.#io = new options.sensor.io({ + hz: 400_000, + address: 0x40, + ...options.sensor + }); + } + + readByte(address) { + return this.#io.readUint8(address); + } + + writeByte(address, value) { + return this.#io.writeUint8(address, value); + } + + /** + * Initialize ES7210 for M5Stack CoreS3 + * Configuration based on M5Unified _microphone_enabled_cb_cores3 + */ + initialize() { + // Reset + this.writeByte(0x00, 0xFF); // RESET_CTL + + // ES7210 register initialization sequence from M5Unified + const initSequence = [ + { reg: 0x00, value: 0x41 }, // RESET_CTL + { reg: 0x01, value: 0x1f }, // CLK_ON_OFF + { reg: 0x06, value: 0x00 }, // DIGITAL_PDN + { reg: 0x07, value: 0x20 }, // ADC_OSR + { reg: 0x08, value: 0x10 }, // MODE_CFG + { reg: 0x09, value: 0x30 }, // TCT0_CHPINI + { reg: 0x0A, value: 0x30 }, // TCT1_CHPINI + { reg: 0x20, value: 0x0a }, // ADC34_HPF2 + { reg: 0x21, value: 0x2a }, // ADC34_HPF1 + { reg: 0x22, value: 0x0a }, // ADC12_HPF2 + { reg: 0x23, value: 0x2a }, // ADC12_HPF1 + { reg: 0x02, value: 0xC1 }, + { reg: 0x04, value: 0x01 }, + { reg: 0x05, value: 0x00 }, + { reg: 0x11, value: 0x60 }, + { reg: 0x40, value: 0x42 }, // ANALOG_SYS + { reg: 0x41, value: 0x70 }, // MICBIAS12 + { reg: 0x42, value: 0x70 }, // MICBIAS34 + { reg: 0x43, value: 0x1B }, // MIC1_GAIN + { reg: 0x44, value: 0x1B }, // MIC2_GAIN + { reg: 0x45, value: 0x00 }, // MIC3_GAIN + { reg: 0x46, value: 0x00 }, // MIC4_GAIN + { reg: 0x47, value: 0x00 }, // MIC1_LP + { reg: 0x48, value: 0x00 }, // MIC2_LP + { reg: 0x49, value: 0x00 }, // MIC3_LP + { reg: 0x4A, value: 0x00 }, // MIC4_LP + { reg: 0x4B, value: 0x00 }, // MIC12_PDN + { reg: 0x4C, value: 0xFF }, // MIC34_PDN + { reg: 0x01, value: 0x14 }, // CLK_ON_OFF + ]; + + for (const {reg, value} of initSequence) { + this.writeByte(reg, value); + } + } + + /** + * Power down ES7210 + */ + powerDown() { + this.writeByte(0x00, 0xFF); // RESET_CTL + } +} + +export default ES7210; diff --git a/modules/drivers/peripherals/es7210/manifest.json b/modules/drivers/peripherals/es7210/manifest.json new file mode 100644 index 000000000..e8302d20d --- /dev/null +++ b/modules/drivers/peripherals/es7210/manifest.json @@ -0,0 +1,8 @@ +{ + "modules": { + "embedded:peripheral/Audio/es7210": "./es7210" + }, + "preload": [ + "embedded:peripheral/Audio/es7210" + ] +} diff --git a/modules/io/audioin/esp32/audioin.c b/modules/io/audioin/esp32/audioin.c index 33cd67d44..b59b73410 100644 --- a/modules/io/audioin/esp32/audioin.c +++ b/modules/io/audioin/esp32/audioin.c @@ -518,7 +518,8 @@ void audioInLoop(void *pvParameter) #else i2s_std_config_t rx_std_cfg = { .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(input->sampleRate), - .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_MONO), + .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, + (input->numChannels == 2) ? I2S_SLOT_MODE_STEREO : I2S_SLOT_MODE_MONO), .gpio_cfg = { .mclk = I2S_GPIO_UNUSED, .bclk = MODDEF_AUDIOIN_I2S_BCK_PIN, @@ -532,7 +533,7 @@ void audioInLoop(void *pvParameter) } } }; - rx_std_cfg.slot_cfg.slot_mask = I2S_STD_SLOT_RIGHT; //@@ + rx_std_cfg.slot_cfg.slot_mask = MODDEF_AUDIOIN_I2S_SLOT; err = i2s_channel_init_std_mode(input->handle, &rx_std_cfg); if (err) { From ab8bb3a69ee9689a3eb148869285168577c673a0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 22:40:38 +0000 Subject: [PATCH 3/6] Fix I2S slot configuration for stereo microphone input Co-authored-by: meganetaaan <1918755+meganetaaan@users.noreply.github.com> --- build/devices/esp32/targets/m5stack_cores3/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/devices/esp32/targets/m5stack_cores3/manifest.json b/build/devices/esp32/targets/m5stack_cores3/manifest.json index a727aa681..4eafe117b 100644 --- a/build/devices/esp32/targets/m5stack_cores3/manifest.json +++ b/build/devices/esp32/targets/m5stack_cores3/manifest.json @@ -125,7 +125,7 @@ "lr_pin": 33, "datain": 14, "pdm": 0, - "slot": "I2S_STD_SLOT_RIGHT" + "slot": "I2S_STD_SLOT_BOTH" } }, "camera": { From fa47850e494070d1703e61e81d58a09ba123e1a3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 22:43:59 +0000 Subject: [PATCH 4/6] Use explicit slot mask for stereo I2S configuration Co-authored-by: meganetaaan <1918755+meganetaaan@users.noreply.github.com> --- build/devices/esp32/targets/m5stack_cores3/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/devices/esp32/targets/m5stack_cores3/manifest.json b/build/devices/esp32/targets/m5stack_cores3/manifest.json index 4eafe117b..c606c7b9f 100644 --- a/build/devices/esp32/targets/m5stack_cores3/manifest.json +++ b/build/devices/esp32/targets/m5stack_cores3/manifest.json @@ -125,7 +125,7 @@ "lr_pin": 33, "datain": 14, "pdm": 0, - "slot": "I2S_STD_SLOT_BOTH" + "slot": "(I2S_STD_SLOT_LEFT | I2S_STD_SLOT_RIGHT)" } }, "camera": { From d4ab9afbde4b39ee393ccc8a9300dfd09da45c75 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 22:45:31 +0000 Subject: [PATCH 5/6] Improve code formatting in audioin.c Co-authored-by: meganetaaan <1918755+meganetaaan@users.noreply.github.com> --- modules/io/audioin/esp32/audioin.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/io/audioin/esp32/audioin.c b/modules/io/audioin/esp32/audioin.c index b59b73410..9bc82517d 100644 --- a/modules/io/audioin/esp32/audioin.c +++ b/modules/io/audioin/esp32/audioin.c @@ -518,8 +518,7 @@ void audioInLoop(void *pvParameter) #else i2s_std_config_t rx_std_cfg = { .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(input->sampleRate), - .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, - (input->numChannels == 2) ? I2S_SLOT_MODE_STEREO : I2S_SLOT_MODE_MONO), + .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, (input->numChannels == 2) ? I2S_SLOT_MODE_STEREO : I2S_SLOT_MODE_MONO), .gpio_cfg = { .mclk = I2S_GPIO_UNUSED, .bclk = MODDEF_AUDIOIN_I2S_BCK_PIN, From 1a2605f640f832917b7409395092e6fe08f2822b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 22:47:41 +0000 Subject: [PATCH 6/6] Add error handling for ES7210 initialization Co-authored-by: meganetaaan <1918755+meganetaaan@users.noreply.github.com> --- .../devices/esp32/targets/m5stack_cores3/setup-target.js | 9 +++++++-- modules/drivers/peripherals/es7210/es7210.js | 6 +++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/build/devices/esp32/targets/m5stack_cores3/setup-target.js b/build/devices/esp32/targets/m5stack_cores3/setup-target.js index 9ec9decf2..d389d8c3e 100644 --- a/build/devices/esp32/targets/m5stack_cores3/setup-target.js +++ b/build/devices/esp32/targets/m5stack_cores3/setup-target.js @@ -70,8 +70,13 @@ export default function (done) { globalThis.amp = new AW88298({sensor: { ...device.I2C.internal, io: device.io.SMBus }}); // microphone ADC - globalThis.mic = new ES7210({sensor: { ...device.I2C.internal, io: device.io.SMBus }}); - globalThis.mic.initialize(); + try { + globalThis.mic = new ES7210({sensor: { ...device.I2C.internal, io: device.io.SMBus }}); + globalThis.mic.initialize(); + } catch (e) { + trace("ES7210 microphone initialization failed: " + e + "\n"); + globalThis.mic = undefined; + } // start-up sound if (config.startupSound) { diff --git a/modules/drivers/peripherals/es7210/es7210.js b/modules/drivers/peripherals/es7210/es7210.js index 6479a940d..dbde6a2eb 100644 --- a/modules/drivers/peripherals/es7210/es7210.js +++ b/modules/drivers/peripherals/es7210/es7210.js @@ -47,7 +47,11 @@ class ES7210 { */ initialize() { // Reset - this.writeByte(0x00, 0xFF); // RESET_CTL + try { + this.writeByte(0x00, 0xFF); // RESET_CTL + } catch (e) { + throw new Error("ES7210 not responding on I2C"); + } // ES7210 register initialization sequence from M5Unified const initSequence = [