291 lines
12 KiB
Plaintext
291 lines
12 KiB
Plaintext
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta name="generator" content="HTML Tidy for HTML5 for Apple macOS version 5.8.0">
|
|
<!-- Copyright Bob Jacobsen 2008 -->
|
|
|
|
<title>JMRI: Simple Signal Logic</title><!--#include virtual="/help/en/parts/Style.shtml" -->
|
|
</head>
|
|
<body>
|
|
<!--#include virtual="/help/en/parts/Header.shtml" -->
|
|
|
|
<div id="mBody">
|
|
<!--#include virtual="Sidebar.shtml" -->
|
|
|
|
<div id="mainContent">
|
|
<h1>JMRI: Simple Signal Logic</h1>
|
|
|
|
<p class="subtitle">Background information of the logic used to control simple signals</p>
|
|
|
|
<div class="para">
|
|
<p>This page describes the logic used by the JMRI Simple Signal panel to control
|
|
signals.</p>
|
|
|
|
<p>We display the actual code, so there's no ambiguity about what it's doing. This is from
|
|
JMRI test release 2.9.1.</p>
|
|
</div>
|
|
|
|
<div class="section">
|
|
<h2 id="single">On Single Block</h2>
|
|
|
|
<div class="para">
|
|
<p>This signal protects one end of a straight through block, with no signaled
|
|
turnouts.</p>
|
|
</div>
|
|
|
|
<div class="para">
|
|
<pre class="code">
|
|
void doSingleBlock() {
|
|
int appearance = SignalHead.GREEN;
|
|
int oldAppearance = ((SignalHead)outputs[0]).getAppearance();
|
|
// check for yellow, flashing yellow overriding green
|
|
if (protectWithFlashing && fastestColor1()==SignalHead.YELLOW)
|
|
appearance = SignalHead.FLASHYELLOW;
|
|
if (fastestColor1()==SignalHead.RED || fastestColor1()==SignalHead.FLASHRED)
|
|
appearance = SignalHead.YELLOW;
|
|
|
|
// if distant signal, show exactly what the home signal does
|
|
if (distantSignal)
|
|
appearance = fastestColor1();
|
|
|
|
// if limited speed and green, reduce to yellow
|
|
if (limitSpeed1)
|
|
appearance = slowerOf(appearance, SignalHead.YELLOW);
|
|
|
|
// check for red overriding yellow or green
|
|
if (watchSensor1!=null && watchSensor1.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
if (watchSensor2!=null && watchSensor2.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
if (watchSensor3!=null && watchSensor3.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
if (watchSensor4!=null && watchSensor4.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
|
|
// check if signal if held, forcing a red aspect by this calculation
|
|
if (((SignalHead)outputs[0]).getHeld())
|
|
appearance = SignalHead.RED;
|
|
|
|
// handle approach lighting
|
|
doApproach();
|
|
|
|
// show result if changed
|
|
if (appearance != oldAppearance) {
|
|
((SignalHead)outputs[0]).setAppearance(appearance);
|
|
if (log.isDebugEnabled()) log.debug("Change appearance of "+name+" to "+appearance);
|
|
}
|
|
}
|
|
</pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="section">
|
|
<h2 id="trailmain">On Main Leg ofTrailing-Point Turnout</h2>
|
|
|
|
<div class="para">
|
|
<p>This signal is along the main route through a turnout, which is defined as the
|
|
direction taken by trains when the turnout is closed. It's protecting the frog of the
|
|
turnout so that trains will stop before running through a turnout set against them.</p>
|
|
</div>
|
|
|
|
<div class="para">
|
|
<pre class="code">
|
|
void doTrailingMain() {
|
|
int appearance = SignalHead.GREEN;
|
|
int oldAppearance = ((SignalHead)outputs[0]).getAppearance();
|
|
// check for yellow, flashing yellow overriding green
|
|
if (protectWithFlashing && fastestColor1()==SignalHead.YELLOW)
|
|
appearance = SignalHead.FLASHYELLOW;
|
|
if (fastestColor1()==SignalHead.RED || fastestColor1()==SignalHead.FLASHRED)
|
|
appearance = SignalHead.YELLOW;
|
|
|
|
// if distant signal, show exactly what the home signal does
|
|
if (distantSignal)
|
|
appearance = fastestColor1();
|
|
|
|
// if limited speed and green, reduce to yellow
|
|
if (limitSpeed1)
|
|
appearance = slowerOf(appearance, SignalHead.YELLOW);
|
|
|
|
// check for red overriding yellow or green
|
|
if (watchSensor1!=null && watchSensor1.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
if (watchSensor2!=null && watchSensor2.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
if (watchSensor3!=null && watchSensor3.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
if (watchSensor4!=null && watchSensor4.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
|
|
if (watchTurnout!=null && watchTurnout.getBean().getKnownState() != Turnout.CLOSED)
|
|
appearance = SignalHead.RED;
|
|
if (watchTurnout!=null && watchTurnout.getBean().getCommandedState() != Turnout.CLOSED)
|
|
appearance = SignalHead.RED;
|
|
|
|
// check if signal if held, forcing a red aspect by this calculation
|
|
if (((SignalHead)outputs[0]).getHeld())
|
|
appearance = SignalHead.RED;
|
|
|
|
// handle approach lighting
|
|
doApproach();
|
|
|
|
// show result if changed
|
|
if (appearance != oldAppearance) {
|
|
((SignalHead)outputs[0]).setAppearance(appearance);
|
|
log.debug("Change appearance of {} to {}", name, appearance);
|
|
}
|
|
}
|
|
</pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="section">
|
|
<h2 id="traildiv">On Diverging Leg of Trailing-Point Turnout</h2>
|
|
|
|
<div class="para">
|
|
<p>This signal is along the diverging route through a turnout, which is defined as the
|
|
direction taken by trains when the turnout is set to "thrown". It's protecting the frog
|
|
of the turnout so that trains will stop before running through a turnout set against
|
|
them.</p>
|
|
</div>
|
|
|
|
<div class="para">
|
|
<pre class="code">
|
|
void doTrailingDiverging() {
|
|
int appearance = SignalHead.GREEN;
|
|
int oldAppearance = ((SignalHead)outputs[0]).getAppearance();
|
|
// check for yellow, flashing yellow overriding green
|
|
if (protectWithFlashing && fastestColor1()==SignalHead.YELLOW)
|
|
appearance = SignalHead.FLASHYELLOW;
|
|
if (fastestColor1()==SignalHead.RED || fastestColor1()==SignalHead.FLASHRED)
|
|
appearance = SignalHead.YELLOW;
|
|
|
|
// if distant signal, show exactly what the home signal does
|
|
if (distantSignal)
|
|
appearance = fastestColor1();
|
|
|
|
// if limited speed and green, reduce to yellow
|
|
if (limitSpeed2)
|
|
appearance = slowerOf(appearance, SignalHead.YELLOW);
|
|
|
|
// check for red overriding yellow or green
|
|
if (watchSensor1!=null && watchSensor1.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
if (watchSensor2!=null && watchSensor2.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
if (watchSensor3!=null && watchSensor3.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
if (watchSensor4!=null && watchSensor4.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
|
|
if (watchTurnout!=null && watchTurnout.getBean().getKnownState() != Turnout.THROWN)
|
|
appearance = SignalHead.RED;
|
|
if (watchTurnout!=null && watchTurnout.getBean().getCommandedState() != Turnout.THROWN)
|
|
appearance = SignalHead.RED;
|
|
|
|
// check if signal if held, forcing a red aspect by this calculation
|
|
if (((SignalHead)outputs[0]).getHeld())
|
|
appearance = SignalHead.RED;
|
|
|
|
// handle approach lighting
|
|
doApproach();
|
|
|
|
// show result if changed
|
|
if (appearance != oldAppearance) {
|
|
((SignalHead)outputs[0]).setAppearance(appearance);
|
|
if (log.isDebugEnabled()) log.debug("Change appearance of "+name+" to "+appearance);
|
|
}
|
|
}
|
|
</pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="section">
|
|
<h2 id="face">On Facing-Point Turnout</h2>
|
|
|
|
<div class="para">
|
|
<p>This signal is protecting the points-end of a turnout. Depending on whether the
|
|
turnout is thrown or closed, the train will take two different routes, and the signal
|
|
will protect different next blocks.</p>
|
|
</div>
|
|
|
|
<div class="para">
|
|
<pre class="code">
|
|
void doFacing() {
|
|
int appearance = SignalHead.GREEN;
|
|
int oldAppearance = ((SignalHead)outputs[0]).getAppearance();
|
|
|
|
// find downstream appearance, being pessimistic if we're not sure of the state
|
|
int s = SignalHead.GREEN;
|
|
if (watchTurnout!=null && watchTurnout.getBean().getKnownState() != Turnout.THROWN)
|
|
s = slowerOf(s, fastestColor1());
|
|
if (watchTurnout!=null && watchTurnout.getBean().getKnownState() != Turnout.CLOSED)
|
|
s = slowerOf(s, fastestColor2());
|
|
|
|
// check for yellow, flashing yellow overriding green
|
|
if (protectWithFlashing && s==SignalHead.YELLOW)
|
|
appearance = SignalHead.FLASHYELLOW;
|
|
if (s==SignalHead.RED || s==SignalHead.FLASHRED)
|
|
appearance = SignalHead.YELLOW;
|
|
// if distant signal, show exactly what the home signal does
|
|
if (distantSignal)
|
|
appearance = s;
|
|
|
|
// if limited speed and green or flashing yellow, reduce to yellow
|
|
if (watchTurnout!=null && limitSpeed1 && watchTurnout.getBean().getKnownState()!=Turnout.THROWN)
|
|
appearance = slowerOf(appearance, SignalHead.YELLOW);
|
|
|
|
if (watchTurnout!=null && limitSpeed2 && watchTurnout.getBean().getKnownState()!=Turnout.CLOSED)
|
|
appearance = slowerOf(appearance, SignalHead.YELLOW);
|
|
|
|
|
|
// check for red overriding yellow or green
|
|
if (watchSensor1!=null && watchSensor1.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
if (watchSensor2!=null && watchSensor2.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
if (watchSensor3!=null && watchSensor3.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
if (watchSensor4!=null && watchSensor4.getBean().getKnownState() != Sensor.INACTIVE)
|
|
appearance = SignalHead.RED;
|
|
|
|
if ((watchTurnout!=null && watchTurnout.getBean().getKnownState() == Turnout.CLOSED)
|
|
&& ((watchedSensor1!=null && watchedSensor1.getBean().getKnownState() != Sensor.INACTIVE)))
|
|
appearance = SignalHead.RED;
|
|
if ((watchTurnout!=null && watchTurnout.getBean().getKnownState() == Turnout.CLOSED) && ((watchedSensor1Alt!=null && watchedSensor1Alt.getBean().getKnownState() != Sensor.INACTIVE)))
|
|
appearance = SignalHead.RED;
|
|
if ((watchTurnout!=null && watchTurnout.getBean().getKnownState() == Turnout.THROWN) && ((watchedSensor2!=null && watchedSensor2.getBean().getKnownState() != Sensor.INACTIVE)))
|
|
appearance = SignalHead.RED;
|
|
if ((watchTurnout!=null && watchTurnout.getBean().getKnownState() == Turnout.THROWN) && ((watchedSensor2Alt!=null && watchedSensor2Alt.getBean().getKnownState() != Sensor.INACTIVE)))
|
|
appearance = SignalHead.RED;
|
|
|
|
// check if turnout in motion, if so force red
|
|
if (watchTurnout!=null && (watchTurnout.getBean().getKnownState() != watchTurnout.getBean().getCommandedState()) )
|
|
appearance = SignalHead.RED;
|
|
if (watchTurnout!=null && (watchTurnout.getBean().getKnownState() != Turnout.THROWN) && (watchTurnout.getBean().getKnownState() != Turnout.CLOSED) ) // checking for other states
|
|
appearance = SignalHead.RED;
|
|
|
|
// check if signal if held, forcing a red aspect by this calculation
|
|
if (((SignalHead)outputs[0]).getHeld())
|
|
appearance = SignalHead.RED;
|
|
|
|
// handle approach lighting
|
|
doApproach();
|
|
|
|
// show result if changed
|
|
if (appearance != oldAppearance)
|
|
((SignalHead)outputs[0]).setAppearance(appearance);
|
|
}
|
|
</pre>
|
|
</div>
|
|
<!--closes para-->
|
|
</div>
|
|
<!--closes section-->
|
|
<!--#include virtual="/help/en/parts/Footer.shtml" -->
|
|
</div>
|
|
</div>
|
|
<!-- close #mBody -->
|
|
<script src="/js/help.js"></script>
|
|
</body>
|
|
</html>
|