//Garagenstopp
//Code fuer Arduino
//Author Retian
//Testversion 1.0

#include <Metro.h>
#include <Wire.h>
#include <MyMCP9808.h>
#include <MyUltrasoundSensor.h>
#include <MyLedMatrix.h>

#define trimmPin 1
#define ldr1Pin 0
#define ldr2Pin 2
#define ledPin 13
#define tastPin 2
#define data 7
#define load 6
#define xclock 5
#define anzMod 2
#define trigPin 9
#define echoPin 8
#define entfernungOffset 3 //cm
#define stoppEntfernung 1  //cm

MyMCP9808 MyMCP(0x18);
MyUltrasoundSensor MyUsS(trigPin, echoPin);
MyLedMatrix MyLM(data, load, xclock, anzMod);
Metro zyklus1 = Metro(150); //Tastenzyklus = 150 ms
Metro zyklus2 = Metro(1000); //Temp.messzyklus = 1 s
Metro zyklus3 = Metro(100); //Entfernungsmesszyklus = 100 ms

//Prototypen
float mcp9808(void);
void setzeLdrSchaltPkt(void);
void setzeBalken(int, byte);

int ldrWert1; //Helligkeit Scheinwerfer / Lichthupe
int ldrWert2; //Helligkeit LED-Matrix
int trimmWert; //Einstellwert Trimmpoti
bool messStatus = LOW;
bool tastWert;
float tempWert;
float entfernung;
float lastEntfernung;
int8_t matrixIndensity;

int8_t colPfeil = (anzMod * 8) - 1;

unsigned long startZeit;
const unsigned long messZeit = 60; //Angabe in Sekunden
const unsigned long ueZeit = 180; //Ueberwachungszeit in Sekunden

extern byte logo[8], rahmenli[8], rahmenre[8], pfeil[8], char_st[8], char_op[8];

void setup() {
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  pinMode(tastPin, INPUT_PULLUP);
  MyLM.clearAll();
  MyLM.setIndensity(5);
  delay(1000);
  MyLM.writeFig(4, logo, 8);
  delay(2000);
  MyLM.clearAll();
  trimmWert = analogRead(trimmPin);
  tempWert = mcp9808();
  zyklus3.reset();
}

void loop() {
  if (zyklus1.check())
  {
    //Tastenabfrage
    tastWert = digitalRead(tastPin);
    if (!tastWert)
    {
      setzeLdrSchaltPkt();
    }
    //LDR fuer Scheinwerfer/Lichthupe
    ldrWert1 = analogRead(ldr1Pin);

    /*Serial.print("trimmWert: "); Serial.println(trimmWert);
      Serial.print("ldrWert1  : "); Serial.println(ldrWert1);
      Serial.println(tempWert);*/
  }

  if (zyklus2.check())
  {
    tempWert = mcp9808();

    //LDR fuer Helligkeit LED-Matrix
    ldrWert2 = analogRead(ldr2Pin);
    //Skalierung der Matrixhelligkeit 0...15
    matrixIndensity = max(0, map(ldrWert2, 0, 1023, 20, 0) - 5);
    MyLM.setIndensity(matrixIndensity);
    //Serial.print("ldrWert2  : "); Serial.println(ldrWert2);
    //Serial.print("matrixIndensity: "); Serial.println(matrixIndensity);

  }

  if (zyklus3.check())
  {
    //Serial.println(millis());
    if (ldrWert1 < trimmWert && messStatus == LOW)
    {
      //digitalWrite(ledPin, HIGH);
      MyLM.clearAll();
      MyLM.writeFig(4, logo, 8);
      delay(2000);
      MyLM.clearAll();
      startZeit = millis();
      messStatus = HIGH;
    }

    if ((millis() - startZeit > messZeit * 1000) && (entfernung < stoppEntfernung))
    {
      //digitalWrite(ledPin, LOW);
      messStatus = LOW;
      MyLM.clearAll();
    }

    if (millis() - startZeit > ueZeit * 1000)
    {
      //digitalWrite(ledPin, LOW);
      messStatus = LOW;
      MyLM.clearAll();
    }

    if (messStatus)
    {
      zyklus3.reset();
      //Serial.println(millis());
      entfernung = MyUsS.distanceTempComp(tempWert) - entfernungOffset;
      //entfernung = MyUsS.distance() - entfernungOffset;

      Serial.println(entfernung);
      if (entfernung > 900) //Fahrzeug ausserhalb Messreichweite
      {
        if (lastEntfernung < 900) MyLM.clearAll();
        lastEntfernung = entfernung;
        MyLM.writeFig(0, rahmenli, 8);
        MyLM.writeFig(8, rahmenre, 8);
      }
      else if (entfernung < stoppEntfernung)
      {
        lastEntfernung = entfernung;
        MyLM.writeFig(0, char_st, 8);
        MyLM.writeFig(8, char_op, 8);
        delay(1000);
      }
      else if (entfernung <= 9.5)
      {
        if (lastEntfernung > 9.5 || lastEntfernung < stoppEntfernung) MyLM.clearAll();
        lastEntfernung = entfernung;
        MyLM.writeNumber(1, (byte)(entfernung + 0.5) + 48);
        colPfeil = 8;
        MyLM.writeFig(colPfeil, pfeil, 8);
      }
      else if (entfernung > 9.5)
      {
        if (lastEntfernung <= 9.5 || lastEntfernung > 9000) MyLM.clearAll();
        lastEntfernung = entfernung;
        MyLM.writeFig(colPfeil, pfeil, 8);
        //MyLM.clearSector(colPfeil + 8, colPfeil + 8 + 1);
        colPfeil--;
        if (colPfeil == -8)
        {
          colPfeil = (anzMod * 8) - 1;
          MyLM.clearAll();
          MyLM.writeFig(colPfeil, pfeil, 8);
        }
      }
    }
  }
}

// Lufttemperatur mit MCP908 ermitteln
float mcp9808()
{
  float temp;
  return temp = MyMCP.readTemp();
}

//Lichtsensor Schaltpunkt einstellen
void setzeLdrSchaltPkt()
{
  //MyLM.setBlankOn();
  MyLM.clearAll();
  while (!tastWert)
  {
    //Serial.print("tastWert: "); Serial.println(tastWert);
    trimmWert = analogRead(trimmPin);
    setzeBalken(trimmWert, 2);
    setzeBalken(ldrWert1, 5);
    ldrWert1 = analogRead(ldr1Pin);
    if (ldrWert1 < trimmWert)digitalWrite(ledPin, HIGH);
    else digitalWrite(ledPin, LOW);
    Serial.print("trimmWert: "); Serial.println(trimmWert);
    Serial.print("ldrWert1  : "); Serial.println(ldrWert1);
    delay(150);
    tastWert = digitalRead(tastPin);
  }
  //MyLM.setBlankOff();
  MyLM.clearAll();
  digitalWrite(ledPin, LOW);
}

//Balkenanzeige ausgeben
void setzeBalken(int balkenWert, byte z)
{
  balkenWert = map(balkenWert, 0, 1023, 0, 16);
  //Serial.print("balkenWert: ");
  //Serial.println(balkenWert);
  for (byte y = 0; y < balkenWert; y++)
  {
    MyLM.setDot(y, z, 1);
    MyLM.setDot(y, z + 1, 1);
  }
  for (byte y = balkenWert; y < 16; y++)
  {
    MyLM.setDot(y, z, 0);
    MyLM.setDot(y, z + 1, 0);
  }
}