// Definice konstant pro tři sedmisegmentové displeje
const int bcdPins[] = {5, 4, 3, 2}; // Piny pro BCD vstupy (společné pro všechny čipy)
const int latchPin1 = 6;            // Latch pin pro první CD4511 (jednotky odpočtu)
const int latchPin2 = 7;            // Latch pin pro druhý CD4511 (desítky odpočtu)
const int latchPin3 = 8;            // Latch pin pro třetí CD4511 (počet nízkých hodnot)

// Definice konstant pro čtení a vyhodnocení vstupů
const int analogPins[] = {A0, A1, A2, A3, A4}; // Analogové vstupy
const int modePin = A5;                        // Pin pro výběr režimu
const int digitalPins[] = {9, 10, 11, 12, 13}; // Digitální výstupy
const float threshold = 1.45;                  // Prahová hodnota ve voltech
const float modeThreshold = 2.5;               // Prahová hodnota pro volbu režimu

// Proměnné pro BIATHLON režim
bool digitalOutputStates[5] = {false, false, false, false, false}; // Stav digitálních výstupů
int biathlonCount = 0; // Počet výstupů ve stavu HIGH

// Proměnné pro PETIBOJ režim
int petibojCount = 0; // Počet změn pod threshold na A2
int secondsElapsed = 0; // Čas od 0 do 50 sekund

// Proměnné pro časovač
unsigned long previousMillis = 0;
const unsigned long interval = 1000; // Interval 1 sekundy

// Proměnná pro aktuální režim
bool isPetibojMode = true; // Výchozí režim (PETIBOJ)
bool displayedModeInfo = false; // Indikátor, zda byla zobrazena informace o režimu

void setup() {
  // Nastavení pinů pro BCD vstupy CD4511 jako výstupy
  for (int i = 0; i < 4; i++) {
    pinMode(bcdPins[i], OUTPUT);
  }
  
  // Nastavení pinů pro LATCH vstupy všech CD4511 jako výstupy
  pinMode(latchPin1, OUTPUT);
  pinMode(latchPin2, OUTPUT);
  pinMode(latchPin3, OUTPUT);
  
  // Inicializace LATCH pinů do hodnoty HIGH
  digitalWrite(latchPin1, HIGH);
  digitalWrite(latchPin2, HIGH);
  digitalWrite(latchPin3, HIGH);

  // Nastavení digitálních výstupů jako výstupy
  for (int i = 0; i < 5; i++) {
    pinMode(digitalPins[i], OUTPUT);
    digitalWrite(digitalPins[i], LOW);
  }

  Serial.begin(9600); // Pro ladění
}

void loop() {
  float modeVoltage = analogRead(modePin) * (5.0 / 1023.0); // Čtení napětí na pinu A5

  // Rozlišení režimů na základě prahového napětí
  bool currentModeIsPetiboj = (modeVoltage < modeThreshold);

  // Pokud došlo ke změně režimu, zobrazit informaci o režimu
  if (currentModeIsPetiboj != isPetibojMode || !displayedModeInfo) {
    isPetibojMode = currentModeIsPetiboj;
    displayModeInfo(isPetibojMode); // Zobrazení informace o zvoleném režimu
    displayedModeInfo = true;       // Nastavení indikátoru, že již byla informace zobrazena
  }

  // Spuštění příslušného režimu
  if (isPetibojMode) {
    petibojMode();
  } else {
    biathlonMode();
  }
}

// Funkce pro zobrazení informace o zvoleném režimu
void displayModeInfo(bool isPetibojMode) {
  unsigned long startMillis = millis();
  bool displayOn = false;

  while (millis() - startMillis < 10000) { // Po dobu 10 sekund
    unsigned long currentMillis = millis();

    if (currentMillis - previousMillis >= 500) { // Střídání stavu každých 0,5 s
      previousMillis = currentMillis;
      displayOn = !displayOn;

      if (displayOn) {
        if (isPetibojMode) {
          // PETIBOJ: 5 na třetím displeji, 80 na displejích času
          displayNumber(5, latchPin3);
          displayNumber(0, latchPin1); // Jednotky času
          displayNumber(8, latchPin2); // Desítky času
        } else {
          // BIATHLON: 8 na třetím displeji, 10 na displejích času
          displayNumber(8, latchPin3);
          displayNumber(0, latchPin1); // Jednotky času
          displayNumber(1, latchPin2); // Desítky času
        }
      } else {
        // Zhasnutí displejů
        displayNumber(15, latchPin1);
        displayNumber(15, latchPin2);
        displayNumber(15, latchPin3);
      }
    }
  }
}

// Funkce pro režim PETIBOJ
void petibojMode() {
  static bool belowThreshold = false;

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval && secondsElapsed < 50 && petibojCount < 5) {
    previousMillis = currentMillis;
    secondsElapsed++;
    int analogValue = analogRead(A2);
    float voltage = analogValue * (5.0 / 1023.0);

    if (voltage < threshold) {
      belowThreshold = true;
    } else if (belowThreshold) {
      belowThreshold = false;
      petibojCount++;
    }

    int tens = secondsElapsed / 10;
    int ones = secondsElapsed % 10;

    // Aktualizace displejů pro čas
    displayNumber(ones, latchPin1);
    displayNumber(tens, latchPin2);
  }

  if (secondsElapsed >= 50 || petibojCount >= 5) {
    // Zachování posledního času a ukončení počítání
    int tens = secondsElapsed / 10;
    int ones = secondsElapsed % 10;
    displayNumber(ones, latchPin1);
    displayNumber(tens, latchPin2);
  }

  // Zobrazení počtu změn na třetím displeji
  displayNumber(petibojCount, latchPin3);
}

// Funkce pro režim BIATHLON
void biathlonMode() {
  int highCount = 0;

  for (int i = 0; i < 5; i++) {
    static bool belowThreshold[5] = {false, false, false, false, false};
    int analogValue = analogRead(analogPins[i]);
    float voltage = analogValue * (5.0 / 1023.0);

    if (voltage < threshold) {
      belowThreshold[i] = true;
    } else if (belowThreshold[i]) {
      belowThreshold[i] = false;
      digitalOutputStates[i] = true;
      digitalWrite(digitalPins[i], HIGH);
    }

    if (digitalOutputStates[i]) {
      highCount++;
    }
  }

  // Vypnutí displejů pro čas
  displayNumber(15, latchPin1);
  displayNumber(15, latchPin2);

  // Zobrazení počtu aktivních výstupů na třetím displeji
  displayNumber(highCount, latchPin3);
}

// Funkce pro zobrazení čísla na daném displeji
void displayNumber(int number, int latchPin) {
  // Nastavení BCD hodnot na vstupy
  for (int i = 0; i < 4; i++) {
    digitalWrite(bcdPins[i], (number >> i) & 0x01);
  }

  // Aktivace latch pinu pro aktualizaci displeje
  digitalWrite(latchPin, LOW);
  delayMicroseconds(1); // Krátký impuls
  digitalWrite(latchPin, HIGH);
}
cd4511-1Breakout
cd4511-2Breakout
cd4511-3Breakout