int clockPin = 12;
int dataPin = 11;
int latchPin = 8;
int buzzer = 9;

int setPin = 7;
int upPin = 6;
int downPin = 5;

// Digitos em binário
int binary [10] = {0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110,
                    0b01101101, 0b01111101, 0b00000111, 0b01111111, 0b01101111};

int state = 0; // 0 SET, 1 RUN, 2 ALARM
int minutes = 0;
int seconds = 30;

// Protótipo da função, p/ parâmetro padrão
#define WAIT 50
bool buttonPressed(int pin, int maxWait = WAIT);

void setup() {
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(setPin, INPUT_PULLUP);
  pinMode(upPin, INPUT_PULLUP);
  pinMode(downPin, INPUT_PULLUP);
}

void loop() {
  if (state == 0) {
    displayTimer();
    if (buttonPressed(setPin)) setTimer();
    if (buttonPressed(downPin, 200)) state = 1;
  }
  if (state == 1) {
    countDown();
  }
  if (state == 2) {
    blinkDisplay();
    buzz(1);
    if (buttonPressed(upPin, 200)) {
      seconds = 30;
      state = 0;
    }
  }
}

void setTimer() {
  buzz(1);
  while (!buttonPressed(setPin)) {
    if (buttonPressed(upPin)) minutes = (minutes + 1 == 10) ? 0 : minutes + 1;
    if (buttonPressed(downPin)) minutes = (minutes - 1 == -1) ? 9 : minutes - 1;
    displayTimer();
  }
  buzz(2);
  while (!buttonPressed(setPin)) {
    if (buttonPressed(upPin)) seconds = (seconds + 10 > 59) ? seconds % 10 : seconds + 10;
    if (buttonPressed(downPin)) seconds = (seconds - 10 < 0) ? seconds + 50 : seconds - 10;
    displayTimer();
  }
  buzz(3);
  while (!buttonPressed(setPin)) {
    if (buttonPressed(upPin)) seconds = ((seconds + 1) % 10 == 0) ? (seconds / 10) * 10 : seconds + 1;
    if (buttonPressed(downPin)) seconds = ((seconds - 1) % 10 == 9) ? (seconds / 10) * 10 + 9 : seconds - 1;
    displayTimer();
  }
  buzz(4);
}

void displayTimer() {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, binary[seconds % 10]);
  shiftOut(dataPin, clockPin, MSBFIRST, binary[seconds / 10]);
  shiftOut(dataPin, clockPin, MSBFIRST, binary[minutes]);
  digitalWrite(latchPin, HIGH);
}

void countDown() {
  displayTimer();
  delay(1000);
  if (seconds - 1 < 0) {
    if (minutes - 1 < 0) {
      state = 2;
    } else {
      seconds = 59;
      minutes--;
    }
  } else {
    seconds--;
  }
}

bool buttonPressed(int pin, int maxWait) {
  int count = 0;
  if (digitalRead(pin) == LOW) {
    while(digitalRead(pin) == LOW) {
      delay(10);
      count++;
      if (count > maxWait) return true;
    }
    if (maxWait == WAIT && count > 5) return true;
  }
  return false;
}

void blinkDisplay() {
  digitalWrite(latchPin, LOW);
  for (int i = 0; i < 3; i++) shiftOut(dataPin, clockPin, MSBFIRST, 0b00000000);
  digitalWrite(latchPin, HIGH);
  delay(400);
  displayTimer();
}

void buzz(int times) {
  for (int i = 0; i < times; i++) {
    digitalWrite(buzzer, HIGH);
    delay(100);
    digitalWrite(buzzer, LOW);
    delay(25);
  }
}
$abcdeabcde151015202530354045505560fghijfghij
$abcdeabcde151015202530354045505560fghijfghij
74HC595
74HC595
74HC595