From 13b24818d6e86b37ce84d797ed77cb77dbcd5105 Mon Sep 17 00:00:00 2001 From: ladyada Date: Tue, 8 Jul 2025 11:13:32 -0400 Subject: [PATCH] added grayscale4 2.66" (maybe could use a better LUT) --- examples/ThinkInk_gray4/ThinkInk_gray4.ino | 4 + .../ThinkInk_tricolor/ThinkInk_tricolor.ino | 12 +- src/Adafruit_ThinkInk.h | 1 + src/panels/ThinkInk_266_Grayscale4_MFGN.h | 175 ++++++++++++++++++ 4 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 src/panels/ThinkInk_266_Grayscale4_MFGN.h diff --git a/examples/ThinkInk_gray4/ThinkInk_gray4.ino b/examples/ThinkInk_gray4/ThinkInk_gray4.ino index a6dfb1a..e8c58d3 100644 --- a/examples/ThinkInk_gray4/ThinkInk_gray4.ino +++ b/examples/ThinkInk_gray4/ThinkInk_gray4.ino @@ -38,6 +38,10 @@ ThinkInk_213_Grayscale4_MFGN display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, EPD_BUSY, EPD_SPI); +// 2.66" Grayscale Featherwing or Breakout (SSD1680) +// ThinkInk_266_Grayscale4_MFGN display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, EPD_BUSY, +// EPD_SPI); + // 2.9" Grayscale Featherwing or Breakout: //ThinkInk_290_Grayscale4_T5 display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, EPD_BUSY, // EPD_SPI); diff --git a/examples/ThinkInk_tricolor/ThinkInk_tricolor.ino b/examples/ThinkInk_tricolor/ThinkInk_tricolor.ino index 409fec5..9b548f3 100644 --- a/examples/ThinkInk_tricolor/ThinkInk_tricolor.ino +++ b/examples/ThinkInk_tricolor/ThinkInk_tricolor.ino @@ -43,8 +43,8 @@ ThinkInk_213_Tricolor_RW display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, EPD_BUSY, EPD_SPI); // 2.13" Tricolor EPD with SSD1680Z chipset -//ThinkInk_213_Tricolor_MFGNR display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, -// EPD_BUSY, EPD_SPI); +// ThinkInk_213_Tricolor_MFGNR display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, +// EPD_BUSY, EPD_SPI); // 2.13" Tricolor EPD with IL0373 chipset // ThinkInk_213_Tricolor_Z16 display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, @@ -52,8 +52,8 @@ ThinkInk_213_Tricolor_RW display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, EPD_BUSY, // 2.66" Tricolor EPD with SSD1680Z chipset -//ThinkInk_266_Tricolor_MFGNR display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, -// EPD_BUSY, EPD_SPI); +// ThinkInk_266_Tricolor_MFGNR display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, +// EPD_BUSY, EPD_SPI); // 2.7" Tricolor Featherwing or Breakout with IL91874 chipset @@ -85,6 +85,10 @@ ThinkInk_213_Tricolor_RW display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, EPD_BUSY, // ThinkInk_420_Tricolor_Z21 display(EPD_DC, EPD_RESET, // EPD_CS, SRAM_CS, EPD_BUSY, EPD_SPI); +// 4.2" Tricolor EPD with SSD1683 chipset +// ThinkInk_420_Tricolor_MFGNR display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, +// EPD_BUSY, EPD_SPI); + void setup() { Serial.begin(115200); while (!Serial) { diff --git a/src/Adafruit_ThinkInk.h b/src/Adafruit_ThinkInk.h index 946a024..3c45a5c 100644 --- a/src/Adafruit_ThinkInk.h +++ b/src/Adafruit_ThinkInk.h @@ -21,6 +21,7 @@ #include "panels/ThinkInk_213_Tricolor_MFGNR.h" #include "panels/ThinkInk_213_Tricolor_RW.h" #include "panels/ThinkInk_213_Tricolor_Z16.h" +#include "panels/ThinkInk_266_Grayscale4_MFGN.h" #include "panels/ThinkInk_266_Tricolor_MFGNR.h" #include "panels/ThinkInk_270_Grayscale4_W3.h" #include "panels/ThinkInk_270_Tricolor_C44.h" diff --git a/src/panels/ThinkInk_266_Grayscale4_MFGN.h b/src/panels/ThinkInk_266_Grayscale4_MFGN.h new file mode 100644 index 0000000..341c485 --- /dev/null +++ b/src/panels/ThinkInk_266_Grayscale4_MFGN.h @@ -0,0 +1,175 @@ +#ifndef _THINKINK_266_GRAYSCALE4_MFGN_H +#define _THINKINK_266_GRAYSCALE4_MFGN_H + +// This file is #included by Adafruit_ThinkInk.h and does not need to +// #include anything else to pick up the EPD header or ink mode enum. + +// clang-format off + +static const uint8_t ti_266mfgn_gray4_init_code[] { + SSD1680_SW_RESET, 0, // soft reset + 0xFF, 100, // busy wait + SSD1680_DRIVER_CONTROL, 3, 0x27, 0x01, 0x00, // Driver output + SSD1680_DATA_MODE, 1, 0x03, // Ram data entry mode + SSD1680_WRITE_BORDER, 1, 0x04, // border color + + SSD1680_SET_RAMXCOUNT, 1, 1, + SSD1680_SET_RAMYCOUNT, 2, 0, 0, + + 0x3F, 1, 0x22, // ??? + SSD1680_GATE_VOLTAGE, 1, 0x17, // Set gate voltage + SSD1680_SOURCE_VOLTAGE, 3, 0x41, 0xAE, 0x32, // Set source voltage + SSD1680_WRITE_VCOM, 1, 0x28, // Vcom Voltage + + 0xFE // EOM +}; + +static const uint8_t ti_266mfgn_monopart_init_code[] { + SSD1680_SW_RESET, 0, // soft reset + 0xFF, 20, // busy wait + SSD1680_DRIVER_CONTROL, 3, 0x27, 0x01, 0x00, // Driver output + SSD1680_DATA_MODE, 1, 0x03, // Ram data entry mode + SSD1680_DISP_CTRL1, 2, 0x00, 0x80, // Display update + + SSD1680_SET_RAMXCOUNT, 1, 1, + SSD1680_SET_RAMYCOUNT, 2, 0, 0, + SSD1680_WRITE_BORDER, 1, 0x05, // border color + + 0x3F, 1, 0x22, // ??? + SSD1680_GATE_VOLTAGE, 1, 0x17, // Set gate voltage + SSD1680_SOURCE_VOLTAGE, 3, 0x41, 0x00, 0x32, // Set source voltage + SSD1680_WRITE_VCOM, 1, 0x36, // Vcom Voltage + 0xFE // EOM +}; + +static const uint8_t ti_266mfgn_monofull_init_code[] { + SSD1680_SW_RESET, 0, // soft reset + 0xFF, 20, // busy wait + SSD1680_DRIVER_CONTROL, 3, 0x27, 0x01, 0x00, // Driver output + SSD1680_DATA_MODE, 1, 0x03, // Ram data entry mode + SSD1680_DISP_CTRL1, 2, 0x00, 0x80, // Display update + + SSD1680_SET_RAMXCOUNT, 1, 1, + SSD1680_SET_RAMYCOUNT, 2, 0, 0, + SSD1680_WRITE_BORDER, 1, 0x05, // border color + + //0x3F, 1, 0x22, // End of LUT normal + //SSD1680_GATE_VOLTAGE, 1, 0x17, // Set gate voltage + //SSD1680_SOURCE_VOLTAGE, 3, 0x41, 0x00, 0x32, // Set source voltage + //SSD1680_WRITE_VCOM, 1, 0x36, // Vcom Voltage + + SSD1680_DISP_CTRL2, 1, 0x20, // Load LUT from OTP (default mono) + + 0xFE +}; + + + +static const uint8_t ti_266mfgn_monofull_lut_code[] = { + 0x32, 153, + 0x80, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, + 0x10, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, + 0x80, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, + 0x10, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x14, 0x8, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xA, 0xA, 0x0, 0xA, 0xA, + 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x14, 0x8, 0x0, 0x1, + 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x0, 0x0, 0x0, + 0xFE +}; + +static const uint8_t ti_266mfgn_monopart_lut_code[] = { + 0xFE // EOM +}; + +static const uint8_t ti_266mfgn_gray4_lut_code[] = { + 0x32, 233, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2A, 0x60, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, + 0x14, 0x00, 0x00, 0x1E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x05, 0x14, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x24, 0x22, 0x22, 0x22, 0x23, 0x32, 0x00, 0x00, 0x00, + + 0xFE // EOM +}; + +// clang-format on + +class ThinkInk_266_Grayscale4_MFGN : public Adafruit_SSD1680 { + public: + ThinkInk_266_Grayscale4_MFGN(int16_t SID, int16_t SCLK, int16_t DC, + int16_t RST, int16_t CS, int16_t SRCS, + int16_t MISO, int16_t BUSY = -1) + : Adafruit_SSD1680(296, 152, SID, SCLK, DC, RST, CS, SRCS, MISO, BUSY){}; + + ThinkInk_266_Grayscale4_MFGN(int16_t DC, int16_t RST, int16_t CS, + int16_t SRCS, int16_t BUSY = -1, + SPIClass* spi = &SPI) + : Adafruit_SSD1680(296, 152, DC, RST, CS, SRCS, BUSY, spi){}; + + void begin(thinkinkmode_t mode = THINKINK_GRAYSCALE4) { + Adafruit_SSD1680::begin(true); + + inkmode = mode; // Preserve ink mode for ImageReader or others + _xram_offset = 0; + + if (mode == THINKINK_GRAYSCALE4) { + setColorBuffer(1, false); // layer 0 inverted + setBlackBuffer(0, false); // layer 1 inverted + + _epd_init_code = ti_266mfgn_gray4_init_code; + _epd_lut_code = ti_266mfgn_gray4_lut_code; + + layer_colors[EPD_WHITE] = 0b00; + layer_colors[EPD_BLACK] = 0b11; + layer_colors[EPD_RED] = 0b01; + layer_colors[EPD_GRAY] = 0b10; + layer_colors[EPD_LIGHT] = 0b01; + layer_colors[EPD_DARK] = 0b10; + + _display_update_val = 0xC7; + + } else if (mode == THINKINK_MONO) { + _epd_init_code = ti_266mfgn_monofull_init_code; + //_epd_lut_code = ti_266mfgn_monofull_lut_code; + //_epd_partial_init_code = ti_266mfgn_monopart_init_code; + //_epd_partial_lut_code = ti_266mfgn_monopart_lut_code; + setColorBuffer(0, true); // layer 0 uninverted + setBlackBuffer(0, true); // only one buffer + + layer_colors[EPD_WHITE] = 0b00; + layer_colors[EPD_BLACK] = 0b01; + layer_colors[EPD_RED] = 0b01; + layer_colors[EPD_GRAY] = 0b01; + layer_colors[EPD_LIGHT] = 0b00; + layer_colors[EPD_DARK] = 0b01; + + setRotation(0); + } + + default_refresh_delay = 1000; + + powerDown(); + } +}; + +#endif // _THINKINK_266_GRAYSCALE4_MFGN_H