//LED SENTIDO DE GIRO
int verde =35;
int amarillo=34;
int pin_rele= 10;

//DEFINIMOS LOS ESTADIOS
int estado=0;
int estadogirohorario=0;
int estadogiroantihorario=1;
int estadoemergencia=2;
const int pulsadorCambioSentido = 12;
const int Potenciometro = 14;

//pulsaor de emergencia
const int pulsador_emergencia = 33;

hw_timer_t * timer = NULL;


//MOTOR
const int motor_A = 19;   
const int motor_B = 18;
const int motor_C = 5; 
const int motor_D = 17; 


#define NUMSEC 4  // 4 u 8 # lineas de  secuencia de movimiento
int tabla_pasos[NUMSEC][4]={ // A B C D
                // {HIGH,LOW,  LOW, LOW},
                                                  {HIGH,HIGH, LOW, LOW},
                // {LOW, HIGH, LOW, LOW},
                                                  {LOW, HIGH, HIGH,LOW},
                // {LOW, LOW,  HIGH,LOW},
                                                  {LOW, LOW,  HIGH,HIGH},
                // {LOW, LOW,  LOW, HIGH},
                                                  {HIGH,LOW,  LOW, HIGH}                       
              };
#define NPASOS_VUELTA_INTERNA 32 // 32 paso completo, 64 semipaso
#define RELACION_VUELTAS_ENGRANAJE 64  // VUELTAS INTERNAS PARA HACER 1 VUELTA EXTERNA 

int npasos=0;  // llega a NPASOS_VUELTA_INTERNA y cuenta vuelta interna ++
int nvueltas_internas=0;  // llega a RELACION_VUELTAS_ENGRANAJE y cuenta vuelta externa ++ 
int nvueltas_externas=0;  // lleva la cuenta de vueltas del eje externo 


// funcion que proporciona el movimiento del siguiente paso
void sgte_paso(){
  static int idsec=0; // va recorriendo la siguiente tabla  

  // escribimos los valores nuevos de la tabla en los pines ABCD
  digitalWrite(motor_A, tabla_pasos[idsec][0]);
  digitalWrite(motor_B, tabla_pasos[idsec][1]);        
  digitalWrite(motor_C, tabla_pasos[idsec][2]);
  digitalWrite(motor_D, tabla_pasos[idsec][3]);

  if( (++idsec)==NUMSEC) idsec=0;  

  return;
}
void sgte_paso2(){
  static int idsec=0; // va recorriendo la siguiente tabla  

  // escribimos los valores nuevos de la tabla en los pines ABCD
  digitalWrite(motor_D, tabla_pasos[idsec][0]);
  digitalWrite(motor_C, tabla_pasos[idsec][1]);        
  digitalWrite(motor_B, tabla_pasos[idsec][2]);
  digitalWrite(motor_A, tabla_pasos[idsec][3]);

  if( (++idsec)==NUMSEC) idsec=0;  

  return;
}

//TIMER QUE NOS DIGA ESTADO DEL MOTOR
void  finTimer() { 
  Serial.println("El motor ha dado ");
  Serial.print(nvueltas_externas);
  Serial.print(" vueltas externas");
  

}
//BOTON DE EMERGENCIA
//void IRAM_ATTR ISR_pulsador_emergencia(){
  //int current_millis = millis(); 
//  if(estado != estadoemergencia){ //si se encuentra en otro estado distinto al de emergencia
//    estado = estadoemergencia; //cuando se pulsa seta de emergencis
//    Serial.printf("ESTADO DE EMERGENCIA (para volver al funcionamiento normal pulse 3 segundos el pulsador de emergencia) \n"); 
//    digitalWrite(verde, LOW);
//    digitalWrite(amarillo, LOW);
//    digitalWrite(pin_rele, HIGH); //apagamos leds y rele en el momento de la interrupción
// }
// float tiempopulsando=0;
// else if(estado == estadoemergencia){ //pulasr durante 3 segundos 
//  if(tiempopulsando>3){
//   Serial.printf("Salimos del estado EMERGENCIA al estado ARRANQUE \n"); 
//    estado=0;
//    }
 //}
 //}
void IRAM_ATTR ISR_CambioSentido(){
  if(estado==0){
    estado = 1;
  }else if(estado==1){
    estado = 0;
  }
}


void setup() {
  pinMode(motor_A, OUTPUT);
  pinMode(motor_B, OUTPUT);
  pinMode(motor_C, OUTPUT);
  pinMode(motor_D, OUTPUT);
  timer = timerBegin(0, 80, true);                
  timerAttachInterrupt(timer, finTimer, true); 
  timerAlarmWrite(timer, 2e6, true);  
  timerAlarmEnable(timer);
  
  //pinMode(pulsador_emergencia,INPUT);
  pinMode(pulsadorCambioSentido, INPUT);   


  //attachInterrupt(digitalPinToInterrupt(pulsador_emergencia), ISR_pulsador_emergencia,FALLING);
  attachInterrupt(digitalPinToInterrupt(pulsadorCambioSentido), ISR_CambioSentido,FALLING);

  pinMode(verde,OUTPUT);
  pinMode(amarillo, OUTPUT);


  Serial.begin(115200);
}

void loop() {
if(estado==0){
  digitalWrite(verde,HIGH);
  digitalWrite(amarillo,LOW);
  npasos++;  //si  llega a NPASOS_VUELTA_INTERNA -> cuenta nvueltas interna ++

  if(npasos == NPASOS_VUELTA_INTERNA){
    npasos=0;
    nvueltas_internas++;
    if(nvueltas_internas==RELACION_VUELTAS_ENGRANAJE){  // llega a RELACION_VUELTAS_ENGRANAJE y cuenta vuelta externa ++ 
      nvueltas_internas=0;
      nvueltas_externas++;  // lleva la cuenta de vueltas del eje externo 
    }
  }
  int valorPot;
    valorPot = analogRead(Potenciometro);
    int retardo = map(valorPot, 0, 1023, 1, 10);
    delay(retardo);
  sgte_paso(); // mueve el motor7
}
if(estado==1){
  digitalWrite(verde,LOW);
  digitalWrite(amarillo,HIGH);
  npasos++;  //si  llega a NPASOS_VUELTA_INTERNA -> cuenta nvueltas interna ++

  if(npasos == NPASOS_VUELTA_INTERNA){
    npasos=0;
    nvueltas_internas++;
    if(nvueltas_internas==RELACION_VUELTAS_ENGRANAJE){  // llega a RELACION_VUELTAS_ENGRANAJE y cuenta vuelta externa ++ 
      nvueltas_internas=0;
      nvueltas_externas--;  // lleva la cuenta de vueltas del eje externo 
    }
  }
  int valorPot;
    valorPot = analogRead(Potenciometro);
    int retardo = map(valorPot, 0, 1023, 1, 10);
    delay(retardo);
  sgte_paso2(); // mueve el motor
}
if(estado==2){
delay(10000000);
}


}