/***********************************************************************
*     Programe d'horloge synchonisée Wi-Fi avec afficheurs 4 digits de *
* 8 fois 8 leds pilotées par MAX7219 asservis à un ESP32-S2 mini et    *
* identification par lecture d'une SD-Card pour la transportabilité... *
* Pour en savoir plus: https://amazing-vacuum-tubes.com                *
***********************************************************************/

#include <WiFi.h> // Accès Wi-Fi
#include "time.h"  // Gestion du temps
#include <MAX72198by32Disp.h> // Gestion Afficheur
#include "MAX7219_Letters.h" // Et pour les lettres
#include "SD.h"  // ainsi que la carte SD

// Connexion des I/Os
#define SD_CS         12
#define SPI_MOSI      11
#define SPI_MISO      9
#define SPI_SCK       7


// Declaration des variables
String ssid ;  // Variables didentification de la box
String password ;  // Variables du mot de passe de la box

const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 3600; // GMT + locale ATTENTION MODIF SI AUTRE QUE LA FRANCE
int   daylightOffset_sec ;  // Hiver / ete

byte Pix_hour; // Variables des heures
byte Pix_min; // Variables des minutes
int Pix_sec; // Variables des secondes
int Pix_date;  // Variables de la date
int Pix_day;  // Variables du jour

int unit_Hour; // Variables des unites d'heures
int dix_Hour;  // Variables des dizaines d'heures
int unit_Minut;  // Variables des unites de minutes
int dix_Minut;  // Variables des dizaines de minutes

int dix_Date;    // Variables des dizaines de jour
int unit_Date;    // Variables des unités de jours

int Jumper = 16;  // Commutateur heure d'été / hiver


MAX72198by32Disp disp(38, 39, 40);  // Connection de l'afficheur Din,CS,CLK

void printLocalTime()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    return;
  }
   //Affectation en variable numérique de l'extraction aux heures, minutes et secondes 
  Pix_hour = timeinfo.tm_hour;
  Pix_min = timeinfo.tm_min;
  Pix_sec = timeinfo.tm_sec;

   //Affichage après mise en forme de l'heure
  disp.Number(4, dix_Hour);
  disp.Numberdp(3, unit_Hour);
  disp.Number(2, dix_Minut);
  disp.Number(1, unit_Minut);
}


void printLocalDate()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    return;
  }
   //Affectation en variable numérique du jour (1à7) et de la date (1 a 31)
  Pix_date = timeinfo.tm_mday;
  Pix_day = timeinfo.tm_wday;

   // Mise en forme des unités et dizaines de jours
  dix_Date = Pix_date /10;
  unit_Date = Pix_date - (dix_Date * 10);

   //Affichage sur les digits 1 & 2
  disp.Number(2, dix_Date);
  disp.Number(1, unit_Date); 

   //Affectation des deux premières lettres du jour (1 = Lu, 2 = Ma....) 
   //et affichage sur les digits 3 & 4
    switch (Pix_day) {
    case 0: 
  disp.Letter(4, D); 
  disp.Letter(3, i);
      break;
    case 1:  
  disp.Letter(4, L); 
  disp.Letter(3, u);
      break;
    case 2:  
  disp.Letter(4, M); 
  disp.Letter(3, a);
      break;
    case 3:  
  disp.Letter(4, M); 
  disp.Letter(3, e);
      break;
    case 4:  
  disp.Letter(4, J); 
  disp.Letter(3, e);
      break;
    case 5:  
    disp.Letter(4, V); 
    disp.Letter(3, e);
      break;
    case 6:  
  disp.Letter(4, S); 
  disp.Letter(3, a);
      break;
  } 

      delay(4500);
}



void setup()
{
  // Topographie de la carte SD
    pinMode(SD_CS, OUTPUT);      
    digitalWrite(SD_CS, HIGH);
    SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
  
  // Initialiser la carte SD
    if (!SD.begin(SD_CS)) {
    return;
    }

  // Lecture de l'identifiant
    File ssidFile = SD.open("/ssid.txt");
    // Vérifier si le fichier est ouvert
      if (ssidFile) {
    // Lire le contenu du fichier
        String data = ssidFile.readString();
        ssid = data;
    // Fermer le fichier
        ssidFile.close();
      }

  // Lecture du Mot de passe
    File passwordFile = SD.open("/password.txt");
    // Vérifier si le fichier est ouvert
      if (passwordFile) {
    // Lire le contenu du fichier
        String data = passwordFile.readString();
        password = data;
    // Fermer le fichier
        passwordFile.close();
      }

    // Lecture de la position du jumper été/hiver
  pinMode (Jumper, INPUT_PULLUP);
  digitalRead (Jumper );
   if  (Jumper, LOW) {
    daylightOffset_sec = 3600; 
  } else {
    daylightOffset_sec = 0;
 }

  //connection au WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
  }

  // initialisation afficheur
  disp.Initialize(0);
  delay(1000);
  disp.Clear();

  // afichage de l'état de la conexion WiFi (CxOk)
  disp.Letter(1, k);
  disp.Letter(2, O);
  disp.Letter(3, x);
  disp.Letter(4, C);
  delay(1500);


  //initialisation et emule le temps
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  printLocalTime();

  //deconnection WiFi car le temps est trop long
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
}


void loop()
{
    struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    return;
  }

   // Mise en forme de l'heure & minute dizaines et unités
  dix_Hour = Pix_hour /10;
  unit_Hour = Pix_hour - (dix_Hour * 10);
  dix_Minut = Pix_min /10;
  unit_Minut = Pix_min - (dix_Minut * 10);
  dix_Date = Pix_date /10;
  unit_Date = Pix_date - (dix_Date * 10);
  
   // Si les seconde sont a plus de 56 affichage du mot "Date"
  if (Pix_sec > 56 ){
disp.Letter(1, e);
disp.Letter(2, t);
disp.Letter(3, a);
disp.Letter(4, D);
    delay(1000);
  
   // et on serend au sous programme d'affichage de la date
  printLocalDate();
  }

  // on boucle sur le sous programme de l'affichage de l'heure & minutes
  printLocalTime();
  delay(1000);

}
