#include <Time.h>
#include <Wire.h>
#include <RtcDS3231.h>
RtcDS3231<TwoWire> Rtc(Wire);

#define DS3231_I2C_ADDR             0x68
#define DS3231_TEMPERATURE_ADDR     0x11

#define RXD2 19    //1 serial1=1,3
#define TXD2 18    //3 serial2=16,17

/*
TFT_BLACK       
TFT_NAVY        
TFT_DARKGREEN   
TFT_DARKCYAN    
TFT_MAROON       
TFT_PURPLE      
TFT_OLIVE       
TFT_LIGHTGREY   
TFT_DARKGREY    
TFT_BLUE        
TFT_GREEN       
TFT_CYAN        
TFT_RED         
TFT_MAGENTA     
TFT_YELLOW      
TFT_WHITE       
TFT_ORANGE      
TFT_GREENYELLOW 
TFT_PINK              
TFT_BROWN       
TFT_GOLD        
TFT_SILVER      
TFT_SKYBLUE     
TFT_VIOLET      

*/
//#include <SPI.h>
#include <TFT_eSPI.h> // Hardware-specific library
TFT_eSPI tft = TFT_eSPI();       // Invoke custom library

uint16_t ccenterx,ccentery;//center x,y of the clock
const uint16_t cradius = 2.65*63;//radius of the clock
const float scosConst = 0.0174532925;
float sx = 0, sy = 1, mx = 1, my = 0, hx = -1, hy = 0;
float sdeg=0, mdeg=0, hdeg=0;
uint16_t osx,osy,omx,omy,ohx,ohy;
uint16_t x0 = 0, x1 = 0, yy0 = 0, yy1 = 0;

int vshift=80;
int thick=4;
String dg;
int st = 40;
String dow[7]  = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};  // Sunday is dayOfWeek 0
String moy[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; // January is month 0

void setup(){
Serial.begin(115200);
Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);  //16,17
Serial.println("Serial Txd is on pin: "+String(TXD2));
Serial.println("Serial Rxd is on pin: "+String(RXD2));
//Wire.begin(I2C_SDA, I2C_SCL);  
  
  tft.init();
  tft.setRotation(2);
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_BLACK); // Background is not defined so it is transparent
  tft.drawRect(0, 7, tft.width()-2, 305+22, TFT_WHITE);

//tft.fillRect(10,10,5,200,TFT_WHITE);
//tft.fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color);
//thickline(10,10,200,50,10,TFT_WHITE);
  ccenterx = tft.width()/2;
  ccentery = tft.height()/2+10;
  osx = ccenterx;
  osy = ccentery;
  omx = ccenterx;
  omy = ccentery;
  ohx = ccenterx;
  ohy = ccentery;
  drawClockFace();// Draw clock face
//tft.setTextFont(3);


  Rtc.Begin();
  RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
//    printDateTime(compiled);
    Serial.println();
    if (!Rtc.IsDateTimeValid())    {
        // Common Cuases:
        //    1) first time you ran and the device wasn't running yet
        //    2) the battery on the device is low or even missing

        Serial.println("RTC lost confidence in the DateTime!");

        // following line sets the RTC to the date & time this sketch was compiled
        // it will also reset the valid flag internally unless the Rtc device is
        // having an issue

        Rtc.SetDateTime(compiled);
    }

    if (!Rtc.GetIsRunning())    {
        Serial.println("RTC was not actively running, starting now");
        Rtc.SetIsRunning(true);
    }

    RtcDateTime now = Rtc.GetDateTime();
    if (now < compiled)     {
        Serial.println("RTC is older than compile time!  (Updating DateTime)");
        Rtc.SetDateTime(compiled);
    }
    else if (now > compiled)     {
        Serial.println("RTC is newer than compile time. (this is expected)");
    }
    else if (now == compiled)     {
        Serial.println("RTC is the same as compile time! (not expected but all is fine)");
    }

    // never assume the Rtc was last configured by you, so
    // just clear them to your needed state
    Rtc.Enable32kHzPin(false);
    Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone); 
RtcDateTime t = Rtc.GetDateTime();  
RtcTemperature temp = Rtc.GetTemperature();
uint8_t data1[30];
String s1=" ";  
sprintf((char*)data1, "-%02d%02d-%02d%02d%02d",t.Day(),t.Month(),t.Hour(),t.Minute(),t.Second() );
Serial.print(dow[t.DayOfWeek()]);
Serial.println((char*)data1);
}


void loop() {
RtcDateTime t = Rtc.GetDateTime();  
RtcTemperature temp = Rtc.GetTemperature();
float tempC = DS3231_get_treg(); 

uint8_t data1[30];
String s1=" ";  
uint32_t currentMillis = millis();
uint32_t ss = currentMillis / 1000;
int ms = currentMillis % 1000;
sprintf((char*)data1, "%s-%02d%02d-%02d%02d%02d.%3d",dow[t.DayOfWeek()],t.Day(),t.Month(),t.Hour(),t.Minute(),t.Second(),ms );
//Serial.println((char*)data1);
//Serial.println(tempC);
drawClockHands(t.Hour(),t.Minute(),t.Second());

tft.setTextColor(TFT_YELLOW,TFT_BLACK);
tft.drawString(dow[t.DayOfWeek()]+","+t.Day()+" "+moy[t.Month()-1]+" "+t.Year()+", T:"+tempC, 5, 375,4);
tft.setTextColor(TFT_GREEN,TFT_BLACK);
tft.drawString(printDigits(t.Hour() )+":"+printDigits(t.Minute())+":"+printDigits(t.Second())+"."+ms, 5, 350+65,6.5);
//delay(1);  //100
}


void thickline2(int x, int y, int x1, int y1, int size, int color) {
  float dx = (size / 2.0) * (y - y1) / sqrt(sq(x - x1) + sq(y - y1));
  float dy = (size / 2.0) * (x - x1) / sqrt(sq(x - x1) + sq(y - y1));
  tft.fillTriangle(x + dx, y - dy, x - dx,  y + dy,  x1 + dx, y1 - dy, color);
  tft.fillTriangle(x - dx, y + dy, x1 - dx, y1 + dy, x1 + dx, y1 - dy, color);
}

void thickcircle(int16_t x0, int16_t y0, int16_t r, int pixel, uint16_t color) {
  for(int i=r;i<=r+pixel;i++){
   tft.drawCircle(x0, y0, i, color);
  }
}

String printDigits(int digits){
  if(digits < 10)
  dg= "0"+String(digits);
  else dg = String(digits);
  return dg;
}
 int p,q,p1,q1,hr;
 void drawClockFace(){
//  cradius = cradius - 20;
  tft.fillCircle(ccenterx, ccentery-vshift, cradius-10, TFT_WHITE);  //blue
  tft.fillCircle(ccenterx, ccentery-vshift, cradius-4-10, TFT_BLACK); //black
  // Draw 12 lines
  
  for(int i = 0; i<360; i+= 30) {
    hr = i/30;
    if(hr==0) hr=12;
    // Serial.println(hr);
    sx = cos((i-90)*scosConst);
    sy = sin((i-90)*scosConst);
    x0 = sx*(cradius-4-10)+ccenterx;
    yy0 = sy*(cradius-4-10)+ccentery;
    x1 = sx*(cradius-11-10)+ccenterx;
    yy1 = sy*(cradius-11-10)+ccentery;
    tft.drawLine(x0, yy0-vshift, x1, yy1-vshift, TFT_CYAN);  //blue
 
    tft.setTextColor(TFT_YELLOW,TFT_BLACK);

   int x00 = sx*(cradius-4-10-10)+ccenterx;
   int yy00 = sy*(cradius-4-10-10)+ccentery;
   int x11 = sx*(cradius-11-10-10)+ccenterx;
   int yy11 = sy*(cradius-11-10-10)+ccentery;
 
 p = (x00+x11)/2;
 q = (yy11+yy00)/2-vshift-11;
 tft.drawString(String(hr), p,q,4);
   }
}

void drawClockHands(uint8_t h,uint8_t m,uint8_t s){
  // Pre-compute hand degrees, x & y coords for a fast screen update
  sdeg = s * 6;                  // 0-59 -> 0-354
  mdeg = m * 6 + sdeg * 0.01666667;  // 0-59 -> 0-360 - includes seconds
  hdeg = h * 30 + mdeg * 0.0833333;  // 0-11 -> 0-360 - includes minutes and seconds
  hx = cos((hdeg-90)*scosConst);    
  hy = sin((hdeg-90)*scosConst);
  mx = cos((mdeg-90)*scosConst);    
  my = sin((mdeg-90)*scosConst);
  sx = cos((sdeg-90)*scosConst);    
  sy = sin((sdeg-90)*scosConst);

// Erase just old hand positions
  thickline2(ohx, ohy, ccenterx+1, ccentery+1-vshift,thick, TFT_BLACK);  
  thickline2(omx, omy, ccenterx+1, ccentery+1-vshift,thick, TFT_BLACK);
  thickline2(osx, osy, ccenterx+1, ccentery+1-vshift,thick, TFT_BLACK);


// Draw new hand positions  
  thickline2(hx*(cradius-28-st)+ccenterx+1, hy*(cradius-28-st)+ccentery+1-vshift, ccenterx+1, ccentery+1-vshift,thick, TFT_GREEN);  //white
  thickline2(mx*(cradius-17-st)+ccenterx+1, my*(cradius-17-st)+ccentery+1-vshift, ccenterx+1, ccentery+1-vshift,thick, TFT_WHITE);
  thickline2(sx*(cradius-54)+ccenterx+1, sy*(cradius-54)+ccentery+1-vshift, ccenterx+1, ccentery+1-vshift,thick, TFT_YELLOW);


/*
// Erase just old hand positions
  tft.drawLine(ohx, ohy, ccenterx+1, ccentery+1-vshift, TFT_BLACK);  
  tft.drawLine(omx, omy, ccenterx+1, ccentery+1-vshift, TFT_BLACK);
  tft.drawLine(osx, osy, ccenterx+1, ccentery+1-vshift, TFT_BLACK); 

// Draw new hand positions 
  tft.drawLine(hx*(cradius-28-st)+ccenterx+1, hy*(cradius-28-st)+ccentery+1-vshift, ccenterx+1, ccentery+1-vshift, TFT_GREEN);  //white
  tft.drawLine(mx*(cradius-17-st)+ccenterx+1, my*(cradius-17-st)+ccentery+1-vshift, ccenterx+1, ccentery+1-vshift, TFT_WHITE);
  tft.drawLine(sx*(cradius-14-st)+ccenterx+1, sy*(cradius-14-st)+ccentery+1-vshift, ccenterx+1, ccentery+1-vshift, TFT_YELLOW);
*/

tft.fillCircle(ccenterx+1, ccentery+1-vshift, 3, TFT_RED);
  osx = sx*(cradius-14-st)+ccenterx+1;
  osy = sy*(cradius-14-st)+ccentery+1-vshift;
  omx = mx*(cradius-17-st)+ccenterx+1;
  omy = my*(cradius-17-st)+ccentery+1-vshift;
  ohx = hx*(cradius-28-st)+ccenterx+1;
  ohy = hy*(cradius-28-st)+ccentery+1-vshift;
}

float DS3231_get_treg(){
 //   int rv;  // Reads the temperature as an int, to save memory
    float rv;
    uint8_t temp_msb, temp_lsb;
    int8_t nint;

    Wire.beginTransmission(DS3231_I2C_ADDR);
    Wire.write(DS3231_TEMPERATURE_ADDR);
    Wire.endTransmission();

    Wire.requestFrom(DS3231_I2C_ADDR, 2);
    temp_msb = Wire.read();
    temp_lsb = Wire.read() >> 6;

    if ((temp_msb & 0x80) != 0)
        nint = temp_msb | ~((1 << 8) - 1);      // if negative get two's complement
    else
        nint = temp_msb;

    rv = 0.25 * temp_lsb + nint;
    return rv;
}
