1+ /* !
2+ * @file src/components/display/drivers/ThinkInk_290_Grayscale4_T5.h
3+ *
4+ * Driver for ThinkInk 2.9" Grayscale 4-level T5 display (present on the
5+ * pre-2025 version of the Adafruit MagTag)
6+ *
7+ * Adafruit invests time and resources providing this open source code,
8+ * please support Adafruit and open-source hardware by purchasing
9+ * products from Adafruit!
10+ *
11+ * Copyright (c) Brent Rubell 2025 for Adafruit Industries.
12+ *
13+ * BSD license, all text here must be included in any redistribution.
14+ *
15+ */
16+ #ifndef WS_DRV_THINKINK_GRAYSCALE4_T5_H
17+ #define WS_DRV_THINKINK_GRAYSCALE4_T5_H
18+
19+ #include " dispDrvBase.h"
20+
21+ /* !
22+ @brief Driver for a ThinkInk 2.9" Grayscale 4-level T5 display (pre-2025 version of the Adafruit MagTag).
23+ */
24+ class dispDrvThinkInkGrayscale4T5 : public dispDrvBase {
25+ public:
26+ /* !
27+ @brief Constructor for the ThinkInk Grayscale 4-level EAAMFGN display
28+ driver.
29+ @param dc
30+ Data/Command pin for the display.
31+ @param rst
32+ Reset pin for the display.
33+ @param cs
34+ Chip Select pin for the display.
35+ @param sram_cs
36+ Optional SRAM Chip Select pin for E-Ink displays that support it.
37+ @param busy
38+ Optional Busy pin for the display.
39+ */
40+ dispDrvThinkInkGrayscale4T5 (int16_t dc, int16_t rst, int16_t cs,
41+ int16_t sram_cs = -1 , int16_t busy = -1 )
42+ : dispDrvBase(dc, rst, cs, sram_cs, busy), _display(nullptr ) {}
43+
44+ ~dispDrvThinkInkGrayscale4T5 () {
45+ if (_display) {
46+ delete _display;
47+ _display = nullptr ;
48+ }
49+ }
50+
51+ /* !
52+ @brief Attempts to initialize the ThinkInk Grayscale 4-level EAAMFGN
53+ display driver.
54+ @param mode
55+ The ThinkInk mode to use for the display.
56+ @param reset
57+ Whether to reset the display before initialization.
58+ @return True if the display was initialized successfully, false otherwise.
59+ */
60+ bool begin (thinkinkmode_t mode, bool reset = true ) override {
61+ _display = new ThinkInk_290_Grayscale4_T5 (_pin_dc, _pin_rst, _pin_cs,
62+ _pin_sram_cs, _pin_busy);
63+ if (!_display)
64+ return false ; // Allocation failed
65+
66+ // Initialize the display
67+ _display->begin (mode);
68+ // Configure display settings
69+ _text_sz = 3 ;
70+ _display->setTextSize (_text_sz);
71+ _display->setTextColor (EPD_BLACK);
72+ _display->setTextWrap (false );
73+ _height = _display->height ();
74+ _width = _display->width ();
75+ // Clear the display buffer
76+ _display->clearBuffer ();
77+ _display->display ();
78+
79+ return true ;
80+ }
81+
82+ /* !
83+ @brief Writes a message to the display.
84+ @param message
85+ The message to write to the display.
86+ @note This method overrides the base class method to provide specific
87+ functionality for the Think Ink Grayscale 4 EAAMGFGN driver.
88+ */
89+ virtual void writeMessage (const char *message) override {
90+ if (_display == nullptr )
91+ return ;
92+
93+ // Start with a fresh display buffer
94+ _display->clearBuffer ();
95+ int16_t y_idx = 0 ;
96+ _display->setCursor (0 , y_idx);
97+
98+ // Calculate the line height based on the text size (NOTE: base height is
99+ // 8px)
100+ int16_t line_height = 8 * _text_sz;
101+ uint16_t c_idx = 0 ;
102+ size_t msg_size = strlen (message);
103+ for (size_t i = 0 ; i < msg_size && c_idx < msg_size; i++) {
104+ if (y_idx + line_height > _height)
105+ break ;
106+ if (message[i] == ' \\ ' && i + 1 < msg_size &&
107+ (message[i + 1 ] == ' n' || message[i + 1 ] == ' r' )) {
108+ // Handle \r\n sequence as a single newline
109+ if (message[i + 1 ] == ' r' && i + 3 < msg_size &&
110+ message[i + 2 ] == ' \\ ' && message[i + 3 ] == ' n' ) {
111+ // Skip to the next line
112+ if (y_idx + line_height > _height)
113+ break ;
114+ y_idx += line_height;
115+ _display->setCursor (0 , y_idx);
116+ i += 3 ;
117+ } else if (message[i + 1 ] == ' n' ) {
118+ // Skip to the next line
119+ if (y_idx + line_height > _height)
120+ break ;
121+ y_idx += line_height;
122+ _display->setCursor (0 , y_idx);
123+ i++;
124+ }
125+ } else if (message[i] == 0xC2 && message[i + 1 ] == 0xB0 ) {
126+ _display->write (char (248 ));
127+ i++;
128+ } else {
129+ _display->print (message[i]);
130+ }
131+ }
132+ _display->display ();
133+ }
134+
135+ private:
136+ ThinkInk_290_Grayscale4_T5 *_display;
137+ };
138+
139+ #endif // WS_DRV_THINKINK_GRAYSCALE4_T5_H
0 commit comments