////////////////////////////////* Ejercicio PR3 - frecuencimetro  */////////////////////////////////////////////
#include <Arduino.h>
#define TIMER0 0

const int senyal_output = 23;
const int senyal_entrada = 18;
const int sube = 32; //PULSADOR VERDE
const int baja = 33; //PULSADOR ROJO
const int empieza = 35; //PULSADOR AZUL

float frec_senyal = 5.8;
float periodo_senyal_ms = 1000 * (1 / frec_senyal);

//variables globales (se utilizan en la interrupción y en el loop)
volatile int t_parpadeo;
volatile int nveces_ISR = 0;
volatile int nflancos = 0;

hw_timer_t *timer = NULL;

void IRAM_ATTR ISR_senyal()
{
  nflancos++;
}

void IRAM_ATTR ISR_sube()
{
  if (t_parpadeo >= 1000)
    t_parpadeo = 500;
  else
    t_parpadeo += 25;

  nveces_ISR++;
}

void IRAM_ATTR ISR_baja()
{
  if (t_parpadeo >= 1000)
    t_parpadeo = 500;
  else
    t_parpadeo += 25;

  nveces_ISR++;
}

void IRAM_ATTR onTimer()
{
  nflancos = 0;
}

void setup()
{
  pinMode(senyal_output, OUTPUT);
  pinMode(sube, INPUT_PULLUP);
  pinMode(baja, INPUT_PULLUP);
  pinMode(empieza, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(senyal_entrada), ISR_senyal, FALLING);
  attachInterrupt(digitalPinToInterrupt(sube), ISR_sube, FALLING);
  attachInterrupt(digitalPinToInterrupt(baja), ISR_baja, FALLING);

  timer = timerBegin(0, 300, true); // Timer 0, prescaler 300 (200 + 10*puesto de laboratorio), contar en microsegundos
  timerAttachInterrupt(timer, &onTimer, true);
  timerAlarmWrite(timer, 1000000, true); // 1 Hz (configuración de cuando tiene que sonar la alarma)
  timerAlarmEnable(timer); // El timer está habilitado (salta la interrupción)
  
  Serial.begin(115200);
}

unsigned long tp1 = 0;
unsigned long current_time;

void loop()
{
  delay(1);
  current_time = millis();
  float valor_frec = nflancos / 10.0;

  if (Serial.available()>0) {  // 
  frec_senyal = Serial.read(); // leer el byte actual
  }
  if (current_time - tp1 > periodo_senyal_ms / 2)
  {
    digitalWrite(senyal_output, !digitalRead(senyal_output));
    tp1 = millis();
  }

  if (current_time - tp1 > 10000)
  {
    Serial.printf("Frec: %4.2f Hz - nflancos: %d  \n", valor_frec, nflancos);
    tp1 = millis();
  }

  if (digitalRead(sube) == LOW)
  {
    if (t_parpadeo >= 1000)
      t_parpadeo = 500;
    else
      t_parpadeo += 25;

    nveces_ISR++;
  }

  if (digitalRead(baja) == LOW)
  {
    if (t_parpadeo >= 1000)
      t_parpadeo = 500;
    else
      t_parpadeo += 25;

    nveces_ISR++;
  }

  timerWrite(timer, 0); // Reiniciar el contador del timer

return;// fin iteracion loop
}
//Este código utiliza el Timer 0 con un prescaler de 300 para contar microsegundos 
//y genera una interrupción cada segundo (timerAlarmWrite(timer, 1000000, true); // 1 Hz). 
//La función onTimer() se llama cada segundo y reinicia el contador nflancos. 
//Además, los botones sube y baja ahora ajustan el tiempo de parpadeo directamente. 
//Recuerda conectar los botones a pines digitales y adaptar el código según la configuración de tu hardware.