1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-26 17:46:14 +01:00

UNTESTED ONRED/ONAMBER/ONGREEN

with genericl code tidy for other ON handlers.
This commit is contained in:
Asbelos 2022-06-17 11:48:37 +01:00
parent 044b467085
commit d0e71875e0
4 changed files with 76 additions and 99 deletions

View File

@ -87,6 +87,9 @@ LookList * RMFT2::onThrowLookup=NULL;
LookList * RMFT2::onCloseLookup=NULL; LookList * RMFT2::onCloseLookup=NULL;
LookList * RMFT2::onActivateLookup=NULL; LookList * RMFT2::onActivateLookup=NULL;
LookList * RMFT2::onDeactivateLookup=NULL; LookList * RMFT2::onDeactivateLookup=NULL;
LookList * RMFT2::onRedLookup=NULL;
LookList * RMFT2::onAmberLookup=NULL;
LookList * RMFT2::onGreenLookup=NULL;
#define GET_OPCODE GETFLASH(RMFT2::RouteCode+progCounter) #define GET_OPCODE GETFLASH(RMFT2::RouteCode+progCounter)
#define GET_OPERAND(n) GETFLASHW(RMFT2::RouteCode+progCounter+1+(n*3)) #define GET_OPERAND(n) GETFLASHW(RMFT2::RouteCode+progCounter+1+(n*3))
@ -116,56 +119,40 @@ int16_t LookList::find(int16_t value) {
return -1; return -1;
} }
/* static */ void RMFT2::begin() { LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
DCCEXParser::setRMFTFilter(RMFT2::ComandFilter);
for (int f=0;f<MAX_FLAGS;f++) flags[f]=0;
int progCounter; int progCounter;
int16_t count=0;
// counters to create lookup arrays // find size for list
int sequenceCount=0; // to allow for seq 0 at start
int onThrowCount=0;
int onCloseCount=0;
int onActivateCount=0;
int onDeactivateCount=0;
// first pass count sizes for fast lookup arrays
for (progCounter=0;; SKIPOP) { for (progCounter=0;; SKIPOP) {
byte opcode=GET_OPCODE; byte opcode=GET_OPCODE;
if (opcode==OPCODE_ENDEXRAIL) break; if (opcode==OPCODE_ENDEXRAIL) break;
switch (opcode) { if (opcode==op1 || opcode==op2 || opcode==op3) count++;
case OPCODE_ROUTE:
case OPCODE_AUTOMATION:
case OPCODE_SEQUENCE:
sequenceCount++;
break;
case OPCODE_ONTHROW:
onThrowCount++;
break;
case OPCODE_ONCLOSE:
onCloseCount++;
break;
case OPCODE_ONACTIVATE:
onActivateCount++;
break;
case OPCODE_ONDEACTIVATE:
onDeactivateCount++;
break;
default: // Ignore
break;
}
} }
// create list
LookList* list=new LookList(count);
if (count==0) return list;
for (progCounter=0;; SKIPOP) {
byte opcode=GET_OPCODE;
if (opcode==OPCODE_ENDEXRAIL) break;
if (opcode==op1 || opcode==op2 || opcode==op3) list->add(GET_OPERAND(0),progCounter);
}
return list;
}
/* static */ void RMFT2::begin() {
DCCEXParser::setRMFTFilter(RMFT2::ComandFilter);
for (int f=0;f<MAX_FLAGS;f++) flags[f]=0;
// create lookups // create lookups
sequenceLookup=new LookList(sequenceCount); sequenceLookup=LookListLoader(OPCODE_ROUTE, OPCODE_AUTOMATION,OPCODE_SEQUENCE);
onThrowLookup=new LookList(onThrowCount); onThrowLookup=LookListLoader(OPCODE_ONTHROW);
onCloseLookup=new LookList(onCloseCount); onCloseLookup=LookListLoader(OPCODE_ONCLOSE);
onActivateLookup=new LookList(onActivateCount); onActivateLookup=LookListLoader(OPCODE_ONACTIVATE);
onDeactivateLookup=new LookList(onDeactivateCount); onDeactivateLookup=LookListLoader(OPCODE_ONDEACTIVATE);
onRedLookup=LookListLoader(OPCODE_ONRED);
onAmberLookup=LookListLoader(OPCODE_ONAMBER);
onGreenLookup=LookListLoader(OPCODE_ONGREEN);
// 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
@ -175,6 +162,7 @@ int16_t LookList::find(int16_t value) {
doSignal(sigid & SIGNAL_ID_MASK, SIGNAL_RED); doSignal(sigid & SIGNAL_ID_MASK, SIGNAL_RED);
} }
int progCounter;
for (progCounter=0;; SKIPOP){ for (progCounter=0;; SKIPOP){
byte opcode=GET_OPCODE; byte opcode=GET_OPCODE;
if (opcode==OPCODE_ENDEXRAIL) break; if (opcode==OPCODE_ENDEXRAIL) break;
@ -216,31 +204,10 @@ int16_t LookList::find(int16_t value) {
break; break;
} }
case OPCODE_ROUTE:
case OPCODE_AUTOMATION:
case OPCODE_SEQUENCE:
sequenceLookup->add(operand,progCounter);
break;
case OPCODE_ONTHROW:
onThrowLookup->add(operand,progCounter);
break;
case OPCODE_ONCLOSE:
onCloseLookup->add(operand,progCounter);
break;
case OPCODE_ONACTIVATE:
onActivateLookup->add(operand,progCounter);
break;
case OPCODE_ONDEACTIVATE:
onDeactivateLookup->add(operand,progCounter);
break;
case OPCODE_AUTOSTART: case OPCODE_AUTOSTART:
// automatically create a task from here at startup. // automatically create a task from here at startup.
new RMFT2(progCounter); // but we will do one at 0 anyway by default.
if (progCounter>0) new RMFT2(progCounter);
break; break;
default: // Ignore default: // Ignore
@ -249,9 +216,7 @@ int16_t LookList::find(int16_t value) {
} }
SKIPOP; // include ENDROUTES opcode SKIPOP; // include ENDROUTES opcode
DIAG(F("EXRAIL %db, fl=%d seq=%d, onT=%d, onC=%d"), DIAG(F("EXRAIL %db, fl=%d"),progCounter,MAX_FLAGS);
progCounter,MAX_FLAGS,
sequenceCount, onThrowCount, onCloseCount);
new RMFT2(0); // add the startup route new RMFT2(0); // add the startup route
} }
@ -461,7 +426,7 @@ RMFT2::RMFT2(int progCtr) {
invert=false; invert=false;
timeoutFlag=false; timeoutFlag=false;
stackDepth=0; stackDepth=0;
onTurnoutId=-1; // Not handling an ONTHROW/ONCLOSE onEventStartPosition=-1; // Not handling an ONxxx
// chain into ring of RMFTs // chain into ring of RMFTs
if (loopTask==NULL) { if (loopTask==NULL) {
@ -1013,6 +978,13 @@ int16_t RMFT2::getSignalSlot(VPIN id) {
} }
/* static */ void RMFT2::doSignal(VPIN id,char rag) { /* static */ void RMFT2::doSignal(VPIN id,char rag) {
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.
// Thjis will work even without a signal definition.
if (rag==SIGNAL_RED) handleEvent(F("RED"),onRedLookup,id);
else if (rag==SIGNAL_GREEN) handleEvent(F("GREEN"), onGreenLookup,id);
else handleEvent(F("AMBER"), onAmberLookup,id);
int16_t sigslot=getSignalSlot(id); int16_t sigslot=getSignalSlot(id);
if (sigslot<0) return; if (sigslot<0) return;
@ -1027,6 +999,7 @@ int16_t RMFT2::getSignalSlot(VPIN id) {
VPIN greenpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+3); VPIN greenpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+3);
if (diag) DIAG(F("signal %d %d %d %d"),sigid,redpin,amberpin,greenpin); if (diag) DIAG(F("signal %d %d %d %d"),sigid,redpin,amberpin,greenpin);
if (sigid & SERVO_SIGNAL_FLAG) { if (sigid & SERVO_SIGNAL_FLAG) {
// A servo signal, the pin numbers are actually servo positions // A servo signal, the pin numbers are actually servo positions
// Note, setting a signal to a zero position has no effect. // Note, setting a signal to a zero position has no effect.
@ -1059,46 +1032,36 @@ int16_t RMFT2::getSignalSlot(VPIN id) {
void RMFT2::turnoutEvent(int16_t turnoutId, bool closed) { void RMFT2::turnoutEvent(int16_t turnoutId, bool closed) {
// Hunt for an ONTHROW/ONCLOSE for this turnout // Hunt for an ONTHROW/ONCLOSE for this turnout
int pc= (closed?onCloseLookup:onThrowLookup)->find(turnoutId); if (closed) handleEvent(F("CLOSE"),onCloseLookup,turnoutId);
if (pc<0) return; else handleEvent(F("THROW"),onThrowLookup,turnoutId);
// Check we dont already have a task running this turnout
RMFT2 * task=loopTask;
while(task) {
if (task->onTurnoutId==turnoutId) {
DIAG(F("Recursive ONTHROW/ONCLOSE for Turnout %d"),turnoutId);
return;
}
task=task->next;
if (task==loopTask) break;
}
task=new RMFT2(pc); // new task starts at this instruction
task->onTurnoutId=turnoutId; // flag for recursion detector
} }
void RMFT2::activateEvent(int16_t addr, bool activate) { void RMFT2::activateEvent(int16_t addr, bool activate) {
// Hunt for an ONACTIVATE/ONDEACTIVATE for this accessory // Hunt for an ONACTIVATE/ONDEACTIVATE for this accessory
int pc= (activate?onActivateLookup:onDeactivateLookup)->find(addr); if (activate) handleEvent(F("ACTIVATE"),onActivateLookup,addr);
else handleEvent(F("DEACTIVATE"),onDeactivateLookup,addr);
}
void RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) {
int pc= handlers->find(id);
if (pc<0) return; if (pc<0) return;
// Check we dont already have a task running this address // Check we dont already have a task running this handler
RMFT2 * task=loopTask; RMFT2 * task=loopTask;
while(task) { while(task) {
if (task->onActivateAddr==addr) { if (task->onEventStartPosition==pc) {
DIAG(F("Recursive ON(DE)ACTIVATE for %d"),addr); DIAG(F("Recursive ON%S(%d)"),reason, id);
return; return;
} }
task=task->next; task=task->next;
if (task==loopTask) break; if (task==loopTask) break;
} }
task->onActivateAddr=addr; // flag for recursion detector
task=new RMFT2(pc); // new task starts at this instruction task=new RMFT2(pc); // new task starts at this instruction
task->onEventStartPosition=pc; // flag for recursion detector
} }
void RMFT2::printMessage2(const FSH * msg) { void RMFT2::printMessage2(const FSH * msg) {
DIAG(F("EXRAIL(%d) %S"),loco,msg); DIAG(F("EXRAIL(%d) %S"),loco,msg);
} }

View File

@ -53,6 +53,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
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_TRACK,
OPCODE_ONRED,OPCODE_ONAMBER,OPCODE_ONGREEN,
// OPcodes below this point are skip-nesting IF operations // OPcodes below this point are skip-nesting IF operations
// placed here so that they may be skipped as a group // placed here so that they may be skipped as a group
@ -63,7 +64,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
OPCODE_IFTIMEOUT, OPCODE_IFTIMEOUT,
OPCODE_IF,OPCODE_IFNOT, OPCODE_IF,OPCODE_IFNOT,
OPCODE_IFRANDOM,OPCODE_IFRESERVE, OPCODE_IFRANDOM,OPCODE_IFRESERVE,
OPCODE_IFCLOSED, OPCODE_IFTHROWN OPCODE_IFCLOSED,OPCODE_IFTHROWN
}; };
@ -132,6 +133,9 @@ private:
static bool isSignal(VPIN id,char rag); static bool isSignal(VPIN id,char rag);
static int16_t getSignalSlot(VPIN id); static int16_t getSignalSlot(VPIN id);
static void setTurnoutHiddenState(Turnout * t); static void setTurnoutHiddenState(Turnout * t);
static LookList* LookListLoader(OPCODE op1,
OPCODE op2=OPCODE_ENDEXRAIL,OPCODE op3=OPCODE_ENDEXRAIL);
static void handleEvent(const FSH* reason,LookList* handlers, int16_t id);
static RMFT2 * loopTask; static RMFT2 * loopTask;
static RMFT2 * pausingTask; static RMFT2 * pausingTask;
void delayMe(long millisecs); void delayMe(long millisecs);
@ -144,7 +148,6 @@ private:
void printMessage(uint16_t id); // Built by RMFTMacros.h void printMessage(uint16_t id); // Built by RMFTMacros.h
void printMessage2(const FSH * msg); void printMessage2(const FSH * msg);
static bool diag; static bool diag;
static const FLASH byte RouteCode[]; static const FLASH byte RouteCode[];
static const FLASH int16_t SignalDefinitions[]; static const FLASH int16_t SignalDefinitions[];
@ -154,6 +157,9 @@ private:
static LookList * onCloseLookup; static LookList * onCloseLookup;
static LookList * onActivateLookup; static LookList * onActivateLookup;
static LookList * onDeactivateLookup; static LookList * onDeactivateLookup;
static LookList * onRedLookup;
static LookList * onAmberLookup;
static LookList * onGreenLookup;
// Local variables - exist for each instance/task // Local variables - exist for each instance/task
@ -172,8 +178,7 @@ private:
bool forward; bool forward;
bool invert; bool invert;
byte speedo; byte speedo;
int16_t onTurnoutId; int onEventStartPosition;
int16_t onActivateAddr;
byte stackDepth; byte stackDepth;
int callStack[MAX_STACK_DEPTH]; int callStack[MAX_STACK_DEPTH];
}; };

View File

@ -79,9 +79,12 @@
#undef LCN #undef LCN
#undef ONACTIVATE #undef ONACTIVATE
#undef ONACTIVATEL #undef ONACTIVATEL
#undef ONAMBER
#undef ONDEACTIVATE #undef ONDEACTIVATE
#undef ONDEACTIVATEL #undef ONDEACTIVATEL
#undef ONCLOSE #undef ONCLOSE
#undef ONGREEN
#undef ONRED
#undef ONTHROW #undef ONTHROW
#undef PARSE #undef PARSE
#undef PAUSE #undef PAUSE
@ -183,9 +186,12 @@
#define LCN(msg) #define LCN(msg)
#define ONACTIVATE(addr,subaddr) #define ONACTIVATE(addr,subaddr)
#define ONACTIVATEL(linear) #define ONACTIVATEL(linear)
#define ONAMBER(signal_id)
#define ONDEACTIVATE(addr,subaddr) #define ONDEACTIVATE(addr,subaddr)
#define ONDEACTIVATEL(linear) #define ONDEACTIVATEL(linear)
#define ONCLOSE(turnout_id) #define ONCLOSE(turnout_id)
#define ONGREEN(signal_id)
#define ONRED(signal_id)
#define ONTHROW(turnout_id) #define ONTHROW(turnout_id)
#define PAUSE #define PAUSE
#define PIN_TURNOUT(id,pin,description...) #define PIN_TURNOUT(id,pin,description...)

View File

@ -263,9 +263,12 @@ const FLASH int16_t RMFT2::SignalDefinitions[] = {
#define LCN(msg) PRINT(msg) #define LCN(msg) PRINT(msg)
#define ONACTIVATE(addr,subaddr) OPCODE_ONACTIVATE,V(addr<<2|subaddr), #define ONACTIVATE(addr,subaddr) OPCODE_ONACTIVATE,V(addr<<2|subaddr),
#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 ONCLOSE(turnout_id) OPCODE_ONCLOSE,V(turnout_id), #define ONCLOSE(turnout_id) OPCODE_ONCLOSE,V(turnout_id),
#define ONDEACTIVATE(addr,subaddr) OPCODE_ONDEACTIVATE,V(addr<<2|subaddr), #define ONDEACTIVATE(addr,subaddr) OPCODE_ONDEACTIVATE,V(addr<<2|subaddr),
#define ONDEACTIVATEL(linear) OPCODE_ONDEACTIVATE,V(linear+3), #define ONDEACTIVATEL(linear) OPCODE_ONDEACTIVATE,V(linear+3),
#define ONGREEN(signal_id) OPCODE_ONGREEN,V(signal_id),
#define ONRED(signal_id) OPCODE_ONRED,V(signal_id),
#define ONTHROW(turnout_id) OPCODE_ONTHROW,V(turnout_id), #define ONTHROW(turnout_id) OPCODE_ONTHROW,V(turnout_id),
#define PAUSE OPCODE_PAUSE,0,0, #define PAUSE OPCODE_PAUSE,0,0,
#define PIN_TURNOUT(id,pin,description...) OPCODE_PINTURNOUT,V(id),OPCODE_PAD,V(pin), #define PIN_TURNOUT(id,pin,description...) OPCODE_PINTURNOUT,V(id),OPCODE_PAD,V(pin),