Skip to content

Commit 12d2354

Browse files
committed
Route DisplayWrite throughout MVC
1 parent ca75bf0 commit 12d2354

File tree

7 files changed

+104
-15
lines changed

7 files changed

+104
-15
lines changed

src/Wippersnapper.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,6 +1688,17 @@ bool cbDecodeDisplayMsg(pb_istream_t *stream, const pb_field_t *field,
16881688
WS._displayController->Handle_Display_AddOrReplace(&msgAddReq);
16891689
// TODO: Add response handling and publishing here, for now it always
16901690
// returns true and doesnt publish back to the broker
1691+
} else if (field->tag ==
1692+
wippersnapper_signal_v1_DisplayRequest_display_write_tag) {
1693+
// Decode message into a DisplayAddRequest
1694+
wippersnapper_display_v1_DisplayWrite msgWrite =
1695+
wippersnapper_display_v1_DisplayWrite_init_zero;
1696+
if (!ws_pb_decode(stream, wippersnapper_display_v1_DisplayWrite_fields,
1697+
&msgWrite)) {
1698+
WS_DEBUG_PRINTLN("ERROR: Failure decoding DisplayWrite message!");
1699+
return false;
1700+
}
1701+
WS._displayController->Handle_Display_Write(&msgWrite);
16911702
}
16921703
return true;
16931704
}

src/components/display/controller.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,32 @@ bool DisplayController::Handle_Display_Remove(
8484
}
8585
WS_DEBUG_PRINTLN("[display] Could not remove display, not found!");
8686
return false;
87+
}
88+
89+
/*!
90+
@brief Handles a Display_Write message.
91+
@param msgWrite
92+
Pointer to a DisplayWrite message structure.
93+
@return True if the display write was successful, false otherwise.
94+
*/
95+
bool DisplayController::Handle_Display_Write(
96+
wippersnapper_display_v1_DisplayWrite *msgWrite) {
97+
// Get the driver instance for the display
98+
DisplayHardware *display = nullptr;
99+
for (auto &hw_instance : _hw_instances) {
100+
if (strcmp(hw_instance->getName(), msgWrite->name) == 0) {
101+
display = hw_instance;
102+
break;
103+
}
104+
}
105+
106+
// Early-out if display not found
107+
if (!display) {
108+
WS_DEBUG_PRINTLN("[display] Failed to write, driver not found!");
109+
return false;
110+
}
111+
112+
// Write the message to the display
113+
display->writeMessage(msgWrite->message);
114+
return true;
87115
}

src/components/display/controller.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ class DisplayController {
3434
bool Handle_Display_AddOrReplace(
3535
wippersnapper_display_v1_DisplayAddOrReplace *msgAdd);
3636
bool Handle_Display_Remove(wippersnapper_display_v1_DisplayRemove *msgRemove);
37-
// bool Handle_Display_Write(...);
37+
bool Handle_Display_Write(wippersnapper_display_v1_DisplayWrite *msgWrite);
38+
3839
private:
3940
std::vector<DisplayHardware *>
4041
_hw_instances; ///< Holds pointers to DisplayHardware instances

src/components/display/drivers/dispDrvBase.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,17 @@ class dispDrvBase {
3131
// Destructor implementation (if we need one)
3232
};
3333

34-
// Virtual function to be implemented by derived classes
3534
virtual bool begin(thinkinkmode_t mode, bool reset = true);
3635

36+
virtual void writeMessage(const char *message) = 0;
37+
3738
protected:
3839
int16_t _pin_dc;
3940
int16_t _pin_rst;
4041
int16_t _pin_cs;
4142
int16_t _pin_busy;
4243
int16_t _pin_sram_cs; // for optional EPD SRAM chip select
44+
uint8_t _text_sz = 1; ///< Text size for display messages
4345
};
4446

4547
#endif // WS_DISP_DRV_BASE_H

src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,55 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase {
4141
// Clear the display buffer
4242
_display->clearBuffer();
4343
_display->display();
44+
4445
return true;
4546
}
4647

48+
virtual void writeMessage(const char *message) override {
49+
if (_display == nullptr)
50+
return;
51+
52+
// Start with a fresh display buffer
53+
// and settings
54+
int16_t y_idx = 0;
55+
_display->clearDisplay();
56+
_display->setTextSize(_text_sz);
57+
_display->setTextColor(EPD_BLACK);
58+
_display->setCursor(0, y_idx);
59+
_display->display();
60+
61+
// Calculate the line height based on the text size (NOTE: base height is
62+
// 8px)
63+
int16_t line_height = 8 * _text_sz;
64+
uint16_t c_idx = 0;
65+
size_t msg_size = strlen(message);
66+
for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) {
67+
if (message[i] == '\\' && i + 1 < msg_size &&
68+
(message[i + 1] == 'n' || message[i + 1] == 'r')) {
69+
// Handle \r\n sequence as a single newline
70+
if (message[i + 1] == 'r' && i + 3 < msg_size &&
71+
message[i + 2] == '\\' && message[i + 3] == 'n') {
72+
// Skip to the next line
73+
y_idx += line_height;
74+
_display->setCursor(0, y_idx);
75+
i += 3;
76+
} else if (message[i + 1] == 'n') {
77+
// Skip to the next line
78+
y_idx += line_height;
79+
_display->setCursor(0, y_idx);
80+
i++;
81+
}
82+
} else if (message[i] == 0xC2 && message[i + 1] == 0xB0) {
83+
_display->write(char(248));
84+
_display->display();
85+
i++;
86+
} else {
87+
_display->print(message[i]);
88+
_display->display();
89+
}
90+
}
91+
}
92+
4793
private:
4894
ThinkInk_290_Grayscale4_EAAMFGN *_display;
4995
};

src/components/display/hardware.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,6 @@ bool DisplayHardware::beginEPD(
105105
return false;
106106
}
107107

108-
// Validate panel type
109-
if (config->panel ==
110-
wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED) {
111-
WS_DEBUG_PRINTLN("[display] Unsupported EPD panel type!");
112-
return false; // Unsupported panel type
113-
}
114-
115108
// Validate mode is a correct EPD mode
116109
if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_UNSPECIFIED) {
117110
WS_DEBUG_PRINTLN("[display] Unsupported EPD mode!");
@@ -168,17 +161,24 @@ bool DisplayHardware::beginEPD(
168161

169162
if (!_disp_drv_base->begin(epd_mode)) {
170163
WS_DEBUG_PRINTLN("[display] Failed to begin display driver!");
171-
delete _disp_drv_base; // Clean up if initialization failed
164+
delete _disp_drv_base;
172165
_disp_drv_base = nullptr;
173-
return false; // Failed to begin display driver
166+
return false;
174167
}
175168

176169
return true; // Configuration successful
177170
}
178171

179-
180172
/*!
181173
@brief Gets the name of the display hardware instance.
182174
@return The name of the display hardware instance.
183175
*/
184176
const char *DisplayHardware::getName() { return _name; }
177+
178+
void DisplayHardware::writeMessage(const char *message) {
179+
if (_disp_drv_base) {
180+
_disp_drv_base->writeMessage(message);
181+
} else {
182+
WS_DEBUG_PRINTLN("[display] No display driver initialized!");
183+
}
184+
}

src/components/display/hardware.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,14 @@ class DisplayHardware {
4444

4545
//
4646
// API for Adafruit_GFX that abstracts hardware functionality
47-
// NOTE: These methods are meant to be implemented within dispDrvBase and exposed within dispDrv driver instances
47+
// NOTE: These methods are meant to be implemented within dispDrvBase and
48+
// exposed within dispDrv driver instances
4849
//
49-
// TODO
50+
void writeMessage(const char *message);
5051

5152
private:
5253
const char *_name; ///< Identifies the hardware instance
5354
wippersnapper_display_v1_DisplayType _type; ///< Display type
54-
dispDrvBase *_disp_drv_base = nullptr; ///< Base display driver
55+
dispDrvBase *_disp_drv_base = nullptr; ///< Base display driver
5556
};
5657
#endif // WS_DISPLAY_HARDWARE_H

0 commit comments

Comments
 (0)