//SCULLCOM HOBBY ELECTRONICS
//ELECTRONIC DC LOAD PROJECT
//Software Version 35 (4x5 Matrix Keypad Version - modified key layout)
//14th April 2018

#include <Arduino.h>

#include <SPI.h>                              //include SPI library (Serial Peripheral Interface)
#include <Wire.h>                             //include I2C library
#include <math.h>                             //
#include <MCP342x.h>                          //Steve Marple library avaiable from    https://github.com/stevemarple/MCP342x
#include <MCP79410_Timer.h>                   //Scullcom Hobby Electronics library  http://www.scullcom.com/MCP79410Timer-master.zip
#include <EEPROM.h>                           //include EEPROM library used for storing setup data
#include <config.h>
#include <screen.h>
#include <SoftwareSerial.h>

SoftwareSerial nexSerial (rxPin,txPin);

static uint8_t __buffer[10];
uint16_t i1;
uint8_t c1;
void setupLimits (void);
void transientSwitch(float current_setting, boolean toggle_status);
void transientListSetup();
void batteryType (void);
void setBatteryCutOff (void);
void setBatteryCutOff (void);
void inputValue (int r);
void batteryTypeSelected (void);
void currentDisplayCal (void);
void BatteryCapacity(void);
void Current(void);
void Resistance(void);
void Power(void);
void transientType(void);
void userSetUp (void);
void fanControl (void);
void batteryCapacityloop (void);
void LoadSwitch(void);
void dacControlVoltage (void);
void dacControl (void);
void ActualReading(void);
void readVoltageCurrent (void);
void displayEncoderReading (void);
void transientLoadToggle();
void CursorPosition(void);
void batteryCurrentLimitValue(void);
void temperatureCutOff(void);
void maxConstantCurrentSetting (void) ;
void transient (void);
void readKeypadInput (void);
void powerLevelCutOff (void) ;
void wait_for_key(bool wait =true );



char customKey;

char decimalPoint;                            //used to test for more than one press of * key (decimal point)

                    

MCP342x adc = MCP342x(I2C_MCP342x_ADDRESS);

MCP79410_Timer timer = MCP79410_Timer(I2C_MCP79410_ADDRESS);

//Set the pins on the I2C chip used for LCD connections
//ADDR,EN,R/W,RS,D4,D5,D6,D7


int temp;                                     //

float BatteryLife = 0;                        //
float BatteryLifePrevious = 0;                //
float Seconds = 0;                            //time variable used in Battery Capacity Mode (BC)
float SecondsLog = 0;                         //variable used for data logging of the time in seconds
float BatteryCutoffVolts;                     //used to set battery discharge cut-off voltage
float MaxBatteryCurrent = 1.0;                //maximum battery current allowed for Battery Capacity Testing

int stopSeconds;                              //store for seconds when timer stopped

int CP = 8;                                   //cursor start position

boolean toggle = false;                       //used for toggle of Load On/Off button

unsigned long controlVoltage = 0;             //used for DAC to control MOSFET

long current = 0;                             //variable used by ADC for measuring the current
long voltage = 0;                             //variable used by ADC for measuring the voltage

float reading = 0;                            //variable for Rotary Encoder value divided by 1000

float setCurrent = 0;                         //variable used for the set current of the load
float setPower = 0;                           //variable used for the set power of the load
float setResistance = 0;                      //variable used for the set resistance of the load



int Load = 0;                                 //Load On/Off flag

float setControlCurrent = 0;                  //variable used to set the temporary store for control current required

int VoltsDecimalPlaces = 3;                   //number of decimal places used for Voltage display on LCD

float ActualVoltage = 0;                      //variable used for Actual Voltage reading of Load
float ActualCurrent = 0;                      //variable used for Actual Current reading of Load
float ActualPower = 0;                        //variable used for Actual Power reading of Load

float BatteryCurrent;                         //
float LoadCurrent;                            //

int CurrentCutOff =0; 
int PowerCutOff = 0;
int tempCutOff = 0; 

int setReading = 0;                           //

int ControlVolts = 0;                         //used to set output current
float OutputVoltage = 0;                      //

uint8_t Mode = 0;                            //used to identify which mode
uint8_t old_Mode = 0;
int modeSelected = 0;                         //Mode status flag

int lastCount = 50;                           //
volatile float encoderPosition = 0;           //
volatile unsigned long factor= 0;             //number of steps to jump
volatile unsigned long encoderMax = 999000;   //sets maximum Rotary Encoder value allowed CAN BE CHANGED AS REQUIRED (was 50000)

float LiPoCutOffVoltage = 3.0;                //set cutoff voltage for LiPo battery
float LiFeCutOffVoltage = 2.8;                //set cutoff voltage for LiFe battery
float NiCdCutOffVoltage = 1.0;                //set cutoff voltage for NiCd battery
float ZiZnCutOffVoltage = 1.0;                //set cutoff voltage for ZiZn battery
float PbAcCutOffVoltage = 1.75;               //set cutoff voltage for PbAc battery
String BatteryType ="    ";

byte exitMode = 0;                           //used to exit battery selection menu and return to CC Mode

char numbers[10];                            //keypad number entry - Plenty to store a representation of a float
byte index = 0;
int z = 1;                                   //was previously 0
float x = 0;
int y = 0;
int r = 0;

float LowCurrent = 0;               //the low current setting for transcient mode
float HighCurrent = 0;              //the high current setting for transcient mode
unsigned long transientPeriod;      //used to store pulse time period in transcient pulse mode
unsigned long current_time;         //used to store the current time in microseconds
unsigned long last_time;            //used to store the time of the last transient switch in micro seconds
boolean transient_mode_status;      //used to maintain the state of the trascient mode (false = low current, true = high current)

float transientList [10][2];        //array to store Transient List data
int total_instructions;             //used in Transient List Mode
int current_instruction;            //used in Transient List Mode

char line0[line_len]= {0};
char line1[line_len]= {0};
char line2[line_len]= {0};
char line3[line_len]= {0};
char line0_old[line_len]= {0};
char line1_old[line_len]= {0};
char line2_old[line_len]= {0};
char line3_old[line_len]= {0};
char temperature_val[5]={0x00};
char temperature_buf[5]={0x00};
bool old_load=true;
void setmode(void);
void color_load (bool load);
bool setVoltage(uint16_t output, bool writeEEPROM) {

  uint8_t packet[3];

  if (writeEEPROM) {
    packet[0] = MCP4725_CMD_WRITEDACEEPROM;
  } else {
    packet[0] = MCP4725_CMD_WRITEDAC;
  }
  packet[1] = output / 16;        // Upper data bits (D11.D10.D9.D8.D7.D6.D5.D4)
  packet[2] = (output % 16) << 4; // Lower data bits (D3.D2.D1.D0.x.x.x.x)

  if (!Wire.write(packet, 3)) {
    return false;
  }

  return true;
}


//--------------------------------Interrupt Routine for Rotary Encoder------------------------
void isr()
{
  static unsigned long lastInterruptTime = 0;
  unsigned long interruptTime = millis();

  if (interruptTime - lastInterruptTime > 5) {  //
    if (digitalRead(pinB) == LOW)
    {
      encoderPosition = encoderPosition - factor;
    }else{
      encoderPosition = encoderPosition + factor;
    }
    encoderPosition = min(encoderMax, max(0, encoderPosition));  // sets maximum range of rotary encoder
    lastInterruptTime = interruptTime;
  }
    }



void serialEvent() {
    while (nexSerial.available() > 0 ){   
        
        c1 = nexSerial.read();
        if (0x65 == c1 ||__buffer[0] == 0x65)
        {
            if (0x65 == c1){
              __buffer[0] = c1; 
              i1++;
            }else{
              __buffer[i1]=c1; 
              i1++; 
            if (i1>=7)
            {
                __buffer[i1] = 0x00;
                if (0xFF == __buffer[4] && 0xFF == __buffer[5] && 0xFF == __buffer[6])
                {
                    if (__buffer[1]==0){
                      switch(__buffer[2]){
                        case 11:
                          customKey='0';
                          break;
                        case 2:
                          customKey='1';
                          break;
                        case 3:
                          customKey='2';
                          break;
                        case 4:
                          customKey='3';
                          break;
                        case 5:
                          customKey='4';
                          break;
                        case 6:
                          customKey='5';
                          break;
                        case 7:
                          customKey='6';
                          break; 
                        case 8:
                          customKey='7';
                          break;
                        case 9:
                          customKey='8';
                          break;
                        case 10:
                          customKey='9';
                          break;
                        case 20:
                          customKey='F';
                          break;
                        case 13:
                          customKey='>';
                          break;
                        case 12:
                          customKey='<';
                          break;
                        case 21:
                          customKey='E';
                          break;
                        case 19:
                          customKey='D';
                          break;
                        case 16:
                          customKey='A';
                          break;
                        case 17:
                          customKey='B';
                          break;
                        case 18:
                          customKey='#';
                          break;
                        case 15:
                          customKey='*';
                          break;
                        case 14:
                          customKey='C';
                          break;
                      }

                    }
                }
              memset(__buffer,0x00,8);
              i1=0;  
            }
        }
    }
    }
}

//---------------------------------Initial Set up---------------------------------------
void setup() {
                                   //used for testing only
  Wire.begin();                                            //join i2c bus (address optional for master)
  Wire.setClock(400000L);                                  //sets bit rate to 400KHz
  pinMode(rxPin, INPUT);
  pinMode(txPin, OUTPUT);
  nexSerial.begin(38400);
  Serial.begin(38400);
  analogReference(INTERNAL2V5);
  /* Register the pop event callback function of the current button component. */
  delay(100);
  unsigned long _tmr1;
  _tmr1 = millis();
  while(nexSerial.available() > 0){     // Read the Serial until it is empty. This is used to clear Serial buffer
    if((millis() - _tmr1) > 400UL){    // Reading... Waiting... But not forever...... 
      break;                            
    } 
      nexSerial.read();                // Read and delete bytes
  }

  CurrentCutOff = EEPROM.read(0x00);
  PowerCutOff = EEPROM.read(0x20);
  tempCutOff = EEPROM.read(0x40);
  MCP342x::generalCallReset();                             //Reset devices
  pinMode (pinA, INPUT);
  pinMode (pinB, INPUT);
  pinMode (CursorPos, INPUT_PULLUP);
  pinMode (LoadOnOff, INPUT_PULLUP);
 
  pinMode (TriggerPulse, INPUT_PULLUP);
    byte error, address;
  int nDevices;
nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
 
    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
 
      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  pinMode (fan, OUTPUT);
  //TCCR2B = (TCCR2B & 0b11111000) | 1;                      //change PWM to above hearing (Kenneth Larvsen recommendation)
  pinMode (temperature, INPUT);
  setVoltage(0,false);                                 //reset DAC to zero for no output current set at Switch On
  analogReference(INTERNAL);                               //use Arduino internal reference for tempurature monitoring
  attachInterrupt(digitalPinToInterrupt(pinA), isr, LOW);
 
  screen_clear('\0');
  writeNum2("t0.xcen", 1);                                 //print SCULLCOM to display with 5 leading spaces (you can change to your own)
  memcpy(line0,(char*)"SCULLCOM",9);
  print_chars2(0,9);
  
  memcpy(line1,(char*)"Hobby Electronics",18); 
  print_chars2(1,18);

  memcpy(line2,(char*)"DC Electronic Load",19);
  print_chars2(2,19);

  memcpy(line3,(char*)"Ver. 35 (5x4 Keypad)",21);
  print_chars2(3,21);

  delay(2000);                                             //3000 mSec delay for intro display
  screen_clear(' ');  
  setupLimits();
  delay(3000);
  screen_clear(' ');  

  last_time = 0;                                           //set the last_time to 0 at the start (Transicent Mode)
  transient_mode_status = false;                           //set the initial transient mode status (false = low, true = high);
  setCurrent = LowCurrent;                                 //first set the current to the low current value (Transicent Mode)

  color_load(0); 
  Current();                                               //sets initial mode to be CC (Constant Current) at Power Up
  //EEPROM.write(0x00, 0xff);
  customKey='\0';

}

//------------------------------------------Main Program Loop---------------------------------
void loop() {


  serialEvent();  
  if(CurrentCutOff > 5){                                 //Test and go to user set limits if required
    userSetUp();
    writeNum2("t0.xcen", 0);
    customKey='\0';
  }else{
  
    readKeypadInput();                                     //read Keypad entry
    
    if (digitalRead(LoadOnOff) == LOW) {
      LoadSwitch();                                          //Load on/off
    }
    
    transient();                                           //test for Transient Mode
    setmode() ;
    if(Mode != MODE_TC && Mode != MODE_TP && Mode != MODE_TT && Mode != MODE_TL){      //if NOT transient mode then Normal Operation
      reading = encoderPosition/1000;                        //read input from rotary encoder 
      maxConstantCurrentSetting();                           //set maxiumum Current allowed in Constant Current Mode (CC)
      powerLevelCutOff();                                    //Check if Power Limit has been exceeded
    
      temperatureCutOff();                                   //check if Maximum Temperature is exceeded
    
      batteryCurrentLimitValue();                            //Battery Discharge Constant Current Limit Value in BC Mode
      displayEncoderReading();                               //display rotary encoder input reading on LCD
      lastCount = encoderPosition;                           //store rotary encoder current position
      CursorPosition();                                      //check and change the cursor position if cursor button pressed
    }else{
      maxConstantCurrentSetting();                           //set maxiumum Current allowed in Constant Current Mode (CC)
      powerLevelCutOff();                                    //Check if Power Limit has been exceeded
    
      temperatureCutOff();                                   //check if Maximum Temperature is exceeded
      transientLoadToggle();                                  //Start Transient Mode
    }
      
    readVoltageCurrent();                                  //routine for ADC's to read actual Voltage and Current
    ActualReading();                                       //Display actual Voltage, Current readings and Actual Wattage
    
    dacControl();
    dacControlVoltage();                                   //sets the drive voltage to control the MOSFET

    batteryCapacityloop();                                     //test if Battery Capacity (BC) mode is selected - if so action
    fanControl();                                          //call heatsink fan control
  }
}
//------------------------------------------------Read Keypad Input-----------------------------------------------------
void readKeypadInput (void) {

//  if (customKey != NO_KEY){                             //only used for testing keypad (uncomment if required for testing keypad)
// Serial.print("customKey = ");                          //only used for testing keypad (uncomment if required for testing keypad)
// Serial.println(customKey);                             //only used for testing keypad (uncomment if required for testing keypad)
//  }                                                     //only used for testing keypad (uncomment if required for testing keypad)

  if(customKey == 'E'){                                     //check for Load on/off
    LoadSwitch();
    customKey='\0';
  }

  if(customKey == 'D'){                                   //check if Set-Up Mode Selected 
    delay(200);
    toggle = false;  
    customKey='\0';                                       //switch Load OFF
    LoadSwitch();
    userSetUp();
    encoderPosition = 0;                                    //reset encoder reading to zero
    index = 0;
    z = 1;                                                  //sets column position for LCD displayed character
    decimalPoint = (' ');                                   //clear decimal point text character reset

}
 
  if(customKey == 'C'){                                   //check if Transient Mode Selected
    toggle = false;    
    customKey='\0';                                     //switch Load OFF
    transientType();
  
    encoderPosition = 0;                                    //reset encoder reading to zero
    index = 0;
    z = 1;                                                  //sets column position for LCD displayed character
    decimalPoint = (' ');                                   //clear decimal point text character reset

  }
               
  if(customKey == 'A'){                                   //check if Constant Current button pressed
    toggle = false;                                         //switch Load OFF
    color_load(0);
    print_chars2(0,20);
    Current();                                              //if selected go to Constant Current Selected routine
    encoderPosition = 0;                                    //reset encoder reading to zero
    index = 0;
    z = 1;                                                  //sets column position for LCD displayed character
    decimalPoint = (' ');                                   //clear decimal point test character reset
    customKey='\0';
  }
         
  if(customKey == 'B'){                                   //check if Constant Power button pressed
    toggle = false;                                         //switch Load OFF
    color_load(0);
    print_chars2(0,20);
    Power();                                                //if selected go to Constant Power Selected routine
    encoderPosition = 0;                                    //reset encoder reading to zero
    index = 0;
    z = 1;                                                  //sets column position for LCD displayed character
    decimalPoint = (' ');                                   //clear decimal point test character reset
    customKey='\0';
  }
          
  if(customKey == '#'){                                   //check if Constant Resistance button pressed  
    toggle = false;                                         //switch Load OFF
    color_load(0);
    print_chars2(0,20);
    Resistance();                                           //if selected go to Constant Resistance Selected routine
    encoderPosition = 0;                                    //reset encoder reading to zero
    index = 0;
    z = 1;                                                  //sets column position for LCD displayed character
    decimalPoint = (' ');                                   //clear decimal point test character reset
    customKey='\0';
  }

  if(customKey == '*'){                                   //check if Battery Capacity button pressed
    setVoltage(0,false);                                //Ensures Load is OFF - sets DAC output voltage to 0
    toggle = false;                                         //switch Load OFF
    batteryType();                                          //select battery type
    index = 0;
    z = 1;                                                  //sets column position for LCD displayed character
    decimalPoint = (' ');                                   //clear decimal point test character reset
    if (exitMode == 1){                                   //if NO battery type selected revert to CC Mode
      color_load(0);
      print_chars2(0,20);
      Current();                                            //if selected go to Constant Current Selected routine
      encoderPosition = 0;                                  //reset encoder reading to zero
      customKey = 'A';
    }
    else
    {
      memcpy(line2+16,(char*)BatteryType.c_str(),4);
      print_chars2(2,20);
      color_load(0);
      print_chars2(0,20);
      timer.reset();                                        //reset timer
      BatteryLifePrevious = 0;
      CP = 9;                                               //set cursor position
      BatteryCapacity();                                    //go to Battery Capacity Routine
    }
  }

  if (Mode != MODE_TC && Mode != MODE_TL && Mode != MODE_TP && Mode != MODE_TT){

    if(customKey >= '0' && customKey <= '9'){               //check for keypad number input
        numbers[index++] = customKey;
        numbers[index] = '\0';
        line3[z]=customKey;
        print_chars2(3,20);
        z = z+1;
        customKey ='\0';
      }
    
    if(customKey == '>'){                                   //check if decimal button key pressed
        if (decimalPoint != ('>')){                         //test if decimal point entered twice - if so skip 
          numbers[index++] = '.';
          numbers[index] = '\0';
          line3[z]='.';
          print_chars2(3,20);
          z = z+1;
          decimalPoint = ('>');                             //used to indicate decimal point has been input
          }
        customKey ='\0';
        }

    if(customKey == '<'){                                 //clear input entry
      index = 0;
      z = 1;                                             //sets column position for LCD displayed character
      print_chars(3,z,(char *) "     ",5);
      numbers[index] = '\0';                             //
      decimalPoint = (' ');                              //clear decimal point test character reset
      customKey ='\0';
      }

    if(customKey == 'F') {                                //use entered number
      x = atof(numbers);     
      reading = x;
      encoderPosition = reading*1000;
      index = 0;
      numbers[index] = '\0';
      z = 1;                                         //sets column position for LCD displayed character
      print_chars(3,z,(char *) "     ",5);
      decimalPoint = (' ');                          //clear decimal point test character reset
      customKey ='\0';
    }
  }
  
}

//----------------------Limit Maximum Current Setting-----------------------------------------
void maxConstantCurrentSetting (void) {
  if (Mode == MODE_CC && reading > CurrentCutOff){           //Limit maximum Current Setting
  reading = CurrentCutOff;
  encoderPosition = (CurrentCutOff * 1000);               //keep encoder position value at maximum Current Limit

  print_chars(3,0,(char*)"Exceeded Power      ",20);                    //20 spaces to clear last line of LCD 
  }

  if (Mode == MODE_CP && reading > PowerCutOff) {             //Limit maximum Current Setting
        reading = PowerCutOff;
        encoderPosition = (PowerCutOff * 1000);            //keep encoder position value at maximum Current Limit

        print_chars(3,0,(char*)"Exceeded Power      ",20);                 //20 spaces to clear last line of LCD 
    }

   if (Mode == MODE_CR && reading > ResistorCutOff ) {             //Limit maximum Current Setting
        reading = ResistorCutOff;
        encoderPosition = (ResistorCutOff * 1000);            //keep encoder position value at maximum Current Limit

        print_chars(3,0,(char*)"Exceeded Power      ",20);                   //20 spaces to clear last line of LCD 
    }

}

//----------------------Power Level Cutoff Routine-------------------------------------------
void powerLevelCutOff (void) {
  if (ActualPower  > PowerCutOff){                        //Check if Power Limit has been exceed
    reading = 0;
    encoderPosition = 0; 

    print_chars(3,0,(char*)"Exceeded Power      ",20);
    color_load(0);
    print_chars2(0,20);
    toggle = false;                                         //switch Load Off
  }
}

//----------------------Battery Constant Current Limit Value------------------------------------------
void batteryCurrentLimitValue (void) {
  if (Mode == MODE_BC && reading > MaxBatteryCurrent){
  reading = MaxBatteryCurrent;
  encoderPosition = (MaxBatteryCurrent*1000);            //keep encoder position value at 1000mA
  }
}

//----------------------Display Rotary Encoder Input Reading on LCD---------------------------
void displayEncoderReading (void) {

    //lcd.setCursor(8,2);                                      //start position of setting entry
    char buff[6];
    uint8_t cursor_pos=8;
    /*
    if ( ( Mode == "CP" || Mode == "CR" ) && reading < 100 ) {
        //lcd.print("0");
        print_chars(2,cursor_pos++,(char*)"0",1);
    }
    
    if (reading < 10) {                                      //add a leading zero to display if reading less than 10
        print_chars(2,cursor_pos++,(char*)"0",1);
    }
    */
    if ( Mode == MODE_CP || Mode == MODE_CR ) {
        //lcd.print (reading, 2);                              //show input reading from Rotary Encoder on LCD
        dtostrf(reading, 5, 2, buff);
        print_chars(2,cursor_pos++,(char*)buff,5);
    } else {
        dtostrf(reading, 5, 3, buff);
        print_chars(2,cursor_pos++,(char*)buff,5);
    }
    //lcd.setCursor (CP, 2);                                   //sets cursor position
    //lcd.cursor();                                            //show cursor on LCD
}

//--------------------------Cursor Position-------------------------------------------------------
//Change cursor the position routine
void CursorPosition(void) {

    // Defaults for two digits before decimal and 3 after decimal point
    int unitPosition = 9;

    //Power and Resistance modes can be 3 digit before decimal but only 2 decimals
    if ( Mode == MODE_CP || Mode == MODE_CR ) {
        unitPosition = 10;        
    }

    if (digitalRead(CursorPos) == LOW) {
    
        delay(200);                                          //simple key bounce delay  
        CP = CP + 1;
        if (CP == unitPosition + 1 ) {
            CP = CP + 1;
        }
    }
    
    if (CP > 13)  { CP = unitPosition; }                     //No point in turning tens and hundreds
    if (CP == unitPosition +4 ) { factor = 1; }
    if (CP == unitPosition +3 ) { factor = 10; }
    if (CP == unitPosition +2 ) { factor = 100; }
    if (CP == unitPosition )    { factor = 1000; }
}

//---------------------------------------------Read Voltage and Current--------------------------------------------------------------
void readVoltageCurrent (void) {
  
  MCP342x::Config status;
// Initiate a conversion; convertAndRead() will wait until it can be read
  adc.convertAndRead(MCP342x::channel1, MCP342x::oneShot,
           MCP342x::resolution16, MCP342x::gain1,                         //"gain1" means we have select the input amp of the ADC to x1
           1000000, voltage, status);
  
// Initiate a conversion; convertAndRead() will wait until it can be read
  adc.convertAndRead(MCP342x::channel2, MCP342x::oneShot,
           MCP342x::resolution16, MCP342x::gain4,                         //"gain4" means we have select the input amp of the ADC to x4
           1000000, current, status);
  
}

//-----------------------------------Calculate Actual Voltage and Current and display on LCD-----------------------------------------
void ActualReading(void) {

  ActualCurrent = (((current*2.048)/32767) * 2.5);        //calculate load current
  currentDisplayCal();                                    //LCD display current calibration correction
  ActualVoltage = (((voltage*2.048)/32767) * 50.4);       //calculate load voltage upto 100v (was 50)
  ActualPower = ActualVoltage*ActualCurrent;

  if (ActualPower <=0){
    ActualPower = 0;
  }

 if (ActualVoltage <=0.0){                              //added to prevent negative readings on LCD due to error
  ActualVoltage = 0.0;
 }
 if (ActualCurrent <= 0.0){                             //added to prevent negative readings on LCD due to error
  ActualCurrent = 0.0;
 }
 
  char buff[6]; 
    if ( ActualCurrent < 10.0 ) {
       dtostrf(ActualCurrent, 4, 3, buff);
    } else {
        dtostrf(ActualCurrent, 4, 2, buff);
    }
    memcpy(line1,buff ,5);
    memcpy(line1+5,(char *)"A " ,2);
    
    if (ActualVoltage < 10.0) {
        //lcd.print(ActualVoltage, 3);
        dtostrf(ActualVoltage, 4, 3, buff);
    } else {
        dtostrf(ActualVoltage, 4, 2, buff);
    }    
    memcpy(line1+7,buff ,6);
    memcpy(line1+12,(char *)"V " ,2);
     
    if (ActualPower < 100 ) {
         dtostrf(ActualPower, 4, 2, buff);
    } else {
         dtostrf(ActualPower, 4, 1, buff);
    }
    memcpy(line1+14,buff ,6);
    print_chars(1,18,(char *)"W " ,2);
}

//-----------------------DAC Control Voltage for Mosfet---------------------------------------
void dacControlVoltage (void) {
  if (Mode == MODE_CC){
  setCurrent = reading*1000;                                //set current is equal to input value in Amps
  setReading = setCurrent;                                  //show the set current reading being used
  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
  controlVoltage = setControlCurrent; 
  }

  if (Mode == MODE_CP){
  setPower = reading*1000;                                  //in Watts
  setReading = setPower;
  setCurrent = setPower/ActualVoltage;
  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
  controlVoltage = setControlCurrent;                       //
  }

  if (Mode == MODE_CR){
  setResistance = reading;                                  //in ohms
  setReading = setResistance;
  setCurrent = (ActualVoltage)/setResistance*1000;
  setControlCurrent = setCurrent * setCurrentCalibrationFactor;
  controlVoltage = setControlCurrent; 
  }

if (Mode == MODE_TC || Mode == MODE_TP || Mode == MODE_TT || Mode == MODE_TL){                            //Transient Modes
  setControlCurrent = (setCurrent * 1000) * setCurrentCalibrationFactor;
  controlVoltage = setControlCurrent; 
  }

}

//-------------------------------------Battery Capacity Discharge Routine----------------------------------------------------
void batteryCapacityloop (void) {
  if (Mode == MODE_BC){
    setCurrent = reading*1000;                             //set current is equal to input value in Amps
    setReading = setCurrent;                               //show the set current reading being used
    setControlCurrent = setCurrent * setCurrentCalibrationFactor;
    controlVoltage = setControlCurrent;
    memcpy(line3,(char*)timer.getTime().c_str(),8);
    Seconds = timer.getTotalSeconds();                     //get totals seconds
  
    LoadCurrent = ActualCurrent;                           //if timer still running use present Actual Current reading
    if (timer.status() == 2){                              //if timer is halted then use last Actual Current reading before timer stopped
      LoadCurrent = BatteryCurrent;
      }
 
    BatteryLife = (LoadCurrent*1000)*(Seconds/3600);       //calculate battery capacity in mAh
    BatteryLife = round(BatteryLife);

    if(BatteryLife >= BatteryLifePrevious){                //only update LCD (mAh) if BatteryLife has increased
  
      if (BatteryLife < 10) {                              //add a 3 leading zero to display if reading less than 10

        memcpy(line3+9,"000",3);
        memcpy(line3+12,(char*)String(BatteryLife).c_str(),1);
      }
      else if (BatteryLife >= 10 && BatteryLife <100){          //add a 2 leading zero to display
        memcpy(line3+9,"00",2);
        memcpy(line3+11,(char*)String(BatteryLife).c_str(),2);
      }
      else if (BatteryLife >= 100 && BatteryLife <1000){        //add a 1 leading zero to display
        memcpy(line3+9,"0",1);
        memcpy(line3+10,(char*)String(BatteryLife).c_str(),3);      
      }
      else {
        memcpy(line3+9,(char*)String(BatteryLife).c_str(),4);   
      }

    memcpy(line3+13,"mAh",3);
    print_chars2(3,20);
    BatteryLifePrevious = BatteryLife;                      //update displayed battery capacity on LCD
    } 
  }


  if (Mode == MODE_BC && ActualVoltage <= BatteryCutoffVolts){ //stops clock if battery reached cutoff level and switch load off
    BatteryCurrent = ActualCurrent;
    setVoltage(0,false);                                  //reset DAC to zero for no output current set at switch on                                             
    toggle = false;                                           //Load is toggled OFF
    color_load(0);
    timer.stop();
  }

  if (Mode == MODE_BC && Load == 1){                       //Routine used for data logging in Battery Capacity Mode
    if (Seconds != SecondsLog){                       //only send serial data if time has changed
      SecondsLog = Seconds;
      Serial.print (SecondsLog);                    //sends serial data of time in seconds
      Serial.print (",");                             //sends a comma as delimiter for logged data
      Serial.println (ActualVoltage);                   //sends serial data of Voltage reading         
    }
  }

}

//--------------------------------------------------Fan Control----------------------------------------------------------
void fanControl (void) {
  temp = analogRead(temperature);
  temp = temp * 0.107421875/2;                                // convert to Celsius
  
  if (temp >= 40){                                        //if temperature 40 degree C or above turn fan on.
    digitalWrite(fan, HIGH); 
  }  else {
    digitalWrite(fan, LOW);                               //otherwise turn fan turned off
  }
  
  memcpy(temperature_val,(char*)String(temp).c_str(),2);
  temperature_val[2]=0xB0;
  temperature_val[3]='C';
  temperature_val[4]=0x00;
  print_temp();

}

  
//-----------------------Toggle Current Load ON or OFF------------------------------
void LoadSwitch(void) {
  
  delay(200);                                              //simple key bounce delay 
 
    if(toggle)
    {
      color_load(0);

      color_load(0);
      current_instruction = 0;                            //reset current instruction for Transient List Mode to zero
      last_time = 0;                                      //reset last time to zero
      transientPeriod = 0;                                //reset transient period time to zero
      setCurrent = 0;                                     //reset setCurrent to zero
      toggle = !toggle;
      Load = 0;        
    }
    else
    {
      print_chars(3,0,(char*)"                    ",20);
      color_load(1);
      toggle = !toggle;
      Load = 1;
    }
}

//-----------------------Select Constant Current LCD set up--------------------------------
void Current(void) {
  Mode = MODE_CC;
  memcpy(line0,(char*)"DC LOAD ",8);
  print_chars2(0,20);
  writeNum2("t0.xcen",(uint16_t) 0);
  print_chars(2,0,(char*)"Set I =            A",20);
  memset(line3,' ',20);
  print_chars2(3,20);
  CP = 9;                                            //sets cursor starting position to units.
  setmode() ; 
}

//----------------------Select Constant Power LCD set up------------------------------------
void Power(void) {
  Mode = MODE_CP;
  writeNum2("t0.xcen",(int) 0);
  memcpy(line0,(char*)"DC LOAD ",7);
  print_chars2(0,20);
  print_chars(2,0,(char*)"Set W =            W",22);
  memset(line3,' ',20);
  print_chars2(3,20);
  CP = 10;                                             //sets cursor starting position to units.
  setmode() ;    
}

//----------------------- Select Constant Resistance LCD set up---------------------------------------
void Resistance(void) {
  Mode = MODE_CR;
  writeNum2("t0.xcen",(int) 0);
  memcpy(line0,(char*)"DC LOAD ",8);
  print_chars2(0,20);
  print_chars(2,0,(char*)"Set R =            R",20);
  memset(line3,' ',20);
  print_chars2(3,20);
  CP = 10;                                             //sets cursor starting position to units.
  setmode() ;
                                          //sets cursor starting position to units.
}

//----------------------- Select Battery Capacity Testing LCD set up---------------------------------------
void BatteryCapacity(void) {
  Mode = MODE_BC;

  writeNum2("t0.xcen",0);
  print_chars(0,0,(char*)"BATTERY             ",20);
  print_chars(2,0,(char*)"Set I =            A",20);
  memset(line3,' ',20);
  print_chars2(3,20);
  CP = 9;                                             //sets cursor starting position to units.
  setmode() ;  
}

//----------------------Battery Type Selection Routine------------------------------------------------
void batteryType (void) {
  exitMode = 0;                                         //reset EXIT mode

  screen_clear(' ');
  print_chars(0,0,(char*)"Select Battery Type",19);  
  print_chars(1,0,(char*)"1=LiPo/Li-Ion 2=LiFe",20);
  print_chars(2,0,(char*)"3=NiCd/NiMH   4=ZiZn",20);
  print_chars(3,0,(char*)"5=Set Voltage 6=Exit",20);                 
  customKey='\0';
  wait_for_key(true);               //stop everything till the user press a key.

  if (customKey == '1'){
    BatteryCutoffVolts = LiPoCutOffVoltage;
    BatteryType = ("LiPo");
  }

  if (customKey == '2'){
    BatteryCutoffVolts = LiFeCutOffVoltage;
    BatteryType = ("LiFe");
  }

  if (customKey == '3'){
    BatteryCutoffVolts = NiCdCutOffVoltage;
    BatteryType = ("NiCd");  
  }

  if (customKey == '4'){
    BatteryCutoffVolts = ZiZnCutOffVoltage;
    BatteryType = ("ZiZn"); 
  }

  if (customKey == '5'){ 
    BatteryType = ("SetV");
  }

  if (customKey == '6'){                                  //Exit selection screen
    exitMode = 1;
  }

  if (customKey == '7' || customKey == '8' || customKey == '9' || customKey == '0' || customKey == 'A' || customKey == 'B' || customKey == 'C' || customKey == 'D' || customKey == '*' || customKey == '#' || customKey == 'E' || customKey == 'F' || customKey == '<' || customKey == '>' ){
    batteryType();                                                      //ignore other keys
  }

  if(BatteryType == "SetV" && exitMode != 1){
    setBatteryCutOff();
  }

  batteryTypeSelected();                                    //briefly display battery type selected and discharge cut off voltage
  customKey=0x00;
  screen_clear(' ');

}

//--------------------------Set DAC Voltage--------------------------------------------
void dacControl (void) {
  if (!toggle){
  setVoltage(0,false);                                 //set DAC output voltage to 0 if Load Off selected
    if(Mode == MODE_BC && ActualVoltage >= BatteryCutoffVolts && timer.status() == 1){
    timer.stop();
    }
  
  }else{
  //Serial.println("Control Voltage");                    //used for testing only
  //Serial.println(controlVoltage);                       //used for testing only
  setVoltage(controlVoltage,false);                   //set DAC output voltage for Range selected
    if(Mode == MODE_BC && ActualVoltage >= BatteryCutoffVolts && timer.status() != 1){
    timer.start();
    }
  }
}

//--------------------------Battery Selected Information--------------------------------------------
void batteryTypeSelected (void) {
  char buff[6];
  if (exitMode != 1){                                      //if battery selection was EXIT then skip this routine
    screen_clear(' ');
    memcpy(line0+2,"Battery Selected",16);
    memcpy(line1+8,(char *)BatteryType.c_str(),4);
    memcpy(line2+2,"Discharge Cutoff",16);
    dtostrf(BatteryCutoffVolts, 4, 2, buff);
    memcpy(line3+6,buff,4);
    memcpy(line3+11," volts",6);
    print_chars2(0,21);
    print_chars2(1,21);
    print_chars2(2,21);
    print_chars2(3,21);                                
    delay(2000);
  }
}

//--------------------------Set Battery Cut-Off Voltage--------------------------------------------
void setBatteryCutOff (void) {

  screen_clear(' ');
  print_chars(0,4,(char*)"Enter Battery",14);  
  print_chars(1,3,(char*)"Cut-Off Voltage",16); 
  y = 8;
  z = 8;
  inputValue(2);
  BatteryCutoffVolts = x;
  screen_clear(' ');
}
void wait_for_key(bool wait){

  bool waiting = true;

  while (customKey==0x00 && (waiting)){  
    waiting = wait;
    delay(10);
    while (customKey==0x00 ){   
        serialEvent();
        
    }
  }
}
//------------------------Key input used for Battery Cut-Off and Transient Mode------------------------
void inputValue (int r=0){
 
 while(customKey != 'F'){               //check if enter pressed (was previously #)
   customKey=0x00; 
   wait_for_key(true);
  if(customKey >= '0' && customKey <= '9'){               //check for keypad number input
       numbers[index++] = customKey;
       numbers[index] = '\0';
       print_char(r,z,customKey);
       z = z+1;
     }
  
  if(customKey == '>'){                                   //Decimal point
      if (decimalPoint != ('>')){                         //test if decimal point entered twice - if so ski
      numbers[index++] = '.';
      numbers[index] = 0x00;
      print_char(r,z,'.');
      z = z+1;
      decimalPoint = ('>');                               //used to indicate decimal point has been input
        }
      }

 if(customKey == '<'){                                    //clear entry
    index = 0;
    z = y;

    numbers[index] = 0x00; 
                                   //
    print_chars(r,z,(char *)"     ",5);
    decimalPoint = (' ');                                 //clear decimal point test character reset
  }

 }
 
  if(customKey == 'F') {                                  //enter value 
    x = atof(numbers);     
    index = 0;
    numbers[index] = 0x00;
    decimalPoint = (' ');                                 //clear decimal point test character reset
  }
  customKey=0x00;
}

//----------------------------------------Transient Mode--------------------------------------------
void transientMode (void) {

  if(Mode != MODE_TL){
    char buff[6];
    y = 11;
    z = 11;
    screen_clear(' ');
    print_chars(0,4,(char*)"Transient Mode",15); 
    memcpy(line1,(char *)"Set Low  I=",11);
    memcpy(line1+19,(char *)"A " ,2);
    print_chars2(1,0); 
    inputValue(1);
    
    if(x >= CurrentCutOff){
      LowCurrent = CurrentCutOff;
    }else{
      LowCurrent = x;
    }

    r++;
    dtostrf(LowCurrent, 5, 3, buff);
    print_chars(r,11,buff,5); 

    customKey = 0x00;

    z = 11;
    memcpy(line2,(char *)"Set High I=",11);
    memcpy(line2+19,(char *)"A " ,2);
    print_chars2(2,0); 
    inputValue(2);
    if(x >= CurrentCutOff){
      HighCurrent = CurrentCutOff;
    }else{
      HighCurrent = x;
    }
    r++;
    dtostrf(HighCurrent, 5, 3, buff);
    print_chars(r,11,buff,5); 

    customKey = 0x00;

    if(Mode == MODE_TC || Mode == MODE_TP){
      z = 11;
      memcpy(line3,(char *)"Set Time  =",11);
      memcpy(line3+16,(char *)"mSec " ,5);
      print_chars2(3,0); 
      inputValue(3);
      transientPeriod = x;
      r++;
      dtostrf(transientPeriod, 5, 0, buff);
      print_chars(r,11,buff,5); 

    }else{

      memset(line3,' ',20);
      print_chars2(3,0);
    }

    screen_clear(' ');

    toggle = false;                                           //switch Load OFF
    memset(line0,' ',18);
    color_load(0);
  }else{  
    transientListSetup();
    screen_clear(' ');
    toggle = false;                                           //switch Load OFF
    color_load(0);
  }
}

//----------------------------------------Transient Type Selection--------------------------------------------
void transientType (void) {
  toggle = false;                                         //switch Load OFF
  exitMode = 0;                                           //reset EXIT mode
  screen_clear(' ');
  writeNum2("t0.xcen",(int) 0);                                 //print SCULLCOM to display with 5 leading spaces (you can change to your own)
  memcpy(line0,(char*)"Transient Mode",15);
  print_chars2(0,0);
  memcpy(line1,(char*)"1 = Continuous",15);
  print_chars2(1,0);
  memcpy(line2,(char*)"2 = Toggle",10);
  memcpy(line2+11,(char*)"3 = Pulse",9);
  print_chars2(2,0);
  memcpy(line3,(char*)"4 = List",8);
  memcpy(line3+11,(char*)"5 = Exit",9);
  print_chars2(3,0);

  wait_for_key(1);                 //stop everything till the user press a key.

  if (customKey == '1'){
    Mode = MODE_TC; 
  }

  if (customKey == '2'){
    Mode = MODE_TT;
  }

  if (customKey == '3'){
    Mode = MODE_TP;  
  }

  if (customKey == '4'){
    Mode = MODE_TL;  
  }

  if (customKey == '5'){                                  //Exit selection screen
    exitMode = 1;
  }

  if (customKey == '6' || customKey == '7' || customKey == '8' || customKey == '9' || customKey == '0' || customKey == 'A' || customKey == 'B' || customKey == 'C' || customKey == 'D' || customKey == '*' || customKey == '#' || customKey == 'E' || customKey == 'F' || customKey == '<' || customKey == '>' ){
    transientType();                                                      //ignore other keys
  }
screen_clear(' ');
customKey=0x00;
if (exitMode == 1){                                       //if NO Transient Mode type selected revert to CC Mode
    color_load(0);
    Current();                                            //if selected go to Constant Current Selected routine
    encoderPosition = 0;                                  //reset encoder reading to zero
    customKey = 'A';
      }else{
    transientMode();
      }
 }
 
//----------------------------------------Transient--------------------------------------------
void transient (void) {
  char buff[6]={0x00};
  if(Mode ==  MODE_TC || Mode ==  MODE_TP || Mode ==  MODE_TT || Mode ==  MODE_TL){
    memcpy(line0,(char*)"DC LOAD ",8);
    print_chars2(0,20);
    if(Mode != MODE_TL){
      memcpy(line2,"Lo=     A  Hi=     A",20);
      dtostrf(LowCurrent, 4, 3, buff);
      memcpy(line2+3,buff ,5);
      dtostrf(HighCurrent, 4, 3, buff);
      memcpy(line2+14,buff ,5);
      
    }else{
      memcpy(line2,"Set I =            A",20);
      dtostrf(transientList[current_instruction][0], 4, 3, buff);
      memcpy(line2+8,buff ,5);
    }


    if(Mode == MODE_TC || Mode == MODE_TP || Mode == MODE_TL){
      memcpy(line3,"Time =       mSecs   ",20);
      dtostrf(transientPeriod, 5, 0, buff);
      memcpy(line3+7,buff,5);
    }else{
      memcpy(line3,"  ",2);
     
    }
    print_chars2(2,20);
    print_chars2(3,20);
  }
delay(1);
}

//-------------------------------------Transcient List Setup-------------------------------------------
void transientListSetup(){

  screen_clear(' ');
  writeNum2("t0.xcen",(int) 0);                                 //print SCULLCOM to display with 5 leading spaces (you can change to your own)
  memcpy(line0,(char*)"Setup Transient List",21);
  print_chars2(0,0);
  memcpy(line1,(char*)"Enter Number in List",21);
  print_chars2(1,0);
  memcpy(line2,(char*)"(between 2 to 10 max",21);
  print_chars2(2,0);
  y = 0;
  z = 0;
  inputValue(3);
  total_instructions = int(x-1);
  customKey = 0x00;
  //lcd.clear();
  char buff[5] = {0x00};
    for(int i=0; i<=(total_instructions); i++){
      screen_clear(' ');
      memcpy(line0,"Set Current     ",16);
      int length = snprintf( NULL, 0, "%d", i+1 );
      itoa(i+1 ,buff,10);
      memcpy(line0+12,buff,length);
      memcpy(line1,"               A",16);
      print_chars2(0,0);
      print_chars2(1,0);

      y = 0;
      z = 0;
      inputValue(1);            //get the users input value
      transientList[i][0] = x; //store the users entered value in the transient list 
      customKey = 0x00;
      memcpy(line2,"Set Time        ",16);
      length = snprintf( NULL, 0, "%d", i+1 );
      itoa(i+1 ,buff,10);
      
      memcpy(line2+12,buff,length);
      memcpy(line3,"               mSec",19);
      print_chars2(2,0);
      print_chars2(3,0);
      y = 0;
      z = 0;
      inputValue(3);            //get the users input value
      transientList[i][1] = x; //store the users entered value in the transient list
      customKey = 0x00;
      screen_clear(' ');  
  }
  current_instruction = 0;      //start at first instrution
}

//-------------------------------------Transcient Load Toggel-------------------------------------------
void transientLoadToggle(){

  if(Mode == MODE_TC){
  current_time = micros();                              //get the current time in micro seconds()
  if (last_time == 0){
    last_time = current_time;
  } else {
    switch (transient_mode_status){
      case (false):
          // we are in the low current setting
          if ((current_time - last_time) >= (transientPeriod * 1000.0)){
             transientSwitch(LowCurrent, true);  
          }
        break;
      case (true):
          // we are in the high current setting 
          if ((current_time - last_time) >= (transientPeriod * 1000.0)){
            transientSwitch(HighCurrent, true);            
          }
        break; 
      } 
     }
    }


  if(Mode == MODE_TP){
    current_time = micros();                            //get the current time in micro seconds()
    if (last_time == 0){
        last_time = current_time;
        transientSwitch(LowCurrent, true);
    }
    if (digitalRead(TriggerPulse) == LOW){
      // a trigger pluse is received
      // set to the high current
      transientSwitch(HighCurrent, true); 
    } else {
        if ((current_time - last_time) >= (transientPeriod * 1000.0)){
            transientSwitch(LowCurrent, true);            
        }
      }  
  }


 if(Mode == MODE_TT){          // this function will toggle between high and low current when the trigger pin is taken low
  if (digitalRead(TriggerPulse) == LOW){
    switch (transient_mode_status){
      case (false):
        transientSwitch(LowCurrent, true);
        delay(200);         //added to prevent key bounce when transient button used (date of addition 31-03-2018)
        break;
      case (true):
        transientSwitch(HighCurrent, true);
        delay(200);         //added to prevent key bounce when transient button used (date of addition 31-03-2018)   
        break;
      }
    }
  }


if(Mode == MODE_TL){
  if (Load == 1){                                                 //Only perform Transient List if Load is ON
   current_time = micros();                                       //get the current time in micro seconds()
    if (last_time == 0){
      last_time = current_time;
      transientPeriod = transientList[current_instruction][1];    //Time data for LCD display
      transientSwitch(transientList[current_instruction][0], false);
    }
    if((current_time - last_time) >= transientList[current_instruction][1] * 1000){     //move to next list instruction
        current_instruction++;
        if(current_instruction > total_instructions){
          current_instruction = 0;
        }
      transientPeriod = transientList[current_instruction][1];   //Time data for LCD display
      transientSwitch(transientList[current_instruction][0], false);
      }
    }
  }

}

//-------------------------------------Transcient Switch-------------------------------------------
void transientSwitch(float current_setting, boolean toggle_status){
  if (toggle_status){
  transient_mode_status = !transient_mode_status;
  }
  setCurrent = current_setting;
  //Serial.print("set current = ");                     //used for testing only
  //Serial.println(setCurrent);                         //used for testing only
  last_time = current_time;
}

//-------------------------------------User set up for limits-------------------------------------------------
void userSetUp (void) {
  y = 14;
  z = 15;
  
  writeNum2("t0.xcen",(int) 1);   
  writeNum2("t1.xcen",(int) 0);   
  writeNum2("t2.xcen",(int) 0);   
  writeNum2("t3.xcen",(int) 0);   

  memcpy(line0,"User Set-Up         ",21);
  print_chars2(0,20);
  memset(line2,' ',20);
  print_chars2(2,20);
  memset(line3,' ',20);
  print_chars2(3,20);
  memcpy(line1,"Current Limit=     A",21);
  print_chars2(1,20);

  inputValue(1);
  CurrentCutOff = x;
  EEPROM.write(0x00, CurrentCutOff);
  
  customKey = 0x00;
  z = 15;
  memcpy(line2,"Power Limit =      W",21);
  print_chars2(2,20);
  inputValue(2);
  PowerCutOff = x;
  EEPROM.write(0x20, PowerCutOff);        

  customKey = 0x00;
  z = 15;
  line3[18]=0xB0;
  memcpy(line3,"Temp. Limit =      C",21);
  print_chars2(3,20);
  inputValue(3);
  z = 1;
  tempCutOff = x;

  EEPROM.write(0x40, tempCutOff);

    writeNum2("t0.xcen",(int) 0);   
    screen_clear(' ');
    color_load(0);
    Current();                                            //if selected go to Constant Current Selected routine
    encoderPosition = 0;                                  //reset encoder reading to zero
    customKey = 'A';
}

//------------------------------------------High Temperature Cut-Off--------------------------------------------------------------
void temperatureCutOff (void){
  if (temp >= tempCutOff){                                 //if Maximum temperature is exceeded
  reading = 0;
  encoderPosition = 0; 
  memcpy(line3,"Over Temperature    ",20);
  print_chars2(3,20);
  color_load(0);
  toggle = false;                                         //switch Load Off
  }
}

//-----------------------------------------Current Read Calibration for LCD Display --------------------------------------------
void currentDisplayCal (void){

  if(ActualCurrent <= 0){
    ActualCurrent = 0;
  }else if(Load == 0){
    ActualCurrent = 0;
  }else{
  ActualCurrent = ActualCurrent + displayCurrentCal;
  }

/*  if (ActualCurrent <= 0.5)
    {
    ActualCurrent = (ActualCurrent +(displayCurrentCal * 3));
    }
    else if (ActualCurrent >= 0.5 && ActualCurrent <1.0)
    {
    ActualCurrent = (ActualCurrent + (displayCurrentCal * 2));
    }
    else if (ActualCurrent >= 1.0 && ActualCurrent <= 1.4)
    {
    ActualCurrent = (ActualCurrent + (displayCurrentCal));
    }
    else 
    {
    ActualCurrent = ActualCurrent;
    }
*/
}
  
//-----------------------------Show limits Stored Data for Current, Power and Temp-----------------------------
void setupLimits (void){
  screen_clear(' ');
  writeNum2("t0.xcen",(int) 1); 
  writeNum2("t1.xcen",(int) 0); 
  writeNum2("t2.xcen",(int) 0); 
  writeNum2("t3.xcen",(int) 0); 
  memcpy(line0," Maximum Limits Set ",20);
  print_chars2(0,20);
  char snum[5];
  memcpy(line1,"Current Limit=    A ",20);
  CurrentCutOff = EEPROM.read(0x00);
  int length = snprintf( NULL, 0, "%d", CurrentCutOff  );

  itoa(CurrentCutOff, snum, 10);
  memcpy(line1+15,snum,length);
  print_chars2(1,20);

  memcpy(line2,"Power Limit  =    W ",20);
  PowerCutOff = EEPROM.read(0x20);
  length = snprintf( NULL, 0, "%d", PowerCutOff );
  itoa(PowerCutOff, snum, 10);
  memcpy(line2+15,snum,length);
  print_chars2(2,20);

  memcpy(line3,"Temp. Limit  =    C ",20);
  tempCutOff = EEPROM.read(0x40);
  length = snprintf( NULL, 0, "%d", tempCutOff );
  itoa(tempCutOff, snum, 10);
  memcpy(line3+15,snum,length);
  print_chars2(3,20);


  }

  //---------------------------------------------------------------------------------------------------------
