#include <TFT_eSPI.h>
#include "CustomFont.h"
#include "SmallFont.h"
#include "GraphicDesign.h"
#include "LogicAlgo.h"
#include <Adafruit_FT6206.h>
#include <Adafruit_GFX.h>
#include <vector>
#include <map>
//Adafruit_ILI9341 tft = Adafruit_ILI9341(16,5);
TFT_eSPI tft = TFT_eSPI();
Adafruit_FT6206 ts;
GraphicDesign gp;
LogicAlgo la;
volatile unsigned int timeCnt = 0;
volatile int hr = 19;
volatile int mi = 47;
volatile int se = 0;
volatile int dd = 1;
volatile int mm = 1;
volatile int yy = 2025;
volatile int day = la.dateToDay(dd, mm, yy);
volatile bool frame = false;
int posMonth = 1 + 4*(mm/4);
int posDay = 1 + 8*(dd/8);
int maxDay = la.daysInMonth(mm, yy);
String h = "";
String m = "";
int state = 0;
// Background time counting
void Task1code(void *parameter) {
while (1) {
unsigned long startTime = micros();
if(se<59) se++;
else {
se = 0;
frame = true;
if(mi<59) mi++;
else {
mi = 0;
if(hr<23) hr++;
else {
hr = 0;
std::vector<int> date = la.nextDate(dd, mm, yy);
dd = date[0]; mm = date[1]; yy = date[2];
day = la.dateToDay(dd, mm, yy);
}
}
}
unsigned long timeSpent = micros()-startTime;
Serial.print("core 0 : time : ");
Serial.println(timeSpent);
vTaskDelay((1000-timeSpent) / portTICK_PERIOD_MS); // 1 second delay
}
}
// get touch point
int tx() {
TS_Point point = ts.getPoint();
return 240-point.x;
}
int ty() {
TS_Point point = ts.getPoint();
return 320-point.y;
}
// difference calculate
int diff(int x, int y) {
int d = x-y;
return d>=0?d:-d;
}
void setup() {
tft.init();
tft1.init();
ts.begin();
Serial.begin(115200);
// drawCalUI(String textAlign, int stDay, int date, int mm, int yy)
tft.fillScreen(0x0);
xTaskCreatePinnedToCore(
Task1code, // Task function
"TimeTask", // Name
1000, // Stack size
NULL, // Task input
1, // Priority
NULL, // Task handle
0); // Core 0
}
void calendarDateEventUI(int date, int month, int year) {
int thatDay = la.dateToDay(date, month, year);
gp.drawCalDateEventUI(thatDay, date, month, year);
while(1) {
if(ts.touched()) {
int instX0 = tx(), instY0 = ty();
// Back Button
if(instX0>=5 && instX0<20 && instY0>=5 && instY0<22) return;
}
}
}
void calendarScreen() {
while(1) {
// Calendar UI
int date = dd, month = mm, year = yy;
int maxD = maxDay, stDay = la.dateToDay(1, mm, yy);
gp.drawCalUI("center", stDay, date, true, month, maxD, year);
while(1) {
// Calculate Calendar Grid Row
int n = stDay + maxD;
int numRow = 5;
if(stDay+maxD < 29) numRow = 4;
else if(stDay+maxD > 35) numRow = 6;
// Touch Control
if(ts.touched()) {
int instX0 = tx(), instY0 = ty();
// Long press
int instX[2] = {instX0, instX0};
int instY[2] = {instY0, instY0};
while(ts.touched()) {
instX[0] = instX[1];
instY[0] = instY[1];
instX[1] = tx();
instY[1] = ty();
}
int instX1 = (instX[1] == 240) ? instX[0] : instX[1];
int instY1 = (instY[1] == 320) ? instY[0] : instY[1];
// Back Button
if(instX0>=5 && instX0<20 && instY0>=5 && instY0<22) return;
// Left Swipe
else if(instX1-instX0 < -20) {
// Erase Calendar
tft.fillRect(15,95, 212,212, 0x0);
gp.drawCalMonth(85, month, 0x0);
month++; // Update
if(month > 12) {
month = 1;
gp.drawCalYear(60, year, 0x0);
year++;
gp.drawCalYear(60, year, 0xffff);
}
maxD = la.daysInMonth(month, year);
stDay = la.dateToDay(1, month, year);
// Re-draw Calendar Grid
gp.drawCalGrid(15, 95, "center", stDay, month, maxD, 0xffff, 0x3fef, 0xaf7e, 0x7bef, 0xac7d);
gp.drawCalMonth(85, month, 0x677e);
if(month == mm && year == yy) {
gp.drawCalDate(15, 95, "center", date, stDay, month, 0x0, 0x94fb, 0xac7d);
}
}
// Right Swipe
else if(instX1-instX0 > 20) {
// Erase Calendar
tft.fillRect(15,95, 212,212, 0x0);
gp.drawCalMonth(85, month, 0x0);
month--; // Update
if(month < 1) {
month = 12;
gp.drawCalYear(60, year, 0x0);
year--;
gp.drawCalYear(60, year, 0xffff);
}
maxD = la.daysInMonth(month, year);
stDay = la.dateToDay(1, month, year);
// Re-draw Calendar Grid
gp.drawCalGrid(15, 95, "center", stDay, month, maxD, 0xffff, 0x3fef, 0xaf7e, 0x7bef, 0xac7d);
gp.drawCalMonth(85, month, 0x677e);
if(month == mm && year == yy) {
gp.drawCalDate(15, 95, "center", date, stDay, month, 0x0, 0x94fb, 0xac7d);
}
}
else if(diff(instX0, instX1)>10 || diff(instY0, instY1)>10) continue;
// Date in detail with events
else if(instX1>15 && instX1<225 && instY1>125 && instY1<125+30*numRow) {
int boxI = (instY1-125)/30;
int boxJ = (instX1-15)/30;
int rawDate = gp.dateCalBox(boxI, boxJ, stDay);
if(rawDate > 0 && rawDate <= maxD) {
tft.fillScreen(0x0); // clear screen
calendarDateEventUI(rawDate, month, year);
tft.fillScreen(0x0);
bool highlightDate = (month == mm && year == yy)? true:false;
gp.drawCalUI("center", stDay, date, highlightDate, month, maxD, year);
}
}
// Change Year
// Previous Year
else if(instX1>60 && instX1<80 && instY1>44 && instY1<64) {
// Erase Previous
gp.drawCalYear(60, year, 0x0);
tft.fillRect(15,95, 212,212, 0x0);
// Update
year--;
if(month == 2) maxD = la.daysInMonth(month, year);
stDay = la.dateToDay(1, month, year);
// Re draw
gp.drawCalYear(60, year, 0xffff);
bool highlightDate = (month == mm && year == yy)? true:false;
gp.drawCalUI("center", stDay, date, highlightDate, month, maxD, year);
}
// Next Year
else if(instX1>160 && instX1<180 && instY1>44 && instY1<64) {
// Erase Previous
gp.drawCalYear(60, year, 0x0);
tft.fillRect(15,95, 212,212, 0x0);
// Update
year++;
if(month == 2) maxD = la.daysInMonth(month, year);
stDay = la.dateToDay(1, month, year);
// Re draw
gp.drawCalYear(60, year, 0xffff);
bool highlightDate = (month == mm && year == yy)? true:false;
gp.drawCalUI("center", stDay, date, highlightDate, month, maxD, year);
}
}
}
}
}
void editScreen() {
while(1) {
// Time Edit Screen
gp.drawTimeEditUI(hr, mi, se, day, dd, mm, yy, posMonth, posDay, maxDay);
int hr1=hr, mi1=mi, se1=se;
int day1=day, dd1=dd, mm1=mm, yy1=yy;
int posM = posMonth, posD=posDay, maxD=maxDay;
while(1) {
bool longPress = false;
if(ts.touched()) {
int instX0 = tx(), instY0 = ty();
// Back Button
if(instX0>=5 && instX0<20 && instY0>=5 && instY0<22) return;
// Time Edit Buttons
else if(instX0>110 && instX0<130 && instY0>23 && instY0<213) {
// Up Buttons
if(((instY0+47)/70 - (instY0+27)/70) == 1) {
int btn = (instY0+47)/70;
switch(btn) {
case 1:
gp.printIntAsStr(30,20, &SmallFont, 0x0, hr1);
hr1 = (hr1+1)%24;
gp.printIntAsStr(30,20, &SmallFont, 0xffff, hr1);
break;
case 2:
gp.printIntAsStr(30,90, &SmallFont, 0x0, mi1);
mi1 = (mi1+1)%60;
gp.printIntAsStr(30,90, &SmallFont, 0xffff, mi1);
break;
case 3:
gp.printIntAsStr(30,160, &SmallFont, 0x0, se1);
se1 = (se1+1)%60;
gp.printIntAsStr(30,160, &SmallFont, 0xffff, se1);
break;
}
delay(20);
}
// Down Buttons
else if(((instY0+17)/70 - (instY0-3)/70) == 1) {
int btn = (instY0+17)/70;
switch(btn) {
case 1:
gp.printIntAsStr(30,20, &SmallFont, 0x0, hr1);
hr1 = ((hr1-1)<0)? 23: hr1-1;
gp.printIntAsStr(30,20, &SmallFont, 0xffff, hr1);
break;
case 2:
gp.printIntAsStr(30,90, &SmallFont, 0x0, mi1);
mi1 = ((mi1-1)<0)? 59: mi1-1;
gp.printIntAsStr(30,90, &SmallFont, 0xffff, mi1);
break;
case 3:
gp.printIntAsStr(30,160, &SmallFont, 0x0, se1);
se1 = ((se1-1)<0)? 59: se1-1;
gp.printIntAsStr(30,160, &SmallFont, 0xffff, se1);
break;
}
delay(20);
}
}
// Date Edit Buttons
else if(instY0>230 && instY0<252) {
// Long Press
int instX[2] = {instX0, instX0};
int instY[2] = {instY0, instY0};
while(ts.touched()) {
instX[0] = instX[1];
instY[0] = instY[1];
instX[1] = tx();
instY[1] = ty();
}
int instX1 = (instX[1] == 240) ? instX[0] : instX[1];
int instY1 = (instY[1] == 320) ? instY[0] : instY[1];
if(diff(instX0, instX1)>10 || diff(instY0, instY1)>10) continue;
// Left Button
if(instX0<20) {
if(posD==1) continue;
posD -= 8;
tft.fillRect(24,230, 190,22, 0x0); // clear space
gp.drawDates(24, 230, posD, maxD+1, 0xffff);
if(dd1>=posD && dd1<=posD+8) gp.drawDate(24, 230, posD, dd1, 0x07ff);
}
// Right Button
else if(instX0>220) {
if(posD==25) continue;
posD += 8;
tft.fillRect(24,230, 190,22, 0x0); // clear space
gp.drawDates(24, 230, posD, maxD+1, 0xffff);
if(dd1>=posD && dd1<=posD+8) gp.drawDate(24, 230, posD, dd1, 0x07ff);
}
// Select Date
else if(instX0>24 && instX0<214) {
int date = posD + (instX0-24)/24;
if(date > maxD) continue; // avoiding invalid date selection
if(dd1>=posD && dd1<=posD+8) gp.drawDate(24, 230, posD, dd1, 0xffff);
gp.drawDay(150, 35, day1, 0xffff);
dd1 = date;
day1 = la.dateToDay(dd1, mm1, yy1);
gp.drawDate(24, 230, posD, dd1, 0x07ff);
gp.drawDay(150, 35, day1, 0x3a1f);
}
}
// Month Edit Buttons
else if(instX0>12 && instX0<228 && instY0>260 && instY0<280) {
// Long Press
int instX[2] = {instX0, instX0};
int instY[2] = {instY0, instY0};
while(ts.touched()) {
instX[0] = instX[1];
instY[0] = instY[1];
instX[1] = tx();
instY[1] = ty();
}
int instX1 = (instX[1] == 240) ? instX[0] : instX[1];
int instY1 = (instY[1] == 320) ? instY[0] : instY[1];
if(diff(instX0, instX1)>10 || diff(instY0, instY1)>10) continue;
// Left Button
if(instX0<32) {
if(posM==1) continue;
posM -= 4;
tft.fillRect(36,260, 166,20, 0x0); // clear space
gp.drawMonths(36, 260, posM, 0xffff);
if(mm1>=posM && mm1<=posM+4) gp.drawMonth(36, 260, posM, mm1, 0x07ff);
}
// Right Button
else if(instX0>208) {
if(posM==9) continue;
posM += 4;
tft.fillRect(36,260, 166,20, 0x0); // clear space
gp.drawMonths(36, 260, posM, 0xffff);
if(mm1>=posM && mm1<=posM+4) gp.drawMonth(36, 260, posM, mm1, 0x07ff);
}
// Select Month
else if(instX0>36 && instX0<202) {
if(mm1>=posM && mm1<=posM+4) gp.drawMonth(36, 260, posM, mm1, 0xffff);
gp.drawDay(150, 35, day1, 0xffff);
mm1 = posM + (instX0-36)/42;
maxD = la.daysInMonth(mm1, yy1);
// Avoid Max Day exeed
if(dd1>maxD) dd1=maxD;
day1 = la.dateToDay(dd1, mm1, yy1);
gp.drawMonth(36, 260, posM, mm1, 0x07ff);
gp.drawDay(150, 35, day1, 0x3a1f);
// Set Max Date According to Month
if(posD==25) {
tft.fillRect(24,230, 190,22, 0x0); // clear space
gp.drawDates(24, 230, posD, maxD+1, 0xffff);
gp.drawDate(24, 230, posD, dd1, 0x07ff);
}
}
}
// Year Edit Button
else if(instX0>45 && instX0<195 && instY0>290 && instY0<310) {
bool btnPressed = false;
// Year Left part Down Button
if(instX0<65) {
int yl = yy1/100;
if(yl == 0) continue;
gp.drawYearL(65, 290, yl, 0x0, 0xffff);
yl--;
yy1 -=100;
gp.drawYearL(65, 290, yl, 0x3fef, 0xffff);
btnPressed = true;
}
// Year Left part Up Button
else if(instX0>95 && instX0<115) {
int yl = yy1/100;
if(yl==99) continue;
gp.drawYearL(65, 290, yl, 0x0, 0xffff);
yl++;
yy1 += 100;
gp.drawYearL(65, 290, yl, 0x3fef, 0xffff);
btnPressed = true;
}
// Year Right part Down Button
else if(instX0>125 && instX0<145) {
int yr = yy1%100;
if(yr==0) continue;
gp.drawYearR(145, 290, yr, 0x0, 0xffff);
yr--;
yy1--;
gp.drawYearR(145, 290, yr, 0x3fef, 0xffff);
btnPressed = true;
}
// Year Right part Down Button
else if(instX0>175 && instX0<195) {
int yr = yy1%100;
if(yr==99) continue;
gp.drawYearR(145, 290, yr, 0x0, 0xffff);
yr++;
yy1++;
gp.drawYearR(145, 290, yr, 0x3fef, 0xffff);
btnPressed = true;
}
// Adjust Day and Max Day According to Year
if(btnPressed) {
maxD = la.daysInMonth(mm1, yy1);
if(dd1>maxD) dd1=maxD;
if(posD==25 && mm1==2) {
tft.fillRect(24,230, 190,22, 0x0); // clear space
gp.drawDates(24, 230, posD, maxD+1, 0xffff);
gp.drawDate(24, 230, posD, dd1, 0x07ff);
}
gp.drawDay(150, 35, day1, 0xffff);
day1 = la.dateToDay(dd1, mm1, yy1);
gp.drawDay(150, 35, day1, 0x3a1f);
}
delay(25);
}
// Save Changes
else if(instX0>206 && instX0<228 && instY0>5 && instY0<20) {
hr=hr1; mi=mi1; se=se1;
day=day1; dd=dd1; mm=mm1; yy=yy1;
posMonth = 1 + 4*(mm/4);
posDay = 1 + 8*(dd/8);
maxDay = la.daysInMonth(mm, yy);
return;
}
}
}
}
}
void homeScreen() {
bool optVisible = false;
int hr1=hr, mi1=mi, day1=day;
int dd1=dd, mm1=mm, yy1=yy;
while(1) {
gp.drawHomeTimeUI(hr1, mi1, day1, dd1, mm1, yy1, 0x0);
hr1=hr; mi1=mi; day1=day;
dd1=dd; mm1=mm; yy1=yy;
gp.drawHomeTimeUI(hr1, mi1, day1, dd1, mm1, yy1, 0xffff);
frame = false;
while(!frame) {
if(ts.touched()) {
int instX0 = tx();
int instY0 = ty();
int instX[2] = {instX0, instX0};
int instY[2] = {instY0, instY0};
while(ts.touched()) {
instX[0] = instX[1];
instY[0] = instY[1];
instX[1] = tx();
instY[1] = ty();
}
int instX1 = (instX[1] == 240) ? instX[0] : instX[1];
int instY1 = (instY[1] == 320) ? instY[0] : instY[1];
// Swipe up for Calendar
if(instY0-instY1 > 20) {
tft.fillScreen(0x0); // clear screen
// Calendar UI
calendarScreen();
tft.fillScreen(0x0); // clear screen
break;
}
else if(diff(instX0, instX1)>10 || diff(instY0, instY1)>10) continue;
if(optVisible) {
if(instX1>210 && instX1<230 && instY1>5 && instY1<25) {
// time edit screen
editScreen();
tft.fillScreen(0x0); // clearing screen
break;
}
}
optVisible = optVisible ? false : true;
if(optVisible) gp.drawEdit(210, 5, 0xffff);
else gp.drawEdit(210, 5, 0x0);
delay(10);
}
}
}
}
void loop() {
// bool optVisible = false;
homeScreen();
//gp.drawEdit(10, 10, 0xffff);
//unsigned long startTime = millis();
}