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