#include <TM1637TinyDisplay.h>
#include <Preferences.h>

#define CLK 18
#define DIO 19
#define SENSOR_START 2
#define SENSOR_STOP 0
#define BOTAO_PRETO 5
#define BOTAO_VERDE 15
#define STEP_PIN 12
#define ENABLE_PIN 27
#define PIN_SIRENE 25

TM1637TinyDisplay display(CLK, DIO);
Preferences prefs;

unsigned int contador = 0;
unsigned long tempoInicio = 0;
bool motorAtivo = false;
bool esperandoStop = false;
bool jaContou = false;

bool ultimoEstadoStart = HIGH;
bool ultimoEstadoStop = HIGH;

bool alarmeAtivo = false;
enum MotivoAlarme { NENHUM, ERRO_SELO };
MotivoAlarme motivoAlarme = NENHUM;

// Modo F
bool modoF = false;
int funcaoAtual = 1;
unsigned long tempoUltimaInteracao = 0;
bool ajustandoValor = false;

// Valores configuráveis
unsigned int tempoExtraParada = 0;   // F01
unsigned int velocidadeMotor = 5000; // F02

void salvarConfiguracoes() {
  prefs.putUInt("tempoExtra", tempoExtraParada);
  prefs.putUInt("velocidade", velocidadeMotor);
}

void carregarConfiguracoes() {
  tempoExtraParada = prefs.getUInt("tempoExtra", 0);
  velocidadeMotor = prefs.getUInt("velocidade", 5000);
}

void exibirFuncao() {
  char buf[5];
  snprintf(buf, sizeof(buf), "F%d", funcaoAtual);
  display.showString(buf);
}

void exibirValor(unsigned int valor) {
  display.showNumberDec(valor, false);
}

void setup() {
  pinMode(SENSOR_START, INPUT_PULLUP);
  pinMode(SENSOR_STOP, INPUT_PULLUP);
  pinMode(BOTAO_PRETO, INPUT_PULLUP);
  pinMode(BOTAO_VERDE, INPUT_PULLUP);

  pinMode(STEP_PIN, OUTPUT);
  pinMode(ENABLE_PIN, OUTPUT);
  digitalWrite(ENABLE_PIN, HIGH);

  pinMode(PIN_SIRENE, OUTPUT);
  digitalWrite(PIN_SIRENE, LOW);

  display.setBrightness(7);
  prefs.begin("cnt", false);
  contador = prefs.getUInt("valor", 0);
  carregarConfiguracoes();
  display.showNumberDec(contador, true);
}

void loop() {
  static unsigned long tempoPressionadoPreto = 0;
  static unsigned long tempoPressionadoVerde = 0;
  static unsigned long ultimoTempoVerde = 0;
  static unsigned long ultimoTempoPreto = 0;

  static bool ultimoEstadoBotaoPreto = HIGH;
  static bool ultimoEstadoBotaoVerde = HIGH;

  // Zerar contador com botão verde pressionado por 7s
  if (digitalRead(BOTAO_VERDE) == LOW) {
    if (tempoPressionadoVerde == 0) tempoPressionadoVerde = millis();
    if ((millis() - tempoPressionadoVerde >= 7000)) {
      contador = 0;
      prefs.putUInt("valor", contador);
      display.showNumberDec(contador, true);
      delay(500);
      while (digitalRead(BOTAO_VERDE) == LOW) delay(10);
      tempoPressionadoVerde = 0;
    }
  } else {
    tempoPressionadoVerde = 0;
  }

  // Entrar no modo F com botão preto pressionado por 5s
  if (digitalRead(BOTAO_PRETO) == LOW) {
    if (tempoPressionadoPreto == 0) tempoPressionadoPreto = millis();
    if (!modoF && (millis() - tempoPressionadoPreto >= 5000)) {
      modoF = true;
      funcaoAtual = 1;
      ajustandoValor = false;
      tempoUltimaInteracao = millis();
      exibirFuncao();
    }
  } else {
    tempoPressionadoPreto = 0;
  }

  // -------------------- MODO F --------------------
  if (modoF) {
    if (ajustandoValor && (millis() - tempoUltimaInteracao > 4000)) {
      salvarConfiguracoes();
      ajustandoValor = false;
      exibirFuncao();
      tempoUltimaInteracao = millis();
    } else if (!ajustandoValor && (millis() - tempoUltimaInteracao > 4000)) {
      modoF = false;
      display.showNumberDec(contador, true);
      return;
    }

    // VERDE: Aumenta valor ou troca função
    bool estadoVerde = digitalRead(BOTAO_VERDE);
    if (estadoVerde == LOW && ultimoEstadoBotaoVerde == HIGH) {
      tempoUltimaInteracao = millis();
      if (!ajustandoValor) {
        funcaoAtual++;
        if (funcaoAtual > 2) funcaoAtual = 1;
        exibirFuncao();
      } else {
        if (funcaoAtual == 1 && tempoExtraParada < 3000) tempoExtraParada++;
        else if (funcaoAtual == 2 && velocidadeMotor < 10000) velocidadeMotor += 100;
        exibirValor(funcaoAtual == 1 ? tempoExtraParada : velocidadeMotor);
      }
      ultimoTempoVerde = millis();
    }
    ultimoEstadoBotaoVerde = estadoVerde;

    // PRETO: Diminui valor ou entra em ajuste
    bool estadoPreto = digitalRead(BOTAO_PRETO);
    if (estadoPreto == LOW && ultimoEstadoBotaoPreto == HIGH) {
      tempoUltimaInteracao = millis();
      if (!ajustandoValor) {
        ajustandoValor = true;
        exibirValor(funcaoAtual == 1 ? tempoExtraParada : velocidadeMotor);
      } else {
        if (funcaoAtual == 1 && tempoExtraParada > 0) tempoExtraParada--;
        else if (funcaoAtual == 2 && velocidadeMotor > 100) velocidadeMotor -= 100;
        exibirValor(funcaoAtual == 1 ? tempoExtraParada : velocidadeMotor);
      }
      ultimoTempoPreto = millis();
    }
    ultimoEstadoBotaoPreto = estadoPreto;

    // Repetição contínua para VERDE
    if (estadoVerde == LOW && ajustandoValor && (millis() - ultimoTempoVerde > 700)) {
      if (millis() % 100 < 10) {
        tempoUltimaInteracao = millis();
        if (funcaoAtual == 1 && tempoExtraParada < 3000) tempoExtraParada++;
        else if (funcaoAtual == 2 && velocidadeMotor < 10000) velocidadeMotor += 100;
        exibirValor(funcaoAtual == 1 ? tempoExtraParada : velocidadeMotor);
      }
    }

    // Repetição contínua para PRETO
    if (estadoPreto == LOW && ajustandoValor && (millis() - ultimoTempoPreto > 700)) {
      if (millis() % 100 < 10) {
        tempoUltimaInteracao = millis();
        if (funcaoAtual == 1 && tempoExtraParada > 0) tempoExtraParada--;
        else if (funcaoAtual == 2 && velocidadeMotor > 100) velocidadeMotor -= 100;
        exibirValor(funcaoAtual == 1 ? tempoExtraParada : velocidadeMotor);
      }
    }
    return;
  }

  // ------------------ FUNCIONAMENTO NORMAL ------------------
  bool estadoAtualStart = digitalRead(SENSOR_START);
  bool estadoAtualStop = digitalRead(SENSOR_STOP);

  if (alarmeAtivo && motivoAlarme == ERRO_SELO) {
    display.showString("SELO");
    digitalWrite(PIN_SIRENE, HIGH);
    if (digitalRead(BOTAO_VERDE) == LOW) {
      alarmeAtivo = false;
      motivoAlarme = NENHUM;
      digitalWrite(PIN_SIRENE, LOW);
      display.showNumberDec(contador, true);
      delay(500);
    }
    return;
  }

  if (ultimoEstadoStart == HIGH && estadoAtualStart == LOW && !motorAtivo) {
    motorAtivo = true;
    esperandoStop = true;
    jaContou = false;
    tempoInicio = millis();
    digitalWrite(ENABLE_PIN, LOW);
  }

  if (motorAtivo) {
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(velocidadeMotor);
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(velocidadeMotor);

    if (ultimoEstadoStop == HIGH && estadoAtualStop == LOW && esperandoStop && !jaContou) {
      delay(tempoExtraParada);
      contador = (contador + 1) % 10000;
      prefs.putUInt("valor", contador);
      if (!alarmeAtivo) display.showNumberDec(contador, true);
      jaContou = true;
      esperandoStop = false;
      motorAtivo = false;
      digitalWrite(ENABLE_PIN, HIGH);
    }

    if (millis() - tempoInicio >= 2000 && esperandoStop && !jaContou) {
      esperandoStop = false;
      jaContou = true;
      motorAtivo = false;
      digitalWrite(ENABLE_PIN, HIGH);
      alarmeAtivo = true;
      motivoAlarme = ERRO_SELO;
    }
  }

  ultimoEstadoStart = estadoAtualStart;
  ultimoEstadoStop = estadoAtualStop;
}
4-Digit Display
A4988
NOCOMNCVCCGNDINLED1PWRRelay Module