From a86bcb1ef51b9ddd4c6ae030d15c7895185b2361 Mon Sep 17 00:00:00 2001 From: jerrrrycho Date: Sat, 7 Nov 2026 20:08:59 +0100 Subject: [PATCH] fix: SM42 shunt mode switched on at the first move of the switch (eu07/maszyna#497) CurrentSwitch() asked MaxCurrentSwitch() first. Since 2e86b3a5 (2021) that one takes any change of the motor overload relay threshold, on every engine type, and reports it, so the first move of the switch only flipped the threshold (meaningless on a diesel) and the shunt mode of the SM42/SP42 (and the 2Ls150 gear of the SM03) took a second one, both on and off; the cab switch, which shows the shunt mode, didn't move at the first click. The diesels with a shunt mode now set it alone. --- McZapkie/Mover.cpp | 27 +++++++++++++-------------- tests/unit/test_diesel.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 330e8eb8..34caced1 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -809,6 +809,19 @@ bool TMoverParameters::ChangeCab(int direction) // rozruch wysoki (true) albo niski (false) bool TMoverParameters::CurrentSwitch(bool const State) { + // TBD, TODO: split off shunt mode toggle into a separate command? It doesn't make much sense to have these two together like that + // the diesels with a shunt mode have no motor overload relay threshold to switch, the switch sets their shunt mode alone. + // MaxCurrentSwitch() takes any change of the setting, so asked first it took the first move of the switch (eu07/maszyna#497) + if (true == ShuntModeAllow && (EngineType == TEngineType::DieselEngine || EngineType == TEngineType::DieselElectric)) + { + // dla 2Ls150 przed ustawieniem kierunku, for SM42/SP42 at the controller's zero position + if (EngineType == TEngineType::DieselEngine ? DirActive != 0 : false == IsMainCtrlNoPowerPos()) + { + return false; + } + ShuntMode = State; + return true; + } if (MaxCurrentSwitch(State)) { @@ -818,20 +831,6 @@ bool TMoverParameters::CurrentSwitch(bool const State) } return true; } - // TBD, TODO: split off shunt mode toggle into a separate command? It doesn't make much sense to have these two together like that - // dla 2Ls150 - if (EngineType == TEngineType::DieselEngine && true == ShuntModeAllow && DirActive == 0) - { - // przed ustawieniem kierunku - ShuntMode = State; - return true; - } - // for SM42/SP42 - if (EngineType == TEngineType::DieselElectric && true == ShuntModeAllow && IsMainCtrlNoPowerPos()) - { - ShuntMode = State; - return true; - } return false; }; diff --git a/tests/unit/test_diesel.cpp b/tests/unit/test_diesel.cpp index 07686dc1..c4ea147d 100644 --- a/tests/unit/test_diesel.cpp +++ b/tests/unit/test_diesel.cpp @@ -177,3 +177,32 @@ TEST_CASE("diesel: the 214M railbus's speed control, up to the speed of a button CHECK_FALSE(railbus.SpeedCtrlUnit.IsActive); scenario.check(); } + +TEST_CASE("diesel: the SM42's shunt mode, switched on and off with one move of the switch") { + // eu07/maszyna#497: the shunt mode of the diesel-electrics (ShuntMode=1) shares its switch with the motor + // overload relay threshold of the electric locomotives (CurrentSwitch()). the SM42 has no such relay, so + // the switch sets the shunt mode at the first move, at the controller's zero position only + scenario scenario{"diesel/sm42 shunt mode", motion() + traction(), test::track{}}; + scenario.add("sm42_v1/6d1", 1); + REQUIRE(scenario.start_up()); + auto &sm42{scenario.cab()}; + REQUIRE(sm42.ShuntModeAllow); + CHECK_FALSE(sm42.ShuntMode); + scenario.act("shunt mode on"); + CHECK(sm42.CurrentSwitch(true)); + CHECK(sm42.ShuntMode); + scenario.get_going(); + scenario.act("shunting power"); + sm42.AnPos = 0.5; + CHECK(sm42.IncMainCtrl(1)); + scenario.wait(60.0); + CHECK(sm42.Vel > 1.0); + // not with the controller out of its zero position + CHECK_FALSE(sm42.CurrentSwitch(false)); + CHECK(sm42.ShuntMode); + scenario.notch_back(0); + scenario.act("shunt mode off"); + CHECK(sm42.CurrentSwitch(false)); + CHECK_FALSE(sm42.ShuntMode); + scenario.check(); +}