diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp index ee760b0..32f9874 100644 --- a/CommandDistributor.cpp +++ b/CommandDistributor.cpp @@ -269,6 +269,6 @@ void CommandDistributor::broadcastRaw(clientType type, char * msg) { broadcastReply(type, F("%s"),msg); } -void CommandDistributor::broadcastTrackState(const FSH* format,byte trackLetter,int16_t dcAddr) { - broadcastReply(COMMAND_TYPE, format,trackLetter,dcAddr); +void CommandDistributor::broadcastTrackState(const FSH* format,byte trackLetter,char pmode, int16_t dcAddr) { + broadcastReply(COMMAND_TYPE, format,trackLetter,pmode, dcAddr); } diff --git a/CommandDistributor.h b/CommandDistributor.h index a51d58a..99b9f1e 100644 --- a/CommandDistributor.h +++ b/CommandDistributor.h @@ -55,7 +55,7 @@ public : static int16_t retClockTime(); static void broadcastPower(); static void broadcastRaw(clientType type,char * msg); - static void broadcastTrackState(const FSH* format,byte trackLetter,int16_t dcAddr); + static void broadcastTrackState(const FSH* format,byte trackLetter,char pmode, int16_t dcAddr); template static void broadcastReply(clientType type, Targs... msg); static void forget(byte clientId); diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 29c252d..150070c 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -555,6 +555,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) bool main=false; bool prog=false; bool join=false; + bool singletrack=false; if (params > 1) break; if (params==0) { // All main=true; @@ -574,12 +575,28 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) prog=true; } #endif + else if (p[0] >= 'A' && p[0] <= 'H') { // <1 A-H> + uint8_t t = (p[0] - 'A'); + if (TrackManager::isProg(t)) { + main = false; + prog = true; + } + else + { + main=true; + prog=false; + } + singletrack=true; + if (main) TrackManager::SetMainTrackPower(POWERMODE::ON, t); + if (prog) TrackManager::SetProgTrackPower(POWERMODE::ON, t); + } else break; // will reply } TrackManager::setJoin(join); - if (main) TrackManager::setMainPower(POWERMODE::ON); - if (prog) TrackManager::setProgPower(POWERMODE::ON); - + if (!singletrack) { + if (main) TrackManager::setMainPower(POWERMODE::ON); + if (prog) TrackManager::setProgPower(POWERMODE::ON); + } CommandDistributor::broadcastPower(); return; } @@ -588,6 +605,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) { bool main=false; bool prog=false; + bool singletrack=false; if (params > 1) break; if (params==0) { // All main=true; @@ -601,17 +619,34 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) else if (p[0]==HASH_KEYWORD_PROG) { // <0 PROG> prog=true; } -#endif +#endif + else if (p[0] >= 'A' && p[0] <= 'H') { // <1 A-H> + uint8_t t = (p[0] - 'A'); + if (TrackManager::isProg(t)) { + main = false; + prog = true; + } + else + { + main=true; + prog=false; + } + singletrack=true; + if (main) TrackManager::SetMainTrackPower(POWERMODE::OFF, t); + if (prog) TrackManager::SetProgTrackPower(POWERMODE::OFF, t); + } + else break; // will reply } TrackManager::setJoin(false); + if (!singletrack) { 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); + if (prog) { + TrackManager::progTrackBoosted=false; // Prog track boost mode will not outlive prog track off + TrackManager::setProgPower(POWERMODE::OFF); + } } - CommandDistributor::broadcastPower(); return; } diff --git a/TrackManager.cpp b/TrackManager.cpp index bd7c623..413fd95 100644 --- a/TrackManager.cpp +++ b/TrackManager.cpp @@ -353,32 +353,48 @@ void TrackManager::streamTrackState(Print* stream, byte t) { // null stream means send to commandDistributor for broadcast if (track[t]==NULL) return; auto format=F(""); + bool pstate = TrackManager::isPowerOn(t); + //char PMODE[] = "OFF"; + //if (pstate) PMODE="ON "; + //if (TrackManager::isPowerOn(t)) {char PMODE[] = "ON";} + // else {char PMODE[] = "OFF";} + switch(track[t]->getMode()) { case TRACK_MODE_MAIN: - format=F("<= %c MAIN>\n"); + format=F("<= %c MAIN %c>\n"); break; #ifndef DISABLE_PROG case TRACK_MODE_PROG: - format=F("<= %c PROG>\n"); + format=F("<= %c PROG %c>\n"); break; #endif case TRACK_MODE_NONE: - format=F("<= %c NONE>\n"); + format=F("<= %c NONE %c>\n"); break; case TRACK_MODE_EXT: - format=F("<= %c EXT>\n"); + format=F("<= %c EXT %c>\n"); break; case TRACK_MODE_DC: - format=F("<= %c DC %d>\n"); + format=F("<= %c DC %c %d>\n"); break; case TRACK_MODE_DCX: - format=F("<= %c DCX %d>\n"); + format=F("<= %c DCX %c %d>\n"); break; default: break; // unknown, dont care } - if (stream) StringFormatter::send(stream,format,'A'+t,trackDCAddr[t]); - else CommandDistributor::broadcastTrackState(format,'A'+t,trackDCAddr[t]); + switch (pstate) { + case true: + if (stream) StringFormatter::send(stream,format,'A'+t,"ON", trackDCAddr[t]); + else CommandDistributor::broadcastTrackState(format,'A'+t,"ON", trackDCAddr[t]); + break; + case false: + if (stream) StringFormatter::send(stream,format,'A'+t,"OFF", trackDCAddr[t]); + else CommandDistributor::broadcastTrackState(format,'A'+t,"OFF", trackDCAddr[t]); + break; + } + //if (stream) StringFormatter::send(stream,format,'A'+t,PMODE, trackDCAddr[t]); + //else CommandDistributor::broadcastTrackState(format,'A'+t,PMODE, trackDCAddr[t]); } byte TrackManager::nextCycleTrack=MAX_TRACKS; @@ -412,45 +428,51 @@ std::vectorTrackManager::getMainDrivers() { } #endif -void TrackManager::setPower2(bool setProg,POWERMODE mode) { +void TrackManager::setPower2(bool setProg,POWERMODE mode, bool doall, uint8_t thistrack) { if (!setProg) mainPowerGuess=mode; FOR_EACH_TRACK(t) { - MotorDriver * driver=track[t]; - if (!driver) continue; - switch (track[t]->getMode()) { - case TRACK_MODE_MAIN: - if (setProg) break; - // 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); - break; - case TRACK_MODE_DC: - case TRACK_MODE_DCX: - if (setProg) break; - driver->setBrake(true); // DC starts with brake on - applyDCSpeed(t); // speed match DCC throttles - driver->setPower(mode); - break; - case TRACK_MODE_PROG: - if (!setProg) break; - driver->setBrake(true); - driver->setBrake(false); - driver->setPower(mode); - break; - case TRACK_MODE_EXT: - driver->setBrake(true); - driver->setBrake(false); - driver->setPower(mode); - break; - case TRACK_MODE_NONE: - break; + if (doall==false && thistrack != t) break; + MotorDriver * driver=track[t]; + if (!driver) continue; + switch (track[t]->getMode()) { + case TRACK_MODE_MAIN: + if (setProg) break; + // 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); + break; + case TRACK_MODE_DC: + case TRACK_MODE_DCX: + if (setProg) break; + driver->setBrake(true); // DC starts with brake on + applyDCSpeed(t); // speed match DCC throttles + driver->setPower(mode); + break; + case TRACK_MODE_PROG: + if (!setProg) break; + driver->setBrake(true); + driver->setBrake(false); + driver->setPower(mode); + break; + case TRACK_MODE_EXT: + driver->setBrake(true); + driver->setBrake(false); + driver->setPower(mode); + break; + case TRACK_MODE_NONE: + break; } + } } - + +// void TrackManager::setTrackPower(bool progTrack,POWERMODE mode, uint8_t track) { +// // write the code for this. +// } + POWERMODE TrackManager::getProgPower() { FOR_EACH_TRACK(t) if (track[t]->getMode()==TRACK_MODE_PROG) @@ -526,3 +548,8 @@ bool TrackManager::isPowerOn(byte t) { return true; } +bool TrackManager::isProg(byte t) { + if (track[t]->getMode()==TRACK_MODE_PROG) + return true; + return false; +} \ No newline at end of file diff --git a/TrackManager.h b/TrackManager.h index 60d5f24..3f9c73f 100644 --- a/TrackManager.h +++ b/TrackManager.h @@ -60,10 +60,12 @@ class TrackManager { #ifdef ARDUINO_ARCH_ESP32 static std::vectorgetMainDrivers(); #endif - static void setPower2(bool progTrack,POWERMODE mode); + static void setPower2(bool progTrack,POWERMODE mode, bool doall, uint8_t thistrack); static void setPower(POWERMODE mode) {setMainPower(mode); setProgPower(mode);} - static void setMainPower(POWERMODE mode) {setPower2(false,mode);} - static void setProgPower(POWERMODE mode) {setPower2(true,mode);} + static void setMainPower(POWERMODE mode) {setPower2(false,mode,true,0);} + static void setProgPower(POWERMODE mode) {setPower2(true,mode,true,0);} + static void SetMainTrackPower(POWERMODE mode, uint8_t track) {setPower2(false,mode,false,track);} + static void SetProgTrackPower(POWERMODE mode, uint8_t track) {setPower2(true,mode,false,track);} static const int16_t MAX_TRACKS=8; static bool setTrackMode(byte track, TRACK_MODE mode, int16_t DCaddr=0); @@ -80,6 +82,7 @@ class TrackManager { static void reportObsoleteCurrent(Print* stream); static void streamTrackState(Print* stream, byte t); static bool isPowerOn(byte t); + static bool isProg(byte t); static int16_t joinRelay; static bool progTrackSyncMain; // true when prog track is a siding switched to main