//#include <virtuabotixRTC.h> //Libreria

#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>

// CLK -> 6, DAT -> 7, RST -> 8 Para DS1302
RTC_DS3231 rtc;
//virtuabotixRTC myRTC(6, 7, 8);
LiquidCrystal_I2C lcd(0x27, 20, 4);

// Caracteres customizados para crear numeros grandes.
uint8_t DEFINICION_CARACTERES[8][8] = {
  { //Esquina superior izquierda
    B00111,
    B01111,
    B11111,
    B00000,
    B11111,
    B11111,
    B11111,
    B11111
  },
  { // Cuadro entero
    B11111,
    B11111,
    B11111,
    B00000,
    B11111,
    B11111,
    B11111,
    B11111
  },
  { ///Esquina inferior izquierda
    B11111,
    B11111,
    B11111,
    B00000,
    B11111,
    B11111,
    B01111,
    B00111
  },
  { //Esquina superior derecha
    B11100,
    B11110,
    B11111,
    B00000,
    B11111,
    B11111,
    B11111,
    B11111
  },
  { //Esquina inferior dereccha
    B11111,
    B11111,
    B11111,
    B00000,
    B11111,
    B11111,
    B11110,
    B11100
  },
  { //Punto bajo
    B00000,
    B00000,
    B00000,
    B00000,
    B11111,
    B11111,
    B11111,
    B11111
  },
  { //Punto alto
    B11111,
    B11111,
    B11111,
    B00000,
    B00000,
    B00000,
    B00000,
    B00000
  },
  {// punto fino
    B00000,
    B00000,
    B00000,
    B00000,
    B11100,
    B11100,
    B11100,
    B11100
  }
};

const char DEFINICION_NUMEROS[10][4][4] = {
  { // Definición del 0
    {  0,  1,  1,  3 },
    {  1, 32, 32,  1 },
    {  1, 32, 32,  1 },
    {  2,  1,  1,  4 }
  },
  { // Definición del 1
    {  0,  1,  1, 32 },
    { 32,  1,  1, 32 },
    { 32,  1,  1, 32 },
    {  2,  1,  1,  4 }
  },
  { // Definición del 2
    {  0,  1,  1,  3 },
    {  5,  5,  5,  1 },
    {  1,  6,  6,  6 },
    {  2,  1,  1,  4 }
  },
  { // Definición del 3
    {  0,  1,  1,  3 },
    { 32,  5,  5,  1 },
    { 32,  6,  6,  1 },
    {  2,  1,  1,  4 }
  },
  { // Definición del 4
    {  0, 32, 32,  3 },
    {  1,  5,  5,  1 },
    {  6,  6,  6,  1 },
    { 32, 32, 32,  4 }
  },
  { // Definición del 5
    {  0,  1,  1,  3 },
    {  1,  5,  5,  5 },
    {  6,  6,  6,  1 },
    {  2,  1,  1,  4 }
  },
  { // Definición del 6
    {  0,  1,  1,  3 },
    {  1,  5,  5,  5 },
    {  1,  6,  6,  1 },
    {  2,  1,  1,  4 }
  },
  { // Definición del 7
    {  0,  1,  1,  3 },
    { 32, 32, 32,  1 },
    { 32, 32, 32,  1 },
    { 32, 32, 32,  4 }
  },
  { // Definición del 8
    {  0,  1,  1,  3 },
    {  1,  5,  5,  1 },
    {  1,  6,  6,  1 },
    {  2,  1,  1,  4 }
  },
  { // Definición del 9
    {  0,  1,  1,  3 },
    {  1,  5,  5,  1 },
    {  6,  6,  6,  1 },
    {  2,  1,  1,  4 }
  },
};

// Función que muestra un dígito a partir de la columna indicada
void mostrarDigito(int digito, int columna) {
  for (int fila = 0; fila < 4; fila++) {
    lcd.setCursor(columna, fila);
    for (int caracter = 0; caracter < 4; caracter++) {
      lcd.print(DEFINICION_NUMEROS[digito][fila][caracter]);
    }
  }
}

void setup() {
  Serial.begin(9600);   // Activa serial
  lcd.init();           // Inicia lcd
  lcd.backlight();      // Enciende retroiluminacion
  //lcd.clear();
   if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (! rtc.begin()) {
    Serial.println("RTC is NOT running!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  // Creamos los nuevos caracteres
  for (int i = 0; i < 8; i++) {
    lcd.createChar(i, DEFINICION_CARACTERES[i]);
  }
}

// Las variable las inicializamos a -1 para asegurarnos que al inicio "detecta un cambio" y "refresca" el valor mostrándolo
int anteriorHora = -1;                  // Para saber cuando cambia la hora y "refrescarla"
int anteriorMinuto = -1;                // Para saber cuando cambia el minuto y "refrescarlo"
int anteriorSegundo = -1;               // Para saber cuando cambia el segundo y saber cuándo se han de mostrar los dos puntos

unsigned long instanteAnterior = 0;     // Para controlar cuando han pasado 500 milisegundos desde que se mostraron los dos puntos
bool esperandoOcultarDosPuntos = false; // Para saber cuando se está esperando a ocultar los dos puntos

void loop() {
  DateTime now = rtc.now();
 // myRTC.updateTime();   // Esta función actualiza las variables para obtener resultados actuales
  if (anteriorHora != now.hour()) {    // Si cambia el valor de la hora la muestra
    anteriorHora = now.hour();
    mostrarDigito((now.hour() / 10) % 10, 0);
    mostrarDigito(now.hour() % 10, 5);
  }
  if (anteriorMinuto != now.minute()) {  // Si cambia el valor de los minutos los muestra
    anteriorMinuto = now.minute();
    mostrarDigito((now.minute() / 10) % 10, 11);
    mostrarDigito(now.minute() % 10, 16);
  }
  if (anteriorSegundo != now.second()) { // Si cambia el valor de los segundos, muestra los dos puntos
    anteriorSegundo = now.second();
    lcd.setCursor(10, 1);
    lcd.print((char)7);
    lcd.setCursor(10, 2);
    lcd.print((char)7);
    instanteAnterior = millis();          // Guardamos el instante actual para saber cuándo transcurren 500 milisegundos
    esperandoOcultarDosPuntos = true;     // Indicamos que se está esperando a ocultar los dos puntos
  }
  if ((esperandoOcultarDosPuntos == true) && ((millis() - instanteAnterior) >= 500)) {  // Si se está esperando ocultar los dos puntos y han pasado medio segundo
    esperandoOcultarDosPuntos = false;
    lcd.setCursor(10, 1);
    lcd.print(' ');
    lcd.setCursor(10, 2);
    lcd.print(' ');
  }
}
GND5VSDASCLSQWRTCDS1307+