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

Compare commits

..

1 Commits

Author SHA1 Message Date
Kcsmith0708
1b069aa941
Merge 04f0f56348 into 2ff1619ad1 2023-10-06 20:59:03 +02:00
15 changed files with 156 additions and 475 deletions

2
.gitignore vendored
View File

@ -13,5 +13,3 @@ myFilter.cpp
my*.h my*.h
!my*.example.h !my*.example.h
compile_commands.json compile_commands.json
newcode.txt.old
UserAddin.txt

View File

@ -162,7 +162,7 @@ void CommandDistributor::broadcastTurnout(int16_t id, bool isClosed ) {
} }
void CommandDistributor::broadcastTurntable(int16_t id, uint8_t position, bool moving) { void CommandDistributor::broadcastTurntable(int16_t id, uint8_t position, bool moving) {
broadcastReply(COMMAND_TYPE, F("<I %d %d %d>\n"), id, position, moving); broadcastReply(COMMAND_TYPE, F("<i %d %d %d>\n"), id, position, moving);
} }
void CommandDistributor::broadcastClockTime(int16_t time, int8_t rate) { void CommandDistributor::broadcastClockTime(int16_t time, int8_t rate) {
@ -269,6 +269,6 @@ void CommandDistributor::broadcastRaw(clientType type, char * msg) {
broadcastReply(type, F("%s"),msg); broadcastReply(type, F("%s"),msg);
} }
void CommandDistributor::broadcastTrackState(const FSH* format,byte trackLetter, int16_t dcAddr) { void CommandDistributor::broadcastTrackState(const FSH* format,byte trackLetter,int16_t dcAddr) {
broadcastReply(COMMAND_TYPE, format,trackLetter, dcAddr); broadcastReply(COMMAND_TYPE, format,trackLetter,dcAddr);
} }

View File

@ -55,7 +55,7 @@ public :
static int16_t retClockTime(); static int16_t retClockTime();
static void broadcastPower(); static void broadcastPower();
static void broadcastRaw(clientType type,char * msg); 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,int16_t dcAddr);
template<typename... Targs> static void broadcastReply(clientType type, Targs... msg); template<typename... Targs> static void broadcastReply(clientType type, Targs... msg);
static void forget(byte clientId); static void forget(byte clientId);

View File

@ -60,14 +60,14 @@ Once a new OPCODE is decided upon, update this list.
G, G,
h, h,
H, Turnout state broadcast H, Turnout state broadcast
i, Server details string i, Reserved for future use - Turntable object broadcast
I, Turntable object command, control, and broadcast I, Reserved for future use - Turntable object command and control
j, Throttle responses j, Throttle responses
J, Throttle queries J, Throttle queries
k, Reserved for future use - Potentially Railcom k, Reserved for future use - Potentially Railcom
K, Reserved for future use - Potentially Railcom K, Reserved for future use - Potentially Railcom
l, Loco speedbyte/function map broadcast l, Loco speedbyte/function map broadcast
L, Reserved for LCC interface (implemented in EXRAIL) L,
m, m,
M, Write DCC packet M, Write DCC packet
n, n,
@ -122,7 +122,7 @@ Once a new OPCODE is decided upon, update this list.
for (int16_t i=0;;i+=sizeof(flashList[0])) { \ for (int16_t i=0;;i+=sizeof(flashList[0])) { \
int16_t value=GETHIGHFLASHW(flashList,i); \ int16_t value=GETHIGHFLASHW(flashList,i); \
if (value==INT16_MAX) break; \ if (value==INT16_MAX) break; \
StringFormatter::send(stream,F(" %d"),value); \ if (value != 0) StringFormatter::send(stream,F(" %d"),value); \
} }
@ -157,7 +157,6 @@ const int16_t HASH_KEYWORD_VPIN=-415;
const int16_t HASH_KEYWORD_A='A'; const int16_t HASH_KEYWORD_A='A';
const int16_t HASH_KEYWORD_C='C'; const int16_t HASH_KEYWORD_C='C';
const int16_t HASH_KEYWORD_G='G'; const int16_t HASH_KEYWORD_G='G';
const int16_t HASH_KEYWORD_H='H';
const int16_t HASH_KEYWORD_I='I'; const int16_t HASH_KEYWORD_I='I';
const int16_t HASH_KEYWORD_O='O'; const int16_t HASH_KEYWORD_O='O';
const int16_t HASH_KEYWORD_P='P'; const int16_t HASH_KEYWORD_P='P';
@ -553,131 +552,69 @@ 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; bool main=false;
bool prog=false; bool prog=false;
bool join=false; bool join=false;
bool singletrack=false; if (params > 1) break;
//byte t=0; if (params==0) { // All
if (params > 1) break; main=true;
if (params==0) { // All prog=true;
main=true; }
prog=true; if (params==1) {
} if (p[0]==HASH_KEYWORD_MAIN) { // <1 MAIN>
if (params==1) { main=true;
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; main=true;
prog=true; prog=true;
join=true; join=true;
} }
else if (p[0]==HASH_KEYWORD_PROG) { // <1 PROG> else if (p[0]==HASH_KEYWORD_PROG) { // <1 PROG>
prog=true; prog=true;
} }
#endif #endif
//else if (p[0] >= 'A' && p[0] <= 'H') { // <1 A-H> else break; // will reply <X>
else if (p[0] >= HASH_KEYWORD_A && p[0] <= HASH_KEYWORD_H) { // <1 A-H> }
byte t = (p[0] - 'A'); TrackManager::setJoin(join);
//DIAG(F("Processing track - %d "), t); if (main) TrackManager::setMainPower(POWERMODE::ON);
if (TrackManager::isProg(t)) { if (prog) TrackManager::setProgPower(POWERMODE::ON);
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>
}
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();
return;
}
CommandDistributor::broadcastPower();
return;
} }
case '0': // POWEROFF <0 [MAIN | PROG] > case '0': // POWEROFF <0 [MAIN | PROG] >
{ {
bool main=false; bool main=false;
bool prog=false; bool prog=false;
bool singletrack=false; if (params > 1) break;
//byte t=0; if (params==0) { // All
if (params > 1) break; main=true;
if (params==0) { // All prog=true;
main=true; }
prog=true; if (params==1) {
} if (p[0]==HASH_KEYWORD_MAIN) { // <0 MAIN>
if (params==1) { main=true;
if (p[0]==HASH_KEYWORD_MAIN) { // <0 MAIN> }
main=true; #ifndef DISABLE_PROG
} else if (p[0]==HASH_KEYWORD_PROG) { // <0 PROG>
#ifndef DISABLE_PROG prog=true;
else if (p[0]==HASH_KEYWORD_PROG) { // <0 PROG> }
prog=true; #endif
} else break; // will reply <X>
#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> TrackManager::setJoin(false);
byte t = (p[0] - 'A'); if (main) TrackManager::setMainPower(POWERMODE::OFF);
//DIAG(F("Processing track - %d "), t); if (prog) {
if (TrackManager::isProg(t)) { TrackManager::progTrackBoosted=false; // Prog track boost mode will not outlive prog track off
main = false; TrackManager::setProgPower(POWERMODE::OFF);
prog = true; }
}
else CommandDistributor::broadcastPower();
{ return;
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>
}
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;
} }
}
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.
@ -805,15 +742,11 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
SENDFLASHLIST(stream,RMFT2::rosterIdList) SENDFLASHLIST(stream,RMFT2::rosterIdList)
} }
else { else {
auto rosterName= RMFT2::getRosterName(id); const FSH * functionNames= RMFT2::getRosterFunctions(id);
if (!rosterName) rosterName=F(""); StringFormatter::send(stream,F(" %d \"%S\" \"%S\""),
id, RMFT2::getRosterName(id),
auto functionNames= RMFT2::getRosterFunctions(id); functionNames == NULL ? RMFT2::getRosterFunctions(0) : functionNames);
if (!functionNames) functionNames=RMFT2::getRosterFunctions(0); }
if (!functionNames) functionNames=F("");
StringFormatter::send(stream,F(" %d \"%S\" \"%S\""),
id, rosterName, functionNames);
}
#endif #endif
StringFormatter::send(stream, F(">\n")); StringFormatter::send(stream, F(">\n"));
return; return;
@ -906,9 +839,6 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
break; break;
#endif #endif
case 'L': // LCC interface implemented in EXRAIL parser
break; // Will <X> if not intercepted by EXRAIL
default: //anything else will diagnose and drop out to <X> default: //anything else will diagnose and drop out to <X>
DIAG(F("Opcode=%c params=%d"), opcode, params); DIAG(F("Opcode=%c params=%d"), opcode, params);
for (int i = 0; i < params; i++) for (int i = 0; i < params; i++)
@ -1251,7 +1181,7 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[])
if (tto) { if (tto) {
bool type = tto->isEXTT(); bool type = tto->isEXTT();
uint8_t position = tto->getPosition(); uint8_t position = tto->getPosition();
StringFormatter::send(stream, F("<I %d %d>\n"), type, position); StringFormatter::send(stream, F("<i %d %d>\n"), type, position);
} else { } else {
return false; return false;
} }
@ -1277,7 +1207,7 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[])
if (!DCCTurntable::create(p[0])) return false; if (!DCCTurntable::create(p[0])) return false;
Turntable *tto = Turntable::get(p[0]); Turntable *tto = Turntable::get(p[0]);
tto->addPosition(0, 0, p[2]); tto->addPosition(0, 0, p[2]);
StringFormatter::send(stream, F("<I>\n")); StringFormatter::send(stream, F("<i>\n"));
} else { } else {
if (!tto) return false; if (!tto) return false;
if (!tto->isEXTT()) return false; if (!tto->isEXTT()) return false;
@ -1294,7 +1224,7 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[])
if (!EXTTTurntable::create(p[0], (VPIN)p[2])) return false; if (!EXTTTurntable::create(p[0], (VPIN)p[2])) return false;
Turntable *tto = Turntable::get(p[0]); Turntable *tto = Turntable::get(p[0]);
tto->addPosition(0, 0, p[3]); tto->addPosition(0, 0, p[3]);
StringFormatter::send(stream, F("<I>\n")); StringFormatter::send(stream, F("<i>\n"));
} else { } else {
return false; return false;
} }
@ -1308,7 +1238,7 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[])
// tto must exist, no more than 48 positions, angle 0 - 3600 // tto must exist, no more than 48 positions, angle 0 - 3600
if (!tto || p[2] > 48 || p[4] < 0 || p[4] > 3600) return false; if (!tto || p[2] > 48 || p[4] < 0 || p[4] > 3600) return false;
tto->addPosition(p[2], p[3], p[4]); tto->addPosition(p[2], p[3], p[4]);
StringFormatter::send(stream, F("<I>\n")); StringFormatter::send(stream, F("<i>\n"));
} else { } else {
return false; return false;
} }

View File

@ -85,7 +85,7 @@ RMFT2 * RMFT2::pausingTask=NULL; // Task causing a PAUSE.
// when pausingTask is set, that is the ONLY task that gets any service, // when pausingTask is set, that is the ONLY task that gets any service,
// and all others will have their locos stopped, then resumed after the pausing task resumes. // and all others will have their locos stopped, then resumed after the pausing task resumes.
byte RMFT2::flags[MAX_FLAGS]; byte RMFT2::flags[MAX_FLAGS];
Print * RMFT2::LCCSerial=0;
LookList * RMFT2::sequenceLookup=NULL; LookList * RMFT2::sequenceLookup=NULL;
LookList * RMFT2::onThrowLookup=NULL; LookList * RMFT2::onThrowLookup=NULL;
LookList * RMFT2::onCloseLookup=NULL; LookList * RMFT2::onCloseLookup=NULL;
@ -176,26 +176,23 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
onCloseLookup=LookListLoader(OPCODE_ONCLOSE); onCloseLookup=LookListLoader(OPCODE_ONCLOSE);
onActivateLookup=LookListLoader(OPCODE_ONACTIVATE); onActivateLookup=LookListLoader(OPCODE_ONACTIVATE);
onDeactivateLookup=LookListLoader(OPCODE_ONDEACTIVATE); onDeactivateLookup=LookListLoader(OPCODE_ONDEACTIVATE);
onRedLookup=LookListLoader(OPCODE_ONRED);
onAmberLookup=LookListLoader(OPCODE_ONAMBER);
onGreenLookup=LookListLoader(OPCODE_ONGREEN);
onChangeLookup=LookListLoader(OPCODE_ONCHANGE); onChangeLookup=LookListLoader(OPCODE_ONCHANGE);
onClockLookup=LookListLoader(OPCODE_ONTIME); onClockLookup=LookListLoader(OPCODE_ONTIME);
#ifndef IO_NO_HAL #ifndef IO_NO_HAL
onRotateLookup=LookListLoader(OPCODE_ONROTATE); onRotateLookup=LookListLoader(OPCODE_ONROTATE);
#endif #endif
onOverloadLookup=LookListLoader(OPCODE_ONOVERLOAD); onOverloadLookup=LookListLoader(OPCODE_ONOVERLOAD);
// onLCCLookup is not the same so not loaded here.
// Second pass startup, define any turnouts or servos, set signals red // Second pass startup, define any turnouts or servos, set signals red
// add sequences onRoutines to the lookups // add sequences onRoutines to the lookups
if (compileFeatures & FEATURE_SIGNAL) {
onRedLookup=LookListLoader(OPCODE_ONRED);
onAmberLookup=LookListLoader(OPCODE_ONAMBER);
onGreenLookup=LookListLoader(OPCODE_ONGREEN);
for (int sigslot=0;;sigslot++) { for (int sigslot=0;;sigslot++) {
VPIN sigid=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigslot*8); VPIN sigid=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigslot*8);
if (sigid==0) break; // end of signal list if (sigid==0) break; // end of signal list
doSignal(sigid & SIGNAL_ID_MASK, SIGNAL_RED); doSignal(sigid & SIGNAL_ID_MASK, SIGNAL_RED);
} }
}
int progCounter; int progCounter;
for (progCounter=0;; SKIPOP){ for (progCounter=0;; SKIPOP){
@ -346,65 +343,13 @@ void RMFT2::ComandFilter(Print * stream, byte & opcode, byte & paramCount, int16
reject=!parseSlash(stream,paramCount,p); reject=!parseSlash(stream,paramCount,p);
opcode=0; opcode=0;
break; break;
case 'L':
if (compileFeatures & FEATURE_LCC) {
// This entire code block is compiled out if LLC macros not used
if (paramCount==0) { //<L> LCC adapter introducing self
LCCSerial=stream; // now we know where to send events we raise
// loop through all possible sent events
for (int progCounter=0;; SKIPOP) {
byte opcode=GET_OPCODE;
if (opcode==OPCODE_ENDEXRAIL) break;
if (opcode==OPCODE_LCC) StringFormatter::send(stream,F("<LS x%h>\n"),getOperand(progCounter,0));
if (opcode==OPCODE_LCCX) { // long form LCC
StringFormatter::send(stream,F("<LS x%h%h%h%h>\n"),
getOperand(progCounter,1),
getOperand(progCounter,2),
getOperand(progCounter,3),
getOperand(progCounter,0)
);
}}
// we stream the hex events we wish to listen to
// and at the same time build the event index looku.
int eventIndex=0;
for (int progCounter=0;; SKIPOP) {
byte opcode=GET_OPCODE;
if (opcode==OPCODE_ENDEXRAIL) break;
if (opcode==OPCODE_ONLCC) {
onLCCLookup[eventIndex]=progCounter; // TODO skip...
StringFormatter::send(stream,F("<LL %d x%h%h%h:%h>\n"),
eventIndex,
getOperand(progCounter,1),
getOperand(progCounter,2),
getOperand(progCounter,3),
getOperand(progCounter,0)
);
eventIndex++;
}
}
StringFormatter::send(stream,F("<LR>\n")); // Ready to rumble
opcode=0;
break;
}
if (paramCount==1) { // <L eventid> LCC event arrived from adapter
int16_t eventid=p[0];
reject=eventid<0 || eventid>=countLCCLookup;
if (!reject) startNonRecursiveTask(F("LCC"),eventid,onLCCLookup[eventid]);
opcode=0;
}
}
break;
default: // other commands pass through default: // other commands pass through
break; break;
} }
if (reject) { if (reject) {
opcode=0; opcode=0;
StringFormatter::send(stream,F("<X>\n")); StringFormatter::send(stream,F("<X>"));
} }
} }
@ -432,19 +377,17 @@ bool RMFT2::parseSlash(Print * stream, byte & paramCount, int16_t p[]) {
if (flag & LATCH_FLAG) StringFormatter::send(stream,F(" LATCHED")); if (flag & LATCH_FLAG) StringFormatter::send(stream,F(" LATCHED"));
} }
} }
// do the signals
if (compileFeatures & FEATURE_SIGNAL) { // flags[n] represents the state of the nth signal in the table
// do the signals for (int sigslot=0;;sigslot++) {
// flags[n] represents the state of the nth signal in the table VPIN sigid=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigslot*8);
for (int sigslot=0;;sigslot++) { if (sigid==0) break; // end of signal list
VPIN sigid=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigslot*8); byte flag=flags[sigslot] & SIGNAL_MASK; // obtain signal flags for this id
if (sigid==0) break; // end of signal list StringFormatter::send(stream,F("\n%S[%d]"),
byte flag=flags[sigslot] & SIGNAL_MASK; // obtain signal flags for this id (flag == SIGNAL_RED)? F("RED") : (flag==SIGNAL_GREEN) ? F("GREEN") : F("AMBER"),
StringFormatter::send(stream,F("\n%S[%d]"), sigid & SIGNAL_ID_MASK);
(flag == SIGNAL_RED)? F("RED") : (flag==SIGNAL_GREEN) ? F("GREEN") : F("AMBER"),
sigid & SIGNAL_ID_MASK);
}
} }
StringFormatter::send(stream,F(" *>\n")); StringFormatter::send(stream,F(" *>\n"));
return true; return true;
} }
@ -838,20 +781,6 @@ void RMFT2::loop2() {
CommandDistributor::broadcastPower(); CommandDistributor::broadcastPower();
break; break;
case OPCODE_SET_POWER:
// operand is TRACK_POWER , trackid
//byte thistrack=getOperand(1);
switch (operand) {
case TRACK_POWER_0:
TrackManager::setTrackPower(TrackManager::isProg(getOperand(1)), false, POWERMODE::OFF, getOperand(1));
break;
case TRACK_POWER_1:
TrackManager::setTrackPower(TrackManager::isProg(getOperand(1)), false, POWERMODE::ON, getOperand(1));
break;
}
break;
case OPCODE_SET_TRACK: case OPCODE_SET_TRACK:
// operand is trackmode<<8 | track id // operand is trackmode<<8 | track id
// If DC/DCX use my loco for DC address // If DC/DCX use my loco for DC address
@ -1092,20 +1021,6 @@ void RMFT2::loop2() {
} }
break; break;
case OPCODE_LCC: // short form LCC
if ((compileFeatures & FEATURE_LCC) && LCCSerial)
StringFormatter::send(LCCSerial,F("<L x%h>"),(uint16_t)operand);
break;
case OPCODE_LCCX: // long form LCC
if ((compileFeatures & FEATURE_LCC) && LCCSerial)
StringFormatter::send(LCCSerial,F("<L x%h%h%h%h>\n"),
getOperand(progCounter,1),
getOperand(progCounter,2),
getOperand(progCounter,3),
getOperand(progCounter,0)
);
break;
case OPCODE_SERVO: // OPCODE_SERVO,V(vpin),OPCODE_PAD,V(position),OPCODE_PAD,V(profile),OPCODE_PAD,V(duration) case OPCODE_SERVO: // OPCODE_SERVO,V(vpin),OPCODE_PAD,V(position),OPCODE_PAD,V(profile),OPCODE_PAD,V(duration)
IODevice::writeAnalogue(operand,getOperand(1),getOperand(2),getOperand(3)); IODevice::writeAnalogue(operand,getOperand(1),getOperand(2),getOperand(3));
@ -1143,7 +1058,6 @@ void RMFT2::loop2() {
case OPCODE_SERVOTURNOUT: // Turnout definition ignored at runtime case OPCODE_SERVOTURNOUT: // Turnout definition ignored at runtime
case OPCODE_PINTURNOUT: // Turnout definition ignored at runtime case OPCODE_PINTURNOUT: // Turnout definition ignored at runtime
case OPCODE_ONCLOSE: // Turnout event catchers ignored here case OPCODE_ONCLOSE: // Turnout event catchers ignored here
case OPCODE_ONLCC: // LCC event catchers ignored here
case OPCODE_ONTHROW: case OPCODE_ONTHROW:
case OPCODE_ONACTIVATE: // Activate event catchers ignored here case OPCODE_ONACTIVATE: // Activate event catchers ignored here
case OPCODE_ONDEACTIVATE: case OPCODE_ONDEACTIVATE:
@ -1213,7 +1127,6 @@ int16_t RMFT2::getSignalSlot(int16_t id) {
} }
/* static */ void RMFT2::doSignal(int16_t id,char rag) { /* static */ void RMFT2::doSignal(int16_t id,char rag) {
if (!(compileFeatures & FEATURE_SIGNAL)) return; // dont compile code below
if (diag) DIAG(F(" doSignal %d %x"),id,rag); if (diag) DIAG(F(" doSignal %d %x"),id,rag);
// Schedule any event handler for this signal change. // Schedule any event handler for this signal change.
@ -1281,7 +1194,6 @@ int16_t RMFT2::getSignalSlot(int16_t id) {
} }
/* static */ bool RMFT2::isSignal(int16_t id,char rag) { /* static */ bool RMFT2::isSignal(int16_t id,char rag) {
if (!(compileFeatures & FEATURE_SIGNAL)) return false;
int16_t sigslot=getSignalSlot(id); int16_t sigslot=getSignalSlot(id);
if (sigslot<0) return false; if (sigslot<0) return false;
return (flags[sigslot] & SIGNAL_MASK) == rag; return (flags[sigslot] & SIGNAL_MASK) == rag;
@ -1334,10 +1246,8 @@ void RMFT2::powerEvent(int16_t track, bool overload) {
void RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) { void RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) {
int pc= handlers->find(id); int pc= handlers->find(id);
if (pc>=0) startNonRecursiveTask(reason,id,pc); if (pc<0) return;
}
void RMFT2::startNonRecursiveTask(const FSH* reason, int16_t id,int pc) {
// Check we dont already have a task running this handler // Check we dont already have a task running this handler
RMFT2 * task=loopTask; RMFT2 * task=loopTask;
while(task) { while(task) {

View File

@ -59,14 +59,15 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
OPCODE_ROSTER,OPCODE_KILLALL, OPCODE_ROSTER,OPCODE_KILLALL,
OPCODE_ROUTE,OPCODE_AUTOMATION,OPCODE_SEQUENCE, OPCODE_ROUTE,OPCODE_AUTOMATION,OPCODE_SEQUENCE,
OPCODE_ENDTASK,OPCODE_ENDEXRAIL, OPCODE_ENDTASK,OPCODE_ENDEXRAIL,
OPCODE_SET_TRACK,OPCODE_SET_POWER, OPCODE_SET_TRACK,
OPCODE_ONRED,OPCODE_ONAMBER,OPCODE_ONGREEN, OPCODE_ONRED,OPCODE_ONAMBER,OPCODE_ONGREEN,
OPCODE_ONCHANGE, OPCODE_ONCHANGE,
OPCODE_ONCLOCKTIME, OPCODE_ONCLOCKTIME,
OPCODE_ONTIME, OPCODE_ONTIME,
#ifndef IO_NO_HAL
OPCODE_TTADDPOSITION,OPCODE_DCCTURNTABLE,OPCODE_EXTTTURNTABLE, OPCODE_TTADDPOSITION,OPCODE_DCCTURNTABLE,OPCODE_EXTTTURNTABLE,
OPCODE_ONROTATE,OPCODE_ROTATE,OPCODE_WAITFORTT, OPCODE_ONROTATE,OPCODE_ROTATE,OPCODE_IFTTPOSITION,OPCODE_WAITFORTT,
OPCODE_LCC,OPCODE_LCCX,OPCODE_ONLCC, #endif
OPCODE_ONOVERLOAD, OPCODE_ONOVERLOAD,
// OPcodes below this point are skip-nesting IF operations // OPcodes below this point are skip-nesting IF operations
@ -80,8 +81,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
OPCODE_IFRANDOM,OPCODE_IFRESERVE, OPCODE_IFRANDOM,OPCODE_IFRESERVE,
OPCODE_IFCLOSED,OPCODE_IFTHROWN, OPCODE_IFCLOSED,OPCODE_IFTHROWN,
OPCODE_IFRE, OPCODE_IFRE,
OPCODE_IFLOCO, OPCODE_IFLOCO
OPCODE_IFTTPOSITION
}; };
// Ensure thrunge_lcd is put last as there may be more than one display, // Ensure thrunge_lcd is put last as there may be more than one display,
@ -95,10 +95,6 @@ enum thrunger: byte {
thrunge_lcd, // Must be last!! thrunge_lcd, // Must be last!!
}; };
// Flag bits for compile time features.
static const byte FEATURE_SIGNAL= 0x80;
static const byte FEATURE_LCC = 0x40;
static const byte FEATURE_ROSTER= 0x20;
// Flag bits for status of hardware and TPL // Flag bits for status of hardware and TPL
@ -178,7 +174,6 @@ private:
OPCODE op2=OPCODE_ENDEXRAIL,OPCODE op3=OPCODE_ENDEXRAIL); OPCODE op2=OPCODE_ENDEXRAIL,OPCODE op3=OPCODE_ENDEXRAIL);
static void handleEvent(const FSH* reason,LookList* handlers, int16_t id); static void handleEvent(const FSH* reason,LookList* handlers, int16_t id);
static uint16_t getOperand(int progCounter,byte n); static uint16_t getOperand(int progCounter,byte n);
static void startNonRecursiveTask(const FSH* reason, int16_t id,int pc);
static RMFT2 * loopTask; static RMFT2 * loopTask;
static RMFT2 * pausingTask; static RMFT2 * pausingTask;
void delayMe(long millisecs); void delayMe(long millisecs);
@ -197,7 +192,6 @@ private:
static const HIGHFLASH byte RouteCode[]; static const HIGHFLASH byte RouteCode[];
static const HIGHFLASH int16_t SignalDefinitions[]; static const HIGHFLASH int16_t SignalDefinitions[];
static byte flags[MAX_FLAGS]; static byte flags[MAX_FLAGS];
static Print * LCCSerial;
static LookList * sequenceLookup; static LookList * sequenceLookup;
static LookList * onThrowLookup; static LookList * onThrowLookup;
static LookList * onCloseLookup; static LookList * onCloseLookup;
@ -213,10 +207,6 @@ private:
#endif #endif
static LookList * onOverloadLookup; static LookList * onOverloadLookup;
static const int countLCCLookup;
static int onLCCLookup[];
static const byte compileFeatures;
// Local variables - exist for each instance/task // Local variables - exist for each instance/task
RMFT2 *next; // loop chain RMFT2 *next; // loop chain
int progCounter; // Byte offset of next route opcode in ROUTES table int progCounter; // Byte offset of next route opcode in ROUTES table

View File

@ -86,8 +86,6 @@
#undef LATCH #undef LATCH
#undef LCD #undef LCD
#undef SCREEN #undef SCREEN
#undef LCC
#undef LCCX
#undef LCN #undef LCN
#undef MOVETT #undef MOVETT
#undef ONACTIVATE #undef ONACTIVATE
@ -96,7 +94,6 @@
#undef ONDEACTIVATE #undef ONDEACTIVATE
#undef ONDEACTIVATEL #undef ONDEACTIVATEL
#undef ONCLOSE #undef ONCLOSE
#undef ONLCC
#undef ONTIME #undef ONTIME
#undef ONCLOCKTIME #undef ONCLOCKTIME
#undef ONCLOCKMINS #undef ONCLOCKMINS
@ -141,7 +138,6 @@
#undef SERVO_SIGNAL #undef SERVO_SIGNAL
#undef SET #undef SET
#undef SET_TRACK #undef SET_TRACK
#undef SET_POWER
#undef SETLOCO #undef SETLOCO
#undef SIGNAL #undef SIGNAL
#undef SIGNALH #undef SIGNALH
@ -196,7 +192,7 @@
#define ENDTASK #define ENDTASK
#define ESTOP #define ESTOP
#define EXRAIL #define EXRAIL
#define EXTT_TURNTABLE(id,vpin,home,description) #define EXTT_TURNTABLE(id,vpin,i2c_address,home,description)
#define FADE(pin,value,ms) #define FADE(pin,value,ms)
#define FOFF(func) #define FOFF(func)
#define FOLLOW(route) #define FOLLOW(route)
@ -225,8 +221,6 @@
#define JOIN #define JOIN
#define KILLALL #define KILLALL
#define LATCH(sensor_id) #define LATCH(sensor_id)
#define LCC(eventid)
#define LCCX(senderid,eventid)
#define LCD(row,msg) #define LCD(row,msg)
#define SCREEN(display,row,msg) #define SCREEN(display,row,msg)
#define LCN(msg) #define LCN(msg)
@ -241,7 +235,6 @@
#define ONDEACTIVATE(addr,subaddr) #define ONDEACTIVATE(addr,subaddr)
#define ONDEACTIVATEL(linear) #define ONDEACTIVATEL(linear)
#define ONCLOSE(turnout_id) #define ONCLOSE(turnout_id)
#define ONLCC(sender,event)
#define ONGREEN(signal_id) #define ONGREEN(signal_id)
#define ONRED(signal_id) #define ONRED(signal_id)
#define ONROTATE(turntable_id) #define ONROTATE(turntable_id)
@ -282,7 +275,6 @@
#define SERVO_TURNOUT(id,pin,activeAngle,inactiveAngle,profile,description...) #define SERVO_TURNOUT(id,pin,activeAngle,inactiveAngle,profile,description...)
#define SET(pin) #define SET(pin)
#define SET_TRACK(track,mode) #define SET_TRACK(track,mode)
#define SET_POWER(track,onoff)
#define SETLOCO(loco) #define SETLOCO(loco)
#define SIGNAL(redpin,amberpin,greenpin) #define SIGNAL(redpin,amberpin,greenpin)
#define SIGNALH(redpin,amberpin,greenpin) #define SIGNALH(redpin,amberpin,greenpin)

View File

@ -63,11 +63,6 @@
// (10#mins)%100) // (10#mins)%100)
#define STRIP_ZERO(value) 10##value%100 #define STRIP_ZERO(value) 10##value%100
// These constants help EXRAIL macros convert Track Power e.g. SET_POWER(A ON|OFF).
//const byte TRACK_POWER_0=0, TRACK_POWER_OFF=0;
//const byte TRACK_POWER_1=1, TRACK_POWER_ON=1;
// Pass 1 Implements aliases // Pass 1 Implements aliases
#include "EXRAIL2MacroReset.h" #include "EXRAIL2MacroReset.h"
#undef ALIAS #undef ALIAS
@ -79,34 +74,12 @@
#include "EXRAIL2MacroReset.h" #include "EXRAIL2MacroReset.h"
#undef HAL #undef HAL
#define HAL(haltype,params...) haltype::create(params); #define HAL(haltype,params...) haltype::create(params);
#undef EXTT_TURNTABLE
#define EXTT_TURNTABLE(id,vpin,i2c_address,home,description...) EXTurntable::create(vpin,1,i2c_address);
void exrailHalSetup() { void exrailHalSetup() {
#include "myAutomation.h" #include "myAutomation.h"
} }
// Pass 1c detect compile time featurtes
#include "EXRAIL2MacroReset.h"
#undef SIGNAL
#define SIGNAL(redpin,amberpin,greenpin) | FEATURE_SIGNAL
#undef SIGNALH
#define SIGNALH(redpin,amberpin,greenpin) | FEATURE_SIGNAL
#undef SERVO_SIGNAL
#define SERVO_SIGNAL(vpin,redval,amberval,greenval) | FEATURE_SIGNAL
#undef DCC_SIGNAL
#define DCC_SIGNAL(id,addr,subaddr) | FEATURE_SIGNAL
#undef VIRTUAL_SIGNAL
#define VIRTUAL_SIGNAL(id) | FEATURE_SIGNAL
#undef LCC
#define LCC(eventid) | FEATURE_LCC
#undef LCCX
#define LCCX(senderid,eventid) | FEATURE_LCC
#undef ONLCC
#define ONLCC(senderid,eventid) | FEATURE_LCC
const byte RMFT2::compileFeatures = 0
#include "myAutomation.h"
;
// Pass 2 create throttle route list // Pass 2 create throttle route list
#include "EXRAIL2MacroReset.h" #include "EXRAIL2MacroReset.h"
#undef ROUTE #undef ROUTE
@ -224,7 +197,7 @@ const FSH * RMFT2::getTurnoutDescription(int16_t turnoutid) {
#undef DCC_TURNTABLE #undef DCC_TURNTABLE
#define DCC_TURNTABLE(id,home,description...) O_DESC(id,description) #define DCC_TURNTABLE(id,home,description...) O_DESC(id,description)
#undef EXTT_TURNTABLE #undef EXTT_TURNTABLE
#define EXTT_TURNTABLE(id,vpin,home,description...) O_DESC(id,description) #define EXTT_TURNTABLE(id,vpin,i2c_address,home,description...) O_DESC(id,description)
const FSH * RMFT2::getTurntableDescription(int16_t turntableId) { const FSH * RMFT2::getTurntableDescription(int16_t turntableId) {
switch (turntableId) { switch (turntableId) {
@ -300,16 +273,6 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = {
#include "myAutomation.h" #include "myAutomation.h"
0,0,0,0 }; 0,0,0,0 };
// Pass 9 ONLCC counter and lookup array
#include "EXRAIL2MacroReset.h"
#undef ONLCC
#define ONLCC(sender,event) +1
const int RMFT2::countLCCLookup=0
#include "myAutomation.h"
;
int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
// Last Pass : create main routes table // Last Pass : create main routes table
// Only undef the macros, not dummy them. // Only undef the macros, not dummy them.
#define RMFT2_UNDEF_ONLY #define RMFT2_UNDEF_ONLY
@ -354,7 +317,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#define ESTOP OPCODE_SPEED,V(1), #define ESTOP OPCODE_SPEED,V(1),
#define EXRAIL #define EXRAIL
#ifndef IO_NO_HAL #ifndef IO_NO_HAL
#define EXTT_TURNTABLE(id,vpin,home,description...) OPCODE_EXTTTURNTABLE,V(id),OPCODE_PAD,V(vpin),OPCODE_PAD,V(home), #define EXTT_TURNTABLE(id,vpin,i2c_address,home,description...) OPCODE_EXTTTURNTABLE,V(id),OPCODE_PAD,V(vpin),OPCODE_PAD,V(i2c_address),OPCODE_PAD,V(home),
#endif #endif
#define FADE(pin,value,ms) OPCODE_SERVO,V(pin),OPCODE_PAD,V(value),OPCODE_PAD,V(PCA9685::ProfileType::UseDuration|PCA9685::NoPowerOff),OPCODE_PAD,V(ms/100L), #define FADE(pin,value,ms) OPCODE_SERVO,V(pin),OPCODE_PAD,V(value),OPCODE_PAD,V(PCA9685::ProfileType::UseDuration|PCA9685::NoPowerOff),OPCODE_PAD,V(ms/100L),
#define FOFF(func) OPCODE_FOFF,V(func), #define FOFF(func) OPCODE_FOFF,V(func),
@ -386,11 +349,6 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#define JOIN OPCODE_JOIN,0,0, #define JOIN OPCODE_JOIN,0,0,
#define KILLALL OPCODE_KILLALL,0,0, #define KILLALL OPCODE_KILLALL,0,0,
#define LATCH(sensor_id) OPCODE_LATCH,V(sensor_id), #define LATCH(sensor_id) OPCODE_LATCH,V(sensor_id),
#define LCC(eventid) OPCODE_LCC,V(eventid),
#define LCCX(sender,event) OPCODE_LCCX,V(event),\
OPCODE_PAD,V((((uint64_t)sender)>>32)&0xFFFF),\
OPCODE_PAD,V((((uint64_t)sender)>>16)&0xFFFF),\
OPCODE_PAD,V((((uint64_t)sender)>>0)&0xFFFF),
#define LCD(id,msg) PRINT(msg) #define LCD(id,msg) PRINT(msg)
#define SCREEN(display,id,msg) PRINT(msg) #define SCREEN(display,id,msg) PRINT(msg)
#define LCN(msg) PRINT(msg) #define LCN(msg) PRINT(msg)
@ -399,10 +357,6 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#define ONACTIVATEL(linear) OPCODE_ONACTIVATE,V(linear+3), #define ONACTIVATEL(linear) OPCODE_ONACTIVATE,V(linear+3),
#define ONAMBER(signal_id) OPCODE_ONAMBER,V(signal_id), #define ONAMBER(signal_id) OPCODE_ONAMBER,V(signal_id),
#define ONCLOSE(turnout_id) OPCODE_ONCLOSE,V(turnout_id), #define ONCLOSE(turnout_id) OPCODE_ONCLOSE,V(turnout_id),
#define ONLCC(sender,event) OPCODE_ONLCC,V(event),\
OPCODE_PAD,V((((uint64_t)sender)>>32)&0xFFFF),\
OPCODE_PAD,V((((uint64_t)sender)>>16)&0xFFFF),\
OPCODE_PAD,V((((uint64_t)sender)>>0)&0xFFFF),
#define ONTIME(value) OPCODE_ONTIME,V(value), #define ONTIME(value) OPCODE_ONTIME,V(value),
#define ONCLOCKTIME(hours,mins) OPCODE_ONTIME,V((STRIP_ZERO(hours)*60)+STRIP_ZERO(mins)), #define ONCLOCKTIME(hours,mins) OPCODE_ONTIME,V((STRIP_ZERO(hours)*60)+STRIP_ZERO(mins)),
#define ONCLOCKMINS(mins) ONCLOCKTIME(25,mins) #define ONCLOCKMINS(mins) ONCLOCKTIME(25,mins)
@ -453,7 +407,6 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#define SERVO_TURNOUT(id,pin,activeAngle,inactiveAngle,profile,description...) OPCODE_SERVOTURNOUT,V(id),OPCODE_PAD,V(pin),OPCODE_PAD,V(activeAngle),OPCODE_PAD,V(inactiveAngle),OPCODE_PAD,V(PCA9685::ProfileType::profile), #define SERVO_TURNOUT(id,pin,activeAngle,inactiveAngle,profile,description...) OPCODE_SERVOTURNOUT,V(id),OPCODE_PAD,V(pin),OPCODE_PAD,V(activeAngle),OPCODE_PAD,V(inactiveAngle),OPCODE_PAD,V(PCA9685::ProfileType::profile),
#define SET(pin) OPCODE_SET,V(pin), #define SET(pin) OPCODE_SET,V(pin),
#define SET_TRACK(track,mode) OPCODE_SET_TRACK,V(TRACK_MODE_##mode <<8 | TRACK_NUMBER_##track), #define SET_TRACK(track,mode) OPCODE_SET_TRACK,V(TRACK_MODE_##mode <<8 | TRACK_NUMBER_##track),
#define SET_POWER(track,onoff) OPCODE_SET_POWER,V(TRACK_POWER_##onoff),OPCODE_PAD, V(TRACK_NUMBER_##track),
#define SETLOCO(loco) OPCODE_SETLOCO,V(loco), #define SETLOCO(loco) OPCODE_SETLOCO,V(loco),
#define SIGNAL(redpin,amberpin,greenpin) #define SIGNAL(redpin,amberpin,greenpin)
#define SIGNALH(redpin,amberpin,greenpin) #define SIGNALH(redpin,amberpin,greenpin)

View File

@ -117,7 +117,6 @@ void StringFormatter::send2(Print * stream,const FSH* format, va_list args) {
case 'o': stream->print(va_arg(args, int), OCT); break; case 'o': stream->print(va_arg(args, int), OCT); break;
case 'x': stream->print((unsigned int)va_arg(args, unsigned int), HEX); break; case 'x': stream->print((unsigned int)va_arg(args, unsigned int), HEX); break;
case 'X': stream->print((unsigned long)va_arg(args, unsigned long), HEX); break; case 'X': stream->print((unsigned long)va_arg(args, unsigned long), HEX); break;
case 'h': printHex(stream,(unsigned int)va_arg(args, unsigned int)); break;
case 'M': case 'M':
{ // this prints a unsigned long microseconds time in readable format { // this prints a unsigned long microseconds time in readable format
unsigned long time = va_arg(args, long); unsigned long time = va_arg(args, long);
@ -219,15 +218,4 @@ void StringFormatter::printPadded(Print* stream, long value, byte width, bool fo
if (!formatLeft) stream->print(value, DEC); if (!formatLeft) stream->print(value, DEC);
} }
// printHex prints the full 2 byte hex with leading zeros, unlike print(value,HEX)
const char FLASH hexchars[]="0123456789ABCDEF";
void StringFormatter::printHex(Print * stream,uint16_t value) {
char result[5];
for (int i=3;i>=0;i--) {
result[i]=GETFLASH(hexchars+(value & 0x0F));
value>>=4;
}
result[4]='\0';
stream->print(result);
}

View File

@ -49,7 +49,6 @@ class StringFormatter
static void lcd2(uint8_t display, byte row, const FSH* input...); static void lcd2(uint8_t display, byte row, const FSH* input...);
static void printEscapes(char * input); static void printEscapes(char * input);
static void printEscape( char c); static void printEscape( char c);
static void printHex(Print * stream,uint16_t value);
private: private:
static void send2(Print * serial, const FSH* input,va_list args); static void send2(Print * serial, const FSH* input,va_list args);

View File

@ -26,8 +26,7 @@
#include "MotorDriver.h" #include "MotorDriver.h"
#include "DCCTimer.h" #include "DCCTimer.h"
#include "DIAG.h" #include "DIAG.h"
#include "CommandDistributor.h" #include"CommandDistributor.h"
#include "DCCEXParser.h"
// Virtualised Motor shield multi-track hardware Interface // Virtualised Motor shield multi-track hardware Interface
#define FOR_EACH_TRACK(t) for (byte t=0;t<=lastTrack;t++) #define FOR_EACH_TRACK(t) for (byte t=0;t<=lastTrack;t++)
@ -332,7 +331,6 @@ bool TrackManager::parseJ(Print *stream, int16_t params, int16_t p[])
FOR_EACH_TRACK(t) FOR_EACH_TRACK(t)
streamTrackState(stream,t); streamTrackState(stream,t);
return true; return true;
} }
p[0]-=HASH_KEYWORD_A; // convert A... to 0.... p[0]-=HASH_KEYWORD_A; // convert A... to 0....
@ -367,36 +365,32 @@ void TrackManager::streamTrackState(Print* stream, byte t) {
// null stream means send to commandDistributor for broadcast // null stream means send to commandDistributor for broadcast
if (track[t]==NULL) return; if (track[t]==NULL) return;
auto format=F(""); auto format=F("");
bool pstate = TrackManager::isPowerOn(t);
switch(track[t]->getMode()) { switch(track[t]->getMode()) {
case TRACK_MODE_MAIN: case TRACK_MODE_MAIN:
if (pstate) {format=F("<= %c MAIN ON>\n");} else {format = F("<= %c MAIN OFF>\n");} format=F("<= %c MAIN>\n");
break; break;
#ifndef DISABLE_PROG #ifndef DISABLE_PROG
case TRACK_MODE_PROG: case TRACK_MODE_PROG:
if (pstate) {format=F("<= %c PROG ON>\n");} else {format=F("<= %c PROG OFF>\n");} format=F("<= %c PROG>\n");
break; break;
#endif #endif
case TRACK_MODE_NONE: case TRACK_MODE_NONE:
if (pstate) {format=F("<= %c NONE ON>\n");} else {format=F("<= %c NONE OFF>\n");} format=F("<= %c NONE>\n");
break; break;
case TRACK_MODE_EXT: case TRACK_MODE_EXT:
if (pstate) {format=F("<= %c EXT ON>\n");} else {format=F("<= %c EXT OFF>\n");} format=F("<= %c EXT>\n");
break; break;
case TRACK_MODE_DC: case TRACK_MODE_DC:
if (pstate) {format=F("<= %c DC %d ON>\n");} else {format=F("<= %c DC %d OFF>\n");} format=F("<= %c DC %d>\n");
break; break;
case TRACK_MODE_DCX: case TRACK_MODE_DCX:
if (pstate) {format=F("<= %c DCX %d ON>\n");} else {format=F("<= %c DCX %d OFF>\n");} format=F("<= %c DCX %d>\n");
break; break;
default: default:
break; // unknown, dont care break; // unknown, dont care
} }
if (stream) StringFormatter::send(stream,format,'A'+t,trackDCAddr[t]);
if (stream) StringFormatter::send(stream,format,'A'+t, trackDCAddr[t]); else CommandDistributor::broadcastTrackState(format,'A'+t,trackDCAddr[t]);
else CommandDistributor::broadcastTrackState(format,'A'+t, trackDCAddr[t]);
} }
byte TrackManager::nextCycleTrack=MAX_TRACKS; byte TrackManager::nextCycleTrack=MAX_TRACKS;
@ -430,70 +424,49 @@ std::vector<MotorDriver *>TrackManager::getMainDrivers() {
} }
#endif #endif
void TrackManager::setPower2(bool setProg,bool setJoin, POWERMODE mode) { void TrackManager::setPower2(bool setProg,POWERMODE mode) {
if (!setProg) mainPowerGuess=mode; if (!setProg) mainPowerGuess=mode;
FOR_EACH_TRACK(t) { FOR_EACH_TRACK(t) {
MotorDriver * driver=track[t];
TrackManager::setTrackPower(setProg, setJoin, mode, t); if (!driver) continue;
switch (track[t]->getMode()) {
} case TRACK_MODE_MAIN:
return; if (setProg) break;
} // toggle brake before turning power on - resets overcurrent error
// on the Pololu board if brake is wired to ^D2.
void TrackManager::setTrackPower(bool setProg, bool setJoin, POWERMODE mode, byte thistrack) { // XXX see if we can make this conditional
driver->setBrake(true);
//DIAG(F("SetTrackPower Processing Track %d"), thistrack); driver->setBrake(false); // DCC runs with brake off
MotorDriver * driver=track[thistrack]; driver->setPower(mode);
if (!driver) return; break;
case TRACK_MODE_DC:
switch (track[thistrack]->getMode()) { case TRACK_MODE_DCX:
case TRACK_MODE_MAIN: if (setProg) break;
if (setProg) break; driver->setBrake(true); // DC starts with brake on
// toggle brake before turning power on - resets overcurrent error applyDCSpeed(t); // speed match DCC throttles
// on the Pololu board if brake is wired to ^D2. driver->setPower(mode);
// XXX see if we can make this conditional break;
driver->setBrake(true); case TRACK_MODE_PROG:
driver->setBrake(false); // DCC runs with brake off if (!setProg) break;
driver->setPower(mode); driver->setBrake(true);
break; driver->setBrake(false);
case TRACK_MODE_DC: driver->setPower(mode);
case TRACK_MODE_DCX: break;
//DIAG(F("Processing track - %d setProg %d"), thistrack, setProg); case TRACK_MODE_EXT:
if (setProg || setJoin) break; driver->setBrake(true);
driver->setBrake(true); // DC starts with brake on driver->setBrake(false);
applyDCSpeed(thistrack); // speed match DCC throttles driver->setPower(mode);
driver->setPower(mode); break;
break; case TRACK_MODE_NONE:
case TRACK_MODE_PROG: break;
if (!setProg && !setJoin) 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::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.
// <c MeterName value C/V unit min max res warn>
int maxCurrent=track[0]->raw2mA(track[0]->getRawCurrentTripValue());
StringFormatter::send(stream, F("<c CurrentMAIN %d C Milli 0 %d 1 %d>\n"),
track[0]->raw2mA(track[0]->getCurrentRaw(false)), maxCurrent, maxCurrent);
} }
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();
return POWERMODE::OFF; return POWERMODE::OFF;
} }
@ -565,32 +538,3 @@ bool TrackManager::isPowerOn(byte t) {
return true; return true;
} }
bool TrackManager::isProg(byte t) {
if (track[t]->getMode()==TRACK_MODE_PROG)
return true;
return false;
}
byte TrackManager::returnMode(byte t) {
return (track[t]->getMode());
}
int16_t TrackManager::returnDCAddr(byte t) {
return (trackDCAddr[t]);
}
const char* TrackManager::getModeName(byte Mode) {
//DIAG(F("PowerMode %d"), Mode);
switch (Mode)
{
case 1: return "NONE";
case 2: return "MAIN";
case 4: return "PROG";
case 8: return "DC";
case 16: return "DCX";
case 32: return "EXT";
default: return "----";
}
}

View File

@ -39,10 +39,6 @@ const byte TRACK_NUMBER_5=5, TRACK_NUMBER_F=5;
const byte TRACK_NUMBER_6=6, TRACK_NUMBER_G=6; const byte TRACK_NUMBER_6=6, TRACK_NUMBER_G=6;
const byte TRACK_NUMBER_7=7, TRACK_NUMBER_H=7; const byte TRACK_NUMBER_7=7, TRACK_NUMBER_H=7;
// These constants help EXRAIL macros convert Track Power e.g. SET_POWER(A ON|OFF).
const byte TRACK_POWER_0=0, TRACK_POWER_OFF=0;
const byte TRACK_POWER_1=1, TRACK_POWER_ON=1;
class TrackManager { class TrackManager {
public: public:
static void Setup(const FSH * shieldName, static void Setup(const FSH * shieldName,
@ -64,14 +60,10 @@ class TrackManager {
#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,POWERMODE mode);
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 setMainPower(POWERMODE mode) {setPower2(false,mode);}
static void setProgPower(POWERMODE mode) {setPower2(true,false,mode);} static void setProgPower(POWERMODE mode) {setPower2(true,mode);}
static void setJoinPower(POWERMODE mode) {setPower2(false,true,mode);}
static void setTrackPower(bool setProg, bool setJoin, POWERMODE mode, byte thistrack);
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);
@ -85,14 +77,9 @@ class TrackManager {
static void sampleCurrent(); static void sampleCurrent();
static void reportGauges(Print* stream); static void reportGauges(Print* stream);
static void reportCurrent(Print* stream); static void reportCurrent(Print* stream);
static void reportPowerChange(Print* stream, byte thistrack);
static void reportObsoleteCurrent(Print* stream); static void reportObsoleteCurrent(Print* stream);
static void streamTrackState(Print* stream, byte t); static void streamTrackState(Print* stream, byte t);
static bool isPowerOn(byte t); static bool isPowerOn(byte t);
static bool isProg(byte t);
static byte returnMode(byte t);
static int16_t returnDCAddr(byte t);
static const char* getModeName(byte Mode);
static int16_t joinRelay; static int16_t joinRelay;
static bool progTrackSyncMain; // true when prog track is a siding switched to main static bool progTrackSyncMain; // true when prog track is a siding switched to main

View File

@ -185,7 +185,7 @@ public:
for (Turntable *tto = _firstTurntable; tto != 0; tto = tto->_nextTurntable) for (Turntable *tto = _firstTurntable; tto != 0; tto = tto->_nextTurntable)
if (!tto->isHidden()) { if (!tto->isHidden()) {
gotOne = true; gotOne = true;
StringFormatter::send(stream, F("<I %d %d>\n"), tto->getId(), tto->getPosition()); StringFormatter::send(stream, F("<i %d %d>\n"), tto->getId(), tto->getPosition());
} }
return gotOne; return gotOne;
} }

View File

@ -24,7 +24,6 @@
//#include "IO_TouchKeypad.h // Touch keypad with 16 keys //#include "IO_TouchKeypad.h // Touch keypad with 16 keys
//#include "IO_EXTurntable.h" // Turntable-EX turntable controller //#include "IO_EXTurntable.h" // Turntable-EX turntable controller
//#include "IO_EXFastClock.h" // FastClock driver //#include "IO_EXFastClock.h" // FastClock driver
//#include "IO_PCA9555.h" // 16-bit I/O expander (NXP & Texas Instruments).
//========================================================================== //==========================================================================
// The function halSetup() is invoked from CS if it exists within the build. // The function halSetup() is invoked from CS if it exists within the build.

View File

@ -3,16 +3,7 @@
#include "StringFormatter.h" #include "StringFormatter.h"
#define VERSION "5.1.16" #define VERSION "5.1.11"
// 5.1.16 - Remove I2C address from EXTT_TURNTABLE macro to work with MUX, requires separate HAL macro to create
// 5.1.15 - LCC/Adapter support and Exrail feature-compile-out.
// 5.1.14 - Fixed IFTTPOSITION
// 5.1.13 - Changed turntable broadcast from i to I due to server string conflict
// 5.1.12 - Added Power commands <0 A> & <1 A> etc. and update to <=>
// Added EXRAIL SET_POWER(track, ON/OFF)
// Fixed a problem whereby <1 MAIN> also powered on PROG track
// Added functions to TrackManager.cpp to allow UserAddin code for power display on OLED/LCD
// Added - returnMode(byte t), returnDCAddr(byte t) & getModeName(byte Mode)
// 5.1.11 - STM32F4xx revised I2C clock setup, no correctly sets clock and has fully variable frequency selection // 5.1.11 - STM32F4xx revised I2C clock setup, no correctly sets clock and has fully variable frequency selection
// 5.1.10 - STM32F4xx DCCEXanalogWrite to handle PWM generation for TrackManager DC/DCX // 5.1.10 - STM32F4xx DCCEXanalogWrite to handle PWM generation for TrackManager DC/DCX
// - STM32F4xx DCC 58uS timer now using non-PWM output timers where possible // - STM32F4xx DCC 58uS timer now using non-PWM output timers where possible