diff --git a/src/Devices/AtcBombardier.cs b/src/Devices/AtcBombardier.cs
index 719bedd..34aa334 100644
--- a/src/Devices/AtcBombardier.cs
+++ b/src/Devices/AtcBombardier.cs
@@ -1,5 +1,4 @@
-using System;
-using OpenBveApi.Runtime;
+using OpenBveApi.Runtime;
namespace OpenbveFcmbTrainPlugin
{
@@ -26,23 +25,25 @@ namespace OpenbveFcmbTrainPlugin
/// The current state of the device.
private DeviceStates DeviceState;
- /// Represents the state of the device.
- private enum AtcBrakeStates
+ /// Represents the state of the ATC control.
+ private enum AtcControlStates
{
/// The brakes are released.
Released,
+ /// The power is cut.
+ NoPower,
/// The service brake is applied and can be released.
- Service,
+ BrakeService,
/// The service brake is applied and cannot be released.
- ServiceNoRelease,
+ BrakeServiceNoRelease,
/// The service brake is fully applied.
- Full,
+ BrakeFull,
/// The emergency brake is applied.
- Emergency,
+ BrakeEmergency,
}
- /// The current state of the ATC brake.
- private AtcBrakeStates AtcBrakeState;
+ /// The current state of the ATC control.
+ private AtcControlStates AtcControlState;
/// The time needed by the ATC device to initialize, in seconds.
private double InitializationTime = 30;
@@ -75,20 +76,68 @@ namespace OpenbveFcmbTrainPlugin
DeviceState = DeviceStates.Initializing;
}
+ double speed = train.State.Speed.KilometersPerHour;
+ bool stopped = speed < 0.05;
+
+ // Speed limit calculation
+ // By default, use YARD mode speed limit
+ double limit = 25;
+ double powerLimit = limit - 2;
+ double releaseLimit = limit - 5;
+ double emergencyLimit = limit + 4;
+
+ // Speed limit enforcement
+ if (DeviceState == DeviceStates.YARD || DeviceState == DeviceStates.ATP || DeviceState == DeviceStates.ATO)
+ {
+ if (AtcControlState == AtcControlStates.Released && speed >= powerLimit)
+ {
+ // Cut power on power limit
+ AtcControlState = AtcControlStates.NoPower;
+ }
+ if (AtcControlState == AtcControlStates.NoPower && speed < powerLimit)
+ {
+ // Stop cutting power below power limit
+ AtcControlState = AtcControlStates.Released;
+ }
+ if (speed > limit && speed < emergencyLimit)
+ {
+ // Apply service brake on limit
+ AtcControlState = AtcControlStates.BrakeServiceNoRelease;
+ }
+ if (speed > emergencyLimit)
+ {
+ // Unselect driving mode to apply emergency brake if overspeeding
+ DeviceState = DeviceStates.Initialized;
+ }
+
+ // Allow brake release under defined threshold
+ if (AtcControlState == AtcControlStates.BrakeServiceNoRelease && speed < releaseLimit)
+ {
+ AtcControlState = AtcControlStates.BrakeService;
+ }
+ }
+
// Brake application
if (DeviceState != DeviceStates.Override)
{
- switch (AtcBrakeState)
+ switch (AtcControlState)
{
- case AtcBrakeStates.Released:
+ case AtcControlStates.Released:
RequestedBrakeNotch = -1;
+ RequestedPowerNotch = -1;
break;
- case AtcBrakeStates.Service:
- case AtcBrakeStates.ServiceNoRelease:
+ case AtcControlStates.NoPower:
+ RequestedBrakeNotch = -1;
+ RequestedPowerNotch = 0;
+ break;
+ case AtcControlStates.BrakeService:
+ case AtcControlStates.BrakeServiceNoRelease:
RequestedBrakeNotch = train.ServiceBrakeNotch;
+ RequestedPowerNotch = 0;
break;
- case AtcBrakeStates.Emergency:
+ case AtcControlStates.BrakeEmergency:
RequestedBrakeNotch = train.Specs.BrakeNotches + 1;
+ RequestedPowerNotch = 0;
break;
}
}
@@ -108,7 +157,7 @@ namespace OpenbveFcmbTrainPlugin
train.ContinuousProtection = false;
train.VigilanceOverride = false;
// Apply emergency brake during initialization
- AtcBrakeState = AtcBrakeStates.Emergency;
+ AtcControlState = AtcControlStates.BrakeEmergency;
// Wait during initialization time
InitializationCounter += elapsedTime.Seconds;
// If initialization is complete, change the state of the device
@@ -122,15 +171,15 @@ namespace OpenbveFcmbTrainPlugin
case DeviceStates.Initialized:
train.ContinuousProtection = false;
train.VigilanceOverride = false;
- // Apply service brake while no driving mode is selected
- AtcBrakeState = AtcBrakeStates.ServiceNoRelease;
+ // Apply service/emergency brake while no driving mode is selected
+ AtcControlState = stopped ? AtcControlStates.BrakeServiceNoRelease : AtcControlStates.BrakeEmergency;
break;
// ATC device is in YARD (M+25) driving mode
case DeviceStates.YARD:
train.ContinuousProtection = false;
train.VigilanceOverride = false;
// If the train is not moving, count idle time
- if (train.State.Speed.KilometersPerHour < 0.05)
+ if (stopped)
{
YardIdleCounter += elapsedTime.Seconds;
}
@@ -141,16 +190,27 @@ namespace OpenbveFcmbTrainPlugin
// If above idle time, apply the service brake
if (YardIdleCounter >= YardIdleTime)
{
- AtcBrakeState = AtcBrakeStates.Service;
+ AtcControlState = AtcControlStates.BrakeService;
}
else
{
- AtcBrakeState = AtcBrakeStates.Released;
+ AtcControlState = AtcControlStates.Released;
}
// Apply brake if any door opens
if (train.DoorState != DoorStates.None)
{
- RequestedBrakeNotch = train.State.Speed.KilometersPerHour < 0.05 ? train.Specs.BrakeNotches + 1 : train.ServiceBrakeNotch;
+ RequestedBrakeNotch = stopped ? train.Specs.BrakeNotches + 1 : train.ServiceBrakeNotch;
+ }
+ // Speed limitations
+ if (speed > 23)
+ {
+ // Cut power over 23 km/h
+ RequestedPowerNotch = 0;
+ if (speed > 25)
+ {
+ // Apply service brake over 25 km/h
+ AtcControlState = AtcControlStates.BrakeServiceNoRelease;
+ }
}
break;
// ATC device is in ATP (M+ATP) driving mode
@@ -173,20 +233,20 @@ namespace OpenbveFcmbTrainPlugin
// Panel indicators
train.Panel[25] = DeviceState == DeviceStates.Override ? 1 : 0;
train.Panel[26] = DeviceState == DeviceStates.YARD ? 1 : 0;
- train.Panel[26] += DeviceState == DeviceStates.Initialized && train.State.Speed.KilometersPerHour < 0.05 && blink ? 1 : 0;
+ train.Panel[26] += DeviceState == DeviceStates.Initialized && stopped && blink ? 1 : 0;
train.Panel[27] = DeviceState == DeviceStates.ATP ? 1 : 0;
train.Panel[28] = DeviceState == DeviceStates.ATP ? 1 : 0;
- switch (AtcBrakeState)
+ switch (AtcControlState)
{
- case AtcBrakeStates.Released:
- case AtcBrakeStates.Emergency:
+ case AtcControlStates.Released:
+ case AtcControlStates.BrakeEmergency:
train.Panel[32] = 0;
break;
- case AtcBrakeStates.ServiceNoRelease:
- case AtcBrakeStates.Full:
+ case AtcControlStates.BrakeServiceNoRelease:
+ case AtcControlStates.BrakeFull:
train.Panel[32] = 1;
break;
- case AtcBrakeStates.Service:
+ case AtcControlStates.BrakeService:
train.Panel[32] = blink ? 1 : 0;
break;
}
@@ -236,9 +296,9 @@ namespace OpenbveFcmbTrainPlugin
if (!OpenbveFcmbTrainPlugin.KeysPressed[(int)key])
{
// Allow brake release under certain conditions
- if (AtcBrakeState == AtcBrakeStates.Service)
+ if (AtcControlState == AtcControlStates.BrakeService)
{
- AtcBrakeState = AtcBrakeStates.Released;
+ AtcControlState = AtcControlStates.Released;
// Reset YARD idle counter
YardIdleCounter = 0;
}