Skip to content

Snake!#10936

Open
jp-bennett wants to merge 28 commits into
developfrom
snake
Open

Snake!#10936
jp-bennett wants to merge 28 commits into
developfrom
snake

Conversation

@jp-bennett

@jp-bennett jp-bennett commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Disabled by default. Initially intended for a conference display.

Made with help from Claude.

Summary by CodeRabbit

  • New Features
    • Added optional build-time Snake game mode with a dedicated “games” UI flow, joystick indicators, deterministic gameplay, and persistent high-scores.
    • Added an alphanumeric “initials” picker overlay (A–Z/0–9 entry) with a result callback.
    • Added support for HUB75 RGB LED matrix displays, including new configuration options and variants.
  • Bug Fixes
    • Improved input handling so the Snake UI cleanly intercepts controls without conflicting with normal navigation.
  • Tests
    • Added unit tests covering Snake reset, movement/direction rules, scoring, collisions, and death behavior.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

⚡ Try this PR in the Web Flasher

Flash this PR in the Web Flasher

firmware commit boards expires

Warning

This is an automated, unreviewed CI test build. Back up your device configuration
before flashing, and only flash devices you are able to recover.

Supported boards built by this PR (27)
Device Board Platform
Crowpanel Adv 3.5 TFT elecrow-adv-35-tft esp32-s3
Heltec HT62 heltec-ht62-esp32c3-sx1262 esp32-c3
Heltec Mesh Node 096 heltec-mesh-node-t096 nrf52840
Heltec Mesh Node T1 heltec-mesh-node-t1 nrf52840
Heltec Mesh Node T114 heltec-mesh-node-t114 nrf52840
Heltec V3 heltec-v3 esp32-s3
Heltec V4 heltec-v4 esp32-s3
Meshnology W10 meshnology_w10 esp32-s3
Raspberry Pi Pico pico rp2040
Raspberry Pi Pico W picow rp2040
RAK WisMesh Tag rak_wismeshtag nrf52840
RAK WisBlock 11200 rak11200 esp32
RAK WisBlock 11310 rak11310 rp2040
RAK3312 rak3312 esp32-s3
RAK WisBlock 4631 rak4631 nrf52840
Seeed SenseCAP Mesh-Tracker-X1 seeed_mesh_tracker_X1 nrf52840
Seeed Wio Tracker L1 seeed_wio_tracker_L1 nrf52840
Seeed Xiao NRF52840 Kit seeed_xiao_nrf52840_kit nrf52840
Seeed Xiao ESP32-S3 seeed-xiao-s3 esp32-s3
Station G2 station-g2 esp32-s3
Station G3 station-g3 esp32-s3
LILYGO T-Deck t-deck-tft esp32-s3
LILYGO T-Echo t-echo nrf52840
LILYGO T-Echo Plus t-echo-plus nrf52840
LILYGO T-Impulse Plus t-impulse-plus nrf52840
LilyGo T3-C6 tlora-c6 esp32-c6
Seeed SenseCAP T1000-E tracker-t1000-e nrf52840

Build artifacts expire on 2026-08-13. Updated for 9325b0e.

@github-actions github-actions Bot added needs-review Needs human review enhancement New feature or request labels Jul 8, 2026
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds an opt-in Snake game to BaseUI displays and introduces HUB75 RGB-matrix display support across ESP32 and Portduino targets, including rendering backends, configuration, Screen/UI integration, high-score persistence, picker input, and tests.

Changes

Snake Game Feature

Layer / File(s) Summary
Game contract and simulation tests
src/configuration.h, src/modules/SnakeGame.h, src/modules/SnakeGame.cpp, test/test_snake/*
Adds the games feature flag, fixed-grid Snake API and implementation, deterministic movement and food placement, collision/scoring rules, and Unity coverage.
SnakeModule lifecycle and persistence
src/modules/SnakeModule.h, src/modules/SnakeModule.cpp, src/modules/Modules.cpp
Adds gameplay states, input handling, tick scheduling, OLED rendering, high-score ranking and CRC-backed storage, optional announcements, and conditional module creation.
Alphanumeric initials picker
src/graphics/Screen.h, src/graphics/Screen.cpp, src/graphics/draw/NotificationRenderer.*
Adds the picker notification type, Screen API, character editing behavior, callback completion, and picker rendering.
Games frame and navigation integration
src/graphics/Screen.cpp, src/graphics/draw/UIRenderer.cpp, src/graphics/images.h
Adds a dedicated games frame, joystick indicators, game launch handling, input interception, and navigation-bar suppression during gameplay.

HUB75 Display Support

Layer / File(s) Summary
HUB75 backend contracts and detection
src/graphics/HUB75Display.h, variants/native/portduino/HUB75Native.h, src/platform/portduino/PortduinoGlue.h, src/platform/portduino/architecture.h, src/graphics/TFTColorRegions.h
Defines HUB75 display interfaces, configuration fields, display selection metadata, conditional native detection, and color-region support.
ESP32 HUB75 backend and target
src/graphics/HUB75Display.cpp, variants/esp32s3/visualizer-hub75/*
Implements DMA-panel initialization, dirty framebuffer rendering, brightness and display commands, and adds an ESP32-S3 HUB75 target variant.
Portduino backend and configuration
src/platform/portduino/HUB75Native.cpp, src/platform/portduino/PortduinoGlue.cpp, variants/native/portduino/platformio.ini, src/graphics/Screen.cpp
Loads and emits HUB75 settings, initializes the native RGB-matrix backend, renders full frames, and selects HUB75 panels at runtime.
HUB75 configuration profiles
bin/config-dist.yaml, bin/config.d/display-hub75-64x64.yaml
Adds documented HUB75 configuration examples and a 64x64 panel profile.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Screen
  participant SnakeModule
  participant SnakeGame
  participant NotificationRenderer
  participant SafeFile

  User->>Screen: Select games frame
  Screen->>SnakeModule: launchGame()
  SnakeModule->>SnakeModule: loadHighScores()
  SnakeModule->>SnakeModule: startPlaying()
  loop each tick
    SnakeModule->>SnakeGame: step()
    SnakeGame-->>SnakeModule: alive or won state
    SnakeModule->>Screen: requestRedraw()
  end
  SnakeModule->>Screen: showAlphanumericPicker(callback)
  Screen->>NotificationRenderer: drawAlphanumericPicker
  NotificationRenderer-->>SnakeModule: initials callback
  SnakeModule->>SafeFile: saveHighScores()
Loading
sequenceDiagram
  participant YAMLConfig
  participant PortduinoGlue
  participant Screen
  participant HUB75Native
  participant RGBMatrix

  YAMLConfig->>PortduinoGlue: load HUB75 settings
  PortduinoGlue->>Screen: set display geometry and panel type
  Screen->>HUB75Native: construct and connect backend
  HUB75Native->>RGBMatrix: create matrix and render framebuffer
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is too sparse and does not follow the template, missing testing/attestation details and any regression notes. Replace the boilerplate with a real summary and include testing performed, affected devices, and any regression caveats.
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is too vague to describe the actual change; it only says "Snake!" and doesn't communicate what was added. Use a concise title that names the main change, such as adding Snake game support or HUB75 Snake integration.
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch snake

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.

@jp-bennett jp-bennett added the baseui Issues directly related to BaseUI label Jul 8, 2026

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (6)
src/modules/SnakeModule.h (1)

13-15: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Trim multi-paragraph doc comments per coding guidelines.

The SNAKE_ANNOUNCE_HIGH_SCORE doc (Lines 13-15) and the class-level doc (Lines 28-37) exceed the guideline limit with multi-paragraph explanations. As per coding guidelines, **/*.{c,cc,cpp,cxx,h,hpp,hh}: "Keep code comments minimal: one or two lines maximum... and do not restate the next line."

Also applies to: 28-37

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/SnakeModule.h` around lines 13 - 15, Trim the doc comments in
SnakeModule.h so they fit the coding guideline of one or two lines maximum and
avoid multi-paragraph explanations. Shorten both the SNAKE_ANNOUNCE_HIGH_SCORE
comment and the SnakeModule class-level doc, keeping only the essential summary
and removing repeated details or restatements of nearby code.

Source: Coding guidelines

src/modules/SnakeGame.h (2)

7-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Trim multi-line doc comments per coding guidelines.

The class-level doc (Lines 7-16) and the setDirection/step docs (Lines 42-47, 50-54) run 3-4+ content lines with multi-paragraph explanations. As per coding guidelines, **/*.{c,cc,cpp,cxx,h,hpp,hh}: "Keep code comments minimal: one or two lines maximum, only when the reason is not obvious, and do not restate the next line."

Also applies to: 42-47, 50-54

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/SnakeGame.h` around lines 7 - 16, Trim the long multi-line
comments in SnakeGame.h to meet the coding guideline by shortening the
class-level doc and the setDirection/step docs to at most one or two lines each,
keeping only essential context. Update the comments attached to SnakeGame,
setDirection, and step so they are minimal and do not restate obvious code
behavior or include multi-paragraph explanations.

Source: Coding guidelines


72-76: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider an assert() for the test-seam precondition.

placeFoodAt documents "Caller must pass an unoccupied cell" but doesn't verify it. As per coding guidelines, "Use assert() for invariants that should never fail," which would catch test misuse without adding runtime cost in production builds (NDEBUG).

🛡️ Proposed fix
-    void placeFoodAt(uint8_t x, uint8_t y) { foodCell = {x, y}; }
+    void placeFoodAt(uint8_t x, uint8_t y) {
+        assert(!occupied(x, y));
+        foodCell = {x, y};
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/SnakeGame.h` around lines 72 - 76, The test-seam helper
SnakeGame::placeFoodAt documents that the caller must pass an unoccupied cell,
but it does not enforce that invariant. Add an assert() inside placeFoodAt to
verify the requested x,y is not already occupied before assigning foodCell, so
misuse is caught in debug/test builds without production overhead. Use the
existing SnakeGame and placeFoodAt symbols to locate the change.

Source: Coding guidelines

src/modules/SnakeModule.cpp (1)

22-25: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Trim comments exceeding the guideline's line limit.

The pixel-layout block comment (Lines 22-25, 4 lines) and the exitToIdle explanation (Lines 100-103, 3 lines) exceed the stated limit. As per coding guidelines, "Keep code comments minimal: use at most one or two lines, only when the reason is not obvious; do not add multi-paragraph explanatory comments."

Also applies to: 100-103

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/SnakeModule.cpp` around lines 22 - 25, Trim the oversized
explanatory comments in SnakeModule so they fit the guideline of at most one or
two lines. Shorten the pixel-layout block near the top of the file and the
exitToIdle explanation to only the essential intent, removing multi-line detail
while keeping a brief note if needed for non-obvious behavior.

Source: Coding guidelines

src/graphics/draw/NotificationRenderer.cpp (1)

469-471: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Trim the drawAlphanumericPicker header comment to ≤2 lines.

This block is 3 lines; per repo guideline comments should be capped at 1-2 lines.

✏️ Suggested trim
-// Arcade-style initials entry. Mirrors drawHexPicker's cursor/confirm flow, but each position
-// holds a character from ALPHANUMERIC_CHARS (cycled with UP/DOWN) instead of a packed digit, and
-// the assembled string is returned through textInputCallback.
+// Arcade-style initials entry, mirroring drawHexPicker's cursor/confirm flow but cycling
+// each position through ALPHANUMERIC_CHARS instead of a packed digit.

As per coding guidelines, "Keep code comments minimal: use at most one or two lines, only when the reason is not obvious; do not add multi-paragraph explanatory comments or restate what the next line does."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/graphics/draw/NotificationRenderer.cpp` around lines 469 - 471, The
header comment for drawAlphanumericPicker is too long and should be trimmed to
at most two lines. Shorten the explanatory comment above drawAlphanumericPicker
so it stays minimal and still identifies the picker behavior, without restating
implementation details; use the drawAlphanumericPicker symbol to locate the
block.

Source: Coding guidelines

src/graphics/Screen.cpp (1)

456-465: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Trim the drawSnakeFrame comment to ≤2 lines.

This block is 3 lines; per repo guideline comments should be capped at 1-2 lines.

✏️ Suggested trim
 `#if` BASEUI_HAS_GAMES
-// The games frame is a dedicated, always-present frame (unlike generic module frames it is placed
-// at a fixed position right after home), so it draws through its own trampoline rather than the
-// moduleFrames lockstep used by drawModuleFrame.
+// Dedicated always-present frame, so it uses its own trampoline instead of drawModuleFrame's lockstep.
 static void drawSnakeFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)

As per coding guidelines, "Keep code comments minimal: use at most one or two lines, only when the reason is not obvious; do not add multi-paragraph explanatory comments or restate what the next line does."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/graphics/Screen.cpp` around lines 456 - 465, The comment above
drawSnakeFrame in Screen.cpp is too long and should be reduced to at most 2
lines. Shorten the existing explanation while preserving the essential rationale
for why this frame uses its own trampoline instead of moduleFrames, and keep the
static drawSnakeFrame identifier easy to locate.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/modules/SnakeModule.cpp`:
- Around line 430-447: The saveHighScores() write path is not fully
synchronized, because SafeFile only protects open/close while FSCom.mkdir and
sf.write() can still race with other SPI users. Update
SnakeModule::saveHighScores() to take spiLock around the filesystem operations
that touch the bus, including the directory creation and the actual write call,
and keep sf.close() outside that lock to avoid nested locking.
- Around line 136-141: Replace the raw millis()-based wake-kick timing in
SnakeModule with Throttle-based rate limiting. In the SnakeModule logic around
the display-awake kick, avoid direct lastAwakeKickMs arithmetic and instead use
Throttle::isWithinTimespanMs() or a small non-lambda helper that can be passed
to Throttle::execute(), since execute only accepts a plain function pointer.
Keep the existing EVENT_PRESS trigger behavior, but route the timing check
through the Throttle utility.

---

Nitpick comments:
In `@src/graphics/draw/NotificationRenderer.cpp`:
- Around line 469-471: The header comment for drawAlphanumericPicker is too long
and should be trimmed to at most two lines. Shorten the explanatory comment
above drawAlphanumericPicker so it stays minimal and still identifies the picker
behavior, without restating implementation details; use the
drawAlphanumericPicker symbol to locate the block.

In `@src/graphics/Screen.cpp`:
- Around line 456-465: The comment above drawSnakeFrame in Screen.cpp is too
long and should be reduced to at most 2 lines. Shorten the existing explanation
while preserving the essential rationale for why this frame uses its own
trampoline instead of moduleFrames, and keep the static drawSnakeFrame
identifier easy to locate.

In `@src/modules/SnakeGame.h`:
- Around line 7-16: Trim the long multi-line comments in SnakeGame.h to meet the
coding guideline by shortening the class-level doc and the setDirection/step
docs to at most one or two lines each, keeping only essential context. Update
the comments attached to SnakeGame, setDirection, and step so they are minimal
and do not restate obvious code behavior or include multi-paragraph
explanations.
- Around line 72-76: The test-seam helper SnakeGame::placeFoodAt documents that
the caller must pass an unoccupied cell, but it does not enforce that invariant.
Add an assert() inside placeFoodAt to verify the requested x,y is not already
occupied before assigning foodCell, so misuse is caught in debug/test builds
without production overhead. Use the existing SnakeGame and placeFoodAt symbols
to locate the change.

In `@src/modules/SnakeModule.cpp`:
- Around line 22-25: Trim the oversized explanatory comments in SnakeModule so
they fit the guideline of at most one or two lines. Shorten the pixel-layout
block near the top of the file and the exitToIdle explanation to only the
essential intent, removing multi-line detail while keeping a brief note if
needed for non-obvious behavior.

In `@src/modules/SnakeModule.h`:
- Around line 13-15: Trim the doc comments in SnakeModule.h so they fit the
coding guideline of one or two lines maximum and avoid multi-paragraph
explanations. Shorten both the SNAKE_ANNOUNCE_HIGH_SCORE comment and the
SnakeModule class-level doc, keeping only the essential summary and removing
repeated details or restatements of nearby code.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f5ae4f53-1fb2-4884-987c-c272be2e0701

📥 Commits

Reviewing files that changed from the base of the PR and between 8d20606 and 282264b.

📒 Files selected for processing (14)
  • src/configuration.h
  • src/graphics/Screen.cpp
  • src/graphics/Screen.h
  • src/graphics/draw/NotificationRenderer.cpp
  • src/graphics/draw/NotificationRenderer.h
  • src/graphics/draw/UIRenderer.cpp
  • src/graphics/images.h
  • src/modules/Modules.cpp
  • src/modules/SnakeGame.cpp
  • src/modules/SnakeGame.h
  • src/modules/SnakeModule.cpp
  • src/modules/SnakeModule.h
  • test/native-suite-count
  • test/test_snake/test_main.cpp

Comment thread src/modules/SnakeModule.cpp Outdated
Comment on lines +136 to +141
// Keep the display awake through long straight runs that generate no key presses.
const uint32_t now = millis();
if (now - lastAwakeKickMs > 1500) {
powerFSM.trigger(EVENT_PRESS);
lastAwakeKickMs = now;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm Throttle's API surface before applying the diff
ast-grep outline src --items all --type class,function --match 'Throttle'
rg -n -A5 'class Throttle' src

Repository: meshtastic/firmware

Length of output: 613


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant code around the reviewed lines and Throttle usage patterns.
sed -n '110,170p' src/modules/SnakeModule.cpp
printf '\n---\n'
sed -n '1,120p' src/mesh/Throttle.h
printf '\n---\n'
sed -n '1,220p' src/mesh/Throttle.cpp
printf '\n---\n'
rg -n "Throttle::execute\\(|Throttle::isWithinTimespanMs\\(" src | head -n 50

Repository: meshtastic/firmware

Length of output: 9591


Use Throttle here instead of raw millis() arithmetic. Throttle::execute() only accepts a plain function pointer, so this needs a small helper or Throttle::isWithinTimespanMs() rather than the lambda shown in the diff.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/SnakeModule.cpp` around lines 136 - 141, Replace the raw
millis()-based wake-kick timing in SnakeModule with Throttle-based rate
limiting. In the SnakeModule logic around the display-awake kick, avoid direct
lastAwakeKickMs arithmetic and instead use Throttle::isWithinTimespanMs() or a
small non-lambda helper that can be passed to Throttle::execute(), since execute
only accepts a plain function pointer. Keep the existing EVENT_PRESS trigger
behavior, but route the timing check through the Throttle utility.

Source: Coding guidelines

Comment thread src/modules/SnakeModule.cpp Outdated
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Firmware Size Report

42 targets | vs develop: 21 increased, 1 decreased, net +453,308 (+442.7 KB)

Target Flash vs develop RAM RAM vs develop
picow 1,275,544 📈 +30,664 (+29.9 KB) 152,524 n/a
pico2w 1,249,956 📈 +29,440 (+28.8 KB) 159,004 n/a
rak11310 834,296 📈 +28,872 (+28.2 KB) 86,336 n/a
pico 811,544 📈 +28,856 (+28.2 KB) 85,892 n/a
seeed_xiao_rp2040 809,760 📈 +28,856 (+28.2 KB) 85,884 n/a
Show 37 more target(s)
Target Flash vs develop RAM RAM vs develop
seeed_xiao_rp2350 795,768 📈 +27,832 (+27.2 KB) 92,384 n/a
pico2 797,592 📈 +27,816 (+27.2 KB) 92,392 n/a
t-deck-tft 3,833,984 📈 +23,312 (+22.8 KB) 108,024 n/a
elecrow-adv-35-tft 3,439,328 📈 +22,704 (+22.2 KB) 94,632 n/a
heltec-vision-master-e213-inkhud 2,249,824 📈 +22,464 (+21.9 KB) 92,408 n/a
rak3312 2,291,888 📈 +19,648 (+19.2 KB) 102,040 n/a
seeed-xiao-s3 2,295,648 📈 +19,504 (+19.0 KB) 102,056 n/a
station-g3 2,285,120 📈 +18,768 (+18.3 KB) 101,864 n/a
station-g2 2,285,104 📈 +18,752 (+18.3 KB) 101,864 n/a
heltec-v3 2,282,800 📈 +18,720 (+18.3 KB) 130,232 n/a
rak11200 1,879,248 📈 +18,640 (+18.2 KB) 87,068 n/a
heltec-ht62-esp32c3-sx1262 2,153,184 📈 +18,192 (+17.8 KB) 112,004 n/a
t-eth-elite 2,509,392 📈 +17,904 (+17.5 KB) 103,100 n/a
heltec-v4 2,294,992 📈 +17,696 (+17.3 KB) 101,112 n/a
tlora-c6 2,384,912 📈 +16,608 (+16.2 KB) 102,772 n/a
rak3172 182,932 📉 -3,364 (-3.3 KB) 25,008 n/a
wio-e5 240,052 📈 +1,424 (+1.4 KB) 26,640 n/a
heltec-mesh-node-t096 751,240 110,508 n/a
heltec-mesh-node-t1 749,112 102,252 n/a
heltec-mesh-node-t114 749,032 110,444 n/a
heltec-mesh-solar 746,104 110,612 n/a
heltec-mesh-solar-eink 737,968 109,932 n/a
heltec-mesh-solar-inkhud 717,800 101,372 n/a
heltec-mesh-solar-oled 746,200 110,612 n/a
heltec-mesh-solar-tft 752,488 110,708 n/a
heltec-mesh-tower-v2 737,176 101,468 n/a
meshnology_w10 2,465,488 136,228 n/a
rak4631 767,128 104,524 n/a
rak_wismeshtag 600,160 92,604 n/a
seeed_mesh_tracker_X1 507,248 87,316 n/a
seeed_wio_tracker_L1 740,664 110,356 n/a
seeed_xiao_nrf52840_kit 735,416 102,076 n/a
t-echo 754,208 93,252 n/a
t-echo-inkhud 713,256 83,956 n/a
t-echo-plus 751,920 93,252 n/a
t-impulse-plus 727,680 110,340 n/a
tracker-t1000-e 506,312 87,316 n/a

Size budgets

Env Metric Measured Budget Used
rak4631 RAM (.data+.bss) 104,524 113,000 92.5%
rak4631 flash 767,128 786,000 97.6%

Budgets live in bin/ram_budgets.json and are raised deliberately in the PR that needs the headroom - never automatically.


Updated for 2bd1ee5

@Ixitxachitl

Copy link
Copy Markdown
Contributor

spiLock->lock() breaks saving on nRF52, scope the manual lock only around FSCom.mkdir() and let SafeFile handle its own locking?

@jp-bennett

Copy link
Copy Markdown
Collaborator Author

spiLock->lock() breaks saving on nRF52, scope the manual lock only around FSCom.mkdir() and let SafeFile handle its own locking?

I didn't realize creating the safefile object took a lock internally. And for whatever reason, sf.write() does not lock internally.

jp-bennett and others added 7 commits July 8, 2026 13:05
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
- Implement TetrisGame class for game logic, including piece movement, rotation, and line clearing.
- Create TetrisModule class to manage game state, input handling, and rendering on OLED display.
- Introduce high score tracking with persistence and optional mesh broadcasting.
- Define UI states for title, playing, paused, game over, and high scores.
- Implement input handling for game controls and state transitions.
- Add rendering functions for the game board, high scores, and title screen.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (5)
src/platform/portduino/PortduinoGlue.cpp (1)

1073-1075: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Cast to unsigned char before tolower().

Passing a plain (possibly signed) char to tolower() is undefined behavior for values with the high bit set. Low-risk here since action names are expected to be ASCII, but the fix is trivial.

🛡️ Proposed fix
                     for (auto &c : action)
-                        c = tolower(c);
+                        c = tolower(static_cast<unsigned char>(c));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/platform/portduino/PortduinoGlue.cpp` around lines 1073 - 1075, Update
the action normalization loop in the button handling code to cast each character
to unsigned char before passing it to tolower(), while preserving the existing
lowercase conversion behavior.
src/platform/portduino/HUB75Native.cpp (2)

62-62: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

CreateMatrixFromOptions is the legacy alias.

Per rpi-rgb-led-matrix's led-matrix.h, CreateMatrixFromOptions() is documented as the "Legacy version of RGBMatrix::CreateFromOptions()". Functionally identical today, but consider calling RGBMatrix::CreateFromOptions(options, runtime) directly to avoid relying on a legacy shim.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/platform/portduino/HUB75Native.cpp` at line 62, Update the matrix
initialization in HUB75Native to call
rgb_matrix::RGBMatrix::CreateFromOptions(options, runtime) instead of the legacy
rgb_matrix::CreateMatrixFromOptions alias, preserving the existing options and
runtime arguments.

11-18: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Consider an assert() on displayWidth/displayHeight.

The comment documents an ordering invariant (portduino_config fully populated before this constructor runs) but nothing enforces it; a broken initialization order would silently produce a 0x0 geometry. As per coding guidelines, "Use assert() for invariants that should never fail."

🛡️ Proposed fix
     setGeometry(GEOMETRY_RAWMODE, portduino_config.displayWidth, portduino_config.displayHeight);
+    assert(portduino_config.displayWidth > 0 && portduino_config.displayHeight > 0);
     LOG_DEBUG("HUB75Native %dx%d", portduino_config.displayWidth, portduino_config.displayHeight);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/platform/portduino/HUB75Native.cpp` around lines 11 - 18, Add assertions
in the HUB75Native constructor before setGeometry to enforce that
portduino_config.displayWidth and portduino_config.displayHeight are positive.
Keep the existing geometry setup and debug logging unchanged, ensuring invalid
initialization fails immediately instead of configuring a 0x0 display.

Source: Coding guidelines

variants/native/portduino/HUB75Native.h (1)

18-28: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Trim the multi-paragraph class comment.

This 11-line, multi-paragraph doc comment exceeds the project's comment guideline. As per coding guidelines, "Keep code comments minimal: use at most one or two lines... do not add multi-paragraph explanatory comments." Consider moving the design rationale to a design doc/PR description and leaving a 1-2 line summary here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@variants/native/portduino/HUB75Native.h` around lines 18 - 28, Replace the
multi-paragraph comment above the HUB75 native backend with a concise one- or
two-line summary of its purpose. Remove the implementation details, design
rationale, configuration explanation, and source-location note from the comment.

Source: Coding guidelines

src/platform/portduino/architecture.h (1)

39-41: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing #ifndef guard breaks the file's override convention.

Every other flag in this file (HAS_BUTTON, HAS_WIFI, HAS_RADIO, etc.) uses #ifndef X / #defineX 1 /#endif`` so a variant can pre-define the flag to override auto-detection. This new block skips that guard, so if anything ever pre-defines HAS_HUB75_NATIVE to a different value before this header, you'll get a macro-redefinition conflict instead of a clean override.

♻️ Proposed fix
-#if defined(ARCH_PORTDUINO) && __has_include(<led-matrix.h>)
-#define HAS_HUB75_NATIVE 1
+#ifndef HAS_HUB75_NATIVE
+#if __has_include(<led-matrix.h>)
+#define HAS_HUB75_NATIVE 1
+#endif
 `#endif`
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/platform/portduino/architecture.h` around lines 39 - 41, Update the
HAS_HUB75_NATIVE detection block in architecture.h to follow the file’s existing
override convention: only define it when ARCH_PORTDUINO and led-matrix.h are
available and HAS_HUB75_NATIVE is not already defined, preserving any
pre-defined value without macro redefinition.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/platform/portduino/PortduinoGlue.cpp`:
- Around line 1012-1036: Update the HUB75 configuration block around
yamlConfig["Display"]["HUB75"] to require both the HUB75 YAML node and
displayPanel == hub75 before applying HUB75 settings or overwriting
displayWidth/displayHeight. Preserve the existing HUB75 configuration behavior
when hub75 is the selected panel, while ignoring stray HUB75 settings for other
panel types.

---

Nitpick comments:
In `@src/platform/portduino/architecture.h`:
- Around line 39-41: Update the HAS_HUB75_NATIVE detection block in
architecture.h to follow the file’s existing override convention: only define it
when ARCH_PORTDUINO and led-matrix.h are available and HAS_HUB75_NATIVE is not
already defined, preserving any pre-defined value without macro redefinition.

In `@src/platform/portduino/HUB75Native.cpp`:
- Line 62: Update the matrix initialization in HUB75Native to call
rgb_matrix::RGBMatrix::CreateFromOptions(options, runtime) instead of the legacy
rgb_matrix::CreateMatrixFromOptions alias, preserving the existing options and
runtime arguments.
- Around line 11-18: Add assertions in the HUB75Native constructor before
setGeometry to enforce that portduino_config.displayWidth and
portduino_config.displayHeight are positive. Keep the existing geometry setup
and debug logging unchanged, ensuring invalid initialization fails immediately
instead of configuring a 0x0 display.

In `@src/platform/portduino/PortduinoGlue.cpp`:
- Around line 1073-1075: Update the action normalization loop in the button
handling code to cast each character to unsigned char before passing it to
tolower(), while preserving the existing lowercase conversion behavior.

In `@variants/native/portduino/HUB75Native.h`:
- Around line 18-28: Replace the multi-paragraph comment above the HUB75 native
backend with a concise one- or two-line summary of its purpose. Remove the
implementation details, design rationale, configuration explanation, and
source-location note from the comment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 163a134d-6a43-4a59-80c7-9ce74a402b7a

📥 Commits

Reviewing files that changed from the base of the PR and between 976b342 and c039fcc.

📒 Files selected for processing (14)
  • bin/config-dist.yaml
  • bin/config.d/display-hub75-64x64.yaml
  • src/graphics/HUB75Display.cpp
  • src/graphics/HUB75Display.h
  • src/graphics/Screen.cpp
  • src/graphics/TFTColorRegions.h
  • src/platform/portduino/HUB75Native.cpp
  • src/platform/portduino/PortduinoGlue.cpp
  • src/platform/portduino/PortduinoGlue.h
  • src/platform/portduino/architecture.h
  • variants/esp32s3/visualizer-hub75/platformio.ini
  • variants/esp32s3/visualizer-hub75/variant.h
  • variants/native/portduino/HUB75Native.h
  • variants/native/portduino/platformio.ini
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/graphics/Screen.cpp

Comment thread src/platform/portduino/PortduinoGlue.cpp Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

baseui Issues directly related to BaseUI enhancement New feature or request needs-review Needs human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants