//Autor: Martin Chlebovec (martinius96)
//Projekt: Metronóm - UART only
//Revízia: 29. May 2020
//Donate for more: paypal.me/chlebovec

//Nastavenie vývodov Arduina k jednotlivým perifériám (Vstupy, výstupy)
const int BUZZER = 9;
const int LED_BLU = 8;
const int LED_RED = 7;
const int BUT_CHANGE_TICK = 6;
const int BUT_plusone = 5;
const int BUT_minusone = 4;
const int BUT_plusten = 3;
const int BUT_minusten = 2;

//Nastavenie počiatočných časových premenných s millis()
unsigned long lastDebounceTime1 = 0;
unsigned long lastDebounceTime2 = 0;
unsigned long lastDebounceTime3 = 0;
unsigned long lastDebounceTime4 = 0;
unsigned long lastDebounceTime5 = 0;
unsigned long debounceInterval = 50;
unsigned long elapsedInterval = 0;
unsigned long interval = 1000; //interval tikání v milisekundách

//Nastavenie počiatočných stavov tlačidiel
int buttonState1 = HIGH;
int buttonState2 = HIGH;
int buttonState3 = HIGH;
int buttonState4 = HIGH;
int buttonState5 = HIGH;

//Nastavenie posledných stavov tlačidiel
int lastButtonState1 = HIGH;
int lastButtonState2 = HIGH;
int lastButtonState3 = HIGH;
int lastButtonState4 = HIGH;
int lastButtonState5 = HIGH;

//Deklarácia hodnôt frekvencií pre doby + poslednú dobu, rytmus, atď...
const int freqFirst = 1700;
const int freqFourths = 1500;
int rythm = 4;
int freq = 0;
int bpm = 0;
int tick_case = 0;
int actual = 0;

//Defínicia funkcie pre výpis BPM
void showBPM()
{
  // bpm = 60000 / interval;
  Serial.print("BPM: ");
  Serial.println(bpm);
}

//Defínicia funkcie pre výpis rytmusu
void showRythm()
{
  Serial.print("Takt: ");
  Serial.print(rythm);
  Serial.println("/4");
}

//Defínicia funkcie s volaním funkcií pre výpis BPM, rytmusu
void aktualizaceDispleje()
{
  showBPM();
  showRythm();
}

void setup() {
  //počiatočné nastavenie výstupov a vstupov
  pinMode(LED_RED, OUTPUT);
  pinMode(LED_BLU, OUTPUT);
  pinMode(BUZZER, OUTPUT);
  pinMode(BUT_CHANGE_TICK, INPUT_PULLUP);
  pinMode(BUT_plusone, INPUT_PULLUP);
  pinMode(BUT_minusone, INPUT_PULLUP);
  pinMode(BUT_plusten, INPUT_PULLUP);
  pinMode(BUT_minusten, INPUT_PULLUP);
  Serial.begin(115200);
Serial.println("Hello Arduino\n");
}

void loop() {
  int reading1 = digitalRead(BUT_plusone);
  int reading2 = digitalRead(BUT_minusone);
  int reading3 = digitalRead(BUT_plusten);
  int reading4 = digitalRead(BUT_minusten);
  int reading5 = digitalRead(BUT_CHANGE_TICK);

  if (reading1 != lastButtonState1) {
    lastDebounceTime1 = millis();
  }

  if (reading2 != lastButtonState2) {
    lastDebounceTime2 = millis();
  }

  if (reading3 != lastButtonState3) {
    lastDebounceTime3 = millis();
  }

  if (reading4 != lastButtonState4) {
    lastDebounceTime4 = millis();
  }

  if (reading5 != lastButtonState5) {
    lastDebounceTime5 = millis();
  }

  if ((millis() - lastDebounceTime1) >= debounceInterval) {
    if (reading1 != buttonState1) {
      buttonState1 = reading1;
      if (buttonState1 == HIGH) {
        bpm = bpm + 1; //bmp + 1
        interval = 60000 / bpm;
        freq = freqFirst;
        aktualizaceDispleje();
        digitalWrite(LED_RED, LOW);
        digitalWrite(LED_BLU, HIGH);
        tone(BUZZER, freq);
        actual = 1;
        elapsedInterval = millis();
      }
    }
  }

  if ((millis() - lastDebounceTime2) >= debounceInterval) {
    if (reading2 != buttonState2) {
      buttonState2 = reading2;
      if (buttonState2 == HIGH) {
        bpm = bpm - 1; //bmp - 1
        if (bpm < 0) {
          bpm = 0;
        }
        interval = 60000 / bpm;
        freq = freqFirst;
        aktualizaceDispleje();
        digitalWrite(LED_RED, LOW);
        digitalWrite(LED_BLU, HIGH);
        tone(BUZZER, freq);
        actual = 1;
        elapsedInterval = millis();
      }
    }
  }

  if ((millis() - lastDebounceTime3) >= debounceInterval) {
    if (reading3 != buttonState3) {
      buttonState3 = reading3;
      if (buttonState3 == HIGH) {
        bpm = bpm + 10; //bmp + 10
        interval = 60000 / bpm;
        freq = freqFirst;
        aktualizaceDispleje();
        digitalWrite(LED_RED, LOW);
        digitalWrite(LED_BLU, HIGH);
        tone(BUZZER, freq);
        actual = 1;
        elapsedInterval = millis();
      }
    }
  }

  if ((millis() - lastDebounceTime4) >= debounceInterval) {
    if (reading4 != buttonState4) {
      buttonState4 = reading4;
      if (buttonState4 == HIGH) {
        bpm = bpm - 10; //bmp - 10
        if (bpm < 0) {
          bpm = 0;
        }
        interval = 60000 / bpm;
        freq = freqFirst;
        aktualizaceDispleje();
        digitalWrite(LED_RED, LOW);
        digitalWrite(LED_BLU, HIGH);
        tone(BUZZER, freq);
        actual = 1;
        elapsedInterval = millis();
      }
    }
  }

  if ((millis() - lastDebounceTime5) >= debounceInterval) {
    if (reading5 != buttonState5) {
      buttonState5 = reading5;
      if (buttonState5 == HIGH) {
        tick_case++;
        switch (tick_case) {
          case 0:
            rythm = 4; // 4/4 takt
            break;
          case 1:
            rythm = 5; // 5/4 takt
            break;
          case 2:
            rythm = 3; // 3/4 takt
            break;
          default:
            tick_case = 0;
            rythm = 4;
            break;
        }
        aktualizaceDispleje();
      }
    }
  }

  if (freq != 0 && bpm != 0) {
    if ((millis() - elapsedInterval) >= debounceInterval) { //50ms beep
      digitalWrite(LED_RED, LOW);
      digitalWrite(LED_BLU, LOW);
      noTone(BUZZER);
    }
    if ((millis() - elapsedInterval) >= interval) {
      actual++;
      if (actual > rythm) {
        actual = 1;
      }
      if (actual < rythm) {
        freq = freqFirst;
        digitalWrite(LED_RED, LOW);
        digitalWrite(LED_BLU, HIGH);
      }
      if (actual == rythm) {
        freq = freqFourths;
        digitalWrite(LED_RED, HIGH);
        digitalWrite(LED_BLU, LOW);
      }
      tone(BUZZER, freq);
      elapsedInterval = millis();
    }
  }

  lastButtonState1 = reading1;
  lastButtonState2 = reading2;
  lastButtonState3 = reading3;
  lastButtonState4 = reading4;
  lastButtonState5 = reading5;
}
nano:12
nano:11
nano:10
nano:9
nano:8
nano:7
nano:6
nano:5
nano:4
nano:3
nano:2
nano:GND.2
nano:RESET.2
nano:0
nano:1
nano:13
nano:3.3V
nano:AREF
nano:A0
nano:A1
nano:A2
nano:A3
nano:A4
nano:A5
nano:A6
nano:A7
nano:5V
nano:RESET
nano:GND.1
nano:VIN
nano:12.2
nano:5V.2
nano:13.2
nano:11.2
nano:RESET.3
nano:GND.3
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
btn3:1.l
btn3:2.l
btn3:1.r
btn3:2.r
btn4:1.l
btn4:2.l
btn4:1.r
btn4:2.r
btn5:1.l
btn5:2.l
btn5:1.r
btn5:2.r
led1:A
led1:C
led2:A
led2:C
bz1:1
bz1:2