#include <LiquidCrystal.h>
#include <Encoder.h>

// Rotary Encoder Inputs
#define pinOout 8

#define pinEstop 18
#define pinSW 19
#define pinA 20
#define pinB 21

// rotary encoder min/max values
#define maxPWM 100
#define maxPID 150
//#define minVAL 0

//define the control modes
#define PWM 0
#define PID 1
volatile int newPosition = 0;
volatile int oldPosition = 0;

volatile int controlMode = PWM;  // [0 - PWM] [1 - PID]
volatile bool updateMode = true;
//   Best Performance: both pins have interrupt capability
Encoder tempEnc(pinA, pinB);


// for simulator
LiquidCrystal lcd(13, 12, 7, 6, 5, 4);

// for real arduino
//LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
void setup() {
  //set the interrupt for the estop
  pinMode(pinEstop, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinEstop), estop, LOW);

  // lcd initialization
  lcd.begin(16, 2);  // start the library
  lcd.setCursor(0, 0);
  lcd.print("Screen Enc V2");  // print a simple message
  delay(1000);
  lcd.clear();

  // set up interrupts for the switch
  pinMode(pinSW, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinSW), updateModeISR, FALLING);  // attach the flag setting the controlChange flag

  // Call the updateMode
  //updateMode();

  // Setup Serial Monitor1
  Serial.begin(9600);
}

void estop() {
  lcd.clear(); //clear the screen
  lcd.setCursor(0, 0);
  lcd.print("*****E-STOP*****");  // print the estop message
  while (!digitalRead(pinEstop));
  asm volatile("jmp 0");     // assembly function for reset
}

void updateModeISR() {
  updateMode = true;
}

void updateScreen() {
  bool justSwitched = false;
  if (updateMode) {
    switch (controlMode) {

      case PWM:
        controlMode = PID;
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("TEMP:        PID");  // print the PID message
        lcd.setCursor(0, 1);
        lcd.print("TEMP:        ");  // print the PID message
        break;

      case PID:
        controlMode = PWM;
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("TEMP:        PWM");  // print the PWM message
        lcd.setCursor(0, 1);
        lcd.print("POWR:           ");  // print a simple message
        break;
    }
    tempEnc.write(0);
    justSwitched = true;
    updateMode = false;
  }

  newPosition = tempEnc.read() / 4;  //read the encoder value and convert to number of detents

  if (newPosition < 0) {  // check for underflow
    newPosition = 0;
    tempEnc.write(0);
  }

  if (oldPosition != newPosition || justSwitched) {
    switch (controlMode) {
      case PWM:
        if (newPosition > maxPWM) {
          newPosition = maxPWM;
        }

        lcd.setCursor(6, 1);
        lcd.print(newPosition);  // print a simple message
        lcd.print("%");  // print a simple message
        oldPosition = newPosition;
        break;

      case PID:
        if (newPosition > maxPID) {
          newPosition = maxPID;
        }

        lcd.setCursor(6, 1);
        lcd.print(newPosition);  // print a simple message
        lcd.print("C");  // print a simple message
        oldPosition = newPosition;
        break;
    }
    justSwitched = false;
  }
}

void loop() {
  updateScreen();
}