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