#include <FastLED.h>
#include <Wire.h>

//BEGIN RTC CODE

//rtc variables
static int second, minute, hour;
static int dayOfWeek, dayOfMonth, month, year;
//end rtc variables

#define DS3231_I2C_ADDRESS 0x68

byte decToBcd(byte val) {
  return ( (val / 10 * 16) + (val % 10) );
}

// Convert binary coded decimal to decimal numbers
byte bcdToDec(byte val) {
  return ( (val / 16 * 10) + (val % 16) );
}

// Set the time
void rtc_setTime(byte second, byte minute, byte hour, byte wday, byte mday, byte mon, byte year) {
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours

  Wire.write(decToBcd(wday)); // set day of week (1=Monday, 7=Sunday)
  Wire.write(decToBcd(mday)); // set date (1 to 31)
  Wire.write(decToBcd(mon)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  
  Wire.endTransmission();
}

//Refresh/Read the time
void rtc_readTime() {
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();

  // request seven bytes of data from DS3231 starting from register 00h
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  second = bcdToDec(Wire.read() & 0x7f);
  minute = bcdToDec(Wire.read());
  hour = bcdToDec(Wire.read() & 0x3f);
  dayOfWeek = bcdToDec(Wire.read());
  dayOfMonth = bcdToDec(Wire.read());
  month = bcdToDec(Wire.read());
  year = bcdToDec(Wire.read());

  //leap year correction (if year is > 2100)
  #define LEAP_YEAR(Y)     ( !(((Y))%4) && ( (((Y))%100) || !(((Y))%400) ) )

  if(LEAP_YEAR(year) == 0 && dayOfMonth == 29 && month == 2){
    rtc_setTime(second, minute, hour, dayOfWeek, 1, 3, year);
  }

  if(year == 0){
    rtc_setTime(second, minute, hour, dayOfWeek, dayOfMonth, month, 2100);
  }
}

void rtc_init(){
  Wire.begin(); 
}

//END RTC CODE






#define LED_PIN 4
#define NUM_LEDS 60
#define LED_ORDER GRB
#define LED_TYPE WS2812B

CRGB leds[NUM_LEDS];

void setup(){
  FastLED.addLeds<LED_TYPE, LED_PIN, LED_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.setBrightness(255);
  Serial.begin(115200);
  rtc_init();
}

//function for mapping hour
long map_hour(double x, long in_min, long in_max, long out_min, long out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

//from https://www.geeksforgeeks.org/modulus-two-float-double-numbers/
double findMod(double a, double b){
    double mod;
    // Handling negative values
    if (a < 0)
        mod = -a;
    else
        mod =  a;
    if (b < 0)
        b = -b;
 
    // Finding mod by repeated subtraction
     
    while (mod >= b)
        mod = mod - b;
 
    // Sign of result typically depends
    // on sign of a.
    if (a < 0)
        return -mod;
 
    return mod;
}

void loop(){
  FastLED.clear();
  rtc_readTime();


  static double hour24 = ( ( ( ( hour ) * 3600 ) +( minute * 60) + second ) ), hour12 = ( ( ( ( hour-12 ) * 3600 ) +( minute * 60) + second ) );
  static double new_hour = 0;
  
  if(hour > 12){
    new_hour = findMod(hour12,86400) / 3600;
  } else {
    new_hour = findMod(hour24,86400) / 3600;
  }

  leds[second] = CRGB::Red;
  leds[minute] = CRGB::Green;
  leds[map_hour(new_hour, 0, 12, 0, NUM_LEDS)] = CRGB::Blue;
  FastLED.show();
  delay(500);
}
esp:VIN
esp:GND.2
esp:D13
esp:D12
esp:D14
esp:D27
esp:D26
esp:D25
esp:D33
esp:D32
esp:D35
esp:D34
esp:VN
esp:VP
esp:EN
esp:3V3
esp:GND.1
esp:D15
esp:D2
esp:D4
esp:RX2
esp:TX2
esp:D5
esp:D18
esp:D19
esp:D21
esp:RX0
esp:TX0
esp:D22
esp:D23
ring1:GND
ring1:VCC
ring1:DIN
ring1:DOUT
GND5VSDASCLSQWRTCDS1307+
rtc1:GND
rtc1:5V
rtc1:SDA
rtc1:SCL
rtc1:SQW