Skip to content

Commit 9fd844e

Browse files
committed
Complete: EPD/MagTag implementation and test integration
1 parent 6e5e4bc commit 9fd844e

File tree

24 files changed

+151
-114
lines changed

24 files changed

+151
-114
lines changed

src/components/display/controller.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ void DisplayController::update(int32_t rssi, bool is_connected) {
159159
for (DisplayHardware *hw_instance : _hw_instances) {
160160
// Note: For now, battery is always 100% as we don't have a way to read it
161161
// yet.
162+
WS_DEBUG_PRINTLN("[display] Updating status bar...");
162163
hw_instance->updateStatusBar(rssi, 100, is_connected);
163164
}
164165

src/components/display/drivers/dispDrvSt7789.h

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ class dispDrvSt7789 : public dispDrvBase {
127127
} else if (_width == 135 && _height == 240) {
128128
_display->drawBitmap(0, 0, tft_bmp_logo_240135, 240, 135, ST77XX_WHITE);
129129
} else {
130-
// Unsupported resolution
130+
// Unsupported resolution detected, skip splash screen
131131
return;
132132
}
133133

@@ -156,21 +156,26 @@ class dispDrvSt7789 : public dispDrvBase {
156156

157157
// Calculate icon positions (rightmost side of status bar), center
158158
// vertically
159-
_statusbar_icons_y = (ST7789_STATUSBAR_HEIGHT - ST7789_STATUSBAR_ICON_SZ) / 2;
159+
_statusbar_icons_y =
160+
(ST7789_STATUSBAR_HEIGHT - ST7789_STATUSBAR_ICON_SZ) / 2;
160161
_statusbar_icon_battery_x = _display->width() - ST7789_STATUSBAR_ICON_SZ -
161-
ST7789_STATUSBAR_ICON_MARGIN;
162-
_statusbar_icon_wifi_x = _statusbar_icon_battery_x - ST7789_STATUSBAR_ICON_SZ - ST7789_STATUSBAR_ICON_SPACING;
163-
_statusbar_icon_cloud_x = _statusbar_icon_wifi_x - ST7789_STATUSBAR_ICON_SZ - ST7789_STATUSBAR_ICON_SPACING;
162+
ST7789_STATUSBAR_ICON_MARGIN;
163+
_statusbar_icon_wifi_x = _statusbar_icon_battery_x -
164+
ST7789_STATUSBAR_ICON_SZ -
165+
ST7789_STATUSBAR_ICON_SPACING;
166+
_statusbar_icon_cloud_x = _statusbar_icon_wifi_x -
167+
ST7789_STATUSBAR_ICON_SZ -
168+
ST7789_STATUSBAR_ICON_SPACING;
164169
// Draw icons
165-
_display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_online,
166-
ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ,
167-
ST77XX_BLACK);
168-
_display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y, epd_bmp_wifi_full,
169-
ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ,
170-
ST77XX_BLACK);
171-
_display->drawBitmap(_statusbar_icon_battery_x, _statusbar_icons_y, epd_bmp_bat_full,
172-
ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ,
173-
ST77XX_BLACK);
170+
_display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y,
171+
epd_bmp_cloud_online, ST7789_STATUSBAR_ICON_SZ,
172+
ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK);
173+
_display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y,
174+
epd_bmp_wifi_full, ST7789_STATUSBAR_ICON_SZ,
175+
ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK);
176+
_display->drawBitmap(_statusbar_icon_battery_x, _statusbar_icons_y,
177+
epd_bmp_bat_full, ST7789_STATUSBAR_ICON_SZ,
178+
ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK);
174179
}
175180

176181
/*!
@@ -198,16 +203,17 @@ class dispDrvSt7789 : public dispDrvBase {
198203

199204
if (update_mqtt) {
200205
// Clear and draw the new cloud icon, based on MQTT connection status
201-
_display->fillRect(_statusbar_icon_cloud_x, _statusbar_icons_y, ST7789_STATUSBAR_ICON_SZ,
202-
ST7789_STATUSBAR_ICON_SZ, ST77XX_WHITE);
206+
_display->fillRect(_statusbar_icon_cloud_x, _statusbar_icons_y,
207+
ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ,
208+
ST77XX_WHITE);
203209
if (mqtt_status) {
204-
_display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_online,
205-
ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ,
206-
ST77XX_BLACK);
210+
_display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y,
211+
epd_bmp_cloud_online, ST7789_STATUSBAR_ICON_SZ,
212+
ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK);
207213
} else {
208-
_display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_offline,
209-
ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ,
210-
ST77XX_BLACK);
214+
_display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y,
215+
epd_bmp_cloud_offline, ST7789_STATUSBAR_ICON_SZ,
216+
ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK);
211217
}
212218
_statusbar_mqtt_connected = mqtt_status;
213219
}
@@ -227,9 +233,11 @@ class dispDrvSt7789 : public dispDrvBase {
227233
wifi_icon = epd_bmp_wifi_no_signal;
228234
}
229235
// Clear and draw the new WiFi icon, based on RSSI
230-
_display->fillRect(_statusbar_icon_wifi_x, _statusbar_icons_y, ST7789_STATUSBAR_ICON_SZ,
231-
ST7789_STATUSBAR_ICON_SZ, ST77XX_WHITE);
232-
_display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y, wifi_icon, ST7789_STATUSBAR_ICON_SZ,
236+
_display->fillRect(_statusbar_icon_wifi_x, _statusbar_icons_y,
237+
ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ,
238+
ST77XX_WHITE);
239+
_display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y,
240+
wifi_icon, ST7789_STATUSBAR_ICON_SZ,
233241
ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK);
234242
_statusbar_rssi = rssi;
235243
}

src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
20 ///< Height of the status bar in pixels, assumes 16px icons
2323
#define STATUS_BAR_BORDER 1 ///< Border around the status bar in pixels
2424
#define STATUS_BAR_ICON_SZ 16 ///< Size of status bar icons in pixels
25-
#define STATUS_BAR_ICON_SPACING 4 ///< Spacing between status bar icons in pixels
26-
#define STATUS_BAR_ICON_MARGIN 5 ///< Margin from edge of display to status bar icons in pixels
25+
#define STATUS_BAR_ICON_SPACING \
26+
4 ///< Spacing between status bar icons in pixels
27+
#define STATUS_BAR_ICON_MARGIN \
28+
5 ///< Margin from edge of display to status bar icons in pixels
2729

2830
/*!
2931
@brief Driver for a ThinkInk 2.9" Grayscale 4-level EAAMFGN display.
@@ -73,7 +75,6 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase {
7375
// Initialize the display
7476
_display->begin(mode);
7577
// Configure display settings
76-
_text_sz = 3;
7778
_display->setTextSize(_text_sz);
7879
_display->setTextColor(EPD_BLACK);
7980
_display->setTextWrap(false);
@@ -116,16 +117,24 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase {
116117
_display->print(io_username);
117118

118119
// Calculate status bar icon positions and center vertically
119-
_statusbar_icons_y = STATUS_BAR_BORDER + ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / 2);
120-
_statusbar_icon_battery_x = _display->width() - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_MARGIN;
121-
_statusbar_icon_wifi_x = _statusbar_icon_battery_x - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_SPACING;
122-
_statusbar_icon_cloud_x = _statusbar_icon_wifi_x - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_SPACING;
120+
_statusbar_icons_y =
121+
STATUS_BAR_BORDER +
122+
((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / 2);
123+
_statusbar_icon_battery_x =
124+
_display->width() - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_MARGIN;
125+
_statusbar_icon_wifi_x = _statusbar_icon_battery_x - STATUS_BAR_ICON_SZ -
126+
STATUS_BAR_ICON_SPACING;
127+
_statusbar_icon_cloud_x =
128+
_statusbar_icon_wifi_x - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_SPACING;
123129
// Draw icons on right side of the status bar
124-
_display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_online,
125-
STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK);
126-
_display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y, epd_bmp_wifi_full, STATUS_BAR_ICON_SZ,
130+
_display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y,
131+
epd_bmp_cloud_online, STATUS_BAR_ICON_SZ,
127132
STATUS_BAR_ICON_SZ, EPD_BLACK);
128-
_display->drawBitmap(_statusbar_icon_battery_x, _statusbar_icons_y, epd_bmp_bat_full, STATUS_BAR_ICON_SZ,
133+
_display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y,
134+
epd_bmp_wifi_full, STATUS_BAR_ICON_SZ,
135+
STATUS_BAR_ICON_SZ, EPD_BLACK);
136+
_display->drawBitmap(_statusbar_icon_battery_x, _statusbar_icons_y,
137+
epd_bmp_bat_full, STATUS_BAR_ICON_SZ,
129138
STATUS_BAR_ICON_SZ, EPD_BLACK);
130139

131140
_display->display();
@@ -145,21 +154,54 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase {
145154
if (!_display)
146155
return;
147156

148-
bool do_update = false;
157+
// Only update wifi icon if the RSSI has changed significantly (+/- 5dB)
158+
bool update_rssi = abs(rssi - _statusbar_rssi) >= 5;
159+
// Only update cloud icon if MQTT status has changed
160+
bool update_mqtt = mqtt_status != _statusbar_mqtt_connected;
149161

150-
// For EPD - redraws take 1-2 seconds, so only update the cloud state
162+
// No need to update if nothing has changed
163+
if (!update_rssi && !update_mqtt)
164+
return;
151165

152-
// Update cloud icon only if it changed state
153-
// Clear and draw the new cloud icon, based on MQTT connection status
154-
_display->fillRect(_statusbar_icon_cloud_x, _statusbar_icons_y, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ,
155-
EPD_WHITE);
156-
if (mqtt_status == 21) {
157-
_display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_online,
158-
STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK);
166+
if (update_mqtt) {
167+
// updating the RSSI occurs too frequently to be practical
168+
_display->fillRect(_statusbar_icon_cloud_x, _statusbar_icons_y,
169+
STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_WHITE);
170+
if (mqtt_status) {
171+
_display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y,
172+
epd_bmp_cloud_online, STATUS_BAR_ICON_SZ,
173+
STATUS_BAR_ICON_SZ, EPD_BLACK);
174+
} else {
175+
_display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y,
176+
epd_bmp_cloud_offline, STATUS_BAR_ICON_SZ,
177+
STATUS_BAR_ICON_SZ, EPD_BLACK);
178+
}
179+
_statusbar_mqtt_connected = mqtt_status;
180+
}
181+
182+
// Update WiFi icon only if RSSI has changed significantly (+/-3dB)
183+
if (update_rssi) {
184+
const unsigned char *wifi_icon = epd_bmp_wifi_no_signal;
185+
if (rssi >= -50) {
186+
wifi_icon = epd_bmp_wifi_full;
187+
} else if (rssi < -50 && rssi >= -60) {
188+
wifi_icon = epd_bmp_wifi_fair;
189+
} else if (rssi < -60 && rssi >= -70) {
190+
wifi_icon = epd_bmp_wifi_weak;
191+
} else if (rssi < -70 && rssi >= -80) {
192+
wifi_icon = epd_bmp_wifi_no_signal;
159193
} else {
160-
_display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_offline,
161-
STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK);
194+
wifi_icon = epd_bmp_wifi_no_signal;
162195
}
196+
// Clear and draw the new WiFi icon, based on RSSI
197+
_display->fillRect(_statusbar_icon_wifi_x, _statusbar_icons_y,
198+
STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ,
199+
EPD_WHITE);
200+
_display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y,
201+
wifi_icon, STATUS_BAR_ICON_SZ,
202+
STATUS_BAR_ICON_SZ, EPD_BLACK);
203+
_statusbar_rssi = rssi;
204+
}
163205

164206
_display->display();
165207
}
@@ -178,14 +220,19 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase {
178220
// Clear only the area below the status bar
179221
_display->fillRect(0, STATUS_BAR_HEIGHT, _display->width(),
180222
_display->height() - STATUS_BAR_HEIGHT, EPD_WHITE);
181-
int16_t y_idx = STATUS_BAR_HEIGHT;
223+
// Add padding between status bar and text content
224+
int16_t y_idx = STATUS_BAR_HEIGHT + 4;
182225
_display->setCursor(0, y_idx);
183226

184227
// Calculate the line height based on the text size (NOTE: base height is
185228
// 8px)
186229
int16_t line_height = 8 * _text_sz;
187230
uint16_t c_idx = 0;
188231
size_t msg_size = strlen(message);
232+
233+
// Reset the text size to the configured value before we write
234+
_display->setTextSize(_text_sz);
235+
189236
for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) {
190237
if (y_idx + line_height > _height)
191238
break;

src/components/display/hardware.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ bool DisplayHardware::beginEPD(
248248
_drvDisp = nullptr;
249249
return false;
250250
}
251+
WS_DEBUG_PRINTLN("[display] Text Magnification: ");
252+
WS_DEBUG_PRINTLN(config->text_size);
253+
_drvDisp->setTextSize(config->text_size);
251254

252255
if (!_drvDisp->begin(epd_mode)) {
253256
WS_DEBUG_PRINTLN("[display] Failed to begin display driver!");
@@ -341,13 +344,8 @@ bool DisplayHardware::beginTft(
341344

342345
_drvDisp->setWidth(config->width);
343346
_drvDisp->setHeight(config->height);
344-
WS_DEBUG_PRINT("[display] TFT Resolution: ");
345-
WS_DEBUG_PRINT(config->width);
346-
WS_DEBUG_PRINT("x");
347-
WS_DEBUG_PRINTLN(config->height);
348347
_drvDisp->setRotation(config->rotation);
349-
WS_DEBUG_PRINT("[display] TFT Rotation: ");
350-
WS_DEBUG_PRINTLN(config->rotation);
348+
_drvDisp->setTextSize(config->text_size);
351349
_drvDisp->begin();
352350

353351
return true;

src/wippersnapper/description/v1/description.pb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* Automatically generated nanopb constant definitions */
2-
/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */
2+
/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */
33

44
#include "wippersnapper/description/v1/description.pb.h"
55
#if PB_PROTO_HEADER_VERSION != 40

src/wippersnapper/description/v1/description.pb.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* Automatically generated nanopb header */
2-
/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */
2+
/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */
33

44
#ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED
55
#define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED

src/wippersnapper/display/v1/display.pb.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* Automatically generated nanopb constant definitions */
2-
/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */
2+
/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */
33

44
#include "wippersnapper/display/v1/display.pb.h"
55
#if PB_PROTO_HEADER_VERSION != 40
@@ -9,9 +9,6 @@
99
PB_BIND(wippersnapper_display_v1_EpdSpiConfig, wippersnapper_display_v1_EpdSpiConfig, AUTO)
1010

1111

12-
PB_BIND(wippersnapper_display_v1_EPDWriteOptions, wippersnapper_display_v1_EPDWriteOptions, AUTO)
13-
14-
1512
PB_BIND(wippersnapper_display_v1_EPDConfig, wippersnapper_display_v1_EPDConfig, AUTO)
1613

1714

0 commit comments

Comments
 (0)