/*************************************************
  With thanks to Volos
    https://www.youtube.com/watch?v=cBtsLxZ13hQ
  Updated for ESP32 Core V3.0.0   June 2025
*************************************************/
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite sprite = TFT_eSprite(&tft);
//............INPUT PINS............switches and buttons
#define THROTTLE 43
#define BRIGHTNESS 14
//......................................colors
#define backColor 0x0026
#define gaugeColor 0x055D
#define dataColor 0x0311
#define purple 0xEA16
#define needleColor 0xF811
//............................dont edit this
int cx=75;
int cy=75;
int r=72;
int ir=70;
int n=0;
int angle=0;
float x2[360]; //outer points of RPM gaouges
float y2[360];
float px2[360]; //ineer point of RPM gaouges
float py2[360];
float lx2[360]; //text of RPM gaouges
float ly2[360];
float nx2[360]; //needle low of RPM gaouges
float ny2[360];
double rad=0.01745;
unsigned short color1;
unsigned short color2;
float sA;
float rA;
int blinkPeriod=500;
unsigned long currentTimeL=0;
unsigned long currentTimeR=0;
int brightnesses[5]={40,80,120,150,240};
int selectedBrightness=3;
int deb1=0;
int deb2=0;
int debB=0;
//........................................................colors
unsigned short blockColor[4]={0x0312,0x0290,0x01EC,0x016A};
unsigned short dirColor[2]={0x0312,TFT_ORANGE};
unsigned short lightColor[3]={0x01EC,0x0FA8,0xB79F};
// .........important variables
float rpmAngle=5;  //.....RPM variable 0-9
float sweepAngle=5;  //.....RPM variable 0-9
void setup() {
  pinMode(THROTTLE,INPUT_PULLUP);
 
  tft.init();
    tft.setRotation(1);
    tft.fillScreen(backColor);
    sprite.createSprite(320,150);
    sprite.setSwapBytes(true);
    sprite.setTextDatum(4);
    sprite.setTextColor(TFT_WHITE,backColor);
    sprite.setTextDatum(4);
     ledcAttach(0, 10000, 8);
//    ledcAttachPin(38, 0);
     ledcWrite(0, brightnesses[selectedBrightness]);  //brightnes of screen
  int a=120;
  for(int i=0;i<360;i++)
    {
       x2[i]=((r-10)*cos(rad*a))+320-cx;
       y2[i]=((r-10)*sin(rad*a))+cy;
       px2[i]=((r-14)*cos(rad*a))+320-cx;
       py2[i]=((r-14)*sin(rad*a))+cy;
       lx2[i]=((r-24)*cos(rad*a))+320-cx;
       ly2[i]=((r-24)*sin(rad*a))+cy;
       nx2[i]=((r-36)*cos(rad*a))+320-cx;
       ny2[i]=((r-36)*sin(rad*a))+cy;
       a++;
       if(a==360)
       a=0;
    }     
}
void draw()
{
  sprite.fillSprite(backColor);
   sprite.fillSmoothCircle(320-cx, cy, r+2, backColor);
  
  for(int i=0;i<5;i++)
   {
   if(i<=2)
   sprite.fillRect(230+(7*i),70,5,5,TFT_WHITE);   /// fuel  rect
   else
   sprite.drawRect(230+(7*i),70,5,5,TFT_WHITE); //empty fuel rect
   }   
    sprite.fillSmoothRoundRect(240,84,9,16,2,TFT_WHITE,blockColor[1]);
    sprite.fillSmoothRoundRect(251,86,2,14,2,TFT_WHITE,blockColor[1]);
    sprite.fillSmoothRoundRect(241,86,7,5,1,blockColor[1],TFT_WHITE);
    sprite.drawLine(238,99,251,99,TFT_WHITE);  //pumpimage
  sprite.drawSmoothArc(320-cx, cy, r, ir, 30, 330, gaugeColor, backColor);
  sprite.drawSmoothArc(320-cx, cy, r-5, r-6, 30, 330, TFT_WHITE, backColor);
  sprite.drawSmoothArc(320-cx, cy, r-38, ir-37, 10, 350, gaugeColor, backColor);
  
   //.....................................................draw GAUGES
 
      for(int i=0;i<19;i++){
      if(i<20) {color1=gaugeColor; color2=TFT_WHITE;} else {color1=purple; color2=purple;}
  if(i%2==0) {
  sprite.drawWedgeLine(x2[i*16],y2[i*16],px2[i*16],py2[i*16],2,1,color1);
  sprite.setTextColor(color2,backColor);
  sprite.drawString(String(i/2),lx2[i*16],ly2[i*16]);
  }else
  sprite.drawWedgeLine(x2[i*16],y2[i*16],px2[i*16],py2[i*16],1,1,color2);
  }
  // ........................................needles draw
     rA=2*rpmAngle*1.6;
  
   sprite.drawWedgeLine(px2[(int)rA],py2[(int)rA],nx2[(int)rA],ny2[(int)rA],2,2,needleColor);
  //.....................................drawing  TEXT
   
 
  sprite.setTextColor(TFT_ORANGE,backColor);
  sprite.drawString("x1000",320-cx,136);
  sprite.drawString("RPM",320-cx,126);
   //..............................................push Sprite to screen  
   sprite.pushSprite(0,10);
  
}
/*///////////////////////////////////////////////////////////////////////////
void sweep()
{
  sprite.fillSprite(backColor);
   sprite.fillSmoothCircle(320-cx, cy, r+2, backColor);
  
  for(int i=0;i<5;i++)
   {
   if(i<=2)
   sprite.fillRect(230+(7*i),70,5,5,TFT_WHITE);   /// fuel  rect
   else
   sprite.drawRect(230+(7*i),70,5,5,TFT_WHITE); //empty fuel rect
   }   
    sprite.fillSmoothRoundRect(240,84,9,16,2,TFT_WHITE,blockColor[1]);
    sprite.fillSmoothRoundRect(251,86,2,14,2,TFT_WHITE,blockColor[1]);
    sprite.fillSmoothRoundRect(241,86,7,5,1,blockColor[1],TFT_WHITE);
    sprite.drawLine(238,99,251,99,TFT_WHITE);  //pumpimage
  sprite.drawSmoothArc(320-cx, cy, r, ir, 30, 330, gaugeColor, backColor);
  sprite.drawSmoothArc(320-cx, cy, r-5, r-6, 30, 330, TFT_WHITE, backColor);
  sprite.drawSmoothArc(320-cx, cy, r-38, ir-37, 10, 350, gaugeColor, backColor);
  
   //.....................................................draw GAUGES
 
      for(int i=0;i<19;i++){
      if(i<20) {color1=gaugeColor; color2=TFT_WHITE;} else {color1=purple; color2=purple;}
  if(i%2==0) {
  sprite.drawWedgeLine(x2[i*16],y2[i*16],px2[i*16],py2[i*16],2,1,color1);
  sprite.setTextColor(color2,backColor);
  sprite.drawString(String(i/2),lx2[i*16],ly2[i*16]);
  }else
  sprite.drawWedgeLine(x2[i*16],y2[i*16],px2[i*16],py2[i*16],1,1,color2);
  }
 
  //.....................................drawing  TEXT
   
 
  sprite.setTextColor(TFT_ORANGE,backColor);
  sprite.drawString("x1000",320-cx,136);
  sprite.drawString("RPM",320-cx,126);
   //..............................................push Sprite to screen  
   sprite.pushSprite(0,10);
  
   // ........................................needles draw
  for(sweepAngle=0;sweepAngle<270;sweepAngle++){
     rA=2*sweepAngle*1.6;
  
   sprite.drawWedgeLine(px2[(int)rA],py2[(int)rA],nx2[(int)rA],ny2[(int)rA],2,2,needleColor);
  }
}
sweep();
//////////////////////////////////////////////////////////////////////////*/
//int blinking=1;
void loop() {
    if(digitalRead(BRIGHTNESS)==0)
  {
  if(debB==0)
    {
      debB=1;
      selectedBrightness++;
      if(selectedBrightness==5) selectedBrightness=0;
      ledcWrite(0, brightnesses[selectedBrightness]);  //brightnes of screen
     }
  }else debB=0;
 
  draw();
  
   if(digitalRead(THROTTLE)==0 && rpmAngle<75)
  {rpmAngle=rpmAngle+1;} 
   if(digitalRead(THROTTLE)==1 && rpmAngle>0)
  { if(rpmAngle>=3)
    rpmAngle=rpmAngle-3;
    else
    rpmAngle=0;
    } 
}