muwerk mupplet Display Library
muwerk applets; mupplets: functional units that support specific hardware or reusable applications
Loading...
Searching...
No Matches
display_matrix_st7735.h
1// display_matrix_st7735.h - mupplet for ZFZ Matrix Display using ST7735
2
3#pragma once
4
5#include "muwerk.h"
6#include "helper/light_controller.h"
7#include "helper/mup_gfx_display.h"
8#include "hardware/st7735_matrix.h"
9
10namespace ustd {
11class DisplayMatrixST7735 : public MuppletGfxDisplay {
12 public:
13 static const char *version; // = "0.1.0";
14
15 private:
16 // hardware configuration
17 St7735Matrix display;
18 uint8_t blPin;
19 bool blActiveLogic = false;
20 uint8_t blChannel;
21 uint16_t blPwmRange;
22
23 // runtime
24 LightController light;
25
26 public:
50 DisplayMatrixST7735(String name, uint8_t hardware, uint8_t rotation, uint8_t csPin,
51 uint8_t dcPin, uint8_t rsPin = -1, uint8_t blPin = -1,
52 bool blActiveLogic = false, uint8_t blChannel = 0)
53 : MuppletGfxDisplay(name, MUPDISP_FEATURE_COLOR),
54 display(csPin, dcPin, rsPin, hardware, rotation), blPin(blPin),
55 blActiveLogic(blActiveLogic), blChannel(blChannel) {
56 current_bg = ST7735_BLACK;
57 current_fg = ST7735_WHITE;
58 }
59
65 void begin(Scheduler *_pSched, bool initialState = false) {
66 pSched = _pSched;
67 tID = pSched->add([this]() { this->loop(); }, name, 10000L);
68
69 pSched->subscribe(tID, name + "/display/#", [this](String top, String msg, String org) {
70 this->commandParser(top.substring(name.length() + 9), msg, name + "/display");
71 });
72 if (blPin != -1 && blPin != 0) {
73 // backlight control enabled - initialize hardware
74 initBacklightHardware();
75 // backlight control enabled - register commadn parser
76 pSched->subscribe(tID, name + "/light/#", [this](String top, String msg, String org) {
77 this->light.commandParser(top.substring(name.length() + 7), msg);
78 });
79 }
80
81 // initialize default values
82 current_font = 0;
83#ifdef USTD_FEATURE_PROGRAMPLAYER
84 programInit();
85#endif
86
87 // prepare hardware
88 display.begin();
89 display.setTextWrap(false);
90 display.setTextColor(current_fg, current_bg);
91
92 // start light controller
93 if (blPin != -1 && blPin != 0) {
94 light.begin(
95 [this](bool state, double level, bool control, bool notify) {
96 this->onLightControl(state, level, control, notify);
97 },
98 initialState);
99 } else {
100 display.enableDisplay(true);
101 }
102 }
103
104 private:
105 void loop() {
106 light.loop();
107#ifdef USTD_FEATURE_PROGRAMPLAYER
108 programLoop();
109#endif
110 }
111
112 void onLightControl(bool state, double level, bool control, bool notify) {
113 if (control) {
114 if (state && level == 1.0) {
115 // backlight is on at maximum brightness
116#ifdef __ESP32__
117 ledcWrite(blChannel, blActiveLogic ? blPwmRange : 0);
118#else
119 digitalWrite(blPin, blActiveLogic ? HIGH : LOW);
120#endif
121 } else if (state && level > 0.0) {
122 // backlight is dimmed
123 uint16_t bri = (uint16_t)(level * (double)blPwmRange);
124 if (bri) {
125 if (!blActiveLogic) {
126 bri = blPwmRange - bri;
127 }
128#ifdef __ESP32__
129 ledcWrite(blChannel, bri);
130#else
131 analogWrite(blPin, bri);
132#endif
133 } else {
134 light.forceState(false, 0.0);
135 onLightControl(false, 0.0, control, notify);
136 }
137 } else {
138 // backlight is off
139#ifdef __ESP32__
140 ledcWrite(blChannel, blActiveLogic ? 0 : blPwmRange);
141#else
142 digitalWrite(blPin, blActiveLogic ? LOW : HIGH);
143#endif
144 }
145 }
146 if (notify) {
147 pSched->publish(name + "/light/unitbrightness", String(level, 3));
148 pSched->publish(name + "/light/state", state ? "on" : "off");
149 }
150 }
151
152 // abstract methods implementation
153 virtual void getDimensions(int16_t &width, int16_t &height) {
154 width = display.width();
155 height = display.height();
156 }
157
158 virtual bool getTextWrap() {
159 return display.getTextWrap();
160 }
161
162 virtual void setTextWrap(bool wrap) {
163 display.setTextWrap(wrap);
164 }
165
166 virtual void setTextFont(uint8_t font, int16_t baseLineAdjustment) {
167 display.setFont(fonts[font]);
168 if (baseLineAdjustment) {
169 int16_t y = display.getCursorY();
170 display.setCursor(display.getCursorX(), y + baseLineAdjustment);
171 }
172 }
173
174 virtual void setTextColor(uint16_t fg, uint16_t bg) {
175 display.setTextColor(fg, bg);
176 }
177
178 virtual void getCursor(int16_t &x, int16_t &y) {
179 x = display.getCursorX();
180 y = display.getCursorY();
181 }
182
183 virtual void setCursor(int16_t x, int16_t y) {
184 display.setCursor(x, y);
185 }
186
187 virtual void displayClear(int16_t x, int16_t y, int16_t w, int16_t h) {
188 display.fillRect(x, y, w, h, display.getTextBackground());
189 }
190
191 virtual void displayClear(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t bg) {
192 display.fillRect(x, y, w, h, bg);
193 }
194
195 virtual void displayPrint(String content, bool ln = false) {
196 if (ln) {
197 display.println(content);
198 } else {
199 display.print(content);
200 }
201 }
202
203 virtual bool displayFormat(int16_t x, int16_t y, int16_t w, int16_t align, String content,
204 uint8_t font, uint16_t color, uint16_t bg) {
205 display.setFont(fonts[font]);
206 display.setTextColor(color, bg);
207 bool ret = display.printFormatted(x, y, w, align, content, sizes[font].baseLine,
208 sizes[font].yAdvance);
209 display.setTextColor(current_fg, current_bg);
210 display.setFont(fonts[current_font]);
211 return ret;
212 }
213
214#ifdef USTD_FEATURE_PROGRAMPLAYER
215 virtual bool initNextCharDimensions(ProgramItem &item) {
216 while (charPos < item.content.length()) {
217 int16_t minx = 0x7FFF, miny = 0x7FFF, maxx = -1, maxy = -1;
218 int16_t x = 0, y = sizes[item.font].baseLine;
219 display.getCharBounds(item.content[charPos], &x, &y, &minx, &miny, &maxx, &maxy);
220 if (maxx >= minx) {
221 charX = x;
222 charY = sizes[item.font].yAdvance;
223 if (item.content[charPos] == ' ') {
224 lastPos += charX;
225 } else {
226 return true;
227 }
228 } else if (item.content[charPos] == ' ') {
229 lastPos += charX;
230 }
231 // char is not printable
232 ++charPos;
233 }
234 // end of string
235 return false;
236 }
237#endif
238
239 // implementation
240 void initBacklightHardware() {
241#if defined(__ESP32__)
242 pinMode(blPin, OUTPUT);
243// use first channel of 16 channels (started from zero)
244#define LEDC_TIMER_BITS 10
245// use 5000 Hz as a LEDC base frequency
246#define LEDC_BASE_FREQ 5000
247 ledcSetup(blChannel, LEDC_BASE_FREQ, LEDC_TIMER_BITS);
248 ledcAttachPin(blPin, blChannel);
249#else
250 pinMode(blPin, OUTPUT);
251#endif
252#ifdef __ESP__
253 blPwmRange = 1023;
254#else
255 blPwmRange = 255;
256#endif
257 }
258
259 void getTextDimensions(uint8_t font, const char *content, int16_t &width, int16_t &height) {
260 if (!content || !*content) {
261 width = 0;
262 height = 0;
263 return;
264 }
265 int16_t x, y;
266 uint16_t w, h;
267 uint8_t old_font = current_font;
268 bool old_wrap = display.getTextWrap();
269 display.setFont(fonts[font]);
270 display.setTextWrap(false);
271 display.getTextBounds(content, 0, sizes[font].baseLine, &x, &y, &w, &h);
272 display.setTextWrap(old_wrap);
273 display.setFont(fonts[old_font]);
274 width = (int16_t)w;
275 height = (int16_t)h;
276 }
277};
278
279} // namespace ustd
The muwerk namespace.
Definition: display_digits_max72xx.h:10