815 lines
25 KiB
Plaintext
815 lines
25 KiB
Plaintext
//////////////////////////////////////////////////////////////////////////
|
|
// DCC++ CONTROLLER: Classes for Sensors and AutoPilot Control
|
|
//
|
|
// AutoPilot Button - automaticaly operates three cabs in a pattern
|
|
// by which each cab travels out to the sky bridge,
|
|
// reverses course, and comes back into the inner
|
|
// reversing loop after passing through the crossover
|
|
// - status is saved between session
|
|
// - clicking this button RESUMES a previous session
|
|
// or stops the current session
|
|
// - resumption implies all cabs, turnouts, and sensors are in
|
|
// the exact same position as before the session was halted
|
|
// - shift-clicking this button STARTS a new session
|
|
// - starting a new seesion assume all cabs are in their start position
|
|
// but sensors and turnouts will be automatically reset
|
|
//
|
|
// TrackSensor - defines a track sensor that triggers when the first car of a train passes, and
|
|
// then again when the last car of that same train passes.
|
|
// - creates a track sensor button on the track layout where ther sensor is located
|
|
// - a given track sensor is defined to be "on" once an initial trigger is received from passage
|
|
// of first the car of a train, and defined to be "off" once a second trigger is received from
|
|
// passage of last car of that same train
|
|
// - if the on/off status of a track sensor button seems out of sync with the actual train,
|
|
// user can manually toggle the sensor "on" or "off" by clicking the appropriate sensor button
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
class AutoPilotButton extends RectButton{
|
|
int[] cabs={8601,6021,1506,622,1202,54}; // list of all cabs to be included in autoPilot - order does not matter since it will be randomized
|
|
ArrayList<CabButton> cabList = new ArrayList<CabButton>();
|
|
int phase=0;
|
|
int tCount=0;
|
|
int crossOver=0;
|
|
AutoProgram program=AutoProgram.NONE;
|
|
XML cabListXML, phaseXML, tCountXML, crossOverXML, programXML;
|
|
int safetyTimer;
|
|
|
|
AutoPilotButton(int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText){
|
|
this(null, xPos, yPos, bWidth, bHeight, baseHue, fontSize, bText);
|
|
}
|
|
|
|
AutoPilotButton(Window window, int xPos, int yPos, int bWidth, int bHeight, int baseHue, int fontSize, String bText){
|
|
super(window, xPos, yPos, bWidth, bHeight, baseHue, color(0), fontSize, bText, ButtonType.NORMAL);
|
|
|
|
phaseXML=autoPilotXML.getChild("Phase");
|
|
if(phaseXML==null){
|
|
phaseXML=autoPilotXML.addChild("Phase");
|
|
phaseXML.setContent(str(phase));
|
|
} else{
|
|
phase=int(phaseXML.getContent());
|
|
}
|
|
|
|
tCountXML=autoPilotXML.getChild("TCount");
|
|
if(tCountXML==null){
|
|
tCountXML=autoPilotXML.addChild("TCount");
|
|
tCountXML.setContent(str(tCount));
|
|
} else{
|
|
tCount=int(tCountXML.getContent());
|
|
}
|
|
|
|
crossOverXML=autoPilotXML.getChild("CrossOver");
|
|
if(crossOverXML==null){
|
|
crossOverXML=autoPilotXML.addChild("CrossOver");
|
|
crossOverXML.setContent(str(crossOver));
|
|
} else{
|
|
crossOver=int(crossOverXML.getContent());
|
|
}
|
|
|
|
programXML=autoPilotXML.getChild("Program");
|
|
if(programXML==null){
|
|
programXML=autoPilotXML.addChild("Program");
|
|
programXML.setContent(program.name);
|
|
} else{
|
|
program=AutoProgram.index(programXML.getContent());
|
|
}
|
|
|
|
cabListXML=autoPilotXML.getChild("CabList");
|
|
if(cabListXML==null){
|
|
cabListXML=autoPilotXML.addChild("CabList");
|
|
cabListXML.setContent(join(nf(cabs,0)," "));
|
|
}
|
|
|
|
for(int i: int(split(trim(cabListXML.getContent())," ")))
|
|
cabList.add(cabsHM.get("Cab"+i));
|
|
|
|
updateDiagBox();
|
|
|
|
} // AutoButton
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void display(){
|
|
super.display();
|
|
|
|
textAlign(CENTER,CENTER);
|
|
textFont(messageFont,12);
|
|
fill(color(255));
|
|
text(program.name,xPos+xWindow(),yPos+yWindow()+bHeight/2+10);
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void pressed(){
|
|
|
|
if(isOn){
|
|
turnOff();
|
|
return;
|
|
}
|
|
|
|
if(program==AutoProgram.NONE){
|
|
msgBoxMain.setMessage("Can't resume Auto Pilot until program specified!",color(50,50,200));
|
|
return;
|
|
}
|
|
|
|
for(CabButton cb : cabList) // set throttles of all cabs specified in current program to prior values
|
|
cb.setThrottle(ThrottleSpeed.index(cb.speedXML.getContent()));
|
|
|
|
if(program.equals(AutoProgram.AUTO_CLEAN))
|
|
cleaningCab.turnOn();
|
|
|
|
msgBoxMain.setMessage("Auto Pilot Resuming",color(50,50,200));
|
|
safetyTimer=millis();
|
|
turnOn();
|
|
} // pressed
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void init(){
|
|
phase=0;
|
|
tCount=0;
|
|
crossOver=0;
|
|
|
|
for(TrackSensor ts : sensorsHM.values())
|
|
ts.reset();
|
|
|
|
cabList.clear();
|
|
for(int i:cabs)
|
|
cabList.add(cabsHM.get("Cab"+i));
|
|
|
|
for(int i=0;i<3;i++) // randomize list
|
|
cabList.add(0,cabList.remove(int(random(i,cabList.size()))));
|
|
|
|
updateCabList();
|
|
|
|
for(CabButton cb : cabList) // halt all cabs specified in full autopilot program
|
|
cb.setThrottle(ThrottleSpeed.STOP);
|
|
|
|
rButtonReset.pressed();
|
|
cabList.get(0).sidingRoute.pressed(); // set siding turnouts so they are aligned for first cab
|
|
rButtonSpiral.pressed();
|
|
rButton12.pressed();
|
|
|
|
cabList.get(0).setThrottle(ThrottleSpeed.FULL); // start first cab!
|
|
|
|
msgBoxMain.setMessage("Auto Pilot Engaged",color(50,50,200));
|
|
updateDiagBox();
|
|
|
|
} // init()
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void clean(){
|
|
|
|
if(isOn){
|
|
msgBoxMain.setMessage("Auto Pilot already engaged!",color(50,50,200));
|
|
return;
|
|
}
|
|
|
|
cleaningCab.turnOn(); // turn on cleaning car
|
|
cabList.clear();
|
|
cabList.add(cabsHM.get("Cab"+2004)); // assumes cab 2004 is pulling cleaning car
|
|
updateCabList();
|
|
phase=100;
|
|
phaseXML.setContent(str(phase));
|
|
tButton10.pressed(0);
|
|
|
|
for(TrackSensor ts : sensorsHM.values())
|
|
ts.reset();
|
|
|
|
cabList.get(0).setThrottle(ThrottleSpeed.FULL); // start throttle for cab
|
|
msgBoxMain.setMessage("Auto Clean Engaged",color(50,50,200));
|
|
setProgram(AutoProgram.AUTO_CLEAN);
|
|
safetyTimer=millis();
|
|
turnOn();
|
|
|
|
} // clean
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void parkCab(CabButton selectedCab){
|
|
|
|
if(selectedCab.parkingSensor==0){
|
|
msgBoxMain.setMessage("Auto Park not available for Cab "+selectedCab.cab,color(50,50,200));
|
|
return;
|
|
}
|
|
|
|
if(isOn){
|
|
msgBoxMain.setMessage("Auto Pilot already engaged!",color(50,50,200));
|
|
return;
|
|
}
|
|
|
|
cabList.clear();
|
|
cabList.add(selectedCab);
|
|
updateCabList();
|
|
phase=42;
|
|
phaseXML.setContent(str(phase));
|
|
cabList.get(0).setThrottle(ThrottleSpeed.FULL); // start throttle for cab selected --- do not modify throttles for any other cabs
|
|
msgBoxMain.setMessage("Auto Park Engaged for Cab "+selectedCab.cab,color(50,50,200));
|
|
setProgram(AutoProgram.SINGLE_CAB_PARK);
|
|
safetyTimer=millis();
|
|
turnOn();
|
|
|
|
} // parkCab
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void shiftPressed(){
|
|
|
|
if(!isOn){
|
|
setProgram(AutoProgram.ALL_CABS_RUN);
|
|
safetyTimer=millis();
|
|
turnOn();
|
|
msgBoxMain.setMessage("Starting Auto Pilot...",color(50,50,200));
|
|
buttonQueue.add(this);
|
|
} else
|
|
if(program==AutoProgram.ALL_CABS_RUN){
|
|
msgBoxMain.setMessage("Switching to Auto Park",color(50,50,200));
|
|
setProgram(AutoProgram.ALL_CABS_PARK);
|
|
} else{
|
|
msgBoxMain.setMessage("Auto Park or other program already engaged!",color(50,50,200));
|
|
}
|
|
} // shiftPressed
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void turnOff(){
|
|
super.turnOff();
|
|
|
|
msgBoxMain.setMessage("Auto Pilot Disengaged",color(50,50,200));
|
|
|
|
for(CabButton cb : cabList) // halt (but without updating XML) all cabs specified in current program only
|
|
cb.stopThrottle();
|
|
|
|
if(program.equals(AutoProgram.AUTO_CLEAN))
|
|
cleaningCab.turnOff();
|
|
|
|
if(program.equals(AutoProgram.SINGLE_CAB_RUN)){
|
|
aPort.write("<u>");
|
|
setProgram(AutoProgram.NONE);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void updateCabList(){
|
|
|
|
cabListXML.setContent("");
|
|
for(CabButton cb : cabList)
|
|
cabListXML.setContent(cabListXML.getContent()+cb.cab+" ");
|
|
|
|
cabListXML.setContent(trim(cabListXML.getContent()));
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void process(int s, boolean isActive){
|
|
|
|
int lastPhase;
|
|
|
|
if(!isOn || program.equals(AutoProgram.SINGLE_CAB_RUN))
|
|
return;
|
|
|
|
if(!isActive)
|
|
s=-s;
|
|
|
|
lastPhase=phase;
|
|
|
|
switch(s){
|
|
|
|
case 1:
|
|
if(phase==3){
|
|
rButtonBridge.pressed();
|
|
phase=4;
|
|
} else
|
|
if(phase==4){
|
|
phase=5;
|
|
} else
|
|
if(phase==5){
|
|
phase=6;
|
|
} else
|
|
if(phase==10){
|
|
crossOver++;
|
|
if(crossOver==2){
|
|
cabList.get(0).stopThrottle();
|
|
// cabList.get(0).activateFunction(CabFunction.HORN,true);
|
|
// cabList.get(0).activateFunction(CabFunction.HORN,false);
|
|
} else{
|
|
cabList.get(0).activateFunction(CabFunction.S_HORN,true);
|
|
}
|
|
} else
|
|
if(phase==11){
|
|
phase=12;
|
|
} else
|
|
if(phase==13){
|
|
phase=14;
|
|
} else
|
|
if(phase==40){
|
|
tButton20.pressed(0);
|
|
phase=41;
|
|
}
|
|
break;
|
|
|
|
case -1:
|
|
if(phase==2){
|
|
tCount++;
|
|
} else
|
|
if(phase==120){
|
|
phase=42;
|
|
tButton20.pressed(1);
|
|
tButton10.pressed(0);
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
if(phase==0){
|
|
tButton40.routeDisabled();
|
|
cabList.get(1).sidingRoute.pressed();
|
|
tButton40.routeEnabled();
|
|
cabList.get(1).setThrottle(ThrottleSpeed.FULL);
|
|
phase=1;
|
|
// } else
|
|
// if(phase==10 || phase==11){
|
|
// cabList.get(2).setFunction(CabFunction.HORN,false);
|
|
} else
|
|
if(phase==30){
|
|
tButton50.pressed(1);
|
|
phase=31;
|
|
}
|
|
break;
|
|
|
|
case -2:
|
|
if(phase==2){
|
|
tCount++;
|
|
if(tCount==1)
|
|
cabList.get(1).setThrottle(ThrottleSpeed.STOP);
|
|
} else
|
|
if(phase==9){
|
|
tButton30.pressed(1);
|
|
tCount++;
|
|
} else
|
|
if(phase==10){
|
|
if(crossOver>0){
|
|
crossOver--;
|
|
}
|
|
if(crossOver==1){
|
|
cabList.get(0).setThrottle(ThrottleSpeed.FULL);
|
|
// cabList.get(0).activateFunction(CabFunction.S_HORN,true);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
if(phase==7){
|
|
tButton30.pressed(0);
|
|
phase=8;
|
|
} else
|
|
if(phase==10){
|
|
crossOver++;
|
|
if(crossOver==2){
|
|
cabList.get(2).stopThrottle();
|
|
// cabList.get(2).activateFunction(CabFunction.HORN,true);
|
|
// cabList.get(2).activateFunction(CabFunction.HORN,false);
|
|
} else{
|
|
cabList.get(2).activateFunction(CabFunction.S_HORN,true);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case -3:
|
|
if(phase==110){
|
|
phase++;
|
|
tButton30.pressed(1);
|
|
} else
|
|
if(phase==111||phase==112){
|
|
phase++;
|
|
} else
|
|
if(phase==113){
|
|
phase++;
|
|
tButton30.pressed(0);
|
|
tButton40.pressed(1);
|
|
tButton1.pressed(0);
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
if(phase==1){
|
|
tButton40.routeDisabled();
|
|
cabList.get(2).sidingRoute.pressed();
|
|
tButton40.routeEnabled();
|
|
cabList.get(2).setThrottle(ThrottleSpeed.FULL);
|
|
phase=2;
|
|
} else
|
|
if(phase==8){
|
|
tButton40.pressed(0);
|
|
phase=9;
|
|
// } else
|
|
// if(phase==10){
|
|
// cabList.get(0).setFunction(CabFunction.HORN,false);
|
|
} else
|
|
if(phase==12){
|
|
tButton4.pressed(1); // set reversing loop
|
|
tButton7.pressed(0);
|
|
phase=20; // start "parking" phase, then resume pattern
|
|
} else
|
|
if((phase==21 || phase==31 || phase==42) && cabList.get(0).parkingSensor==4){
|
|
cabList.get(0).setThrottle(ThrottleSpeed.SLOW);
|
|
phase++;
|
|
} else
|
|
if(phase==41){
|
|
tButton50.pressed(0);
|
|
tButton4.pressed(1); // set reversing loop
|
|
tButton7.pressed(0);
|
|
phase=42;
|
|
}
|
|
break;
|
|
|
|
case -4:
|
|
if(phase==10){
|
|
if(crossOver>0){
|
|
crossOver--;
|
|
}
|
|
if(crossOver==1){
|
|
cabList.get(2).setThrottle(ThrottleSpeed.FULL);
|
|
// cabList.get(2).activateFunction(CabFunction.S_HORN,true);
|
|
}
|
|
cabList.get(1).setThrottle(ThrottleSpeed.FULL); // just in case cab-1 was stopped on bridge
|
|
tButton40.pressed(1);
|
|
tButton1.pressed(0);
|
|
tButton20.pressed(1);
|
|
crossOver=0;
|
|
phase=11;
|
|
} else
|
|
if((phase==22 || phase==32 || phase==43) && cabList.get(0).parkingSensor==4){
|
|
phase++;
|
|
cabList.get(0).setThrottle(ThrottleSpeed.STOP);
|
|
cabList.get(0).sidingRoute.shiftPressed();
|
|
delay(500);
|
|
cabList.get(0).sidingRoute.pressed();
|
|
sensorsHM.get(cabList.get(0).sidingSensor).pressed(false);
|
|
cabList.get(0).setThrottle(ThrottleSpeed.REVERSE);
|
|
}
|
|
break;
|
|
|
|
case 5:
|
|
if(phase==6){
|
|
cabList.get(0).setThrottle(ThrottleSpeed.SLOW);
|
|
} else
|
|
if(phase==14){
|
|
cabList.get(1).setThrottle(ThrottleSpeed.SLOW);
|
|
} else
|
|
if(phase==42 && cabList.get(0).parkingSensor==5){
|
|
cabList.get(0).setThrottle(ThrottleSpeed.SLOW);
|
|
phase++;
|
|
}
|
|
break;
|
|
|
|
case -5:
|
|
if(phase==6){
|
|
cabList.get(0).setThrottle(ThrottleSpeed.STOP);
|
|
phase=7;
|
|
} else
|
|
if(phase==14){
|
|
cabList.get(1).setThrottle(ThrottleSpeed.STOP);
|
|
cabList.add(cabList.remove(0)); // move cab-0 to end of list
|
|
updateCabList();
|
|
phase=7; // start next cycle
|
|
} else
|
|
if(phase==43 && cabList.get(0).parkingSensor==5){
|
|
phase++;
|
|
cabList.get(0).setThrottle(ThrottleSpeed.STOP);
|
|
cabList.get(0).sidingRoute.shiftPressed();
|
|
delay(500);
|
|
cabList.get(0).sidingRoute.pressed();
|
|
sensorsHM.get(cabList.get(0).sidingSensor).pressed(false);
|
|
delay(100);
|
|
cabList.get(0).setThrottle(ThrottleSpeed.REVERSE);
|
|
} else
|
|
if(phase==100){
|
|
phase++;
|
|
tButton10.pressed(1);
|
|
tButton30.pressed(1);
|
|
tButton50.pressed(1);
|
|
tButton4.pressed(0);
|
|
tButton20.pressed(0);
|
|
} else
|
|
if(phase==101||phase==102){
|
|
phase++;
|
|
} else
|
|
if(phase==103){
|
|
phase++;
|
|
tButton20.pressed(1);
|
|
tButton50.pressed(0);
|
|
} else
|
|
if(phase==104||phase==105){
|
|
phase++;
|
|
} else
|
|
if(phase==106){
|
|
phase++;
|
|
tButton10.pressed(0);
|
|
} else
|
|
if(phase==107||phase==108){
|
|
phase++;
|
|
} else
|
|
if(phase==109){
|
|
phase++;
|
|
tButton20.pressed(0);
|
|
tButton30.pressed(0);
|
|
}
|
|
break;
|
|
|
|
case 6:
|
|
if(phase==10){
|
|
cabList.get(1).stopThrottle(); // wait on bridge until cab-0 clears sensor 4
|
|
}
|
|
break;
|
|
|
|
case -6:
|
|
if(phase==9){
|
|
tCount++;
|
|
tButton8.pressed();
|
|
}
|
|
break;
|
|
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
case 12:
|
|
case 13:
|
|
case 14:
|
|
if(phase==23 || phase==33 || phase==44){
|
|
phase++;
|
|
cabList.get(0).setThrottle(ThrottleSpeed.REVERSE_SLOW);
|
|
}
|
|
break;
|
|
|
|
case -7:
|
|
case -8:
|
|
case -9:
|
|
case -10:
|
|
case -12:
|
|
case -13:
|
|
case -14:
|
|
if(phase==24 || phase==34 || phase==45){
|
|
cabList.get(0).setThrottle(ThrottleSpeed.STOP);
|
|
sensorsHM.get(cabList.get(0).parkingSensor).pressed(false);
|
|
tButton40.pressed(1);
|
|
if(program==AutoProgram.SINGLE_CAB_PARK||program==AutoProgram.AUTO_CLEAN){
|
|
phase=51; // phase must have previously been 45
|
|
turnOff();
|
|
} else
|
|
if(program==AutoProgram.ALL_CABS_PARK){
|
|
cabList.add(0,cabList.remove(2)); // move cab-2 to beginning of list, making it cab-0
|
|
updateCabList();
|
|
phase+=6; // start parking routine at either phase=30, or if second cab just parked then phase=40, or if third cab finished parking phase=51
|
|
if(phase==51){
|
|
turnOff();
|
|
}
|
|
} else{
|
|
cabList.add(3,cabList.remove(int(random(3,cabList.size())))); // pick random cab to be next to leave siding
|
|
updateCabList();
|
|
tButton40.routeDisabled();
|
|
cabList.get(3).sidingRoute.pressed();
|
|
tButton40.routeEnabled();
|
|
cabList.get(3).setThrottle(ThrottleSpeed.FULL);
|
|
phase=25;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 11:
|
|
if(phase==20){
|
|
phase=21;
|
|
} else
|
|
if((phase==21 || phase==31 || phase==42) && cabList.get(0).parkingSensor==11){
|
|
cabList.get(0).setThrottle(ThrottleSpeed.SLOW);
|
|
phase++;
|
|
} else
|
|
if(phase==25){
|
|
phase=26;
|
|
} else
|
|
if(phase==26){
|
|
phase=13;
|
|
}
|
|
break;
|
|
|
|
case -11:
|
|
if((phase==22 || phase==32 || phase==43) && cabList.get(0).parkingSensor==11){
|
|
phase++;
|
|
cabList.get(0).setThrottle(ThrottleSpeed.STOP);
|
|
cabList.get(0).sidingRoute.shiftPressed();
|
|
delay(500);
|
|
cabList.get(0).sidingRoute.pressed();
|
|
sensorsHM.get(cabList.get(0).sidingSensor).pressed(false);
|
|
delay(100);
|
|
cabList.get(0).setThrottle(ThrottleSpeed.REVERSE);
|
|
} else
|
|
if(phase==114||phase==115){
|
|
phase++;
|
|
} else
|
|
if(phase==116){
|
|
phase++;
|
|
tButton4.pressed(1);
|
|
tButton7.pressed(0);
|
|
tButton5.pressed(0);
|
|
tButton20.pressed(0);
|
|
tButton8.pressed(0);
|
|
} else
|
|
if(phase==117){
|
|
phase++;
|
|
tButton40.pressed(0);
|
|
} else
|
|
if(phase==118||phase==119){
|
|
phase++;
|
|
}
|
|
break;
|
|
|
|
} // switch t
|
|
|
|
if(phase==2 && tCount==2){
|
|
cabList.get(1).setThrottle(ThrottleSpeed.FULL); // just in case cab-1 was previously stopped to wait for cab-0 to catch up
|
|
rButton10.pressed();
|
|
rButton11.pressed();
|
|
tCount=0;
|
|
phase=3;
|
|
} else
|
|
|
|
if(phase==9 && tCount==2){
|
|
cabList.get(0).setThrottle(ThrottleSpeed.FULL);
|
|
tButton20.pressed(0);
|
|
tButton4.pressed(0);
|
|
tCount=0;
|
|
crossOver=0;
|
|
phase=10;
|
|
}
|
|
|
|
phaseXML.setContent(str(phase));
|
|
tCountXML.setContent(str(tCount));
|
|
crossOverXML.setContent(str(crossOver));
|
|
|
|
updateDiagBox();
|
|
|
|
if(phase!=lastPhase) // there was an update of the phase
|
|
safetyTimer=millis(); // reset timer
|
|
|
|
|
|
} // process
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void setProgram(AutoProgram p){
|
|
program=p;
|
|
programXML.setContent(program.name);
|
|
updateDiagBox();
|
|
saveXMLFlag=true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void updateDiagBox(){
|
|
|
|
String s="";
|
|
|
|
for(XML xml: autoPilotXML.getChildren()){
|
|
if(!xml.getName().equals("#text"))
|
|
s=s+(String.format("%10s",xml.getName())+" = "+xml.getContent()+"\n");
|
|
}
|
|
|
|
msgAutoState.setMessage(s);
|
|
|
|
} // updateDiagBox
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void safetyCheck(){
|
|
|
|
int countDown;
|
|
|
|
if(!isOn || program.equals(AutoProgram.SINGLE_CAB_RUN))
|
|
return;
|
|
|
|
countDown=120-int((millis()-safetyTimer)/1000);
|
|
|
|
msgAutoTimer.setMessage("Timer = "+countDown);
|
|
|
|
if(countDown<=0){
|
|
powerButton.turnOff();
|
|
turnOff();
|
|
}
|
|
|
|
} // safetyCheck
|
|
|
|
} // AutoPilot Class
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// DCC Component: TrackSensor
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
class TrackSensor extends Track{
|
|
boolean isActive=false;
|
|
boolean sensorDefault;
|
|
int xPos, yPos;
|
|
int mTime;
|
|
int kWidth, kHeight;
|
|
String sensorName;
|
|
int sensorNum;
|
|
XML sensorButtonXML;
|
|
MessageBox msgBoxSensor;
|
|
|
|
TrackSensor(Track refTrack, int trackPoint, float tLength, int kWidth, int kHeight, int sensorNum, boolean sensorDefault){
|
|
super(refTrack,trackPoint,tLength);
|
|
this.kWidth=kWidth;
|
|
this.kHeight=kHeight;
|
|
this.xPos=int(x[1]*layout.sFactor+layout.xCorner);
|
|
this.yPos=int(y[1]*layout.sFactor+layout.yCorner);
|
|
this.sensorNum=sensorNum;
|
|
sensorName="Sensor"+sensorNum;
|
|
componentName=sensorName;
|
|
this.sensorDefault=sensorDefault;
|
|
sensorButtonXML=sensorButtonsXML.getChild(sensorName);
|
|
if(sensorButtonXML==null){
|
|
sensorButtonXML=sensorButtonsXML.addChild(sensorName);
|
|
sensorButtonXML.setContent(str(isActive));
|
|
} else{
|
|
isActive=boolean(sensorButtonXML.getContent());
|
|
}
|
|
sensorsHM.put(sensorNum,this);
|
|
msgBoxSensor=new MessageBox(sensorWindow,0,sensorNum*22+22,-1,0,color(175),18,"S-"+nf(sensorNum,2)+":",color(50,50,250));
|
|
}
|
|
|
|
TrackSensor(Track refTrack, int trackPoint, float curveRadius, float curveAngleDeg, int kWidth, int kHeight, int sensorNum, boolean sensorDefault){
|
|
super(refTrack,trackPoint,curveRadius,curveAngleDeg);
|
|
this.kWidth=kWidth;
|
|
this.kHeight=kHeight;
|
|
this.xPos=int(x[1]*layout.sFactor+layout.xCorner);
|
|
this.yPos=int(y[1]*layout.sFactor+layout.yCorner);
|
|
this.sensorNum=sensorNum;
|
|
this.sensorDefault=sensorDefault;
|
|
sensorName="Sensor"+sensorNum;
|
|
componentName=sensorName;
|
|
sensorButtonXML=sensorButtonsXML.getChild(sensorName);
|
|
if(sensorButtonXML==null){
|
|
sensorButtonXML=sensorButtonsXML.addChild(sensorName);
|
|
sensorButtonXML.setContent(str(isActive));
|
|
} else{
|
|
isActive=boolean(sensorButtonXML.getContent());
|
|
}
|
|
sensorsHM.put(sensorNum,this);
|
|
msgBoxSensor=new MessageBox(sensorWindow,0,sensorNum*22+22,-1,0,color(175),18,"S-"+nf(sensorNum,2)+":",color(50,50,250));
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void display(){
|
|
ellipseMode(CENTER);
|
|
|
|
strokeWeight(1);
|
|
stroke(color(255,255,0));
|
|
noFill();
|
|
|
|
if(isActive)
|
|
fill(color(50,50,200));
|
|
|
|
ellipse(xPos,yPos,kWidth/2,kHeight/2);
|
|
} // display()
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void pressed(){
|
|
pressed(!isActive);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void pressed(boolean isActive){
|
|
this.isActive=isActive;
|
|
autoPilot.process(sensorNum,isActive);
|
|
sensorButtonXML.setContent(str(isActive));
|
|
saveXMLFlag=true;
|
|
if(isActive){
|
|
msgBoxSensor.setMessage("S-"+nf(sensorNum,2)+": "+nf(hour(),2)+":"+nf(minute(),2)+":"+nf(second(),2)+" - "+nf((millis()-mTime)/1000.0,0,1)+" sec");
|
|
mTime=millis();
|
|
}
|
|
|
|
} // pressed
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void reset(){
|
|
pressed(sensorDefault);
|
|
|
|
} // reset
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void check(){
|
|
if(selectedComponent==null && (mouseX-xPos)*(mouseX-xPos)/(kWidth*kWidth/4.0)+(mouseY-yPos)*(mouseY-yPos)/(kHeight*kHeight/4.0)<=1){
|
|
cursorType=HAND;
|
|
selectedComponent=this;
|
|
}
|
|
|
|
} // check
|
|
|
|
} // TrackSensor Class |