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);