#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

// LCD  Pin   Note
// ---  ---   -------------------
// CLK  D13   Serial clock
// DIN  D11   MOSI
// DC   D9    Data/Command select
// CS   D10   LCD chip select
// RST  D8    LCD reset
Adafruit_PCD8544 display = Adafruit_PCD8544(9, 10, 8);

// Two optical sensors are used, spaced SENSOR_DISTANCE [um] apart
//#define SENSOR_DISTANCE 200000 // [um] measured distance between the two IR beams
long SENSOR_DISTANCE = 200000; // [um] measured distance between the two IR beams (200.000 = 20cm)
// [us] timer starts when one of the sensor inputs goes HIGH (if LOW is needed, invert all digitalRead statements)
// [us] timer stops when the other sensor goes HIGH
// m_per_s = distance / (stop_time - start_time)
// km_per_hr = 3.6 * m_per_s, mph = 2.23694 * m_per_s;

////// CONFIGURATION
// To select the model scale, use a wire between GND and A0:O45, A1:OO76, A2:TT120, A3:N160
// If no wire is used the scale defaults to HO87
// Use a wire between GND and pin8 to toggle speed display between km/h and MPH.
#define UNITS 0 // set the default units here: 0:km/h, 1:MPH
//#define LOCO_LENGTH 250 // [mm] used to calculate how long to disable sensor input when finished
#define SENSOR_L_PIN 7 //D7
#define SENSOR_R_PIN 6 //D6
#define INFO_PIN 2

byte state = 0;
byte units = UNITS;
byte scale = 87; // Default scale is HO
unsigned int counter;
long start_us;
long stop_us;
long measured_us;
long oldPosition;// = -999;
float m_per_s;
float km_per_hr;
float mi_per_hr;
int menu_punkt = 1;

void serial_print() {
  if (units) Serial.print("    MPH "); else Serial.print("   km/h ");
  if (units) Serial.print(mi_per_hr); else Serial.print(km_per_hr);
  Serial.print("   m/s ");
  Serial.print(m_per_s);
  Serial.print("   ms ");
  Serial.print(int((measured_us + 500) / 1000));
  Serial.print("   scale ");
  switch (scale) {
    case 45:
      Serial.println("O 1/45"); break;
    case 76:
      Serial.println("OO 1/76"); break;
    case 87:
      Serial.println("HO 1/87"); break;
    case 120:
      Serial.println("TT 1/120"); break;
    case 160:
      Serial.println("N 1/160"); break;
  }
  Serial.println("");
  Serial.print(counter);
  Serial.println(" venter paa tog ...");
  Serial.println("");
}

void printDefault() {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.setTextSize(2);
  display.setTextColor(BLACK);
  display.println(" START");
  display.println(" TOGET");
  display.setTextSize(1);
  display.setCursor(3, 40);
  display.print("Tryk for info");
  display.display();
}

void setup() {
  Serial.begin(9600);

  display.begin();
  display.setContrast(60);
  display.clearDisplay(); //Clear splashscreen
  display.display();

  pinMode(INFO_PIN, INPUT_PULLUP);
  pinMode(SENSOR_L_PIN, INPUT_PULLUP);
  pinMode(SENSOR_R_PIN, INPUT_PULLUP);
  /*  if (!digitalRead(2)) scale = 45; // scale O
    if (!digitalRead(3)) scale = 76; // scale OO
    if (!digitalRead(4)) scale = 120; // scale TT
    if (!digitalRead(5)) scale = 160; // scale N
    // if none is LOW scale = 87 HO
    if (!digitalRead(12)) units = !units;
  */
  printDefault();
}

void loop() {
  switch (state) {
    case 0: // initial state, ready to start measuring
      if (!digitalRead(SENSOR_L_PIN)) {
        start_us = micros();
        state = 1;
      }
      if (!digitalRead(SENSOR_R_PIN)) {
        start_us = micros();
        state = 2;
      }
      if (!digitalRead(INFO_PIN)) {
        state = 4;
      }
      break;

    case 1: // L sensor was triggered first, now wait for R
      //digitalWrite(13, LOW);
      Serial.print("L >>> R");
      display.clearDisplay();
      display.drawRect(0, 0, 84, 48, BLACK);
      display.setCursor(12, 22);
      display.setTextSize(1);
      display.print("L >>>>>> R");
      display.display();
      while (digitalRead(SENSOR_R_PIN)) {} // loop here until sensor R is triggered
      stop_us = micros();
      state = 3;
      break;

    case 2: // R sensor was triggered first, now wait for L
      //digitalWrite(13, LOW);
      Serial.print("L <<< R");
      display.clearDisplay();
      display.drawRect(0, 0, 84, 48, BLACK);
      display.setCursor(12, 22);
      display.setTextSize(1);
      display.print("L <<<<<< R");
      display.display();
      while (digitalRead(SENSOR_L_PIN)) {} // loop here until sensor L is triggered
      stop_us = micros();
      state = 3;
      break;

    case 3: // calculate and show speed values
      measured_us = stop_us - start_us - long(10); // -10 to compensate for code delay
      m_per_s = float(scale) * float(SENSOR_DISTANCE) / float(measured_us);
      km_per_hr = 3.6 * m_per_s;
      mi_per_hr = 2.23694 * m_per_s;
      counter++;

      display.clearDisplay();
      display.fillRect(0, 0, 84, 26, BLACK);
      display.setCursor(2, 2);
      display.setTextSize(1);
      display.setTextColor(WHITE, BLACK);
      display.print("Km/t:");
      display.setCursor(2, 11);
      display.setTextSize(2);
      display.print(km_per_hr);
      display.drawRect(0, 26, 84, 22, BLACK);

      display.setTextColor(BLACK, WHITE);
      display.setCursor(2, 29);
      display.setTextSize(1);
      display.print("Type ");
      switch (scale) {
        case 45:
          display.print("O 1/45"); break;
        case 76:
          display.print("OO 1/76"); break;
        case 87:
          display.print("HO 1/87"); break;
        case 120:
          display.print("TT 1/120"); break;
        case 160:
          display.print("N 1/160"); break;
      }
      display.setCursor(2, 38);
      display.print("M/S: ");
      display.print(m_per_s);

      // ms her //

      display.display();

      serial_print();

      while(digitalRead(INFO_PIN));
      state = 0;
      printDefault();
      delay(200);      break;

    case 4:
      //Print menu
      display.clearDisplay();
      display.setCursor(0, 0);
      display.setTextSize(1);
      display.setTextColor(BLACK);
      display.println("Afstand:");
      display.print("       ");
      if ((SENSOR_DISTANCE / 1000) < 999) display.print(" ");
      else if ((SENSOR_DISTANCE / 1000) < 100) display.print(" ");
      display.print(SENSOR_DISTANCE / 1000);
      display.println(" mm");
      display.println("");
      display.println("Skala:");
      switch (scale) {
        case 45:
          display.println("        O 1/45"); break;
        case 76:
          display.println("       OO 1/76"); break;
        case 87:
          display.println("       HO 1/87"); break;
        case 120:
          display.println("      TT 1/120"); break;
        case 160:
          display.println("       N 1/160"); break;
      }
      display.display();
      delay(500);
      while(digitalRead(INFO_PIN));
      state = 0;
      printDefault();
      delay(500);
  }
}