Repository navigation
EPD / OLED / LED panels: init without clear keeps the image on the panel - #375
Merged
Merged
Conversation
With M5Unified cfg.clear_display = false (LGFX init_without_reset(false)), the image on the panel was wiped during initialization (m5stack#370): - GDEW0154D67 / SSD1677: LGFX_Device::init_impl() re-applies the invert setting after Panel::init(), and setInvert() marked the whole frame dirty while the init sequence was pending, so the endWrite() of init_impl() refreshed the panel with the (white) host buffer. Re-applying the current value no longer marks the frame dirty; a changed value is still shown. - GDEW0154D67: the frame sent by the init sequence is no longer inverted. With the inverted frame, the flip draw that follows ended inverted whenever that was the first display() after a reset (not visible before, because init() itself refreshed the panel). - TM1680: init() no longer pushes the cleared buffer, and setInvert() pushes only when the value changes. The init commands do not touch the LED RAM, so the image stays on the LEDs until the first draw. - Panel_1bitOLED / Panel_M5UnitGlass: init() clears the host buffer (and the tile dirty flags of the Unit GLASS) without pushing it. They relied on the clear() of a normal init; with an init without clear, the first partial drawing would have sent whatever the allocator left there. The host buffer cannot be read back from these panels, so the first drawing after an init without clear still replaces the whole panel with the new buffer. What changes is that the initialization itself no longer wipes it.
This was referenced Oct 23, 2026
Merged
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.
Fixes #370.
Problem
With M5Unified
cfg.clear_display = false, the image that was on the panel before a reset or a deep sleep is wiped duringM5.begin():LGFX_Device::init_impl()re-applies the invert setting afterPanel::init().Panel_GDEW0154D67::setInvert()marked the whole frame dirty while the init sequence was pending, so theendWrite()ofinit_impl()refreshed the whole panel with the (white) host buffer.setInvert()call pushed the cleared host buffer to the LEDs (andPanel_TM1680::init()did so a second time), so everybegin()turned the matrix off.setInvert()marks the whole frame dirty unconditionally).Change
Panel_GDEW0154D67::setInvert()/Panel_SSD1677::setInvert(): while the init sequence is pending, applying the current value does not mark the frame dirty. The firstdisplay()after a reset sends the whole frame anyway.Panel_GDEW0154D67::display(): the frame sent by the init sequence is no longer inverted. With the inverted frame, the flip draw that follows ended inverted (white and black swapped) whenever that was the firstdisplay()after a reset; it did not show before becauseinit()itself refreshed the panel.Panel_TM1680:init()no longer pushes the cleared buffer, andsetInvert()pushes only when the value changes. The init commands do not touch the LED RAM, so the image stays on the LEDs until the first draw. On a cold power-up the LED RAM is undefined until the first push, which now comes with theclear()of a normal init instead of insideinit(); the gap is a few I2C bytes.Panel_1bitOLED(SSD1306 / SH110x / SSD1309 units) andPanel_M5UnitGlass:init()clears the host buffer (nothing is pushed). These panels relied on theclear()of a normal init to initialize the buffer; with an init without clear, the first partial drawing would have sent whatever the allocator left in the page.The host buffer cannot be read back from these panels, so the first drawing after an init without clear still replaces the whole panel with the new buffer (white / off outside the drawn area). What is fixed is that
begin()itself no longer wipes the panel.The M5Unified side (external displays following
cfg.clear_display) is m5stack/M5Unified#416.Test
esp_restart(),esp_deep_sleep()andM5.Power.deepSleep()followed byM5.begin()withclear_display = false(before: the D67 unit turned white then black duringbegin()). A normal boot withclear_display = truestill clears and draws correctly. On the D67 the first drawing after an init without clear comes out with the right polarity and without ghosting of the previous image, inepd_quality(the default) and inepd_fast; before the change that drawing ended inverted inepd_quality.esp_restart()+M5.begin()withclear_display = false(before: all LEDs off).