/*
pour montre TTGO T-Watch v1
par Silicium628
à voir aussi -> https://projetsdiy.fr/ttgo-t-watch-debuter-librairie-esp32-tft_espi/
*/
#define version1 "2.0"
#include "config.h"
#include "Free_Fonts.h"
#include <EEPROM.h>
#define EEPROM_SIZE 100
#include "data_perso2.c"
#include "Listeuse.h"
bool irq = false;
char buf[128];
bool rtcIrq = false;
TTGOClass *ttgo;
TFT_eSPI * tft;
AXP20X_Class *power;
BOUTON bouton1;
BOUTON bouton2;
BOUTON bouton3;
BOUTON bouton4;
BOUTON bouton5;
BOUTON bouton6;
BOUTON bouton7;
BOUTON bouton8;
BOUTON bouton9;
BOUTON bouton10;
BOUTON bouton11;
BOUTON bouton12;
BOUTON bouton13;
BOUTON bouton14;
BOUTON bouton15;
/***************************************************************************************
** Section 6: Colour enumeration
***************************************************************************************/
// Default color definitions
/**
#define TFT_BLACK 0x0000 // 0, 0, 0
#define TFT_NAVY 0x000F // 0, 0, 128
#define TFT_DARKGREEN 0x03E0 // 0, 128, 0
#define TFT_DARKCYAN 0x03EF // 0, 128, 128
#define TFT_MAROON 0x7800 // 128, 0, 0
#define TFT_PURPLE 0x780F // 128, 0, 128
#define TFT_OLIVE 0x7BE0 // 128, 128, 0
#define TFT_LIGHTGREY 0xD69A // 211, 211, 211
#define TFT_DARKGREY 0x7BEF // 128, 128, 128
#define TFT_BLUE 0x001F // 0, 0, 255
#define TFT_GREEN 0x07E0 // 0, 255, 0
#define TFT_CYAN 0x07FF // 0, 255, 255
#define TFT_RED 0xF800 // 255, 0, 0
#define TFT_MAGENTA 0xF81F // 255, 0, 255
#define TFT_YELLOW 0xFFE0 // 255, 255, 0
#define TFT_WHITE 0xFFFF // 255, 255, 255
#define TFT_ORANGE 0xFDA0 // 255, 180, 0
#define TFT_GREENYELLOW 0xB7E0 // 180, 255, 0
#define TFT_PINK 0xFE19 // 255, 192, 203 //Lighter pink, was 0xFC9F
#define TFT_BROWN 0x9A60 // 150, 75, 0
#define TFT_GOLD 0xFEA0 // 255, 215, 0
#define TFT_SILVER 0xC618 // 192, 192, 192
#define TFT_SKYBLUE 0x867D // 135, 206, 235
#define TFT_VIOLET 0x915C // 180, 46, 226
**/
bool KeyPressed = false;
bool lenergy = false;
static bool irq_axp202 = false;
static bool return_to_deepsleep = true;
#define TIME_TO_SLEEP 30
uint8_t secondes;
uint8_t heures;
uint8_t minutes;
uint8_t etats[nb_elements]; // nb_elements est défini dans le fichier data_perso2.c
uint8_t lst_num_affi[11]; // liste des numéros des strings actuellement affichés
uint16_t num_ligne_pointee;
uint8_t top_lst=0;
uint8_t lst_a_afficher=1; // =0 ou 1 (2 listes)
uint8_t choix_ok =0;
uint8_t mode=0;
uint8_t reg_heure=0;
int16_t x_1, y_1;
int16_t x_2, y_2;
uint16_t memo_y_2=0;
void init_boutons()
{
// sur la partie listeuse
if(lst_a_afficher == 0)
{
bouton1.init(199,0, 40,40, "fleche_droite", TFT_BROWN);
}
else
{
bouton1.init(199,0, 40,40, "fleche_gauche", TFT_CYAN);
}
bouton1.dessine(0);
String s2;
if(lst_a_afficher == 0) {s2="x";} else {s2="!";}
bouton2.init(199,65, 40,40, s2, TFT_GREEN);
bouton2.dessine(0);
bouton3.init(199,140, 40,20, "fleche_haut", TFT_WHITE);
bouton3.dessine(0);
bouton4.init(199,200, 40,20, "fleche_bas", TFT_WHITE);
bouton4.dessine(0);
// sur la page de choix
bouton5.init(120,0, 40,40, "W", TFT_RED);
bouton6.init(180,0, 40,40, "R", TFT_GREEN);
bouton7.init(5,80, 100,40, "Montre", TFT_WHITE);
bouton8.init(5,130, 100,40, "Liste", TFT_WHITE);
bouton9.init(150,190, 40,40, "+", TFT_WHITE); // bouton "inc minutes"
bouton10.init(80,190, 40,40, "-", TFT_WHITE); // bouton "dec minutes"
bouton11.init(120,80, 110,40, "Reg h,m", TFT_WHITE); // bouton accès règlage minutes
bouton12.init(120,130, 110,40, "Batt", TFT_WHITE);
bouton13.init(130,200, 100,40, "retour", TFT_WHITE);
bouton14.init(150,40, 40,40, "+", TFT_WHITE); // bouton "inc heures"
bouton15.init(80,40, 40,40, "-", TFT_WHITE); // bouton "dec heures"
}
uint16_t nb_elmt_liste_en_cours()
{
uint16_t nb1=0;
for(int n=0; n<nb_elements; n++)
{
if (etats[n] == lst_a_afficher) {nb1++;}
}
return(nb1);
}
void affiche_data()
{
if (mode==0)
{
String s1;
tft->setFreeFont(FF18);
tft->fillScreen(TFT_BLACK);
if(lst_a_afficher==0) {tft->setTextColor(TFT_CYAN, TFT_BLACK);} else {tft->setTextColor(TFT_BROWN, TFT_BLACK);}
for(uint16_t i=0; i<11; i++) {lst_num_affi[i]=255;} // RAZ liste
int16_t dy=22;
// n'affiche que les lignes de la liste choisie (parmi 2 listes)
uint16_t y=0;
uint8_t i=top_lst;
uint8_t n=0;
while((i<nb_elements) && (n<11))
{
if (etats[i] == lst_a_afficher)
{
uint16_t num1;
num1 =top_lst + n;
//num1 ++; // pour afficher à partir de 1 au lieu de 0...
s1 =(String)num1;
tft->setFreeFont(FF1);
tft->setTextColor(TFT_SILVER, TFT_BLACK);
tft->drawString(s1, 0, y+2, GFXFF); // affiche les numéros à gauche du texte
String el1 = elements[i];
tft->setFreeFont(FF18);
if(lst_a_afficher==0) {tft->setTextColor(TFT_CYAN, TFT_BLACK);} else {tft->setTextColor(TFT_BROWN, TFT_BLACK);}
tft->drawString(el1, 34, y, GFXFF);
y+=dy;
lst_num_affi[n]=i;
n++;
}
i++;
}
tft->setFreeFont(FF1);
init_boutons();
uint16_t nb_el1;
nb_el1= nb_elmt_liste_en_cours();
s1 =(String)nb_el1;
tft->setTextColor(TFT_WHITE, TFT_BLUE);
tft->setTextFont(2); // très petits caractères
tft->drawString(s1, 220, 225, GFXFF); // affiche le nombre en bas à droite
}
}
void affiche_batterie()
{
tft->fillScreen(TFT_BLACK);
uint8_t fin_bcl=0;
while (fin_bcl == 0)
{
//tft->fillScreen(TFT_BLACK);
tft->fillRect(0, 0, 230, 150, TFT_BLACK);
tft->setTextColor(TFT_CYAN, TFT_BLACK);
tft->setFreeFont(FF1);
bouton13.dessine(0);
tft->setTextColor(TFT_CYAN, TFT_BLACK);
tft->setFreeFont(FF1);
tft->setCursor(0, 10);
tft->print("VBUS ETAT: ");
if (power->isVBUSPlug())
{
tft->setTextColor(TFT_GREEN, TFT_BLACK);
tft->println("CONNECT");
tft->setTextColor(TFT_YELLOW, TFT_BLACK);
tft->print("VBUS V : ");
tft->print(power->getVbusVoltage());
tft->println(" mV");
tft->setTextColor(TFT_BLUE, TFT_BLACK);
tft->print("VBUS I: ");
tft->print(power->getVbusCurrent());
tft->println(" mA");
}
else
{
tft->setTextColor(TFT_RED, TFT_BLACK);
tft->println("DISCONNECT");
tft->setTextColor(TFT_GREEN, TFT_BLACK);
}
tft->println();
tft->setTextColor(TFT_CYAN, TFT_BLACK);
tft->print("BATT Li-Ion : ");
// You can use isBatteryConnect() to check whether the battery is connected properly
if (power->isBatteryConnect())
{
tft->setTextColor(TFT_GREEN, TFT_BLACK);
tft->println("CONNECT");
tft->setTextColor(TFT_YELLOW, TFT_BLACK);
float V=power->getBattVoltage();
V /=1000;
tft->print(V);
tft->println(" V");
// To display the charging status, you must first discharge the battery,
// and it is impossible to read the full charge when it is fully charged
if (power->isChargeing())
{
tft->setTextColor(TFT_BLUE, TFT_BLACK);
tft->print("Charge : ");
tft->print(power->getBattChargeCurrent());
tft->println(" mA");
}
else
{
// Show current consumption
tft->setTextColor(TFT_WHITE, TFT_BLACK);
tft->print("Decharge : ");
tft->print(power->getBattDischargeCurrent());
tft->println(" mA");
tft->print(power->getBattPercentage());
tft->println(" %");
}
}
else
{
tft->setTextColor(TFT_RED, TFT_BLACK);
tft->println("DISCONNECT");
tft->setTextColor(TFT_GREEN, TFT_BLACK);
}
for(int n=0; n<10; n++) // pour obtenir un temps de réaction très bref en gardant une tempo de 1s
{
if (ttgo->getTouch(x_1, y_1))
{
fin_bcl=1;
affi_choix();
mode=1;
}
delay(100);
}
}
}
void affi_choix()
{
tft->fillScreen(TFT_BLACK);
tft->setTextColor(TFT_CYAN, TFT_BLACK);
tft->setFreeFont(FF18);
tft->drawString("Eeprom :", 10, 5, GFXFF);
tft->drawLine(0, 45, 239, 45, TFT_WHITE);
//tft->drawString("Fonction :", 10, 55, GFXFF);
bouton5.dessine(0);
bouton6.dessine(0);
bouton7.dessine(0);
bouton8.dessine(0);
bouton11.dessine(0);
bouton12.dessine(0);
}
void setup()
{
//Serial.begin(115200);
//Serial.println("setup()");
EEPROM.begin(EEPROM_SIZE); // en mémoire flash
ttgo = TTGOClass::getWatch();
ttgo->begin();
power = ttgo->power;
ttgo->openBL(); // allume le rétroéclairage
ttgo->bl->adjust(150); //Lower the brightness
tft = ttgo->tft;
tft->fillScreen(TFT_BLACK);
ttgo->rtc->disableAlarm();
// ttgo->rtc->setDateTime(2021, 03, 12, 17, 21, 30); // commenter cette ligne sauf pour remettre à l'heure
for(int n =0; n<nb_elements; n++)
{
etats[n]= 1;
}
uint16_t dy=22;
uint16_t decal=0;
// for(int decal =0; decal<nb_elements; decal++)
{
uint16_t y=0;
tft->fillScreen(TFT_BLACK);
affiche_data();
delay(100);
}
init_boutons();
uint8_t v1 = EEPROM.read(0);
String s1;
s1 =(String)v1;
tft->setFreeFont(FF1);
tft->setTextColor(TFT_SILVER, TFT_BLACK);
tft->drawString(s1, 150, 70, GFXFF);
pinMode(AXP202_INT, INPUT_PULLUP);
attachInterrupt(AXP202_INT, []
{
irq = true;
}, FALLING);
//!Clear IRQ unprocessed first
power->enableIRQ(AXP202_PEK_SHORTPRESS_IRQ | AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_CHARGING_IRQ, true);
// ADC monitoring must be enabled to use the AXP202 monitoring function
power->adc1Enable(AXP202_VBUS_VOL_ADC1 | AXP202_VBUS_CUR_ADC1 | AXP202_BATT_CUR_ADC1 | AXP202_BATT_VOL_ADC1, true);
power->clearIRQ();
read_eeprom();
mode=0;
lst_a_afficher=0;
//affi_choix();
//affiche_data();
affiche_heure();
}
void trace_curseur_triangulaire(uint16_t x, uint16_t y, uint32_t couleur)
{
tft->fillTriangle (x, y-12, x, y+6, x+10, y-2, couleur);
}
void affi_string(String s, uint16_t x, uint16_t y)
{
tft->setFreeFont(FF1);
tft->setTextColor(TFT_WHITE, TFT_BLACK);
tft->drawString(" ", x, y, GFXFF);
tft->drawString(s, x, y, GFXFF);
}
void affi_int(uint16_t k, uint16_t x, uint16_t y)
{
String s1 =(String)k;
tft->setFreeFont(FF1);
tft->setTextColor(TFT_WHITE, TFT_BLACK);
tft->drawString(" ", x, y, GFXFF);
tft->drawString(s1, x, y, GFXFF);
}
void affi_message(String m1)
{
tft->setTextColor(TFT_WHITE, TFT_BLUE);
tft->setFreeFont(FF18);
ttgo->tft->drawString(m1, 25, 100);
delay(1000);
affiche_data();
}
void record_etat()
{
if (nb_elements > 100) {return;}
int adresse =0;
uint8_t nbe = nb_elements;
for(int n=0; n<nb_elements; n++)
{
EEPROM.write(adresse, etats[n]);
EEPROM.commit();
delay(5);
adresse ++;
}
}
void read_eeprom()
{
int adresse =0;
for(int n=0; n<nb_elements; n++)
{
uint8_t v;
v = EEPROM.read(adresse);
//Serial.print(n); Serial.print(": "); Serial.println(v);
etats[n]=v;
adresse ++;
}
}
void inc_heures()
{
RTC_Date dt1 = ttgo->rtc->getDateTime();
if (dt1.hour<23) {dt1.hour++;}
ttgo->rtc->setDateTime(dt1);
}
void dec_heures()
{
RTC_Date dt1 = ttgo->rtc->getDateTime();
if (dt1.hour>0) {dt1.hour--;}
ttgo->rtc->setDateTime(dt1);
}
void inc_minutes()
{
RTC_Date dt1 = ttgo->rtc->getDateTime();
if (dt1.minute<59) {dt1.minute++;}
else
{
dt1.hour++;
dt1.minute=0;
}
ttgo->rtc->setDateTime(dt1);
}
void dec_minutes()
{
RTC_Date dt1 = ttgo->rtc->getDateTime();
if (dt1.minute>0) {dt1.minute--;}
else
{
dt1.hour--;
dt1.minute=59;
}
ttgo->rtc->setDateTime(dt1);
}
void affiche_heure()
{
uint32_t d2;
String s1, s2;
tft->fillScreen(TFT_BLACK);
if (reg_heure==1)
{
tft->fillScreen(TFT_BLACK);
tft->setTextColor(TFT_CYAN, TFT_BLACK);
tft->setFreeFont(FF18);
tft->drawString("h:", 10, 50, GFXFF);
bouton14.dessine(0);
bouton15.dessine(0);
tft->setTextColor(TFT_CYAN, TFT_BLACK);
tft->setFreeFont(FF18);
tft->drawString("mn :", 10, 200, GFXFF);
bouton9.dessine(0);
bouton10.dessine(0);
bouton14.dessine(0);
bouton15.dessine(0);
}
//ttgo->tft->setTextColor(TFT_YELLOW, TFT_BLACK);
uint8_t stop=0;
while(stop==0)
{
ttgo->tft->setTextColor(TFT_YELLOW, TFT_BLACK);
RTC_Date dt1 = ttgo->rtc->getDateTime();
heures = dt1.hour;
s1="";
if (heures<10) {s1 +="0";}
s1+= String(heures);
s1+=":";
minutes = dt1.minute;
if (minutes<10) {s1 +="0";}
s1 += String (minutes);
s1+=" ";
tft->setFreeFont(FM24);
ttgo->tft->drawString(s1, 40, 100);
secondes = dt1.second;
s2 = String (secondes);
s2+=" ";
tft->setFreeFont(FM12);
ttgo->tft->setTextColor(TFT_BLUE, TFT_BLACK);
ttgo->tft->drawString(s2, 40, 150);
if (irq)
{
ttgo->power->readIRQ();
if (ttgo->power->isPEKShortPressIRQ())
{
ttgo->power->clearIRQ();
stop=1;
}
//irq = false;
}
if (reg_heure==1)
{
if (ttgo->getTouch(x_1, y_1))
{
if (detect_btn(&bouton9)) { inc_minutes(); }
if (detect_btn(&bouton10)) { dec_minutes(); }
if (detect_btn(&bouton14)) { inc_heures(); }
if (detect_btn(&bouton15)) { dec_heures(); }
}
}
if (stop ==0) {delay(500);}
}
reg_heure=0;
mode=1;
affi_choix();
}
int detect_btn(BOUTON *bouton_i)
{
// calcul de la distance^2 du point cliqué / centre du bouton; rappel : sq = fonction "carré de"
// d²=dx²+dy²
// inutile d'en prendre la racine carrée, on peut utiliser la valeur d² directement
uint32_t d2;
uint16_t milieu_x = bouton_i->x0 + bouton_i->dx/2;
d2= sq(x_1 - milieu_x) + sq(y_1 - bouton_i->y0);
if (d2 < 2000)
{
bouton_i->dessine(1);
delay (200);
bouton_i->dessine(0);
return(1);
}
else
{
return(0);
}
}
void loop()
{
uint32_t d2;
if (irq)
{
irq = false;
power->readIRQ();
//if (power->isVbusPlugInIRQ()) {affi_message("Power Plug In"); }
//if (power->isVbusRemoveIRQ()) {affi_message("Power Remove"); }
if (power->isPEKShortPressIRQ())
{
affi_choix();
mode=1;
}
power->clearIRQ();
}
if (ttgo->getTouch(x_1, y_1))
{
if(mode==0) // mode "normal"
{
if (x_1<160) // gestion du curseur à gauche
{
num_ligne_pointee = y_1/22;
/** affi_int(num_ligne_pointee, 120, 0); // pour test -> [0..10] **/
x_2=20;
y_2=22*(y_1/22)+12;
uint8_t num_el = lst_num_affi[num_ligne_pointee];
if(((y_2 != memo_y_2) && (num_el != 255))|| (num_ligne_pointee==0) ) // la valeur 255 est inscrite au delà de la fin des éléments présents . cf: affiche_data()
{
/**
affi_int(num_el, 120, 20); // pour test
String s1 = elements[num_el];
affi_string(s1 ,120,40); // pour test
**/
trace_curseur_triangulaire(x_2, memo_y_2, TFT_BLACK); //efface le précédent
trace_curseur_triangulaire(x_2, y_2, TFT_YELLOW); //trace le curseur triangulaire jaune
memo_y_2 = y_2;
bouton2.couleur=TFT_GREEN;
bouton2.dessine(0);
choix_ok=1;
}
}
else // gestion des boutons à droite
{
if (detect_btn(&bouton1))
{
lst_a_afficher=1-lst_a_afficher;
top_lst=0;
affiche_data();
}
if (detect_btn(&bouton2))
{
if (choix_ok==1)
{
uint8_t n_el = lst_num_affi[num_ligne_pointee];
etats[n_el]=1-etats[n_el];
affiche_data();
bouton2.couleur=TFT_DARKGREY;
bouton2.dessine(0);
choix_ok=0;
}
}
if (detect_btn(&bouton3))
{
top_lst=0;
affiche_data();
}
if (detect_btn(&bouton4))
{
uint16_t nb_max = nb_elmt_liste_en_cours();
//if (top_lst < (nb_max-11))
top_lst=lst_num_affi[10]; // on part du dernier élément de l'affichage en cours
//{top_lst+=11;} //attention à cette valeur : elle doit correspondre au nb de lignes affichées
affiche_data();
}
}
}
else if(mode==1) // ecran de choix avec 5 boutons
{
if (detect_btn(&bouton5))
{
record_etat();
}
if (detect_btn(&bouton6))
{
read_eeprom();
mode=0;
lst_a_afficher=0;
affiche_data();
}
if (detect_btn(&bouton7))
{
affiche_heure();
x_1=0;
y_1=0;
}
if (detect_btn(&bouton8))
{
x_1=0;
y_1=0;
mode=0;
affiche_data();
}
if (detect_btn(&bouton11))
{
reg_heure=1;
affiche_heure();
}
if (detect_btn(&bouton12))
{
affiche_batterie();
}
}
}
delay(5);
}
/** ***********************************************************************************
CLASS BOUTON // affiche un bouton cliquable
***************************************************************************************/
// Constructeur
BOUTON::BOUTON()
{
}
void BOUTON::init(uint16_t x_i, uint16_t y_i, uint16_t dx_i, uint16_t dy_i, String s_i, uint32_t couleur_i)
{
x0 = x_i;
y0 = y_i;
dx = dx_i;
dy = dy_i;
s = s_i;
couleur =couleur_i;
}
void BOUTON::dessine(uint8_t fill_i)
{
if(fill_i==1)
{
tft->fillRoundRect(x0, y0, dx, dy, 5, couleur);
}
else
{
tft->fillRoundRect(x0, y0, dx, dy, 5, TFT_BLACK); // "éteint" le bouton
tft->drawRoundRect(x0, y0, dx, dy, 5, couleur); // retrace le pourtour
//
if (s=="fleche_haut") {tft->fillTriangle (x0+12, y0+15, x0+30, y0+15, x0+20, y0+5, couleur);}
else if (s=="fleche_bas") {tft->fillTriangle (x0+12, y0+5, x0+30, y0+5, x0+20, y0+15, couleur);}
else if (s=="fleche_droite") {tft->fillTriangle (x0+15, y0+8, x0+15, y0+26, x0+25, y0+18, couleur);}
else if (s=="fleche_gauche") {tft->fillTriangle (x0+25, y0+8, x0+25, y0+26, x0+15, y0+18, couleur);}
else
{
tft->setFreeFont(FF18);
tft->setTextColor(TFT_WHITE, TFT_BLACK);
tft->drawString(s, x0+11, y0+10);
}
}
}