#include <LiquidMenu.h>

//#include <LiquidCrystal.h>

// int led_seleccionado = 0;
bool mode = false;
int x = 0;
TaskHandle_t Tarea0;

int x1 = 0; //Para los ciclos
int delayciclos;
int demora;
int timer = 0;
int cursorPos;
int cursorPos2 = 0;
int Contaux = 0;
unsigned long Ciclos = 0;
unsigned long Ciclos_1 = 0;
unsigned long Ciclos_2 = 0;
unsigned long tanterior;
int Cont_1 = 0;
int Cont_2 = 0;
int Cont_3 = 0;
boolean Giro = true;
boolean auxGiro;
String Gir;
boolean a = false;
boolean b = false;
unsigned long Pasos = 0;
bool showChar = true;


//Driver Motor Step
const int steppin = 33;
const int dirpin = 32;

//Display 16x2
//LiquidCrystal_I2C lcd(0x27, 16, 2);
const int RS = 23, EN = 22, D4 = 5, D5 = 18, D6 = 19, D7 = 21;
LiquidCrystal lcd(RS, EN, D4, D5, D6, D7);

byte tpuntos[] = {
  0b00000,
  0b00000,
  0b00001,
  0b01000,
  0b11100,
  0b01001,
  0b01000,
  0b01100
}; // t:

byte ipuntos[] = {
  0b00000,
  0b00000,
  0b00001,
  0b01000,
  0b00000,
  0b01001,
  0b01000,
  0b01100
}; //i:

byte s[] = {
  0b00000,
  0b01000,
  0b10011,
  0b10100,
  0b10010,
  0b10001,
  0b01110,
  0b00000
}; //(s

byte paren[] = {
  0b00000,
  0b10000,
  0b01000,
  0b01000,
  0b01000,
  0b01000,
  0b10000,
  0b00000
}; // )

byte uve[]{
  0b00000,
  0b00000,
  0b10101,
  0b10100,
  0b10100,
  0b10101,
  0b01000,
  0b00000
};

byte UP[]{
  0b00100,
  0b01110,
  0b11111,
  0b00100,
  0b00100,
  0b00100,
  0b00000,
  0b00000,
};

const int Pulsa = 4;

//ENCODER
const int outputA = 15; // CLK
const int outputB = 2; // DT
const int SW = 16;
int incremento = 0;
int incrementos = 0;
int aState;
int aLastState;

//LiquidMenu
//Pantalla 1
LiquidLine linea1(1, 0, "Volumen");
LiquidLine linea2(1, 1, "Encender");
//LiquidLine linea3(1, 0, "Ciclos?");
LiquidLine linea3(1, 0, "Opciones");
//LiquidLine linea4(1, 1, "Hola a todos");
LiquidScreen pantalla1(linea1,linea2,linea3);

//Pantalla linea 1 -> Pantalla 2
LiquidLine linea1_2(1, 0, "Cantidad");
LiquidLine linea2_2(1, 1, "Repeticiones");
LiquidLine linea3_2(1, 0, "Atras");
LiquidScreen pantalla2(linea1_2,linea2_2,linea3_2);

//Pantalla linea 2 -> Pantalla 3
LiquidLine linea1_3(1, 0, "Hacia la Der.");
LiquidLine linea2_3(1, 1, "Hacia la Izq.");
LiquidLine linea3_3(1, 0, "Atras");
LiquidScreen pantalla3(linea1_3,linea2_3,linea3_3);

//Pantalla linea 4 -> Pantalla 4
LiquidLine linea1_4(1, 0, "Opcion 1");
LiquidLine linea2_4(1, 1, "Opcion 2");
LiquidLine linea3_4(1, 1, "Atras");
LiquidScreen pantalla4(linea1_4,linea2_4,linea3_4);

LiquidMenu menu(lcd,pantalla1,pantalla2,pantalla3,pantalla4);

void setup() {

  Serial.begin(115200);
  pinMode(Pulsa, INPUT_PULLUP);
  pinMode(SW,INPUT_PULLUP);
  pinMode(outputA, INPUT);
  pinMode(outputB, INPUT);
  pinMode(steppin, OUTPUT);
  pinMode(dirpin, OUTPUT);

  xTaskCreatePinnedToCore(Motor, "Tarea_0", 1000, NULL, 1, &Tarea0, 0);

  lcd.begin(16, 2);
  lcd.createChar (0, tpuntos);
  lcd.createChar (1, ipuntos);
  lcd.createChar (2, s);
  lcd.createChar (3, paren);
  lcd.createChar (4, uve);

  tanterior = millis();

  linea1.set_focusPosition(Position::LEFT); 
  linea2.set_focusPosition(Position::LEFT); 
  linea3.set_focusPosition(Position::LEFT); 
   
  linea1.attach_function(1, fn_volumen); 
  linea2.attach_function(1, fn_encender);
  linea3.attach_function(1, fn_opciones);
  
  menu.add_screen(pantalla1);
  
//---------------------------------------------

  linea1_2.set_focusPosition(Position::LEFT); 
  linea2_2.set_focusPosition(Position::LEFT); 
  linea3_2.set_focusPosition(Position::LEFT); 
  
  linea1_2.attach_function(1, fn_cantidad);
  linea2_2.attach_function(1, fn_ciclos); 
  linea3_2.attach_function(1, fn_atras);
   
  menu.add_screen(pantalla2);

//---------------------------------------------

  linea1_3.set_focusPosition(Position::LEFT); 
  linea2_3.set_focusPosition(Position::LEFT);
  linea3_3.set_focusPosition(Position::LEFT); 
   
  linea1_3.attach_function(1, fn_onR); 
  linea2_3.attach_function(1, fn_onL);
  linea3_3.attach_function(1, fn_atras); 
    
  menu.add_screen(pantalla3);

//---------------------------------------------

  linea1_4.set_focusPosition(Position::LEFT); 
  linea2_4.set_focusPosition(Position::LEFT); 
  linea3_4.set_focusPosition(Position::LEFT); 
   
  linea1_4.attach_function(1, fn_opcion1); 
  linea2_4.attach_function(1, fn_opcion2);
  linea3_4.attach_function(1, fn_atras);

  menu.add_screen(pantalla4);

//---------------------------------------------
  pantalla1.set_displayLineCount(2);
  pantalla2.set_displayLineCount(2);
  pantalla3.set_displayLineCount(2);
  pantalla4.set_displayLineCount(2);

  menu.set_focusedLine(0);

  menu.update();
}

void loop() {

  selectOption();
  atrass();
  aState = digitalRead(outputA);
  if (aState != aLastState){   
    if (digitalRead(outputB) != aState) {      
      incremento++;
      if(incremento>1){
        incremento = 0;
        menu.switch_focus(false);
      }
    }     
    else {
      incremento++;
      if(incremento>1){
        incremento = 0;
        menu.switch_focus(true);
      }    
    }
    menu.update();
    aLastState = aState;
  }
}

//Funciones:::::
void selectOption(){
  if(digitalRead(SW) == LOW){
    menu.call_function(1);
    delay(500);
  }
}

void fn_volumen(){
  menu.change_screen(2);
  menu.set_focusedLine(0);
}

void fn_encender(){
  menu.change_screen(3);
  menu.set_focusedLine(0);
}

void fn_opciones(){
  menu.change_screen(4);
  menu.set_focusedLine(0);
}

void fn_off(){
  menu.change_screen(1);
  menu.set_focusedLine(0);
}

void fn_atras(){
  menu.change_screen(1);
  menu.set_focusedLine(0);
}

void Motor(void *parameter){
 
  while(1==1){
    while(mode == true && x1 < Ciclos){
      for(x1 = 0; x1 < Ciclos; x1++){
        delay(delayciclos);
        digitalWrite(dirpin, Giro);
        for(x = 0; x < Pasos; x++){
          digitalWrite(steppin, HIGH);
          digitalWrite(steppin, LOW);
          delayMicroseconds(5000);
          if(digitalRead(Pulsa) == LOW){
            break;
            atrass();
          }
        }
      }
      Giro = true;
    }
    vTaskDelay(50);
  }
}

void fn_onR(){

  Pasos = 4294967295;
  Ciclos = 4294967295;
  delayciclos = 0;
  Giro = true;
  a = true;
  b = true;
  fn_ciclos();
  menu.change_screen(3);
  menu.set_focusedLine(0);
}

void fn_onL(){
  
  Pasos = 4294967295;
  Ciclos = 4294967295;
  delayciclos = 0;
  Giro = false;
  a = true;
  b = true;
  fn_ciclos();
  menu.change_screen(3);
  menu.set_focusedLine(1);
}

void fn_cantidad(){

  Ciclos = 1;
  delayciclos = 0;
  a = true;
  fn_ciclos();
}

void fn_ciclos(){

  lcd.clear();
  delay(250);
  for(int i = 0; i < 3; i++){

      while(digitalRead(SW)==1 && a == false){
      if(digitalRead(Pulsa) == LOW){
       break;
       atrass();
      }
      Movement();
      switch(i){
        case 0:
        Ciclos_1 = Contaux;
        cursorPos = 12;
        lcd.setCursor(11, 0);
        lcd.print(Ciclos_2);
        lcd.setCursor(11,1);
        lcd.print(demora);
        break;
        case 1:
        Ciclos_2 = Contaux;
        cursorPos = 11;
        lcd.setCursor(12, 0);
        lcd.print(Ciclos_1);
        lcd.setCursor(11,1);
        lcd.print(demora);
        break;
        case 2:
        demora = Contaux;
        lcd.setCursor(11, 0);
        lcd.print(Ciclos);
        cursorPos = 11;
        cursorPos2 = 1;

        break;
      }
      lcd.setCursor(1, 0);
      lcd.write(165);
      lcd.print("Repet. = ");
      lcd.setCursor(1, 1);
      lcd.write(165);
      lcd.print("Demora = ");
      lcd.setCursor(13,1);
      lcd.write((byte)2);
      lcd.write((byte)3);
      //lcd.print("(s)");

      lcd.setCursor(cursorPos, cursorPos2);
    
      if (millis() - tanterior >= 350) {
        tanterior = millis();

        if (showChar) {
          lcd.print(Contaux);
        } 
        else {
          lcd.print(" ");
        }
        showChar = !showChar;
      }

      Ciclos = Ciclos_2*10 + Ciclos_1*1;
      
      delayciclos = demora*1000;
    }
    delay(250);
    Contaux = 0;
    cursorPos2 = 0;
    lcd.clear();
    delay(100);
  }
  Ciclos_1 = 0; Ciclos_2 = 0;

  if(b == false){
    for(int i = 0; i < 4; i++){
        if(digitalRead(Pulsa) == LOW){
          break;
          i = 2;
          atrass();
        }
      delay(150);
      while(digitalRead(SW)==1 && digitalRead(Pulsa) == HIGH){
        Movement();
        switch(i){
          case 0:
            Cont_1 = Contaux;
            lcd.setCursor(10, 0);
            lcd.print(Cont_3);
            lcd.print(Cont_2);
            break;
          case 1:
            Cont_2 = Contaux;
            lcd.setCursor(10, 0);
            lcd.print(Cont_3);
            lcd.setCursor(12, 0);
            lcd.print(Cont_1);
            break;
          case 2:
            Cont_3 = Contaux;
            lcd.setCursor(11, 0);
            lcd.print(Cont_2);
            lcd.print(Cont_1);
            break;
          case 3:
            cursorPos2 = 1;
            lcd.setCursor(10,0);
            lcd.print(Pasos);
            lcd.setCursor(1,1);
            if(auxGiro == 1){
              auxGiro = "Funca 1";
              lcd.print(String(auxGiro));
              
            }
            else{
              auxGiro = "Funca 0";
              lcd.print(String(auxGiro));
            }
            break;

        }
        lcd.setCursor(0, 0);
        lcd.print("Cant. => ");
        lcd.setCursor(14, 0);
        lcd.print("ml ");
        cursorPos = 12 - i;

        lcd.setCursor(cursorPos, cursorPos2);
        if (millis() - tanterior >= 350) {
          tanterior = millis();

          if (showChar) {
          lcd.print(Contaux);
          } 
          else {
          lcd.print(" ");
          }
          showChar = !showChar;
        } 
      }
      Pasos = (Cont_1 + 10*Cont_2 + 100*Cont_3);
      
      delay(150);
      Contaux = 0;
      demora = 0;
      lcd.clear();
    }
  }
  Cont_1 = 0; Cont_2 = 0; Cont_3 = 0;
  cursorPos2 = 0;
  x1 = 0;
  a = false;
  b = false;
  mode = true;
  proceso();
}

void fn_opcion1(){
  lcd.clear();
  lcd.setCursor(4, 0);
  //lcd.print(cantidad);
  lcd.setCursor(0, 1);
  lcd.print(millis() / 1000);
  delay(2000);
}

void fn_opcion2(){
  lcd.print("hello, world!");
  lcd.setCursor(0, 1);
  lcd.print(millis() / 1000);
  delay(2000);
}

void Movement(){

  aState = digitalRead(outputA);
  if (aState != aLastState){
    if (digitalRead(outputB) != aState){
      incremento++;
      if(incremento>1){
        incremento = 0;
        Contaux--;
        auxGiro = 1;
      }
    } 
    else {
      incremento++;
      if(incremento>1){
        incremento = 0;
        Contaux++;
        auxGiro = 0;
      }
    }
    aLastState = aState;
    lcd.clear();
  }

  if(Contaux < 0){
    Contaux = 0;
  }
  
  if(Contaux > 9){
    Contaux = 9;
  }
}

void proceso(){

  lcd.clear();
  while(mode == true && x1 < Ciclos){
    if(digitalRead(SW) == LOW){
      mode = false;
      x1 = 0;
      Pasos = 0;
      Ciclos = 0;
      x1 = 0;
      break;
    }
    lcd.setCursor(0, 0);
    lcd.print("R");
    lcd.write((byte)0);
    if(Ciclos != 4294967295){
      lcd.print(Ciclos);
    }
    else{
      lcd.print("0");
    }
    lcd.setCursor(6, 0);
    lcd.print("R");
    lcd.write((byte)1);
    lcd.print(x1);
    lcd.setCursor(12,0);
    if(Giro == true){
      lcd.print("DER");
    }
    else{
      lcd.print("IZQ");
    }
    lcd.setCursor(0, 1);
    lcd.print("t:" + String(delayciclos/1000));
    lcd.write((byte)2);
    lcd.write((byte)3);
    lcd.setCursor(6, 1);
    lcd.write((byte)4);
    if(Pasos != 4294967295){
    lcd.print(Pasos);
    }
    else{
      lcd.print("0");
    }
    lcd.print("/");
    lcd.print(x);
    lcd.setCursor(14,1);
    lcd.print("u");

    if(1 < x && x < 10){
      lcd.clear();
    }
  }
  mode = false;
}

void atrass(){

  if(digitalRead(Pulsa) == LOW){
    Pasos = 0;
    mode = false;
    menu.change_screen(1);
    menu.set_focusedLine(0);
    digitalWrite(steppin,LOW);  
  }
}
A4988