Skip to content

Add the esp32s3-n8r2 firmware and the Adafruit MatrixPortal S3 - #160

Merged
ewowi merged 3 commits into
MoonModules:mainfrom
AnjinMeili:esp32s3-n8r2-matrixportal
Oct 28, 2026
Merged

ewowi merged 3 commits into
MoonModules:mainfrom
AnjinMeili:esp32s3-n8r2-matrixportal

Conversation

@AnjinMeili

Copy link
Copy Markdown
Contributor

What it changes, and why

Adds an esp32s3-n8r2 firmware and an Adafruit MatrixPortal S3 device model.

The MatrixPortal S3 is an ESP32-S3 with 8 MB flash and 2 MB quad PSRAM (N8R2; Adafruit's CircuitPython and Arduino board definitions agree). The N8R8/N16R8 images set SPIRAM_MODE_OCT, which fails PSRAM init on a quad part, and hold GPIO 35 to 37, which the MatrixPortal routes to HUB75 lines. So it ran the esp32s3-zero image, which boots but uses 4 MB of its 8.

  • Firmware: sdkconfig.defaults.esp32s3-n8r2 is the S3-Zero fragment with 8 MB flash and the 8 MB MoonBase table (3 MB app slot, 4 MB LittleFS). It is named after the memory part, like n8r8 and n16r8, so it serves any N8R2 board; board pins stay runtime config.
  • Partition table: esp32dev_8mb_moonbase.csv is renamed 8mb_moonbase.csv, matching 4mb_moonbase.csv, since the S3 now shares it with the esp32-pico.
  • Device model: the Hub75 driver on the existing MatrixPortal S3 pin map, a 64x32 1/16-scan grid, I2C on 16/17, BOOT on/off and UP/DOWN stepping brightness. Accelerometer planned.
  • MoonBase and the installer code need no change: neither treats an S3 variant specially.

Not included: a board image, which needs a copy with Adafruit's permission.

It touches eleven files, one past the ten in the contribution guide, with firmwares.json (generated) left out of the count. The eleventh is a one-line fix in moonbase.md, whose list of MoonBase variants had gone stale and which now links build-system's list instead.

What an agent wrote

Claude Code wrote all of it: the fragment, the registry entry, the device model, the rename and the docs. I reviewed every line.

What I tested, and on which hardware

  • check_firmwares and check_devices pass.
  • The desktop unit tests pass, unit_PartitionTables among them, which checks the renamed table.
  • build_esp32.py --firmware esp32s3-n8r2 builds: the app is 2198 KB of its 3072 KB slot (72%, 874 KB free), where the S3-Zero image fills 83% of its 2496 KB.
  • Flashed to an Adafruit MatrixPortal S3 over USB: the System card shows 8 MB flash (QIO) and 2.0 MB quad PSRAM at 80 MHz, and the board settings applied.
  • A 128x64 1/32-scan panel lights at 704 Hz refresh, and DDP from another machine shows through NetworkReceive.
  • Known: the panel pulses at minimum brightness, which the maintainer identified as a HUB75 driver bug, outside this change.

🤖 Generated with Claude Code

The Adafruit MatrixPortal S3 gets its own firmware and a catalog entry. Its ESP32-S3 has 8 MB flash and 2 MB quad PSRAM: the octal-PSRAM S3 images fail PSRAM init on it, and the S3-Zero image it ran used half its flash. The installer sets up its HUB75 panel, I2C bus and three buttons after the flash.

**Scripts/MoonDeck**
- `esp32s3-n8r2` in the firmware registry: MoonBase, WiFi only, shipped; `firmwares.json` regenerated.
- `sdkconfig.defaults.esp32s3-n8r2`: the S3-Zero fragment with 8 MB flash and the 8 MB MoonBase table (3 MB app slot, 4 MB LittleFS).
- `esp32dev_8mb_moonbase.csv` is `8mb_moonbase.csv`, matching `4mb_moonbase.csv`, since its layout holds nothing classic-specific; the esp32-pico fragment follows.
- deviceModels: Adafruit MatrixPortal S3, with the Hub75 driver on its `MatrixPortal S3` pin map, a 64x32 1/16-scan grid, I2C on 16/17, BOOT toggling `Control.switch1` and UP/DOWN stepping `Control.fader1` (brightness) by 16. Accelerometer planned. No image yet: it needs a copy with Adafruit's permission.

**Tests**
- `unit_PartitionTables` declares `8mb_moonbase.csv`.
- check_firmwares and check_devices pass, and so do the desktop unit tests.
- Flashed to a MatrixPortal S3: 8 MB flash, 2.0 MB quad PSRAM, a 128x64 panel lights at 704 Hz and shows DDP through NetworkReceive.
- collect_kpi skipped: configuration and catalog only, no runtime code changed.

**Docs/CI**
- hub75-panels: the MatrixPortal runs `esp32s3-n8r2`.
- build-system: `esp32s3-n8r2` in the MoonBase list; moonbase.md links that list instead of keeping a stale copy.
- firmware-variants: a row for the quad-PSRAM S3 images, `esp32s3-zero` and `esp32s3-n8r2`.
- MIGRATING: a MatrixPortal on the S3-Zero image keeps working; moving to the new one is one USB install with an erase.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 28, 2026 09:14
@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

N8R2 and N8R8 installers share a partition-table artifact despite different app offsets, so release artifact flattening can leave an incompatible layout that boots the wrong image or fails to boot.

1 open issue
What changed in this PR

Adds an 8 MB quad-PSRAM firmware variant and an Adafruit MatrixPortal S3 device preset, integrating the board into the existing build registry and installer.

Changes:

  • Registers esp32s3-n8r2 with MoonBase and a shared 8 MB partition layout.
  • Adds MatrixPortal S3 defaults for HUB75, I2C, and button controls.
  • Updates partition-test references and documents firmware selection and USB migration.
File Description
test/​unit/​core/​unit_PartitionTables.cpp Updates the renamed partition-table reference.
mooninstaller/​firmwares.json Adds the generated N8R2 firmware entry.
mooninstaller/​deviceModels.json Adds the MatrixPortal S3 device preset.
moondeck/​build/​build_esp32.py Registers the N8R2 build variant.
esp32/​sdkconfig.defaults.esp32s3-n8r2 Configures 8 MB flash, quad PSRAM, and MoonBase.
esp32/​sdkconfig.defaults.esp32-pico References the shared partition-table filename.
esp32/​partitions/​8mb_moonbase.csv Renames the table and generalizes its header comment.
docs/​reference/​MIGRATING.md Documents USB migration to the N8R2 layout.
docs/​reference/​hardware/​hub75-panels.md Updates MatrixPortal firmware guidance.
docs/​reference/​hardware/​firmware-variants.md Lists the quad-PSRAM S3 variants.
docs/​reference/​build-system.md Adds N8R2 to the MoonBase variant list.
docs/​explanation/​architecture/​moonbase.md Replaces a stale variant list with a reference link.

Review effort: Balanced

Comment thread moondeck/build/build_esp32.py Resolved
ewowi and others added 2 commits October 28, 2026 14:11
The S3-Zero and N8R2 images now build from one quad-PSRAM fragment, and each MoonBase table fragment sets the flash size it spans. Every firmware's settings are unchanged.

**Scripts/MoonDeck**
- `sdkconfig.defaults.esp32s3-quad`, from `esp32s3-zero`: QIO flash, 2 MB quad PSRAM at 80 MHz and the exec heap, for both quad-PSRAM S3 images. The `esp32s3-n8r2` fragment, which repeated it, is gone.
- `sdkconfig.defaults.moonbase-8mb`: 8 MB flash and `8mb_moonbase.csv`, for `esp32-pico` and `esp32s3-n8r2`, as `moonbase-4mb` and `moonbase-16mb` hold their tables.
- `moonbase-4mb` sets the 4 MB flash size, which the C3 and S3-Zero fragments each set before.
- The base fragment no longer sets the `ESPTOOLPY_FLASHSIZE` string, which Kconfig derives from the size choice and ignores in a defaults file.

**Tests**
- Merged fragment settings diffed per firmware before and after: identical, except the esp32-pico's explicit `ESPTOOLPY_FLASHSIZE` string, which Kconfig derives from the size choice.
- ESP32 builds: esp32s3-n8r2, esp32s3-zero, esp32-pico, esp32c3.
- check_firmwares, check_devices, check_prose, check_docgen (0 errors, warnings unchanged), check_code, desktop tests, test_host.
- collect_kpi skipped: build configuration only, no setting changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The architecture page describes which variants use MoonBase without dating the sentence.

**Docs/CI**
- moonbase.md: "lists the variants that use it today" loses "today", which check_prose flags as a Temporal error.

**Tests**
- check_prose over the CI range `e73179ad...HEAD`: clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ewowi
ewowi merged commit 47483ca into MoonModules:main Oct 28, 2026
10 checks passed
@ewowi

ewowi commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

Thanks James, merged! A clean first contribution: one topic, a clear description, and tested on the board itself. The 8mb_moonbase.csv rename and the stale MoonBase list were welcome fixes along the way.

Before merging I added a maintainer commit on your branch for a project convention. The S3-Zero and N8R2 images now share one sdkconfig.defaults.esp32s3-quad fragment (QIO flash, quad PSRAM, exec heap). A new moonbase-8mb fragment holds the 8 MB flash size and partition table for both esp32-pico and esp32s3-n8r2, as moonbase-4mb and moonbase-16mb do for theirs. Every firmware's settings are unchanged, and the four affected images build. A second commit drops "today" from the MoonBase line in moonbase.md, which the prose check flags as dating the sentence.

Looking forward to #161, and to the accelerometer when you get to it. The processes behind the review are on MoonWalk.

ewowi pushed a commit that referenced this pull request Oct 28, 2026
The release named the partition table by flash size, assuming every firmware of one size shares a layout. They do not: esp32-pico's MoonBase table puts the app at 0xF0000 and esp32s3-n8r8's dual-OTA table at 0x10000, and esp32-16mb's MoonBase table differs from the 16 MB OTA table of esp32s3-n16r8, the P4s and esp32s31. Each matrix job overwrote the shared file, so v7.0.0 publishes the MoonBase 8 MB table and the OTA 16 MB table, and the N8R8 and esp32-16mb web installers write the wrong layout. The table now carries the firmware prefix, like the app and bootloader; only the ota-data, identical for every firmware, stays shared.

**Scripts/MoonDeck**
- generate_manifest: the partition-table part is `firmware-<F>-v<ver>-partition-table.bin`; the flash-size lookup goes.
- preview_installer stages the same name.

**Tests**
- `test_every_firmware_names_its_own_partition_table`: every shipped ESP32 manifest names a table of its own. Control: the previous generator gives esp32-pico and esp32s3-n8r8 both `partition-table-8mb.bin`.
- The installer merge test rejects the per-firmware table as an app image.
- test_host passes: Python 616, JS 350.

**Docs/CI**
- release.yml stages the per-firmware table and no longer uploads `partition-table-*.bin`; the Pages restage keeps that pattern for the releases that published it.
- install.js: the esptool fallback for esp32s31 names the per-firmware table.

**Reviews**
- Copilot on #160 (high): N8R2 and N8R8 share `partition-table-8mb.bin` despite different app offsets. Done: the collision was already on main (pico against N8R8, esp32-16mb against the OTA variants) and is fixed here for all of them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ewowi

ewowi commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

Hi James, both PRs are in the latest build on the web installer now, and before we cut a stable release we'd love a test on your MatrixPortal S3:

  1. Open https://moonmodules.org/MoonLight/install/, pick the release latest (7.1.0-dev.8 or newer) and the device Adafruit MatrixPortal S3.
  2. Tick Erase chip first and install. Your settings will be wiped, so take a backup first if you want to keep them.
  3. After it comes back: does the System card show 8 MB flash and 2 MB PSRAM, did the board settings apply (Hub75 on the MatrixPortal pin map, I2C on 16/17, the three buttons), and does the panel light?

Your serial flash proved the firmware; this proves the release pipeline and the installer's device setup, which is the path other MatrixPortal owners will take. A short "works" or what you saw is all we need.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants