#include <SPI.h>
#include <CleO.h>
#include <Wire.h>
#include <stdlib.h>
#include "DHT.h"

#define I2C_OUT_ADDR 64 >> 1    // I2C-Addresse als 7 Bit
#define I2C_IN_ADDR  112 >> 1   // I2C-INPUT-Addresse als 7 Bit
#define I2C_433MHz_ADDR  16 >> 1     // I2C-433MHz-Addresse als 7 Bit
#define DHTTYPE DHT22         // DHT 22  (AM2302), AM2321
#define DHTPIN 2              // what digital pin we're connected to

byte VAL=0;
int globalCurrSite = 4, del=150;
bool penDownOnBack = false;
int16_t previousDur = 0, previousTag = 0;
DHT dht(DHTPIN, DHTTYPE);     //DHT fr Temperatursensor

//Digital Output
bool penDownOn1 = false, penDownOn2 = false, penDownOn3 = false, penDownOn4 = false, penDownOn5 = false, penDownOn6 = false, penDownOn7 = false, penDownOn8 = false;
bool but1Dwn = false, but2Dwn = false, but3Dwn = false, but4Dwn = false, but5Dwn = false, but6Dwn = false, but7Dwn = false, but8Dwn = false;

//Digital Input
char anzeige[15]="";

//Startseite
bool penDownOn20 = false, penDownOn21 = false, penDownOn22 = false, penDownOn23 = false;
bool butADwn=false, butBDwn=false;

//Terrarium
char tempNow[15]="";
char humNow[15]="";

//Funkmodul
bool penDownOn30=false, penDownOn31=false, penDownOn32=false, penDownOn33=false;
int32_t aOnButCol = BLUE, aOffButCol=GREY, bOnButCol = BLUE, bOffButCol=GREY ,aBackCol=LIGHTGREY,bBackCol = LIGHTGREY;

void setup() 
{
  Serial.begin(9600);       //Serielle Schnittstelle konfigurieren
  CleO.begin();           //CleO initialisieren
  Wire.begin();           //Wire initialisieren
  dht.begin();            //dht initialisieren
  setSystemcode();      //Systemcode bertragen
}
void setSystemcode()
{
  Wire.beginTransmission(I2C_433MHz_ADDR);
  Wire.write(0);  //Register Systemcode einstellen
  Wire.write(0);  //DIP1 = ON
  Wire.write(0);  //DIP2 = ON
  Wire.write(0);  //DIP3 = ON
  Wire.write(15); //DIP4 = OFF
  Wire.write(15); //DIP5 = OFF
  Wire.endTransmission();
}
void loop() 
{
  initSite();
}
void initSite()
{
  //Seiten-Weiche
  switch(globalCurrSite)
  {
    case 0:
      display_start();
      control_start();
    break;
    case 1:
      display_do();
      control_do();
    break;
    case 2:
      display_di();
      control_di();
    break;
    case 3:
      display_terra();
      control_terra();
    break;
    case 4:
      display_funk();
      control_funk();
  }
}
void display_funk()
{
  CleO.Start();
  int tiefeBt1 = 100;
  CleO.StringExt(FONT_MEDIUM, 160, 0, BLUE, TM, 0, 0, "HOKA I2C DEMO");
  CleO.RectangleExt(0, 50, 350, 500, WHITE, TL, 0, 0);
  CleO.LineWidth(30);
  
  if (penDownOnBack) {
    penDownOnBack = false;
    globalCurrSite = 0;
  } else if (penDownOn30) {
  penDownOn30 = false;
    send433Data(1,129);
    aBackCol = GREEN;
    aOnButCol = GREY;
    aOffButCol = BLUE;
  } else if (penDownOn31) {
  penDownOn31 = false;
    send433Data(1,130);
    bBackCol = GREEN;
    bOnButCol = GREY;
    bOffButCol = BLUE;
  } else if (penDownOn32) {
  penDownOn32 = false;
    send433Data(1,1);
    aBackCol = RED;
    aOnButCol = BLUE;
    aOffButCol = GREY;
  } else if (penDownOn33) {
  penDownOn33 = false;
    send433Data(1,2);
    bBackCol = RED;
    bOnButCol = BLUE;
    bOffButCol = GREY;
  }

  //Hintergrund A
  CleO.RectangleExt(20, 60, 280, 125, aBackCol, TL, 0, 0);

  //Hintergrund B
  CleO.RectangleExt(20, 200, 280, 125, bBackCol, TL, 0, 0);

  //Gruppe A
  CleO.Tag(30);
  CleO.RectangleExt(30, 80, 100, 65, aOnButCol, TL, 0, 0);
  CleO.StringExt(FONT_MEDIUM,80, 110, WHITE, MM, 0, 0, "A EIN");
  CleO.Tag(32);
  CleO.RectangleExt(180, 80, 100, 65, aOffButCol, TL, 0, 0);
  CleO.StringExt(FONT_MEDIUM,230, 110, WHITE, MM, 0, 0, "A AUS");

  //Gruppe B
  CleO.Tag(31);
  CleO.RectangleExt(30, 220, 100, 65, bOnButCol, TL, 0, 0);
  CleO.StringExt(FONT_MEDIUM,80, 250, WHITE, MM, 0, 0, "B EIN");
  CleO.Tag(33);
  CleO.RectangleExt(180, 220, 100, 65, bOffButCol, TL, 0, 0);
  CleO.StringExt(FONT_MEDIUM,230, 250, WHITE, MM, 0, 0, "B AUS");
  
  CleO.Tag(100);
  CleO.LineColor(BLUE);
  CleO.Line(0, 375, 350, 375);
  CleO.StringExt(FONT_MEDIUM,160, 375, WHITE, MM, 0, 0, "Startseite");
  CleO.StringExt(FONT_SANS_2, 160, 440, BLUE, TM, 0, 0, "www.horter.de");
  
  CleO.Show();
}
void display_do()
{
  CleO.Start();
  CleO.StringExt(FONT_MEDIUM, 160, 0, BLUE, TM, 0, 0, "HOKA I2C DEMO");
  CleO.RectangleExt(0, 50, 350, 500, WHITE, TL, 0, 0);
  CleO.LineWidth(30);

  //Funktionen Buttons
  
  if (penDownOn1) {     //wenn penDownOn1
    if (but1Dwn) {      //wenn bt1Dwn true
      VAL -=1;          //globale Variable wird -1 gesetzt 
    } else {          //ansonsten 
      VAL += 1;         //globale Variable wird +1 gesetzt
    }
    but1Dwn = !but1Dwn;   //bt1Dwn "schaltet" 
    delay(del);         //kurze Pause zum Finger wegnehmen
  }
  else if (penDownOn2) {
    if (but2Dwn) {
      VAL -=2;
    } else {
      VAL += 2;
    }
    but2Dwn = !but2Dwn;
    delay(del);
  }
  else if (penDownOn3) {
    if (but3Dwn) {
      VAL -=4;
    } else {
      VAL += 4;
    }
    but3Dwn = !but3Dwn;
    delay(del);
  }
  else if (penDownOn4) {
    if (but4Dwn) {
      VAL -=8;
    } else {
      VAL += 8;
    }
    but4Dwn = !but4Dwn;
    delay(del);
  }
  else if (penDownOn5) {
    if (but5Dwn) {
      VAL -=16;
    } else {
      VAL += 16;
    }
    but5Dwn = !but5Dwn;
    delay(del);
  }
  else if (penDownOn6) {
    if (but6Dwn) {
      VAL -=32;
    } else {
      VAL += 32;
    }
    but6Dwn = !but6Dwn;
    delay(del);
  }
  else if (penDownOn7) {
    if (but7Dwn) {
      VAL -=64;
    } else {
      VAL += 64;
    }
    but7Dwn = !but7Dwn;
    delay(del);
  }
  else if (penDownOn8) {
    if (but8Dwn) {
      VAL -=128;
    } else {
      VAL += 128;
    }
    but8Dwn = !but8Dwn;
    delay(del);
  }
  else if (penDownOnBack) {
    penDownOnBack = false;
    globalCurrSite = 0;
  }
  else  {}  

  int tiefe = 175;          //Tiefe aller 8 Buttons (Des ganzen Kontainers)
  int fromLeft1 = 40;         //Abstand von Links aller 8 Buttons
  int width1 = 40;            //Radius der Buttons
  int abst = 68;                //Abstand zwischen Buttons
  int tiefe1 = tiefe+60;        
  int fromLeft = fromLeft1+35;  
  int width = width1+35;
  
  //setValue-Funktion zum Ansteuern des Moduls
  setValue(VAL);
  
  //Layout Buttons    
  CleO.Tag(1);    //Tag für identifizierung 
  CleO.CircleExt(fromLeft1, tiefe1, 0, 30, BLUE, MM, 0, 0);       //Button zeichnen 
  CleO.StringExt(FONT_MEDIUM, fromLeft1, tiefe1, WHITE, MM, 0, 0, "1"); //Beschriftung
  CleO.Tag(3);
  CleO.CircleExt(fromLeft1+abst, tiefe1, 0, 30, BLUE, MM, 0, 0);
  CleO.StringExt(FONT_MEDIUM, fromLeft1+abst, tiefe1, WHITE, MM, 0, 0, "3");
  CleO.Tag(5);
  CleO.CircleExt(fromLeft1+abst*2, tiefe1, 0, 30, BLUE, MM, 0, 0);
  CleO.StringExt(FONT_MEDIUM, fromLeft1+abst*2, tiefe1, WHITE, MM, 0, 0, "5");
  CleO.Tag(7);
  CleO.CircleExt(fromLeft1+abst*3, tiefe1, 0, 30, BLUE, MM, 0, 0);
  CleO.StringExt(FONT_MEDIUM, fromLeft1+abst*3, tiefe1, WHITE, MM, 0, 0, "7");
  CleO.Tag(2);
  CleO.LineColor(BLUE);
  CleO.CircleExt(fromLeft, tiefe, 0, 30, BLUE, MM, 0, 0);
  CleO.StringExt(FONT_MEDIUM, fromLeft, tiefe, WHITE, MM, 0, 0, "2");
  CleO.Tag(4);
  CleO.LineColor(BLUE);
  CleO.CircleExt(fromLeft+abst, tiefe, 0, 30, BLUE, MM, 0, 0);
  CleO.StringExt(FONT_MEDIUM, fromLeft+abst, tiefe, WHITE, MM, 0, 0, "4");
  CleO.Tag(6);
  CleO.LineColor(BLUE);
  CleO.CircleExt(fromLeft+abst*2, tiefe, 0, 30, BLUE, MM, 0, 0);
  CleO.StringExt(FONT_MEDIUM, fromLeft+abst*2, tiefe, WHITE, MM, 0, 0, "6");
  CleO.Tag(8);
  CleO.LineColor(BLUE);
  CleO.CircleExt(fromLeft+abst*3, tiefe, 0, 30, BLUE, MM, 0, 0);
  CleO.StringExt(FONT_MEDIUM, fromLeft+abst*3, tiefe, WHITE, MM, 0, 0, "8");
  CleO.Tag(100);
  CleO.LineColor(BLUE);
  CleO.Line(0, 375, 350, 375);
  CleO.StringExt(FONT_MEDIUM,160, 375, WHITE, MM, 0, 0, "Startseite");
  //Footer
  CleO.StringExt(FONT_SANS_2, 160, 440, BLUE, TM, 0, 0, "www.horter.de");
  
  CleO.Show();
}
void display_terra()
{
  CleO.Start();
  int tiefeBt1 = 100;
  
  //Titel 
  CleO.StringExt(FONT_MEDIUM, 160, 0, BLUE, TM, 0, 0, "HOKA I2C DEMO");
  
  //Hintergrund
  CleO.RectangleExt(0, 50, 350, 500, WHITE, TL, 0, 0);
  
  //Überschrift
  CleO.StringExt(FONT_MEDIUM, 160, 80, BLACK, MM, 0, 0, "Temperatur /");
  CleO.StringExt(FONT_MEDIUM, 160, 125, BLACK, MM, 0, 0, "Luftfeuchtigkeit");
  
  //Konvertiere int zu String
  itoa(getTemperature(),tempNow,10);    //Für Temperatur
  itoa(getHumidity(),humNow,10);      //Für Luftfeuchtigkeit
  
  //Zeichne Anzeige 
  CleO.CircleExt(80, 220, 40, 45, LIGHTGREY, MM, 0, 0);
  CleO.CircleExt(220, 220, 40, 45, LIGHTGREY, MM, 0, 0);
  CleO.RectangleExt(0, 220 , 320, 480, WHITE, TL, 0, 0);
  
  //Zeichne Temperatur Nadel
  CleO.NeedleWidth(10);
  CleO.NeedleExt(80, 220, 50, BLUE, controlNeedleTemp(getTemperature()+90), 0);
  CleO.StringExt(FONT_MEDIUM, 65, 250, BLACK, TM, 0, 0, tempNow);
  CleO.StringExt(FONT_MEDIUM, 95, 250, BLACK, TM, 0, 0, " C");
  
  //Zeichne Feuchtigkeits Nadel
  CleO.NeedleExt(220, 220, 50, BLUE, controlNeedleHum(getHumidity()+90), 0);
  CleO.StringExt(FONT_MEDIUM, 205, 250, BLACK, TM, 0, 0, humNow);
  CleO.StringExt(FONT_MEDIUM, 235, 250, BLACK, TM, 0, 0, " %");
  CleO.LineWidth(30);
  
  //Funktion für zurück-Button
  if (penDownOnBack) {
    penDownOnBack = false;
    globalCurrSite = 0;
  }
  
  //Startseite-Button
  CleO.Tag(100);
  CleO.LineColor(BLUE);
  CleO.Line(0, 375, 350, 375);
  CleO.StringExt(FONT_MEDIUM,160, 375, WHITE, MM, 0, 0, "Startseite");
  
  //Footer
  CleO.StringExt(FONT_SANS_2, 160, 440, BLUE, TM, 0, 0, "www.horter.de");
  CleO.Show();
}
void display_di()
{
  CleO.Start();
  int tiefeBt1 = 100;
  CleO.StringExt(FONT_MEDIUM, 160, 0, BLUE, TM, 0, 0, "HOKA I2C DEMO");
  CleO.RectangleExt(0, 50, 350, 500, WHITE, TL, 0, 0);
  CleO.CircleExt(160,240,90,100,LIGHTGREY,MM,0,0);
  CleO.RectangleExt(0, 240, 320, 100, WHITE, TL, 0, 0);
  CleO.NeedleWidth(15);
  itoa(getInput(),anzeige,10);
  CleO.StringExt(FONT_MEDIUM, 160, 90, BLACK, TM, 0, 0, anzeige);
  CleO.NeedleExt(160, 240, 110, BLUE,controlNeedle(getInput())+90, 0);
  CleO.LineWidth(30);
  if (penDownOnBack) {
    penDownOnBack = false;
    globalCurrSite = 0;
  }
  CleO.Tag(100);
  CleO.LineColor(BLUE);
  CleO.Line(0, 375, 350, 375);
  CleO.StringExt(FONT_MEDIUM,160, 375, WHITE, MM, 0, 0, "Startseite");
  CleO.StringExt(FONT_SANS_2, 160, 440, BLUE, TM, 0, 0, "www.horter.de");
  CleO.Show();
}
void display_start()
{
  CleO.Start();
  int tiefeBt1 = 100;
  int tiefeBt2 = tiefeBt1+75;
  int tiefeBt3 = tiefeBt2+75;
  int tiefeBt4 = tiefeBt3+75;
  //int tiefeBt5 = tiefeBt4+75;
  //int tiefeBt6 = tiefeBt5+75;
  
  CleO.StringExt(FONT_MEDIUM, 160, 0, BLUE, TM, 0, 0, "HOKA I2C DEMO");
  CleO.RectangleExt(0, 50, 350, 500, WHITE, TL, 0, 0);
  CleO.LineWidth(30);
  
  if (penDownOn20) {
    penDownOn20 = false;
    globalCurrSite = 1;
  }
  else if (penDownOn21) {
    penDownOn21 = false;
    globalCurrSite = 2;
  }
  else if (penDownOn22) {
    penDownOn22 = false;
    globalCurrSite = 3;
  }
  else if (penDownOn23) {
    penDownOn23 = false;
    globalCurrSite = 4;
  }
  
  CleO.Tag(20);
  CleO.LineColor(BLUE);
  CleO.Line(0, tiefeBt1, 350, tiefeBt1);
  CleO.StringExt(FONT_MEDIUM, 160, tiefeBt1, WHITE, MM, 0, 0, "Digital Output");
  CleO.Tag(21);
  CleO.LineColor(BLUE);
  CleO.Line(0, tiefeBt2, 350, tiefeBt2);
  CleO.StringExt(FONT_MEDIUM, 160, tiefeBt2, WHITE, MM, 0, 0, "Digital Input");
  CleO.Tag(22);
  CleO.LineColor(BLUE);
  CleO.Line(0, tiefeBt3, 350, tiefeBt3);
  CleO.StringExt(FONT_MEDIUM, 160, tiefeBt3, WHITE, MM, 0, 0, "Terrarium Daten");
  CleO.Tag(23);
  CleO.LineColor(BLUE);
  CleO.Line(0, tiefeBt4, 350, tiefeBt4);
  CleO.StringExt(FONT_MEDIUM, 160, tiefeBt4, WHITE, MM, 0, 0, "Funkmodul");
  
  CleO.StringExt(FONT_SANS_2, 160, 440, BLUE, TM, 0, 0, "www.horter.de");
  CleO.Show();
}
void control_do()
{
  int16_t x, y, dur, tag;
  CleO.TouchCoordinates(x, y, dur, tag);  //Tag des Berührungspunktes einlesen

  
  if (previousDur == 0 && dur != 0)     //Wenn previousDur == 0 -> berührung aktiv und Dauer der Berührung nicht 0
  {
    previousTag = tag;            //Tag zwischenspeichern
    previousDur = 1;            //Setze previousDur = 1 für "wurde gedrückt"
    if (tag == 1)             //Button-Tag herausfinden
      penDownOn1 = true;          //entsprechende bool-Variable schalten (Weitere Verarbeitung in "display_do()")
    else if (tag == 2)
      penDownOn2 = true;
    else if (tag == 3)
      penDownOn3 = true;
    else if (tag == 4)
      penDownOn4 = true;
    else if (tag == 5)
      penDownOn5 = true;
    else if (tag == 6)
      penDownOn6 = true;
    else if (tag == 7)
      penDownOn7 = true;
    else if (tag == 8)
      penDownOn8 = true;
    else if (tag == 100)
      penDownOnBack = true;
  }
  
  else if (previousDur == 1 && dur == 0)  //Wenn previousDur == 1 -> berührung inaktiv und Dauer der Berührung ist 0
  {
    previousDur = 0;            //Setze previousDur = 1 für "wurde losgelassen"
    if (previousTag == 1)
      penDownOn1 = false;
    else if (previousTag == 2)
      penDownOn2 = false;
    else if (previousTag == 3)
      penDownOn3 = false;
    else if (previousTag == 4)
      penDownOn4 = false;
    else if (previousTag == 5)
      penDownOn5 = false;
    else if (previousTag == 6)
      penDownOn6 = false;
    else if (previousTag == 7)
      penDownOn7 = false;
    else if (previousTag == 8)
      penDownOn8 = false;
    else if (previousTag == 8)
      penDownOnBack = false;
  }
}
void control_terra()
{
  int16_t x, y, dur, tag;
  CleO.TouchCoordinates(x, y, dur, tag);
  if (previousDur == 0 && dur != 0) 
  {
    previousTag = tag;
    previousDur = 1;
    if (tag == 100)
      penDownOnBack = true;
  }
  else if (previousDur == 1 && dur == 0) 
  {
    previousDur = 0;
    if (previousTag == 100)
      penDownOnBack = false;    
  }  
}
void control_start()
{
  int16_t x, y, dur, tag;
  CleO.TouchCoordinates(x, y, dur, tag);

  if (previousDur == 0 && dur != 0) 
  {
    previousTag = tag;
    previousDur = 1;
    if (tag == 20)
      penDownOn20 = true;
  else if (tag == 21)
      penDownOn21 = true;
  else if (tag == 22)
      penDownOn22 = true;
  else if (tag == 23)
      penDownOn23 = true;
  }
  else if (previousDur == 1 && dur == 0) 
  {
    previousDur = 0;
    if (previousTag == 20)
      penDownOn20 = false; 
    else if (previousTag == 21)
      penDownOn21 = false; 
    else if (previousTag == 22)
      penDownOn22 = false; 
    else if (previousTag == 23)
      penDownOn23 = false;     
  }
}
void control_di()
{
  int16_t x, y, dur, tag;
  CleO.TouchCoordinates(x, y, dur, tag);
  if (previousDur == 0 && dur != 0) 
  {
    previousTag = tag;
    previousDur = 1;
    if (tag == 100)
      penDownOnBack = true;
  }
  else if (previousDur == 1 && dur == 0) 
  {
    previousDur = 0;
    if (previousTag == 100)
      penDownOnBack = false;    
  }
}
void control_funk()
{
  int16_t x, y, dur, tag;
  CleO.TouchCoordinates(x, y, dur, tag);
  if (previousDur == 0 && dur != 0) 
  {
    previousTag = tag;
    previousDur = 1;
    if (tag == 100)
      penDownOnBack = true;
  else if (tag == 30)
      penDownOn30 = true;
  else if (tag == 31)
      penDownOn31 = true;
  else if (tag == 32)
      penDownOn32 = true;
  else if (tag == 33)
      penDownOn33 = true;
  }
  else if (previousDur == 1 && dur == 0) 
  {
    previousDur = 0;
    if (previousTag == 100)
      penDownOnBack = false; 
  else if (previousTag == 30)
      penDownOn30 = false;
  else if (previousTag == 31)
      penDownOn31 = false;
  else if (previousTag == 32)
      penDownOn32 = false;
  else if (previousTag == 33)
      penDownOn33 = false;   
  }
}
void setValue(byte wert)
{
  byte val = 255-wert;                  //val mit invertiertem Wert belegen
  Wire.beginTransmission(I2C_OUT_ADDR);     //Uebertragung beginnen
  Wire.write(val);                    //Werte uebertragen
  Wire.endTransmission();               //Uebertragung beenden
}
int getInput()
{
   int val;               
   Wire.requestFrom(I2C_IN_ADDR, 1);    //Abfrage an Adresse schicken
   val = 255 - Wire.read();           //Wert invertieren
   return val;
}
void send433Data(int fb, int sb)    //Erstes und zweites Bit
{
  int wdh = 3;
  for (int i=0;i<wdh;i++)
  {
    Wire.beginTransmission(I2C_433MHz_ADDR);
    Wire.write(fb);
    Wire.write(sb);
    Wire.endTransmission();
  }
}
float getTemperature()
{
  return dht.readTemperature();       //DHT Library-Befehl
}
float getHumidity()
{
  return dht.readHumidity();        //DHT Library-Befehl
}  
int controlNeedle(int val)
{
  double b = 0.705;             //255 Werte auf 180 Grad -> 0.705 Grad pro +1
  int res = b*val;              //Position der Nadel anhand von val bestimmen 
  return res;                   //Auf "int" gerundetes Ergebnis ausgeben
}
int controlNeedleTemp(int val)
{
  double b = 1.1;   
  int res = b*val;    
  return res;
}
int controlNeedleHum(int val)
{
  double b = 1.4;   
  int res = b*val;    
  return res;
}