/*

Arduino Nano - old bootloader
Robert Parnell.
27/5/22
Wascoe Siding - signal module

V1 - create basic structure
V2 - 10/6/22. Simulated on-line and tested OK. To check on real hardware.
  Signal 1 has 2x turnout indicators and track circuit.
  Signal 2 does not have a separate track circuit (shared), no separate turnout indicators.


board outputs:
S1red Signal 1 - red
S1yel Signal 1 - yellow
S1grn Signal 1 - green
S1toL Signal 1 - turnout L
S1toR Signal 1 - turnout R
TC1   Panel mimic - track circuit 1
TC2   Panel mimic - track circuit 2 - XXXX not required, to be removed. Make this emergency display.
S2red Signal 2 - red
S2yel Signal 2 - yellow
S2grn Signal 2 - green

board inputs:
track circuit 1
emergency stop
signal box proceed - signal 1
signal box proceed - signal 2 (if either input is inactive, then signal is at stop)
next signal ahead status (stop or proceed)
turnout L (from lever) OR signal box proceed in other direction
turnout R - from lever
turnout 3 - from lever


*/

//outputs:
int S1red = 2;// D2 etc
int S1yel = 3; 
int S1grn = 4; 
int S1toL = 5; 
int S1toR = 6; 
int EMERGind = 7; 
int TC1 = 8;
int TC2 = 9; // note - there is only one track circuit input, this isn't required 
int S2red = 10; 
int S2yel = 11; 
int S2grn  = 12; 

//inputs:
int trackcircuit1 = A0;
int emergencystop = A1;
int signal1proceed = A2;
int signal2proceed = A3; 
int signal1aheadstatus = A4; 
int turnoutL = A5;
int turnoutR = A6; 
int signal2aheadstatus = A7;

// input values:
int trackcct1Val = 1000;
int emergStopVal = 1000;
int signal1Val = 1000;
int signal2Val = 1000;
int signal1aheadVal = 1000;
int signal2aheadVal = 1000;
int turnoutLVal = 1000;
int turnoutRVal = 1000;


int testtime = 100; // milliseconds for test lamp sequence

// for setting signal to "caution" after the block has become unoccupied - if signal is set to full clear
int blockwasoccupied = false; //
int blockisoccupied = false; //
unsigned long startMillis; // for starting countdown after blockwas occupied
unsigned long sigatStopMillis; // for 2 second debounce of track circuit
unsigned long cautiontimer = 8000; // time period for countdown (effectively less 2secs due to debounce timer)
unsigned long currentMillis; // what will be the current value to compare countdown to



void setup() {
  
  pinMode(S1red, OUTPUT);
  pinMode(S1yel, OUTPUT);
  pinMode(S1grn, OUTPUT);
  pinMode(S2red, OUTPUT);
  pinMode(S2yel, OUTPUT);
  pinMode(S2grn, OUTPUT);
  pinMode(S1toL, OUTPUT);
  pinMode(S1toR, OUTPUT);
  pinMode(EMERGind, OUTPUT);
  pinMode(TC1, OUTPUT);
  pinMode(TC2, OUTPUT);
  
  pinMode(trackcircuit1, INPUT);
  pinMode(emergencystop, INPUT);
  pinMode(signal1proceed, INPUT);
  pinMode(signal2proceed, INPUT);
  pinMode(signal1aheadstatus, INPUT);
  pinMode(turnoutL, INPUT);
  pinMode(turnoutR, INPUT);
  pinMode(signal2aheadstatus, INPUT);

  startuptest();
  Serial.begin(115200); // Any baud rate should work
  Serial.println("Hello Arduino\n");
    
}

void loop() {  
  // read input values
  // display appropriate signal
  // go back and do it again!
  readinputvalues();
  displaysignals();
    delay(200);
}

void readinputvalues(){
     trackcct1Val = analogRead(trackcircuit1); // track circuit 1 status
     if (trackcct1Val <=500) {
       blockisoccupied = true; //
       blockwasoccupied = true;
       sigatStopMillis = millis();
     }
     else {
        currentMillis=millis();
        if (currentMillis-sigatStopMillis>=2000) blockisoccupied = false;
        if (currentMillis-sigatStopMillis>=cautiontimer) blockwasoccupied = false;
     }
     emergStopVal = analogRead(emergencystop); // emergency stop status
     signal1Val = analogRead(signal1proceed); // signaller signal switch
     signal2Val = analogRead(signal2proceed); // signaller signal switch
     signal1aheadVal = analogRead(signal1aheadstatus); // the signal status in advance of this signal
     signal2aheadVal = analogRead(signal2aheadstatus); // the signal status in advance of this signal
     turnoutLVal = analogRead(turnoutL); // the turnout lever status for Left turnout
     turnoutRVal = analogRead(turnoutR); // the turnout lever status for Right turnout

}

void displaysignals(){
  // check emergency stop
  // check track circuit status
  // check signal switches
  // if cleared, check signal ahead and timer
  // also determine if turnout or straight route is set
  // if nothing else affected, display clear
  if (emergStopVal<=500){
    displaySTOP();
    digitalWrite(EMERGind,HIGH);
    Serial.println("Emergency stop activated");
  }
    else{
      digitalWrite(EMERGind,LOW);
      if (blockisoccupied == true){
       displaySTOP();
       digitalWrite(TC1,HIGH); // track circuit mimic ON
      }
        else{
          // block is not occupied
          digitalWrite(TC1,LOW); // track circuit mimic OFF
          
          // ****************** SIGNAL 1 ****************
          if (signal1Val>=500){
            Serial.println("signal 1 is at stop");
          // signal is set to stop
          digitalWrite(S1red,HIGH); // on
          digitalWrite(S1yel,LOW); // off
          digitalWrite(S1grn,LOW); // off
          digitalWrite(S1toL,LOW); // off
          digitalWrite(S1toR,LOW); // off
          }
          else{
            Serial.println("Signal 1 is not at stop");
            if (signal1Val<=500){
              // signal is set to proceed
              if (turnoutLVal<=500){
                Serial.println("L turnout");
                //display turnout aspect to the left
                digitalWrite(S1red,HIGH); // on
                digitalWrite(S1yel,LOW); // off
                digitalWrite(S1grn,LOW); // off
                digitalWrite(S1toL,HIGH); // on
                digitalWrite(S1toR,LOW); // off
                
              }
              if (turnoutRVal<=500){
                Serial.println("R turnout");
                // insert - display turnout aspect to the right
                digitalWrite(S1red,HIGH); // on
                digitalWrite(S1yel,LOW); // off
                digitalWrite(S1grn,LOW); // off
                digitalWrite(S1toL,LOW); // off
                digitalWrite(S1toR,HIGH); // on
                
              }
              if ((turnoutLVal>=500) && (turnoutRVal>=500)){
                if ((blockwasoccupied == true) || (signal1aheadVal<=500)){
                  Serial.println("Caution");
                  // display caution aspect
                  digitalWrite(S1red,LOW); // off
                  digitalWrite(S1yel,HIGH); // on
                  digitalWrite(S1grn,LOW); // off
                  digitalWrite(S1toL,LOW); // off
                  digitalWrite(S1toR,LOW); // off
                  
                }
                
              
              else {
                // display clear
                Serial.println("Clear");
                if ((blockwasoccupied == false) & (signal1aheadVal>=500)){
                digitalWrite(S1red,LOW); // off
                digitalWrite(S1yel,LOW); // off
                digitalWrite(S1grn,HIGH); // on
                digitalWrite(S1toL,LOW); // off
                digitalWrite(S1toR,LOW); // off
                
                }
              } 
              }
            }
            
          }
          // ****************** SIGNAL 2 *******************
          if (signal2Val>=500){
            Serial.println("Signal 2 is at stop");
          digitalWrite(S2red,HIGH); // on
          digitalWrite(S2yel,LOW); // off
          digitalWrite(S2grn,LOW); // off
          }
                    else{
            Serial.println("Signal is not at stop");
            if (signal2Val<=500){
              // signal 2 is set to proceed
              // signal 2 may not have any turnouts. Left in - can be removed later. 10/6/22
              if (turnoutLVal<=500){
                Serial.println("L turnout");
                //display turnout aspect to the left
                digitalWrite(S2red,HIGH); // on
                digitalWrite(S2yel,LOW); // off
                digitalWrite(S2grn,LOW); // off
                digitalWrite(S1toL,HIGH); // on
                digitalWrite(S1toR,LOW); // off
                
              }
              if (turnoutRVal<=500){
                Serial.println("R turnout");
                // insert - display turnout aspect to the right
                digitalWrite(S2red,HIGH); // on
                digitalWrite(S2yel,LOW); // off
                digitalWrite(S2grn,LOW); // off
                digitalWrite(S1toL,LOW); // off
                digitalWrite(S1toR,HIGH); // on
                
              }
              if ((turnoutLVal>=500) && (turnoutRVal>=500)){
                if ((blockwasoccupied == true) || (signal2aheadVal<=500)){
                  Serial.println("Caution2");
                  // display caution aspect
                  digitalWrite(S2red,LOW); // off
                  digitalWrite(S2yel,HIGH); // on
                  digitalWrite(S2grn,LOW); // off
                  digitalWrite(S1toL,LOW); // off
                  digitalWrite(S1toR,LOW); // off
                  
                }
                
              
              else {
                // display clear
                Serial.println("Clear 2");
                if ((blockwasoccupied == false) & (signal2aheadVal>=500)){
                digitalWrite(S2red,LOW); // off
                digitalWrite(S2yel,LOW); // off
                digitalWrite(S2grn,HIGH); // on
                digitalWrite(S1toL,LOW); // off
                digitalWrite(S1toR,LOW); // off
                
                }
              } 
              }
            }
            
          }
          
        }
    }
  
  
}
void startuptest(){
  // cycle throgh and test all outputs for a short time
  
  digitalWrite(S1red,HIGH); // on
  delay (testtime);
  digitalWrite(S1red,LOW); // off
  digitalWrite(S1yel,HIGH); // on
    delay (testtime);
  digitalWrite(S1yel,LOW); // off
  digitalWrite(S1grn,HIGH); // on
  delay (testtime);
  digitalWrite(S1grn,LOW); // off
  digitalWrite(S2red,HIGH); // on
  delay (testtime);
  digitalWrite(S2red,LOW); // off
  digitalWrite(S2yel,HIGH); // on
  delay (testtime);
  digitalWrite(S2yel,LOW); // off
  digitalWrite(S2grn,HIGH); // on
  delay (testtime);
  digitalWrite(S2grn,LOW); // off
  digitalWrite(S1toL,HIGH); // on
  delay (testtime);
  digitalWrite(S1toL,LOW); // off
  digitalWrite(S1toR,HIGH); // on
  delay (testtime);
  digitalWrite(S1toR,LOW); // off
  digitalWrite(EMERGind,HIGH); // on
  delay (testtime);
  digitalWrite(EMERGind,LOW); // off
  digitalWrite(TC1,HIGH); // on
  delay (testtime);
  digitalWrite(TC1,LOW); // off
  digitalWrite(TC2,HIGH); // on
  delay (testtime);
  digitalWrite(TC2,LOW); // off
  
}

void displaySTOP(){
    digitalWrite(S1red,HIGH); // on
    digitalWrite(S1yel,LOW); // off
    digitalWrite(S1grn,LOW); // off
    digitalWrite(S2red,HIGH); // on
    digitalWrite(S2yel,LOW); // off
    digitalWrite(S2grn,LOW); // off
    
     
     digitalWrite(S1toL,LOW); // off
     digitalWrite(S1toR,LOW); // off
     
}