diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index 0e17ea9..f9935d7 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -2,7 +2,7 @@ * © 2021 Neil McKechnie * © 2021-2023 Harald Barth * © 2020-2023 Chris Harlow - * © 2022 Colin Murdoch + * © 2022-2023 Colin Murdoch * All rights reserved. * * This file is part of CommandStation-EX @@ -94,6 +94,7 @@ LookList * RMFT2::onAmberLookup=NULL; LookList * RMFT2::onGreenLookup=NULL; LookList * RMFT2::onChangeLookup=NULL; LookList * RMFT2::onClockLookup=NULL; +LookList * RMFT2::onOverloadLookup=NULL; #define GET_OPCODE GETHIGHFLASH(RMFT2::RouteCode,progCounter) #define SKIPOP progCounter+=3 @@ -175,6 +176,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { onGreenLookup=LookListLoader(OPCODE_ONGREEN); onChangeLookup=LookListLoader(OPCODE_ONCHANGE); onClockLookup=LookListLoader(OPCODE_ONTIME); + onOverloadLookup=LookListLoader(OPCODE_ONOVERLOAD); // Second pass startup, define any turnouts or servos, set signals red @@ -195,6 +197,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { case OPCODE_AT: case OPCODE_ATTIMEOUT2: case OPCODE_AFTER: + case OPCODE_AFTEROVERLOAD: case OPCODE_IF: case OPCODE_IFNOT: { int16_t pin = (int16_t)operand; @@ -684,7 +687,17 @@ void RMFT2::loop2() { } if (millis()-waitAfter < 500 ) return; break; - + + case OPCODE_AFTEROVERLOAD: // waits for the power to be turned back on - either by power routine or button + if (!TrackManager::isPowerOn(operand)) { + // reset timer to half a second and keep waiting + waitAfter=millis(); + delayMe(50); + return; + } + if (millis()-waitAfter < 500 ) return; + break; + case OPCODE_LATCH: setFlag(operand,LATCH_FLAG); break; @@ -986,6 +999,7 @@ void RMFT2::loop2() { case OPCODE_ONGREEN: case OPCODE_ONCHANGE: case OPCODE_ONTIME: + case OPCODE_ONOVERLOAD: break; @@ -1140,6 +1154,16 @@ void RMFT2::clockEvent(int16_t clocktime, bool change) { } } +void RMFT2::powerEvent(int16_t track, bool overload) { + // Hunt for an ONOVERLOAD for this item + if (Diag::CMD) + DIAG(F("Looking for Power event on track : %c"), track); + if (overload) { + handleEvent(F("POWER"),onOverloadLookup,track); + } +} + + void RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) { int pc= handlers->find(id); if (pc<0) return; diff --git a/EXRAIL2.h b/EXRAIL2.h index 4d106e6..6e00561 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -1,7 +1,7 @@ /* * © 2021 Neil McKechnie * © 2020-2022 Chris Harlow - * © 2022 Colin Murdoch + * © 2022-2023 Colin Murdoch * © 2023 Harald Barth * All rights reserved. * @@ -35,7 +35,8 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, OPCODE_FWD,OPCODE_REV,OPCODE_SPEED,OPCODE_INVERT_DIRECTION, OPCODE_RESERVE,OPCODE_FREE, - OPCODE_AT,OPCODE_AFTER,OPCODE_AUTOSTART, + OPCODE_AT,OPCODE_AFTER, + OPCODE_AFTEROVERLOAD,OPCODE_AUTOSTART, OPCODE_ATGTE,OPCODE_ATLT, OPCODE_ATTIMEOUT1,OPCODE_ATTIMEOUT2, OPCODE_LATCH,OPCODE_UNLATCH,OPCODE_SET,OPCODE_RESET, @@ -62,6 +63,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, OPCODE_ONCHANGE, OPCODE_ONCLOCKTIME, OPCODE_ONTIME, + OPCODE_ONOVERLOAD, // OPcodes below this point are skip-nesting IF operations // placed here so that they may be skipped as a group @@ -130,6 +132,7 @@ class LookList { static void activateEvent(int16_t addr, bool active); static void changeEvent(int16_t id, bool change); static void clockEvent(int16_t clocktime, bool change); + static void powerEvent(int16_t track, bool overload); static const int16_t SERVO_SIGNAL_FLAG=0x4000; static const int16_t ACTIVE_HIGH_SIGNAL_FLAG=0x2000; static const int16_t DCC_SIGNAL_FLAG=0x1000; @@ -188,6 +191,7 @@ private: static LookList * onGreenLookup; static LookList * onChangeLookup; static LookList * onClockLookup; + static LookList * onOverloadLookup; // Local variables - exist for each instance/task RMFT2 *next; // loop chain diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index 588a417..22cf562 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -1,6 +1,6 @@ /* * © 2020-2022 Chris Harlow. All rights reserved. - * © 2022 Colin Murdoch + * © 2022-2023 Colin Murdoch * © 2023 Harald Barth * * This file is part of CommandStation-EX @@ -27,6 +27,7 @@ #undef ACTIVATE #undef ACTIVATEL #undef AFTER +#undef AFTEROVERLOAD #undef ALIAS #undef AMBER #undef ANOUT @@ -93,6 +94,7 @@ #undef ONTIME #undef ONCLOCKTIME #undef ONCLOCKMINS +#undef ONOVERLOAD #undef ONGREEN #undef ONRED #undef ONTHROW @@ -152,6 +154,7 @@ #define ACTIVATE(addr,subaddr) #define ACTIVATEL(addr) #define AFTER(sensor_id) +#define AFTEROVERLOAD(track_id) #define ALIAS(name,value...) #define AMBER(signal_id) #define ANOUT(vpin,value,param1,param2) @@ -215,6 +218,7 @@ #define ONTIME(value) #define ONCLOCKTIME(hours,mins) #define ONCLOCKMINS(mins) +#define ONOVERLOAD(track_id) #define ONDEACTIVATE(addr,subaddr) #define ONDEACTIVATEL(linear) #define ONCLOSE(turnout_id) diff --git a/EXRAILMacros.h b/EXRAILMacros.h index 66b0111..d1cad0c 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -1,7 +1,7 @@ /* * © 2021 Neil McKechnie * © 2020-2022 Chris Harlow - * © 2022 Colin Murdoch + * © 2022-2023 Colin Murdoch * © 2023 Harald Barth * All rights reserved. * @@ -256,6 +256,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define ACTIVATE(addr,subaddr) OPCODE_DCCACTIVATE,V(addr<<3 | subaddr<<1 | 1), #define ACTIVATEL(addr) OPCODE_DCCACTIVATE,V((addr+3)<<1 | 1), #define AFTER(sensor_id) OPCODE_AT,V(sensor_id),OPCODE_AFTER,V(sensor_id), +#define AFTEROVERLOAD(track_id) OPCODE_AFTEROVERLOAD,V(TRACK_NUMBER_##track_id), #define ALIAS(name,value...) #define AMBER(signal_id) OPCODE_AMBER,V(signal_id), #define ANOUT(vpin,value,param1,param2) OPCODE_SERVO,V(vpin),OPCODE_PAD,V(value),OPCODE_PAD,V(param1),OPCODE_PAD,V(param2), @@ -320,6 +321,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define ONTIME(value) OPCODE_ONTIME,V(value), #define ONCLOCKTIME(hours,mins) OPCODE_ONTIME,V((STRIP_ZERO(hours)*60)+STRIP_ZERO(mins)), #define ONCLOCKMINS(mins) ONCLOCKTIME(25,mins) +#define ONOVERLOAD(track_id) OPCODE_ONOVERLOAD,V(TRACK_NUMBER_##track_id), #define ONDEACTIVATE(addr,subaddr) OPCODE_ONDEACTIVATE,V(addr<<2|subaddr), #define ONDEACTIVATEL(linear) OPCODE_ONDEACTIVATE,V(linear+3), #define ONGREEN(signal_id) OPCODE_ONGREEN,V(signal_id), diff --git a/MotorDriver.cpp b/MotorDriver.cpp index d5dca13..4644ad5 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -4,6 +4,7 @@ * © 2021 Fred Decker * © 2020-2023 Harald Barth * © 2020-2021 Chris Harlow + * © 2023 Colin Murdoch * All rights reserved. * * This file is part of CommandStation-EX @@ -26,6 +27,7 @@ #include "DCCWaveform.h" #include "DCCTimer.h" #include "DIAG.h" +#include "EXRAIL2.h" unsigned long MotorDriver::globalOverloadStart = 0; @@ -613,7 +615,9 @@ void MotorDriver::checkPowerOverload(bool useProgLimit, byte trackno) { // adjust next wait time power_sample_overload_wait *= 2; if (power_sample_overload_wait > POWER_SAMPLE_RETRY_MAX) - power_sample_overload_wait = POWER_SAMPLE_RETRY_MAX; + power_sample_overload_wait = POWER_SAMPLE_RETRY_MAX; + DIAG(F("Calling EXRAIL")); + RMFT2::powerEvent(trackno, true); // Tell EXRAIL we have an overload // power on test DIAG(F("TRACK %c POWER RESTORE (after %4M)"), trackno + 'A', mslpc); setPower(POWERMODE::ALERT); diff --git a/TrackManager.cpp b/TrackManager.cpp index 91c78ea..bd7c623 100644 --- a/TrackManager.cpp +++ b/TrackManager.cpp @@ -1,6 +1,7 @@ /* * © 2022 Chris Harlow * © 2022 Harald Barth + * © 2023 Colin Murdoch * All rights reserved. * * This file is part of DCC++EX @@ -518,3 +519,10 @@ void TrackManager::setJoin(bool joined) { progTrackSyncMain=joined; if (joinRelay!=UNUSED_PIN) digitalWrite(joinRelay,joined?HIGH:LOW); } + +bool TrackManager::isPowerOn(byte t) { + if (track[t]->getPower()!=POWERMODE::ON) + return false; + return true; + } + diff --git a/TrackManager.h b/TrackManager.h index 965cfa3..60d5f24 100644 --- a/TrackManager.h +++ b/TrackManager.h @@ -1,6 +1,8 @@ /* * © 2022 Chris Harlow * © 2022 Harald Barth + * © 2023 Colin Murdoch + * * All rights reserved. * * This file is part of CommandStation-EX @@ -77,6 +79,7 @@ class TrackManager { static void reportCurrent(Print* stream); static void reportObsoleteCurrent(Print* stream); static void streamTrackState(Print* stream, byte t); + static bool isPowerOn(byte t); static int16_t joinRelay; static bool progTrackSyncMain; // true when prog track is a siding switched to main