// menus[] est a passer en PROGMEM (en insérant PROGMEM juste avant le =, avec espaces de chaque coté)
// les caractères du switch du refresh menu sont aussi a passer sous F()
// ajustement des tensions batterie a faire

// image vers BMP mischianti.org/images-to-byte-array-online-converter-cpp-arduino/
// editeur BMP jsfiddle.net/serisman/nuqdg6wc/ noter que l'éditeur ne travaille qu'en verticale, et que l'écran a besoin d'horizontal
// infos lib GFX circuitgeeks.com/oled-display-arduino/

//https://wokwi.com/projects/346178932556431954


#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>

// IHM

#define SCREEN_ADRESS 0x3c
#define PIN_BOUTON_HAUT A13
#define PIN_BOUTON_BAS A14
#define PIN_BOUTON_GAUCHE A15
#define PIN_BOUTON_DROITE A12
#define PIN_BATT_LVL A0

#define DUREE_SPAM_BOUTON 10 //Durée durant laquelle le bouton doit être enfoncé avant de commencer a spam. unité : cycles de boucle

// affichage

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define LINE_POSITION 110 //A MODIFIER AVEC PRECAUTION
//ne doit pas être inférieur à 8.5 fois la longueur du plus long titre de menus, ou glitch 

// interface

#define language 0 // FR 0  EN 1

#define BOARD_NAME "1.0"  //Nom de la carte à afficher sur le splash
#define BOARD_NAME_LOCATION 78  //Permet de réajuster en x le nom de la carte

// menus 

const char menus[][round(LINE_POSITION/5)-5] = {"",
#if language == 0
"A propos","Servos","Batterie","Deplacements","Tests","Manette" // a noter : chaque menu a un ID, correspondant a son rang dans cette chaine, déterminé par la var menu_selector
#else language == 1
"About","Servos","Battery","Movements","Tests","Controller"
#endif
,""}; // ne surtout pas enlever les vides au début et à la fin

#define ID_A_PROPOS 1
#define ID_SERVOS 2
#define ID_BATTERIE 3
#define ID_DEPLACEMENTS 4

// Batterie

#define BATT_ALERT 30 // (%)
const char battery_types[][8]{
  "OFF","LIPO 4S","LIPO 5S","LIPO 6S"
};

// EEPROM

#define USE_EXTERNAL_EEPROM 0 //mettre sur 1 pour utiliser l'EEPROM I2C au lieu de l'interne au 2560
// ATmega 2560, 4096 adresses
#define ADRESS_SERVO11 1
#define ADRESS_SERVO12 2
#define ADRESS_SERVO21 3
#define ADRESS_SERVO22 4
#define ADRESS_SERVO31 5
#define ADRESS_SERVO32 6
#define ADRESS_SERVO41 7
#define ADRESS_SERVO42 8
#define ADRESS_SERVO51 9
#define ADRESS_SERVO52 10
#define ADRESS_SERVO61 11
#define ADRESS_SERVO62 12
#define ADRESS_SERVO71 13
#define ADRESS_SERVO72 14
#define ADRESS_SERVO81 15
#define ADRESS_SERVO82 16

#define ADRESS_BATT_TYPE 18

#define ADRESS_MOVEMENT_MODE 20


// ====================================== PROGRAMME ======================================

const unsigned char logo [] PROGMEM = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0x80, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0x00, 0x70, 0x1c, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0x01, 0xfc, 0x7f, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0x03, 0x06, 0xc1, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0x02, 0x03, 0x80, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xe3, 0x06, 0x01, 0x08, 0xc1, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xc3, 0x06, 0x71, 0x1c, 0xc1, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xc3, 0x06, 0x00, 0x08, 0xc1, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xc3, 0x02, 0x00, 0x00, 0x81, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xc3, 0x03, 0x0c, 0x61, 0x81, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xc3, 0x01, 0xf8, 0x3f, 0x01, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xc3, 0x00, 0x00, 0x00, 0x01, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xc3, 0x00, 0x00, 0x00, 0x01, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xc3, 0x00, 0x00, 0x00, 0x01, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xe3, 0x7f, 0xff, 0xff, 0xfd, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0x3f, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0x1f, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0x80, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// venant d'autre part dans le programme
#define _HardwareVersion "0.1"
#define _FirmwareVersion "0.1"
boolean mode_deplacement; // 1 holo 0 normal
boolean manette_connectee = 0;
byte manette_type = -1;
void setup(){init_IHM();
  delay(2000);
  display.clearDisplay();
  display.display();
  
  display.drawLine(0, 33, 128, 33, WHITE); // uniquement pour délimiter le fait que c'est ici un écran deux fois plus haut
}
void loop(){loop_IHM();}
#include <Wire.h>
//======================================

byte menu_selector = 2;
byte sous_menu = 0;
boolean refresh_menu_flag = 1;
#define MENUS_AMOUNT (sizeof(menus)/sizeof(menus[0]) -2)
byte Title_position (byte lenght){return ((LINE_POSITION/2)-(3*lenght));}
boolean blink_manette;
boolean blink_batterie;
byte servo_selector;
byte buffer_reglages_servo[16];
boolean modif_made_servo;
boolean modif_made_batt;
boolean modif_made_deplacements;
byte battery_type = 0;
boolean bouton_gauche;
boolean bouton_droite;
boolean bouton_bas;
boolean bouton_haut;
byte compteur_gauche;
byte compteur_droite;

void init_IHM() {
  Serial.begin(115200);
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADRESS)) { // Address 0x3D for 128x32
    Serial.println(F("UNRECOVERABLE ERROR ! Display init failed !"));
  }
  display.clearDisplay();
  
  display.drawBitmap(0,0,logo, 128, 128, WHITE);
  display.setTextSize(1);      // Normal 1:1 pixel scale
  display.setTextColor(BLACK); // Draw white text
  display.cp437(true);         // Use full 256 char 'Code Page 437' font
  display_print(60,10,F("Roboduino"));
  display_print(BOARD_NAME_LOCATION,20,BOARD_NAME);
  display.display();
  display.setTextColor(WHITE); // Draw white text

  pinMode(PIN_BOUTON_GAUCHE,INPUT_PULLUP);
  pinMode(PIN_BOUTON_DROITE,INPUT_PULLUP);
  pinMode(PIN_BOUTON_HAUT,INPUT_PULLUP);
  pinMode(PIN_BOUTON_BAS,INPUT_PULLUP);

  init_stockage_IHM();
}

void loop_IHM() {
  if(digitalRead(PIN_BOUTON_GAUCHE) == 0){ // a l'ajout d'une nouvelle entrée, une exception doit être mise a la première if de la série, si le sous menu peut avoir des fonctions sur le bouton de gauche (autre que retour)
    compteur_gauche += 1;
    if (bouton_gauche == 0){
      bouton_gauche = 1;
      refresh_menu_flag = 1;
      if (sous_menu != ID_SERVOS) sous_menu = 0;
      else if (sous_menu == ID_SERVOS && servo_selector == 0) sous_menu = 0;
      else if (sous_menu == ID_SERVOS && servo_selector != 0 && buffer_reglages_servo[servo_selector -1] > 0){modif_made_servo = 1; buffer_reglages_servo[servo_selector -1] -= 1;}
  }} else {if (compteur_gauche > 0) compteur_gauche = 0; if (bouton_gauche == 1) bouton_gauche = 0;}

  if(digitalRead(PIN_BOUTON_DROITE) == 0){
    compteur_droite += 1;
    if (bouton_droite == 0) { 
      bouton_droite = 1;
      refresh_menu_flag = 1;
      if (sous_menu == 0) sous_menu = menu_selector;
      else if (sous_menu == ID_BATTERIE && modif_made_batt == 1){modif_made_batt = 0;_stockage_update(ADRESS_BATT_TYPE, battery_type);}
      else if (sous_menu == ID_SERVOS && servo_selector == 0 && modif_made_servo){modif_made_servo = 0;servo_stockage_update();}
      else if (sous_menu == ID_SERVOS && servo_selector != 0 && buffer_reglages_servo[servo_selector -1] < 180){modif_made_servo = 1; buffer_reglages_servo[servo_selector -1] += 1;}
      else if (sous_menu == ID_DEPLACEMENTS && modif_made_deplacements == 1){modif_made_deplacements = 0;_stockage_update(ADRESS_MOVEMENT_MODE, mode_deplacement);}
  }} else {if (compteur_droite > 0) compteur_droite = 0; if (bouton_droite) bouton_droite = 0;}

  if(digitalRead(PIN_BOUTON_BAS) == 0){
    if (bouton_bas == 0) {
      bouton_bas = 1;
      refresh_menu_flag = 1;
      if(menu_selector < MENUS_AMOUNT && !sous_menu) menu_selector += 1;
      else if (sous_menu == ID_BATTERIE && battery_type > 0){battery_type -= 1;modif_made_batt = 1;}
      else if (sous_menu == ID_SERVOS && servo_selector < 16) servo_selector += 1;
      else if (sous_menu == ID_DEPLACEMENTS){mode_deplacement = 0;modif_made_deplacements = 1;}
  }} else if (bouton_bas) bouton_bas = 0;

  if(digitalRead(PIN_BOUTON_HAUT) == 0){
    if (bouton_haut == 0){
      bouton_haut = 1;
      refresh_menu_flag = 1;
      if(menu_selector > 1 && !sous_menu) menu_selector -= 1;
      else if (sous_menu == ID_BATTERIE && battery_type < (sizeof(battery_types)/sizeof(battery_types[0])-1)){battery_type += 1;modif_made_batt = 1;}
      else if (sous_menu == ID_SERVOS && servo_selector > 0) servo_selector -= 1;
      else if (sous_menu == ID_DEPLACEMENTS){mode_deplacement = 1;modif_made_deplacements = 1;}
  }} else if (bouton_haut) bouton_haut = 0;

  if (menu_selector == ID_SERVOS && sous_menu != 0){ //remettre à 0 pour permettre de spam
    if (compteur_gauche > DUREE_SPAM_BOUTON) bouton_gauche = 0;
    if (compteur_droite > DUREE_SPAM_BOUTON) bouton_droite = 0;
  }

  if(refresh_menu_flag){
    refresh_menu();
    refresh_menu_flag = 0;}
  refresh_statuts();
}

// ========================================== MENUS ==========================================

void refresh_menu(){
  display.fillRect(0, 0, LINE_POSITION, 33, SSD1306_BLACK); display.drawLine(LINE_POSITION, 0, LINE_POSITION, SCREEN_HEIGHT, WHITE);
  switch (sous_menu){
 
  case ID_DEPLACEMENTS:
    _tracer_header_sous_menu(sous_menu,true);
    display_print(2,13,F("Mode :"));
    if (mode_deplacement){
      _tracer_triangle_bas(40,13,true);
      display_print(50,13,F("Holonome"));
    } else {
      _tracer_triangle_haut(LINE_POSITION - 10, 13, true);
      display_print(50,13,F("Char"));
    }
    if(modif_made_deplacements){
      #if language == 0
        display_print(70,23,F("Sauv."));
      #else language == 1
        display_print(75,23,F("Save"));
      #endif
      _tracer_triangle_droite(100,23,true);
    }
  break;

  case ID_A_PROPOS:
    _tracer_header_sous_menu(sous_menu,true);
    display_print(2,13,F("Roboduino"));
    display_print(61,13,BOARD_NAME);
    display_print(2,23,F("Hard."));
    display_print(34,23,_HardwareVersion);
    display_print(LINE_POSITION - 46,23,F("Fir."));
    display_print(LINE_POSITION - 20,23,_FirmwareVersion);

  break;

  case ID_SERVOS: //servos
    _tracer_header_sous_menu(sous_menu, false);
    if (servo_selector != 0)_tracer_triangle_haut(2,3,true);
    if (servo_selector != 16)_tracer_triangle_bas(2,23,true);
      
    if(servo_selector == 0){ 
      display.setCursor(11, 13);
      #if language == 0
        display.print(F("Retour"));
      #else language == 1
        display.print(F("Back"));
      #endif
      _tracer_triangle_gauche(2,13,true);
      if (modif_made_servo){ 
        #if language == 0
          display_print(58,13,F("Sauveg."));
        #else language == 1
          display_print(74,13,F("Save"))
        #endif
        _tracer_triangle_droite(LINE_POSITION - 10,13,true);
      }
    } else {
      display_print(11,13,F("Servo"));
      display_print(45,13,int(ceil(float(servo_selector)/2)));
      display_print(49,13,".");
      display_print(55,13,(servo_selector + 1) % 2 + 1);
      if (buffer_reglages_servo[servo_selector-1] < 180) _tracer_triangle_droite(LINE_POSITION-10,13,true);
      if (buffer_reglages_servo[servo_selector-1] > 0) _tracer_triangle_gauche(70,13,true);
      display_print(80,13,buffer_reglages_servo[servo_selector - 1]);
    }

    if (modif_made_servo){
      #if language == 0
        display_print(30,23,F("Non sauveg. !"));
      #else language == 1
        display_print(43,23,F("Not saved !"));
      #endif
    }
  break;

  case ID_BATTERIE: //batt
    _tracer_header_sous_menu(sous_menu, true);
    display_print(2,13,F("Type :"));
    if (battery_type > 0) _tracer_triangle_bas(38,13,true);
    if (battery_type < (sizeof(battery_types)/sizeof(battery_types[0])-1)) _tracer_triangle_haut(LINE_POSITION-10,13,true);
    display_print(48,13,battery_types[battery_type]);
    
    if(modif_made_batt){
    #if language == 0
      display_print(70,23,F("Sauv."));
    #else language == 1
      display_print(75,23,F("Save"));
    #endif
    _tracer_triangle_droite(100,23,true);
    }
  break;
  
  case 0: // menu principal
    display_print(11,3,menus[menu_selector-1]);
    display_print(11,13,menus[menu_selector]);
    display_print(11,23,menus[menu_selector+1]);

    if (menu_selector != 1)_tracer_triangle_haut(2,3,true);
    _tracer_triangle_droite(2,13,true);
    if (menu_selector != MENUS_AMOUNT)_tracer_triangle_bas(2,23,true);

    display.drawRoundRect(0, 11, LINE_POSITION -1, 11 , 3, WHITE);
  break;
  
  default: // écran d'erreur
    display.setCursor(1, 2);    
    #if language == 0
      display.print(F("Erreur interne !"));
    #else language == 1
      display.print(F("Internal Error !"));
    #endif
    display.setCursor(1, 13);
    #if language == 0
      display.print(F("menu indisponnible"));
    #else language == 1
      display.print(F("menu unavailable"));
    #endif
    display.setCursor(1, 24);
    #if language == 0
      display.print(F("cliquez 'retour'"));
    #else language == 1
      display.print(F("click 'Previous'"));
    #endif
  break;
  }

  display.display();
}


// ========================================== STATUTS ==========================================
void refresh_statuts(){
  display.fillRect(LINE_POSITION +1, 0, 127 - LINE_POSITION, 33, SSD1306_BLACK); display.drawLine(LINE_POSITION, 0, LINE_POSITION, SCREEN_HEIGHT, WHITE);

  _tracer_batt(battery_type,16,6,analogRead(PIN_BATT_LVL)/10);
  _tracer_manette(manette_type,!manette_connectee,113,8);
  _tracer_mode_deplacement(mode_deplacement);

  display.display();
}

void _tracer_mode_deplacement(boolean mode){
  if (mode){
    display_write(118,15,0x18);
    display_write(118,20,0x19);
    display_write(122,18,0x1A);
    display_write(114,18,0x1B);
  } else {
    display_write(114,15,0x18);
    display_write(114,20,0x19);
    display_write(122,15,0x18);
    display_write(122,20,0x19);
  }
}

long ancienTempsBlinkBatterie;

void _tracer_batt(byte type, byte Batt_width, byte Batt_height, byte value){
  Batt_width -= 4;
  
  byte Batt_lvl;
  switch (type){ // note : value est divisée par 10 en amont, soit 0 à 102
  case 0 : break;
  case 1 : Batt_lvl = round(value)/10; break;
  default : Batt_lvl = 255; break;
  }
  
  if (Batt_lvl < BATT_ALERT/10 && type){
     if(millis() - ancienTempsBlinkBatterie > 300){
      blink_batterie = !blink_batterie;
      ancienTempsBlinkBatterie = millis();
    }
  } else blink_batterie = 1;

  if (blink_batterie){
    if (Batt_lvl == 255){display_print(110,0,F("ERR"));}
    else {
      display.drawRect(127 - Batt_width,0,Batt_width +1,Batt_height,WHITE); //dessine le corp de la batterie
      display.drawRect(128 - 3 - Batt_width,1,2,Batt_height -2,WHITE);  //dessine le bornier de la batterie
      if (type){display.fillRect(127-(Batt_lvl * Batt_width) / 10,1,Batt_width,Batt_height -2,WHITE);}//remplie la batterie selon le niveau
      else display.drawLine(127-Batt_width, 0, 127, Batt_height-1, WHITE);
    }
  }
}


long ancienTempsBlinkManette;

void _tracer_manette(byte type, boolean blink, byte x, byte y){
  if (blink){
    if(millis() - ancienTempsBlinkManette > 500){
      blink_manette = !blink_manette;
      ancienTempsBlinkManette = millis();
    }
  } else blink_manette = 1;

  if (blink_manette){
    switch (type){
    
      case 0: //filaire
        display.drawLine(x+1, y+3, x+11, y+3, WHITE);
        display.drawLine(x+6, y+2, x+13, y+2, WHITE);
        display.drawLine(x+6, y+4, x+13, y+4, WHITE);
        display.drawLine(x+8, y+1, x+11, y+1, WHITE);
        display.drawLine(x+8, y+5, x+11, y+5, WHITE);
      break;

      case 1: //2.4G
        display_print(x+2,y,"RF");
      break;

      default : //(-1) pas de manette connectée
        display_print(x+5,y,"?");
      break;
    }
  }
}
void _tracer_triangle_haut(byte x, byte y, boolean fill){if (fill) display.fillTriangle(x,y+6,  x+3,y,    x+6,y+6,  WHITE); else display.drawTriangle(x,y+6,  x+3,y,    x+6,y+6,  WHITE);}
void _tracer_triangle_droite(byte x, byte y, boolean fill){if (fill) display.fillTriangle(x,y,  x+6,y+3,  x,y+6,   WHITE); else display.drawTriangle(x,y,  x+6,y+3,  x,y+6,   WHITE);}
void _tracer_triangle_bas(byte x, byte y, boolean fill){if (fill) display.fillTriangle(x,y,  x+3,y+6,   x+6,y,  WHITE); else display.drawTriangle(x,y,  x+3,y+6,   x+6,y,  WHITE); }
void _tracer_triangle_gauche(byte x, byte y, boolean fill){if (fill) display.fillTriangle(x+6,y,  x,y+3,  x+6,y+6,   WHITE); else display.drawTriangle(x+6,y,  x,y+3,  x+6,y+6,   WHITE);}
void _tracer_header_sous_menu(byte identifiant,boolean retour){display.setCursor(Title_position(strlen(menus[identifiant])), 2); 
                                                              display.print(menus[identifiant]);
                                                              if(retour)_tracer_triangle_gauche(2,3,true);}

void display_print(byte x, byte y, String message){
  display.setCursor(x,y);
  display.print(message);
}
void display_print(byte x, byte y, int message){
  display.setCursor(x,y);
  display.print(message);
}
void display_write(byte x, byte y, int message){
  display.setCursor(x,y);
  display.write(message);
}

byte _stockage_read(uint16_t adress){
  #if USE_EXTERNAL_EEPROM == 1

  #else 
    return EEPROM.read(adress);
  #endif
}
void _stockage_update(byte adress, byte data){
  #if USE_EXTERNAL_EEPROM == 1

  #else 
    EEPROM.update(adress,data);
  #endif
}

void init_stockage_IHM(){
  if (_stockage_read(ADRESS_BATT_TYPE) == 255) _stockage_update(ADRESS_BATT_TYPE,0);else battery_type = _stockage_read(ADRESS_BATT_TYPE);
  if (_stockage_read(ADRESS_MOVEMENT_MODE) == 255) _stockage_update(ADRESS_MOVEMENT_MODE, 0); else mode_deplacement = _stockage_read(ADRESS_MOVEMENT_MODE);
  if (_stockage_read(ADRESS_SERVO11) == 255) _stockage_update(ADRESS_SERVO11,0);else buffer_reglages_servo[0] = _stockage_read(ADRESS_SERVO11);
  if (_stockage_read(ADRESS_SERVO12) == 255) _stockage_update(ADRESS_SERVO12,0);else buffer_reglages_servo[1] = _stockage_read(ADRESS_SERVO12);
  if (_stockage_read(ADRESS_SERVO21) == 255) _stockage_update(ADRESS_SERVO21,0);else buffer_reglages_servo[2] = _stockage_read(ADRESS_SERVO21);
  if (_stockage_read(ADRESS_SERVO22) == 255) _stockage_update(ADRESS_SERVO22,0);else buffer_reglages_servo[3] = _stockage_read(ADRESS_SERVO22);
  if (_stockage_read(ADRESS_SERVO31) == 255) _stockage_update(ADRESS_SERVO31,0);else buffer_reglages_servo[4] = _stockage_read(ADRESS_SERVO31);
  if (_stockage_read(ADRESS_SERVO32) == 255) _stockage_update(ADRESS_SERVO32,0);else buffer_reglages_servo[5] = _stockage_read(ADRESS_SERVO32);
  if (_stockage_read(ADRESS_SERVO41) == 255) _stockage_update(ADRESS_SERVO41,0);else buffer_reglages_servo[6] = _stockage_read(ADRESS_SERVO41);
  if (_stockage_read(ADRESS_SERVO42) == 255) _stockage_update(ADRESS_SERVO42,0);else buffer_reglages_servo[7] = _stockage_read(ADRESS_SERVO42);
  if (_stockage_read(ADRESS_SERVO51) == 255) _stockage_update(ADRESS_SERVO51,0);else buffer_reglages_servo[8] = _stockage_read(ADRESS_SERVO51);
  if (_stockage_read(ADRESS_SERVO52) == 255) _stockage_update(ADRESS_SERVO52,0);else buffer_reglages_servo[9] = _stockage_read(ADRESS_SERVO52);
  if (_stockage_read(ADRESS_SERVO61) == 255) _stockage_update(ADRESS_SERVO61,0);else buffer_reglages_servo[10] = _stockage_read(ADRESS_SERVO61);
  if (_stockage_read(ADRESS_SERVO62) == 255) _stockage_update(ADRESS_SERVO62,0);else buffer_reglages_servo[11] = _stockage_read(ADRESS_SERVO62);
  if (_stockage_read(ADRESS_SERVO71) == 255) _stockage_update(ADRESS_SERVO71,0);else buffer_reglages_servo[12] = _stockage_read(ADRESS_SERVO71);
  if (_stockage_read(ADRESS_SERVO72) == 255) _stockage_update(ADRESS_SERVO72,0);else buffer_reglages_servo[13] = _stockage_read(ADRESS_SERVO72);
  if (_stockage_read(ADRESS_SERVO81) == 255) _stockage_update(ADRESS_SERVO81,0);else buffer_reglages_servo[14] = _stockage_read(ADRESS_SERVO81);
  if (_stockage_read(ADRESS_SERVO82) == 255) _stockage_update(ADRESS_SERVO82,0);else buffer_reglages_servo[15] = _stockage_read(ADRESS_SERVO82);
}
void servo_stockage_update(){
  _stockage_update(ADRESS_SERVO11,buffer_reglages_servo[0]);
  _stockage_update(ADRESS_SERVO12,buffer_reglages_servo[1]);
  _stockage_update(ADRESS_SERVO21,buffer_reglages_servo[2]);
  _stockage_update(ADRESS_SERVO22,buffer_reglages_servo[3]);
  _stockage_update(ADRESS_SERVO31,buffer_reglages_servo[4]);
  _stockage_update(ADRESS_SERVO32,buffer_reglages_servo[5]);
  _stockage_update(ADRESS_SERVO41,buffer_reglages_servo[6]);
  _stockage_update(ADRESS_SERVO42,buffer_reglages_servo[7]);
  _stockage_update(ADRESS_SERVO51,buffer_reglages_servo[8]);
  _stockage_update(ADRESS_SERVO52,buffer_reglages_servo[9]);
  _stockage_update(ADRESS_SERVO61,buffer_reglages_servo[10]);
  _stockage_update(ADRESS_SERVO62,buffer_reglages_servo[11]);
  _stockage_update(ADRESS_SERVO71,buffer_reglages_servo[12]);
  _stockage_update(ADRESS_SERVO72,buffer_reglages_servo[13]);
  _stockage_update(ADRESS_SERVO81,buffer_reglages_servo[14]);
  _stockage_update(ADRESS_SERVO82,buffer_reglages_servo[15]);
}