E213: runtime-configurable display rotation via NodePrefs#2393
Open
chrisfore wants to merge 10 commits intomeshcore-dev:devfrom
Open
E213: runtime-configurable display rotation via NodePrefs#2393chrisfore wants to merge 10 commits intomeshcore-dev:devfrom
chrisfore wants to merge 10 commits intomeshcore-dev:devfrom
Conversation
This was referenced Apr 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
src/helpers/ui/E213Display.cpphardcodesdisplay->setRotation(3). Users who flash stock firmware from the web flasher can't un-flip the display when their case orients the panel differently — the only current fix requires a source rebuild with a custom build flag, which is out of reach for most users.Solution
Adds
uint8_t display_rotationto bothNodePrefsstructs (companion_radio and the common one used by repeater/room_server) and exposes it via the existing text CLI:set display.rotation N/get display.rotationinCommonCLI(repeater, room_server)set display.rotation Nin companion_radio'sMyMesh.cppCLI (matchesset pinstyle)Value range 0–3 (same semantics as Arduino GFX
setRotation). Default is3, preserving current behavior for every existing install.DisplayDrivergets a virtual no-opsetRotation(uint8_t)somain.cppcan call it uniformly;E213Displayoverrides it. The threemain.cppfiles (companion_radio, simple_repeater, simple_room_server) calldisplay.setRotation(prefs->display_rotation)after prefs load.Schema migration
New field is appended at the end of the existing fixed-offset
NodePrefsserialization in bothsrc/helpers/CommonCLI.cpp(byte 291) andexamples/companion_radio/DataStore.cpp(byte 137). Reading an older prefs file returns 0 bytes for the trailing read, leaving the in-memory default of3. No data loss, no format break. Same pattern already used whenrx_boosted_gainwas moved to the end ofCommonCLI's layout.Verified on hardware
Tested on a Heltec Vision Master E213 running
Heltec_E213_companion_radio_usb:set display.rotation 1over USB serial, rebooted. Display renders at rotation 1 — un-flips the panel in the target 3D-printed case.savePrefs()wrote correctly.Heltec_E213_companion_radio_usbfrom meshcore.io/flasher on erased flash, setpin 999999via CLI rescue, then reflashed fix-branch firmware at0x0without erasing the data partition. On reboot, display renders at rotation 3 (new field defaulted correctly on the old prefs file), andcat UserData/new_prefsshowsble_pinbytes at offset 80 still reading3F420F00(= 999999 little-endian) — migration preserves all existing fields.Also clean-built across all 5 E213 envs (companion_radio_{usb,ble}, repeater, room_server, repeater_bridge_espnow) and regression envs (Heltec_v3_repeater, Heltec_v3_companion_radio_usb, RAK_4631_repeater).
Known limitation for companion_radio_usb users
On
companion_radio_usb, the USBSerialis dedicated to the binarycmd_frameprotocol for the companion app, so raw text input from a terminal likescreenis consumed by the frame parser (ArduinoSerialInterface::checkRecvFramediscards non-<bytes) and never reaches the text CLI reader. The existing CLI rescue mechanism (long-press USER button within 8 s of boot, which sets_cli_rescue = true) gives access to the text CLI — that's how I ranset display.rotationin the verification above.companion_radio_bleusers don't have this issue:Serialis free because the companion protocol runs over BLE.A cleaner UX (exposing
display_rotationvia a newcmd_frameopcode so the phone app can toggle it without the rescue-button gesture) is filed as a follow-up issue.Out of scope / follow-ups
E290Display.cpphas the same hardcoded-rotation pattern; filed as a separate issue (I have no E290 hardware to test).cmd_frameopcode for companion-appdisplay_rotationcontrol — separate issue. Needed by both companion_radio_usb users (to avoid rescue-mode workaround) and _ble users (who have no USB CLI at all).SSD1306,ST7735,GxEPD,ST7789) onto the prefs-backed mechanism — out of scope; they continue to use theDISPLAY_ROTATIONcompile flag.