-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathClockDisplay.cpp
More file actions
657 lines (596 loc) · 27.1 KB
/
ClockDisplay.cpp
File metadata and controls
657 lines (596 loc) · 27.1 KB
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
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
/*
ClockDisplay.cpp
Manage the display of the LCD clock face
*/
#include "ClockDisplay.h"
#include "EEPROMFunctions.h"
#include "RTClock.h"
#include "Button.h"
extern RTClockClass RTClock; // Real-time clock object
Button buttonArray[MAXBUTTONS]; // Array of buttons used on the configuration screen
/**************************************************************************
@brief Converts raw touch screen locations (screenPtr) into actual pixel locations on the display (displayPtr) using the
supplied matrix.
@param[out] displayPtr Pointer to the tsPoint_t object that will hold
the compensated pixel location on the display
@param[in] screenPtr Pointer to the tsPoint_t object that contains the
raw touch screen co-ordinates (before the
calibration calculations are made)
@param[in] matrixPtr Pointer to the calibration matrix coefficients
used during the calibration process (calculated
via the tsCalibrate() helper function)
**************************************************************************/
int ClockDisplay::calibrateTSPoint(tsPoint_t * displayPtr, tsPoint_t * screenPtr )
{
//tsMatrix_t * matrixPtr = &_tsMatrix;
int retValue = 0;
if (_tsMatrixPtr->Divider != 0)
{
displayPtr->x = ((_tsMatrixPtr->An * screenPtr->x) +
(_tsMatrixPtr->Bn * screenPtr->y) +
_tsMatrixPtr->Cn
) / _tsMatrixPtr->Divider;
displayPtr->y = ((_tsMatrixPtr->Dn * screenPtr->x) +
(_tsMatrixPtr->En * screenPtr->y) +
_tsMatrixPtr->Fn
) / _tsMatrixPtr->Divider;
}
else
{
return -1;
}
return(retValue);
}
/**************************************************************************/
/*!
@brief Checks for a touch event
*/
/**************************************************************************/
int ClockDisplay::checkForTouchEvent(RA8875* disp, tsPoint_t * point, bool waitMode)
{
tsPoint_t raw, calibrated;
uint16_t x, y;
disp->touchEnable(true);
if (disp->touched())
{
// We're reading the raw register data.
// The Sumotoy calibration routine was highly inaccurate,
// So we're using the Adafruit calibration code instead
disp->touchReadAdc(&x, &y);
raw.x = x;
raw.y = y;
calibrateTSPoint(&calibrated, &raw);
point->x = calibrated.x;
point->y = calibrated.y;
//disp->fillCircle(point->x, point->y, 3, RA8875_YELLOW);
if (waitMode) // waitMode = wait for remaining touches to be cleared
{
while (disp->touched())
{
disp->touchReadAdc(&x, &y);
delay(1);
}
}
return 1;
}
else
{
point->x = 0;
point->y = 0;
return 0;
}
return 0;
}
/**************************************************************************/
/*!
@brief Starts the screen calibration process. Each corner will be
tested, meaning that each boundary (top, left, right and
bottom) will be tested twice and the readings averaged.
*/
/**************************************************************************/
void ClockDisplay::tsCalibrate(RA8875* disp)
{
// read calibration data from eeprom
_tsMatrix0.An = EEPROMReadSignedLong(EEPROM_CALIBRATION_LOCATION);
_tsMatrix0.Bn = EEPROMReadSignedLong(EEPROM_CALIBRATION_LOCATION + 4);
_tsMatrix0.Cn = EEPROMReadSignedLong(EEPROM_CALIBRATION_LOCATION + 8);
_tsMatrix0.Dn = EEPROMReadSignedLong(EEPROM_CALIBRATION_LOCATION + 12);
_tsMatrix0.En = EEPROMReadSignedLong(EEPROM_CALIBRATION_LOCATION + 16);
_tsMatrix0.Fn = EEPROMReadSignedLong(EEPROM_CALIBRATION_LOCATION + 20);
_tsMatrix0.Divider = EEPROMReadSignedLong(EEPROM_CALIBRATION_LOCATION + 24);
/*
Serial.println(_tsMatrix0.An);
Serial.println(_tsMatrix0.Bn);
Serial.println(_tsMatrix0.Cn);
Serial.println(_tsMatrix0.Dn);
Serial.println(_tsMatrix0.En);
Serial.println(_tsMatrix0.Fn);
Serial.println(_tsMatrix0.Divider);
*/
_tsMatrix180.An = EEPROMReadSignedLong(EEPROM_CALIBRATION_LOCATION + 28);
_tsMatrix180.Bn = EEPROMReadSignedLong(EEPROM_CALIBRATION_LOCATION + 32);
_tsMatrix180.Cn = EEPROMReadSignedLong(EEPROM_CALIBRATION_LOCATION + 36);
_tsMatrix180.Dn = EEPROMReadSignedLong(EEPROM_CALIBRATION_LOCATION + 40);
_tsMatrix180.En = EEPROMReadSignedLong(EEPROM_CALIBRATION_LOCATION + 44);
_tsMatrix180.Fn = EEPROMReadSignedLong(EEPROM_CALIBRATION_LOCATION + 48);
_tsMatrix180.Divider = EEPROMReadSignedLong(EEPROM_CALIBRATION_LOCATION + 52);
/*
Serial.println(_tsMatrix180.An);
Serial.println(_tsMatrix180.Bn);
Serial.println(_tsMatrix180.Cn);
Serial.println(_tsMatrix180.Dn);
Serial.println(_tsMatrix180.En);
Serial.println(_tsMatrix180.Fn);
Serial.println(_tsMatrix180.Divider);
*/
}
// Display boot-up colors test pattern on the screen. Oooh, pretty!
void ClockDisplay::testPattern(RA8875 *disp)
{
uint16_t colors[] = { RA8875_WHITE , RA8875_RED , RA8875_YELLOW , RA8875_GREEN , RA8875_CYAN , RA8875_MAGENTA, RA8875_BLACK };
for (int i = 0; i < 7; ++i)
{
disp->fillWindow(colors[i]);
delay(500);
}
}
ClockDisplay::ClockDisplay()
{
// Initiatize Main Time section
timeArray[0].setup('0', W_LARGEDIGIT, H_LARGEDIGIT, X_TIMEHOURHIGH, Y_TIME_UPPER, HRHIGH);
timeArray[1].setup('0', W_LARGEDIGIT, H_LARGEDIGIT, X_TIMEHOURLOW, Y_TIME_UPPER, HRLOW);
timeArray[2].setup('0', W_LARGEDIGIT, H_LARGEDIGIT, X_TIMEMINUTEHIGH, Y_TIME_UPPER, MNHIGH);
timeArray[3].setup('0', W_LARGEDIGIT, H_LARGEDIGIT, X_TIMEMINUTELOW, Y_TIME_UPPER, MNLOW);
timeArray[4].setup('0', W_LARGEDIGIT, H_LARGEDIGIT, X_TIMESECONDHIGH, Y_TIME_UPPER, SEHIGH);
timeArray[5].setup('0', W_LARGEDIGIT, H_LARGEDIGIT, X_TIMESECONDLOW, Y_TIME_UPPER, SELOW);
colonChar1.setup(':', W_COLON, H_COLON, X_COLON1, Y_TIME_UPPER, IDNULL);
colonChar2.setup(':', W_COLON, H_COLON, X_COLON2, Y_TIME_UPPER, IDNULL);
// Initialize Main Date section
dateArray[0].setup('0', W_LARGEDIGIT, H_LARGEDIGIT, X_DATEMONTHHIGH, Y_DATE_UPPER, MOHIGH);
dateArray[1].setup('1', W_LARGEDIGIT, H_LARGEDIGIT, X_DATEMONTHLOW, Y_DATE_UPPER, MOLOW);
dateArray[2].setup('0', W_LARGEDIGIT, H_LARGEDIGIT, X_DATEDAYHIGH, Y_DATE_UPPER, DYHIGH);
dateArray[3].setup('1', W_LARGEDIGIT, H_LARGEDIGIT, X_DATEDAYLOW, Y_DATE_UPPER, DYLOW);
dateArray[4].setup('1', W_LARGEDIGIT, H_LARGEDIGIT, X_DATEYEARHIGH, Y_DATE_UPPER, YRHIGH);
dateArray[5].setup('6', W_LARGEDIGIT, H_LARGEDIGIT, X_DATEYEARLOW, Y_DATE_UPPER, YRLOW);
slashChar1.setup('/', W_SLASH, H_SLASH, X_SLASH1, Y_DATE_UPPER, IDNULL);
slashChar2.setup('/', W_SLASH, H_SLASH, X_SLASH2, Y_DATE_UPPER, IDNULL);
// Initialize up AM/PM indicator dots
amDot.setup(X_AMPM, Y_AM, AMPM_DOTSIZE);
pmDot.setup(X_AMPM, Y_PM, AMPM_DOTSIZE);
numberBase = BASE_HEX; // Default number base for display is HEX
configMode = false; // In "run" mode, not configutration mode
displayBase = DISPLAY_24H; // Default to military time display
amPm = AMPM_MORNING; // default to AM
rotation = ROTATION_0; // 0-degree screen rotation
_tsMatrixPtr = &_tsMatrix0; // Touch screen calibration matrix for 0-degree rotation
}
ClockDisplay::~ClockDisplay()
{
}
/*
Refresh the time on the clock
Refreshes only the internal time elements. Does NOT refresh the time on the clock's face. refreshClock() does that.
Mode is passed through to the function that updates the time/date character objects:
REFRESH_MIN = refresh an object only if the value of the time element in that object has changed. Minimizes screen redraws, which can be slow on the tft display.
REFRESH_ALL = Refresh the object whether it's changed or not. Forces a full redraw of the whole clock acreen.
*/
void ClockDisplay::refreshTime(RA8875 *disp, int mode)
{
uint8_t tUnit;
char charRep[3];
int i;
char *baseArray = "0123456789ABCDEF"; // Possible display digits
for (i = UNIT_HOUR; i <= UNIT_YEAR_SHORT; ++i) // Loop through all time/date parts
{
tUnit = RTClock.getUnit(i);
if (i == UNIT_HOUR) // Account for 12H display
{
amPm = (tUnit < 12) ? AMPM_MORNING : AMPM_AFTERNOON;
if (displayBase == DISPLAY_12H)
{
if (tUnit > 12)
tUnit -= 12;
if (tUnit == 0)
tUnit = 12;
}
}
// Account for 12-hour display time
// Get high- and low-order digits base on the current display mode (decimal or hex)
// If in configuration mode mode, force decimal base.
charRep[0] = baseArray[tUnit / (configMode ? BASE_DEC : numberBase)];
charRep[1] = baseArray[tUnit % (configMode ? BASE_DEC : numberBase)]; // Get low-order digit
charRep[2] = '\0'; // NULL-terminate string, not because it's really needed here, but just for safety
timeArray[(i - 1) * 2].setNewChar((tUnit >> 4), charRep[0], mode); // Set high-order digit & bits
timeArray[((i - 1) * 2) + 1].setNewChar((tUnit & 0xF), charRep[1], mode); // Set low-order digit & bits
}
return;
}
void ClockDisplay::setRotation(uint8_t rot)
{
rotation = rot;
_tsMatrixPtr = (rotation == ROTATION_0) ? &_tsMatrix0 : &_tsMatrix180; // Set calibration matrix based on screen orientation (0 or 180 degrees)
}
/*
Refresh the clock face.
refreshMode indicates how to handles the refresh
REFRESH_MIN = refresh the character object only if the value of the time element in that object has changed. Minimizes screen redraws, which can be slow on the tft display.
REFRESH_ALL = Refresh the character whether it's changed or not. Forces a full redraw of the whole clock.
drawMode indicates what parts of the clock face to draw
DRAW_HEXBIN = Draw both Hex & Binary parts
DRAW_HEXONLY = Draw only the upper hexadecimal part
*/
void ClockDisplay::refreshClock(RA8875 *disp, int refreshMode, int drawMode)
{
int i;
if (refreshMode == REFRESH_ALL)
disp->fillWindow(bgColor); // Start with a clean slate
disp->setRotation(rotation);
// Print time
for (int i = 0; i < 6; ++i) // HH, MM, SS
{
timeArray[i].drawChar(disp, fgColor, bgColor);
// Normally we draw both the hex/decimal time on the upper part of the screen and the binary time on the lower part of the screen.
// On the configuration screen, we don't want to draw the binary time, because that's where the config buttons go
// DRAW_HEXONLY indicates to not draw the lower binary part
if (drawMode == DRAW_HEXBIN)
timeArray[i].drawBinary(disp, fgColor, bgColor);
}
colonChar1.drawChar(disp, fgColor, bgColor); // 2 colons between time elements
colonChar2.drawChar(disp, fgColor, bgColor);
// Print Date
for (int i = 0; i<6; ++i) // MM, DD, YY
{
dateArray[i].drawChar(disp, fgColor, bgColor);
// Same as above
if (drawMode == DRAW_HEXBIN)
dateArray[i].drawBinary(disp, fgColor, bgColor);
}
slashChar1.drawChar(disp, fgColor, bgColor); // 2 slashes between date elements
slashChar2.drawChar(disp, fgColor, bgColor);
if (displayBase == DISPLAY_12H) // Need AM/PM indicator
{
if (amPm == AMPM_MORNING)
{
if (refreshMode == REFRESH_ALL)
amDot.refreshDot(disp, fgColor);
else
amDot.drawDot(disp, fgColor);
pmDot.eraseDot(disp, bgColor);
}
else // AMPM_AFTERNOON
{
amDot.eraseDot(disp, bgColor);
if (refreshMode == REFRESH_ALL)
pmDot.refreshDot(disp, fgColor);
else
pmDot.drawDot(disp, fgColor);
}
}
else
{
amDot.eraseDot(disp, bgColor);
pmDot.eraseDot(disp, bgColor);
}
if ((refreshMode == REFRESH_ALL) && (drawMode == DRAW_HEXBIN)) // Refreshing whole screen (hex & binary). Need to add the binary labels
{
disp->setFont(INT);
disp->setTextColor(fgColor, bgColor);
disp->setFontScale(BINFONTSIZE);
disp->setCursor(X_BIN_TIMELABEL, Y_BIN_1); disp->println(F("H:"));
disp->setCursor(X_BIN_TIMELABEL, Y_BIN_2); disp->println(F("M:"));
disp->setCursor(X_BIN_TIMELABEL, Y_BIN_3); disp->println(F("S:"));
disp->setCursor(X_BIN_DATELABEL, Y_BIN_1); disp->println(F("M:"));
disp->setCursor(X_BIN_DATELABEL, Y_BIN_2); disp->println(F("D:"));
disp->setCursor(X_BIN_DATELABEL, Y_BIN_3); disp->println(F("Y:"));
}
return;
}
/*
Given an X,Y point on the screen, return which button (if any) was pressed
Returns 0-MAXBUTTONS for an actual button
Returns -1 if area pressed was not a button
*/
int ClockDisplay::identifyArea(tsPoint_t point)
{
int i;
for (i = 0; i < MAXBUTTONS; ++i)
{
if (buttonArray[i].isButton(point.x, point.y))
return i;
}
return -1;
}
/*
Displays the setup screen, places the buttons, and watches for screen presses
*/
int ClockDisplay::setupScreen(RA8875* disp)
{
tsPoint_t calibrated; // Holds calibrated screen points when screen is touched
int touchArea; // The button that was touched
int i, newRefreshMode;
bool redrawButtons = true, exitLoop=false;
uint16_t newFg=fgColor, newBg=bgColor;
/*
systemresetCounter is used as a safeguard to accidentally resetting the clock
The user must press the three reset buttons in order to force the reset.
Press the buttons in any other order and systemresetCounter is reset to zero and the user must start again.
*/
int systemResetCounter = 0;
configMode = true; // Tells the clock we're in configuration mode. Suppress some normal screen drawing functions
// Initialize all the buttons on the display
// These are the buttons to adjust the time/date up & down
buttonArray[BTN_HOURUP].setup(X_TIMEHOURHIGH, Y_TIME_UPPER, ((X_COLON1) - (X_TIMEHOURHIGH)), (H_LARGEDIGIT/2), NULL_COLOR, NULL_COLOR, NULL_COLOR, NULL, SETUPFONTSIZE, NULL, NULL, NULL);
buttonArray[BTN_HOURDOWN].setup(X_TIMEHOURHIGH, Y_TIME_MID, ((X_COLON1) - (X_TIMEHOURHIGH)), (H_LARGEDIGIT/2), NULL_COLOR, NULL_COLOR, NULL_COLOR, NULL, SETUPFONTSIZE, NULL, NULL, NULL);
buttonArray[BTN_MINUTEUP].setup(X_TIMEMINUTEHIGH, Y_TIME_UPPER, ((X_COLON2) - (X_TIMEMINUTEHIGH)), (H_LARGEDIGIT/2), NULL_COLOR, NULL_COLOR, NULL_COLOR, NULL, SETUPFONTSIZE, NULL, NULL, NULL);
buttonArray[BTN_MINUTEDOWN].setup(X_TIMEMINUTEHIGH, Y_TIME_MID, ((X_COLON2) - (X_TIMEMINUTEHIGH)), (H_LARGEDIGIT / 2), NULL_COLOR, NULL_COLOR, NULL_COLOR, NULL, SETUPFONTSIZE, NULL, NULL, NULL);
buttonArray[BTN_MONTHUP].setup(X_DATEMONTHHIGH, Y_DATE_UPPER, ((X_SLASH1)-(X_DATEMONTHHIGH)), (H_LARGEDIGIT / 2), NULL_COLOR, NULL_COLOR, NULL_COLOR, NULL, SETUPFONTSIZE, NULL, NULL, NULL);
buttonArray[BTN_MONTHDOWN].setup(X_DATEMONTHHIGH, Y_DATE_MID, ((X_SLASH1)-(X_DATEMONTHHIGH)), (H_LARGEDIGIT / 2), NULL_COLOR, NULL_COLOR, NULL_COLOR, NULL, SETUPFONTSIZE, NULL, NULL, NULL);
buttonArray[BTN_DAYUP].setup(X_DATEDAYHIGH, Y_DATE_UPPER, ((X_SLASH2) - (X_DATEDAYHIGH)), (H_LARGEDIGIT / 2), NULL_COLOR, NULL_COLOR, NULL_COLOR, NULL, SETUPFONTSIZE, NULL, NULL, NULL);
buttonArray[BTN_DAYDOWN].setup(X_DATEDAYHIGH, Y_DATE_MID, ((X_SLASH2) - (X_DATEDAYHIGH)), (H_LARGEDIGIT / 2), NULL_COLOR, NULL_COLOR, NULL_COLOR, NULL, SETUPFONTSIZE, NULL, NULL, NULL);
buttonArray[BTN_YEARUP].setup(X_DATEYEARHIGH, Y_DATE_UPPER, ((X_DATEYEARHIGH) + (W_LARGEDIGIT * 2)), (H_LARGEDIGIT / 2), NULL_COLOR, NULL_COLOR, NULL_COLOR, NULL, SETUPFONTSIZE, NULL, NULL, NULL);
buttonArray[BTN_YEARDOWN].setup(X_DATEYEARHIGH, Y_DATE_MID, ((X_DATEYEARHIGH) + (W_LARGEDIGIT * 2)), (H_LARGEDIGIT / 2), NULL_COLOR, NULL_COLOR, NULL_COLOR, NULL, SETUPFONTSIZE, NULL, NULL, NULL);
// These are the configuration buttons (color, number base, reset, etc)
buttonArray[BTN_FGBLACK].setup(X_COLOR1, Y_COLOR_FG, W_COLOR, H_COLOR, RA8875_BLACK, RA8875_WHITE, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_FGBLUE].setup(X_COLOR2, Y_COLOR_FG, W_COLOR, H_COLOR, RA8875_BLUE, RA8875_WHITE, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_FGRED].setup(X_COLOR3, Y_COLOR_FG, W_COLOR, H_COLOR, RA8875_RED, RA8875_BLACK, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_FGGREEN].setup(X_COLOR4, Y_COLOR_FG, W_COLOR, H_COLOR, RA8875_GREEN, RA8875_BLACK, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_FGCYAN].setup(X_COLOR5, Y_COLOR_FG, W_COLOR, H_COLOR, RA8875_CYAN, RA8875_BLACK, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_FGMAGENTA].setup(X_COLOR6, Y_COLOR_FG, W_COLOR, H_COLOR, RA8875_MAGENTA, RA8875_BLACK, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_FGYELLOW].setup(X_COLOR7, Y_COLOR_FG, W_COLOR, H_COLOR, RA8875_YELLOW, RA8875_BLACK, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_FGWHITE].setup(X_COLOR8, Y_COLOR_FG, W_COLOR, H_COLOR, RA8875_WHITE, RA8875_BLACK, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_BGBLACK].setup(X_COLOR1, Y_COLOR_BG, W_COLOR, H_COLOR, RA8875_BLACK, RA8875_WHITE, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_BGBLUE].setup(X_COLOR2, Y_COLOR_BG, W_COLOR, H_COLOR, RA8875_BLUE, RA8875_WHITE, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_BGRED].setup(X_COLOR3, Y_COLOR_BG, W_COLOR, H_COLOR, RA8875_RED, RA8875_BLACK, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_BGGREEN].setup(X_COLOR4, Y_COLOR_BG, W_COLOR, H_COLOR, RA8875_GREEN, RA8875_BLACK, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_BGCYAN].setup(X_COLOR5, Y_COLOR_BG, W_COLOR, H_COLOR, RA8875_CYAN, RA8875_BLACK, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_BGMAGENTA].setup(X_COLOR6, Y_COLOR_BG, W_COLOR, H_COLOR, RA8875_MAGENTA, RA8875_BLACK, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_BGYELLOW].setup(X_COLOR7, Y_COLOR_BG, W_COLOR, H_COLOR, RA8875_YELLOW, RA8875_BLACK, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_BGWHITE].setup(X_COLOR8, Y_COLOR_BG, W_COLOR, H_COLOR, RA8875_WHITE, RA8875_BLACK, NULL, NULL, NULL, NULL, NULL, NULL);
buttonArray[BTN_BASE].setup(X_BASE, Y_BASE, W_BASE, H_BASE, RA8875_WHITE, RA8875_BLACK, RA8875_BLACK, RA8875_WHITE, SETUPFONTSIZE, (numberBase == BASE_HEX)?"HEX":"DEC", (X_BASE + 12), (Y_BASE + 6));
buttonArray[BTN_RST1].setup(X_RESET1, Y_RESET, W_RESET, H_RESET, RA8875_GREEN, RA8875_BLACK, RA8875_BLACK, RA8875_GREEN, SETUPFONTSIZE, "1st", (X_RESET1 + 7), (Y_RESET + 5));
buttonArray[BTN_RST2].setup(X_RESET2, Y_RESET, W_RESET, H_RESET, RA8875_YELLOW, RA8875_BLACK, RA8875_BLACK, RA8875_YELLOW, SETUPFONTSIZE, "2nd", (X_RESET2 + 7), (Y_RESET + 5));
buttonArray[BTN_RST3].setup(X_RESET3, Y_RESET, W_RESET, H_RESET, RA8875_RED, RA8875_BLACK, RA8875_WHITE, RA8875_RED, SETUPFONTSIZE, "3rd", (X_RESET3 + 7), (Y_RESET + 5));
buttonArray[BTN_DONE].setup(X_DONE, Y_DONE, W_DONE, H_DONE, RA8875_RED, RA8875_BLACK, RA8875_WHITE, RA8875_RED, SETUPFONTSIZE+1, "Done!", (X_DONE + 7), (Y_DONE + 5));
buttonArray[BTN_DISPLAY].setup(X_DISPLAY, Y_DISPLAY, W_DISPLAY, H_DISPLAY, RA8875_WHITE, RA8875_BLACK, RA8875_BLACK, RA8875_WHITE, SETUPFONTSIZE, (displayBase == DISPLAY_24H) ? "24H" : "12H", (X_DISPLAY + 12), (Y_DISPLAY + 6));
buttonArray[BTN_ROTATE].setup(X_ROTATE, Y_ROTATE, W_ROTATE, H_ROTATE, RA8875_WHITE, RA8875_BLACK, RA8875_BLACK, RA8875_WHITE, SETUPFONTSIZE, "Rotate", (X_ROTATE + 3), (Y_ROTATE + 6));
disp->fillWindow(bgColor); // Clear the screen
// Get the latest date & time
refreshTime(disp, REFRESH_ALL);
// Only draw upper part of screen
refreshClock(disp, REFRESH_ALL, DRAW_HEXONLY);
do
{
if (redrawButtons) // For some reason, we need to redraw the buttons and their labels
{
disp->setFont(INT);
for (i = 0; i < MAXBUTTONS; ++i)
buttonArray[i].draw(disp, fgColor, bgColor);
disp->setTextColor(RA8875_WHITE, RA8875_BLACK);
disp->setFontScale(SETUPFONTSIZE);
disp->setCursor(X_FOREBACKBASE_LABEL, Y_FORELABEL); disp->print(F(" Foreground:"));
disp->setCursor(X_FOREBACKBASE_LABEL, Y_BACKLABEL); disp->print(F(" Background:"));
disp->setCursor(X_FOREBACKBASE_LABEL, Y_BASELABEL); disp->print(F(" Number Base:"));
disp->setCursor(X_DISPLAYLABEL, Y_DISPLAYLABEL); disp->print(F(" Display:"));
disp->setCursor(X_RESETLABEL, Y_RESETLABEL); disp->print(F(" Reset:"));
redrawButtons = false;
}
newRefreshMode = REFRESH_MIN; // For any changes, refresh the screen only as much as needed
if (checkForTouchEvent(disp, &calibrated, true) != 0) // Was screen touched?
{
if ((touchArea = identifyArea(calibrated)) != -1) // If so, was it touched in a button area?
{
switch (touchArea)
{
case BTN_HOURUP: // Incremenmt hour
RTClock.incrementUnit(UNIT_HOUR);
systemResetCounter = 0;
break;
case BTN_HOURDOWN: // Decrement hour
RTClock.decrementUnit(UNIT_HOUR);
systemResetCounter = 0;
break;
case BTN_MINUTEUP: // Increment minute. Seconds are automatically set to zero
RTClock.incrementUnit(UNIT_MINUTE);
systemResetCounter = 0;
break;
case BTN_MINUTEDOWN: // Decrement minute. Seconds are automatically set to zero
RTClock.decrementUnit(UNIT_MINUTE);
systemResetCounter = 0;
break;
case BTN_MONTHUP: // Increment month
RTClock.incrementUnit(UNIT_MONTH);
systemResetCounter = 0;
break;
case BTN_MONTHDOWN: // Decrement month
RTClock.decrementUnit(UNIT_MONTH);
systemResetCounter = 0;
break;
case BTN_DAYUP: // Increment day
RTClock.incrementUnit(UNIT_DAY);
systemResetCounter = 0;
break;
case BTN_DAYDOWN: // Decrement day
RTClock.decrementUnit(UNIT_DAY);
systemResetCounter = 0;
break;
case BTN_YEARUP: // Increment year
RTClock.incrementUnit(UNIT_YEAR);
systemResetCounter = 0;
break;
case BTN_YEARDOWN: // Decrement year
RTClock.decrementUnit(UNIT_YEAR);
systemResetCounter = 0;
break;
case BTN_FGBLACK: // Set foreground to black
newFg=RA8875_BLACK;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_FGBLUE: // Set foreground to blue
newFg = RA8875_BLUE;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_FGRED: // Set foreground to red
newFg = RA8875_RED;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_FGGREEN: // Set foreground to green
newFg = RA8875_GREEN;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_FGCYAN: // Set foreground to cyan
newFg = RA8875_CYAN;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_FGMAGENTA: // Set foreground to magenta
newFg = RA8875_MAGENTA;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_FGYELLOW: // Set foreground to yellow
newFg = RA8875_YELLOW;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_FGWHITE: // Set foreground to white
newFg = RA8875_WHITE;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_BGBLACK: // Set background to black
newBg = RA8875_BLACK;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_BGBLUE: // Set background to blue
newBg = RA8875_BLUE;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_BGRED: // Set background to red
newBg = RA8875_RED;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_BGGREEN: // Set background to green
newBg = RA8875_GREEN;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_BGCYAN: // Set background to cyan
newBg = RA8875_CYAN;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_BGMAGENTA: // Set background to magenta
newBg = RA8875_MAGENTA;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_BGYELLOW: // Set background to yellow
newBg = RA8875_YELLOW;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_BGWHITE: // Set background to white
newBg = RA8875_WHITE;
newRefreshMode = REFRESH_ALL;
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_BASE: // Toggle between hex & decimal display
numberBase = (numberBase == BASE_HEX) ? BASE_DEC : BASE_HEX;
buttonArray[BTN_BASE].setLabel((numberBase == BASE_HEX) ? "HEX" : "DEC");
redrawButtons = true;
break;
case BTN_RST1: // Reset clock - 1st step
/*
Resetting the clock resets the time, color, and display components back to default state, then reboots the Arduino.
It does NOT reset the display calibration coordinates. To reset the calibration you must run the TftCalibration Sketch again.
To reset the clock, the "1st", "2nd", and "3rd" buttons must be pressed in that order.
This was done to prevent accidental reset due to the flaky nature of the touch screen accuracy.
*/
systemResetCounter = 1;
break;
case BTN_RST2: // Reset clock - second step
if (systemResetCounter == 1)
systemResetCounter = 2;
else
systemResetCounter = 0; // Start counting over again.
break;
case BTN_RST3: // Reset clock - 3rd step
if (systemResetCounter == 2) // First two steps have already been completed
{
disp->fillWindow(RA8875_BLACK); // Give immediate feedback to user
EEPROMWritelong(EEPROM_SIGNATURE_LOCATION, (uint32_t)0x0); // Reset system settings signature. Force new settings on reboot.
RTClock.resetClock(); // Set time/date back to initial time
softwareReset();
}
else
systemResetCounter = 0;
break;
case BTN_DISPLAY: // Toggle 12/24H display
displayBase = (displayBase == DISPLAY_24H) ? DISPLAY_12H : DISPLAY_24H;
buttonArray[BTN_DISPLAY].setLabel((displayBase == DISPLAY_24H) ? "24H" : "12H");
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_ROTATE: // Rotate display 180 degrees
setRotation((rotation == ROTATION_0) ? ROTATION_180 : ROTATION_0); // screen Flip rotation
disp->setRotation(rotation); // Reset screen rotation
redrawButtons = true;
systemResetCounter = 0;
break;
case BTN_DONE:
newRefreshMode = REFRESH_ALL;
disp->fillWindow(bgColor);
exitLoop = true;
break;
}
// Adjust screen to account for any color changes
setFgColor(newFg);
setBgColor(newBg);
refreshTime(disp, newRefreshMode);
refreshClock(disp, newRefreshMode, (exitLoop == false)?DRAW_HEXONLY:DRAW_HEXBIN);
newRefreshMode = REFRESH_MIN;
// Save new settings
EEPROMWritelong(EEPROM_CONFIG_LOCATION, (uint32_t)fgColor);
EEPROMWritelong(EEPROM_CONFIG_LOCATION + 4, (uint32_t)bgColor);
EEPROMWritelong(EEPROM_CONFIG_LOCATION + 8, (uint32_t)numberBase);
EEPROMWritelong(EEPROM_CONFIG_LOCATION + 12, (uint32_t)displayBase);
EEPROMWritelong(EEPROM_CONFIG_LOCATION + 16, (uint32_t)rotation);
}
}
}
while (exitLoop == false);
configMode = false;
// Force redraw of colons & slashes, because the system doesn't think they've been updated and won't draw them otherwise.
colonChar1.triggerHexUpdate();
colonChar2.triggerHexUpdate();
slashChar1.triggerHexUpdate();
slashChar2.triggerHexUpdate();
return 0;
}
void ClockDisplay::softwareReset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile (" jmp 0");
}