1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
|
/*
Patch class for 32x16 RGB Matrix panels
reimplement all functions which use x,y coordinates
*/
#ifndef ESP_HUB75_32x16MatrixPanel
#define ESP_HUB75_32x16MatrixPanel
#include "ESP32-HUB75-MatrixPanel-I2S-DMA.h"
#include <Fonts/FreeSansBold12pt7b.h>
#include "glcdfont.c"
struct VirtualCoords {
int16_t x;
int16_t y;
};
#define VP_WIDTH 32
#define VP_HEIGHT 16
#define DEFAULT_FONT_W 5
#define DEFAULT_FONT_H 7
#define PIXEL_SPACE 1 // space between chars in a string
/* --- PRINTF_BYTE_TO_BINARY macro's --- */
#define PRINTF_BINARY_PATTERN_INT8 "%c%c%c%c%c%c%c%c"
#define PRINTF_BYTE_TO_BINARY_INT8(i) \
(((i) & 0x80ll) ? '1' : '0'), \
(((i) & 0x40ll) ? '1' : '0'), \
(((i) & 0x20ll) ? '1' : '0'), \
(((i) & 0x10ll) ? '1' : '0'), \
(((i) & 0x08ll) ? '1' : '0'), \
(((i) & 0x04ll) ? '1' : '0'), \
(((i) & 0x02ll) ? '1' : '0'), \
(((i) & 0x01ll) ? '1' : '0')
#define PRINTF_BINARY_PATTERN_INT16 \
PRINTF_BINARY_PATTERN_INT8 PRINTF_BINARY_PATTERN_INT8
#define PRINTF_BYTE_TO_BINARY_INT16(i) \
PRINTF_BYTE_TO_BINARY_INT8((i) >> 8), PRINTF_BYTE_TO_BINARY_INT8(i)
/* --- end macros --- */
class QuarterScanMatrixPanel : public Adafruit_GFX
{
public:
MatrixPanel_I2S_DMA *display;
QuarterScanMatrixPanel(MatrixPanel_I2S_DMA &disp) : Adafruit_GFX(64, 32)
{
this->display = &disp;
size_x = size_y = 1 ;
wrap = false;
cursor_x = cursor_y = 0;
dir = 1;
loop = true;
}
VirtualCoords getCoords(int16_t x, int16_t y);
int16_t getVirtualX(int16_t x) {
VirtualCoords coords = getCoords(x, 0);
return coords.x;
}
int16_t getVirtualY(int16_t y) {
VirtualCoords coords = getCoords(0,y);
return coords.y;
}
// int16_t getVirtualY(int16_t y) {return getCoords(0,y).y;}
/** extended function to draw lines/rects/... **/
virtual uint8_t width() {return VP_WIDTH;};
virtual uint8_t height() {return VP_HEIGHT;};
virtual void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
virtual void drawHLine(int16_t x0, int16_t y0, int16_t w, uint16_t color);
virtual void drawVLine(int16_t x0, int16_t y0, int16_t h, uint16_t color);
virtual void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
virtual void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size);
virtual void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size_x, uint8_t size_y);
virtual void scrollChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint16_t dir, uint16_t speed);
virtual void drawString(int16_t x, int16_t y, unsigned char* c, uint16_t color, uint16_t bg);
virtual size_t write(unsigned char c); // write a character on current cursor position
virtual size_t write(const char *str); // write a character array (string) on current cursor position
virtual void setTextWrap(bool w);
virtual void setCursor (int16_t x, int16_t y);
void setTextFGColor(uint16_t color) {textFGColor = color;};
void setTextBGColor(uint16_t color) {textBGColor = color;};
void setTextSize(uint8_t x, uint8_t y) {size_x = x; size_y = y;}; // magnification, default = 1
void setScrollDir(uint8_t d = 1) { dir = (d != 1) ? 0 : 1;}; // set scroll dir default = 1
void setScroolLoop (bool b = true) { loop = b;} ; // scroll text in a loop, default true
void scrollText(const char *str, uint16_t speed, uint16_t pixels);
/**------------------------------------------**/
// equivalent methods of the matrix library so it can be just swapped out.
virtual void drawPixel(int16_t x, int16_t y, uint16_t color);
virtual void fillScreen(uint16_t color); // overwrite adafruit implementation
void clearScreen() { fillScreen(0); }
//void drawPixelRGB565(int16_t x, int16_t y, uint16_t color);
void drawPixelRGB888(int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b);
//void drawPixelRGB24(int16_t x, int16_t y, RGB24 color);
void drawIcon (int *ico, int16_t x, int16_t y, int16_t module_cols, int16_t module_rows);
uint16_t color444(uint8_t r, uint8_t g, uint8_t b) {
return display->color444(r, g, b);
}
uint16_t color565(uint8_t r, uint8_t g, uint8_t b) {
return display->color565(r, g, b);
}
uint16_t color333(uint8_t r, uint8_t g, uint8_t b) {
return display->color333(r, g, b);
}
void flipDMABuffer() { display->flipDMABuffer(); }
void showDMABuffer() { display->showDMABuffer(); }
void drawDisplayTest();
protected:
int16_t cursor_x, cursor_y; // Cursor position
uint8_t size_x, size_y; // Font size Multiplier default = 1 => 5x7 Font (5width,7Height)
uint16_t textFGColor, textBGColor;
bool wrap ; // < If set, 'wrap' text at right edge of display
uint8_t dir ; // used for scrolling text direction
bool loop ; // used for scrolling text in a loop
private:
VirtualCoords coords;
}; // end Class header
/***************************************************************************************
@brief scroll text from right to left or vice versa on current cursor position
please note, this function is not interruptable.
@param *c pointer to \0 terminated string
@param pixels number of pixels to scroll, if 0, than scroll complete text
@param speed velocity of scrolling in ms
***************************************************************************************/
void QuarterScanMatrixPanel::scrollText(const char *str,uint16_t speed, uint16_t pixels = 0) {
// first we put all columns of every char inside str into a big array of lines
// than we move through this array and draw line per line and move this line
// one position to dir
const uint8_t xSize = 6;
uint16_t len = strlen(str);
uint8_t array[len * xSize]; // size of array number of chars * width of char
//uint16_t lenArray = sizeof(array)/sizeof(array[0]);
uint16_t aPtr = 0;
//
// generate array
char c = *str;
// Serial.printf("size *str (%d), size array: (%d) \n", len, lenArray);
while (c) {
// Serial.printf("** %c ** \n", c);
// read font line per line. A line is a column inside a char
for (int8_t i = 0; i < 5; i++) {
uint8_t line = pgm_read_byte(&font[c * 5 + i]);
array[aPtr++] = line;
// Serial.printf("%d - Line " PRINTF_BINARY_PATTERN_INT8 "\n", i, PRINTF_BYTE_TO_BINARY_INT8(line) );
}
str++;
c = *str;
array[aPtr++] = 0x00; // line with 0 (space between chars)
}
array[aPtr++] = 0x00; // line with 0 (space between chars)
/*
Serial.printf("---------------------------- \n");
for (aPtr=0; aPtr < (len*xSize); aPtr++) {
Serial.printf("%d - Line " PRINTF_BINARY_PATTERN_INT8 "\n", aPtr, PRINTF_BYTE_TO_BINARY_INT8(array[aPtr]) );
}
*/
int16_t x,y,lastX, p;
lastX = (dir) ? VP_WIDTH : 0;
x = cursor_x;
y = cursor_y;
Serial.printf("X: %d, Y: %d \n", x,y);
p=0;
pixels = (pixels) ? pixels : len * xSize;
while (p <= pixels) {
// remove last pixel positions
fillRect(x,y,5,7,textBGColor);
// set new pixel position
x = (dir) ? lastX - p : lastX + p - pixels;
// iterator through our array
for (uint8_t i=0; i < (len*xSize); i++) {
uint8_t line = array[i];
//Serial.printf("%d:%d : " PRINTF_BINARY_PATTERN_INT8 "\n", x, i, PRINTF_BYTE_TO_BINARY_INT8(line) );
// read line and shift from right to left
// start with bit 0 (top of char) to 7(bottom)
for (uint8_t j=0; j < 8; j++, line>>=1) {
if (line & 1) {
// got 1, if x + i outside panel ignore pixel
if (x + i >= 0 && x + i < VP_WIDTH) {
drawPixel(x + i, y + j, textFGColor);
}
}
else {
// got 0
if (x + i >= 0 && x + i < VP_WIDTH) {
drawPixel(x + i, y + j, textBGColor);
}
} // if
} // for j
} // for i
p++;
delay(speed);
} // while
}
inline size_t QuarterScanMatrixPanel::write(const char *str) {
uint8_t x, y;
x=cursor_x;
y=cursor_y;
char c = *str;
while (c) {
//Serial.printf("%c ", c);
write(c);
str++;
c = *str;
x = x + ((DEFAULT_FONT_W + PIXEL_SPACE) * size_x);
setCursor(x,y);
}
Serial.printf("\n");
return 1;
}
inline size_t QuarterScanMatrixPanel::write(unsigned char c) {
Serial.printf("\twrite(%d, %d, %c)\n", cursor_x, cursor_y, c);
drawChar(cursor_x, cursor_y, c, textFGColor, textBGColor, size_x, size_y);
return 1;
}
void QuarterScanMatrixPanel::setTextWrap(bool w) {this->display->setTextWrap(w);}
void QuarterScanMatrixPanel::setCursor(int16_t x, int16_t y) {
cursor_x = x;
cursor_y = y;
}
/* - new for 16x32 panels - */
inline void QuarterScanMatrixPanel::drawLine(int16_t x, int16_t y, int16_t x1, int16_t y1, uint16_t color)
{
int16_t a,b;
for (a=x; a <= x1; a++) {
for (b=y; b <= y1; b++) {
drawPixel(a,b,color);
}
}
}
inline void QuarterScanMatrixPanel::drawHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
{
drawLine(x,y,x+w,y, color);
}
inline void QuarterScanMatrixPanel::drawVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
{
drawLine(x,y,x,y+h, color);
}
inline void QuarterScanMatrixPanel::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
{
for (int16_t i = x; i < x + w; i++) {
drawVLine(i, y, h, color);
}
}
void QuarterScanMatrixPanel::drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size)
{
drawChar(x,y,c,color, bg, size, size);
}
inline void QuarterScanMatrixPanel::scrollChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint16_t dir, uint16_t speed){
if ((x >= VP_WIDTH) ||
(y >= VP_HEIGHT) ||
((x + 6 * size_x-1) < 0) ||
((y + 8 * size_y-1) <0))
return;
setTextWrap(true);
// text wrap is only for the right end of the panel, to scroll soft out of the left of panel
// algorithm should wrap the character from left to right
// loop s = scroll-loop, scrolls char 5 pixels into dir
uint8_t lastX = x;
for (int8_t s = 0; s < 6; s++) {
// loop i : width of a character
Serial.printf("X:%d ", x);
// clear current position
fillRect(x,y,5,7,0);
x = lastX - s;
for (int8_t i = 0; i < 5; i++) {
// first line is the first vertical part of a character and 8bits long
// last bit is everytime 0
// we read 5 lines with 8 bit (5x7 char + 8bit with zeros)
// Example : char A (90deg cw)
// 01111100
// 00010010
// 00010001
// 00010010
// 01111100
uint8_t line = pgm_read_byte(&font[c * 5 + i]);
// shift from right to left bit per bit
// loop j = height of a character
// loop through a column of current character
Serial.printf("i:%d ", i);
// ignore all pixels outside panel
if (x+i >= VP_WIDTH) continue;
for (int8_t j=0; j < 8; j++, line >>= 1) {
if (line & 1) {
Serial.printf
(" ON %d", x+i);
// we read 1
if (x >= 0) {
drawPixel(x+i, y+j, color);
}
else if (x+i >= 0) {
drawPixel(x+i, y+j, color);
}
}
else if (bg != color) {
// we read 0
Serial.printf(" OFF %d", x+i);
if (x >= 0) {
drawPixel(x+i, y+j, bg);
}
else if (x+i >= 0) {
drawPixel(x+i, y+j, bg);
}
}
}
}
Serial.printf("\n");
delay(speed);
}
}
inline void QuarterScanMatrixPanel::drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size_x, uint8_t size_y)
{
//Serial.printf("unmapped : drawChar(%d, %d, %c) \n",x, y, c);
// note: remapping to 16x32 coordinates is done inside drawPixel() or fillRect
if ((x >= VP_WIDTH) ||
(y >= VP_HEIGHT) ||
((x + 6 * size_x-1) < 0) ||
((y + 8 * size_y-1) <0))
return;
//Serial.printf("Font-Array : %d \n", sizeof(font));
for (int8_t i = 0; i < 5; i++) {
uint8_t line = pgm_read_byte(&font[c * 5 + i]);
//Serial.printf("%d - Line " PRINTF_BINARY_PATTERN_INT8 "\n", i, PRINTF_BYTE_TO_BINARY_INT8(line) );
for (int8_t j = 0; j < 8; j++, line >>= 1) {
if (line & 1) {
if (size_x == 1 && size_y == 1)
//Serial.printf("");
drawPixel(x + i, y + j, color);
else
// remark: it's important to call function with original coordinates for x/y
fillRect(x + i * size_x, y + j * size_y, size_x, size_y,
color);
} else if (bg != color) {
if (size_x == 1 && size_y == 1)
drawPixel(x + i, y + j, bg);
else
// remark: it's important to call function with original coordinates for x/y
fillRect(x + i * size_x, y + j * size_y, size_x, size_y, bg);
}
}
}
}
inline void QuarterScanMatrixPanel::drawString(int16_t x, int16_t y, unsigned char* c, uint16_t color, uint16_t bg) {
}
inline VirtualCoords QuarterScanMatrixPanel::getCoords(int16_t x, int16_t y)
{
const int y_remap[] = { 0,1,8,9,4,5,12,13,16,17,24,25,22,23,30,31 };
if (y > VP_HEIGHT)
y = VP_HEIGHT;
if (x > VP_WIDTH)
x = VP_WIDTH;
coords.x = x + VP_WIDTH;
coords.y = y_remap[y];
return coords;
}
/* -------------------------*/
inline void QuarterScanMatrixPanel::drawPixel(int16_t x, int16_t y, uint16_t color)
{
VirtualCoords coords = getCoords(x, y);
this->display->drawPixel(coords.x, coords.y, color);
}
inline void QuarterScanMatrixPanel::fillScreen(uint16_t color) // adafruit virtual void override
{
// No need to map this.
this->display->fillScreen(color);
}
/*
inline void QuarterScanMatrixPanel::drawPixelRGB565(int16_t x, int16_t y, uint16_t color)
{
VirtualCoords coords = getCoords(x, y);
this->display->drawPixelRGB565( coords.x, coords.y, color);
}
*/
inline void QuarterScanMatrixPanel::drawPixelRGB888(int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b)
{
VirtualCoords coords = getCoords(x, y);
this->display->drawPixelRGB888( coords.x, coords.y, r, g, b);
}
/*
inline void QuarterScanMatrixPanel::drawPixelRGB24(int16_t x, int16_t y, RGB24 color)
{
VirtualCoords coords = getCoords(x, y);
this->display->drawPixelRGB24(coords.x, coords.y, color);
}
*/
// need to recreate this one, as it wouldn't work to just map where it starts.
inline void QuarterScanMatrixPanel::drawIcon (int *ico, int16_t x, int16_t y, int16_t module_cols, int16_t module_rows) { }
#endif
|