1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-30 03:26:13 +01:00

Trackmanager rework for simpler structure

This commit is contained in:
Harald Barth 2023-11-14 00:05:18 +01:00
parent 86ed8ff8a6
commit 582ff890f4
6 changed files with 126 additions and 163 deletions

View File

@ -248,6 +248,11 @@ void CommandDistributor::broadcastLoco(byte slot) {
} }
void CommandDistributor::broadcastPower() { void CommandDistributor::broadcastPower() {
char pstr[] = "? x";
for(byte t=0; t<8; t++)
if (TrackManager::getPower(t, pstr))
broadcastReply(COMMAND_TYPE, F("<p%s>\n"),pstr);
bool main=TrackManager::getMainPower()==POWERMODE::ON; bool main=TrackManager::getMainPower()==POWERMODE::ON;
bool prog=TrackManager::getProgPower()==POWERMODE::ON; bool prog=TrackManager::getProgPower()==POWERMODE::ON;
bool join=TrackManager::isJoined(); bool join=TrackManager::isJoined();

View File

@ -553,131 +553,66 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
case '1': // POWERON <1 [MAIN|PROG|JOIN]> case '1': // POWERON <1 [MAIN|PROG|JOIN]>
{ {
bool main=false; if (params > 1) break;
bool prog=false; if (params==0) { // All
bool join=false; TrackManager::setTrackPower(TRACK_MODE_ALL, POWERMODE::ON);
bool singletrack=false; }
//byte t=0; if (params==1) {
if (params > 1) break; if (p[0]==HASH_KEYWORD_MAIN) { // <1 MAIN>
if (params==0) { // All TrackManager::setTrackPower(TRACK_MODE_MAIN, POWERMODE::ON);
main=true;
prog=true;
}
if (params==1) {
if (p[0]==HASH_KEYWORD_MAIN) { // <1 MAIN>
main=true;
} }
#ifndef DISABLE_PROG #ifndef DISABLE_PROG
else if (p[0] == HASH_KEYWORD_JOIN) { // <1 JOIN> else if (p[0] == HASH_KEYWORD_JOIN) { // <1 JOIN>
main=true; TrackManager::setJoin(true);
prog=true; TrackManager::setTrackPower(TRACK_MODE_MAIN|TRACK_MODE_PROG, POWERMODE::ON);
join=true;
} }
else if (p[0]==HASH_KEYWORD_PROG) { // <1 PROG> else if (p[0]==HASH_KEYWORD_PROG) { // <1 PROG>
prog=true; TrackManager::setJoin(false);
TrackManager::setTrackPower(TRACK_MODE_PROG, POWERMODE::ON);
} }
#endif #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> else if (p[0] >= HASH_KEYWORD_A && p[0] <= HASH_KEYWORD_H) { // <1 A-H>
byte t = (p[0] - 'A'); byte t = (p[0] - 'A');
//DIAG(F("Processing track - %d "), t); TrackManager::setTrackPower(POWERMODE::ON, t);
if (TrackManager::isProg(t)) { //StringFormatter::send(stream, F("<p1 %c>\n"), t+'A');
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;
} }
else break; // will reply <X> else break; // will reply <X>
} }
CommandDistributor::broadcastPower();
//TrackManager::streamTrackState(NULL,t);
if (!singletrack) { return;
TrackManager::setJoin(join); }
if (join) TrackManager::setJoinPower(POWERMODE::ON);
else {
if (main) TrackManager::setMainPower(POWERMODE::ON);
if (prog) TrackManager::setProgPower(POWERMODE::ON);
}
CommandDistributor::broadcastPower();
return;
}
}
case '0': // POWEROFF <0 [MAIN | PROG] > case '0': // POWEROFF <0 [MAIN | PROG] >
{ {
bool main=false; if (params > 1) break;
bool prog=false; if (params==0) { // All
bool singletrack=false; TrackManager::setJoin(false);
//byte t=0; TrackManager::setTrackPower(TRACK_MODE_ALL, POWERMODE::OFF);
if (params > 1) break; }
if (params==0) { // All if (params==1) {
main=true; if (p[0]==HASH_KEYWORD_MAIN) { // <0 MAIN>
prog=true; TrackManager::setJoin(false);
} TrackManager::setTrackPower(TRACK_MODE_MAIN, POWERMODE::OFF);
if (params==1) { }
if (p[0]==HASH_KEYWORD_MAIN) { // <0 MAIN>
main=true;
}
#ifndef DISABLE_PROG #ifndef DISABLE_PROG
else if (p[0]==HASH_KEYWORD_PROG) { // <0 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 #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>
else if (p[0] >= HASH_KEYWORD_A && p[0] <= HASH_KEYWORD_H) { // <1 A-H> byte t = (p[0] - 'A');
byte t = (p[0] - 'A'); TrackManager::setJoin(false);
//DIAG(F("Processing track - %d "), t); TrackManager::setTrackPower(POWERMODE::OFF, t);
if (TrackManager::isProg(t)) { //StringFormatter::send(stream, F("<p0 %c>\n"), t+'A');
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 <X>
} }
else break; // will reply <X>
if (!singletrack) { }
TrackManager::setJoin(false); CommandDistributor::broadcastPower();
return;
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;
}
}
case '!': // ESTOP ALL <!> case '!': // ESTOP ALL <!>
DCC::setThrottle(0,1,1); // this broadcasts speed 1(estop) and sets all reminders to speed 1. DCC::setThrottle(0,1,1); // this broadcasts speed 1(estop) and sets all reminders to speed 1.

View File

@ -636,10 +636,10 @@ void RMFT2::loop2() {
//byte thistrack=getOperand(1); //byte thistrack=getOperand(1);
switch (operand) { switch (operand) {
case TRACK_POWER_0: case TRACK_POWER_0:
TrackManager::setTrackPower(TrackManager::isProg(getOperand(1)), false, POWERMODE::OFF, getOperand(1)); TrackManager::setTrackPower(POWERMODE::OFF, getOperand(1));
break; break;
case TRACK_POWER_1: case TRACK_POWER_1:
TrackManager::setTrackPower(TrackManager::isProg(getOperand(1)), false, POWERMODE::ON, getOperand(1)); TrackManager::setTrackPower(POWERMODE::ON, getOperand(1));
break; break;
} }

View File

@ -35,7 +35,8 @@ template<class T> inline T operator& (T a, T b) { return (T)((int)a & (int)b); }
template<class T> inline T operator^ (T a, T b) { return (T)((int)a ^ (int)b); } template<class T> 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, 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_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 setHIGH(fastpin) *fastpin.inout |= fastpin.maskHIGH
#define setLOW(fastpin) *fastpin.inout &= fastpin.maskLOW #define setLOW(fastpin) *fastpin.inout &= fastpin.maskLOW

View File

@ -471,51 +471,48 @@ std::vector<MotorDriver *>TrackManager::getMainDrivers() {
} }
#endif #endif
void TrackManager::setPower2(bool setProg,bool setJoin, POWERMODE mode) { // Set track power for all tracks with this mode
if (!setProg) mainPowerGuess=mode; void TrackManager::setTrackPower(TRACK_MODE trackmode, POWERMODE powermode) {
FOR_EACH_TRACK(t) { FOR_EACH_TRACK(t) {
MotorDriver *driver=track[t];
TrackManager::setTrackPower(setProg, setJoin, mode, t); if (trackmode & driver->getMode()) {
if (powermode == POWERMODE::ON) {
} if (trackmode & TRACK_MODE_DC) {
return; driver->setBrake(true); // DC starts with brake on
} applyDCSpeed(t); // speed match DCC throttles
} else {
void TrackManager::setTrackPower(bool setProg, bool setJoin, POWERMODE mode, byte thistrack) { // toggle brake before turning power on - resets overcurrent error
// on the Pololu board if brake is wired to ^D2.
//DIAG(F("SetTrackPower Processing Track %d"), thistrack); driver->setBrake(true);
MotorDriver * driver=track[thistrack]; driver->setBrake(false); // DCC runs with brake off
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);
} }
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 // This function is for backward JMRI compatibility only
// It reports the first track only, as main, regardless of track settings. // It reports the first track only, as main, regardless of track settings.
// <c MeterName value C/V unit min max res warn> // <c MeterName value C/V unit min max res warn>
@ -524,12 +521,38 @@ void TrackManager::setTrackPower(bool setProg, bool setJoin, POWERMODE mode, byt
track[0]->raw2mA(track[0]->getCurrentRaw(false)), maxCurrent, maxCurrent); track[0]->raw2mA(track[0]->getCurrentRaw(false)), maxCurrent, maxCurrent);
} }
// returns state of the one and only prog track
POWERMODE TrackManager::getProgPower() { POWERMODE TrackManager::getProgPower() {
FOR_EACH_TRACK(t) FOR_EACH_TRACK(t)
if (track[t]->getMode() & TRACK_MODE_PROG) if (track[t]->getMode() & TRACK_MODE_PROG)
return track[t]->getPower(); return track[t]->getPower(); // optimize: there is max one prog track
return POWERMODE::OFF; 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) { void TrackManager::reportObsoleteCurrent(Print* stream) {
// This function is for backward JMRI compatibility only // This function is for backward JMRI compatibility only

View File

@ -62,23 +62,22 @@ class TrackManager {
static void setDCSignal(int16_t cab, byte speedbyte); static void setDCSignal(int16_t cab, byte speedbyte);
static MotorDriver * getProgDriver(); static MotorDriver * getProgDriver();
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
static std::vector<MotorDriver *>getMainDrivers(); static std::vector<MotorDriver *>getMainDrivers();
#endif #endif
static void setPower2(bool progTrack,bool joinTrack,POWERMODE mode);
static void setPower(POWERMODE mode) {setMainPower(mode); setProgPower(mode);} static void setPower(POWERMODE mode) {setMainPower(mode); setProgPower(mode);}
static void setMainPower(POWERMODE mode) {setPower2(false,false,mode);} static void setTrackPower(POWERMODE mode, byte t);
static void setProgPower(POWERMODE mode) {setPower2(true,false,mode);} static void setTrackPower(TRACK_MODE trackmode, POWERMODE powermode);
static void setJoinPower(POWERMODE mode) {setPower2(false,true,mode);} static void setMainPower(POWERMODE mode) {setTrackPower(TRACK_MODE_MAIN, mode);}
static void setTrackPower(bool setProg, bool setJoin, POWERMODE mode, byte thistrack); static void setProgPower(POWERMODE mode) {setTrackPower(TRACK_MODE_PROG, mode);}
static const int16_t MAX_TRACKS=8; static const int16_t MAX_TRACKS=8;
static bool setTrackMode(byte track, TRACK_MODE mode, int16_t DCaddr=0); static bool setTrackMode(byte track, TRACK_MODE mode, int16_t DCaddr=0);
static bool parseJ(Print * stream, int16_t params, int16_t p[]); static bool parseJ(Print * stream, int16_t params, int16_t p[]);
static void loop(); static void loop();
static POWERMODE getMainPower() {return mainPowerGuess;} static POWERMODE getMainPower();
static POWERMODE getProgPower(); static POWERMODE getProgPower();
static bool getPower(byte t, char s[]);
static void setJoin(bool join); static void setJoin(bool join);
static bool isJoined() { return progTrackSyncMain;} static bool isJoined() { return progTrackSyncMain;}
static void setJoinRelayPin(byte joinRelayPin); static void setJoinRelayPin(byte joinRelayPin);