diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp
index cd9e89e..89c8714 100644
--- a/CommandDistributor.cpp
+++ b/CommandDistributor.cpp
@@ -248,6 +248,11 @@ void CommandDistributor::broadcastLoco(byte slot) {
}
void CommandDistributor::broadcastPower() {
+ char pstr[] = "? x";
+ for(byte t=0; t<8; t++)
+ if (TrackManager::getPower(t, pstr))
+ broadcastReply(COMMAND_TYPE, F("
\n"),pstr);
+
bool main=TrackManager::getMainPower()==POWERMODE::ON;
bool prog=TrackManager::getProgPower()==POWERMODE::ON;
bool join=TrackManager::isJoined();
diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp
index 96596c6..3b91d86 100644
--- a/DCCEXParser.cpp
+++ b/DCCEXParser.cpp
@@ -553,131 +553,66 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
case '1': // POWERON <1 [MAIN|PROG|JOIN]>
{
- bool main=false;
- bool prog=false;
- bool join=false;
- bool singletrack=false;
- //byte t=0;
- if (params > 1) break;
- if (params==0) { // All
- main=true;
- prog=true;
- }
- if (params==1) {
- if (p[0]==HASH_KEYWORD_MAIN) { // <1 MAIN>
- main=true;
+ if (params > 1) break;
+ if (params==0) { // All
+ TrackManager::setTrackPower(TRACK_MODE_ALL, POWERMODE::ON);
+ }
+ if (params==1) {
+ if (p[0]==HASH_KEYWORD_MAIN) { // <1 MAIN>
+ TrackManager::setTrackPower(TRACK_MODE_MAIN, POWERMODE::ON);
}
#ifndef DISABLE_PROG
else if (p[0] == HASH_KEYWORD_JOIN) { // <1 JOIN>
- main=true;
- prog=true;
- join=true;
+ TrackManager::setJoin(true);
+ TrackManager::setTrackPower(TRACK_MODE_MAIN|TRACK_MODE_PROG, POWERMODE::ON);
}
else if (p[0]==HASH_KEYWORD_PROG) { // <1 PROG>
- prog=true;
+ TrackManager::setJoin(false);
+ TrackManager::setTrackPower(TRACK_MODE_PROG, POWERMODE::ON);
}
#endif
- //else if (p[0] >= 'A' && p[0] <= 'H') { // <1 A-H>
else if (p[0] >= HASH_KEYWORD_A && p[0] <= HASH_KEYWORD_H) { // <1 A-H>
- byte t = (p[0] - 'A');
- //DIAG(F("Processing track - %d "), t);
- if (TrackManager::isProg(t)) {
- main = false;
- prog = true;
- }
- else
- {
- main=true;
- prog=false;
- }
- singletrack=true;
- if (main) TrackManager::setTrackPower(false, false, POWERMODE::ON, t);
- if (prog) TrackManager::setTrackPower(true, false, POWERMODE::ON, t);
-
- StringFormatter::send(stream, F("<1 %c>\n"), t+'A');
- //CommandDistributor::broadcastPower();
- //TrackManager::streamTrackState(NULL,t);
- return;
+ byte t = (p[0] - 'A');
+ TrackManager::setTrackPower(POWERMODE::ON, t);
+ //StringFormatter::send(stream, F("\n"), t+'A');
}
-
else break; // will reply
- }
-
- if (!singletrack) {
- TrackManager::setJoin(join);
- if (join) TrackManager::setJoinPower(POWERMODE::ON);
- else {
- if (main) TrackManager::setMainPower(POWERMODE::ON);
- if (prog) TrackManager::setProgPower(POWERMODE::ON);
- }
- CommandDistributor::broadcastPower();
+ }
+ CommandDistributor::broadcastPower();
+ //TrackManager::streamTrackState(NULL,t);
- return;
- }
+ return;
+ }
- }
-
case '0': // POWEROFF <0 [MAIN | PROG] >
{
- bool main=false;
- bool prog=false;
- bool singletrack=false;
- //byte t=0;
- if (params > 1) break;
- if (params==0) { // All
- main=true;
- prog=true;
- }
- if (params==1) {
- if (p[0]==HASH_KEYWORD_MAIN) { // <0 MAIN>
- main=true;
- }
+ if (params > 1) break;
+ if (params==0) { // All
+ TrackManager::setJoin(false);
+ TrackManager::setTrackPower(TRACK_MODE_ALL, POWERMODE::OFF);
+ }
+ if (params==1) {
+ if (p[0]==HASH_KEYWORD_MAIN) { // <0 MAIN>
+ TrackManager::setJoin(false);
+ TrackManager::setTrackPower(TRACK_MODE_MAIN, POWERMODE::OFF);
+ }
#ifndef DISABLE_PROG
else if (p[0]==HASH_KEYWORD_PROG) { // <0 PROG>
- prog=true;
+ TrackManager::progTrackBoosted=false; // Prog track boost mode will not outlive prog track off
+ TrackManager::setTrackPower(TRACK_MODE_PROG, POWERMODE::OFF);
}
#endif
- //else if (p[0] >= 'A' && p[0] <= 'H') { // <1 A-H>
- else if (p[0] >= HASH_KEYWORD_A && p[0] <= HASH_KEYWORD_H) { // <1 A-H>
- byte t = (p[0] - 'A');
- //DIAG(F("Processing track - %d "), t);
- if (TrackManager::isProg(t)) {
- main = false;
- prog = true;
- }
- else
- {
- main=true;
- prog=false;
- }
- singletrack=true;
- TrackManager::setJoin(false);
- if (main) TrackManager::setTrackPower(false, false, POWERMODE::OFF, t);
- if (prog) {
- TrackManager::progTrackBoosted=false; // Prog track boost mode will not outlive prog track off
- TrackManager::setTrackPower(true, false, POWERMODE::OFF, t);
- }
- StringFormatter::send(stream, F("<0 %c>\n"), t+'A');
- //CommandDistributor::broadcastPower();
- //TrackManager::streamTrackState(NULL, t);
- return;
- }
-
- else break; // will reply
+ else if (p[0] >= HASH_KEYWORD_A && p[0] <= HASH_KEYWORD_H) { // <1 A-H>
+ byte t = (p[0] - 'A');
+ TrackManager::setJoin(false);
+ TrackManager::setTrackPower(POWERMODE::OFF, t);
+ //StringFormatter::send(stream, F("\n"), t+'A');
}
-
- if (!singletrack) {
- TrackManager::setJoin(false);
-
- if (main) TrackManager::setMainPower(POWERMODE::OFF);
- if (prog) {
- TrackManager::progTrackBoosted=false; // Prog track boost mode will not outlive prog track off
- TrackManager::setProgPower(POWERMODE::OFF);
- }
- CommandDistributor::broadcastPower();
- return;
- }
- }
+ else break; // will reply
+ }
+ CommandDistributor::broadcastPower();
+ return;
+ }
case '!': // ESTOP ALL
DCC::setThrottle(0,1,1); // this broadcasts speed 1(estop) and sets all reminders to speed 1.
diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp
index 8e6a6b5..933650c 100644
--- a/EXRAIL2.cpp
+++ b/EXRAIL2.cpp
@@ -636,10 +636,10 @@ void RMFT2::loop2() {
//byte thistrack=getOperand(1);
switch (operand) {
case TRACK_POWER_0:
- TrackManager::setTrackPower(TrackManager::isProg(getOperand(1)), false, POWERMODE::OFF, getOperand(1));
+ TrackManager::setTrackPower(POWERMODE::OFF, getOperand(1));
break;
case TRACK_POWER_1:
- TrackManager::setTrackPower(TrackManager::isProg(getOperand(1)), false, POWERMODE::ON, getOperand(1));
+ TrackManager::setTrackPower(POWERMODE::ON, getOperand(1));
break;
}
diff --git a/MotorDriver.h b/MotorDriver.h
index db2ccc5..19bfd13 100644
--- a/MotorDriver.h
+++ b/MotorDriver.h
@@ -35,7 +35,8 @@ template inline T operator& (T a, T b) { return (T)((int)a & (int)b); }
template inline T operator^ (T a, T b) { return (T)((int)a ^ (int)b); }
enum TRACK_MODE : byte {TRACK_MODE_NONE = 1, TRACK_MODE_MAIN = 2, TRACK_MODE_PROG = 4,
TRACK_MODE_DC = 8, TRACK_MODE_EXT = 16, TRACK_MODE_BOOST = 32,
- TRACK_MODE_INV = 64, TRACK_MODE_DCX = 72, TRACK_MODE_AUTOINV = 128};
+ TRACK_MODE_ALL = 62, // only to operate all tracks
+ TRACK_MODE_INV = 64, TRACK_MODE_DCX = 72 /*DC + INV*/, TRACK_MODE_AUTOINV = 128};
#define setHIGH(fastpin) *fastpin.inout |= fastpin.maskHIGH
#define setLOW(fastpin) *fastpin.inout &= fastpin.maskLOW
diff --git a/TrackManager.cpp b/TrackManager.cpp
index 8cdadb2..ff56001 100644
--- a/TrackManager.cpp
+++ b/TrackManager.cpp
@@ -471,51 +471,48 @@ std::vectorTrackManager::getMainDrivers() {
}
#endif
-void TrackManager::setPower2(bool setProg,bool setJoin, POWERMODE mode) {
- if (!setProg) mainPowerGuess=mode;
- FOR_EACH_TRACK(t) {
-
- TrackManager::setTrackPower(setProg, setJoin, mode, t);
-
- }
- return;
-}
-
-void TrackManager::setTrackPower(bool setProg, bool setJoin, POWERMODE mode, byte thistrack) {
-
- //DIAG(F("SetTrackPower Processing Track %d"), thistrack);
- MotorDriver * driver=track[thistrack];
- if (!driver) return;
-
- TRACK_MODE tm = track[thistrack]->getMode();
- if ( (tm & TRACK_MODE_MAIN)
- && !setProg ){
- // toggle brake before turning power on - resets overcurrent error
- // on the Pololu board if brake is wired to ^D2.
- // XXX see if we can make this conditional
- driver->setBrake(true);
- driver->setBrake(false); // DCC runs with brake off
- driver->setPower(mode);
- } else if ( (tm & TRACK_MODE_DC)
- && !(setProg || setJoin)){
- //DIAG(F("Processing track - %d setProg %d"), thistrack, setProg);
- driver->setBrake(true); // DC starts with brake on
- applyDCSpeed(thistrack); // speed match DCC throttles
- driver->setPower(mode);
- } else if ( (tm & TRACK_MODE_PROG)
- && (setProg || setJoin) ){
- driver->setBrake(true);
- driver->setBrake(false);
- driver->setPower(mode);
- } else if ( (tm & TRACK_MODE_EXT)
- || (tm & TRACK_MODE_BOOST)){
- driver->setBrake(true);
- driver->setBrake(false);
- driver->setPower(mode);
+// Set track power for all tracks with this mode
+void TrackManager::setTrackPower(TRACK_MODE trackmode, POWERMODE powermode) {
+ FOR_EACH_TRACK(t) {
+ MotorDriver *driver=track[t];
+ if (trackmode & driver->getMode()) {
+ if (powermode == POWERMODE::ON) {
+ if (trackmode & TRACK_MODE_DC) {
+ driver->setBrake(true); // DC starts with brake on
+ applyDCSpeed(t); // speed match DCC throttles
+ } else {
+ // toggle brake before turning power on - resets overcurrent error
+ // on the Pololu board if brake is wired to ^D2.
+ driver->setBrake(true);
+ driver->setBrake(false); // DCC runs with brake off
+ }
}
+ driver->setPower(powermode);
+ }
+ }
}
- void TrackManager::reportPowerChange(Print* stream, byte thistrack) {
+// Set track power for this track, inependent of mode
+void TrackManager::setTrackPower(POWERMODE powermode, byte t) {
+ MotorDriver *driver=track[t];
+ TRACK_MODE trackmode = driver->getMode();
+ if (trackmode & TRACK_MODE_DC) {
+ if (powermode == POWERMODE::ON) {
+ driver->setBrake(true); // DC starts with brake on
+ applyDCSpeed(t); // speed match DCC throttles
+ }
+ } else {
+ if (powermode == POWERMODE::ON) {
+ // toggle brake before turning power on - resets overcurrent error
+ // on the Pololu board if brake is wired to ^D2.
+ driver->setBrake(true);
+ driver->setBrake(false); // DCC runs with brake off
+ }
+ }
+ driver->setPower(powermode);
+}
+
+void TrackManager::reportPowerChange(Print* stream, byte thistrack) {
// This function is for backward JMRI compatibility only
// It reports the first track only, as main, regardless of track settings.
//
@@ -524,12 +521,38 @@ void TrackManager::setTrackPower(bool setProg, bool setJoin, POWERMODE mode, byt
track[0]->raw2mA(track[0]->getCurrentRaw(false)), maxCurrent, maxCurrent);
}
+// returns state of the one and only prog track
POWERMODE TrackManager::getProgPower() {
- FOR_EACH_TRACK(t)
- if (track[t]->getMode() & TRACK_MODE_PROG)
- return track[t]->getPower();
- return POWERMODE::OFF;
+ FOR_EACH_TRACK(t)
+ if (track[t]->getMode() & TRACK_MODE_PROG)
+ return track[t]->getPower(); // optimize: there is max one prog track
+ return POWERMODE::OFF;
+}
+
+// returns on if all are on. returns off otherwise
+POWERMODE TrackManager::getMainPower() {
+ POWERMODE result = POWERMODE::OFF;
+ FOR_EACH_TRACK(t) {
+ if (track[t]->getMode() & TRACK_MODE_MAIN) {
+ POWERMODE p = track[t]->getPower();
+ if (p == POWERMODE::OFF)
+ return POWERMODE::OFF; // done and out
+ if (p == POWERMODE::ON)
+ result = POWERMODE::ON;
+ }
}
+ return result;
+}
+
+bool TrackManager::getPower(byte t, char s[]) {
+ if (track[t]) {
+ s[0] = track[t]->getPower() == POWERMODE::ON ? '1' : '0';
+ s[2] = t + 'A';
+ return true;
+ }
+ return false;
+}
+
void TrackManager::reportObsoleteCurrent(Print* stream) {
// This function is for backward JMRI compatibility only
diff --git a/TrackManager.h b/TrackManager.h
index d1edca2..644c45a 100644
--- a/TrackManager.h
+++ b/TrackManager.h
@@ -62,23 +62,22 @@ class TrackManager {
static void setDCSignal(int16_t cab, byte speedbyte);
static MotorDriver * getProgDriver();
#ifdef ARDUINO_ARCH_ESP32
- static std::vectorgetMainDrivers();
+ static std::vectorgetMainDrivers();
#endif
- static void setPower2(bool progTrack,bool joinTrack,POWERMODE mode);
static void setPower(POWERMODE mode) {setMainPower(mode); setProgPower(mode);}
- static void setMainPower(POWERMODE mode) {setPower2(false,false,mode);}
- static void setProgPower(POWERMODE mode) {setPower2(true,false,mode);}
- static void setJoinPower(POWERMODE mode) {setPower2(false,true,mode);}
- static void setTrackPower(bool setProg, bool setJoin, POWERMODE mode, byte thistrack);
-
+ static void setTrackPower(POWERMODE mode, byte t);
+ static void setTrackPower(TRACK_MODE trackmode, POWERMODE powermode);
+ static void setMainPower(POWERMODE mode) {setTrackPower(TRACK_MODE_MAIN, mode);}
+ static void setProgPower(POWERMODE mode) {setTrackPower(TRACK_MODE_PROG, mode);}
static const int16_t MAX_TRACKS=8;
static bool setTrackMode(byte track, TRACK_MODE mode, int16_t DCaddr=0);
static bool parseJ(Print * stream, int16_t params, int16_t p[]);
static void loop();
- static POWERMODE getMainPower() {return mainPowerGuess;}
+ static POWERMODE getMainPower();
static POWERMODE getProgPower();
+ static bool getPower(byte t, char s[]);
static void setJoin(bool join);
static bool isJoined() { return progTrackSyncMain;}
static void setJoinRelayPin(byte joinRelayPin);