//
// Wascoe Siding Loco Points interlocking
// R. Parnell 8/10/2023
//
// V5: 16/1/24 - bugs seemed to have been removed. Simulation Ok. Removal of 
// "serial print" to tidy up code and allow respective output to be used for signal lamp output.
// Found value for route 3 to be "010" instead of "10".

// 15/1/24: working through flickering issue and resolving. 
// Need to add feature whereby if conflicting signal switches are set,
// nothing happens. A unique scenario can exist when 7 points are reversed.

// V4: 14/1/24 - further simulation debugging, working through errors...
// V3: 12/1/24 - heartbeat not working, other minor issues. Suspect accidental changing of code
// that was still valid for compilation and accidentally saved. The bug to be found!
// Update: heartbeater timer was set to Zero! Fixed up and tested.

// - signals flicker on red when set to proceed. To be sorted out.

// 14/1/24 - flicker probably as a result of using serial print for debugging as D)/D1 are used
// as outputs. 

// V2 4/1/24: a realisation that the outputs should be active LOW, not high, to drive the relays.
// This version reworks the outputs to the opposite state of V1.

// 18/11/23 - points lever warning not working correctly. Pulses very randomly in any input state.


// ************************************

//  ***  *****  *   ****  *****
// *       *   * *  *   *   *
//  ***    *  ***** ****    *
//     *   *  *   * *  *    *
//  ***    *  *   * *   *   *
//
// ***************************************

// inputs - active "low"
// outputs - acitve "high"
// define outputs

int M1red = 0; // M1 red
int M1yel = 1; // yellow
int M1grn = 2; //  green

int M2red = 3;
int M2yel = 4;
int M2grn = 5;
int M2TO = 6;
int M2y1 = 7;
int M2y2 = 8;

int ST11red = 9;
int ST11yel = 10;
int ST11grn = 11;
int ST11TO = 12;

int ST13red = 13;
int ST13yelM = 14;
int ST13yelS = 15;

int ST12red = 16;
int ST12yel = 17;
int ST12grn = 18;
int ST12y1 = 19;
int ST12y2 = 20;

int HBon=0;
bool HBtoggle = false; // PLwarning LED toggle
//16/10/23

int displaydelay = 40; // minimum time to display each signal aspect

// points mimics redefined.
// 6 outputs all up.
// 5N, 5R (one relay, NC or NO contacts)
// Group A (part of 7 points on the main line)
// Group B (7 points "N" on main and station road)
// Group C (7 points "R")
// Group D (6R & 7R) OR (6N &7N)
// Group E (6N & 7R) OR (6R & 7N)

int pts5NR = 21; // normal, reverse, track circuit mimic
//int pts5R = 22;
int groupA = 22;
int groupB = 23;
int groupC = 24;
int groupD = 25;
int groupE = 26;


int pts5TC = 27;
int pts6TC = 28;
int pts7TC = 29;
      //int pts6N = 24;
      //int pts6R = 25;
                
     // int pts7N = 27;
     // int pts7R = 28;
                    
int pts9N = 30;
int pts9R = 31;
int pts9TC = 32; // not used at this point in time (reserved for possible use later)

int pts10N = 33;
int pts10R = 34;
int pts10TC = 35; // not used at this point in time

int pts11N = 36;
int pts11R = 37;
int pts11TC = 38; // not used at this point in time

int pts12N = 39;
int pts12R = 40;
int pts12TC = 41; // not used at this point in time

int PLRW = 42; // points lever reverse warning

// define inputs:

int emerg = 43; // emergency stop input

int M1proceed = 44;
int M2proceed = 45;
int ST12proceed = 46;
int ST1113proceed = 47;

int C2stop = 48; // is next signal C2 at stop?
int C4stop = 49;
int ST15stop = 50;
int M3stop = 51;

int pts5Ndet = A0; // detection of Normal
int pts5Rdet = A1; // detection of Reverse
int pts5block = A2; // track circuit input

int pts6Ndet = A3; // detection of Normal
int pts6Rdet = A4; // detection of Reverse
int pts6block = A5; // track circuit input

int pts7Ndet = A6; // detection of Normal
int pts7Rdet = A7; // detection of Reverse
int pts7block = A8; // track circuit input

int intransitLED = A9; // if any points are not normal or reverse 19/11/23
// not enough inputs for future block detection of 9, 10, 11 and 12 points
int hbLED = A10;

int pts9normal = A12; // 9-12 temporary for the purpose of displaying mimic and lever reverse warning
int pts10normal = A13;
int pts11normal = A14;
int pts12normal = A15;

unsigned long HBMillis = 500; 
unsigned long HBtimer = 500;
unsigned long HBstartMillis = 0;
unsigned long HBcurrentMillis = 0;

//unsigned long warningONcurrentmillis;
//unsigned long warningOFFcurrentmillis;
//unsigned long startMillis; // for starting countdown after blockwas occupied
//unsigned long warningmillis = 600; // time period for warning flashing on/off 50% duty cycle
unsigned long currentMillis; // what will be the current value to compare countdown to
bool leveralerton = false; // lever warning indicator toggle

bool warning5 = false; // flag for setting points lever warning alert
bool warning6 = false;
bool warning7 = false;
bool warning8 = false;
bool warning9 = false;
bool warning10 = false;
bool warning11 = false;
bool warning12 = false;

bool intransit5= false; // added 19/11/23
bool intransit6= false; // added 19/11/23
bool intransit7= false; // added 19/11/23
bool intransit8= false; // added 19/11/23
bool intransit9= false; // added 19/11/23
bool intransit10= false; // added 19/11/23
bool intransit11= false; // added 19/11/23
bool intransit12= false; // added 19/11/23

bool  block5occ = false;
bool  block6occ = false;
bool  block7occ = false;
bool  block9occ = false; // block 9 to 12 included to "future proof" programming
bool  block10occ = false;
bool  block11occ = false;
bool  block12occ = false;
bool  emergstop = false;
bool M1stopVal = false;
bool M2stopVal = false;
bool ST1113stopVal = false;
bool ST12stopVal = false;
bool C4nextstop = false;
bool C2nextstop = false;
bool ST15next = false;
bool M3next = false;
bool pts5Normal = false;
bool pts5Reverse = false;
bool pts6Normal = false;
bool pts6Reverse = false;

bool pts6N7N = true; // possible routes for 6 points, given other circumstances
bool pts6N7R = false; // main to/from yard
bool pts6R7N = false; // station to/from yard
bool pts6R7R = false; // station to/from main

bool pts7Normal = false;
bool pts7Reverse = false;

bool pts9Normal = true;
bool pts10Normal = true;
bool pts11Normal = true;
bool pts12Normal = true;

int route = 100; // 1 of 6 possible combinations of routes with the possible points settings




//#########################

void setup() {


//Serial.begin(9600); // open the serial port at 9600 bps:
// serial port for debugging purposes only

// startMillis = millis(); //start timer value for alert
HBstartMillis = millis(); 

// digital inputs:
  pinMode(emerg, INPUT_PULLUP); //INPUT_PULLUP
  pinMode(M1proceed, INPUT_PULLUP);
  pinMode(M2proceed, INPUT_PULLUP);
  pinMode(ST12proceed, INPUT_PULLUP);
  pinMode(ST1113proceed, INPUT_PULLUP);
  pinMode(C2stop, INPUT_PULLUP);
  pinMode(C4stop, INPUT_PULLUP);
  pinMode(ST15stop, INPUT_PULLUP);
  pinMode(M3stop, INPUT_PULLUP);
  // analogue inputs
  pinMode(pts5Ndet, INPUT);
  pinMode(pts5Rdet, INPUT);
  pinMode(pts5block, INPUT);
  pinMode(pts6Ndet, INPUT);
  pinMode(pts6Rdet, INPUT);
  pinMode(pts6block, INPUT);
  pinMode(pts7Ndet, INPUT);
  pinMode(pts7Rdet, INPUT);
  pinMode(pts7block, INPUT);
  pinMode(pts9normal, INPUT);
  pinMode(pts10normal, INPUT);
  pinMode(pts11normal, INPUT);
  pinMode(pts12normal, INPUT);

  pinMode(M1red, OUTPUT);
  pinMode(M1yel, OUTPUT);
  pinMode(M1grn, OUTPUT);

  pinMode(M2red, OUTPUT);
  pinMode(M2yel, OUTPUT);
  pinMode(M2grn, OUTPUT);
  pinMode(M2TO, OUTPUT);
  pinMode(M2y1, OUTPUT);
  pinMode(M2y2, OUTPUT);

  pinMode(ST11red, OUTPUT);
  pinMode(ST11yel, OUTPUT);
  pinMode(ST11grn, OUTPUT);
  pinMode(ST11TO, OUTPUT);

  pinMode(ST13red, OUTPUT);
  pinMode(ST13yelM, OUTPUT);
  pinMode(ST13yelS, OUTPUT);

  pinMode(ST12red, OUTPUT);
  pinMode(ST12yel, OUTPUT);
  pinMode(ST12grn, OUTPUT);
  pinMode(ST12y1, OUTPUT);
  pinMode(ST12y2, OUTPUT);

  pinMode(intransitLED, OUTPUT);
  pinMode(hbLED, OUTPUT);
  
  pinMode(pts5NR, OUTPUT); // normal/reverse
  //pinMode(pts5R, OUTPUT);
  pinMode(groupA, OUTPUT); // 16/10/23
  pinMode(groupB, OUTPUT);
  pinMode(groupC, OUTPUT);
  pinMode(groupD, OUTPUT);
  pinMode(groupE, OUTPUT);
  
 
  //pinMode(pts6N, OUTPUT);
  //pinMode(pts6R, OUTPUT);
  //pinMode(pts7N, OUTPUT);
 // pinMode(pts7R, OUTPUT);
 
 
  pinMode(pts5TC, OUTPUT);
  pinMode(pts6TC, OUTPUT);
  pinMode(pts7TC, OUTPUT);

  pinMode(pts9N, OUTPUT);
  pinMode(pts9R, OUTPUT);
  pinMode(pts9TC, OUTPUT); // not used at this point in time (reserved for possible use later)

  pinMode(pts10N, OUTPUT);
  pinMode(pts10R, OUTPUT);
  pinMode(pts10TC, OUTPUT); // not used at this point in time

  pinMode(pts11N, OUTPUT);
  pinMode(pts11R, OUTPUT);
  pinMode(pts11TC, OUTPUT); // not used at this point in time

  pinMode(pts12N, OUTPUT);
  pinMode(pts12R, OUTPUT);
  pinMode(pts12TC, OUTPUT); // not used at this point in time

  pinMode(PLRW, OUTPUT); // points lever reverse warning

// turn all outputs off (HIGH)

  digitalWrite(M1red, HIGH);
  digitalWrite(M1yel, HIGH);
  digitalWrite(M1grn, HIGH);

  digitalWrite(M2red, HIGH);
  digitalWrite(M2yel, HIGH);
  digitalWrite(M2grn, HIGH);
  digitalWrite(M2TO, HIGH);
  digitalWrite(M2y1, HIGH);
  digitalWrite(M2y2, HIGH);

  digitalWrite(ST11red, HIGH);
  digitalWrite(ST11yel, HIGH);
  digitalWrite(ST11grn, HIGH);
  digitalWrite(ST11TO, HIGH);

  digitalWrite(ST13red, HIGH);
  digitalWrite(ST13yelM, HIGH);
  digitalWrite(ST13yelS, HIGH);

  digitalWrite(ST12red, HIGH);
  digitalWrite(ST12yel, HIGH);
  digitalWrite(ST12grn, HIGH);
  digitalWrite(ST12y1, HIGH);
  digitalWrite(ST12y2, HIGH);

//16/10/23
  digitalWrite(pts5NR, HIGH); // normal, reverse, track circuit mimic
  //digitalWrite(pts5R, LOW);
  digitalWrite(groupA, HIGH);
  digitalWrite(groupB, HIGH);
  digitalWrite(groupC, HIGH);
  digitalWrite(groupD, HIGH);
  digitalWrite(groupE, HIGH);
  
  digitalWrite(pts5TC, HIGH);
  digitalWrite(pts6TC, HIGH);
  digitalWrite(pts7TC, HIGH);

  digitalWrite(pts9N, HIGH);
  digitalWrite(pts9R, HIGH);
  digitalWrite(pts9TC, HIGH); // not used at this point in time (reserved for possible use later)

  digitalWrite(pts10N, HIGH);
  digitalWrite(pts10R, HIGH);
  digitalWrite(pts10TC, HIGH); // not used at this point in time

  digitalWrite(pts11N, HIGH);
  digitalWrite(pts11R, HIGH);
  digitalWrite(pts11TC, HIGH); // not used at this point in time

  digitalWrite(pts12N, HIGH);
  digitalWrite(pts12R, HIGH);
  digitalWrite(pts12TC, HIGH); // not used at this point in time

  digitalWrite(PLRW, HIGH); // points lever reverse warning

  // set all signals to stop, since we don't know much else!
  M1stop();
  M2stop();
  ST12stop();
  ST11stop();
  ST13stop();


  //                                   ###################################
  ///                                     ### end of initialisation ###
  ///                                     ### end of initialisation ###
  ///                                     ### end of initialisation ###
  //                                   ###################################
}

//#########################

//            START LOOP ##
//            START LOOP ##
//            START LOOP ##
//            START LOOP ##
//             START LOOP ##

void loop() {

  readinputs();
  
 //currentMillis = millis();
  // suspect that the flasher uses up too much memory and causes erractic behaviour. 19/11/23
  
      // flash heartbeat LED along the way
    HBcurrentMillis = millis();
      if (HBcurrentMillis - HBstartMillis >= HBtimer){
    HBtoggle = !HBtoggle; // invert the status from true/false to false/true 
        digitalWrite(hbLED,HBtoggle); // turn HB on/off
    HBstartMillis = HBcurrentMillis;
    } 

  route = 0; // reset route options to zero
  //HBtimer = millis();

  // display points settings and set red signals if against the points
  // points 5,6,7 have been programmed for possible future inclusing of points detection in both N and R

  // since no point blade detection at the time of writing, points 5, 6, 7 are assumed to be set to "reverse"
  // if the lever is not set to "normal"
  
  // pts5NR relay. HIGH = "normal" mimic
  //              HIGH = "reverse" mimic
 
if ((pts5Normal==true)&&(pts5Reverse==false)) {
    digitalWrite(pts5NR, HIGH);
    warning5 = false;
    intransit5=false;
  } else if ((pts5Normal == false)&&(pts5Reverse==true)) {
    digitalWrite(pts5NR, LOW);
    warning5 = true;
    intransit5=false;
    route = route + 100; // route will be 5 or 6 into yard 2
  } else if ((pts5Normal==false)&&(pts5Reverse==false)){
    digitalWrite(pts5NR, LOW);
    warning5 = true;
    intransit5=true;
  }
  
  if ((pts6Normal==false)&&(pts6Reverse==false)) intransit6=true;
  if ((pts7Normal==false)&&(pts7Reverse==false)) intransit7=true;
  
  if ((pts6Normal==true)&&(pts6Reverse==false)) intransit6=false;
  if ((pts7Normal==true)&&(pts7Reverse==false)) intransit7=false;
  if ((pts6Normal==false)&&(pts6Reverse==true)) intransit6=false;
  if ((pts7Normal==false)&&(pts7Reverse==true)) intransit7=false;
  // 6
  
  if ((pts7Normal == true) && (pts6Normal == true)) {
    digitalWrite(groupA,LOW);
    digitalWrite(groupB,LOW);
    digitalWrite(groupD,LOW);
    digitalWrite(groupC,HIGH);
    digitalWrite(groupE,HIGH);
    ST13stop();
    warning7 = false;
    warning6 = false;
  }

  if ((pts7Reverse == true) && (pts6Reverse == true)) { //7 points reversed. M1 must be STOP
    digitalWrite(groupA,LOW);
    digitalWrite(groupC,LOW);
    digitalWrite(groupD,LOW);
    digitalWrite(groupB,HIGH);
    digitalWrite(groupE,HIGH);
    warning7 = true;
    warning6 = true;
    M1stop();
    ST13stop();
    ST12stop();
    route = route + 11;
   // Serial.println("7R & 6R");//debugging
  }

  if ((pts7Normal == true) && (pts6Reverse == true)) {
    digitalWrite(groupA,LOW);
    digitalWrite(groupB,LOW);
    digitalWrite(groupE,LOW);
    digitalWrite(groupC,HIGH);
    digitalWrite(groupD,HIGH);
    ST11stop();
    warning6 = true;
    warning7 = false;
    route = route + 10;
      }
  if ((pts7Reverse == true) && (pts6Normal == true)) { //7 points reversed. M1 must be STOP
    //Serial.println("7 reversed, 6 normal");//debugging
    digitalWrite(groupA,LOW);
    digitalWrite(groupC,LOW);
    digitalWrite(groupE,LOW);
    digitalWrite(groupB,HIGH);
    digitalWrite(groupD,HIGH);
    warning7 = true;
    warning6 = false;
    M1stop();
    ST11stop();
    //Serial.println("ST11 stoppped line 498"); //debugging
    ST12stop();
    route = route + 1;
    //Serial.println("7R & 6N");//debugging
  }
  //bool pts6routeNstation = true; // possible routes for 6 points, given other circumstances
  //bool pts6routeNX = false; // normal - crossing route from main to/from yard
  //bool pts6routeSTM = false; // station to/from main
  //bool pts6routeyardSTN = false; // station to/from yard
  //bool pts6Normal = false;
  //bool pts6Reverse = false;

  if (pts9Normal == true) {
    digitalWrite(pts9N, LOW);
    warning9 = false;
  } else {
    digitalWrite(pts9N, HIGH);
    warning9 = true;
  }

  if (pts10Normal == true) {
    digitalWrite(pts10N, LOW);
    warning10 = false;
  } else {
    digitalWrite(pts10N, HIGH);
    warning10 = true;
  }

  if (pts11Normal == true) {
    digitalWrite(pts11N, LOW);
    warning11 = false;
  } else {
    digitalWrite(pts11N, HIGH);
    warning11 = true;
  }

  if (pts12Normal == true) {
    digitalWrite(pts12N, LOW);
    warning12 = false;
  } else {
    digitalWrite(pts12N, HIGH);
    warning12 = true;
  }
 // currentMillis = millis();
  
  
  //
  // points lever alert warning light
  //

              if ((intransit6==true)||(intransit5==true)||(intransit7==true)||(intransit9==true)||(intransit10==true)||(intransit11==true)||(intransit12==true))   digitalWrite(intransitLED,LOW);
              if ((intransit5==false)&&(intransit6==false))  digitalWrite(intransitLED,HIGH);
 
               if ((warning5 == false) && (warning6 == false) && (warning7 == false) && (warning9 == false) && (warning10 == false) && (warning11 == false) && (warning12 == false)) {
              //turn warning off
                leveralerton = false;
              } else leveralerton = true;
  
 

              if (leveralerton==true){ //just turn it on steady 
              //Serial.println("lever alert is on"); // debugging
               digitalWrite(PLRW, LOW);
                }
              else digitalWrite(PLRW, HIGH);
  //
  // end points lever alert warning light
  //

  // display track circuit occupancy status of each block
  // check block occupancy here. Display respective mimics and set appropriate signals to stop
  //Should blocks be occupied, then skip the setting signals bit.
  // affected signals for block occupancy:
  // block 5 - ST13 - stop
  //            ST12 and M2 only if routes set
  // block 6 - ST11 & ST12 stop
  //            M2 and ST13 if routes set
  // block 7 - M2 and M1 stop
  //          ST11 and ST13 if routes set
  if (block5occ == true) {
    digitalWrite(pts5TC, LOW);
  } else {
    digitalWrite(pts5TC, HIGH);
  }

  if (block6occ == true) {
    digitalWrite(pts6TC, LOW);
  } else {
    digitalWrite(pts6TC, HIGH);
  }

  if (block7occ == true) {
    digitalWrite(pts7TC, LOW);
  } else {
    digitalWrite(pts7TC, HIGH);
  }
// 
// not enough inputs for blocks 9 to 12 to be programmed. Requires separate controller. Not wired or configured
// for detection or signals at time of writing. 13/10/23.

  // at this point - all points settings and occupancies are shown.
  // now check for emergnecy stop. If no emerg, check what routes are set and then signals settings etc
  // add in section below such that if a switch is set to stop, then the respective signals
  // will display stop. 15/1/24
  
  if (ST1113stopVal == true) {
          ST11stop();
          ST13stop();
  }
  if (ST12stopVal == true){
        ST12stop();
  }        
  if (M1stopVal == true){
    M1stop();
  }
  if (M2stopVal == true){
    M2stop();
  }
  
  if (emergstop == true) {
    M1stop();
    M2stop();
    ST12stop();
    ST11stop();
    ST13stop();
      }
  else {
    //for each given route setting option, place known affected conflicting signals to stop
    // then see if block affecting that route is occupied or not.
    // then check if signal switch is set to proceed.
    //  then check if next signal is at stop or not,
    // show respective aspect

    // route 1: 6N and 7N (route value 0 or 100)
    // 1111111111111111111111111111111111111111111111111111

    if (route == 0 || route == 100) {
      //route 1 set
      ST13stop(); //it's a given that this one will be at stop
      if (block6occ == true) {
        ST12stop();
        ST11stop();
              } else {
        //see if the respective signal switch is set to proceed, since block is clear
        if (ST1113stopVal == false) {
          ST12stop();
          //ST11 is set to proceed, now checking next block
          if (ST15next == true) { // true if at stop, false if at proceed
            //display caution if true, otherwise display clear
            //set ST11 to caution and ST12 to stop
            ST11caution();
          } else {
            // set ST11 to clear here and ST12 to stop
            ST11clear();
          }
        }
            if(ST1113stopVal == true){
              ST11stop();
            }
            if (ST12stopVal == true){
              ST12stop();
            }
        //now check ST12 stop value and set signal accordingly
        if (ST12stopVal == false) {
          ST11stop();
           //ST12 is set to proceed, now check next block
          if (C4nextstop == true) {
            // display caution if true, otherwise display clear
            ST12caution();
          } else {
            // set ST12 to clear here and ST11 to stop
            ST12clear();
          }
        }

      } //<- this is the end of block 6 occupancy and signal setting check

      points7NormalSignals();

    } //<- this is the end of "route 1" subroutine

// 2222222222222222222222222222222222222222222222222222222222
    // route 2 - points 5NorR, 6R, 7R
    if (route == 11 || route == 111)  {
      ST13stop(); //it's a given that this one will be at stop
      M1stop();
      ST12stop();
      
      if (block6occ == true || block7occ == true) {
        M2stop();
        ST11stop();
            } else {
        //see if the respective signal switch is set to proceed, since block is clear
        if (ST1113stopVal == false && M2stopVal == true) {
          M2stop();
          ST11turnout();
        } else {
          ST11stop();
            //M2stop(); // <- this appears to be erroneous 14/1/24
          //Serial.println("M2 stopped by line 676"); //debugging
        }

        //now check M2 stop value and set signal accordingly
        if (M2stopVal == false && ST1113stopVal == true) {
          ST11stop();
          M2turnout();
          //ST12 is set to proceed
        } else {
          // set ST12 to clear here and ST11 to stop
          M2stop();
          //ST11stop(); // <- this appears to be erroneous 14/1/24
          //Serial.println("ST11 stoppped line 697"); //debugging
        }


      } //<- this is the end of route 2 occupancy and signal setting check

    } //<- this is the end of "route 2" subroutine

//333333333333333333333333333333333333333333333333333333333333333333333333333

    // route 3 - points 5N, 6R, 7N
    if (route == 10) {
     // Serial.println("route 3 - 5N, 6R, 7N"); //debugging
      //route 1 set
      ST11stop(); //it's a given that this one will be at stop
        if (block6occ == true || block5occ == true) {
        ST13stop();
        ST12stop();
      } else {
       // Serial.println("checking switch ST1113 and ST12"); // debugging
        //see if the respective signal switch is set to proceed, since block is clear
        if (ST1113stopVal == false) {
          ST12stop(); //opposing signal
          ST13station();//ST13 is set to proceed
        } 
        if (ST1113stopVal == true) {
          ST13stop();
        }

        //now check ST12 stop value and set signal accordingly
        if (ST12stopVal == false) {
          ST13stop();
          //ST12 is set to proceed
          ST12yard1();
        } else {
          ST12stop();
        }
if (ST12stopVal == true) {
          ST12stop();
        }
      } //<- this is the end of block 6 occupancy and signal setting check

      points7NormalSignals(); //use this void as it is common for route 1 and route 3

    } //<- this is the end of "route 3" subroutine

//444444444444444444444444444444444444444444444444444444444444444444
    // route 4 - points 5N, 6N, 7R
    if (route == 1) {
      //route 4 set
      // STOP = M1, ST11, ST12
      // M2 and ST13 available for proceed indications
      M1stop(); //it's a given that this one will be at stop
      ST11stop(); //it's a given that this one will be at stop
      ST12stop(); //it's a given that this one will be at stop
      if (block6occ == true || block5occ == true || block7occ == true) {
        M2stop();
        ST13stop();
      } else {
        //see if the respective signal switch is set to proceed, since block is clear
        //anticlockwise:
        if (ST1113stopVal == false && M2stopVal == true) {
          M2stop(); //opposing signal
          ST13main();
          } else {
          ST13stop();
          //M2stop(); // <- this appears to be erroneous 14/1/23
              }

        //now check M2 stop value and set signal accordingly
        //clockwise:
        if (M2stopVal == false && ST1113stopVal == true) {
          ST13stop();
          //ST12 is set to proceed
          M2yard1();
        } 
        
        /*else {
          M2stop();
          Serial.println("M2 stopped by line 764"); // debugging
          ST13stop();
          Serial.println("ST13 set to stop by line 783");//debugging
        } */ //this group from else is deemed erroneous 15/1/24. Simulated OK as remarked out.

      } //<- this is the end of block 6 occupancy and signal setting check

    } //<- this is the end of "route 4" subroutine

//55555555555555555555555555555555555555555555555555555555555555
    // route 5 - points 5R, 6N,7R
    if (route==101)  {
      // STOP = M1, ST11, ST12
      // M2 and ST13 available for proceed indications
      M1stop(); //it's a given that this one will be at stop
      ST11stop(); //it's a given that this one will be at stop
      ST12stop(); //it's a given that this one will be at stop
        
      if (block6occ == true || block5occ == true || block7occ == true) {
        M2stop();
        ST13stop();
      } else {
        //see if the respective signal switch is set to proceed, since block is clear
        //anticlockwise:
        if (ST1113stopVal == false && M2stopVal == true) {
          M2stop(); //opposing signal
          ST13main();
          } 
          /*else {
          ST13stop();
          //M2stop(); // <- this line appears to be erroneous 14/1/24
          //Serial.println("M2 stopped by line 796"); // debugging
        } */ //this group from else remarked out 15/1/24

        //now check M2 stop value and set signal accordingly
        //clockwise:
        if (M2stopVal == false && ST1113stopVal == true) {
          ST13stop();
          //ST12 is set to proceed
          M2yard2();
        }
        
        /* else {
          M2stop();
          Serial.println("M2 stopped by line 807"); // debugging
          ST13stop();
          Serial.println("ST13 stopped by line 828"); //debugging
        } */ // remarked out from else, seems erroneous from simulation 15/1/24

      } //<- this is the end of block 6 occupancy and signal setting check

    } //<- this is the end of "route 5" subroutine

//666666666666666666666666666666666666666666666666666666
    // route 6 - points 5R, 6R, 7N
    if (route==110) {
      // ST11 stop
      // M1, M2, ST12, ST13 available to set to proceed
   
         ST11stop(); //it's a given that this one will be at stop
          if (block6occ == true || block5occ == true) {
        ST13stop();
        ST12stop();
      } else {
        //see if the respective signal switch is set to proceed, since block is clear
        if (ST1113stopVal == false) {
          ST12stop(); //opposing signal
          ST13station();//ST13 is set to proceed
        } else {
          ST13stop();
        }

        //now check ST12 stop value and set signal accordingly
        if (ST12stopVal == false) {
          ST13stop();
          //ST12 is set to proceed
          ST12yard2();
        } else {
          ST12stop();
        }

      } //<- this is the end of block 6 occupancy and signal setting check

      points7NormalSignals(); //use this void as it is common for route 1, 3 and 6

    } //<- this is the end of "route 6" subroutine

  } // <- this is the end of the "else" from emergency stop being active or not

} //            <- this is the end of the main loop void

// ##########################################################################################

void readinputs() {
  // read all input values
  if (digitalRead(emerg) == LOW ) {
    emergstop = true;
  } else emergstop = false;

  if (digitalRead(pts5block) == LOW ) {
    block5occ = true;
  } else block5occ = false;

  if (digitalRead(pts6block) == LOW ) {
    block6occ = true;
  } else block6occ = false;

  if (digitalRead(pts7block) == LOW ) {
    block7occ = true;
  } else block7occ = false;

  if (digitalRead(M1proceed) == LOW) {
    M1stopVal = false;
  } else M1stopVal = true;

  if (digitalRead(M2proceed) == LOW) {
    M2stopVal = false;
  } else M2stopVal = true;

  if (digitalRead(ST1113proceed) == LOW) {
    ST1113stopVal = false;
  } else ST1113stopVal = true;

  if (digitalRead(ST12proceed) == LOW) {
    ST12stopVal = false; // the switch is set to proceed - therefore, not at stop
  } else ST12stopVal = true;

  if (digitalRead(C2stop) == LOW) {
    C2nextstop = true; // next signal is at stop, so this value is true
  } else C2nextstop = false;

  if (digitalRead(C4stop) == LOW) {
    C4nextstop = true; // next signal is at stop, so this value is true
  } else C4nextstop = false;

  if (digitalRead(ST15stop) == LOW) {
    ST15next = true; // next signal is at stop, so this value is true
  } else ST15next = false;

  if (digitalRead(M3stop) == LOW) {
    M3next = true; // next signal is at stop, so this value is true
  } else M3next = false;
// #5 points:
  if (digitalRead(pts5Ndet) == LOW) pts5Normal = true; 
   else (pts5Normal = false);

  if (digitalRead(pts5Rdet) == LOW) pts5Reverse = true; 
   else (pts5Reverse = false); 

// #6 points:
  if (digitalRead(pts6Ndet) == LOW) {
    pts6Normal = true; 
  } else pts6Normal = false;

  if (digitalRead(pts6Rdet) == LOW) {
    pts6Reverse = true; 
  } else pts6Reverse = false;

// #7 points:
  if (digitalRead(pts7Ndet) == LOW) {
    pts7Normal = true; 
  } else pts7Normal = false;

  if (digitalRead(pts7Rdet) == LOW) {
    pts7Reverse = true; 
  } else pts7Reverse = false;

  if (digitalRead(pts9normal) == LOW) { // points 9-12 are only checked if normal, since there are no signals for these at this time of creating the code
    pts9Normal = true; 
  } else pts9Normal = false;

  if (digitalRead(pts10normal) == LOW) {
    pts10Normal = true; 
  } else pts10Normal = false;

  if (digitalRead(pts11normal) == LOW) {
    pts11Normal = true; 
  } else pts11Normal = false;

  if (digitalRead(pts12normal) == LOW) {
    pts12Normal = true; 
  } else pts12Normal = false;

//Serial.println("end of reading inputs"); // debugging

} //              <- end of reading inputs void



// ##########################################################################################
//##### signal indications:
// added short delay to display each aspect, for switch debounce and rapid changing switches by signaller

void M1stop() {
  
  digitalWrite(M1red, LOW);
  digitalWrite(M1yel, HIGH);
  digitalWrite(M1grn, HIGH);
  //Serial.println("M1 stop"); // debugging
  delay (displaydelay);
}

void M1caution() {
  digitalWrite(M1red, HIGH);
  digitalWrite(M1yel, LOW);
  digitalWrite(M1grn, HIGH);
  //Serial.println("M1 caution"); // debugging
  delay (displaydelay);
}

void M1clear() {
  digitalWrite(M1red, HIGH);
  digitalWrite(M1yel, HIGH);
  digitalWrite(M1grn, LOW);
  //Serial.println("M1 clear"); // debugging
  delay (displaydelay);
}

void M2stop() {
  digitalWrite(M2red, LOW);
  digitalWrite(M2yel, HIGH);
  digitalWrite(M2grn, HIGH);
  digitalWrite(M2TO, HIGH);
  digitalWrite(M2y1, HIGH);
  digitalWrite(M2y2, HIGH);
  //Serial.println("M2 stop"); // debugging
  delay (displaydelay);
}

void M2caution() {
  digitalWrite(M2red, HIGH);
  digitalWrite(M2yel, LOW);
  digitalWrite(M2grn, HIGH);
  digitalWrite(M2TO, HIGH);
  digitalWrite(M2y1, HIGH);
  digitalWrite(M2y2, HIGH);
  //Serial.println("M2 caution"); // debugging
  delay (displaydelay);
}

void M2clear() {
  digitalWrite(M2red, HIGH);
  digitalWrite(M2yel, HIGH);
  digitalWrite(M2grn, LOW);
  digitalWrite(M2TO, HIGH);
  digitalWrite(M2y1, HIGH);
  digitalWrite(M2y2, HIGH);
  //Serial.println("M1 clear"); // debugging
  delay (displaydelay);
}

void M2turnout() {
  // for turnouts and yard routes, red lamp/marker light will activate via diode gate within signal head
  
  digitalWrite(M2red, HIGH);
  digitalWrite(M2yel, HIGH);
  digitalWrite(M2grn, HIGH);
  digitalWrite(M2TO, LOW);
  digitalWrite(M2y1, HIGH);
  digitalWrite(M2y2, HIGH);
  //Serial.println("M2 turnout "); // debugging
  delay (displaydelay);
}

void M2yard1() {
  digitalWrite(M2red, HIGH);
  digitalWrite(M2yel, HIGH);
  digitalWrite(M2grn, HIGH);
  digitalWrite(M2TO, HIGH);
  digitalWrite(M2y1, LOW);
  digitalWrite(M2y2, HIGH);
  //Serial.println("M2 yard 1 "); // debugging
  delay (displaydelay);
}

void M2yard2() {
  digitalWrite(M2red, HIGH);
  digitalWrite(M2yel, HIGH);
  digitalWrite(M2grn, HIGH);
  digitalWrite(M2TO, HIGH);
  digitalWrite(M2y1, HIGH);
  digitalWrite(M2y2, LOW);
  //Serial.println("M2 yard 2 "); // debugging
  delay (displaydelay);
}
void ST11stop() {
  digitalWrite(ST11red, LOW);
  digitalWrite(ST11yel, HIGH);
  digitalWrite(ST11grn, HIGH);
  digitalWrite(ST11TO, HIGH);
  //Serial.println("ST11 stop"); // debugging
  delay (displaydelay);
  
}
void ST11caution() {
  digitalWrite(ST11red, HIGH);
  digitalWrite(ST11yel, LOW);
  digitalWrite(ST11grn, HIGH);
  digitalWrite(ST11TO, HIGH);
  //Serial.println("ST11 caution"); // debugging
  delay (displaydelay);
}
void ST11clear() {
  digitalWrite(ST11red, HIGH);
  digitalWrite(ST11yel, HIGH);
  digitalWrite(ST11grn, LOW);
  digitalWrite(ST11TO, HIGH);
 // Serial.println("ST11 clear"); // debugging
  delay (displaydelay);
}
void ST11turnout() {
  digitalWrite(ST11red, HIGH);
  digitalWrite(ST11yel, HIGH);
  digitalWrite(ST11grn, HIGH);
  digitalWrite(ST11TO, LOW);
  //Serial.println(" ST11 turnout "); // debugging
  delay (displaydelay);
}
void ST12stop() { // semaphore signal

  digitalWrite(ST12red, LOW); // also guard's indicator 4/1/24
  digitalWrite(ST12yel, HIGH);
  digitalWrite(ST12grn, HIGH);
  digitalWrite(ST12y1, HIGH);
  digitalWrite(ST12y2, HIGH);
  //Serial.println("ST12 stop"); // debugging
  delay (displaydelay);
}
void ST12caution() { // semaphore signal

  digitalWrite(ST12red, HIGH);
  digitalWrite(ST12yel, LOW);
  digitalWrite(ST12grn, HIGH);
  digitalWrite(ST12y1, HIGH);
  digitalWrite(ST12y2, HIGH);
  //Serial.println(" ST12 caution"); // debugging
  delay (displaydelay);
}
void ST12clear() { // semaphore signal

  digitalWrite(ST12red, HIGH);
  digitalWrite(ST12yel, HIGH);
  digitalWrite(ST12grn, LOW);
  digitalWrite(ST12y1, HIGH);
  digitalWrite(ST12y2, HIGH);
 // Serial.println(" ST12 clear"); // debugging
  delay (displaydelay);
}
void ST12yard1() { // semaphore signal

  digitalWrite(ST12red, HIGH);
  digitalWrite(ST12yel, HIGH);
  digitalWrite(ST12grn, HIGH);
  digitalWrite(ST12y1, LOW);
  digitalWrite(ST12y2, HIGH);
  //Serial.println("ST12 yard 1"); // debugging
  delay (displaydelay);
}
void ST12yard2() { // semaphore signal

  digitalWrite(ST12red, HIGH);
  digitalWrite(ST12yel, HIGH);
  digitalWrite(ST12grn, HIGH);
  digitalWrite(ST12y1, HIGH);
  digitalWrite(ST12y2, LOW);
 //Serial.println("  ST12 yard 2"); // debugging
  delay (displaydelay);
}

void ST13stop() {
  digitalWrite(ST13red, LOW);
  digitalWrite(ST13yelM, HIGH);
  digitalWrite(ST13yelS, HIGH);
  //Serial.println("ST13 stop"); // debugging
  delay (displaydelay);
  
}
void ST13main() {
  digitalWrite(ST13red, HIGH);
  digitalWrite(ST13yelM, LOW);
  digitalWrite(ST13yelS, HIGH);
 // Serial.println("ST13 main"); // debugging
  delay (displaydelay);
}
void ST13station() {
  digitalWrite(ST13red, HIGH);
  digitalWrite(ST13yelM, HIGH);
  digitalWrite(ST13yelS, LOW);
  //Serial.println("ST13 station"); // debugging
  delay (displaydelay);
}
void points7NormalSignals() {
  // common for route 1 and 3
  if (M1stopVal == true){
    M1stop();
  }
  if (M2stopVal == true){
    M2stop();
  }
  
  if (block7occ == true) {
    M1stop();
    M2stop();
      } else {
    // block 7 is not occupied, check signal switch setting
    if (M1stopVal == false) {
      //M1 is set to proceed. Set M2 to stop and see if M1 caution or clear
      M2stop();
     // Serial.println("M2 stopped by line 1123"); // debugging
            if (C2nextstop == true) {
        // Set M1 to caution
        M1caution();
      } else {
        // set M1 to clear
        M1clear();
      }
    }

    if (M2stopVal == false) {
      // now check opposite direction etc
      M1stop();
     // Serial.println("M2 stopVal is false");//debugging
      if (M3next == true) { // if M3 is at stop, then display caution. If not, display clear.
        M2caution();
      } else {
        M2clear();
      }

    }

  } //<- this is the end of setting the main line signal after checking block7 occupancy

}