2525class dispDrvThinkInkGrayscale4T5 : public dispDrvBase {
2626public:
2727 /* !
28- @brief Constructor for the ThinkInk Grayscale 4-level EAAMFGN display
29- driver.
28+ @brief Constructor for the ThinkInk Grayscale T5 EPD display driver.
3029 @param dc
3130 Data/Command pin for the display.
3231 @param rst
@@ -44,13 +43,16 @@ class dispDrvThinkInkGrayscale4T5 : public dispDrvBase {
4443
4544 ~dispDrvThinkInkGrayscale4T5 () {
4645 if (_display) {
46+ // Clear the display buffer before deleting
47+ _display->clearBuffer ();
48+ _display->display ();
4749 delete _display;
4850 _display = nullptr ;
4951 }
5052 }
5153
5254 /* !
53- @brief Attempts to initialize the ThinkInk Grayscale 4-level EAAMFGN
55+ @brief Attempts to initialize the ThinkInk Grayscale 4 T5 EPD
5456 display driver.
5557 @param mode
5658 The ThinkInk mode to use for the display.
@@ -67,7 +69,6 @@ class dispDrvThinkInkGrayscale4T5 : public dispDrvBase {
6769 // Initialize the display
6870 _display->begin (mode);
6971 // Configure display settings
70- _text_sz = 3 ;
7172 _display->setTextSize (_text_sz);
7273 _display->setTextColor (EPD_BLACK);
7374 _display->setTextWrap (false );
@@ -80,6 +81,119 @@ class dispDrvThinkInkGrayscale4T5 : public dispDrvBase {
8081 return true ;
8182 }
8283
84+ /* !
85+ @brief Draws a status bar at the top of the display.
86+ @param io_username
87+ The Adafruit IO username to display on the status bar.
88+ */
89+ virtual void drawStatusBar (const char *io_username) override {
90+ if (!_display)
91+ return ;
92+
93+ // Clear the entire display buffer to remove splash screen
94+ _display->clearBuffer ();
95+
96+ // Draw status bar
97+ _display->fillRect (0 , 0 , _display->width (), STATUS_BAR_HEIGHT, EPD_BLACK);
98+ _display->fillRect (STATUS_BAR_BORDER, STATUS_BAR_BORDER,
99+ _display->width () - (2 * STATUS_BAR_BORDER),
100+ STATUS_BAR_HEIGHT - (2 * STATUS_BAR_BORDER), EPD_WHITE);
101+
102+ // Draw username on left side of the status bar
103+ _display->setTextSize (1 );
104+ _display->setTextColor (EPD_BLACK);
105+ _display->setCursor (5 , 6 );
106+ _display->print (io_username);
107+
108+ // Calculate status bar icon positions and center vertically
109+ _statusbar_icons_y =
110+ STATUS_BAR_BORDER +
111+ ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / 2 );
112+ _statusbar_icon_battery_x =
113+ _display->width () - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_MARGIN;
114+ _statusbar_icon_wifi_x = _statusbar_icon_battery_x - STATUS_BAR_ICON_SZ -
115+ STATUS_BAR_ICON_SPACING;
116+ _statusbar_icon_cloud_x =
117+ _statusbar_icon_wifi_x - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_SPACING;
118+ // Draw icons on right side of the status bar
119+ _display->drawBitmap (_statusbar_icon_cloud_x, _statusbar_icons_y,
120+ epd_bmp_cloud_online, STATUS_BAR_ICON_SZ,
121+ STATUS_BAR_ICON_SZ, EPD_BLACK);
122+ _display->drawBitmap (_statusbar_icon_wifi_x, _statusbar_icons_y,
123+ epd_bmp_wifi_full, STATUS_BAR_ICON_SZ,
124+ STATUS_BAR_ICON_SZ, EPD_BLACK);
125+ _display->drawBitmap (_statusbar_icon_battery_x, _statusbar_icons_y,
126+ epd_bmp_bat_full, STATUS_BAR_ICON_SZ,
127+ STATUS_BAR_ICON_SZ, EPD_BLACK);
128+
129+ _display->display ();
130+ }
131+
132+ /* !
133+ @brief Updates the status bar with current information (battery level,
134+ connectivity status, etc).
135+ @param rssi
136+ The current WiFi RSSI (signal strength) in dB.
137+ @param bat
138+ The current battery level as a percentage (0-100).
139+ @param mqtt_status
140+ The current MQTT connection status.
141+ */
142+ void updateStatusBar (int8_t rssi, uint8_t bat, bool mqtt_status) override {
143+ if (!_display)
144+ return ;
145+
146+ // Only update wifi icon if the RSSI has changed significantly (+/- 5dB)
147+ bool update_rssi = abs (rssi - _statusbar_rssi) >= 5 ;
148+ // Only update cloud icon if MQTT status has changed
149+ bool update_mqtt = mqtt_status != _statusbar_mqtt_connected;
150+
151+ // No need to update if nothing has changed
152+ if (!update_rssi && !update_mqtt)
153+ return ;
154+
155+ if (update_mqtt) {
156+ // updating the RSSI occurs too frequently to be practical
157+ _display->fillRect (_statusbar_icon_cloud_x, _statusbar_icons_y,
158+ STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_WHITE);
159+ if (mqtt_status) {
160+ _display->drawBitmap (_statusbar_icon_cloud_x, _statusbar_icons_y,
161+ epd_bmp_cloud_online, STATUS_BAR_ICON_SZ,
162+ STATUS_BAR_ICON_SZ, EPD_BLACK);
163+ } else {
164+ _display->drawBitmap (_statusbar_icon_cloud_x, _statusbar_icons_y,
165+ epd_bmp_cloud_offline, STATUS_BAR_ICON_SZ,
166+ STATUS_BAR_ICON_SZ, EPD_BLACK);
167+ }
168+ _statusbar_mqtt_connected = mqtt_status;
169+ }
170+
171+ // Update WiFi icon only if RSSI has changed significantly (+/-3dB)
172+ if (update_rssi) {
173+ const unsigned char *wifi_icon = epd_bmp_wifi_no_signal;
174+ if (rssi >= -50 ) {
175+ wifi_icon = epd_bmp_wifi_full;
176+ } else if (rssi < -50 && rssi >= -60 ) {
177+ wifi_icon = epd_bmp_wifi_fair;
178+ } else if (rssi < -60 && rssi >= -70 ) {
179+ wifi_icon = epd_bmp_wifi_weak;
180+ } else if (rssi < -70 && rssi >= -80 ) {
181+ wifi_icon = epd_bmp_wifi_no_signal;
182+ } else {
183+ wifi_icon = epd_bmp_wifi_no_signal;
184+ }
185+ // Clear and draw the new WiFi icon, based on RSSI
186+ _display->fillRect (_statusbar_icon_wifi_x, _statusbar_icons_y,
187+ STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_WHITE);
188+ _display->drawBitmap (_statusbar_icon_wifi_x, _statusbar_icons_y,
189+ wifi_icon, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ,
190+ EPD_BLACK);
191+ _statusbar_rssi = rssi;
192+ }
193+
194+ _display->display ();
195+ }
196+
83197 /* !
84198 @brief Writes a message to the display.
85199 @param message
@@ -91,16 +205,22 @@ class dispDrvThinkInkGrayscale4T5 : public dispDrvBase {
91205 if (_display == nullptr )
92206 return ;
93207
94- // Start with a fresh display buffer
95- _display->clearBuffer ();
96- int16_t y_idx = 0 ;
208+ // Clear only the area below the status bar
209+ _display->fillRect (0 , STATUS_BAR_HEIGHT, _display->width (),
210+ _display->height () - STATUS_BAR_HEIGHT, EPD_WHITE);
211+ // Add padding between status bar and text content
212+ int16_t y_idx = STATUS_BAR_HEIGHT + 4 ;
97213 _display->setCursor (0 , y_idx);
98214
99215 // Calculate the line height based on the text size (NOTE: base height is
100216 // 8px)
101217 int16_t line_height = 8 * _text_sz;
102218 uint16_t c_idx = 0 ;
103219 size_t msg_size = strlen (message);
220+
221+ // Reset the text size to the configured value before we write
222+ _display->setTextSize (_text_sz);
223+
104224 for (size_t i = 0 ; i < msg_size && c_idx < msg_size; i++) {
105225 if (y_idx + line_height > _height)
106226 break ;
0 commit comments