#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
//#include <WiFi.h>
#include <EEPROM.h>

//////// logica botão ///////////////////
bool buttonState = LOW;     // Estado atual do botão ENTER
bool lastButtonState = LOW; // Estado anterior do botão ENTER
bool buttonState1 = LOW;     // Estado atual do botão CIMA
bool lastButtonState1 = LOW; // Estado anterior do botão CIMA
bool buttonState2 = LOW;     // Estado atual do botão BAIXO 
bool lastButtonState2 = LOW; // Estado anterior do botão BAIXO
bool buttonState3 = HIGH;     // Estado atual do botão DIREITA
bool lastButtonState3 = HIGH; // Estado anterior do botão DIREITA
bool buttonState4 = HIGH;     // Estado atual do botão ESQUERDA
bool lastButtonState4 = HIGH; // Estado anterior do botão ESQUERDA

bool CIMA=LOW;
bool BAIXO=LOW;
bool SET=LOW;
int acelera=0;
int acelera1=0;
int atraso=0;
#define UP_BUTTON_PIN 14
#define ENTER_BUTTON_PIN 12
#define DOWN_BUTTON_PIN 13
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

//GRAFICO
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
int xPos = 0;      // Posição horizontal da linha
int lastValue = 0;  // Valor anterior da entrada analógica
int graphData[OLED_WIDTH];  // Dados do gráfico
int menor=0;
// Initialize the OLED display
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//declaraçãoes globais
  int menu=0;
  int submenu=0;
  int submenu1=0;
  int submenu2=0;

//controle de tensao e corrente ////
int tensao=0;
int corrente=0;
bool SAIDA_TENSAO=0;
bool SAIDA_CORRENTE=0; 
bool SAIDA_RELE=0;

int Div_tensao=10;
int Div_corrente=50;
//comparadores
int maiortensao=240;
int menortensao=190;
int rearmetensaominima=200;
int rearmetensaomaxima=235;
int sobrecorrente=10;
int tempodisparotensao=100;
int temporearmetensao=100;
int tempodisparocorrente=10;
int temporearmecorrente=10;
bool rearmeautomatico=1;
int tempoparaligar=30;
///tempos contatores
int tempo_segundo_disparo_tensao=0;
int tempo_segundo_rearme_tensao=0;
int tempo_segundo_disparo_corrente=0;
int tempo_segundo_rearme_corrente=0;
int ligar=0;
//entradas 
  int valorGPIO32; // Lê o valor da porta analógica GPIO32
  int valorGPIO33; // Lê o valor da porta analógica GPIO33


void setup() {
        Serial.begin(9600);
        EEPROM.begin(512); // Inicializa a EEPROM com 512 bytes de tamanho
        pinMode(UP_BUTTON_PIN, INPUT_PULLUP);
        pinMode(ENTER_BUTTON_PIN, INPUT_PULLUP);
        pinMode(DOWN_BUTTON_PIN, INPUT_PULLUP);
        pinMode(15, OUTPUT);
        digitalWrite(15, LOW);
          // Initialize the OLED display
        display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
        display.display();
      delay(2);  // Pause for 2 seconds
       // Clear the display
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("CARREGANDO");
  display.display();
  
    // Inicializa os dados do gráfico
  for (int i = 0; i < OLED_WIDTH; i++) {
    graphData[i] = OLED_HEIGHT / 2;
  }
}



void loop() {

   valorGPIO32 = analogRead(32); // Lê o valor da porta analógica GPIO32
   valorGPIO33 = analogRead(33); // Lê o valor da porta analógica GPIO33
  delay(10);
  tensao=(valorGPIO33/Div_tensao);
  corrente=(valorGPIO32/Div_corrente);
  delay(10);
//---------DECLARAÇÕES DE OLED--------------
      display.clearDisplay();  // Limpa a tela
      display.setTextSize(1);
      display.setTextColor(SSD1306_WHITE); 
////////////////////////////////////////////
digitalWrite(15, SAIDA_RELE);

  botoes();//chama função de botoes
  diparotensao();
  if(submenu==0){
    ////// indice botoes //////
      if(CIMA==1){menu--;}
      if(BAIXO==1){menu++;}
      if(menu>5||menu<0){menu=0;}
     if(SET==1){submenu=1;}//if(submenu>5||submenu<0){submenu=0;}
    ///////////////////////////
     display.clearDisplay();  // Limpa a tela
     display.setTextSize(1);
     display.setCursor(2, 1);
     if(menu==0)display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); 
     display.print(" INICIO ");
     display.setTextColor(SSD1306_WHITE); 
     display.setCursor(2, 10);
     if(menu==1)display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
     display.print(" AJ. TENSAO ");
     display.setTextColor(SSD1306_WHITE); 
     display.setCursor(2, 20);
     if(menu==2)display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
     display.print(" AJ. CORRENTE ");
     display.setTextColor(SSD1306_WHITE); 
     display.setCursor(2, 30);
     if(menu==3)display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
     display.print(" AJ. TEMPO ");
     display.setTextColor(SSD1306_WHITE); 
     display.setCursor(2, 40);
     if(menu==4)display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
     display.print(" GRAFICO ");
     display.setTextColor(SSD1306_WHITE); 
     display.setCursor(2, 50);
     if(menu==5)display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
     display.print(" COMUNICACAO ");
    }



          if(submenu==1){//inicio de submenu 1
   
            if(menu==0){ 
               if(CIMA==1) {Div_tensao++;}
               if(BAIXO==1) {Div_tensao--;}
             display.clearDisplay();  // Limpa a tela
             display.setTextSize(1);    
             display.setCursor(2, 2);      
             display.println("---REDE ELETRICA---");
             display.setCursor(2, 16);
             display.print("U: ");
             display.setTextSize(2);     
             display.print(tensao); 
             display.print("V~ ");
             display.setTextSize(1); 
              if(tensao<rearmetensaomaxima && tensao>rearmetensaominima){display.print("Normal ");}
              if(tensao>maiortensao){display.print("Sobre>                  ");}
              if(tensao<menortensao){display.print("Sub  <                  ");}
              if(tempo_segundo_disparo_tensao>0) {
             display.print(tempo_segundo_disparo_tensao);
              }
             if (tempo_segundo_rearme_tensao>0){
             display.print(tempo_segundo_rearme_tensao);}

             display.setCursor(2, 36);
             display.print("I: ");
             display.setTextSize(2);
             display.print(corrente);
             display.print(" A~"); 
             display.setTextSize(1);
             if(tempo_segundo_disparo_corrente>0){display.print(tempo_segundo_disparo_corrente);}
             display.setCursor(2, 54); 
             display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);      
             display.print("^ voltar ");
             if(SAIDA_RELE==1){display.print("   Normal  ");}
           if(CIMA==1){submenu=0;}//volta
              }
           if(menu==1){       
           if(CIMA==1){submenu=2;}
           if(CIMA==1) {submenu1--;}
           if(BAIXO==1){submenu1++;}
           if(submenu1>4||submenu1<0){submenu1=0;}
            display.clearDisplay();  // Limpa a tela
            display.setTextSize(1);
            display.setCursor(2, 2); 
            display.println("Selecione o ajuste");
            display.setCursor(2, 12); 
          if(submenu1==0) display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);    
            display.println("--TENSAO MINIMA >");
            display.setTextColor(SSD1306_WHITE);
            display.setCursor(2, 22);
          if(submenu1==1) display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);    
            display.println("--TENSAO MIN REARME");
            display.setTextColor(SSD1306_WHITE);
            display.setCursor(2, 32);
          if(submenu1==2) display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);    
            display.println("--TENSAO MAXIMA >");
            display.setTextColor(SSD1306_WHITE);
            display.setCursor(2, 42);
          if(submenu1==3) display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);    
            display.println("--TENSAO MAX REARME");
            display.setTextColor(SSD1306_WHITE);
          if(submenu1==4) {display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
            if(SET==1){submenu=0;}}    
            display.println("<--Volta");
            display.setTextColor(SSD1306_WHITE);
            display.display();
           }
       if(menu==2){
            display.clearDisplay();  // Limpa a tela
            display.setTextSize(1);
            display.setCursor(2, 2);      
            display.println("AJ.CORRENTE MAXIMA");
            display.setCursor(20, 22);
            display.setTextSize(2);
            display.print("I:");
            display.print(sobrecorrente);
            display.print("A");
            display.display();
           }
       if(menu==3){
         if(CIMA==1){submenu=3;}
         if(CIMA==1) {submenu2--;}
         if(BAIXO==1){submenu2++;}
         if(submenu2>3||submenu2<0){submenu2=0;}
          display.clearDisplay();  // Limpa a tela
          display.setTextSize(1);
          display.setCursor(2, 12); 
         if(submenu2==0) display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);         
          display.println("AJ.TEMPO FALHA TENSAO");
          display.setTextColor(SSD1306_WHITE);
          display.setCursor(2, 22);
         if(submenu2==1) display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);    
          display.println("AJ.TEMPO FALHA CORRENTE");
          display.setTextColor(SSD1306_WHITE);
          display.setCursor(2, 32);
        if(submenu2==2) display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);    
          display.println("AJ.TEMPO RESET");
          display.setTextColor(SSD1306_WHITE);
          display.setCursor(2, 52);
        if(submenu2==3) {display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
          if(SET==1){submenu=0;}}    
          display.println("<--Volta");
          display.setTextColor(SSD1306_WHITE); 
          display.display();

         }
        if(menu==4){  
          grafico();
        if(CIMA==1){submenu=0;}
       }
      if(menu==5){
         display.clearDisplay();  // Limpa a tela
         display.setTextSize(1);
         display.setCursor(2, 2);      
         display.println("COMUNICACAO");
         display.setCursor(2, 22);
         display.println("Falha comunicacao");
         display.display();
        }
}//fim de submenu 1

        if(submenu==2){
            if(SET==1){submenu=1;}
            if(submenu1==0){
             display.clearDisplay();  // Limpa a tela
             display.setTextSize(1);
             display.setCursor(2, 2);      
             display.println("Aj.tensao MINIMA  de funcionamento >");
             display.setCursor(2, 22);
             display.setTextSize(2);
             display.print("U:");
             display.print(menortensao);
             display.print("Vac");
             display.display(); 
              }
             if(submenu1==1){
             display.clearDisplay();  // Limpa a tela
             display.setTextSize(1);
             display.setCursor(2, 2);      
             display.println("Aj.tensao min REARME");
             display.setCursor(2, 22);
             display.setTextSize(2);
             display.print("U:");
             display.print(rearmetensaominima);
             display.print("Vac");
             display.display(); 
             }
              if(submenu1==2){
             display.clearDisplay();  // Limpa a tela
             display.setTextSize(1);
             display.setCursor(2, 2);      
             display.println("Ajuste tensao MAXIMA  de funcionamento >");
             display.setCursor(2, 22);
             display.setTextSize(2);
             display.print("U:");
             display.print(maiortensao);
             display.print("Vac");
             display.display(); 
              }
             if(submenu1==3){
             display.clearDisplay();  // Limpa a tela
             display.setTextSize(1);
             display.setCursor(2, 2);      
             display.println("Aj.tensao max REARME");
             display.setCursor(2, 22);
             display.setTextSize(2);
             display.print("U:");
             display.println(rearmetensaomaxima);
             display.print("Vac");
             display.display(); 
             }
          }
                    if(submenu==3){
                      if(SET==1){submenu=1;}
                    if(submenu2==0){
                     display.clearDisplay();  // Limpa a tela
                     display.setTextSize(1);
                     display.setCursor(2, 2);      
                     display.println("Aj. Tempo Falha tensao");
                     display.setCursor(2, 22);
                     display.setTextSize(2);
                     display.println(tempodisparotensao);
                     display.display(); 
                     }
                    if(submenu2==1){
                     display.clearDisplay();  // Limpa a tela
                     display.setTextSize(1);
                     display.setCursor(2, 2);      
                     display.println("Aj. Tempo Falha Corrente");
                     display.setCursor(2, 22);
                     display.setTextSize(2);
                     display.println(tempodisparocorrente);
                     display.display(); 
                     }
                   if(submenu2==2){
                    display.clearDisplay();  // Limpa a tela
                    display.setTextSize(1);
                    display.setCursor(2, 2);      
                    display.println("Ajuste Tempo REARME");
                    display.setCursor(2, 22);
                    display.setTextSize(2);
                     display.println(tempo_segundo_rearme_tensao);
                    display.display(); 
                   }
               }
display.display();
}///############ FINAL DO LOOP ####################

 void botoes(){
//ZERA OS SINAIS DE BOTAO
       CIMA=0;
       BAIXO=0;
       SET=0;

///////////  FUNÇÃO BOTAO DESCE //////////////////////////////
     buttonState2 = digitalRead(DOWN_BUTTON_PIN);//botão precionado
      // if(buttonState2 == LOW){acelera1++;}else {acelera1=0;}
       if ((buttonState2 == LOW && lastButtonState2 == HIGH)||(acelera1>10)) {        
        BAIXO=1;// Gera um pulso
      } lastButtonState2 = buttonState2;
///////////  FUNÇÃO BOTAO SOBE //////////////////////////////
    buttonState1 = digitalRead(UP_BUTTON_PIN);//botão precionado
      // if(buttonState1 == LOW){acelera++;}else {acelera=0;}
       if ((buttonState1 == LOW && lastButtonState1 == HIGH)|| (acelera>10)) {        
        CIMA=1;// Gera um pulso
      }lastButtonState1 = buttonState1;
/////// ////////função botão SET /////////////////////////////////////
    buttonState = digitalRead(ENTER_BUTTON_PIN);//botão precionado

       // Verifica se o botão foi pressionado
  if (buttonState == LOW && lastButtonState == HIGH) {//SET
      SET=1;// Gera um pulso
   }lastButtonState = buttonState;

       atraso++;
  if (buttonState == HIGH){atraso=0;} 
       if(atraso>4){atraso=4;}
     //  if(atraso==2){SET=1;}

 }  





 void grafico(){      
      display.clearDisplay();  // Limpa a tela
      display.setTextSize(1);
      display.setCursor(2, 2);       
      display.print(" Grafico ");
      display.print(tensao);
      display.print(" Vac ");
      display.println(menor);
      display.setCursor(2, 54);       
      display.print("^ voltar ");
      display.drawRect(0,0,128,64, SSD1306_WHITE);//desenha quadrado
      //( inicio > ,inicio v, tamanha horizontal, tamanho vertical,)
      display.drawRect(0, menor, 128, 1, SSD1306_WHITE);//desenha linha
       // Mapeia o valor lido para o intervalo do display OLED
      int displayValue = map(tensao, 400, 0,0, OLED_HEIGHT);
     // Move o gráfico para a esquerda
      for (int i = 1; i < OLED_WIDTH; i++) {
      graphData[i - 1] = graphData[i];
       }
        // Adiciona o novo valor ao gráfico
      graphData[OLED_WIDTH - 1] = displayValue;
      drawGraph();      // Desenha o gráfico
      display.display();// Atualiza o display
       if(BAIXO==1){menor++;}
       if(CIMA==1){menor--;}
       }
 void drawGraph() {// FUNÇÃO GRAFICO
    for (int i = 1; i < OLED_WIDTH; i++) {
    int y1 = graphData[i - 1];
    int y2 = graphData[i];
    display.drawLine(i - 1, y1, i, y2, SSD1306_WHITE);
  }
}
void diparotensao(){
  ligar++;
 if(ligar==tempoparaligar){ligar=tempoparaligar;}
  //logica para tensao
 if(tensao>maiortensao||tensao<menortensao){tempo_segundo_disparo_tensao++;}else{tempo_segundo_disparo_tensao=0;}
 if(tempo_segundo_disparo_tensao > tempodisparotensao){SAIDA_TENSAO=0;tempo_segundo_disparo_tensao = tempodisparotensao;}
 if(tensao<rearmetensaomaxima && tensao>rearmetensaominima){
 if(SAIDA_TENSAO==0){tempo_segundo_rearme_tensao++;}else{tempo_segundo_rearme_tensao=0;}
 if(tempo_segundo_rearme_tensao>temporearmetensao){SAIDA_TENSAO=1;}
   }
  //logica para corrente
  if(corrente > sobrecorrente){tempo_segundo_disparo_corrente++;}
  else{tempo_segundo_disparo_corrente=0;}
  if(tempo_segundo_disparo_corrente > tempodisparocorrente){
    SAIDA_CORRENTE=0;tempo_segundo_disparo_corrente = tempodisparocorrente;}
    if(rearmeautomatico==1){
  if(SAIDA_CORRENTE==0){tempo_segundo_rearme_corrente++;}else{tempo_segundo_rearme_corrente=0;}
  if(tempo_segundo_rearme_corrente > temporearmecorrente){SAIDA_CORRENTE=1;}
    }
  //LOGICA PARA LIGAR SAIDA 
  if(SAIDA_TENSAO==1 && SAIDA_CORRENTE==1){SAIDA_RELE=1;}else{SAIDA_RELE=0;}
 // }//fim do tempo para ligar
}