#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#define TFT_DC 2
#define TFT_CS 3
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
#define IR_PIN A0
uint32_t lastCode;
#define CODE_1 3476094720
#define CODE_2 3877175040
#define CODE_3 223943040
#define CODE_4 4010868480
#define CODE_ADD 4244832000
#define CODE_SUB 1738080000
#define CODE_C 1336999680
#define CODE_POWER 1570963200
#define CODE_MUL 534839040
#define CODE_EQUAL 1470693120
#define CODE_DIV 1871773440
#define CODE_MENU 501415680
#define CODE_BS 1036189440
uint8_t pageMode;
int tempVal;
unsigned long stopwatchStart;
bool stopwatchRun;
uint8_t bgR,bgG,bgB,colorSel;
long counter;
uint8_t pagePopup;
void printCenter(const char *txt,int y,uint16_t color,uint8_t size)
{
int16_t x1,y1;uint16_t w,h;
tft.setTextSize(size);
tft.getTextBounds(txt,0,y,&x1,&y1,&w,&h);
tft.setCursor((tft.width()-w)/2,y);
tft.setTextColor(color);
tft.println(txt);
}
void drawProgress(uint16_t x,uint16_t y,uint16_t w,uint16_t h,int val,int maxVal,uint16_t fill,uint16_t border)
{
tft.drawRect(x,y,w,h,border);
tft.fillRect(x+1,y+1,map(val,0,maxVal,0,w),h-2,fill);
}
// 底部状态栏+按键提示
void drawTip(const char *tip)
{
tft.drawFastHLine(0,260,320,ILI9341_DARKGREY);
tft.setTextSize(1);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(5,265);
tft.print(tip);
}
uint32_t readIR()
{
if(digitalRead(IR_PIN))return 0;
uint32_t t=micros();
while(!digitalRead(IR_PIN));
uint32_t low=micros()-t;
if(low<5000){
while(digitalRead(IR_PIN));
while(!digitalRead(IR_PIN));
return lastCode;
}
while(digitalRead(IR_PIN));
uint32_t code=0;
for(uint8_t i=0;i<32;i++){
while(!digitalRead(IR_PIN));
uint32_t s=micros();
while(digitalRead(IR_PIN));
if(micros()-s>1000)code|=1UL<<i;
}
lastCode=code;
return code;
}
void showWelcome()
{
tft.fillScreen(tft.color565(bgR,bgG,bgB));
printCenter("DASH",60,ILI9341_YELLOW,3);
printCenter("<< / >> Switch Mode",120,ILI9341_CYAN,2);
drawTip("Press any key to start");
pagePopup = 1;
}
void renderTemp()
{
tft.fillScreen(tft.color565(bgR,bgG,bgB));
tft.setTextSize(2);
tft.setTextColor(ILI9341_RED);
tft.setCursor(10,10);
tft.print("TEMP");
drawProgress(10,50,300,25,tempVal,50,ILI9341_RED,ILI9341_WHITE);
tft.setTextSize(3);
tft.setCursor(10,90);
tft.print(tempVal);
tft.print(" C");
drawTip("+/- adjust C=reset");
pagePopup = 0;
}
void renderStopwatch()
{
tft.fillScreen(tft.color565(bgR,bgG,bgB));
tft.setTextSize(2);
tft.setTextColor(ILI9341_BLUE);
tft.setCursor(10,10);
tft.print("TIME");
unsigned long ms = stopwatchRun ? (millis()-stopwatchStart) : stopwatchStart;
tft.setTextSize(3);
tft.setCursor(10,80);
tft.print(ms/1000);
tft.print(".");
tft.print(ms%1000);
drawTip("Play=start BS=clear");
pagePopup = 0;
}
void renderRGB()
{
tft.fillScreen(tft.color565(bgR,bgG,bgB));
tft.setTextSize(2);
tft.setTextColor(ILI9341_MAGENTA);
tft.setCursor(10,10);
tft.print("RGB");
drawProgress(10,40,300,15,bgR,255,ILI9341_RED,ILI9341_WHITE);
drawProgress(10,70,300,15,bgG,255,ILI9341_GREEN,ILI9341_WHITE);
drawProgress(10,100,300,15,bgB,255,ILI9341_BLUE,ILI9341_WHITE);
drawTip("C=ch +/- adjust");
pagePopup = 0;
}
void renderCounter()
{
tft.fillScreen(tft.color565(bgR,bgG,bgB));
tft.setTextSize(2);
tft.setTextColor(ILI9341_YELLOW);
tft.setCursor(10,10);
tft.print("CNT");
tft.setTextSize(4);
tft.setCursor(10,80);
tft.print(counter);
drawTip("+/- add BS=clear");
pagePopup = 0;
}
void refreshPage()
{
switch(pageMode)
{
case 1: renderTemp(); break;
case 2: renderStopwatch(); break;
case 3: renderRGB(); break;
case 4: renderCounter(); break;
default: renderTemp(); break;
}
}
void dashReset()
{
pageMode=0;
tempVal=25;
stopwatchStart=0; stopwatchRun=false;
bgR=0;bgG=0;bgB=0;colorSel=0;
counter=0;
showWelcome();
}
void setup()
{
Serial.begin(115200);
pinMode(IR_PIN, INPUT);
tft.begin();
dashReset();
}
void loop()
{
uint32_t code = readIR();
if(code==0){
delay(5);
goto serialCmd;
}
if(pagePopup==1){
pageMode = 1;
refreshPage();
delay(100);
return;
}
// 全局切页
if(code==CODE_1) pageMode=1;
else if(code==CODE_2) pageMode=2;
else if(code==CODE_3) pageMode=3;
else if(code==CODE_4) pageMode=4;
else if(code==CODE_MUL){pageMode--; if(pageMode<1)pageMode=4;}
else if(code==CODE_DIV){pageMode++; if(pageMode>4)pageMode=1;}
else if(code==CODE_POWER){dashReset();return;}
else if(code==CODE_MENU){pageMode++; if(pageMode>4)pageMode=1;}
// 页面功能
if(pageMode==1)
{
if(code==CODE_ADD) tempVal=constrain(tempVal+1,0,50);
else if(code==CODE_SUB) tempVal=constrain(tempVal-1,0,50);
else if(code==CODE_C) tempVal=25;
}
else if(pageMode==2)
{
if(code==CODE_EQUAL) stopwatchRun=!stopwatchRun;
else if(code==CODE_BS) stopwatchStart=0,stopwatchRun=false;
}
else if(pageMode==3)
{
if(code==CODE_C) colorSel=(colorSel+1)%3;
else if(code==CODE_ADD){
if(colorSel==0) bgR=constrain(bgR+10,0,255);
if(colorSel==1) bgG=constrain(bgG+10,0,255);
if(colorSel==2) bgB=constrain(bgB+10,0,255);
}
else if(code==CODE_SUB){
if(colorSel==0) bgR=constrain(bgR-10,0,255);
if(colorSel==1) bgG=constrain(bgG-10,0,255);
if(colorSel==2) bgB=constrain(bgB-10,0,255);
}
}
else if(pageMode==4)
{
if(code==CODE_ADD) counter++;
else if(code==CODE_SUB) counter--;
else if(code==CODE_BS) counter=0;
}
refreshPage();
delay(80);
serialCmd:
if(Serial.available()>0)
{
char cmd=Serial.read();
if(cmd>='1'&&cmd<='4') pageMode=cmd-'0';
if(cmd=='R') dashReset();
if(pagePopup==0) refreshPage();
}
}