/***********************************************************************
 * Napěťový komparátor V1.1                     * 27.1.2024 * RoMaSoft *
 ***********************************************************************/

// ------------------ Defilice vstupů a výstupů ------------------------
#define A_Out 1                       //definice výstupu A - pin 6
#define B_Out 3                       //definice výstupu B - pin 2
#define C_Out 4                       //definice výstupu C - pin 3
#define D_Out 5                       //definice výstupu D - pin 1 (pozor je i RESETem)
#define Vstup A1                      //napěťový vstup - pin 7


// ------------------ Konstanty pro nastavení parametrů ----------------
const float Napajeni = 5.0;           //napájecí napětí (pro výpočet)

const float A_SP1 = 3.0;              //komparační úroveň pro sepnutí SP1 A_Out
const int A_Scas1 = 5;                //čas pro sepnutí od SP1 v sekundách (1..32767s)
const float A_SP2 = 4.0;              //komparační úroveň pro sepnutí SP2 A_Out
const int A_Scas2 = 1;                //čas pro sepnutí od SP2 v sekundách (1..32767s)
const float A_RP1 = 2.0;              //komparační úroveň pro rozepnutí RP1 A_Out
const int A_Rcas1 = 5;                //čas pro rozepnutí od RP1 v sekundách (1..32767s)
const float A_RP2 = 1.0;              //komparační úroveň pro rozepnutí RP2 A_Out
const int A_Rcas2 = 1;                //čas pro rozepnutí RP2 v sekundách (1..32767s)
const bool A_Typ = true;              //typ výstupu (true=sepne výstup, false=rozepne výstup)

const float B_SP1 = 3.0;              //komparační úroveň pro sepnutí SP1 B_Out
const int B_Scas1 = 5;                //čas pro sepnutí od SP1 v sekundách (1..32767s)
const float B_SP2 = 4.0;              //komparační úroveň pro sepnutí SP2 B_Out
const int B_Scas2 = 1;                //čas pro sepnutí od SP2 v sekundách (1..32767s)
const float B_RP1 = 2.0;              //komparační úroveň pro rozepnutí RP1 B_Out
const int B_Rcas1 = 5;                //čas pro rozepnutí od RP1 v sekundách (1..32767s)
const float B_RP2 = 1.0;              //komparační úroveň pro rozepnutí RP2 B_Out
const int B_Rcas2 = 1;                //čas pro rozepnutí RP2 v sekundách (1..32767s)
const bool B_Typ = true;              //typ výstupu (true=sepne výstup, false=rozepne výstup)

const float C_SP1 = 3.0;              //komparační úroveň pro sepnutí SP1 C_Out
const int C_Scas1 = 5;                //čas pro sepnutí od SP1 v sekundách (1..32767s)
const float C_SP2 = 4.0;              //komparační úroveň pro sepnutí SP2 C_Out
const int C_Scas2 = 1;                //čas pro sepnutí od SP2 v sekundách (1..32767s)
const float C_RP1 = 2.0;              //komparační úroveň pro rozepnutí RP1 C_Out
const int C_Rcas1 = 5;                //čas pro rozepnutí od RP1 v sekundách (1..32767s)
const float C_RP2 = 1.0;              //komparační úroveň pro rozepnutí RP2 C_Out
const int C_Rcas2 = 1;                //čas pro rozepnutí RP2 v sekundách (1..32767s)
const bool C_Typ = true;              //typ výstupu (true=sepne výstup, false=rozepne výstup)

const float D_SP1 = 3.0;              //komparační úroveň pro sepnutí SP1 D_Out
const int D_Scas1 = 5;                //čas pro sepnutí od SP1 v sekundách (1..32767s)
const float D_SP2 = 4.0;              //komparační úroveň pro sepnutí SP2 D_Out
const int D_Scas2 = 1;                //čas pro sepnutí od SP2 v sekundách (1..32767s)
const float D_RP1 = 2.0;              //komparační úroveň pro rozepnutí RP1 D_Out
const int D_Rcas1 = 5;                //čas pro rozepnutí od RP1 v sekundách (1..32767s)
const float D_RP2 = 1.0;              //komparační úroveň pro rozepnutí RP2 D_Out
const int D_Rcas2 = 1;                //čas pro rozepnutí RP2 v sekundách (1..32767s)
const bool D_Typ = true;              //typ výstupu (true=sepne výstup, false=rozepne výstup)


// ------------------ Definice proměných -------------------------------
double HlavniCasovac;                 //hlavní časovač pro generování 1s pulzů
int AktCas;
int Hodnota;                          //hodnota z A/D převodníku
float Napeti;                         //napětí vypočtené z hodnoty
int Cas1_A;                           //časovač 1 pro výstup A_Out
int Cas2_A;                           //časovač 2 pro výstup A_Out
byte Stav_A = 4;                      //stav výstupu A
int Cas1_B;                           //časovač 1 pro výstup B_Out
int Cas2_B;                           //časovač 2 pro výstup B_Out
byte Stav_B = 4;                      //stav výstupu B
int Cas1_C;                           //časovač 1 pro výstup C_Out
int Cas2_C;                           //časovač 2 pro výstup C_Out
byte Stav_C = 4;                      //stav výstupu C
int Cas1_D;                           //časovač 1 pro výstup D_Out
int Cas2_D;                           //časovač 2 pro výstup D_Out
byte Stav_D = 4;                      //stav výstupu D


// ================== Nastavení ========================================
void setup() {
  pinMode(A_Out, OUTPUT);             //Out1 je zvolen jako výstup
  pinMode(B_Out, OUTPUT);             //Out2 je zvolen jako výstup 
  pinMode(C_Out, OUTPUT);             //Out3 je zvolen jako výstup 
  pinMode(D_Out, OUTPUT);             //Out4 je zvolen jako výstup 
}


// ================== Hlavní smyčka ====================================
void loop() {
  Casovani();                         //obsluha všech časovačů
  NactiHodnotu();                     //načte hodnotu z A/D převodníku
  PrevedNaNapeti();                   //převede hodnotu na napětí
  NastavOut_A();                      //obsluha výstupu A_Out
  NastavOut_B();                      //obsluha výstupu B_Out
  NastavOut_C();                      //obsluha výstupu C_Out
  NastavOut_D();                      //obsluha výstupu D_Out
}


// ------------------ Obsluha všech časovačů ---------------------------
void Casovani() {
  //provede se každou 1 sekundu
  if (millis() >= HlavniCasovac) {
    HlavniCasovac = millis() + 1000;  //nastavení časovače + 1s 

    //inkrementace časovačů a omezení přetečení na 32400s (9h)
    Cas1_A = Cas1_A + 1;
    if (Cas1_A > 32400) {Cas1_A = 32400;}
    Cas2_A = Cas2_A + 1;
    if (Cas1_A > 32400) {Cas1_A = 32400;}

    Cas1_B = Cas1_B + 1;
    if (Cas1_B > 32400) {Cas1_B = 32400;}
    Cas2_B = Cas2_B + 1;
    if (Cas1_B > 32400) {Cas1_B = 32400;}

    Cas1_C = Cas1_C + 1;
    if (Cas1_C > 32400) {Cas1_C = 32400;}
    Cas2_C = Cas2_C + 1;
    if (Cas1_C > 32400) {Cas1_C = 32400;}

    Cas1_D = Cas1_D + 1;
    if (Cas1_D > 32400) {Cas1_D = 32400;}
    Cas2_D = Cas2_D + 1;
    if (Cas1_D > 32400) {Cas1_D = 32400;}
  }
}


// ------------------ Načtení hodnoty z A/D převodníku -----------------
void NactiHodnotu() {
  Hodnota = analogRead(Vstup);        //načte hodnotu z A/D převodníku
}


// ------------------ Převod hodnoty na napětí -------------------------
void PrevedNaNapeti() {
  Napeti = (Napajeni / 1024) * Hodnota;    //vypočte skutečné napětí
}


// ------------------ Obsluha komparátoru 1 ----------------------------
void NastavOut_A() {
  //klidový stav
  if (Napeti <= A_SP1 and Napeti >= A_RP1) {
    Stav_A = 4;
    Cas1_A = 0;
    Cas2_A = 0;  
  }

  //překročení SP1
  if (Napeti > A_SP1) {

    //start časování od překročení SP1
    if (Stav_A <=4) {
      Stav_A = 5;
      Cas1_A = 0;
    }

    //odčasováno SP1
    if (Stav_A >=5 and Cas1_A > A_Scas1) {
      Stav_A = 6;
    }

    
  }


  //podkročení RP1
  if (Napeti < A_RP1) {
    
    //start časování od podkročení RP1
    if (Stav_A >=4) {
      Stav_A = 3;
      Cas1_A = 0;
    }

    //odčasováno RP1
    if (Stav_A <=3 and Cas1_A > A_Scas1) {
      Stav_A = 2;
    }
  }

  if (Stav_A == 6 or Stav_A == 8) {digitalWrite(A_Out, A_Typ);}
  if (Stav_A == 2 or Stav_A == 0) {digitalWrite(A_Out, !A_Typ);}

  /*
  if (Stav_A == 4 and Napeti > A_SP1) {
    Stav_A = 5;
    Cas1_A = 0;
  }

  if (Stav_A == 5 and Napeti > A_SP1 and Cas1_A > A_Scas1) {
    Stav_A = 6;
  }
  
  if (Stav_A >= 4 and Stav_A <= 6 and Napeti > A_SP2) {
    Stav_A = 7;
    Cas2_A = 0;
  }

  if (Stav_A == 7 and Napeti > A_SP2 and Cas2_A > A_Scas2) {
    Stav_A = 8;
  }
  
  
  */
}


// ------------------ Obsluha komparátoru B ----------------------------
void NastavOut_B() {

}


// ------------------ Obsluha komparátoru C ----------------------------
void NastavOut_C() {

}


// ------------------ Obsluha komparátoru D ----------------------------
void NastavOut_D() {

}
ATTINY8520PU