/*
 * Gray_LifeClock
 * Code by: Gray Mack
 * Published at: https://wokwi.com/projects/397194902577285121
 * Description: A life clock. Days since my birth, to my est death and from one other date
 * Why I made this:
 * Just drempt it up from my own anguish
 * License: MIT license
 *          https://choosealicense.com/licenses/mit/
 * Created: 5/7/2024
 * Board: Arduino Uno or compatible
 * Select Board: Arduino Uno
 * Processor: ATMEGA328p
 * 
 * Connections:
 *  3 TM1637 displays with individual clock lines and shared data line
 *  (to be replaced with 8x7seg displays)
 * RTC DS1307
 *  (to be replaced with ds3231)
 * 
 * 05/07/2024 initial code creation
 * //2024
 * //2024
 * //2024 
*/

// ----[ configuration ]------------------------------------
#define SerialBaud 115200
#define USE_DS1307 true  // false = use DS3220
#define USE_TM1637 true  // false = use MAX
#define SET_TIME false

// ----[ included libraries ]--------------------------------
//#include <Time.h>  
#include <Wire.h>
#include <I2C_RTC.h>
#include <time.h>
//#include <DS1307RTC.h>

#if(USE_TM1637)
#include <TM1637Display.h>
#endif



// ----[ pin definitions ]-----------------------------------
const uint8_t Display1Clock = 2;
const uint8_t Display2Clock = 3;
const uint8_t Display3Clock = 4;
const uint8_t DisplaysData  = 5;

// ----[ constants ]-----------------------------------------
#define GET_UNIX_EPOCH false
#ifndef CalendarYrToTm
#define  CalendarYrToTm(Y)   ((Y) - 1970)
#endif
// ----[ predeclarations ]-----------------------------------

// ----[ global variables ]----------------------------------
#if(USE_TM1637)
TM1637Display DisplayDaysSinceBirth(Display1Clock, DisplaysData);
TM1637Display DisplayDaysToDeathEST(Display2Clock, DisplaysData);
TM1637Display DisplayDaysSinceX(Display3Clock, DisplaysData);
#endif

#if(USE_DS1307)
static DS1307 RTC;
#endif

time_t Birth;
time_t ProjectedDeath;
time_t Extra;

// ----[ code ]----------------------------------------------

void setup() {
  Serial.begin(SerialBaud);
  Serial.println("Hello GrayLifeClock!");

  TimeTest();


  RTC.begin();
  RTC.setHourMode(CLOCK_H12);
  #if(SET_TIME)
    RTC.setWeek(1);
    RTC.setDate(22,07,21);
    RTC.setTime(23,00,00);
  #endif
  //setSyncProvider(RTC.get);   // the function to get the time from the RTC
  //if(timeStatus()!= timeSet) 
  //  setTime(12, 00, 00, 1, 1, 2013); //(hr,min,sec,day,month,yr); 
  
  #define YEAR_OFFSET 30 // because Y2K years can only go back to 1/1/2000 not UNIX years of 1/1/1970

  struct tm t;
  // BIRTH
  t.tm_year = CalendarYrToTm(1970);
  t.tm_mon = 5;
  t.tm_mday = 21;
  t.tm_hour = 3;
  t.tm_min = 2;
  t.tm_sec = 0;
  Birth = mktime(&t);

  // EST DEATH / age 72
  t.tm_year = CalendarYrToTm(2042);
  t.tm_mon = 5;
  t.tm_mday = 21;
  t.tm_hour = 3;
  t.tm_min = 2;
  t.tm_sec = 0;
  ProjectedDeath = mktime(&t);

  t.tm_year = CalendarYrToTm(2011);
  t.tm_mon = 5;
  t.tm_mday = 20;
  t.tm_hour = 17;
  t.tm_min = 1;
  t.tm_sec = 0;
  Extra = mktime(&t);


  InitDisplays();
  TestDisplays();
}

void loop()
{
  
  struct tm tmnow;
  tmnow.tm_year = CalendarYrToTm(RTC.getYear());
  tmnow.tm_mon = RTC.getMonth();
  tmnow.tm_mday = RTC.getDay();
  tmnow.tm_hour = RTC.getHours();
  tmnow.tm_min = RTC.getMinutes();
  tmnow.tm_sec = RTC.getSeconds();
  time_t tnow = mktime(&tmnow);
  
  Serial.print(" tnow: ");
  Serial.println(tnow);     // 599468093

  Serial.print("birth: ");
  Serial.print(Birth);     // 536142376
  Serial.print(" ");
  //Serial.print(ctime(Birth));
  Serial.println();

  Serial.print("death: ");
  Serial.print(ProjectedDeath);     // 536142376
  Serial.print(" ");
  //Serial.print(ctime(ProjectedDeath));
  Serial.println();

  Serial.print("extra: ");
  Serial.print(Extra);     // 536142376
  Serial.print(" ");
  //Serial.print(ctime(Extra));
  Serial.println();


  uint32_t secAlive = difftimeUint(tnow, Birth);
  Serial.print("days alive: ");
  Serial.println(secAlive /60 / 60 / 24);   // 19710
  
  uint32_t secExtra = difftimeUint(tnow, Extra);
  Serial.print("days since extra: ");
  Serial.println(secExtra /60 / 60 / 24);   // 367

  uint32_t secRemain = difftimeUint(ProjectedDeath, tnow);
  Serial.print("Est death: ");
  Serial.println(secRemain /60 / 60 / 24);

  uint32_t secTotal = difftimeUint(ProjectedDeath, Birth);
  Serial.print("Est age at death: ");
  Serial.println(secTotal /60 / 60 / 24 / 365);
  
  Serial.println();

  DisplayDaysSinceBirth.showNumberDec(secAlive /60 / 60 / 24, false);
  DisplayDaysToDeathEST.showNumberDec(secExtra /60 / 60 / 24, false);
  DisplayDaysSinceX.showNumberDec(secRemain /60 / 60 / 24, false);

  delay(10000);
}


void InitDisplays()
{
  DisplayDaysSinceBirth.setBrightness(0x0f);
  DisplayDaysToDeathEST.setBrightness(0x0f);
  DisplayDaysSinceX.setBrightness(0x0f);
}

void TestDisplays()
{
  DisplayDaysSinceBirth.showNumberDec(1234, false);
  DisplayDaysToDeathEST.showNumberDec(2345, false);
  DisplayDaysSinceX.showNumberDec(3456, false);
  delay(2000);
  DisplayDaysSinceBirth.clear();
  DisplayDaysToDeathEST.clear();
  DisplayDaysSinceX.clear();
}

void TimeTest()
{
  struct tm t;
  time_t tt;

  t.tm_year = CalendarYrToTm(1870);
  t.tm_mon = 1;
  t.tm_mday = 2;
  t.tm_hour = 1;
  t.tm_min = 0;
  t.tm_sec = 0;
  tt = mktime(&t);
  Serial.print("tt 1870: ");
  Serial.print((unsigned long) tt);
  Serial.println();

  t.tm_year = CalendarYrToTm(1970);
  t.tm_mon = 1;
  t.tm_mday = 2;
  t.tm_hour = 1;
  t.tm_min = 0;
  t.tm_sec = 0;
  tt = mktime(&t);
  Serial.print("tt 1970: ");
  Serial.print((unsigned long) tt);
  Serial.println();

  t.tm_year = CalendarYrToTm(1980);
  t.tm_mon = 1;
  t.tm_mday = 2;
  t.tm_hour = 1;
  t.tm_min = 0;
  t.tm_sec = 0;
  tt = mktime(&t);
  Serial.print("tt 1980: ");
  Serial.print((unsigned long) tt);
  Serial.println();


  t.tm_year = CalendarYrToTm(2001);
  t.tm_mon = 1;
  t.tm_mday = 2;
  t.tm_hour = 1;
  t.tm_min = 0;
  t.tm_sec = 0;
  tt = mktime(&t);
  Serial.print("tt 2001: ");
  Serial.print((unsigned long) tt);
  Serial.println();

  t.tm_year = CalendarYrToTm(2005);
  t.tm_mon = 1;
  t.tm_mday = 2;
  t.tm_hour = 1;
  t.tm_min = 0;
  t.tm_sec = 0;
  tt = mktime(&t);
  Serial.print("tt 2005: ");
  Serial.print((unsigned long) tt);
  Serial.println();

  t.tm_year = CalendarYrToTm(2025);
  t.tm_mon = 1;
  t.tm_mday = 2;
  t.tm_hour = 1;
  t.tm_min = 0;
  t.tm_sec = 0;
  tt = mktime(&t);
  Serial.print("tt 2025: ");
  Serial.print((unsigned long) tt);
  Serial.println();
  
  t.tm_year = CalendarYrToTm(2042);
  t.tm_mon = 1;
  t.tm_mday = 2;
  t.tm_hour = 1;
  t.tm_min = 0;
  t.tm_sec = 0;
  tt = mktime(&t);
  Serial.print("tt 2042: ");
  Serial.print((unsigned long) tt);
  Serial.println();


  // seems to start at 1870 since 1970 reads at 100 years of seconds. but that would mean rollover in
  // 136 years (2006)
  /*
Hello GrayLifeClock!
tt 1870: 2281441748
tt 1970: 1142148496
tt 1980: 1457681296
tt 2001: 4157614352
tt 2005: 2246599696
tt 2025: 2877751696
tt 2042: 3414209296


 */

}


uint32_t difftimeUint(time_t t1, time_t t2)
{
  return (uint32_t)t1 - (uint32_t)t2;
}
GND5VSDASCLSQWRTCDS1307+
4-Digit Display
4-Digit Display
4-Digit Display