#define SOURIS_XPRESSNET
//#define Debug_Serie_XpressNet
//#define Debug_Serie
#define Debug_Serie_DCC
#define Emulateur_WOKWI
#define EcranTFT
//#define EcranLCD16
#define EcranLCD20
#include <SPI.h>
#include <SdFat.h>
#include <Keypad.h>
#include <Bounce2.h>
#include <EEPROM.h>
#include <string.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Fonts/FreeSerif9pt7b.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include "XpressNet.h" // Protocole XpressNet compatible Roco, Lenz, Viessmann,...
#include "config.h"
#ifdef EcranLCD20
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(I2C, 20, 4);
#endif
#ifdef EcranLCD16
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(I2C, 16, 2);
#endif
#include "LCD_def.h"
#include "XpressNet_Inst.h"
#include "XpressNet_Fonc.h"
#include "fonction.h"
#include "ecran.h"
#include "encodeur.h"
#include "bouton.h"
#include "clavier.h"
#include "portSerie.h"
void setup()
{
//*********************************************************************
//*********************************************************************
#ifdef Emulateur_WOKWI
// Valeur Eeprom pour simulation avec WOKWI
String nomFichierLocosDefault = "meslocos.csv";
ecrireString(EepromDCC_Loco, nomFichierLocosDefault);
String nomFichierAccessoiresDefault = "mesaccessoires.csv";
ecrireString(EepromDCC_Acc, nomFichierAccessoiresDefault);
#ifdef SOURIS_XPRESSNET
XNetAddress = 3;
#endif
DCCEtat = 0;
#ifdef EcranTFT
DCCEtat_Affichage(1);
#endif
//LocoDCC = LocoDCCDefaut;
AffichageMode = 0;
Direction_Old = 1;
#endif
//*********************************************************************
//*********************************************************************
Serial.begin(9600);
//*** Configuration des bornes en sortie
pinMode(LED_Marche1, OUTPUT);
pinMode(LED_Marche2, OUTPUT);
digitalWrite(LED_Marche1, HIGH);
digitalWrite(LED_Marche2, LOW);
Serial.print("*** Souris XpressNet = ");
#ifdef SOURIS_XPRESSNET
XNetAddress = EEPROM.read(EepromXNetAddress);
if (XNetAddress > 31)
{
XNetAddress = 28;
}
Serial.println(XNetAddress);
XpressNet.start(XNetAddress, XNetSRPin);
XpressNet.receive();
#endif
//*** Configuration des bornes en entrée
pinMode(pinCLK, INPUT_PULLUP);
pinMode(pinDT, INPUT_PULLUP);
pinMode(Borne_Mode_Plus, INPUT_PULLUP);
Bt_Mode_Plus.attach(Borne_Mode_Plus);
Bt_Mode_Plus.interval(10);
pinMode(Borne_Mode_Moins, INPUT_PULLUP);
Bt_Mode_Moins.attach(Borne_Mode_Moins);
Bt_Mode_Moins.interval(10);
pinMode(Borne_Encodeur, INPUT_PULLUP);
Bt_Encodeur.attach(Borne_Encodeur);
Bt_Encodeur.interval(10);
pinMode(Borne_Fn_Moins, INPUT_PULLUP);
Bt_Fn_Moins.attach(Borne_Fn_Moins);
Bt_Fn_Moins.interval(10);
pinMode(Borne_Fn_Plus, INPUT_PULLUP);
Bt_Fn_Plus.attach(Borne_Fn_Plus);
Bt_Fn_Plus.interval(10);
pinMode(Borne_Fn_Ok, INPUT_PULLUP);
Bt_Fn_Ok.attach(Borne_Fn_Ok);
Bt_Fn_Ok.interval(10);
LocoDCC = LocoDCCDefaut;
#ifdef EcranLCD16
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Souris XpressNet");
lcd.setCursor(0, 1);
lcd.print("Num = " + String(XNetAddress));
Initialisation_Caracteres_LCD();
MaxNbLettres = 16;
#endif
#ifdef EcranLCD20
lcd.init();
lcd.backlight();
lcd.setCursor(2, 0);
lcd.print("Souris XpressNet");
lcd.setCursor(6, 1);
lcd.print("Num = " + String(XNetAddress));
Initialisation_Caracteres_LCD();
MaxNbLettres = 20;
#endif
#ifdef EcranTFT
tft.begin(); // Initialisation de l'écran
tft.setRotation(1); // Orientation
//SPI.setClockDivider(SPI_CLOCK_DIV2); // 8MHz sur Arduino Uno
// Ou même plus rapide si stable :
SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE0));
EcranTftIni();
#endif
//*** Initialisation de la carte SD
if (!SD.begin(SD_CS, SD_SCK_MHZ(10)))
{
Serial.println("Erreur d'initialisation de la carte SD");
CarteSD = false;
#ifdef EcranLCD20
lcd.setCursor(0, 2);
lcd.print("Pas de carte SD");
#endif
#ifdef EcranLCD16
lcd.setCursor(0, 1);
lcd.print("Pas de carte SD");
#endif
}
#ifdef Emulateur_WOKWI
CarteSD = true;
#endif
if (CarteSD)
{
//***********************************************************************************
//*** Vérification si présence du fichier de la liste des LOCOMOTIVES
String nomFichierLocos = lireString(EepromDCC_Loco, MAX_CARACTERES);
Serial.print(nomFichierLocos);
//*** Lecture du fichier depuis la carte
File textFile = SD.open(nomFichierLocos);
if (textFile)
{
Serial.println(" => Fichier existe");
String ligne = textFile.readStringUntil('\n'); // Ignorer l'en-tête
//*** Lecture ligne par ligne
while (textFile.available() && locoCount < MAX_LOCOMOTIVES)
{
ligne = textFile.readStringUntil('\n');
ligne.trim(); // enlève \r ou espaces inutiles
if (ligne.length() == 0) continue;
ligne.replace(',', ';'); // Remplacer , par ; si nécessaire
//*** Sépare les colonnes
int sep1 = ligne.indexOf(';');
int sep2 = ligne.indexOf(';', sep1 + 1);
if (sep1 > 0 && sep2 > sep1)
{
locos[locoCount].nom = ligne.substring(0, sep1);
locos[locoCount].cv1 = ligne.substring(sep1 + 1, sep2).toInt();
locos[locoCount].crans = ligne.substring(sep2 + 1).toInt();
locoCount++;
}
}
textFile.close();
//*** Message configuration carte SD Ok
#ifdef EcranTFT
tft.setTextColor(ILI9341_GREEN);
tft.setFont(&FreeSans12pt7b);
tft.setCursor(10, 120);
tft.println("Carte SD : OK");
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(10, 150);
tft.println(nomFichierLocos);
#endif
#ifdef EcranLCD20
nomFichierLocos = nombreCaracteres(nomFichierLocos, MaxNbLettres);
lcd.setCursor(0, 2);
lcd.print(nomFichierLocos);
#endif
} else {
Serial.println(" => Erreur lors de l'ouverture du fichier");
//*** Message configuration Absence carte SD
#ifdef EcranTFT
tft.setTextColor(ILI9341_RED);
tft.setFont(&FreeSans12pt7b);
tft.setCursor(10, 120);
tft.println("Pas de fichier Locos");
#endif
#ifdef EcranLCD20
lcd.setCursor(0, 2);
lcd.print("Pas de fichier Locos");
#endif
Serial.println(" => Pas de fichier reconnu");
delay(100);
}
//***********************************************************************************
//*** Vérification si présence du fichier de la liste des ACCESSOIRES
nomFichierAccessoires = lireString(EepromDCC_Acc, MAX_CARACTERES);
Serial.print(nomFichierAccessoires);
FichierAccessoire = false;
//*** Lecture du fichier depuis la carte
textFile = SD.open(nomFichierAccessoires);
if (textFile)
{
Serial.println(" => Fichier existe");
readCSVFile_Initialisation(nomFichierAccessoires);
//*** Message configuration carte SD Ok
#ifdef EcranTFT
tft.setFont(&FreeSans12pt7b);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(10, 170);
tft.println(nomFichierAccessoires);
#endif
#ifdef EcranLCD20
nomFichierAccessoires = nombreCaracteres(nomFichierAccessoires, MaxNbLettres);
lcd.setCursor(0, 3);
lcd.print(nomFichierAccessoires);
#endif
if (fonctionCount > 0)
{
FichierAccessoire = true;
}
} else {
Serial.println(" => Erreur lors de l'ouverture du fichier ");
//*** Message configuration Absence carte SD
#ifdef EcranTFT
tft.setTextColor(ILI9341_RED);
tft.setFont(&FreeSans12pt7b);
tft.setCursor(10, 170);
tft.println("Pas de fichier Accessoires");
#endif
#ifdef EcranLCD20
lcd.setCursor(0, 3);
lcd.print("Pas de fichier Acce.");
#endif
Serial.println(" => Pas de fichier reconnu");
delay(100);
}
} else {
//*** Message configuration Absence carte SD
#ifdef EcranTFT
tft.setTextColor(ILI9341_RED);
tft.setFont(&FreeSans12pt7b);
tft.setCursor(10, 170);
tft.println("Pas de Carte SD");
#endif
Serial.println("Pas de carte SD reconnue");
delay(100);
}
Serial.print("Nbre LOCOS en mémoire = "); Serial.println(locoCount);
Serial.print("Nbre ACCESSOIRES en mémoire = "); Serial.println(fonctionCount);
#ifdef EcranTFT
tft.fillScreen(CouleurFond);
#endif
switch (AffichageMode)
{
case 0:
#ifdef EcranLCD20
lcd.init();
#endif
compteurInt = Vitesse_Old;
AffichageVitesse();
break;
case 3:
compteurInt = AdresseAcc;
EcranAccessoires();
break;
}
// Attacher l'interruption sur le pin CLK
attachInterrupt(digitalPinToInterrupt(pinCLK), LireEncodeur_ISR, FALLING);
Serial.println("\n************************");
}
void loop()
{
serialEvent();
MillisActuel = millis();
#ifdef SOURIS_XPRESSNET
XpressNet.receive();
#endif
GestionEncodeur();
Bt_Encodeur.update();
Bt_Mode_Plus.update();
Bt_Mode_Moins.update();
Bt_Fn_Plus.update();
Bt_Fn_Moins.update();
Bt_Fn_Ok.update();
LireClavier();
LireBoutons();
ClignotementCurseur();
}