Repository navigation
Conversation
… path) The M5Paper (classic ESP32, 16 MB flash, 8 MB PSRAM) drives its 4.7" ED047TC1 960x540 panel through an IT8951 over SPI, the same FastEPD path the ED103TC2 (reTerminal E1003) already uses. No new PlatformIO env: it runs the existing esp32-wrover-e-N4R8 build. - vendored structs header: PanelIC 3005 OD_PANEL_IC_M5PAPER_960X540 (Unreleased changelog entry; canonical opendisplay-protocol change to follow -- the vendored copy is already ahead of canonical) - fastepd_driver_used(): include 3005 in the IT8951 set - IT8951 pins for 3005: SPI from the display block (M5Paper defaults 12/13/14/15, busy 27); reset_pin (GPIO23, the IT8951 supply gate -- reset is not wired) doubles as RST/EN/ITE_EN, matching FastEPD's own BB_PANEL_M5PAPER definition. pwr_pin_2/3 stay the power latch. - panel size: explicit 960x540 unmirrored for 3005 (FastEPD 2.2.0 has no BBEP_DISPLAY_ED047TC1) - m5paper_init(), keyed off panel IC 3005 rather than a device_flags bit (bit 5 is already used differently across firmware families): drives GPIO2 (main-power hold) and GPIO5 (EXT power) HIGH before powerLatchBegin(). Deep-sleep hold and power-off of GPIO2 use the existing MOSFET latch (pwr_latch, pwr_pin_2 = 2). Not yet validated on hardware. Without an RTC wake the board holds its rail through ESP32 deep sleep; RTC power-off follows separately. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KZwG6PyfGku5uKoVTyB9MC
…ut-only touch INT Display: FastEPD 2.2.0 loads an IT8951 frame L_ENDIAN unless the panel is MIRROR_X, which swaps the two bytes of every 16-bit word. On the M5Paper (the only unmirrored IT8951 panel) 4bpp pixel pairs landed 2 px off, so the image looked interlaced / shifted horizontally. Full refreshes on unmirrored IT8951 panels now go through it8951_full_write_unmirrored() (same frame and GC16 waveform as FastEPD's writer, loaded B_ENDIAN as M5Stack's M5EPD driver does); the full-screen DU path uses B_ENDIAN too. Mirrored panels (ED103TC2) keep FastEPD's own path, unchanged. Touch: the M5Paper GT911 INT is GPIO36, an input-only pad with no internal pull-up. The INT wake pulse and address-select reset drove it as an output and INPUT_PULLUP failed, logging GPIO errors on every boot and EPD refresh. Skip driving input-only pads and read them as plain INPUT. Verified on an original M5Paper (ESP32-D0WDQ6-V3, USB config): 960x540 4bpp test image sharp (shifted before the fix), orientation correct, gray steps 0 (black) to 15 (white) look right; no GPIO errors at boot; GT911 taps at all four corners and the centre map correctly with touch flags SWAP_XY|INVERT_Y (0x06); rocker 37/38/39 press and release. Not verified on hardware: 1bpp (mono) and the DU fast path. The mirrored (reTerminal) path is unchanged.
The BM8563 at 0x51 runs from VBAT_IN and its INT line pulls the M5Paper's power-switch gate low. A timer or alarm left armed (M5Stack's factory firmware leaves a repeating timer, and it survives a flash erase) switched the board back on 60-75 s after every reset-button power-off on battery. m5paper_init() now turns AIE/TIE off, clears AF/TF, stops the timer and disables the alarm on every boot, whatever the sensor config says. Verified on hardware (M5Paper, USB config): with the RTC armed by the previous firmware (C2=01, TC=82, 18 s left), boot logged the clear and a readback (temporary, not committed) showed C2=00, TC=03, alarm disabled. Not verified: absence of the phantom power-on after a battery power-off with this build (needs someone at the device).
…of sending gray data as 1bpp it8951_fullscreen_du() always loads w/8 bytes per row from the framebuffer and shows them with the 1bpp DU waveform. In 4bpp mode (GRAY16, or the ED103TC2 panel) that framebuffer holds two pixels per byte, so a FAST refresh put the top quarter of the gray buffer on screen as 1bpp noise. The parallel path already falls back to a full refresh for 4bpp; the IT8951 path now does the same, for both direct and partial transfers. Verified on hardware (M5Paper, GRAY16 config): with a temporary IT8951 memory readback, a FAST upload before this fix left the raw 4bpp bytes in the 1bpp image area (2400/2400 sampled bytes equal to the 4bpp buffer). With this fix the same FAST upload logs "EPD refresh: FAST" and then takes the full 4bpp path: 19200/19200 sampled pixels in IT8951 memory match the framebuffer, and nothing is loaded through the 1bpp DU path. Also verified by readback (no code change needed): 4bpp full, 1bpp full and 1bpp DU on the M5Paper load the frame byte-for-byte as sent (B_ENDIAN). Not verified: the ED103TC2 (reTerminal), which takes the same branch; the on-screen 1bpp bit order (needs eyes); partial transfers in 4bpp mode, which still blit the rect as 1bpp (the M5Paper preset has partial updates off).
The IT8951 1bpp mode takes the leftmost pixel from bit 0 of each byte; FastEPD packs it in bit 7. Mirrored panels (ED103TC2) never showed this, because FastEPD reverses the byte order of each row for them, which together with LSB-first mirrors the whole row. On the unmirrored M5Paper every 8 px group came out mirrored, so mono images were unreadable. Full 1bpp writes and the 1bpp DU path now send each byte bit-reversed, through a 64-byte stack buffer. 4bpp and mirrored panels are unchanged. Verified on hardware (M5Paper, mono config): before the fix a full mono image was unreadable. A test image with four bands pre-scrambled on the host (none, bits reversed in each byte, bytes swapped, both) showed only the bit-reversed band cleanly. After the fix a full refresh of a text/ruler/1 px line test image is clean, and a FAST (DU) refresh is readable with the usual DU ghosting and incomplete fill of large black areas. Not verified: the ED103TC2 (reTerminal), whose mirrored path is unchanged; 1bpp partial (region) refresh.
m5paper_init() drove GPIO5 HIGH, which turns on the 5 V boost for the Grove ports (M5EPD's default). Nothing here uses the ports, so GPIO5 is now driven LOW. The CPU also drops to 80 MHz right after the GPIO2 power hold: BLE needs no more, and a battery wake window is mostly idle polling. Switching after the hold keeps the power-button hold time unchanged. Verified on hardware (M5Paper, USB): reset to GPIO2 hold 1068 ms (1073 ms before), boot log "CPU 80 MHz". A 259200-byte gray upload took 21.72 s on the device (21.76 s at 240 MHz, BLE-bound) and its refresh 1.49 s (1.47 s). Touch still works with EXT power off (a corner tap read x=18, y=51). Cost: the cold-boot QR boot screen renders in 8.2 s instead of 4.2 s; RTC wakes do not draw it. Not verified: the current saving itself (no meter), anything plugged into a Grove port (now unpowered; enabling it needs a config option that does not exist yet).
Comment only, no code change. Not verified on hardware (nothing to verify).
This was referenced Oct 28, 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.
Adds support for the original M5Stack M5Paper (ESP32, ED047TC1 960×540 behind an IT8951 over SPI) as panel IC 3005 on the existing FastEPD IT8951 path. It also fixes two IT8951 bugs that the reTerminal's mirrored panel had been hiding.
Changes
include/opendisplay_structs.h: addOD_PANEL_IC_M5PAPER_960X540 = 3005. This is a backward-compatible enum addition, but it still needs to land in opendisplay-protocol.src/display_service.cpp: route 3005 to the FastEPD IT8951 path.src/main.cpp,src/config_parser.cpp: addm5paper_init(), called when display 0 is panel 3005 and beforepowerLatchBegin(). It:src/display_fastepd.cpp:src/touch_input.cpp: never drive an input-only touch INT pin (ESP32 GPIO34–39). The M5Paper's GT911 INT is GPIO36.Testing
Hardware: an original M5Paper (ESP32-D0WDQ6-V3), built as
esp32-wrover-e-N4R8, configured with the toolbox preset from the matching opendisplay.org PR..github/firmware-targets.jsonbuild.Not tested:
RTC power-off sleep for the M5Paper is a separate stacked PR, #176.
Toolbox preset: OpenDisplay/opendisplay.org#187