diff --git a/build/devices/esp32/targets/m5nanoc6/setup-target.js b/build/devices/esp32/targets/m5nanoc6/setup-target.js
index f5a3622e2..937dbd0bb 100644
--- a/build/devices/esp32/targets/m5nanoc6/setup-target.js
+++ b/build/devices/esp32/targets/m5nanoc6/setup-target.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 Moddable Tech, Inc.
+ * Copyright (c) 2026 Moddable Tech, Inc., Satoshi Tanaka
*
* This file is part of the Moddable SDK Runtime.
*
@@ -20,46 +20,18 @@
import config from "mc/config";
import NeoPixel from "neopixel";
-import Timer from "timer";
import Button from "button";
import LED from "led";
import Digital from "pins/digital";
class NeoPixelLED extends NeoPixel {
- #value = 0;
constructor(options) {
- // Enable RGB LED Power
- const power = new Digital({
- pin: config.led.rgb.power_pin,
- mode: Digital.Output,
- });
- power.write(1);
-
- super({
+ return new NeoPixel({
...options,
pin: config.led.rgb.data_pin,
length: 1,
order: "GRB",
});
- super.brightness = config.led.rgb.brightness;
- }
- read() {
- return this.#value;
- }
- write(value) {
- this.#value = value;
- if (value) {
- super.setPixel(0, super.makeRGB(255, 255, 255));
- } else {
- super.setPixel(0, super.makeRGB(0, 0, 0));
- }
- super.update();
- }
- on() {
- this.write(1);
- }
- off() {
- this.write(0);
}
}
@@ -72,7 +44,7 @@ class BlueLED {
}
}
-class Flash {
+class buttonA {
constructor(options) {
return new Button({
...options,
@@ -90,13 +62,19 @@ globalThis.Host = Object.freeze(
Blue: BlueLED,
},
Button: {
- Default: Flash,
- Flash,
+ Default: buttonA,
+ a: buttonA,
},
},
true
);
export default function (done) {
+ // Enable RGB LED Power
+ const power = new Digital({
+ pin: config.led.rgb.power_pin,
+ mode: Digital.Output,
+ });
+ power.write(1);
done?.();
}
diff --git a/build/devices/esp32/targets/m5nanoh2/host/provider.js b/build/devices/esp32/targets/m5nanoh2/host/provider.js
new file mode 100644
index 000000000..45701f4d9
--- /dev/null
+++ b/build/devices/esp32/targets/m5nanoh2/host/provider.js
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2026 Satoshi Tanaka
+ *
+ * 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 .
+ *
+ */
+
+import I2C from "embedded:io/i2c";
+import SMBus from "embedded:io/smbus";
+import Digital from "embedded:io/digital";
+
+const device = {
+ I2C: {
+ default: {
+ io: I2C,
+ data: 2,
+ clock: 1
+ }
+ },
+ io: {I2C, SMBus, Digital}
+};
+
+export default device;
diff --git a/build/devices/esp32/targets/m5nanoh2/manifest.json b/build/devices/esp32/targets/m5nanoh2/manifest.json
new file mode 100644
index 000000000..9951324b2
--- /dev/null
+++ b/build/devices/esp32/targets/m5nanoh2/manifest.json
@@ -0,0 +1,48 @@
+{
+ "build": {
+ "ESP32_SUBCLASS": "esp32h2",
+ "USE_USB": "2",
+ "SDKCONFIGPATH": "./sdkconfig",
+ "PARTITIONS_FILE_FOR_TARGET": "./sdkconfig/partitions.csv",
+ "PROGRAMMING_MODE_MESSAGE": "INSTRUCTIONS: Hold the BOOT button and press then release the RST button.",
+ "BEFORE_DEBUGGING_MESSAGE": "Press and release the RST button."
+ },
+ "include": [
+ "$(MODULES)/drivers/button/manifest.json",
+ "$(MODULES)/drivers/led/manifest.json",
+ "$(MODULES)/drivers/neopixel/manifest.json"
+ ],
+ "modules": {
+ "setup/target": "./setup-target"
+ },
+ "preload": [
+ "setup/target",
+ "neopixel"
+ ],
+ "config": {
+ "screen": "",
+ "led": {
+ "rgb": {
+ "power_pin": 10,
+ "data_pin": 11,
+ "rainbow": false,
+ "brightness": 32
+ },
+ "blue": {
+ "pin": 4
+ }
+ }
+ },
+ "creation": {
+ "static": 0,
+ "chunk": {
+ "initial": 78848,
+ "incremental": 0
+ },
+ "heap": {
+ "initial": 4928,
+ "incremental": 0
+ },
+ "stack": 512
+ }
+}
diff --git a/build/devices/esp32/targets/m5nanoh2/sdkconfig/partitions.csv b/build/devices/esp32/targets/m5nanoh2/sdkconfig/partitions.csv
new file mode 100644
index 000000000..251bf913b
--- /dev/null
+++ b/build/devices/esp32/targets/m5nanoh2/sdkconfig/partitions.csv
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2016-2023 Moddable Tech, Inc.
+#
+# This file is part of the Moddable SDK Tools.
+#
+# The Moddable SDK Tools is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 Tools 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with the Moddable SDK Tools. If not, see .
+#
+
+# Name, Type, SubType, Offset, Size, Flags
+# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild,,,,
+nvs, data, nvs, 0x9000, 0x006000,
+phy_init, data, phy, 0xf000, 0x001000,
+factory, app, factory, 0x10000, 0x3E0000,
diff --git a/build/devices/esp32/targets/m5nanoh2/sdkconfig/sdkconfig.defaults b/build/devices/esp32/targets/m5nanoh2/sdkconfig/sdkconfig.defaults
new file mode 100644
index 000000000..70d3b27ae
--- /dev/null
+++ b/build/devices/esp32/targets/m5nanoh2/sdkconfig/sdkconfig.defaults
@@ -0,0 +1,4 @@
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESPTOOLPY_FLASHSIZE_2MB=n
+
+
diff --git a/build/devices/esp32/targets/m5nanoh2/setup-target.js b/build/devices/esp32/targets/m5nanoh2/setup-target.js
new file mode 100644
index 000000000..7ab2cbe0d
--- /dev/null
+++ b/build/devices/esp32/targets/m5nanoh2/setup-target.js
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2026 Satoshi Tanaka
+ *
+ * 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 .
+ *
+ */
+
+import config from "mc/config";
+import NeoPixel from "neopixel";
+import Button from "button";
+import LED from "led";
+import Digital from "pins/digital";
+
+class NeoPixelLED extends NeoPixel {
+ constructor(options) {
+ return new NeoPixel({
+ ...options,
+ pin: config.led.rgb.data_pin,
+ length: 1,
+ order: "GRB",
+ });
+ }
+}
+
+class BlueLED {
+ constructor(options) {
+ return new LED({
+ ...options,
+ pin: config.led.blue.pin,
+ });
+ }
+}
+
+class buttonA {
+ constructor(options) {
+ return new Button({
+ ...options,
+ pin: 9,
+ invert: true,
+ });
+ }
+}
+
+globalThis.Host = Object.freeze(
+ {
+ LED: {
+ Default: NeoPixelLED,
+ RGB: NeoPixelLED,
+ Blue: BlueLED,
+ },
+ Button: {
+ Default: buttonA,
+ a: buttonA,
+ },
+ },
+ true
+);
+
+export default function (done) {
+ // Enable RGB LED Power
+ const power = new Digital({
+ pin: config.led.rgb.power_pin,
+ mode: Digital.Output,
+ });
+ power.write(1);
+ done?.();
+}
diff --git a/documentation/assets/devices/m5nanoh2.png b/documentation/assets/devices/m5nanoh2.png
new file mode 100644
index 000000000..195e29587
Binary files /dev/null and b/documentation/assets/devices/m5nanoh2.png differ
diff --git a/documentation/devices/esp32.md b/documentation/devices/esp32.md
index 813dc7227..5e0e41a54 100644
--- a/documentation/devices/esp32.md
+++ b/documentation/devices/esp32.md
@@ -246,6 +246,7 @@ The Moddable SDK supports these ESP32-H2 development kits:
| Name | Platform identifier | Key features | Links |
| :---: | :--- | :--- | :--- |
| 
ESP32-H2-DevKitM-1 | `esp32/esp32h2` | NeoPixel, Button |
[Product page](https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32h2/esp32-h2-devkitm-1/user_guide.html) |
+| 
M5NanoH2 | `esp32/m5nanoh2` | LED, NeoPixel, Button | [Product page](https://docs.m5stack.com/en/core/NanoH2) |
### Specifying ESP32 Subclass in Manifest
diff --git a/modules/io/manifests/esp32/manifest.json b/modules/io/manifests/esp32/manifest.json
index 2371e2732..32db349a8 100644
--- a/modules/io/manifests/esp32/manifest.json
+++ b/modules/io/manifests/esp32/manifest.json
@@ -121,6 +121,11 @@
"embedded:provider/builtin": "$(SUBPLATFORMDIRECTORY)/host/provider"
}
},
+ "esp32/m5nanoh2": {
+ "modules": {
+ "embedded:provider/builtin": "$(SUBPLATFORMDIRECTORY)/host/provider"
+ }
+ },
"esp32/*": {
"include": [
"$(MODDABLE)/examples/manifest_net.json"