You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Where upstream stands (develop 038d615, 2026-09-22)
The X4 Pro ([env:x4pro], ESP32-S3 + 8 MB PSRAM) ships with exactly one power mechanism: HalPowerManager::setPowerSaving drops the CPU 240 → 80 MHz after 3 s of no input and restores it on any activity or render lock. The idle loop still wakes every 10 ms, polling the GT911 over I2C and the ADC. There is no CONFIG_PM_ENABLE, no tickless idle, no DFS, no light sleep. The x4pro profile extends base only and deliberately skips custom_sdkconfig (the USB-OTG/MSC path needs pioarduino's prebuilt TinyUSB graph), so the Arduino sdkconfig cannot be changed without solving that first. That is the structural blocker for real esp_pm.
X4 Pro has no VBUS-detect GPIO (usbDetect = PIN_UNASSIGNED), so the fix: x4 usb attach freeze crosspoint-reader/crosspoint-reader#3082 USB-attach wake never armed there. Added usbWakePin() that falls back to the charger STAT line (GPIO21, HIGH while charging) as the light-sleep wake source.
Compiled the BUSY-wait sleep slices out for the X4 Pro and added a display.isRefreshPending() guard so an idle slice is never entered while an async refresh is in flight (light sleep gates the GPIO edge detector, which would lose the BUSY-done ISR the async finish waits on).
What we learned on the real X4 Pro
The X4 freeze class does not apply. GPIO13 is the display chip-select on the Pro and the hold code is gated by isXteinkDevice(), which excludes Board::XteinkX4Pro.
USB gate works. With a host attached the SOF frame counter on USB-Serial-JTAG holds sleep off; CDC stayed alive over a 40 s idle window with logs every 10 s. Charger STAT covers the plug-in transient; at charge termination STAT drops but SOF already has the link.
Ghosting is not sleep. Rapid page turns showed heavy trails on every build, including with the refresh-time sleep compiled out. This is the panel's normal partial-refresh behaviour, controlled by the refresh-frequency setting. A no-sleep control build was about to be flashed when this was clarified; the A/B toggle was removed again.
Two S3 details worth keeping: LOW_POWER_FREQ is 80 MHz on PSRAM boards (PSRAM clocks off the CPU), and FREEINK_FRONTLIGHT_LS is already on for x4pro, so a lit frontlight does not block sleep.
Recovery is always available: the S3 ROM loader answers on USB-JTAG regardless of firmware state; nothing here touches bootloader, partitions or NVS.
Responsiveness after idle not yet characterised beyond "up to one 50 ms slice by design".
The refresh-time sleep half is compiled out for the Pro; it may be safe to re-enable now that ghosting is understood to be unrelated.
Tickless idle / CONFIG_PM_ENABLE: blocked on the x4pro profile's inability to rebuild the Arduino core. Options are a custom_sdkconfig experiment on the x4pro env to see whether TinyUSB actually breaks, or an ESP-IDF-native build of CrossPoint.
Where upstream stands (develop 038d615, 2026-09-22)
The X4 Pro (
[env:x4pro], ESP32-S3 + 8 MB PSRAM) ships with exactly one power mechanism:HalPowerManager::setPowerSavingdrops the CPU 240 → 80 MHz after 3 s of no input and restores it on any activity or render lock. The idle loop still wakes every 10 ms, polling the GT911 over I2C and the ADC. There is noCONFIG_PM_ENABLE, no tickless idle, no DFS, no light sleep. Thex4proprofile extendsbaseonly and deliberately skipscustom_sdkconfig(the USB-OTG/MSC path needs pioarduino's prebuilt TinyUSB graph), so the Arduino sdkconfig cannot be changed without solving that first. That is the structural blocker for real esp_pm.What was tried upstream
esp_light_sleep_start()in 50 ms slices when idle, plus sleep slices during the e-ink BUSY wait. PPK2 on an X3: idle 9.68 → 2.78 mA, ~3.2× reading time. Merged 2026-08-13.gpio_hold_enwas left latched across the whole idle period, so the pad could not follow the VBUS power-path transition.esp_pm+ tickless + DFS 80–240 prototype was measured on X4 Pro hardware (feat: light-sleep-surviving frontlight (FREEINK_FRONTLIGHT_LS) Free-Ink/freeink-sdk#39 body: 92 % light-sleep residency over 31 min) but never submitted to CrossPoint.CONFIG_PM_ENABLE+ PM locks) and Add display PM locks for auto light sleep Free-Ink/freeink-sdk#12 (display PM locks) open since July, no maintainer decision.What we did (branch
agent/lightsleep-5d3eon this fork)rawInputActive().usbDetect = PIN_UNASSIGNED), so the fix: x4 usb attach freeze crosspoint-reader/crosspoint-reader#3082 USB-attach wake never armed there. AddedusbWakePin()that falls back to the charger STAT line (GPIO21, HIGH while charging) as the light-sleep wake source.display.isRefreshPending()guard so an idle slice is never entered while an async refresh is in flight (light sleep gates the GPIO edge detector, which would lose the BUSY-done ISR the async finish waits on).What we learned on the real X4 Pro
isXteinkDevice(), which excludesBoard::XteinkX4Pro.LOW_POWER_FREQis 80 MHz on PSRAM boards (PSRAM clocks off the CPU), andFREEINK_FRONTLIGHT_LSis already on for x4pro, so a lit frontlight does not block sleep.Not done
CONFIG_PM_ENABLE: blocked on the x4pro profile's inability to rebuild the Arduino core. Options are acustom_sdkconfigexperiment on the x4pro env to see whether TinyUSB actually breaks, or an ESP-IDF-native build of CrossPoint.