muwerk mupplet Display Library
muwerk applets; mupplets: functional units that support specific hardware or reusable applications
Loading...
Searching...
No Matches
max72xx_digits.h
1// max72xx_digits.h - 7/14/16 segment digits controlled by MAX7219 or MAX7221 module driver
2
3#pragma once
4
5#include "max72xx.h"
6#include "mupplet_core.h"
7
8namespace ustd {
9
10static const uint8_t digitTable7Seg[] PROGMEM = {
11 B01111110, // 0
12 B00110000, // 1
13 B01101101, // 2
14 B01111001, // 3
15 B00110011, // 4
16 B01011011, // 5
17 B01011111, // 6
18 B01110000, // 7
19 B01111111, // 8
20 B01111011 // 9
21};
22
23static const uint8_t charTable7Seg[] PROGMEM = {
24 B01110111, // A
25 B00011111, // B
26 B00001101, // C
27 B00111101, // D
28 B01001111, // E
29 B01000111, // F
30 B01011110, // G
31 B00110111, // H
32 B00000110, // I
33 B00111100, // J
34 B00000111, // K
35 B00001110, // L
36 B01110110, // M
37 B00010101, // N
38 B00011101, // O
39 B01100111, // P
40 B11101110, // Q
41 B00000101, // R
42 B01011011, // S
43 B00001111, // T
44 B00111110, // U
45 B00011100, // V
46 B00011100, // W
47 B01001001, // X
48 B00111011, // Y
49 B01101101 // Z
50};
51
52#define MAX72XX_DP B10000000
53#define MAX72XX_SPACE B00000000
54#define MAX72XX_EXCLAMATION B10110000
55#define MAX72XX_QUOTES B00100010
56#define MAX72XX_DASH B00000001
57#define MAX72XX_EQUALS B00001001
58#define MAX72XX_UNDERSCORE B00001000
59#define MAX72XX_PAROPEN B01001110
60#define MAX72XX_PARCLOSE B01111000
61
70class Max72xxDigits : public Print {
71 private:
72 // hardware configuration
73 Max72XX driver;
74
75 // runtime - pixel and module logic
76 uint8_t length;
77 uint8_t bitmapSize;
78 uint8_t *bitmap;
79 uint8_t *outputBuffer;
80 int16_t _width;
81 int16_t _height;
82 int16_t cursor_x;
83 int16_t cursor_y;
84 bool wrap;
85
86 public:
94 Max72xxDigits(uint8_t csPin, uint8_t hDisplays = 1, uint8_t vDisplays = 1, uint8_t length = 8)
95 : driver(csPin, hDisplays * vDisplays), length(length > 8 ? 8 : length) {
96 bitmapSize = hDisplays * vDisplays * length;
97 bitmap = (uint8_t *)malloc(bitmapSize + (hDisplays * vDisplays * 2));
98 outputBuffer = bitmap + bitmapSize;
99 _width = hDisplays * length;
100 _height = vDisplays;
101 cursor_x = 0;
102 cursor_y = 0;
103 wrap = true;
104 }
105
108 void begin() {
109 if (bitmap != nullptr) {
110 // Initialize hardware
111 driver.begin();
112 driver.setTestMode(false);
113 driver.setScanLimit(length);
114 driver.setDecodeMode(B00000000);
115
116 // Clear the display
117 fillScreen(0);
118 write();
119 }
120 }
121
126 inline void setPowerSave(bool powersave) {
127 driver.setPowerSave(powersave);
128 }
129
133 inline void setIntensity(uint8_t intensity) {
134 driver.setIntensity(intensity);
135 }
136
141 inline void setTestMode(bool testmode) {
142 driver.setTestMode(testmode);
143 }
144
149 void setCursor(int16_t x, int16_t y) {
150 cursor_x = x;
151 cursor_y = y;
152 }
153
157 inline void setCursorX(int16_t x) {
158 cursor_x = x;
159 }
160
164 inline void setCursorY(int16_t y) {
165 cursor_y = y;
166 }
167
172 void setTextWrap(bool w) {
173 wrap = w;
174 }
175
184 void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint8_t pattern = B00000000) {
185 x = x < 0 ? 0 : x >= _width ? _width - 1 : x;
186 y = y < 0 ? 0 : y >= _height ? _height - 1 : y;
187 w = w < 0 ? 0 : w >= _width - x ? _width - x : w;
188 h = h < 0 ? 0 : h >= _height - y ? _height - y : h;
189
190 for (int16_t yy = y; yy < y + h; yy++) {
191 memset(bitmap + yy * _width + x, pattern, w);
192 }
193 }
194
208 bool printFormatted(int16_t x, int16_t y, int16_t w, int16_t align, String content) {
209 uint8_t shadowBuffer[8];
210 x = x < 0 ? 0 : x >= _width ? _width - 1 : x;
211 y = y < 0 ? 0 : y >= _height ? _height - 1 : y;
212 w = w < 0 ? 0 : w >= _width - x ? _width - x : w;
213 memset(bitmap + y * _width + x, B00000000, w);
214 uint8_t *pDst = shadowBuffer;
215 const unsigned char *pSrc = (unsigned char *)content.c_str();
216 while (pDst < shadowBuffer + 8 && *pSrc) {
217 if (*pSrc < 32) {
218 pDst--;
219 } else if (*pSrc == '.' || *pSrc == ',') {
220 if (pDst == shadowBuffer) {
221 *pDst = MAX72XX_DP;
222 } else {
223 pDst--;
224 *pDst |= MAX72XX_DP;
225 }
226 } else {
227 *pDst = mapchar(*pSrc);
228 }
229 pSrc++;
230 pDst++;
231 }
232 int16_t size = pDst - shadowBuffer;
233 int16_t offs = 0;
234 int16_t newx = x;
235 pDst = bitmap + (y * length) + x; // fist position of the destination slot
236 switch (align) {
237 default:
238 case 0:
239 // left
240 memcpy(pDst, shadowBuffer, min(w, size));
241 // set cursor after last printed character
242 newx = x + min(w, size);
243 break;
244 case 1:
245 // center
246 if (w < size) {
247 // string is larger than slot size - display only middle part
248 offs = (size - w) / 2;
249 memcpy(pDst, shadowBuffer + offs, w);
250 newx = x + size - offs;
251 } else {
252 // string is smaller than slot size - display center aligned
253 offs = (w - size) / 2;
254 memcpy(pDst + offs, shadowBuffer, size);
255 newx = x + size + offs;
256 }
257 break;
258 case 2:
259 // right
260 if (w < size) {
261 // string is larger than slot size - display only last part
262 offs = size - w;
263 memcpy(pDst, shadowBuffer + offs, w);
264 } else {
265 // string is smaller than slot size - display right aligned
266 offs = w - size;
267 memcpy(pDst + offs, shadowBuffer, size);
268 }
269 newx = x + w;
270 break;
271 }
272 // set cursor after last printed character
273 setCursor(min(_width, newx), y);
274 return *pSrc == 0 && size <= w;
275 }
276
283 void write() {
284 if (bitmap != nullptr) {
285 for (uint8_t digit = 0; digit < length; digit++) {
286 uint16_t endOffset = digit;
287 uint16_t startOffset = bitmapSize + endOffset;
288 uint8_t *pPtr = outputBuffer;
289 do {
290 startOffset -= length;
291 pPtr[0] = Max72XX::digit0 + length - digit - 1;
292 pPtr[1] = bitmap[startOffset];
293 pPtr += 2;
294 } while (startOffset > endOffset);
295 driver.sendBlock(outputBuffer, pPtr - outputBuffer);
296 }
297 }
298 }
299
303 virtual void fillScreen(uint8_t pattern) {
304 if (bitmap != nullptr) {
305 memset(bitmap, pattern, length * driver.getChainLen());
306 cursor_x = 0;
307 cursor_y = 0;
308 }
309 }
310
314 inline int16_t width() const {
315 return _width;
316 };
317
321 inline int16_t height() const {
322 return _height;
323 }
324
328 inline bool getTextWrap() const {
329 return wrap;
330 }
331
335 inline int16_t getCursorX() const {
336 return cursor_x;
337 }
338
342 inline int16_t getCursorY() const {
343 return cursor_y;
344 };
345
350 uint8_t getCharLen(unsigned char c, bool firstChar = false) {
351 if (c < 32) {
352 return 0;
353 } else if (c == '.' || c == ',') {
354 return firstChar ? 1 : 0;
355 }
356 return 1;
357 }
358
359 protected:
360 uint8_t mapchar(uint8_t c) {
361 switch (c) {
362 case '.':
363 case ',':
364 return MAX72XX_DP;
365 case '!':
366 return MAX72XX_EXCLAMATION;
367 case '"':
368 return MAX72XX_QUOTES;
369 case ' ':
370 return MAX72XX_SPACE;
371 case '-':
372 return MAX72XX_DASH;
373 case '=':
374 return MAX72XX_EQUALS;
375 case '(':
376 case '[':
377 case '{':
378 return MAX72XX_PAROPEN;
379 case ')':
380 case ']':
381 case '}':
382 return MAX72XX_PARCLOSE;
383 case '_':
384 return MAX72XX_UNDERSCORE;
385 }
386 if (c >= '0' && c <= '9') {
387 return pgm_read_byte_near(digitTable7Seg + c - '0');
388 } else if (c >= 'A' && c <= 'Z') {
389 return pgm_read_byte_near(charTable7Seg + c - 'A');
390 } else if (c >= 'a' && c <= 'z') {
391 return pgm_read_byte_near(charTable7Seg + c - 'a');
392 } else {
393 return MAX72XX_UNDERSCORE;
394 }
395 }
396
397 virtual size_t write(uint8_t c) {
398 if (c == '\r') {
399 cursor_x = 0;
400 } else if (c == '\n') {
401 cursor_x = 0;
402 cursor_y++;
403 }
404 if (wrap && cursor_x >= _width) {
405 cursor_x = 0;
406 cursor_y++;
407 }
408 if (cursor_x >= _width || cursor_y >= _height) {
409 // out of viewport
410 return 1;
411 }
412 if (cursor_x < 0 || cursor_y < 0) {
413 // out of viewport but we must increment when char is prinatble
414 cursor_x += getCharLen(c, cursor_x == 0);
415 return 1;
416 }
417 uint8_t index = cursor_y * _width + cursor_x;
418 if (c < 32) {
419 return 1;
420 } else if (c == '.' || c == ',') {
421 if (cursor_x == 0) {
422 bitmap[index] = MAX72XX_DP;
423 } else {
424 bitmap[index - 1] |= MAX72XX_DP;
425 cursor_x--;
426 }
427 } else {
428 bitmap[index] = mapchar(c);
429 }
430 cursor_x++;
431 return 1;
432 }
433};
434
435} // namespace ustd
The MAX72XX Controller Class.
Definition: max72xx.h:14
void begin()
Definition: max72xx.h:52
@ digit0
Digit 0.
Definition: max72xx.h:24
void setPowerSave(bool powersave)
Definition: max72xx.h:93
void setIntensity(uint8_t intensity)
Definition: max72xx.h:78
uint8_t getChainLen() const
Definition: max72xx.h:64
void setTestMode(bool testmode)
Definition: max72xx.h:104
void sendBlock(uint8_t *buffer, uint8_t size)
Definition: max72xx.h:126
void setScanLimit(uint8_t scanlimit)
Definition: max72xx.h:85
void setDecodeMode(uint8_t mode)
Definition: max72xx.h:71
The MAX72XX Digits Display Class.
Definition: max72xx_digits.h:70
int16_t width() const
Definition: max72xx_digits.h:314
int16_t height() const
Definition: max72xx_digits.h:321
int16_t getCursorY() const
Definition: max72xx_digits.h:342
bool printFormatted(int16_t x, int16_t y, int16_t w, int16_t align, String content)
Definition: max72xx_digits.h:208
Max72xxDigits(uint8_t csPin, uint8_t hDisplays=1, uint8_t vDisplays=1, uint8_t length=8)
Definition: max72xx_digits.h:94
void setIntensity(uint8_t intensity)
Definition: max72xx_digits.h:133
virtual void fillScreen(uint8_t pattern)
Definition: max72xx_digits.h:303
uint8_t getCharLen(unsigned char c, bool firstChar=false)
Definition: max72xx_digits.h:350
bool getTextWrap() const
Definition: max72xx_digits.h:328
void setTestMode(bool testmode)
Definition: max72xx_digits.h:141
void begin()
Definition: max72xx_digits.h:108
int16_t getCursorX() const
Definition: max72xx_digits.h:335
void setCursor(int16_t x, int16_t y)
Definition: max72xx_digits.h:149
void setCursorY(int16_t y)
Definition: max72xx_digits.h:164
void write()
Definition: max72xx_digits.h:283
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint8_t pattern=B00000000)
Definition: max72xx_digits.h:184
void setCursorX(int16_t x)
Definition: max72xx_digits.h:157
void setTextWrap(bool w)
Definition: max72xx_digits.h:172
void setPowerSave(bool powersave)
Definition: max72xx_digits.h:126
The muwerk namespace.
Definition: display_digits_max72xx.h:10