// name the spi inputs and outputs
#define DC 9 //17        // Display Data/Command
#define RES 8 //16       // Display Reset
#define CS 10 //5         // Display Chip Select
#define thermoCS 14 //15  // MAX31856 temperature sensor Chip Select

// name the other inputs and the outputs
#define enter  4 //32 
#define up     6 //33
#define down   5 //25
#define right  3 //26
#define left   7 //27
#define klixon 15 //2   // over temperature alart
#define pins   21 //14   // 1 = pins up    =  green led 
#define vacuum 22 //13   // 1 = vacuum on  =  yellow led
#define heat   23 //12   // 1 = heater on  =  red led

#define bordercolor 5 // border grey value
#define curvecolor 8  // curve grey value

#define pressed  0  // button pressed
#define released 1  // button released

// both hardware SPI
Adafruit_MAX31856 maxthermo = Adafruit_MAX31856(14);
Adafruit_SSD1322 oled(256, 64, &SPI, DC, RES, CS, 32000000); // name de display struct

// setting PWM properties
const int freq = 500;     // PWM frequenvy for heater output
//const int ledChannel = 0; //
const int resolution = 12; // Output resolution 0-4095

bool blocktemp = false;

// contains the position of the button   true = released   false = pressed
bool enterKey = true; 
bool upKey = true;
bool downKey = true;
bool rightKey = true;
bool leftKey = true;

// latch for single push or repeat button
bool enterKeyblk = false; 
bool upKeyblk = false;
bool downKeyblk = false;
bool rightKeyblk = false;
bool leftKeyblk = false;

bool keyIn = false;                  // false if no button is pressed      true if any button is pressed

bool repeatUpdownKeyblk = false;     // true = single push    false = repeat
bool repeatRightLeftKeyblk = false;  // true = single push    false = repeat
bool repeatEnterKeyblk = false;      // true = single push    false = repeat

bool first = 0;

const char LAYOUT[6][4][29] =
  {
   {"                C         s ", 
    "   Single temperature/time  ", 
    "   Curve  temperature/time  ",
    "                            "}, 
   {"                C         s ", 
    "  Recipe   Setpoint   Time  ", 
    "                C         s ",
    "                            "}, 
   {"                C         s ", 
    " Curve  Point  Value   Time ", 
    "                    C     s ", 
    "                            "},
   {"             C      C     s ", 
    "                            ", 
    "                            ", 
    "                            "},
   {"    Development & design    ", 
    "                            ", 
    "        Herman Adema        ", 
    "                            "},
   {"                            ", 
    "         A009082023         ", 
    "         TEENSY 4.0         ",
    "                            "}
  };
  
const char STATUSLINE[18][29] = 
   {"      PROCESS STOPPED       ",
    "                            ",
    "                            ",
    "      PROCESS STANDBY       ",
    "WARNING:INTERNAL TEMP > 50 C",
    "                            ",
    "      TC OPEN CIRCUIT       ",
    "TC OVERVOLTAGE/UNDERVOLTAGE ",
    " COLD JUNCTION OUT OF RANGE ",
    "      TC OUT OF RANGE       ",
    "  Cold Junction Range Fault ",
    "  Thermocouple Range Fault  ",
    "  Cold Junction High Fault  ",
    "  Cold Junction Low Fault   ",
    "  Thermocouple High Fault   ",
    "  Thermocouple Low Fault    ",
    "  Over/Under Voltage Fault  ",
    "  Thermocouple Open Fault   "};

const char MODE[4][9] = {"  Stop  ","  Heat  ","  Run   "," St-by  "};


const byte POSX[4][5] = {
                        {2, 1, 1, 0,  0},  // screen 0 // single // curve 
                        {3, 3, 11, 22,  0},  // screen 1 // number // recipe // temp // time 
                        {4, 2,  9, 15, 22},  // screen 2 // number // point // temp // time 
                        {3, 3, 11, 21,  0}   // screen 3 // number and cursor positions screen 2 
                                      }; 
const byte POSY[4][5] = {
                        {2, 31, 47, 0,  0},  // screen 0 // single // curve 
                        {3, 47, 47, 47, 0},  // screen 1 // number // recipe // temp // time 
                        {4, 47, 47, 47,47},  // screen 2 // number // point // temp // time 
                        {3, 3, 11, 21,  0}   // screen 3 // number and cursor positions screen 2 
                                      }; 

int font_with = 9;  // Used for calculation of position on display

int curpos = 0;                // cursor position

// scrNr = 1 main screen
int recipeNr0 = 0;             // hotplate recipe number
int oldrecipeNr0 = 0;          // previous hotplate recipe number
int timeValue0 = 0;            // hotplate recipe process time value
int oldtimeValue0 = 0;         // previous hotplate recipe process time value
float tempValue0 = 0;          // hotplate recipe temperature value
float oldtempValue0 = 0;       // previous hotplate recipe temperature value
const int recipeMax0 = 10;     // maximum number of recipes
const int timeMax0 = 999;      // maximum process time
const float tempMax0 = 350;    // maximum hotplate temperature

// scrNr = 2 curve screen
int curveNr1 = 0;              // hotplate curve number
int oldcurveNr1 = 0;           // previous hotplate curve number
int pointNr1 = 0;              // curve point number
int oldpointNr1 = 0;           // previous curve point number
int timeValue1 = 0;            // hotplate curve process time value
int pointcnt = 1;              // current point number
int oldtimeValue1 = 0;         // previous hotplate curve process time value
float tempValue1 = 0;          // hotplate curve temperature value
float oldtempValue1 = 0;       // previous hotplate curve temperature value
const int curveMax1 = 10;      // maximum number of curves
const int pointMax1 = 10;      // maximum number of points
const int timeMax1 = 999;      // maximum process time
const float tempMax1 = 350;    // maximum hotplate temperature

int timeCounter0 = 0;          // hotplate timer value
int oldtimeCounter0 = 0;       // previous hotplate timer value
bool process_start = false;    // start the process timer

int timeCounter1 = 0;          // hotplate timer value
int oldtimeCounter1 = 0;       // previous hotplate timer value
bool process_startC = false;   // start the process timer Curve

uint8_t fault;
double tempMeas = 0;           // actual hotplate temperature
double oldtempMeas = 0;        // previous hotplate temperature
int bacTemp[256];              // temperature curve backup
int bacPoints[256];            // curve points backup
int lastx = 0;                 // last temperature position on curve screen

// enter button modes
int enter1Pos = 0;              // actual enter button position
int oldenter1Pos = 0;           // previous enter button position
int enterMax = 3;               // maximum number of enter button positions

double Input = 0;               // PID input
double oldSetpoint = 0;
double Setpoint = 0;            // PID setpoint
double Output = 0;              // PID output
 
// initialize the PID controller
double Kp=400, Ki=0.1, Kd=0.01; //50,2,0.01
//PID myPID(&Input, &Output, &Setpoint, P_ON_M, Kp, Ki, Kd, DIRECT);
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);

bool setAlert = false;         // set/reset alert
byte pins_up_with_delay = 0;   // pins on delaytime --- does not hold the programm

int statusMsgOld = 5;          // previous status message
int statusMsg = enter1Pos;      // actual status message

// recipes temperature,processtime
short RECIPES[recipeMax0+1][2] = 
  {
    {85,60},{80,60},{80,90},{85,60},{90,60},{95,60},{100,90},{120,60},{120,600},{180,90},{100,90}
  };

short CURVES[curveMax1+1][pointMax1+1][2] = 
  {
    {{90,0},{100,30},{110,60},{120,90},{150,120},{150,150},{170,180},{190,210},{200,240},{200,270},{200,300}},
    {{10,0},{80,60},{80,90},{85,60},{90,60},{95,60},{100,90},{120,60},{120,600},{180,90},{100,90}},
    {{20,0},{80,60},{80,90},{85,60},{90,60},{95,60},{100,90},{120,60},{120,600},{180,90},{100,90}},
    {{0,0},{80,60},{80,90},{85,60},{90,60},{95,60},{100,90},{120,60},{120,600},{180,90},{100,90}},
    {{0,0},{80,60},{80,90},{85,60},{90,60},{95,60},{100,90},{120,60},{120,600},{180,90},{100,90}},
    {{0,0},{80,60},{80,90},{85,60},{90,60},{95,60},{100,90},{120,60},{120,600},{180,90},{100,90}},
    {{0,0},{80,60},{80,90},{85,60},{90,60},{95,60},{100,90},{120,60},{120,600},{180,90},{100,90}},
    {{0,0},{80,60},{80,90},{85,60},{90,60},{95,60},{100,90},{120,60},{120,600},{180,90},{100,90}},
    {{0,0},{80,60},{80,90},{85,60},{90,60},{95,60},{100,90},{120,60},{120,600},{180,90},{100,90}},
    {{0,0},{80,60},{80,90},{85,60},{90,60},{95,60},{100,90},{120,60},{120,600},{180,90},{100,90}},
    {{0,0},{80,60},{80,90},{85,60},{90,60},{95,60},{100,90},{120,60},{120,600},{180,90},{100,90}},
  };

float curvetimescale = 0;        // max times curve
float curvetempscale = 0;        // max temp curve
int scrNr = 1;                 // first screen from LAYOUT[][][]


int trendline[4][256];        // temperature trendlines
int recipesteps[10][30];      // programmable trend follow steps

bool start_scr_timer = false;
int scrsvrcnt = 0;


unsigned long keytime = 0;  
unsigned long initrepeat = 200;
unsigned long keywindow = 50;           // time in ms   // interval for reading keyboard
unsigned long initkeywindow = keywindow;       // time in ms   // interval for reading keyboard used to reset timer
unsigned long keytimecnt = 300;
unsigned long keytimecntinit = keytimecnt;
unsigned long keytottime = 0;

unsigned long temptime = 0;
unsigned long tempwindow = 100;         // time in ms   // interval for temperature measurement and controlling

unsigned long alerttime = 0;
unsigned long alertwindow = 1000;        // time in ms   // interval for checking alert

unsigned long pindelaytime = millis();
unsigned long pindelaywindow = 2000;     // time in ms   // on delay for lifting pins

unsigned long prctimertime = 0;
unsigned long prctimerwindow = 1000;     // time in ms   // interval for process timer

unsigned long prctimertimeC = 0;
unsigned long prctimerwindowC = 1000;     // time in ms   // interval for process timer

unsigned long scrsavertime = 0;
unsigned long scrsaverwindow = 60000;     // time in ms   // interval for screensavercounter
