firmware/src/graphics/niche/Drivers/EInk
todd-herbert bd2d2981c9
Add InkHUD driver for WeAct Studio 4.2" display module (#6384)
* chore: todo.txt

* chore: InkHUD documentation
Word salad for maintainers

* refactor: don't init system applets using onActivate
System applets cannot be deactivated, so we will avoid using onActivate / onDeactivate methods entirely.

* chore: update the example applets

* fix: SSD16XX reset pulse
Allow time for controller IC to wake. Aligns with manufacturer's suggestions.
T-Echo button timing adjusted to prevent bouncing as a result(?) of slightly faster refreshes.

* fix: allow timeout if display update fails
Result is not graceful, but avoids total display lockup requiring power cycle.
Typical cause of failure is poor wiring / power supply.

* fix: improve display health on shutdown
Two extra full refreshes, masquerading as a "shutting down" screen. One is drawn white-on-black, to really shake the pixels up.

* feat: driver for display HINK_E042A87
As of Feb. 2025, these panels are used for "WeActStudio 4.2in B&W" display modules.

* fix: inkhud rotation should default to 0

* Revert "chore: todo.txt"

This reverts commit bea7df44a7.

* fix: more generous timeout for display updates
Previously this was tied to the expected duration of the update, but this didn't account for any delay if our polling thread got held up by an unrelated firmware task.

* fix: don't use the full shutdown screen during reboot

* fix: cooldown period during the display shutdown display sequence
Observed to prevent border pixels from being locked in place with some residual charge?
2025-03-31 09:17:24 +02:00
..
DEPG0154BNS800.cpp 2.6 changes (#5806) 2025-03-01 06:18:33 -06:00
DEPG0154BNS800.h 2.6 changes (#5806) 2025-03-01 06:18:33 -06:00
DEPG0290BNS800.cpp 2.6 changes (#5806) 2025-03-01 06:18:33 -06:00
DEPG0290BNS800.h 2.6 changes (#5806) 2025-03-01 06:18:33 -06:00
EInk.cpp Add InkHUD driver for WeAct Studio 4.2" display module (#6384) 2025-03-31 09:17:24 +02:00
EInk.h Add InkHUD driver for WeAct Studio 4.2" display module (#6384) 2025-03-31 09:17:24 +02:00
GDEY0154D67.cpp InkHUD refactoring (#6216) 2025-03-06 11:25:41 +01:00
GDEY0154D67.h 2.6 changes (#5806) 2025-03-01 06:18:33 -06:00
HINK_E042A87.cpp Add InkHUD driver for WeAct Studio 4.2" display module (#6384) 2025-03-31 09:17:24 +02:00
HINK_E042A87.h Add InkHUD driver for WeAct Studio 4.2" display module (#6384) 2025-03-31 09:17:24 +02:00
LCMEN2R13EFC1.cpp InkHUD refactoring (#6216) 2025-03-06 11:25:41 +01:00
LCMEN2R13EFC1.h InkHUD refactoring (#6216) 2025-03-06 11:25:41 +01:00
README.md Add InkHUD driver for WeAct Studio 4.2" display module (#6384) 2025-03-31 09:17:24 +02:00
SSD16XX.cpp Add InkHUD driver for WeAct Studio 4.2" display module (#6384) 2025-03-31 09:17:24 +02:00
SSD16XX.h Add InkHUD driver for WeAct Studio 4.2" display module (#6384) 2025-03-31 09:17:24 +02:00

NicheGraphics - E-Ink Driver

A driver for E-Ink SPI displays. Suitable for re-use by various NicheGraphics UIs.

Your UI should use the class NicheGraphics::Drivers::EInk . When you set up a hardware variant, you will use one of the specific display model classes, which extend the EInk class.

An example setup might look like this:

void setupNicheGraphics()
{
    using namespace NicheGraphics;

    // An imaginary UI
    YourCustomUI *yourUI = new YourCustomUI();

    // Setup SPI
    SPIClass *hspi = new SPIClass(HSPI);
    hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS);

    // Setup Enk driver
    Drivers::EInk *driver = new Drivers::DEPG0290BNS800;
    driver->begin(hspi, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY);

    // Pass the driver to your UI
    YourUI::driver = driver;
}

Methods

update(uint8_t *imageData, UpdateTypes type)

Update the image on the display

  • imageData to draw to the display.
  • type which type of update to perform.
    • FULL
    • FAST (partial refresh)
    • (Other custom types may be possible)

The imageData is a 1-bit image. X-Pixels are 8-per byte, with the MSB being the leftmost pixel. This was not an InkHUD design decision; it is the raw format accepted by the E-Ink display controllers ICs.

To-do: add a helper method to InkHUD::Drivers::EInk to do this arithmetic for you.

uint16_t w = driver::width();
uint16_t h = driver::height();

uint8_t image[ (w/8) * h ]; // X pixels are 8-per-byte

image[0] |= (1 << 7); // Set pixel x=0, y=0
image[0] |= (1 << 0); // Set pixel x=7, y=0
image[1] |= (1 << 7); // Set pixel x=8, y=0

uint8_t x = 12;
uint8_t y = 2;
uint8_t yBytes = y * (w/8);
uint8_t xBytes = x / 8;
uint8_t xBits = (7-x) % 8;
image[yByte + xByte] |= (1 << xBits); // Set pixel x=12, y=2

await()

Wait for an in-progress update to complete before continuing

supports(UpdateTypes type)

Check if display supports a specific update type. true if supported.

  • type type to check

busy()

Check if display is already performing an update(). true if already updating.

width()

Width of the display, in pixels. Note: most displays are portrait. Your UI will need to implement rotation in software.

height()

Height of the display, in pixels. Note: most displays are portrait. Your UI will need to implement rotation in software.

Supporting New Displays

This topic is not covered in depth, but these notes may be helpful.

The InkHUD::Drivers::EInk class contains only the mechanism for implementing an E-Ink driver on-top of Meshtastic's OSThread. A driver for a specific display needs to extend this class.

Controller IC

If your display uses a controller IC from Solomon Systech, you can probably extend the existing Drivers::SSD16XX class, making only minor modifications.

At this stage, displays using controller ICS from other manufacturers (UltraChip, Fitipower, etc) need to manually implemented. See Drivers::LCMEN2R13EFC1 for an example.

Generic base classes for manufacturers other than Solomon Systech might be added here in future.

Finding Information

Flex-Connector Labels

The orange flex-connector attached to E-Ink displays is often printed with an identifying label. This is not a totally unique identifier, but does give a very strong clue as to the true model of the display, which can be used to search out further information.

Datasheets

The manufacturer of a DIY display module may publish a datasheet. These are often incomplete, but might reveal the true model of the display, or the controller IC.

If you can determine the true model name of the display, you can likely find a more complete datasheet on the display manufacturer's website. This will often provide a "typical operating sequence"; a general overview of the code used to drive the display

Example Code

The manufacturer of a DIY module may publish example code. You may have more luck finding example code published by the display manufacturer themselves, if you can determine the true model of the panel. These examples are a very valuable reference.

Other E-Ink drivers

Libraries like ZinggJM's GxEPD2 can be valuable sources of information, although your panel may not be specifically supported, and only compatible with a driver there, so some caution is advised.

The display selection file in GxEPD2's Hello World example is also a useful resource for matching "flex connector labels" with display models, but the flex connector label is not a unique identifier, so this is only another clue.