#include <Wire.h>               //komunikace po I2C
#include <Stepper.h>            //krokove motory
#include <SPI.h>                //komunikace po SPI
#include <SD.h>                 //ctecka SD karet
#include <LiquidCrystal.h>      //LCD
#define DS3231_I2C_ADDRESS 0x68 //nastaveni adresy casoveho modulu
#define CS_PIN 2                //nastaveni datoveho pinu ctecky

int xPin = A0;      //osa x joysticku
int yPin = A1;      //osa y joysticku
int hpPin = A2;     //fotorezistor HP
int hlPin = A3;     //fotorezistor HL
int dlPin = A4;     //fotorezistor DL
int dpPin = A5;     //fotorezistor DP
int pinCas = 23;    //prepinac rezimu v poloze casovace
int pinMan = 25;    //prepinac rezimu v poloze manualni
int pinKal = 27;    //spinac kalibrace
int PinX0 = 3;      //piny motoru nataceni (osa x)
int PinX1 = 4;
int PinX2 = 5;
int PinX3 = 6;
int PinY0 = 7;      //piny motoru naklonu (osa y)
int PinY1 = 8;
int PinY2 = 9;
int PinY3 = 10;
int trimr_u = A6;   //trimr tolerance uhlu
int trimr_f = A7;   //trimr tolerance fotorezistoru

const byte zaznamu = 200;         //zaznamy na karte pro jeden den
float necitlivost_f = 0.08 * 256; //tolerance fotorezistoru
float necitlivost_u = 5;          //tolerance uhlu

//nastaveni pinu pro displej
LiquidCrystal lcd(39, 41, 43, 45, 47, 49);

//nastaveni motoru
Stepper motorX(200, PinX0, PinX2, PinX1, PinX3);
Stepper motorY(200, PinY0, PinY2, PinY1, PinY3);

float akc_naklon = 0;   //naklon dle akcelerometru
float azimut = 0;       //skutecny azimut
float zenit = 0;        //skutecny zenit
float azimut_n = 0;     //pozadovany azimut
float zenit_n = 0;      //pozadovany zenit
int xPozice = 0;        //vychylka joysticku v ose x
int yPozice = 0;        //vychylka joysticku v ose y
byte rezim = 1;   //rezim: 1 = automaticky, 2 = casovac, 3 = manualni
int hp = 0;             //hodnota fotorezistoru HP
int hl = 0;             //hodnota fotorezistoru HL
int dp = 0;             //hodnota fotorezistoru DP
int dl = 0;             //hodnota fotorezistoru DL
int nahore = 0;         //osvetleni horni casti
int dole = 0;           //osvetleni dolni casti
int vlevo = 0;          //osvetleni leve casti
int vpravo = 0;         //osvetleni prave casti
int rozdilX = 0;        //rozdil osvetleni v ose x
int rozdilY = 0;        //rozdil osvetleni v ose y
int i = 0;              //pomocna promenna
int j = -1;             //pomocna promenna

void setup() {
  Wire.begin();           //komunikace po I2C
  Serial.begin(115200);   //komunikace po seriove lince
  
  //nehraje roli, ale musi byt zavolano
  motorX.setSpeed(30);
  motorY.setSpeed(30);
  
  //nastaveni rezimu pinu
  pinMode(xPin, INPUT);
  pinMode(yPin, INPUT);
  pinMode(pinCas, INPUT_PULLUP);
  pinMode(pinMan, INPUT_PULLUP);
  pinMode(hpPin, INPUT);
  pinMode(hlPin, INPUT);
  pinMode(dpPin, INPUT);
  pinMode(dlPin, INPUT);
  pinMode(trimr_u, INPUT);
  pinMode(trimr_f, INPUT);

  //nastaveni pracovniho rezimu
  if (digitalRead(pinCas) == LOW){
    rezim = 2;
    Serial.println("Rezim casovace");     //vypis na seriovou linku
  }else if (digitalRead(pinMan) == LOW){
    rezim = 3;
    Serial.println("Manualni rezim");
  }else{
    rezim = 1;
    Serial.println("Automaticky rezim");
  }

  //nastaveni casu (seconds, minutes, hours, day, date, month, year)
  //setDS3231time(0,37,16,4,26,04,17);

  Serial.println("Nastaveni displeje");
  lcd.begin(16, 2);

  i = 0;                          //reset pomocne promenne
  if (rezim == 3){          //manualni rezim
    lcd.clear();
    lcd.setCursor(4,0);
    lcd.print("MANUALNI");
    lcd.setCursor(5,1);
    lcd.print("REZIM!");
  }
}

void loop() {  
  //cteni hodnot z joysticku
  xPozice = analogRead(xPin);
  yPozice = 1023 - analogRead(yPin);

  //ziskani hodnot z fotorezistoru a vypocet prumernych hodnot
  hp = analogRead(hpPin);
  hl = analogRead(hlPin);
  dl = analogRead(dlPin);
  dp = analogRead(dpPin);
  nahore = (hp + hl) / 2;
  dole = (dp + dl) / 2;
  vlevo = (dl + hl) / 2;
  vpravo = (hp + dp) / 2;
  rozdilX = vlevo - vpravo;
  rozdilY = nahore - dole;
  
  //nacteni hodnot trimru
  necitlivost_f = map(analogRead(trimr_f), 0, 1023, 1, 256);
  necitlivost_u = map(analogRead(trimr_u), 0, 1023, 1, 360);

  switch(rezim){
    case 1: //automaticky
      if (i >= 300){      //aktualizace displeje kazdou tristou iteraci
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(hl);        //udaje z hornich fotorezistoru
        lcd.print("/");
        lcd.print(hp);
        lcd.setCursor(9,0);
        lcd.print("(~");
        lcd.print(necitlivost_f, 0);  //aktualni nastaveni tolerance
        lcd.print(")");
        lcd.setCursor(0,1);
        lcd.print(dl);        //udaje ze spodnich fotorezistoru
        lcd.print("/");
        lcd.print(dp);
        lcd.setCursor(9,1);
        lcd.print("(~");
        lcd.print(necitlivost_f, 0);  //opet tolerance
        lcd.print(")");
        i = 0;                        //restart pocitadla iteraci
      }
      if (rozdilX > necitlivost_f){   //kontrola proti toleranci
        motorX.step(-1);              //otoceni motoru
        delay(1);
      }else if (rozdilX < -necitlivost_f){
        motorX.step(1);              //opacny smer
        delay(1);
      }
      if (rozdilY > necitlivost_f){
        motorY.step(-1);
        delay(1);
      }else if (rozdilY < -necitlivost_f){
        motorY.step(1);
        delay(1);
      }
    break;
    case 2: //casovac
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("REZIM");
      lcd.setCursor(0,1);
      lcd.print("NEPODPOROVAN!");
    break;
    case 3: //manualni
      if (xPozice < 300){         //kontrola vychylky joysticku
        motorX.step(-1);
        delay(1);
      }else if (xPozice > 700){
        motorX.step(1);
        delay(1);
      }
      if (yPozice < 300){
        motorY.step(1);
        delay(1);
      }else if (yPozice > 700){
        motorY.step(-1);
        delay(1);
      }
    break;
  }
  i++;                            //pripocitani iterace
}
