diff --git a/src/lgfx/v1/panel/Panel_GDEW0154D67.inl b/src/lgfx/v1/panel/Panel_GDEW0154D67.inl index 39a2d443..e8437882 100644 --- a/src/lgfx/v1/panel/Panel_GDEW0154D67.inl +++ b/src/lgfx/v1/panel/Panel_GDEW0154D67.inl @@ -185,9 +185,11 @@ epd_mode が epd_qualityか否かの変化をした場合も同様にCMD_DISPLAY if (_initialize_seq) { _initialize_seq = false; // リセット直後は起動シーケンス設定およびフレームバッファの転送を行う。ここではリフレッシュは行わない。 + // Send the normal frame here: with the inverted one, the flip draw below ended inverted + // (white and black swapped) whenever this was the first display() after a reset. _bus->writeCommand(cmd_display_update_control_2, 8); _bus->writeData(0xF8, 8); - _exec_transfer(cmd_write_ram_bw, _range_mod, true); + _exec_transfer(cmd_write_ram_bw, _range_mod); _bus->writeCommand(cmd_master_activation, 8); _send_msec = millis(); } @@ -243,16 +245,23 @@ epd_mode が epd_qualityか否かの変化をした場合も同様にCMD_DISPLAY void Panel_GDEW0154D67::setInvert(bool invert) { if (_invert == invert && !_initialize_seq) { return; } + const bool changed = (_invert != invert); _invert = invert; startWrite(); _wait_busy(); _bus->writeCommand(cmd_display_update_control_1, 8); _bus->writeData((invert ^ _cfg.invert) ? 0x88 : 0x00, 8); - _need_flip_draw = true; - _range_mod.top = 0; - _range_mod.left = 0; - _range_mod.right = _width - 1; - _range_mod.bottom = _height - 1; + // Re-applying the current value right after a reset (LGFX_Device::init_impl does) must not mark + // the frame dirty: the first display() sends the whole frame anyway, and a refresh here would wipe + // the image kept on the panel (init without clear). A changed value is still shown at once. + if (changed || !_initialize_seq) + { + _need_flip_draw = true; + _range_mod.top = 0; + _range_mod.left = 0; + _range_mod.right = _width - 1; + _range_mod.bottom = _height - 1; + } endWrite(); } diff --git a/src/lgfx/v1/panel/Panel_M5UnitGLASS.inl b/src/lgfx/v1/panel/Panel_M5UnitGLASS.inl index d49f6cb4..20947f73 100644 --- a/src/lgfx/v1/panel/Panel_M5UnitGLASS.inl +++ b/src/lgfx/v1/panel/Panel_M5UnitGLASS.inl @@ -24,6 +24,8 @@ Contributors: #include "../misc/pixelcopy.hpp" #include "../misc/colortype.hpp" +#include + namespace lgfx { inline namespace v1 @@ -36,6 +38,11 @@ namespace lgfx { return false; } + // Panel_HasBuffer::init leaves the buffer uninitialized, and the per-tile dirty flags are only + // ever OR-ed / cleared in display(); both must start known for the first display() after an init + // without clear to send just what was drawn. + memset(_buf, 0, _get_buffer_length()); + memset(_modified_flags, 0, sizeof(_modified_flags)); bool connected = false; uint8_t res = 0xFFu; diff --git a/src/lgfx/v1/panel/Panel_SSD1306.inl b/src/lgfx/v1/panel/Panel_SSD1306.inl index 038f88d9..e329dcde 100644 --- a/src/lgfx/v1/panel/Panel_SSD1306.inl +++ b/src/lgfx/v1/panel/Panel_SSD1306.inl @@ -24,6 +24,8 @@ Contributors: #include "../misc/pixelcopy.hpp" #include "../misc/dither.hpp" +#include + #ifdef min #undef min #endif @@ -70,6 +72,10 @@ namespace lgfx { return false; } + // Panel_HasBuffer::init does not clear the allocated buffer. Nothing is pushed here, so the image + // on the panel survives an init without clear; the first display() then sends a known buffer + // (black) around the drawn area instead of whatever the allocator left in it. + memset(_buf, 0, _get_buffer_length()); startWrite(true); _bus->beginRead(); diff --git a/src/lgfx/v1/panel/Panel_SSD1677.inl b/src/lgfx/v1/panel/Panel_SSD1677.inl index 42e9c3d3..50c08f53 100644 --- a/src/lgfx/v1/panel/Panel_SSD1677.inl +++ b/src/lgfx/v1/panel/Panel_SSD1677.inl @@ -439,6 +439,9 @@ namespace lgfx void Panel_SSD1677::setInvert(bool invert) { + // Right after a reset the first display() sends the whole frame anyway; marking it dirty here + // would make init() refresh the panel and wipe the image kept on it (init without clear). + if (_invert == invert && _initialize_seq) { return; } _invert = invert; _range_mod.top = 0; _range_mod.left = 0; diff --git a/src/lgfx/v1/panel/Panel_TM1680.inl b/src/lgfx/v1/panel/Panel_TM1680.inl index 529ff75c..b817c3bb 100644 --- a/src/lgfx/v1/panel/Panel_TM1680.inl +++ b/src/lgfx/v1/panel/Panel_TM1680.inl @@ -38,10 +38,11 @@ namespace lgfx { return false; } - // Panel_HasBuffer::init does not clear the allocated buffer; - // clear it here so setInvert below does not push garbage to the LEDs. + // Panel_HasBuffer::init does not clear the allocated buffer. memset(_buf, 0, _get_buffer_length()); + // The init commands do not touch the LED RAM, and nothing is pushed here, so the + // image on the LEDs survives init() (init without clear keeps it until the first draw). startWrite(true); for (size_t i = 0; auto cmds = getInitCommands(i); i++) { @@ -49,7 +50,6 @@ namespace lgfx while (cmds[idx] != 0xFF || cmds[idx + 1] != 0xFF) ++idx; if (idx) { _bus->writeBytes(cmds, idx, false, true); } } - setInvert(_invert); setRotation(_rotation); endWrite(); @@ -58,8 +58,11 @@ namespace lgfx void Panel_TM1680::setInvert(bool invert) { - _invert = invert; // The TM1680 has no display-invert command; invert while packing in display(). + // Only a change is pushed: LGFX_Device::init_impl() re-applies the current value, + // and pushing the cleared buffer there would wipe the LEDs on init without clear. + if (_invert == invert) { return; } + _invert = invert; if (_buf) { startWrite();