#include <Arduino.h>

#include <Servo.h>

/*
   Copyright Sergio Daniel Castañeda Niño 2017

   PLC Arduino Firmware UNO V1.2
*/

#include <EEPROM.h>
#include <math.h>

bool iState[8]= {false, false, false, false, false, false, false, false}; //0-7
bool oState[8]= {false, false, false, false, false, false, false, false};
bool vState[32]= {false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false}; //0-31

bool iAnalog[6] = {false, false, false, false, false, false};
bool oAnalog[5] = {false, false, false, false, false};

bool iPreState[8]= {false, false, false, false, false, false, false, false};
bool oPreState[8]= {false, false, false, false, false, false, false, false};
bool vPreState[32]= {false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false}; //0-31

bool iMask[8]= {false, false, false, false, false, false, false, false}; //0-7
bool oMask[8]= {false, false, false, false, false, false, false, false};
bool vMask[32]= {false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false}; //0-31

bool iUpEdge[8]= {false, false, false, false, false, false, false, false};
bool oUpEdge[8]= {false, false, false, false, false, false, false, false};
bool vUpEdge[32]= {false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false}; //0-31

bool iDownEdge[8]= {false, false, false, false, false, false, false, false};
bool oDownEdge[8]= {false, false, false, false, false, false, false, false};
bool vDownEdge[32]= {false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false}; //0-31


double doubleVariables[16];
short intVariables[16];
int dintVariables[16];

int16_t intValues[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int32_t dintValues[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
float realValues[8]  = {0,0,0,0,0,0,0,0};

uint8_t iPins[8] = {A0, A1, A2, A3, A4, A5, 2, 3}; //INPUT pins
uint8_t oPins[8] = {4, 5, 6, 7, 8, 9, 10, 11};     //OUTPUT pins

int8_t analogOutputs[8] = {0,0,0,0,0,0,0,0};
bool servoOutput[8] = {false, false, false, false, false, false, false, false};

typedef union{
  float val;
  uint8_t bytes[4];
} floatValue;

struct Counter{
  uint8_t no;
  uint8_t reset;
  bool dn;
  bool dnNull;
  bool countNo;
  bool resetNo;
  bool countUp;
  bool countUpNull;
  uint8_t noIndex;
  uint8_t resetIndex;
  uint8_t dnIndex;
  uint8_t countUpIndex;
  uint8_t presetIndex;
  uint8_t countIndex;
};

struct CounterCTUD{
  uint8_t no;
  uint8_t noDown;
  uint8_t reset;
  bool dn;
  bool dnNull;
  bool countNo;
  bool countNoDown;
  bool resetNo;
  bool countUp;
  bool countDown;
  bool countUpNull;
  bool countDownNull;
  uint8_t noIndex;
  uint8_t noDownIndex;
  uint8_t resetIndex;
  uint8_t dnIndex;
  uint8_t countUpIndex;
  uint8_t countDownIndex;
  uint8_t presetIndex;
  uint8_t countIndex;
};


struct Timer{
  uint8_t no;
  bool dn;
  bool dnNull;
  uint8_t reset;
  bool tt;
  bool enableNo;
  bool activeTimer;
  bool ttNull;
  bool timerDone;
  int typeTimer;
  uint8_t noIndex;
  uint8_t dnIndex;
  uint8_t ttIndex;
  uint8_t resetIndex;
  int8_t presetIndex;
  int8_t currentTimeIndex;
  unsigned long startTime;
  bool isPoint1;
};


unsigned long startTime;
unsigned long delta;
unsigned long targetTime;

unsigned long PC; //HERE
uint8_t n;
int mask = (0x3FFF);
bool A;
bool X;
bool Y;

bool notFlag;
bool risingFlag;
bool fallingFlag;
bool iFlag;
bool iFlag1;
bool oFlag1;
bool oFlag;
bool vFlag;
bool vFlag1;
bool vFlag2;
bool vFlag3;

bool latchFlag;
bool unlatchFlag;
bool coilFlag;
bool negateFlag;
bool timerFlag;
bool counterFlag;
bool counterCTUDFlag;

bool inFunction;

struct Counter myCounter[4];
struct CounterCTUD myCounterCTUD[4];
struct Timer myTimer[4];
char bufferSerial[128];
int buffSize;

Servo myServo0;
Servo myServo1;
Servo myServo2;
Servo myServo3;
Servo myServo4;

void reprogram();
void initProgram();
void interpreter();
void updateRegisters();
bool setDnCounter(int posi, bool dnState);
bool setDnCounterCTUD(int posi, bool dnState);
void cleanOldCounters(int tempCountCounter);
void cleanOldTimers(int tempCountTimer);
void blinking();
void checkVariablesDint();
int readAnalogPin(int index);
void writeAnalogPin(int index, int value);
int readAnalogOutput(int index);
void setDnValue(bool newState, int tempPC);
bool getNoValue();
float getSource();
void setDest(float valueDest);
int16_t getJoinValue();
bool isTagEnable(int tempPC);

void checkVariablesAOut();
void checkVariablesInt();
void checkVariablesDint();
void checkVariablesReal();
void readRawVariables();
bool isSourceInt();
int getOutIndex();
bool getUpEdgeActive();
void updateVariable(int tempPC, int32_t valueDest);
void setDest(int tempPC, float valueDest);

void equ();
void neq();
void les();
void leq();
void grt();
void geq();
void mov();
void lim();
void meq();
void andOp();
void orOp();
void notOp();
void xorOp();
void addOp();
void subOp();
void mulOp();
void divOp();
void xpy();
void absMath();
void sqrMath();
void cosMath();
void sinMath();
void tanMath();
void scp();

void bsl();
void bsr();

void setup() {
  pinMode(13, OUTPUT);

  for(int i=0; i<8; i++){       //pinMode for all the pins of the PLC UNO
    pinMode(iPins[i],INPUT);
    pinMode(oPins[i],OUTPUT);
  }

  Serial.begin(9600);

  //checkSpace();               //Uncomment this line to check the program size

  if(EEPROM.read(975)=='2'){
    initProgram();
    interpreter();
    updateRegisters();
  }

  reprogram();
  initProgram();
}

void loop() {
  // put your main code here, to run repeatedly:
  if(EEPROM.read(975)=='2'){
    digitalWrite(13, HIGH);

    while(true){

      interpreter();
      updateRegisters();

    }//END while

  }//END IF EEPROM.read
}//END loop()


void interpreter(){
  PC=0; //put the PC in the start of the memory
  int dataByte= EEPROM.read(PC);

  while(dataByte!='z'){ //z is the value that indicate that the program has ended

    if(inFunction){
      switch(dataByte){
        case 'a':
          equ();
        break;
        case 'b':
          neq();
        break;
        case 'c':
          les();
        break;
        case 'd':
          leq();
        break;
        case 'e':
          grt();
        break;
        case 'f':
          geq();
        break;
        case 'g':
          lim();
        break;
        case 'h':
          meq();
        break;
        case 'i':
          mov();
        break;
        case 'j':
          bsl();
        break;
        case 'k':
          bsr();
        break;
        case 'n':
          andOp();
        break;
        case 'o':
          orOp();
        break;
        case 'p':
          notOp();
        break;
        case 'q':
          xorOp();
        break;
        case 'r':
          addOp();
        break;
        case 's':
          subOp();
        break;
        case 't':
          mulOp();
        break;
        case 'u':
          divOp();
        break;
        case 'v':
          absMath();
        break;
        case 'w':
          sqrMath();
        break;
        case 'x':
          xpy();
        break;
        case 'B':
          cosMath();
        break;
        case 'E':
          sinMath();
        break;
        case 'F':
          tanMath();
        break;
        case 'G':
          scp();
        break;
        default:
          Serial.println("ERROR");
        break;

      }//END swith()
      inFunction = false;
    }
    else{
      switch(dataByte){
        case '$': //functions
          inFunction = true;
          break;
        case 'I': //i
          iFlag=true;
          break;
        case 'i':
          iFlag1 = true;
          break;
        case 'O': //o
          oFlag=true;
          break;
        case 'k':
          oFlag1 = true;
          break;
        case 'V': //v
          vFlag=true;
          break;
        case'v':
          vFlag1=true;
          break;
        case 'U': //v
          vFlag2=true;
          break;
        case'u':
          vFlag3=true;
          break;
        case 'L': //Latch
          latchFlag=true;
          break;
        case 'l': //Unlatch
          unlatchFlag=true;
          break;
        case '|': //or
          Y= Y | A;
          A = true;
          break;
        case '}': //and
          A=Y | A;
          Y=false;
          break;
        case '~': //not
          notFlag=true;
          break;
        case 'e': //RISING EDGE
          risingFlag=true;
          break;
        case 'f': //FALLING EDGE
          fallingFlag=true;
          break;
        case 'C': //coil
          coilFlag=true;
          break;
        case 'n': //negate coil
          negateFlag = true;
          break;
        case 'R': //rung
          A=true;
          Y=false;
          coilFlag = false;
          break;
        case 'q': //timer
          timerFlag=true;
          coilFlag = false;
          break;
        case 'B': //counter CTU
          counterFlag=true;
          coilFlag = false;
          break;
        case 'b': //counter CTUD
          counterCTUDFlag = true;
          coilFlag = false;
          break;
        default:
          dataByte = dataByte - 48;
          if((dataByte<15)&&(dataByte>=0)){  //posible to be changed

            n=dataByte;

            if(coilFlag){
              if(iFlag){
                iState[n]=A;
                iFlag=false;
              }

             else if(oFlag){
               if(latchFlag){
                 latchFlag=false;
                 if(A) oState[n]=true;

                }//END if(latchFlag)
                else if(unlatchFlag){
                  unlatchFlag=false;
                  if(A) oState[n]=false;
                }
                else if(negateFlag){
                  negateFlag=false;
                  if(A) oState[n]=false;
                  else oState[n]=true;
                }

                else if((!latchFlag) && (!unlatchFlag) && (!negateFlag)){
                  oState[n]=A;
                }
                oFlag=false;
              }

              else if(oFlag1){
                if(latchFlag){
                  latchFlag=false;
                  if(A) oState[10+n]=true;

                }//END if(latchFlag)
                else if(unlatchFlag){
                  unlatchFlag=false;
                  if(A) oState[10+n]=false;
                }
                else if(negateFlag){
                  negateFlag=false;
                  if(A) oState[10+n]=false;
                  else oState[10+n]=true;
                }

                else if((!latchFlag) && (!unlatchFlag) && (!negateFlag)){
                  oState[10+n]=A;
                }
                oFlag1=false;
              }

              else if(vFlag){
                if(latchFlag){
                  latchFlag=false;
                  if(A) vState[n]=true;

                }//END if(latchFlag)
                else if(unlatchFlag){
                  unlatchFlag=false;
                  if(A) vState[n]=false;
                }
                else if(negateFlag){
                  negateFlag=false;
                  if(A) vState[n]=false;
                  else vState[n]=true;
                }

                else if((!latchFlag) && (!unlatchFlag) && (!negateFlag)){
                  vState[n]=A;
                }
                vFlag=false;
              }

              else if(vFlag1){
                if(latchFlag){
                  latchFlag=false;
                  if(A) vState[10+n]=true;

                }//END if(latchFlag)
                else if(unlatchFlag){
                  unlatchFlag=false;
                  if(A) vState[10+n]=false;
                }
                else if(negateFlag){
                  negateFlag=false;
                  if(A) vState[10+n]=false;
                  else vState[10+n]=true;
                }

                else if((!latchFlag) && (!unlatchFlag) && (!negateFlag)){
                  vState[10+n]=A;
                }
                vFlag1 = false;
              }

              else if(vFlag2){
                if(latchFlag){
                  latchFlag=false;
                  if(A) vState[20+n]=true;

                }//END if(latchFlag)
                else if(unlatchFlag){
                  unlatchFlag=false;
                  if(A) vState[20+n]=false;
                }
                else if(negateFlag){
                  negateFlag=false;
                  if(A) vState[20+n]=false;
                  else vState[20+n]=true;
                }

                else if((!latchFlag) && (!unlatchFlag) && (!negateFlag)){
                  vState[20+n]=A;
                }
                vFlag2 = false;
              }

              else if(vFlag3){
                if(latchFlag){
                  latchFlag=false;
                  if(A) vState[30+n]=true;

                }//END if(latchFlag)
                else if(unlatchFlag){
                  unlatchFlag=false;
                  if(A) vState[30+n]=false;
                }
                else if(negateFlag){
                  negateFlag=false;
                  if(A) vState[30+n]=false;
                  else vState[30+n]=true;
                }

                else if((!latchFlag) && (!unlatchFlag) && (!negateFlag)){
                  vState[30+n]=A;
                }
                vFlag3 = false;
              }

              //coilFlag=false;
            }//END if(coilFlag)

            else if((!coilFlag)&&(!counterFlag)&&(!counterCTUDFlag)&&(!timerFlag)){

              if((iFlag)){
                if((notFlag) && (!risingFlag) && (!fallingFlag)){
                  if(iState[n]) X = false;
                  else  X = true;
                  //X = ~(iState[n]);
                  A = A & X;
                  notFlag=false;
                }//END IF (notFlag)
                else if((!notFlag) && (risingFlag) && (!fallingFlag)){
                  risingFlag = false;

                  if(iUpEdge[n]) X = true;
                  else  X = false;
                  A = A & X;
                }
                else if((!notFlag) && (!risingFlag) && (fallingFlag)){
                  fallingFlag = false;

                  if(iDownEdge[n]) X = true;
                  else  X = false;
                  A = A & X;
                }
                else if((!notFlag) && (!risingFlag) && (!fallingFlag)) {
                  A=(iState[n] & A);
                }
                iFlag=false;
              }//END if(iFlag)

              else if((iFlag1)){
                if(notFlag){
                  if(iState[10+n]) X = false;
                  else  X = true;
                  //X = ~(iState[10+n]);
                  A = A & X;
                  notFlag=false;
                }//END IF (notFlag)
                else if((!notFlag) && (risingFlag) && (!fallingFlag)){
                  risingFlag=false;

                  if(iUpEdge[10+n]) X = true;
                  else  X = false;
                  A = A & X;
                }
                else if((!notFlag) && (!risingFlag) && (fallingFlag)){
                  fallingFlag=false;

                  if(iDownEdge[10+n]) X = true;
                  else  X = false;
                  A = A & X;
                }
                else if((!notFlag) && (!risingFlag) && (!fallingFlag)) {
                  A=(iState[10+n] & A);
                }//END else
                iFlag1=false;
              }//END if(iFlag)

              else if((oFlag)){
                n=dataByte;
                if((notFlag) && (!risingFlag) && (!fallingFlag)){
                  if(oState[n]) X = false;
                  else  X = true;
                  //X = ~(oState[n]);
                  A = A & X;
                  notFlag=false;
                }//END IF (notFlag)
                else if((!notFlag)&&(risingFlag)&&(!fallingFlag)){
                  risingFlag = false;

                  if(oUpEdge[n]) X = true;
                  else X = false;
                  A = A & X;
                }
                else if((!notFlag)&&(!risingFlag)&&(fallingFlag)){
                  fallingFlag = false;

                  if(oDownEdge[n]) X = true;
                  else X = false;
                  A = A & X;
                }
                else if((!notFlag)&&(!risingFlag)&&(!fallingFlag)){
                  A=(oState[n] & A);
                }//END else
                oFlag=false;
              }//END if(oFlag)

              else if((oFlag1)){
                n=dataByte;
                if((notFlag) && (!risingFlag) && (!fallingFlag)){
                  if(oState[10+n]) X = false;
                  else  X = true;
                  //X = ~(oState[10+n]);
                  A = A & X;
                  notFlag=false;
                }//END IF (notFlag)
                else if((!notFlag)&&(risingFlag)&&(!fallingFlag)){
                  risingFlag = false;

                  if(oUpEdge[10+n]) X = true;
                  else X = false;
                  A = A & X;
                }
                else if((!notFlag)&&(!risingFlag)&&(fallingFlag)){
                  fallingFlag = false;

                  if(oDownEdge[10+n]) X = true;
                  else X = false;
                  A = A & X;
                }
                else if((!notFlag)&&(!risingFlag)&&(!fallingFlag)){
                  A=(oState[10+n] & A);
                }//END else
                oFlag1=false;
              }//END if(oFlag)



              else if((vFlag)){
                n=dataByte;
                if((notFlag) && (!risingFlag) && (!fallingFlag)){
                  if(vState[n]) X = false;
                  else  X = true;
                  A = A & X;
                  notFlag=false;
                }//END
                else if((!notFlag) && (risingFlag) && (!fallingFlag)){
                  risingFlag = false;

                  if(vUpEdge[n]) X = true;
                  else  X = false;
                  A = A & X;
                }
                else if((!notFlag) && (!risingFlag) && (fallingFlag)){
                  fallingFlag = false;

                  if(vDownEdge[n]) X = true;
                  else  X = false;
                  A = A & X;
                }
                else if((!notFlag) && (!risingFlag) && (!fallingFlag)) {
                  A=(vState[n] & A);
                }//END else
                vFlag=false;
              }//END if(vFlag)



              else if((vFlag1)){
                n=dataByte;
                if((notFlag) && (!risingFlag) && (!fallingFlag)){
                  if(vState[10+n]) X = false;
                  else  X = true;
                  A = A & X;
                  notFlag=false;
                }//END IF (notFlag)
                else if((!notFlag) && (risingFlag) && (!fallingFlag)){
                  risingFlag = false;

                  if(vUpEdge[10+n]) X = true;
                  else  X = false;
                  A = A & X;
                }
                else if((!notFlag) && (!risingFlag) && (fallingFlag)){
                  fallingFlag = false;

                  if(vDownEdge[10+n]) X = true;
                  else  X = false;
                  A = A & X;
                }
                else if((!notFlag) && (!risingFlag) && (!fallingFlag)) {
                  A=(vState[10+n] & A);
                }//END else
                vFlag1=false;
              }//END if(vFlag1)



              else if((vFlag2)){
                n=dataByte;
                if((notFlag) && (!risingFlag) && (!fallingFlag)){
                  if(vState[20+n]) X = false;
                  else  X = true;
                  A = A & X;
                  notFlag=false;
                }//END IF (notFlag)
                else if((!notFlag) && (risingFlag) && (!fallingFlag)){
                  risingFlag = false;

                  if(vUpEdge[20+n]) X = true;
                  else  X = false;
                  A = A & X;
                }
                else if((!notFlag) && (!risingFlag) && (fallingFlag)){
                  fallingFlag = false;

                  if(vDownEdge[20+n]) X = true;
                  else  X = false;
                  A = A & X;
                }
                else if((!notFlag) && (!risingFlag) && (!fallingFlag)) {
                  A=(vState[20+n] & A);
                }//END else
                vFlag2=false;
              }//END if(vFlag2)


              else if((vFlag3)){
                n=dataByte;
                if((notFlag) && (!risingFlag) && (!fallingFlag)){
                  if(vState[30+n]) X = false;
                  else  X = true;
                  A = A & X;
                  notFlag=false;
                }//END IF (notFlag)
                else if((!notFlag) && (risingFlag) && (!fallingFlag)){
                  risingFlag = false;

                  if(vUpEdge[30+n]) X = true;
                  else  X = false;
                  A = A & X;
                }
                else if((!notFlag) && (!risingFlag) && (fallingFlag)){
                  fallingFlag = false;

                  if(vDownEdge[30+n]) X = true;
                  else  X = false;
                  A = A & X;
                }
                else if((!notFlag) && (!risingFlag) && (!fallingFlag)) {
                  A=(vState[30+n] & A);
                }//END else
                vFlag3=false;
              }//END if(vFlag3)

            }//END else if(~cFlag)


            else if((!coilFlag)&&(counterFlag)&&(!counterCTUDFlag)&&(!timerFlag)){    //Counter Section CTU

              bool tempNo;
              bool tempReset;
              bool tempDn;

              switch(myCounter[n].no){
                case 0:
                  tempNo = vState[myCounter[n].noIndex];
                break;

                case 1:
                  tempNo = iState[myCounter[n].noIndex];
                break;

                case 2:
                  tempNo = oState[myCounter[n].noIndex];
                break;
              }

              switch(myCounter[n].reset){
                case 0:
                  tempReset = vState[myCounter[n].resetIndex];
                break;

                case 1:
                  tempReset = iState[myCounter[n].resetIndex];
                break;

                case 2:
                  tempReset = oState[myCounter[n].resetIndex];
                break;
              }

              if(myCounter[n].dn) tempDn = oState[myCounter[n].dnIndex];
              else tempDn = vState[myCounter[n].dnIndex];


              //PUT the same code of the PLC Ladder

              if((tempNo)&&(!tempReset)){

                if(!myCounter[n].resetNo){

                  if((tempNo)&&(!myCounter[n].countNo)){
                    dintValues[myCounter[n].countIndex]++;

                    myCounter[n].countNo = true;
                    bool returned = setDnCounter(n,tempDn);
                    if(!myCounter[n].dnNull){
                      if(myCounter[n].dn) oState[myCounter[n].dnIndex] = returned;
                      else vState[myCounter[n].dnIndex] = returned;
                    }

                    if(!myCounter[n].countUpNull){
                      if(myCounter[n].countUp)  oState[myCounter[n].countUpIndex] = true;
                      else  vState[myCounter[n].countUpIndex] = true;
                    }



                  }
                }//END if(!myCounter[n].resetNo)
              }//END if((tempNo)&&(!tempReset))

              else if((!tempNo)&&(myCounter[n].countNo))  {
                myCounter[n].countNo = false;

                if(!myCounter[n].countUpNull){
                  if(myCounter[n].countUp)  oState[myCounter[n].countUpIndex] = false;
                  else  vState[myCounter[n].countUpIndex] = false;
                }
              }

              if((tempReset)&&(!myCounter[n].resetNo)){
                myCounter[n].resetNo = true;
                bool returned = setDnCounter(n,tempDn);
                if(!myCounter[n].dnNull){
                  if(myCounter[n].dn) oState[myCounter[n].dnIndex] = returned;
                  else vState[myCounter[n].dnIndex] = returned;
                }
                dintValues[myCounter[n].countIndex] = 0;

                if(!myCounter[n].countUpNull){
                  if(myCounter[n].countUp)  oState[myCounter[n].countUpIndex] = false;
                  else  vState[myCounter[n].countUpIndex] = false;
                }
              }

              else if((!tempReset)&&(myCounter[n].resetNo)) {
                myCounter[n].resetNo = false;

              }


              counterFlag=false;


            }//END Counter Section

            else if((!coilFlag)&&(!counterFlag)&&(counterCTUDFlag)&&(!timerFlag)){    //Counter Section CTUD

              bool tempNo;
              bool tempReset;
              bool tempNoDown;
              bool tempDn;


              switch(myCounterCTUD[n].no){
                case 0:
                  tempNo = vState[myCounterCTUD[n].noIndex];
                break;

                case 1:
                  tempNo = iState[myCounterCTUD[n].noIndex];
                break;

                case 2:
                  tempNo = oState[myCounterCTUD[n].noIndex];
                break;
              }

             switch(myCounterCTUD[n].noDown){
                case 0:
                  tempNoDown = vState[myCounterCTUD[n].noDownIndex];
                break;

                case 1:
                  tempNoDown = iState[myCounterCTUD[n].noDownIndex];
                break;

                case 2:
                  tempNoDown = oState[myCounterCTUD[n].noDownIndex];
                break;
             }

              switch(myCounterCTUD[n].reset){
                case 0:
                  tempReset = vState[myCounterCTUD[n].resetIndex];
                break;

                case 1:
                  tempReset = iState[myCounterCTUD[n].resetIndex];
                break;

                case 2:
                  tempReset = oState[myCounterCTUD[n].resetIndex];
                break;
             }

              if(myCounterCTUD[n].dn) tempDn = oState[myCounterCTUD[n].dnIndex];
              else tempDn = vState[myCounterCTUD[n].dnIndex];


              //PUT the same code of the PLC Ladder

              if((tempNo)&&(!tempReset)){
                if(!myCounterCTUD[n].resetNo){
                  if((tempNo)&&(!myCounterCTUD[n].countNo)){

                      dintValues[myCounterCTUD[n].countIndex]++;
                      myCounterCTUD[n].countNo = true;
                      bool returned = setDnCounterCTUD(n,tempDn);
                      if(!myCounterCTUD[n].dnNull){
                        if(myCounterCTUD[n].dn) oState[myCounterCTUD[n].dnIndex] = returned;
                        else vState[myCounterCTUD[n].dnIndex] = returned;
                      }

                      if(!myCounterCTUD[n].countUpNull){
                        if(myCounterCTUD[n].countUp)  oState[myCounterCTUD[n].countUpIndex] = true;
                        else  vState[myCounterCTUD[n].countUpIndex] = true;
                      }

                  }
                }//END if(!myCounterCTUD[n].resetNo)
              }//END if((tempNo)&&(!tempReset))

              else if((!tempNo)&&(myCounterCTUD[n].countNo))  {
                myCounterCTUD[n].countNo = false;

                if(!myCounterCTUD[n].countUpNull){
                  if(myCounterCTUD[n].countUp)  oState[myCounterCTUD[n].countUpIndex] = false;
                  else  vState[myCounterCTUD[n].countUpIndex] = false;
                }
              }//END else if((!tempNo) && (myCounterCTUD[n].countNo)


              else if((tempNoDown) && (!tempReset)){
                if(!myCounterCTUD[n].resetNo){
                  if(!myCounterCTUD[n].countNoDown){

                    dintValues[myCounterCTUD[n].countIndex]--;
                    myCounterCTUD[n].countNoDown = true;
                    bool returned = setDnCounterCTUD(n,tempDn);
                    if(!myCounterCTUD[n].dnNull){
                      if(myCounterCTUD[n].dn) oState[myCounterCTUD[n].dnIndex] = returned;
                      else vState[myCounterCTUD[n].dnIndex] = returned;
                    }

                    if(!myCounterCTUD[n].countDownNull){
                      if(myCounterCTUD[n].countDown)  oState[myCounterCTUD[n].countDownIndex] = true;
                      else  vState[myCounterCTUD[n].countDownIndex] = true;
                    }

                  }//END if(!myCounterCTUD[n].countNoDown)
                }//END if(!myCounterCTUD[n].resetNo)
              }//END else if((tempNoDown) && (!tempReset))


              else if((!tempNoDown) && (myCounterCTUD[n].countNoDown)){
                myCounterCTUD[n].countNoDown = false;

                if(!myCounterCTUD[n].countDownNull){
                  if(myCounterCTUD[n].countDown)  oState[myCounterCTUD[n].countDownIndex] = false;
                  else  vState[myCounterCTUD[n].countDownIndex] = false;
                }
              }//END else if((!tempNoDown) && (myCounterCTUD[n].countNoDown))

              if((tempReset)&&(!myCounterCTUD[n].resetNo)){
                myCounterCTUD[n].resetNo = true;
                bool returned = setDnCounterCTUD(n,tempDn);
                if(!myCounterCTUD[n].dnNull){
                  if(myCounterCTUD[n].dn) oState[myCounterCTUD[n].dnIndex] = returned;
                  else vState[myCounterCTUD[n].dnIndex] = returned;
                }
                dintValues[myCounterCTUD[n].countIndex] = 0;

                if(!myCounterCTUD[n].countUpNull){
                  if(myCounterCTUD[n].countUp)  oState[myCounterCTUD[n].countUpIndex] = false;
                  else  vState[myCounterCTUD[n].countUpIndex] = false;
                }
              }

              else if((!tempReset)&&(myCounterCTUD[n].resetNo)) {
                myCounterCTUD[n].resetNo = false;

              }


              counterCTUDFlag=false;


            }//END Counter Section



            else if((!coilFlag)&&(!counterFlag)&&(!counterCTUDFlag)&&(timerFlag)){    //Timer Section

              bool tempNo;

              unsigned long tempTime;

              switch(myTimer[n].no){
                case 0:
                  tempNo = vState[myTimer[n].noIndex];
                break;

                case 1:
                  tempNo = iState[myTimer[n].noIndex];
                break;

                case 2:
                  tempNo = oState[myTimer[n].noIndex];
                break;
              }


              switch(myTimer[n].typeTimer){
                case 1:                                                           //TON
                    if(tempNo){
                      if(!myTimer[n].activeTimer){
                        myTimer[n].activeTimer = true;

                        if(!myTimer[n].ttNull){
                          if(myTimer[n].tt) oState[myTimer[n].ttIndex] = true;
                          else vState[myTimer[n].ttIndex] = true;
                        }

                        myTimer[n].startTime = millis();
                      }
                    }

                    else{
                      myTimer[n].activeTimer = false;


                      if(!myTimer[n].ttNull){
                        if(myTimer[n].tt) oState[myTimer[n].ttIndex] = false;
                        else vState[myTimer[n].ttIndex] = false;
                      }

                      if(!myTimer[n].dnNull){

                        if(myTimer[n].dn) oState[myTimer[n].dnIndex] = false;
                        else vState[myTimer[n].dnIndex] = false;

                        dintValues[myTimer[n].currentTimeIndex] = 0;

                      }
                    }

                    if(myTimer[n].activeTimer){
                      tempTime = millis();
                      tempTime = tempTime - myTimer[n].startTime;

                      dintValues[myTimer[n].currentTimeIndex] = (int32_t)(tempTime*(0.001f));

                      uint32_t tempPreset = 0;
                      if(myTimer[n].isPoint1)
                        tempPreset = (uint32_t)(((0.1)*(dintValues[myTimer[n].presetIndex]))*(1000L));
                      else
                        tempPreset = (uint32_t)((dintValues[myTimer[n].presetIndex])*(1000L));

                      if(tempTime >= tempPreset){
                        delay(20);

                        if(!myTimer[n].ttNull){
                          if(myTimer[n].tt) oState[myTimer[n].ttIndex] = false;
                          else vState[myTimer[n].ttIndex] = false;
                        }

                        if(!myTimer[n].dnNull){
                          if(myTimer[n].dn) oState[myTimer[n].dnIndex] = true;
                          else vState[myTimer[n].dnIndex] = true;
                        }
                      }
                    }
                  break;

                case 2:                                                                 //TOF
                        if(tempNo){
                          if(!myTimer[n].enableNo){
                            myTimer[n].enableNo = true;

                            if(!myTimer[n].ttNull){
                              if(myTimer[n].tt) oState[myTimer[n].ttIndex] = false;
                              else vState[myTimer[n].ttIndex] = false;
                            }

                            if(!myTimer[n].dnNull){
                              if(myTimer[n].dn) oState[myTimer[n].dnIndex] = true;
                              else vState[myTimer[n].dnIndex] = true;
                            }
                          }//END if(!myTimer[n].enableNo)

                          else  {
                            myTimer[n].activeTimer = false;
                            dintValues[myTimer[n].currentTimeIndex] = 0;
                          }
                        }//END if(tempNo

                        else{
                          if(myTimer[n].enableNo){
                            myTimer[n].enableNo = false;

                            if(!myTimer[n].ttNull){
                              if(myTimer[n].tt) oState[myTimer[n].ttIndex] = true;
                              else vState[myTimer[n].ttIndex] = true;
                            }

                            myTimer[n].activeTimer = true;
                            myTimer[n].startTime = millis();
                          }//END if(myTimer[n].enableNo)
                        }//END else

                        if(myTimer[n].activeTimer){
                          tempTime = millis();
                          tempTime = tempTime -myTimer[n].startTime;

                          dintValues[myTimer[n].currentTimeIndex] = (int32_t)(tempTime*(0.001f));

                          uint32_t tempPreset = 0;
                          if(myTimer[n].isPoint1)
                            tempPreset = (uint32_t)(((0.1)*(dintValues[myTimer[n].presetIndex]))*(1000L));
                          else
                            tempPreset = (uint32_t)((dintValues[myTimer[n].presetIndex])*(1000L));

                          if(tempTime >= tempPreset){
                            dintValues[myTimer[n].currentTimeIndex] = 0;
                            delay(20);
                            if(!myTimer[n].ttNull){
                              if(myTimer[n].tt) oState[myTimer[n].ttIndex] = false;
                              else vState[myTimer[n].ttIndex] = false;
                            }

                            if(!myTimer[n].dnNull){
                              if(myTimer[n].dn) oState[myTimer[n].dnIndex] = false;
                              else vState[myTimer[n].dnIndex] = false;
                            }

                            myTimer[n].activeTimer = false;
                          }//END if(tempTime >= myTimer[n].preset)

                        }//END if(myTimer[n].activeTimer)
                  break;


                  case 3:                                                                 //RTO

                    bool tempReset;

                    switch(myTimer[n].reset){
                      case 0:
                        tempReset = vState[myTimer[n].resetIndex];
                      break;

                      case 1:
                        tempReset = iState[myTimer[n].resetIndex];
                      break;

                      case 2:
                        tempReset = oState[myTimer[n].resetIndex];
                      break;
                    }


                    if(tempNo){
                      if((!myTimer[n].activeTimer)&&(!myTimer[n].timerDone)){
                        myTimer[n].activeTimer = true;

                        if(!myTimer[n].ttNull){
                          if(myTimer[n].tt) oState[myTimer[n].ttIndex] = true;
                          else vState[myTimer[n].ttIndex] = true;
                        }
                        myTimer[n].startTime = millis();
                      }
                    }//END if(tempNo)

                    else{
                      if(myTimer[n].activeTimer){
                        myTimer[n].activeTimer = false;

                        if(!myTimer[n].ttNull){
                          if(myTimer[n].tt) oState[myTimer[n].ttIndex] = false;
                          else vState[myTimer[n].ttIndex] = false;
                        }
                        long tempTime = millis();
                        int32_t tempValue = dintValues[myTimer[n].currentTimeIndex]*(1000L);
                        tempValue = tempValue + tempTime - myTimer[n].startTime;
                        dintValues[myTimer[n].currentTimeIndex] = (int32_t)tempValue*(0.001f);

                      }//END if(mytimer[n].activeTimer)


                    }//END else

                    if(tempReset){
                      myTimer[n].activeTimer = false;
                      myTimer[n].enableNo = false;

                      if(!myTimer[n].ttNull){
                          if(myTimer[n].tt) oState[myTimer[n].ttIndex] = false;
                          else vState[myTimer[n].ttIndex] = false;
                      }

                      if(!myTimer[n].dnNull){
                        if(myTimer[n].dn) oState[myTimer[n].dnIndex] = false;
                        else vState[myTimer[n].dnIndex] = false;
                      }

                      dintValues[myTimer[n].currentTimeIndex] = 0;
                      myTimer[n].timerDone = false;
                    }


                    if(myTimer[n].activeTimer){
                      tempTime = millis();
                      tempTime = tempTime - myTimer[n].startTime;
                      int32_t tempValue = dintValues[myTimer[n].currentTimeIndex]*(1000L);
                      tempTime += tempValue;

                      uint32_t tempPreset = 0;
                      if(myTimer[n].isPoint1)
                        tempPreset = (uint32_t)(((0.1)*(dintValues[myTimer[n].presetIndex]))*(1000L));
                      else
                        tempPreset = (uint32_t)((dintValues[myTimer[n].presetIndex])*(1000L));

                      if(tempTime >= tempPreset){

                        delay(20);
                        if(!myTimer[n].ttNull){
                          if(myTimer[n].tt) oState[myTimer[n].ttIndex] = false;
                          else vState[myTimer[n].ttIndex] = false;
                        }//END if(!myTimer[n].ttNull)

                        if(!myTimer[n].dnNull){
                          if(myTimer[n].dn) oState[myTimer[n].dnIndex] = true;
                          else vState[myTimer[n].dnIndex] = true;
                        }

                        myTimer[n].timerDone = true;

                      }//END if(tempTime >= myTimer[n].preset)
                    }//END if(myTimer[n].activeTimer)

                  break;


              }//END switch(myTimer[n].typeTimer)

              timerFlag = false;
            }//END Timer Section

          }//END if(dataByte<15)
      }//END Switch
    }//END ELSE !INFUNCTION

      PC++;
      dataByte= EEPROM.read(PC);

  }//END while(dataByte!=254)
  //Serial.println(" ");

}//END interpreter()

void updateRegisters(){
  for(int i = 0; i<8; i++){
    if(iMask[i]){           //input

      if((!iPreState[i]) && (iState[i]))
        iUpEdge[i] = true;
      else if((iPreState[i]) && (!iState[i]))
        iDownEdge[i] = true;
      else{
        iUpEdge[i] = false;
        iDownEdge[i] = false;
      }

      iPreState[i] = iState[i];
      iState[i]=digitalRead(iPins[i]);
    }

    if(oMask[i]){           //output

      if((!oPreState[i]) && (oState[i]))
        oUpEdge[i] = true;
      else if((oPreState[i]) && (!oState[i]))
        oDownEdge[i] = true;
      else{
        oUpEdge[i] = false;
        oDownEdge[i] = false;
      }

      oPreState[i] = oState[i];
      if(analogOutputs[i] == 0)
        digitalWrite(oPins[i], oState[i]);
    }
  }//END FOR input

  for(int i = 0; i<32; i++){
    if(vMask[i]){

      if((!vPreState[i]) && (vState[i]))
        vUpEdge[i] = true;
      else if((vPreState[i]) && (!vState[i]))
        vDownEdge[i] = true;
      else{
        vUpEdge[i] = false;
        vDownEdge[i] = false;
      }

      vPreState[i] = vState[i];
    }
  }
}//END updateRegisters()

void cleanOutputs(){
      for(int i=0; i<8; i++)
        digitalWrite(oPins[i], false);
  }


  //fOR THE EEPROM 255 = true, 0 = false
void initProgram(){
  if(EEPROM.read(975)=='2'){   //memory status flag

    cleanOutputs();

    digitalWrite(13, HIGH);

    for(int i = 0; i<8; i++){   // i/o variables mask
          int tempVar = EEPROM.read(976+i);//input
          if(tempVar == 126){
            iMask[i] = true;
          }

          tempVar = EEPROM.read(984+i); //output
          if(tempVar == 126){
            oMask[i] = true;
          }
    }//END FOR i/o mask

    for(int i = 0; i<32; i++){   //virtual variables mask
          int tempVar = EEPROM.read(992+i);
          if(tempVar == 126){
            vMask[i] = true;
          }
    }//END FOR virtual mask


    //INIT INT VARIABLES
    int tempPC = 674;
    int32_t tempA = 0;
    int32_t tempB = 0;
    int intIndex = 0;

    while(tempPC<706){
      tempA = EEPROM.read(tempPC);
      tempA = tempA << 8;
      tempPC++;

      tempA = tempA | EEPROM.read(tempPC);
      tempPC++;


      intValues[intIndex] = tempA;
      intIndex++;
    }

    //INIT DINT VARIABLES
    tempPC = 707;
    tempA = 0;
    tempB = 0;
    intIndex = 0;

    while(tempPC < 771){
      tempA = EEPROM.read(tempPC);
      tempA = ((int32_t)tempA) << 24;
      tempPC++;

      tempB = EEPROM.read(tempPC);
      tempB = ((int32_t)tempB) << 16;
      tempA = tempA | tempB;
      tempPC++;

      tempB = EEPROM.read(tempPC);
      tempB = ((int32_t)tempB) << 8;
      tempA = tempA |tempB;
      tempPC++;

      tempA = tempA | ((int32_t)EEPROM.read(tempPC));
      tempPC++;

      dintValues[intIndex] = tempA;
      intIndex++;
    }

    //INIT REAL VARIABLES
    tempPC = 772;
    tempA = 0;
    tempB = 0;
    intIndex = 0;

    floatValue tempFloat;
    while(tempPC < 804){
      tempFloat.bytes[3] = EEPROM.read(tempPC);
      tempPC++;

      tempFloat.bytes[2] = EEPROM.read(tempPC);
      tempPC++;

      tempFloat.bytes[1] = EEPROM.read(tempPC);
      tempPC++;

      tempFloat.bytes[0] = EEPROM.read(tempPC);
      tempPC++;

      realValues[intIndex] = tempFloat.val;
      intIndex++;
    }


    for(int i = 0; i<4; i++){   //Loading Counters 4 COUNTERS
      int tempMulti = 878 + (16*i);
      char tempCounterValue = EEPROM.read(tempMulti);

      if(tempCounterValue == 'B'){  //IF THE COUNTER IS ACTIVE  //CTU

        int tempFlag = EEPROM.read(tempMulti+1);
        if(tempFlag == 'I') {
          myCounter[i].no = 1;
          myCounter[i].noIndex = (EEPROM.read(tempMulti+2))-48;
        }
        else if(tempFlag == 'i'){
          myCounter[i].no = 1;
          myCounter[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
        }
        else if(tempFlag == 'O'){
          myCounter[i].no = 2;
          myCounter[i].noIndex = (EEPROM.read(tempMulti+2))-48;
        }
        else if(tempFlag == 'k'){
          myCounter[i].no = 2;
          myCounter[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
        }
        else{
          myCounter[i].no = 0;
          switch(tempFlag){
            case 'V':
                myCounter[i].noIndex = (EEPROM.read(tempMulti+2))-48;
              break;

            case 'v':
                myCounter[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
              break;

            case 'U':
                myCounter[i].noIndex = (EEPROM.read(tempMulti+2))-48+20;
              break;

            case 'u':
                myCounter[i].noIndex = (EEPROM.read(tempMulti+2))-48+30;
              break;
          }//END switch
        }


        tempFlag = EEPROM.read(tempMulti+3);
        if(tempFlag == 'I') {
          myCounter[i].reset = 1;
          myCounter[i].resetIndex = (EEPROM.read(tempMulti+4))-48;
        }
        else if(tempFlag == 'i'){
          myCounter[i].reset = 1;
          myCounter[i].resetIndex = (EEPROM.read(tempMulti+4))-48+10;
        }
        else if(tempFlag == 'O'){
          myCounter[i].reset = 2;
          myCounter[i].resetIndex = (EEPROM.read(tempMulti+4))-48;
        }
        else if(tempFlag == 'k'){
          myCounter[i].reset = 2;
          myCounter[i].resetIndex = (EEPROM.read(tempMulti+4))-48+10;
        }
        else {
          myCounter[i].reset = 0;
          switch(tempFlag){
            case 'V':
                myCounter[i].resetIndex = (EEPROM.read(tempMulti+4))-48;
              break;

            case 'v':
                myCounter[i].resetIndex = (EEPROM.read(tempMulti+4))-48+10;
              break;

            case 'U':
                myCounter[i].resetIndex = (EEPROM.read(tempMulti+4))-48+20;
              break;

            case 'u':
                myCounter[i].resetIndex = (EEPROM.read(tempMulti+4))-48+30;
              break;
          }//END switch
        }


        tempFlag = EEPROM.read(tempMulti+5);
        if(tempFlag == 's'){ //null
          myCounter[i].dnNull = true;
        }
        else{
          myCounter[i].dnNull = false;
          if(tempFlag == 'O') {
            myCounter[i].dn = true;
            myCounter[i].dnIndex = (EEPROM.read(tempMulti+6))-48;
          }
          else if(tempFlag == 'k'){
            myCounter[i].dn = true;
            myCounter[i].dnIndex = (EEPROM.read(tempMulti+6))-48+10;
          }
          else {
            myCounter[i].dn = false;
            switch(tempFlag){
              case 'V':
                  myCounter[i].dnIndex = (EEPROM.read(tempMulti+6))-48;
                break;

              case 'v':
                  myCounter[i].dnIndex = (EEPROM.read(tempMulti+6))-48+10;
                break;

              case 'U':
                  myCounter[i].dnIndex = (EEPROM.read(tempMulti+6))-48+20;
                break;

              case 'u':
                  myCounter[i].dnIndex = (EEPROM.read(tempMulti+6))-48+30;
                break;
            }//END switch
          }
        }//END else

        tempFlag = EEPROM.read(tempMulti+7);
        if(tempFlag == 's'){
          myCounter[i].countUpNull = true;
        }
        else{
          myCounter[i].countUpNull = false;
          if(tempFlag == 'O') {
            myCounter[i].countUp = true;
            myCounter[i].countUpIndex = (EEPROM.read(tempMulti+8))-48;
          }
          else if(tempFlag == 'k'){
            myCounter[i].countUp = true;
            myCounter[i].countUpIndex = (EEPROM.read(tempMulti+8))-48+10;
          }
          else {
            myCounter[i].countUp = false;
            switch(tempFlag){
              case 'V':
                  myCounter[i].countUpIndex = (EEPROM.read(tempMulti+8))-48;
                break;

              case 'v':
                  myCounter[i].countUpIndex = (EEPROM.read(tempMulti+8))-48+10;
                break;

              case 'U':
                  myCounter[i].countUpIndex = (EEPROM.read(tempMulti+8))-48+20;
                break;

              case 'u':
                  myCounter[i].countUpIndex = (EEPROM.read(tempMulti+8))-48+30;
                break;
            }//END switch
          }
        }//END else


        tempFlag = EEPROM.read(tempMulti+9);
        if(tempFlag == 'P'){
          myCounter[i].presetIndex = EEPROM.read(tempMulti+10);
          myCounter[i].countIndex = EEPROM.read(tempMulti+11);
          myCounter[i].countNo = false;
          myCounter[i].resetNo = false;
        }


      }//END if(244)


      else if(tempCounterValue == 'b'){                                               //CTUD

        int tempFlag = EEPROM.read(tempMulti+1);
        if(tempFlag == 'I') {
          myCounterCTUD[i].no = 1;
          myCounterCTUD[i].noIndex = (EEPROM.read(tempMulti+2))-48;
        }
        else if(tempFlag == 'i'){
          myCounterCTUD[i].no = 1;
          myCounterCTUD[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
        }
        else if(tempFlag == 'O'){
          myCounterCTUD[i].no = 2;
          myCounterCTUD[i].noIndex = (EEPROM.read(tempMulti+2))-48;
        }
        else if(tempFlag == 'k'){
          myCounterCTUD[i].no = 2;
          myCounterCTUD[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
        }
        else{
          myCounterCTUD[i].no = 0;
          switch(tempFlag){
            case 'V':
                myCounterCTUD[i].noIndex = (EEPROM.read(tempMulti+2))-48;
              break;

            case 'v':
                myCounterCTUD[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
              break;

            case 'U':
                myCounterCTUD[i].noIndex = (EEPROM.read(tempMulti+2))-48+20;
              break;

            case 'u':
                myCounterCTUD[i].noIndex = (EEPROM.read(tempMulti+2))-48+30;
              break;
          }//END switch
        }


        tempFlag = EEPROM.read(tempMulti+3);
        if(tempFlag == 'I') {
          myCounterCTUD[i].reset = 1;
          myCounterCTUD[i].resetIndex = (EEPROM.read(tempMulti+4))-48;
        }
        else if(tempFlag == 'i'){
          myCounterCTUD[i].reset = 1;
          myCounterCTUD[i].resetIndex = (EEPROM.read(tempMulti+4))-48+10;
        }
        else if(tempFlag == 'O'){
          myCounterCTUD[i].reset = 2;
          myCounterCTUD[i].resetIndex = (EEPROM.read(tempMulti+4))-48;
        }
        else if(tempFlag == 'k'){
          myCounterCTUD[i].reset = 2;
          myCounterCTUD[i].resetIndex = (EEPROM.read(tempMulti+4))-48+10;
        }
        else {
          myCounterCTUD[i].reset = 0;
          switch(tempFlag){
            case 'V':
                myCounterCTUD[i].resetIndex = (EEPROM.read(tempMulti+4))-48;
              break;

            case 'v':
                myCounterCTUD[i].resetIndex = (EEPROM.read(tempMulti+4))-48+10;
              break;

            case 'U':
                myCounterCTUD[i].resetIndex = (EEPROM.read(tempMulti+4))-48+20;
              break;

            case 'u':
                myCounterCTUD[i].resetIndex = (EEPROM.read(tempMulti+4))-48+30;
              break;
          }//END switch
        }


        tempFlag = EEPROM.read(tempMulti+5);
        if(tempFlag == 's'){
          myCounterCTUD[i].dnNull = true;
        }
        else{
          myCounterCTUD[i].dnNull = false;
          if(tempFlag == 'O') {
            myCounterCTUD[i].dn = true;
            myCounterCTUD[i].dnIndex = (EEPROM.read(tempMulti+6))-48;
          }
          else if(tempFlag == 'k'){
            myCounterCTUD[i].dn = true;
            myCounterCTUD[i].dnIndex = (EEPROM.read(tempMulti+6))-48+10;
          }
          else {
            myCounterCTUD[i].dn = false;
            switch(tempFlag){
              case 'V':
                  myCounterCTUD[i].dnIndex = (EEPROM.read(tempMulti+6))-48;
                break;

              case 'v':
                  myCounterCTUD[i].dnIndex = (EEPROM.read(tempMulti+6))-48+10;
                break;

              case 'U':
                  myCounterCTUD[i].dnIndex = (EEPROM.read(tempMulti+6))-48+20;
                break;

              case 'u':
                  myCounterCTUD[i].dnIndex = (EEPROM.read(tempMulti+6))-48+30;
                break;
            }//END switch
          }
        }//END else


        tempFlag = EEPROM.read(tempMulti+7);
        if(tempFlag == 's'){
          myCounterCTUD[i].countUpNull = true;
        }
        else{
          myCounterCTUD[i].countUpNull = false;
          if(tempFlag == 'O') {
            myCounterCTUD[i].countUp = true;
            myCounterCTUD[i].countUpIndex = (EEPROM.read(tempMulti+8))-48;
          }
          else if(tempFlag == 'k'){
            myCounterCTUD[i].countUp = true;
            myCounterCTUD[i].countUpIndex = (EEPROM.read(tempMulti+8))-48+10;
          }
          else {
            myCounterCTUD[i].countUp = false;
            switch(tempFlag){
              case 'V':
                  myCounterCTUD[i].countUpIndex = (EEPROM.read(tempMulti+8))-48;
                break;

              case 'v':
                  myCounterCTUD[i].countUpIndex = (EEPROM.read(tempMulti+8))-48+10;
                break;

              case 'U':
                  myCounterCTUD[i].countUpIndex = (EEPROM.read(tempMulti+8))-48+20;
                break;

              case 'u':
                  myCounterCTUD[i].countUpIndex = (EEPROM.read(tempMulti+8))-48+30;
                break;
            }//END switch
          }
        }//END else


        tempFlag = EEPROM.read(tempMulti+9);
        if(tempFlag == 'P'){
          myCounterCTUD[i].presetIndex = EEPROM.read(tempMulti+10);
          myCounterCTUD[i].countIndex = EEPROM.read(tempMulti+11);
          myCounterCTUD[i].countNo = false;
          myCounterCTUD[i].resetNo = false;
        }


        tempFlag = EEPROM.read(tempMulti+12);                                         //N.O. DOWN
        if(tempFlag == 'I') {
          myCounterCTUD[i].noDown = 1;
          myCounterCTUD[i].noDownIndex = (EEPROM.read(tempMulti+13))-48;
        }
        else if(tempFlag == 'i'){
          myCounterCTUD[i].noDown = 1;
          myCounterCTUD[i].noDownIndex = (EEPROM.read(tempMulti+13))-48+10;
        }
        else if(tempFlag == 'O'){
          myCounterCTUD[i].noDown = 2;
          myCounterCTUD[i].noDownIndex = (EEPROM.read(tempMulti+13))-48;
        }
        else if(tempFlag == 'k'){
          myCounterCTUD[i].noDown = 2;
          myCounterCTUD[i].noDownIndex = (EEPROM.read(tempMulti+13))-48+10;
        }
        else{
          myCounterCTUD[i].noDown = 0;
          switch(tempFlag){
            case 'V':
                myCounterCTUD[i].noDownIndex = (EEPROM.read(tempMulti+13))-48;
              break;

            case 'v':
                myCounterCTUD[i].noDownIndex = (EEPROM.read(tempMulti+13))-48+10;
              break;

            case 'U':
                myCounterCTUD[i].noDownIndex = (EEPROM.read(tempMulti+13))-48+20;
              break;

            case 'u':
                myCounterCTUD[i].noDownIndex = (EEPROM.read(tempMulti+13))-48+30;
              break;
          }//END switch
        }


        tempFlag = EEPROM.read(tempMulti+14);
        if(tempFlag == 's'){
          myCounterCTUD[i].countDownNull = true;
        }
        else{
          myCounterCTUD[i].countDownNull = false;
          if(tempFlag == 'O') {
            myCounterCTUD[i].countDown = true;
            myCounterCTUD[i].countDownIndex = (EEPROM.read(tempMulti+15))-48;
          }
          else if(tempFlag == 'k'){
            myCounterCTUD[i].countDown = true;
            myCounterCTUD[i].countDownIndex = (EEPROM.read(tempMulti+15))-48+10;
          }
          else {
            myCounterCTUD[i].countDown = false;
            switch(tempFlag){
              case 'V':
                  myCounterCTUD[i].countDownIndex = (EEPROM.read(tempMulti+15))-48;
                break;

              case 'v':
                  myCounterCTUD[i].countDownIndex = (EEPROM.read(tempMulti+15))-48+10;
                break;

              case 'U':
                  myCounterCTUD[i].countDownIndex = (EEPROM.read(tempMulti+15))-48+20;
                break;

              case 'u':
                  myCounterCTUD[i].countDownIndex = (EEPROM.read(tempMulti+15))-48+30;
                break;
            }//END switch
          }
        }//END else

      }//END else if(tempCounterValue == 'b')



    }//END for Counters


    for(int i = 0; i<4; i++){                                                         //Loading Timers
      int tempMulti = 805 + (12*i);
      char tempCounterValue = EEPROM.read(tempMulti);

      if(tempCounterValue == 't'){                                                                           //TON
        myTimer[i].typeTimer = 1;//TON

        int tempFlag = EEPROM.read(tempMulti+1);
        if(tempFlag == 'I') {
          myTimer[i].no = 1;
          myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48;
        }
        else if(tempFlag == 'i'){
          myTimer[i].no = 1;
          myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
        }
        else if(tempFlag == 'O'){
          myTimer[i].no = 2;
          myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48;
        }
        else if(tempFlag == 'k'){
          myTimer[i].no = 2;
          myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
        }
        else {
          myTimer[i].no = 0;
          switch(tempFlag){
              case 'V':
                  myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48;
                break;

              case 'v':
                  myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
                break;

              case 'U':
                  myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+20;
                break;

              case 'u':
                  myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+30;
                break;
            }//END switch
        }//END else


        tempFlag = EEPROM.read(tempMulti+3);
        if(tempFlag == 's'){
          myTimer[i].dnNull = true;
        }
        else{
          myTimer[i].dnNull = false;
          if(tempFlag == 'O') {
            myTimer[i].dn = true;
            myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48;
          }
          else if(tempFlag == 'k'){
            myTimer[i].dn = true;
            myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48+10;
          }
          else {
            myTimer[i].dn = false;
            switch(tempFlag){
              case 'V':
                  myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48;
                break;

              case 'v':
                  myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48+10;
                break;

              case 'U':
                  myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48+20;
                break;

              case 'u':
                  myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48+30;
                break;
            }//END switch
          }//END else
        }//END else


        tempFlag = EEPROM.read(tempMulti+5);
        if(tempFlag == 's'){
          myTimer[i].ttNull = true;
        }
        else{
          myTimer[i].ttNull = false;

          if(tempFlag == 'O') {
            myTimer[i].tt = true;
            myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48;
          }
          else if(tempFlag == 'k'){
            myTimer[i].tt = true;
            myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48+10;
          }
          else {
            myTimer[i].tt = false;
            switch(tempFlag){
              case 'V':
                  myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48;
                break;

              case 'v':
                  myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48+10;
                break;

              case 'U':
                  myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48+20;
                break;

              case 'u':
                  myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48+30;
                break;
            }//END switch
          }//END else
        }//END else


        myTimer[i].presetIndex = EEPROM.read(tempMulti+8);
        myTimer[i].currentTimeIndex = EEPROM.read(tempMulti+9);


        if(EEPROM.read(tempMulti+7)=='0')
          myTimer[i].isPoint1 = false;

        else if(EEPROM.read(tempMulti+7)=='1')
          myTimer[i].isPoint1 = true;

        myTimer[i].enableNo = false;
        myTimer[i].activeTimer = false;
      }



      else if(tempCounterValue == 'T'){                                                                      //TOF
        myTimer[i].typeTimer = 2;//TOF

        int tempFlag = EEPROM.read(tempMulti+1);
        if(tempFlag == 'I') {
          myTimer[i].no = 1;
          myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48;
        }
        else if(tempFlag == 'i'){
          myTimer[i].no = 1;
          myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
        }
        else if(tempFlag == 'O'){
          myTimer[i].no = 2;
          myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48;
        }
        else if(tempFlag == 'k'){
          myTimer[i].no = 2;
          myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
        }
        else {
          myTimer[i].no = 0;
          switch(tempFlag){
              case 'V':
                  myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48;
                break;

              case 'v':
                  myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
                break;

              case 'U':
                  myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+20;
                break;

              case 'u':
                  myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+30;
                break;
            }//END switch
        }//END else


        tempFlag = EEPROM.read(tempMulti+3);
        if(tempFlag == 's'){
          myTimer[i].dnNull = true;
        }
        else{
          myTimer[i].dnNull = false;
          if(tempFlag == 'O') {
            myTimer[i].dn = true;
            myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48;
          }
          else if(tempFlag == 'k'){
            myTimer[i].dn = true;
            myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48+10;
          }
          else {
            myTimer[i].dn = false;
            switch(tempFlag){
              case 'V':
                  myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48;
                break;

              case 'v':
                  myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48+10;
                break;

              case 'U':
                  myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48+20;
                break;

              case 'u':
                  myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48+30;
                break;
            }//END switch
          }//END else
        }//END else


        tempFlag = EEPROM.read(tempMulti+5);
        if(tempFlag == 's'){
          myTimer[i].ttNull = true;
        }
        else{
          myTimer[i].ttNull = false;

          if(tempFlag == 'O') {
            myTimer[i].tt = true;
            myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48;
          }
          else if(tempFlag == 'k'){
            myTimer[i].tt = true;
            myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48+10;
          }
          else {
            myTimer[i].tt = false;
            switch(tempFlag){
              case 'V':
                  myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48;
                break;

              case 'v':
                  myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48+10;
                break;

              case 'U':
                  myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48+20;
                break;

              case 'u':
                  myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48+30;
                break;
            }//END switch
          }//END else
        }//END else


        myTimer[i].presetIndex = EEPROM.read(tempMulti+8);
        myTimer[i].currentTimeIndex = EEPROM.read(tempMulti+9);

        if(EEPROM.read(tempMulti+7)=='0')
          myTimer[i].isPoint1 = false;

        else if(EEPROM.read(tempMulti+7)=='1')
          myTimer[i].isPoint1 = true;

        myTimer[i].enableNo = false;
        myTimer[i].activeTimer = false;
      }


      else if(tempCounterValue == 'S'){                                                                      //RTO

        myTimer[i].typeTimer = 3;//RTO

        int tempFlag = EEPROM.read(tempMulti+1);
        if(tempFlag == 'I') {
          myTimer[i].no = 1;
          myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48;
        }
        else if(tempFlag == 'i'){
          myTimer[i].no = 1;
          myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
        }
        else if(tempFlag == 'O'){
          myTimer[i].no = 2;
          myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48;
        }
        else if(tempFlag == 'k'){
          myTimer[i].no = 2;
          myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
        }
        else {
          myTimer[i].no = 0;
          switch(tempFlag){
              case 'V':
                  myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48;
                break;

              case 'v':
                  myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+10;
                break;

              case 'U':
                  myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+20;
                break;

              case 'u':
                  myTimer[i].noIndex = (EEPROM.read(tempMulti+2))-48+30;
                break;
            }//END switch
        }//END else


        tempFlag = EEPROM.read(tempMulti+3);
        if(tempFlag == 's'){
          myTimer[i].dnNull = true;
        }
        else{
          myTimer[i].dnNull = false;
          if(tempFlag == 'O') {
            myTimer[i].dn = true;
            myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48;
          }
          else if(tempFlag == 'k'){
            myTimer[i].dn = true;
            myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48+10;
          }
          else {
            myTimer[i].dn = false;
            switch(tempFlag){
              case 'V':
                  myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48;
                break;

              case 'v':
                  myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48+10;
                break;

              case 'U':
                  myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48+20;
                break;

              case 'u':
                  myTimer[i].dnIndex = (EEPROM.read(tempMulti+4))-48+30;
                break;
            }//END switch
          }//END else
        }//END else


        tempFlag = EEPROM.read(tempMulti+5);
        if(tempFlag == 's'){
          myTimer[i].ttNull = true;
        }
        else{
          myTimer[i].ttNull = false;

          if(tempFlag == 'O') {
            myTimer[i].tt = true;
            myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48;
          }
          else if(tempFlag == 'k'){
            myTimer[i].tt = true;
            myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48+10;
          }
          else {
            myTimer[i].tt = false;
            switch(tempFlag){
              case 'V':
                  myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48;
                break;

              case 'v':
                  myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48+10;
                break;

              case 'U':
                  myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48+20;
                break;

              case 'u':
                  myTimer[i].ttIndex = (EEPROM.read(tempMulti+6))-48+30;
                break;
            }//END switch
          }//END else
        }//END else


        myTimer[i].presetIndex = EEPROM.read(tempMulti+8);
        myTimer[i].currentTimeIndex = EEPROM.read(tempMulti+9);

        if(EEPROM.read(tempMulti+7)=='0')
          myTimer[i].isPoint1 = false;

        else if(EEPROM.read(tempMulti+7)=='1')
          myTimer[i].isPoint1 = true;

        tempFlag = EEPROM.read(tempMulti+10);
        if(tempFlag == 'I') {
          myTimer[i].reset = 1;
          myTimer[i].resetIndex = (EEPROM.read(tempMulti+11))-48;
        }
        else if(tempFlag == 'i'){
          myTimer[i].reset = 1;
          myTimer[i].resetIndex = (EEPROM.read(tempMulti+11))-48+10;
        }
        else if(tempFlag == 'O'){
          myTimer[i].reset = 2;
          myTimer[i].resetIndex = (EEPROM.read(tempMulti+11))-48;
        }
        else if(tempFlag == 'k'){
          myTimer[i].reset = 2;
          myTimer[i].resetIndex = (EEPROM.read(tempMulti+11))-48+10;
        }
        else {
          myTimer[i].reset = 0;
          switch(tempFlag){
              case 'V':
                  myTimer[i].resetIndex = (EEPROM.read(tempMulti+11))-48;
                break;

              case 'v':
                  myTimer[i].resetIndex = (EEPROM.read(tempMulti+11))-48+10;
                break;

              case 'U':
                  myTimer[i].resetIndex = (EEPROM.read(tempMulti+11))-48+20;
                break;

              case 'u':
                  myTimer[i].resetIndex = (EEPROM.read(tempMulti+11))-48+30;
                break;
            }//END switch
        }//END else

        myTimer[i].enableNo = false;
        myTimer[i].activeTimer = false;
        dintValues[myTimer[i].currentTimeIndex] = 0;
      }

    }//END FOR Timers

  }//END IF

  else{
    digitalWrite(13, LOW);
  }

  PC=0;//HERE
  n=0;
  X=false;
  Y=false;
  notFlag=false;
  fallingFlag=false;
  risingFlag=false;
  iFlag=false;
  iFlag1=false;
  oFlag=false;
  oFlag1=false;
  vFlag=false;
  vFlag1=false;
  vFlag2=false;
  vFlag3=false;
  latchFlag=false;
  unlatchFlag=false;
  negateFlag=false;
  coilFlag=false;
  timerFlag=false;
  counterFlag=false;
  counterCTUDFlag = false;

  inFunction = false;
}

void reprogram(){
  bool timeElapsed = false;
  targetTime = 8000;  //time wating for connection
  startTime = millis();
  digitalWrite(13,HIGH);
  while(!timeElapsed){

    if(Serial.available() > 0){ //Waiting for connection from Android app
      Serial.readBytesUntil(42,bufferSerial,sizeof(bufferSerial));  //Limited by the *(42)

      if(bufferSerial[0] == 'c'){//230
        Serial.println("u");
        //Serial.write(10);
        delay(10);

          bool programing = true;
          int countPC= 0;
          int countCounter = 0;
          int countCounterCTU = 0;
          int countCounterCTUD = 0;
          int countTimer = 0;
          int counterInt = 0;
          int counterDint = 0;
          int counterReal = 0;
          int varSalto = 0;
          int32_t tempA = 0;
          int32_t tempB = 0;
          startTime=millis();

          while(programing){

            if(Serial.available()>0){
              buffSize = Serial.readBytesUntil(42,bufferSerial,sizeof(bufferSerial));     //42 *

              if(buffSize > 0){
                switch(bufferSerial[0]){
                  case 'I': //I
                      for(int i = 1; i<buffSize; i++){
                        EEPROM.write(975+i,bufferSerial[i]);
                      }
                    break;

                  case 'O': //O
                      for(int i = 1; i<buffSize; i++){
                        EEPROM.write(983+i,bufferSerial[i]);
                      }
                    break;

                  case 'V': //V
                      for(int i = 1; i<buffSize; i++){
                        EEPROM.write(991+i,bufferSerial[i]);
                      }

                    break;

                    case 'w':
                        EEPROM.write(673, bufferSerial[1]);
                        break;

                    case 'N': //int

                        varSalto = (674 + (2 * counterInt));

                        tempB = bufferSerial[3] << 14;
                        tempA = bufferSerial[2] << 7;
                        tempB = tempB | tempA | bufferSerial[1];

                        tempA = tempB & (0xFF);
                        EEPROM.write(varSalto + 1, tempA);

                        tempA = tempB & (0xFF00);
                        tempA = tempA >> 8;

                        EEPROM.write(varSalto, tempA);

                        counterInt++;
                      break;

                    case 'L': //dint

                          varSalto = (707+(4 * counterDint));

                          tempB = (((int32_t)bufferSerial[5]) << 28);
                          tempA = (((int32_t)bufferSerial[4]) << 21);
                          tempB = tempB | tempA;
                          tempA = (((int32_t)bufferSerial[3]) << 14);
                          tempB = tempB | tempA;
                          tempA = (((int32_t)bufferSerial[2]) << 7);
                          tempB = tempB | tempA | ((int32_t)bufferSerial[1]);

                          tempA = tempB & (0xFF);
                          EEPROM.write(varSalto + 3, tempA);

                          tempA = tempB & (0xFF00);
                          tempA = tempA >> 8;
                          EEPROM.write(varSalto + 2, tempA);

                          tempA = tempB & (0xFF0000);
                          tempA = tempA >> 16;
                          EEPROM.write(varSalto + 1, tempA);

                          tempA = tempB & (0xFF000000);
                          tempA = tempA >> 24;
                          EEPROM.write(varSalto, tempA);


                          counterDint++;
                      break;

                    case 'F': //real

                          varSalto = (772) + (4 * counterReal);

                          tempB = (((int32_t)bufferSerial[5]) << 28);
                          tempA = (((int32_t)bufferSerial[4]) << 21);
                          tempB = tempB | tempA;
                          tempA = (((int32_t)bufferSerial[3]) << 14);
                          tempB = tempB | tempA;
                          tempA = (((int32_t)bufferSerial[2]) << 7);
                          tempB = tempB | tempA | ((int32_t)bufferSerial[1]);

                          tempA = tempB & (0xFF);
                          EEPROM.write(varSalto + 3, tempA);

                          tempA = tempB & (0xFF00);
                          tempA = tempA >> 8;
                          EEPROM.write(varSalto + 2, tempA);

                          tempA = tempB & (0xFF0000);
                          tempA = tempA >> 16;
                          EEPROM.write(varSalto + 1, tempA);

                          tempA = tempB & (0xFF000000);
                          tempA = tempA >> 24;
                          EEPROM.write(varSalto, tempA);

                        counterReal++;
                      break;

                 case '$':
                    for(int i = 0; i<buffSize; i++){
                      EEPROM.write(countPC, bufferSerial[i]);
                      countPC++;
                    }
                    break;

                  case 'R':
                    for(int i = 0; i<buffSize; i++){
                      EEPROM.write(countPC, bufferSerial[i]);
                      countPC++;
                    }
                    break;

                  case 'B':
                    for(int i = 0; i<buffSize; i++){
                      int salto = (878+i)+(16*countCounter);
                      EEPROM.write(salto, bufferSerial[i]);
                    }
                    EEPROM.write(countPC, 'B');
                    countPC++;
                    EEPROM.write(countPC, (countCounterCTU+48));
                    countPC++;
                    countCounter++;
                    countCounterCTU++;
                    break;

                  case 'b':
                    for(int i = 0; i<buffSize; i++){
                      int salto = (878+i)+(16*countCounter);
                      EEPROM.write(salto, bufferSerial[i]);
                    }
                    EEPROM.write(countPC, 'b');
                    countPC++;
                    EEPROM.write(countPC, (countCounterCTUD+48));
                    countPC++;
                    countCounter++;
                    countCounterCTUD++;
                    break;

                  case 't':
                    for(int i = 0; i<buffSize; i++){
                      int salto = (805+i)+(12*countTimer);
                      EEPROM.write(salto, bufferSerial[i]);
                    }
                    EEPROM.write(countPC,'q');
                    countPC++;
                    EEPROM.write(countPC, (countTimer+48));
                    countPC++;
                    countTimer++;
                    break;

                  case 'T':
                    for(int i = 0; i<buffSize; i++){
                      int salto = (805+i)+(12*countTimer);
                      EEPROM.write(salto, bufferSerial[i]);
                    }
                    EEPROM.write(countPC,'q');
                    countPC++;
                    EEPROM.write(countPC, (countTimer+48));
                    countPC++;
                    countTimer++;
                    break;

                  case 'S':
                    for(int i = 0; i<buffSize; i++){
                      int salto = (805+i)+(12*countTimer);
                      EEPROM.write(salto, bufferSerial[i]);
                    }
                    EEPROM.write(countPC,'q');
                    countPC++;
                    EEPROM.write(countPC, (countTimer+48));
                    countPC++;
                    countTimer++;
                    break;

                  case'x':
                    Serial.flush();
                    while(Serial.read() != -1){

                    }
                    Serial.println('y');
                    //Serial.write(10);
                    break;

                  case'X':
                    Serial.flush();
                    while(Serial.read() != -1){

                    }
                    Serial.println('h');
                    //Serial.write(10);
                    break;

                  case 'r':
                    for(int i = 1; i<buffSize;i++){
                      EEPROM.write(countPC, bufferSerial[i]);
                      countPC++;
                    }
                    break;
                  case 'd':
                      programing = false;
                      digitalWrite(13,HIGH);
                      EEPROM.write(countPC, 'z');
                      EEPROM.write(975,'2');

                      Serial.flush();
                      while(Serial.read() != -1){

                      }
                      cleanOldCounters(countCounter);
                      cleanOldTimers(countTimer);

                    break;
                }//END switch bufferSerial[0]
              }//END buffSize > 0
            }//END if

            blinking();
            delay(10);
            delta = millis();
            delta = delta-startTime;
            if(delta>5000){
              digitalWrite(13,LOW);
            }

          }//END while(programing)

       // }//END Connection TRUE
      }//END Serial 230
    }//END Serial.available

    delta = millis();
    delta = delta - startTime;

    blinking();

    delay(200);

    if(delta>targetTime){
      timeElapsed = true;
      //digitalWrite(13, HIGH);
    }


  }//END While
}//END reprogram

void cleanOldCounters(int tempCountCounter){
  if(tempCountCounter< 7){
    for(int i = tempCountCounter; i<7; i++){
      int salto = (878)+(16*i);
      EEPROM.write(salto, '~');

    }
  }
}//END cleanOldCounters


void cleanOldTimers(int tempCountTimer){
  if(tempCountTimer< 7){
    for(int i = tempCountTimer; i<7; i++){
      int salto = (805)+(12*i);
      EEPROM.write(salto, '~');

    }
  }
}//END cleanOldCounters


bool setDnCounter(int posi, bool dnState){
  bool tempReturn = dnState;
  if(!dnState){
    if(dintValues[myCounter[posi].countIndex] >= dintValues[myCounter[posi].presetIndex]){
      tempReturn = true;
    }//END if(myCounter[posi].count >= myCounter[posi].preset)
  }//END if
  else{
    if(myCounter[posi].resetNo){
      tempReturn = false;
    }
  }
  return tempReturn;
}

bool setDnCounterCTUD(int posi, bool dnState){
  bool tempReturn = dnState;
  if(!dnState){
    if(dintValues[myCounterCTUD[posi].countIndex] >= dintValues[myCounterCTUD[posi].presetIndex]){
      tempReturn = true;
    }//END if(myCounterCTUD[posi].count >= myCounterCTUD[posi].preset)
  }//END if
  else{
    if(myCounterCTUD[posi].resetNo){
      tempReturn = false;
    }

    if(dintValues[myCounterCTUD[posi].countIndex] < dintValues[myCounterCTUD[posi].presetIndex]){
      tempReturn = false;
    }//END if(myCounterCTUD[posi].count < myCounterCTUD[posi].preset)
  }
  return tempReturn;
}


void blinking(){
  if(digitalRead(13)){
      digitalWrite(13, LOW);
    }

    else{
      digitalWrite(13,HIGH);
    }
}

int readAnalogPin(int index){
  return analogRead(iPins[index]);
}

void writeServoPin(int index, int value){

  if(!servoOutput[index]){
    servoOutput[index] = true;

    switch(index){
      case 1:
        myServo0.attach(oPins[index]);
      break;
      case 2:
        myServo1.attach(oPins[index]);
      break;
      case 5:
        myServo2.attach(oPins[index]);
      break;
      case 6:
        myServo3.attach(oPins[index]);
      break;
      case 7:
        myServo4.attach(oPins[index]);
      break;

    }

  }

  if(value > 180)
    value = 180;
  if(value < 0)
    value = 0;

    switch(index){
      case 1:
        myServo0.write(value);
      break;
      case 2:
        myServo1.write(value);
      break;
      case 5:
        myServo2.write(value);
      break;
      case 6:
        myServo3.write(value);
      break;
      case 7:
        myServo4.write(value);
      break;

    }
    delay(15);

    if(value == 0)
      value = 1;

    analogOutputs[index] = (int8_t)value;
}


void writeAnalogPin(int index, int value){

  if(value > 255)
    value = 255;
  if(value < 0)
    value = 0;

  analogWrite(oPins[index], value);
  analogOutputs[index] = (int8_t)value;
}

int readAnalogOutput(int index){
  return (int)analogOutputs[index];
}

void equ(){                                                                     //Equal
  int dnIndex = 0;
  float tempSource = 0;
  float tempSourceB = 0;
  bool tagIsEnable = false;

  PC++;
  dnIndex = PC;
  PC+=2;
  tempSource = getSource();
  PC++;

  //Serial.print("SourceA: ");
  //Serial.println(tempSource);

  tagIsEnable = isTagEnable(PC+3);

  if(tagIsEnable){
    PC+=3;
    tempSourceB = getSource();
  }
  else{
    tempSourceB = (float)getJoinValue();
    PC+=4;
  }

  //Serial.print("SourceB: ");
  //Serial.println(tempSourceB);

  if(tempSource == tempSourceB)
    setDnValue(true, dnIndex);
  else
    setDnValue(false, dnIndex);
}

void neq(){                                                                     //Not equal
  int dnIndex = 0;
  float tempSource = 0;
  float tempSourceB = 0;
  bool tagIsEnable = false;

  PC++;
  dnIndex = PC;
  PC+=2;
  tempSource = getSource();
  PC++;

  tagIsEnable = isTagEnable(PC+3);

  if(tagIsEnable){
    PC+=3;
    tempSourceB = getSource();
  }
  else{
    tempSourceB = (float)getJoinValue();
    PC+=4;
  }


  if(tempSource != tempSourceB)
    setDnValue(true, dnIndex);
  else
    setDnValue(false, dnIndex);
}

void les(){                                                                     //Less than
  int dnIndex = 0;
  float tempSource = 0;
  float tempSourceB = 0;
  bool tagIsEnable = false;

  PC++;
  dnIndex = PC;
  PC+=2;
  tempSource = getSource();
  PC++;

  tagIsEnable = isTagEnable(PC+3);

  if(tagIsEnable){
    PC+=3;
    tempSourceB = getSource();
  }
  else{
    tempSourceB = (float)getJoinValue();
    PC+=4;
  }


  if(tempSource < tempSourceB)
    setDnValue(true, dnIndex);
  else
    setDnValue(false, dnIndex);
}

void leq(){                                                                     //Less and equal
  int dnIndex = 0;
  float tempSource = 0;
  float tempSourceB = 0;
  bool tagIsEnable = false;

  PC++;
  dnIndex = PC;
  PC+=2;
  tempSource = getSource();
  PC++;

  tagIsEnable = isTagEnable(PC+3);

  if(tagIsEnable){
    PC+=3;
    tempSourceB = getSource();
  }
  else{
    tempSourceB = (float)getJoinValue();
    PC+=4;
  }


  if(tempSource <= tempSourceB)
    setDnValue(true, dnIndex);
  else
    setDnValue(false, dnIndex);
}

void grt(){                                                                     //Greater than
  int dnIndex = 0;
  float tempSource = 0;
  float tempSourceB = 0;
  bool tagIsEnable = false;

  PC++;
  dnIndex = PC;
  PC+=2;
  tempSource = getSource();
  PC++;

  tagIsEnable = isTagEnable(PC+3);

  if(tagIsEnable){
    PC+=3;
    tempSourceB = getSource();
  }
  else{
    tempSourceB = (float)getJoinValue();
    PC+=4;
  }


  if(tempSource > tempSourceB)
    setDnValue(true, dnIndex);
  else
    setDnValue(false, dnIndex);
}

void geq(){                                                                     //Greater and equal
  int dnIndex = 0;
  float tempSource = 0;
  float tempSourceB = 0;
  bool tagIsEnable = false;

  PC++;
  dnIndex = PC;
  PC+=2;
  tempSource = getSource();
  PC++;

  tagIsEnable = isTagEnable(PC+3);

  if(tagIsEnable){
    PC+=3;
    tempSourceB = getSource();
  }
  else{
    tempSourceB = (float)getJoinValue();
    PC+=4;
  }


  if(tempSource >= tempSourceB)
    setDnValue(true, dnIndex);
  else
    setDnValue(false, dnIndex);
}


void mov(){                                                                     //Move
    bool noState = false;

    PC++;

    if(isTagEnable(PC))
      noState = getNoValue();
    else{
      noState = true;
      PC++;
    }

    if(noState){
        float tempSource = 0;

        PC++;
        if(isTagEnable(PC)){
          tempSource = getSource();
          PC+=4;
        }
        else{
          PC+=2;
          tempSource = (float)getJoinValue();
          PC+=3;
        }

        //Serial.println(tempSource);
        setDest(tempSource);
    }
    else
      PC+=7;

}

void lim(){                                                                     //Limit
  int dnIndex = 0;
  float tempTest = 0;
  float tempSourceMax = 0;
  float tempSourceMin = 0;
  bool tagIsEnable = false;

  PC++;                                                                         //byte 2
  dnIndex = PC;
  PC+=2;                                                                        //byte 4
  tempTest = getSource();
  PC++;                                                                         //byte 6
  tagIsEnable = isTagEnable(PC+3);

  if(tagIsEnable){
    PC+=3;                                                                      //byte 9
    tempSourceMin = getSource();

  }
  else{
    tempSourceMin = (float)getJoinValue();
    PC+=4;                                                                      //byte 10
  }
  PC++;                                                                         //byte 11

  tagIsEnable = isTagEnable(PC+3);

  if(tagIsEnable){
    PC+=3;                                                                      //byte 14
    tempSourceMax = getSource();
  }
  else{
    tempSourceMax = (float)getJoinValue();
    PC+=4;
  }


  if((tempTest >= tempSourceMin) && (tempTest <= tempSourceMax))
    setDnValue(true, dnIndex);
  else
    setDnValue(false, dnIndex);

}

void meq(){                                                                     //Mask equal
  int dnIndex = 0;
  int32_t tempSource = 0;
  int32_t tempMask = 0;
  int32_t tempCompare = 0;
  bool tagIsEnable = false;

  PC++;                                                                         //byte 2
  dnIndex = PC;
  PC+=2;                                                                        //byte 4
  tempSource = getSource();
  PC++;                                                                         //byte 6
  tagIsEnable = isTagEnable(PC+3);

  if(tagIsEnable){
    PC+=3;                                                                      //byte 9
    tempMask = getSource();

  }
  else{
    tempMask = (float)getJoinValue();
    PC+=4;                                                                      //byte 10
  }
  PC++;                                                                         //byte 11

  tagIsEnable = isTagEnable(PC+3);

  if(tagIsEnable){
    PC+=3;                                                                      //byte 14
    tempCompare = getSource();
  }
  else{
    tempCompare = (float)getJoinValue();
    PC+=4;
  }

tempSource = tempSource & tempMask;

  if(tempSource == tempCompare)
    setDnValue(true, dnIndex);
  else
    setDnValue(false, dnIndex);
}//END meq()

void andOp(){                                                                   //And
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }


  if(noState){
      int32_t tempSourceA = 0;
      int32_t tempSourceB = 0;

      PC++;                                                                     //byte 4
      tempSourceA = (int32_t)getSource();
      PC++;                                                                     //byte 6

      if(isTagEnable(PC+3)){                                                    //(byte 9)
        PC+=3;                                                                  //byte 9
        tempSourceB = (int32_t)getSource();
        PC++;                                                                   //byte 11
      }
      else{
        tempSourceB = (int32_t)getJoinValue();
        PC+=5;                                                                  //byte 11
      }

      tempSourceA = tempSourceA & tempSourceB;

      setDest(tempSourceA);
  }
  else
    PC+=9;                                                                      //byte 12

}//END andOp()

void orOp(){                                                                    //Or
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }


  if(noState){
      int32_t tempSourceA = 0;
      int32_t tempSourceB = 0;

      PC++;                                                                     //byte 4
      tempSourceA = (int32_t)getSource();
      PC++;                                                                     //byte 6

      if(isTagEnable(PC+3)){                                                    //(byte 9)
        PC+=3;                                                                  //byte 9
        tempSourceB = (int32_t)getSource();
        PC++;                                                                   //byte 11
      }
      else{
        tempSourceB = (int32_t)getJoinValue();
        PC+=5;                                                                  //byte 11
      }

      tempSourceA = tempSourceA | tempSourceB;

      setDest(tempSourceA);
  }
  else
    PC+=9;
}//END orOp()

void notOp(){                                                                   //Not
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();                                                     //(byte 3)
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }

  if(noState){
      int32_t tempSource32 = 0;
      int16_t tempSource16 = 0;
      float tempSource = 0;

      PC++;                                                                     //byte 4

      if(isSourceInt()){
        tempSource16 = (int16_t)getSource();
        tempSource16 = ~(tempSource16);
        tempSource = (float)tempSource16;
      }
      else{
        tempSource32 = (int32_t)getSource();
        tempSource32 = ~(tempSource32);
        tempSource = (float)tempSource32;
      }


      PC++;                                                                     //byte 6

      setDest(tempSource);
  }
  else
    PC+=4;                                                                      //byte 7
}//END notOp()

void xorOp(){                                                                   //Xor
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }


  if(noState){
      int32_t tempSourceA = 0;
      int32_t tempSourceB = 0;

      PC++;                                                                     //byte 4
      tempSourceA = (int32_t)getSource();
      PC++;                                                                     //byte 6

      if(isTagEnable(PC+3)){                                                    //(byte 9)
        PC+=3;                                                                  //byte 9
        tempSourceB = (int32_t)getSource();
        PC++;                                                                   //byte 11
      }
      else{
        tempSourceB = (int32_t)getJoinValue();
        PC+=5;                                                                  //byte 11
      }

      tempSourceA = tempSourceA ^ tempSourceB;

      setDest(tempSourceA);
  }
  else
    PC+=9;
}//END xorOp()

void addOp(){                                                                   //Add
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }


  if(noState){
      float tempSourceA = 0;
      float tempSourceB = 0;

      PC++;                                                                     //byte 4
      tempSourceA = getSource();
      PC++;                                                                     //byte 6

      if(isTagEnable(PC+3)){                                                    //(byte 9)
        PC+=3;                                                                  //byte 9
        tempSourceB = getSource();
        PC++;                                                                   //byte 11
      }
      else{
        tempSourceB = (float)getJoinValue();
        PC+=5;                                                                  //byte 11
      }

      tempSourceA += tempSourceB;

      setDest(tempSourceA);
  }
  else
    PC+=9;
}

void subOp(){                                                                   //Sub
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }


  if(noState){
      float tempSourceA = 0;
      float tempSourceB = 0;

      PC++;                                                                     //byte 4
      tempSourceA = getSource();
      PC++;                                                                     //byte 6

      if(isTagEnable(PC+3)){                                                    //(byte 9)
        PC+=3;                                                                  //byte 9
        tempSourceB = getSource();
        PC++;                                                                   //byte 11
      }
      else{
        tempSourceB = (float)getJoinValue();
        PC+=5;                                                                  //byte 11
      }

      tempSourceA -= tempSourceB;

      setDest(tempSourceA);
  }
  else
    PC+=9;
}

void mulOp(){                                                                   //Mul
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }


  if(noState){
      float tempSourceA = 0;
      float tempSourceB = 0;

      PC++;                                                                     //byte 4
      tempSourceA = getSource();
      PC++;                                                                     //byte 6

      if(isTagEnable(PC+3)){                                                    //(byte 9)
        PC+=3;                                                                  //byte 9
        tempSourceB = getSource();

        PC++;                                                                   //byte 11
      }
      else{
        tempSourceB = (float)getJoinValue();
        PC+=5;                                                                  //byte 11
      }

      tempSourceA *= tempSourceB;

      setDest(tempSourceA);
  }
  else
    PC+=9;
}

void divOp(){                                                                   //Div
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }


  if(noState){
      float tempSourceA = 0;
      float tempSourceB = 0;

      PC++;                                                                     //byte 4
      tempSourceA = getSource();
      PC++;                                                                     //byte 6

      if(isTagEnable(PC+3)){                                                    //(byte 9)
        PC+=3;                                                                  //byte 9
        tempSourceB = getSource();
        PC++;                                                                   //byte 11
      }
      else{
        tempSourceB = (float)getJoinValue();
        PC+=5;                                                                  //byte 11
      }

      if(tempSourceB != 0)
        tempSourceA /= tempSourceB;

      setDest(tempSourceA);
  }
  else
    PC+=9;
}

void xpy(){                                                                     //x pow y
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }

  if(noState){
      float tempSourceA = 0;
      float tempSourceB = 0;

      PC++;                                                                     //byte 4
      tempSourceA = getSource();
      PC++;                                                                     //byte 6

      if(isTagEnable(PC+3)){                                                    //(byte 9)
        PC+=3;                                                                  //byte 9
        tempSourceB = getSource();
        PC++;                                                                   //byte 11
      }
      else{
        tempSourceB = (float)getJoinValue();
        PC+=5;                                                                  //byte 11
      }

      tempSourceA = pow(tempSourceA, tempSourceB);

      setDest(tempSourceA);
  }
  else
    PC+=9;
}

void absMath(){                                                                 //Abs
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();                                                     //(byte 3)
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }

  if(noState){
      float tempSource = 0;

      PC++;                                                                     //byte 4
      tempSource = getSource();
      PC++;                                                                     //byte 6

      tempSource = abs(tempSource);

      setDest(tempSource);
  }
  else
    PC+=4;                                                                      //byte 7
}

void sqrMath(){
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();                                                     //(byte 3)
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }

  if(noState){
      float tempSource = 0;

      PC++;                                                                     //byte 4
      tempSource = getSource();
      PC++;                                                                     //byte 6

      tempSource = sqrt(tempSource);

      setDest(tempSource);
  }
  else
    PC+=4;                                                                      //byte 7
}

/*
void asnMath(){
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();                                                     //(byte 3)
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }

  if(noState){
      float tempSource = 0;

      PC++;                                                                     //byte 4
      tempSource = getSource();
      PC++;                                                                     //byte 6

      tempSource = asin(tempSource);

      setDest(tempSource);
  }
  else
    PC+=4;                                                                      //byte 7
}

void acsMath(){
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();                                                     //(byte 3)
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }

  if(noState){
      float tempSource = 0;

      PC++;                                                                     //byte 4
      tempSource = getSource();
      PC++;                                                                     //byte 6

      tempSource = acos(tempSource);

      setDest(tempSource);
  }
  else
    PC+=4;                                                                      //byte 7
}

void atnMath(){
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();                                                     //(byte 3)
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }

  if(noState){
      float tempSource = 0;

      PC++;                                                                     //byte 4
      tempSource = getSource();
      PC++;                                                                     //byte 6

      tempSource = atan(tempSource);

      setDest(tempSource);
  }
  else
    PC+=4;                                                                      //byte 7
}*/

void cosMath(){
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();                                                     //(byte 3)
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }

  if(noState){
      float tempSource = 0;

      PC++;                                                                     //byte 4
      tempSource = getSource();
      PC++;                                                                     //byte 6

      tempSource = cos(tempSource);

      setDest(tempSource);
  }
  else
    PC+=4;                                                                      //byte 7
}

/*
void lnMath(){
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();                                                     //(byte 3)
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }

  if(noState){
      float tempSource = 0;

      PC++;                                                                     //byte 4
      tempSource = getSource();
      PC++;                                                                     //byte 6

      tempSource = log(tempSource);

      setDest(tempSource);
  }
  else
    PC+=4;                                                                      //byte 7
}

void logMath(){
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();                                                     //(byte 3)
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }

  if(noState){
      float tempSource = 0;

      PC++;                                                                     //byte 4
      tempSource = getSource();
      PC++;                                                                     //byte 6

      tempSource = log10(tempSource);

      setDest(tempSource);
  }
  else
    PC+=4;                                                                      //byte 7
}*/

void sinMath(){
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();                                                     //(byte 3)
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }

  if(noState){
      float tempSource = 0;

      PC++;                                                                     //byte 4
      tempSource = getSource();
      PC++;                                                                     //byte 6

      tempSource = sin(tempSource);

      setDest(tempSource);
  }
  else
    PC+=4;                                                                      //byte 7
}

void tanMath(){
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();                                                     //(byte 3)
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }

  if(noState){
      float tempSource = 0;

      PC++;                                                                     //byte 4
      tempSource = getSource();
      PC++;                                                                     //byte 6

      tempSource = tan(tempSource);
      //Serial.print("tan: ");
      //Serial.println(tempSource);
      //Serial.println("");
      setDest(tempSource);
  }
  else
    PC+=4;                                                                      //byte 7
}

void bsl(){                                                                     //Bit Shift Left
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC)){
    bool tempPre = getUpEdgeActive();
    bool noStateShift = getNoValue();

    if(tempPre)
      noState = true;

    if(!noStateShift){
        if(isTagEnable(PC+1))
          setDnValue(false, PC+1);
    }

  }
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }


  if(noState){
    int dnIndex = 0;
    bool dnEnabled = false;
    int ulIndex = 0;
    bool ulEnabled = false;
    int32_t tempInt = 0;
    int sourceIndex = 0;
    bool bitSource = false;
    int32_t tempVarLength = 0;
    bool ulBit = false;

    PC++;                                                                       //byte 4
    if(isTagEnable(PC)){                                                        //if dn is enabled
      dnEnabled = true;
      dnIndex = PC;
    }

    PC+=2;                                                                      //byte 6

    if(isTagEnable(PC)){
      ulEnabled = true;
      ulIndex = PC;
    }

    PC+=2;                                                                      //byte 8

    bool typeVar = isTagEnable(PC);
    PC++;                                                                       //byte 9
    sourceIndex = PC;

    if(typeVar){                                                                //int-dint
      int32_t tempUl = 0;

      tempInt = (int32_t)getSource();
      PC++;                                                                     //byte 11

      if(isTagEnable(PC+1)){
        PC++;                                                                   //byte 12
        bitSource = getNoValue();
        PC++;                                                                   //byte 14
      }
      else{
        if(1==(int8_t)EEPROM.read(PC))
          bitSource = true;
        PC+=3;                                                                  //byte 14
      }

      if(isTagEnable(PC+3)){
        PC+=3;                                                                  //byte 17
        tempVarLength = getSource();
      }
      else{
        tempVarLength = (int32_t)getJoinValue();
        PC+=4;                                                                  //byte 18
      }

      //Logic
      if(ulEnabled){
        tempUl = (tempInt & ((int32_t)1 << (tempVarLength - 1)));

        tempUl = (int32_t)(tempUl >> (tempVarLength - 1));
        if(tempUl == 1)
          ulBit = true;
        else
          ulBit = false;
      }

      int32_t maskUl = 1;
      for(int j = 0; j < (tempVarLength-1); j++){
        maskUl = (maskUl << 1);
        maskUl = (maskUl | 1);
      }

      tempUl = tempInt;

      tempUl = tempUl & maskUl;
      tempUl = tempUl << 1;
      tempUl = tempUl & maskUl;

      if(bitSource)
        tempUl = tempUl | 1;

      int32_t mask2 = ~maskUl;

      tempInt = (tempInt & mask2);

      tempInt = tempInt | tempUl;

      updateVariable(sourceIndex, tempInt);

    }//END int-dint

    else{                                                                       //output
      int outIndex = getOutIndex();
      PC++;                                                                     //byte 11

      if(isTagEnable(PC+1)){
        PC++;                                                                   //byte 12
        bitSource = getNoValue();
        PC++;                                                                   //byte 14
      }
      else{
        if(1==(int8_t)EEPROM.read(PC))
          bitSource = true;
        PC+=3;                                                                  //byte 14
      }

      if(isTagEnable(PC+3)){
        PC+=3;                                                                  //byte 17
        tempVarLength = getSource();
      }
      else{
        tempVarLength = (int32_t)getJoinValue();
        PC+=4;                                                                  //byte 18
      }

      //Logic
      int tempCalc = 8 - outIndex;
      bool tempPostBit = false;
      bool newBit = bitSource;

      if(tempCalc >= 2){
        if(tempVarLength > tempCalc){

          if(ulEnabled)
            ulBit = oState[7];

          for(int j = outIndex; j < 8; j++){
            tempPostBit = oState[j];
            oState[j] = newBit;
            newBit = tempPostBit;
          }
        }

        else{
          if(ulEnabled)
            ulBit = oState[(outIndex + (tempVarLength-1))];

          for(int j = outIndex; j < (tempVarLength + outIndex); j++){
            tempPostBit = oState[j];
            oState[j] = newBit;
            newBit = tempPostBit;
          }
        }
      }//END if(tempCalc >= 2)
      else
        Serial.println("BSL Range Error");

    }//END output

    if(ulEnabled)
      setDnValue(ulBit, ulIndex);
    if(dnEnabled)
      setDnValue(true, dnIndex);

  }//END if(noState)
  else
    PC+=15;
}

void bsr(){                                                                     //Bit Shift Right
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC)){
    bool tempPre = getUpEdgeActive();
    bool noStateShift = getNoValue();

    if(tempPre)
      noState = true;

    if(!noStateShift){
        if(isTagEnable(PC+1))
          setDnValue(false, PC+1);
    }

  }
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }


  if(noState){
    int dnIndex = 0;
    bool dnEnabled = false;
    int ulIndex = 0;
    bool ulEnabled = false;
    int32_t tempInt = 0;
    int sourceIndex = 0;
    bool bitSource = false;
    int32_t tempVarLength = 0;
    bool ulBit = false;

    PC++;                                                                       //byte 4
    if(isTagEnable(PC)){                                                        //if dn is enabled
      dnEnabled = true;
      dnIndex = PC;
    }

    PC+=2;                                                                      //byte 6

    if(isTagEnable(PC)){
      ulEnabled = true;
      ulIndex = PC;
    }

    PC+=2;                                                                      //byte 8

    bool typeVar = isTagEnable(PC);
    PC++;                                                                       //byte 9
    sourceIndex = PC;

    if(typeVar){                                                                //int-dint
      int32_t tempUl = 0;

      tempInt = (int32_t)getSource();
      PC++;                                                                     //byte 11

      if(isTagEnable(PC+1)){
        PC++;                                                                   //byte 12
        bitSource = getNoValue();
        PC++;                                                                   //byte 14
      }
      else{
        if(1==(int8_t)EEPROM.read(PC))
          bitSource = true;
        PC+=3;                                                                  //byte 14
      }

      if(isTagEnable(PC+3)){
        PC+=3;                                                                  //byte 17
        tempVarLength = getSource();
      }
      else{
        tempVarLength = (int32_t)getJoinValue();
        PC+=4;                                                                  //byte 18
      }



      //Logic
      if(ulEnabled){
        tempUl = (tempInt & 1);

        if(tempUl == 1)
          ulBit = true;
        else
          ulBit = false;
      }

      int32_t maskUl = 1;
      for(int j = 0; j < (tempVarLength-1); j++){
        maskUl = (maskUl << 1);
        maskUl = (maskUl | 1);
      }

      tempUl = tempInt;

      tempUl = tempUl & maskUl;
      tempUl = tempUl >> 1;
      tempUl = tempUl & maskUl;


      if(bitSource)
        tempUl = tempUl | ((int32_t)1 << (tempVarLength - 1));


      int32_t mask2 = ~maskUl;

      tempInt = (tempInt & mask2);

      tempInt = tempInt | tempUl;

      updateVariable(sourceIndex, tempInt);


    }//END int-dint

    else{                                                                       //output
      int outIndex = getOutIndex();
      PC++;                                                                     //byte 11

      if(isTagEnable(PC+1)){
        PC++;                                                                   //byte 12
        bitSource = getNoValue();
        PC++;                                                                   //byte 14
      }
      else{
        if(1==(int8_t)EEPROM.read(PC))
          bitSource = true;
        PC+=3;                                                                  //byte 14
      }

      if(isTagEnable(PC+3)){
        PC+=3;                                                                  //byte 17
        tempVarLength = getSource();
      }
      else{
        tempVarLength = (int32_t)getJoinValue();
        PC+=4;                                                                  //byte 18
      }

      //Logic
      int tempCalc = 8 - outIndex;
      bool tempPostBit = false;
      bool newBit = bitSource;

      if(tempCalc >= 2){
        if(tempVarLength > tempCalc){

          if(ulEnabled)
            ulBit = oState[outIndex];

          for(int j = 8; j > outIndex; j--){
            tempPostBit = oState[j-1];
            oState[j-1] = newBit;
            newBit = tempPostBit;
          }
        }

        else{
          if(ulEnabled)
            ulBit = oState[outIndex];

          for(int j = (tempVarLength + outIndex); j > outIndex; j--){
            tempPostBit = oState[j-1];
            oState[j-1] = newBit;
            newBit = tempPostBit;
          }
        }
      }//END if(tempCalc >= 2)
      else
        Serial.println("BSL Range Error");

    }//END output

    if(ulEnabled)
      setDnValue(ulBit, ulIndex);
    if(dnEnabled)
      setDnValue(true, dnIndex);

  }//END if(noState)
  else
    PC+=15;
}


void scp(){                                                                     //Scale with parameter
  bool noState = false;

  PC++;                                                                         //byte 2

  if(isTagEnable(PC))
    noState = getNoValue();
  else{
    noState = true;
    PC++;                                                                       //byte 3
  }


  if(noState){
      int outputIndex = 0;
      float tempInput = 0;
      float tempInputMin = 0;
      float tempInputMax = 0;
      float tempOutputMin = 0;
      float tempOutputMax = 0;

      PC++;                                                                     //byte 4
      outputIndex = PC;
      PC+=2;                                                                    //byte 6

      tempInput = getSource();
      PC++;                                                                     //byte 8

      if(isTagEnable(PC+3)){
        PC+=3;                                                                  //byte 11
        tempInputMin = getSource();
        PC++;                                                                   //byte 13
      }
      else{
        tempInputMin = (float)getJoinValue();
        PC+=5;                                                                  //byte 13
      }

      if(isTagEnable(PC+3)){
        PC+=3;                                                                  //byte 16
        tempInputMax = getSource();
        PC++;                                                                   //byte 18
      }
      else{
        tempInputMax = (float)getJoinValue();
        PC+=5;                                                                  //byte 18
      }


      if(isTagEnable(PC+3)){
        PC+=3;                                                                  //byte 21
        tempOutputMin = getSource();
        PC++;                                                                   //byte 23
      }
      else{
        tempOutputMin = (float)getJoinValue();
        PC+=5;                                                                  //byte 23
      }

      if(isTagEnable(PC+3)){
        PC+=3;                                                                  //byte 26
        tempOutputMax = getSource();
      }
      else{
        tempOutputMax = (float)getJoinValue();
        PC+=4;                                                                  //byte 27
      }

      float tempResult = 0;
      bool calculatePlease = true;

      if(tempInputMax == tempInputMin)
        calculatePlease = false;
      if(tempOutputMin == tempOutputMax)
        calculatePlease = false;
      if(tempInputMin > tempInputMax)
        calculatePlease = false;
      if(tempOutputMin > tempOutputMax)
        calculatePlease = false;

      if(calculatePlease){
        float tempRateCalc =((tempOutputMax - tempOutputMin) / (tempInputMax - tempInputMin));
        float tempOffsetCalc = tempOutputMin - (tempInputMin * tempRateCalc);

        tempResult = (tempInput * tempRateCalc) + tempOffsetCalc;
      }
      else
        tempResult = tempOutputMin;

      if(tempResult > tempOutputMax)
        tempResult = tempOutputMax;
      else if(tempResult < tempOutputMin)
        tempResult = tempOutputMin;

      setDest(outputIndex, tempResult);


  }
  else
    PC+=24;
}

bool isTagEnable(int tempPC){
  bool tempBool = false;

  if(EEPROM.read(tempPC) != 0)
    tempBool = true;

  return tempBool;
}

int16_t getJoinValue(){
  int16_t tempA = 0;
  int16_t tempB = 0;

  tempB = (int16_t)EEPROM.read(PC) << 14;
  tempA = (int16_t)EEPROM.read(PC+1) << 7;
  tempB = tempB | tempA | (int16_t)EEPROM.read(PC+2);

  return tempB;
}

int getOutIndex(){
  int tempReturn = 0;

  uint8_t myDataByte = EEPROM.read(PC);
  PC++;
  uint8_t n = EEPROM.read(PC);
  n = n - 48;

  switch(myDataByte){
    case 'O':                                                                   //output
      tempReturn = n;
    break;
  }

  return tempReturn;
}

void setDnValue(bool newState, int tempPC){

  uint8_t myDataByte = EEPROM.read(tempPC);
  uint8_t n = EEPROM.read(tempPC+1);
  n = n-48;

  switch(myDataByte){
    case 'O':                                                                   //output
      oState[n] = newState;
    break;
    case 'V':                                                                   //virtual
      vState[n] = newState;
    break;
    case 'v':                                                                   //virtual + 10
      vState[n+10] = newState;
    break;
    case 'U':                                                                   //virtual + 20
      vState[n+20] = newState;
    break;
    case 'u':                                                                   //virtual + 30
      vState[n+30] = newState;
    break;

  }

}

bool getUpEdgeActive(){
  bool tempReturn = false;

  uint8_t myDataByte = EEPROM.read(PC);
  uint8_t n = EEPROM.read(PC+1);
  n = n - 48;

  if((myDataByte) != 0){
    switch(myDataByte){
      case 'I':                                                                 //intput
        tempReturn = iUpEdge[n];
      break;
      case 'O':                                                                   //output
        tempReturn = oUpEdge[n];
      break;
      case 'V':                                                                   //virtual
        tempReturn = vUpEdge[n];
      break;
      case 'v':                                                                   //virtual + 10
        tempReturn = vUpEdge[n+10];
      break;
      case 'U':                                                                   //virtual + 20
        tempReturn = vUpEdge[n+20];
      break;
      case 'u':                                                                   //virtual + 30
        tempReturn = vUpEdge[n+30];
      break;

    }
  }
  else
    tempReturn = true;

  return tempReturn;
}

bool getNoValue(){
  bool tempReturn = false;

  uint8_t myDataByte = EEPROM.read(PC);
  PC++;
  uint8_t n = EEPROM.read(PC);
  n = n - 48;


  if((myDataByte) != 0){
    switch(myDataByte){
      case 'I':                                                                 //intput
        tempReturn = iState[n];
      break;
      case 'O':                                                                   //output
        tempReturn = oState[n];
      break;
      case 'V':                                                                   //virtual
        tempReturn = vState[n];
      break;
      case 'v':                                                                   //virtual + 10
        tempReturn = vState[n+10];
      break;
      case 'U':                                                                   //virtual + 20
        tempReturn = vState[n+20];
      break;
      case 'u':                                                                   //virtual + 30
        tempReturn = vState[n+30];
      break;

    }
  }
  else
    tempReturn = true;

  return tempReturn;
}

bool isSourceInt(){
  bool tempReturn = false;

  uint8_t myDataByte = EEPROM.read(PC);

  switch (myDataByte) {
    case 'D':                                                                   //int
      tempReturn = true;
    break;
    case 'd':                                                                   //int + 10
      tempReturn = true;
    break;
  }

  return tempReturn;
}

float getSource(){
  float tempReturn = 0;

  uint8_t myDataByte = EEPROM.read(PC);
  PC++;
  uint8_t n = EEPROM.read(PC);
  n = n - 48;

  switch(myDataByte){
    case 'p':                                                                   //analog input
      tempReturn = (float)readAnalogPin(n);
    break;
    case 'o':                                                                   //analog output
      tempReturn = (float)readAnalogOutput(n);
    break;
    case 'D':                                                                   //int
      tempReturn = (float)intValues[n];
    break;
    case 'd':                                                                   //int + 10
      tempReturn = (float)intValues[n+10];
    break;
    case 'L':                                                                   //long
      tempReturn = (float)dintValues[n];
    break;
    case 'H':                                                                   //long + 10
      tempReturn = (float)dintValues[n+10];
    break;
    case 'F':                                                                   //real
      tempReturn = realValues[n];
    break;
    default:
      tempReturn = 0;
      break;
  }

  return tempReturn;
}

void updateVariable(int tempPC, int32_t valueDest){
  uint8_t myDataByte = EEPROM.read(tempPC);
  uint8_t n = EEPROM.read(tempPC+1);
  n = n-48;

  switch(myDataByte){
        case 'D':                                                                   //int
          intValues[n] = (int16_t)valueDest;
        break;
        case 'd':                                                                   //int + 10
          intValues[n+10] = (int16_t)valueDest;
        break;
        case 'L':                                                                   //long
          dintValues[n] = valueDest;
        break;
        case 'H':                                                                   //long + 10
          dintValues[n+10] = valueDest;
        break;

  }
}

void setDest(float valueDest){

  uint8_t myDataByte = EEPROM.read(PC);
  PC++;
  uint8_t n = EEPROM.read(PC);
  n = n-48;

  switch(myDataByte){
        case 'x':
            writeServoPin(n, (int)valueDest);
        break;
        case 'o':                                                                   //Analog output
          writeAnalogPin(n, (int)valueDest);
        break;
        case 'D':                                                                   //int
          intValues[n] = (int16_t)valueDest;
        break;
        case 'd':                                                                   //int + 10
          intValues[n+10] = (int16_t)valueDest;
        break;
        case 'L':                                                                   //long
          dintValues[n] = (int32_t)valueDest;
        break;
        case 'H':                                                                   //long + 10
          dintValues[n+10] = (int32_t)valueDest;
        break;
        case 'F':                                                                   //real
          realValues[n] = valueDest;
        break;

  }

}

void setDest(int tempPC, float valueDest){

  uint8_t myDataByte = EEPROM.read(tempPC);
  uint8_t n = EEPROM.read(tempPC+1);
  n = n-48;

  switch(myDataByte){
        case 'x':
            writeServoPin(n, (int)valueDest);
        break;
        case 'o':                                                                   //Analog output
          writeAnalogPin(n, (int)valueDest);
        break;
        case 'D':                                                                   //int
          intValues[n] = (int16_t)valueDest;
        break;
        case 'd':                                                                   //int + 10
          intValues[n+10] = (int16_t)valueDest;
        break;
        case 'L':                                                                   //long
          dintValues[n] = (int32_t)valueDest;
        break;
        case 'H':                                                                   //long + 10
          dintValues[n+10] = (int32_t)valueDest;
        break;
        case 'F':                                                                   //real
          realValues[n] = valueDest;
        break;

  }

}


void checkSpace(){
  PC=0; //put the PC in the start of the memory
  int dataByte= EEPROM.read(PC);
  Serial.write(dataByte);
  while(dataByte!='z'){ //z is the value that indicate that the program has ended
    PC++;
    dataByte= EEPROM.read(PC);
    if(dataByte == 'R')
      Serial.println("");
    Serial.write(dataByte);
  }

  dataByte = PC+1;
  int tempPC = (100 * (dataByte))/805;

  Serial.println("");
  Serial.print("Program bytes: ");
  Serial.print(PC+1);
  Serial.print(" (");
  Serial.print(tempPC);
  Serial.println("%)");

  Serial.print("Free: ");
  tempPC = 100 - tempPC;
  Serial.print(tempPC);
  Serial.println("%");
  Serial.println(" ");
}

