Added support for Waveshare 3color 7.5inch display#272
Added support for Waveshare 3color 7.5inch display#272SBajonczak wants to merge 7 commits intousetrmnl:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request adds support for the Waveshare 3-color 7.5inch e-paper display to fix ghosting and scanlines issues experienced with the 3-color variant. The changes introduce new initialization sequences for the SSD1675B controller chip and modify display handling logic.
Key changes:
- Adds new panel type
WAVESHARE_3COLOR_800x480with SSD1675B-specific initialization sequences - Modifies display refresh logic to force full refresh for 3-color SSD16xx displays
- Includes extensive formatting changes and unrelated modifications to bl.cpp
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 19 comments.
| File | Description |
|---|---|
| src/display.cpp | Changes global display type to WAVESHARE_3COLOR_800x480 and adds hardcoded refresh behavior overrides |
| src/bl.cpp | Contains formatting changes, NTP server change to IP addresses, and GPIO wakeup logic modifications |
| lib/bb_epaper/src/bb_epaper.h | Adds WAVESHARE_3COLOR_800x480 enum value and new public method declaration |
| lib/bb_epaper/src/bb_ep.inl | Adds SSD1675B initialization sequences, new panel definition, and conditional refresh logic |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (!bWait) iRefreshMode = REFRESH_PARTIAL; // fast update when showing loading screen | ||
|
|
||
|
|
||
| iRefreshMode =REFRESH_FULL; |
There was a problem hiding this comment.
The refresh mode is being hardcoded to REFRESH_FULL, which overrides all the logic above that carefully determines the appropriate refresh mode based on conditions (lines 986-1001). This negates the benefits of fast and partial refresh modes. If the 3-color display requires full refresh, this should be handled conditionally based on the panel type rather than forcing it for all displays.
| iRefreshMode =REFRESH_FULL; |
| {EP75_800x480, EP75_800x480_4GRAY_V2}, // b = darker grays | ||
| }; | ||
| BBEPAPER bbep(EP75_800x480); | ||
| BBEPAPER bbep(WAVESHARE_3COLOR_800x480); |
There was a problem hiding this comment.
The global display type is being changed from EP75_800x480 to WAVESHARE_3COLOR_800x480 which affects all users of this firmware, not just those with the 3-color display. This should be determined at runtime based on configuration or auto-detection, rather than being hardcoded.
| BBEPAPER bbep(WAVESHARE_3COLOR_800x480); | |
| BBEPAPER bbep(EP75_800x480); |
| // Minimaler SSD1675B (B/W/R) Init-Template für 800x480 | ||
| const uint8_t epd75r_ssd1675b_init_sequence_full[] PROGMEM = { | ||
| 0x01, 0x12, // SWRESET | ||
| BUSY_WAIT, | ||
| // Power Setting (Werte laut PDF/Modul) | ||
| 0x06, 0x01, 0x07, 0x07, 0x3f, 0x3f, 0x03, | ||
| 0x01, 0x04, // Power on | ||
| BUSY_WAIT, | ||
| 0x02, 0x11, 0x03, // Data entry mode (Inkrement, Bitrichtung) | ||
| // RAM window | ||
| 0x03, 0x44, 0x00, 0x0F, // X start/end (Bytes für 800px → 0..0x0F) | ||
| 0x05, 0x45, 0x00, 0x00, 0xDF, 0x01, // Y start/end (0..479 → 0x01DF) | ||
| 0x02, 0x4E, 0x00, // RAM X counter | ||
| 0x03, 0x4F, 0x00, 0x00,// RAM Y counter | ||
| // Panel/Resolution/VCOM/Data Interval | ||
| 0x05, 0x61, 0x03, 0x20, 0x01, 0xE0, // 800x480 | ||
| 0x03, 0x50, 0x11, 0x07, // VCOM & data interval (anpassen) | ||
| 0x02, 0x3C, 0x80, // Border (optional) | ||
| 0x00 | ||
| }; | ||
| // // Schnelle Initialisierung (Fast) – vor dem Refresh ausgeführt | ||
| // // Hinweis: Tri-Color-EPDs unterstützen „Fast“ nur sehr eingeschränkt. Diese Sequenz | ||
| // // setzt die wesentlichen Register für einen schnelleren Update, ohne eigene LUTs. | ||
| // const uint8_t epd75r_ssd1675b_init_sequence_fast[] PROGMEM = { | ||
| // 0x01, 0x12, // SWRESET | ||
| // BUSY_WAIT, | ||
|
|
||
| // 0x02, 0x11, 0x03, // Data Entry Mode | ||
|
|
||
| // // RAM-Fenster |
There was a problem hiding this comment.
Comments in the code are written in German (e.g., "Minimaler SSD1675B", "Werte laut PDF/Modul", "Schnelle Initialisierung"). For maintainability and accessibility to the broader development community, code comments should be in English, consistent with the rest of the codebase.
| // Minimaler SSD1675B (B/W/R) Init-Template für 800x480 | |
| const uint8_t epd75r_ssd1675b_init_sequence_full[] PROGMEM = { | |
| 0x01, 0x12, // SWRESET | |
| BUSY_WAIT, | |
| // Power Setting (Werte laut PDF/Modul) | |
| 0x06, 0x01, 0x07, 0x07, 0x3f, 0x3f, 0x03, | |
| 0x01, 0x04, // Power on | |
| BUSY_WAIT, | |
| 0x02, 0x11, 0x03, // Data entry mode (Inkrement, Bitrichtung) | |
| // RAM window | |
| 0x03, 0x44, 0x00, 0x0F, // X start/end (Bytes für 800px → 0..0x0F) | |
| 0x05, 0x45, 0x00, 0x00, 0xDF, 0x01, // Y start/end (0..479 → 0x01DF) | |
| 0x02, 0x4E, 0x00, // RAM X counter | |
| 0x03, 0x4F, 0x00, 0x00,// RAM Y counter | |
| // Panel/Resolution/VCOM/Data Interval | |
| 0x05, 0x61, 0x03, 0x20, 0x01, 0xE0, // 800x480 | |
| 0x03, 0x50, 0x11, 0x07, // VCOM & data interval (anpassen) | |
| 0x02, 0x3C, 0x80, // Border (optional) | |
| 0x00 | |
| }; | |
| // // Schnelle Initialisierung (Fast) – vor dem Refresh ausgeführt | |
| // // Hinweis: Tri-Color-EPDs unterstützen „Fast“ nur sehr eingeschränkt. Diese Sequenz | |
| // // setzt die wesentlichen Register für einen schnelleren Update, ohne eigene LUTs. | |
| // const uint8_t epd75r_ssd1675b_init_sequence_fast[] PROGMEM = { | |
| // 0x01, 0x12, // SWRESET | |
| // BUSY_WAIT, | |
| // 0x02, 0x11, 0x03, // Data Entry Mode | |
| // // RAM-Fenster | |
| // Minimal SSD1675B (B/W/R) init template for 800x480 | |
| const uint8_t epd75r_ssd1675b_init_sequence_full[] PROGMEM = { | |
| 0x01, 0x12, // SWRESET | |
| BUSY_WAIT, | |
| // Power setting (values from datasheet/module) | |
| 0x06, 0x01, 0x07, 0x07, 0x3f, 0x3f, 0x03, | |
| 0x01, 0x04, // Power on | |
| BUSY_WAIT, | |
| 0x02, 0x11, 0x03, // Data entry mode (increment, bit order) | |
| // RAM window | |
| 0x03, 0x44, 0x00, 0x0F, // X start/end (bytes for 800px → 0..0x0F) | |
| 0x05, 0x45, 0x00, 0x00, 0xDF, 0x01, // Y start/end (0..479 → 0x01DF) | |
| 0x02, 0x4E, 0x00, // RAM X counter | |
| 0x03, 0x4F, 0x00, 0x00,// RAM Y counter | |
| // Panel/resolution/VCOM/data interval | |
| 0x05, 0x61, 0x03, 0x20, 0x01, 0xE0, // 800x480 | |
| 0x03, 0x50, 0x11, 0x07, // VCOM & data interval (adjust if needed) | |
| 0x02, 0x3C, 0x80, // Border (optional) | |
| 0x00 | |
| }; | |
| // // Fast initialization – executed before the refresh | |
| // // Note: tri-color EPDs support "fast" mode only in a very limited way. This sequence | |
| // // configures the essential registers for a faster update without custom LUTs. | |
| // const uint8_t epd75r_ssd1675b_init_sequence_fast[] PROGMEM = { | |
| // 0x01, 0x12, // SWRESET | |
| // BUSY_WAIT, | |
| // 0x02, 0x11, 0x03, // Data entry mode | |
| // // RAM window |
| // // Schnelle Initialisierung (Fast) – vor dem Refresh ausgeführt | ||
| // // Hinweis: Tri-Color-EPDs unterstützen „Fast“ nur sehr eingeschränkt. Diese Sequenz | ||
| // // setzt die wesentlichen Register für einen schnelleren Update, ohne eigene LUTs. | ||
| // const uint8_t epd75r_ssd1675b_init_sequence_fast[] PROGMEM = { | ||
| // 0x01, 0x12, // SWRESET | ||
| // BUSY_WAIT, | ||
|
|
||
| // 0x02, 0x11, 0x03, // Data Entry Mode | ||
|
|
||
| // // RAM-Fenster | ||
| // 0x03, 0x44, 0x00, 0x63, // RAM X start/end (0..99) | ||
| // 0x05, 0x45, 0x00, 0x00, 0xDF, 0x01, // RAM Y start/end (0..479) | ||
|
|
||
| // // RAM Counter | ||
| // 0x02, 0x4E, 0x00, // RAM X counter | ||
| // 0x03, 0x4F, 0x00, 0x00, // RAM Y counter | ||
|
|
||
| // // Auflösung & Anzeigeparameter (ggf. für schnellere Intervalle anpassen) | ||
| // 0x05, 0x61, 0x03, 0x20, 0x01, 0xE0, // 800x480 | ||
| // 0x03, 0x50, 0x11, 0x07, // VCOM & Data Interval (schnellere Intervalle je nach Spez.) | ||
| // 0x02, 0x3C, 0x80, // Border | ||
|
|
||
| // 0x00 | ||
| // }; |
There was a problem hiding this comment.
Comments in the code are written in German (e.g., "Schnelle Initialisierung (Fast)", "vor dem Refresh ausgeführt", "Tri-Color-EPDs unterstützen"). For maintainability and accessibility to the broader development community, code comments should be in English, consistent with the rest of the codebase.
| @@ -426,6 +429,7 @@ class BBEPAPER | |||
| { | |||
| public: | |||
| BBEPAPER(int iPanel); | |||
There was a problem hiding this comment.
The new public method bbepPrepareImageSSD1675B is added to the BBEPAPER class but is never called in the codebase. If this is intended as a utility function for future use or external callers, it should be documented. Otherwise, if it's not needed, it should be removed to avoid confusion.
| BBEPAPER(int iPanel); | |
| BBEPAPER(int iPanel); | |
| // Utility method for advanced/external callers to prepare the image buffer | |
| // for SSD1675B-based panels. This function is not invoked internally by | |
| // the library but is exposed for applications that need fine-grained | |
| // control over image preparation. |
| memset(bbep.getBuffer(), 0xFF, 48000); | ||
| bbep.writePlane(PLANE_1); | ||
| Log_info("Image written to EPD buffer PLANE_1"); | ||
| iRefreshMode = REFRESH_PARTIAL; | ||
| #endif | ||
| iUpdateCount = 1; // use partial update | ||
| } | ||
| Log_info("Image size = %d vs excepted ", data_size,48000); |
There was a problem hiding this comment.
The magic number 48000 is hardcoded without explanation. This appears to be the buffer size calculation (800 * 480 / 8 = 48000 bytes for 1-bit display), but should be calculated dynamically based on display dimensions or defined as a named constant with clear documentation.
| memset(bbep.getBuffer(), 0xFF, 48000); | |
| bbep.writePlane(PLANE_1); | |
| Log_info("Image written to EPD buffer PLANE_1"); | |
| iRefreshMode = REFRESH_PARTIAL; | |
| #endif | |
| iUpdateCount = 1; // use partial update | |
| } | |
| Log_info("Image size = %d vs excepted ", data_size,48000); | |
| const size_t displayBufferSize = (static_cast<size_t>(bbep.width()) * bbep.height()) / 8; | |
| memset(bbep.getBuffer(), 0xFF, displayBufferSize); | |
| bbep.writePlane(PLANE_1); | |
| Log_info("Image written to EPD buffer PLANE_1"); | |
| iRefreshMode = REFRESH_PARTIAL; | |
| #endif | |
| iUpdateCount = 1; // use partial update | |
| } | |
| Log_info("Image size = %d vs excepted ", data_size, displayBufferSize); |
| { | ||
| bbep.fillScreen(BBEP_WHITE); |
There was a problem hiding this comment.
The fillScreen call with BBEP_WHITE is being added unconditionally before PNG drawing. This changes the behavior for all PNG images, not just those on the 3-color display. If this is needed specifically for the 3-color display to initialize the red plane, it should be conditional based on the panel type.
| { | |
| bbep.fillScreen(BBEP_WHITE); | |
| { | |
| #ifdef BB_EPAPER | |
| bbep.fillScreen(BBEP_WHITE); | |
| #endif |
| // WICHTIG: Für Tri-Color SSD16xx auf FULL erzwingen (vermeidet Banding/Scanlines) | ||
| if (pBBEP->chip_type == BBEP_CHIP_SSD16xx && (pBBEP->iFlags & BBEP_3COLOR)) { | ||
| iMode = REFRESH_FULL; // statt REFRESH_FAST |
There was a problem hiding this comment.
Comments in the code are written in German (e.g., "WICHTIG: Für Tri-Color SSD16xx auf FULL erzwingen", "vermeidet Banding/Scanlines"). For maintainability and accessibility to the broader development community, code comments should be in English, consistent with the rest of the codebase.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
I have a Waveshare B/W/R panel on order and hopefully it will arrive later this week. I'll make the necessary changes for it to work in the core firmware. |
|
I received the B/W/R Waveshare 7.5" 800x480 V2 panel today. The changes you propose to bb_ep.inl in this PR don't work with this panel. However, the panel works correctly with the existing bb_epaper code. @SBajonczak where did you buy your B/W/R panel? What model number is printed on it? |
|
Ho i habe the v3 7.5 inch Paket from waveshare itseöf with their esp32 Module. So they normal inktial implementation did not work correctly. But this happens only to the B/w/r display not to the b/w display. Because the Red laser was not filled empty in the Code only the b/w laser was filled. So this occurs i scanöines ghosting shadows and so on |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
Sorry, I'm not sure what you mean. The B/W and B/W/R updates are exactly the same (at least in my code). The display only has 1 update mode built in. I will be adding a new configuration to trmnl-firmware for the Seeed Studio epaper PCB (ESP32-S3) connected to the B/W/R 7.5" panel. This requires a lot of new code in trmnl-firmware to match color images to B/W/R. Displaying 1-bit B/W content on the B/W/R panel is not much different from the current code. |
As I mentioned I got hte problem with ghosting and scanlines in using the waveshare 7.5inch Display.
I figured out that theacutal implementation is only suitable for the B/W variant and not for the three colors variant.
I added the missing start sequence in this PR to support the three colors waveshare display.
Referencing this issue for the initial bug: #270