diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index 243768b..a3c065d 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -87,6 +87,9 @@ LookList * RMFT2::onThrowLookup=NULL; LookList * RMFT2::onCloseLookup=NULL; LookList * RMFT2::onActivateLookup=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_OPERAND(n) GETFLASHW(RMFT2::RouteCode+progCounter+1+(n*3)) @@ -116,56 +119,40 @@ int16_t LookList::find(int16_t value) { return -1; } -/* static */ void RMFT2::begin() { - DCCEXParser::setRMFTFilter(RMFT2::ComandFilter); - for (int f=0;fadd(GET_OPERAND(0),progCounter); + } + return list; +} + +/* static */ void RMFT2::begin() { + DCCEXParser::setRMFTFilter(RMFT2::ComandFilter); + for (int f=0;fadd(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: // 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; default: // Ignore @@ -249,9 +216,7 @@ int16_t LookList::find(int16_t value) { } SKIPOP; // include ENDROUTES opcode - DIAG(F("EXRAIL %db, fl=%d seq=%d, onT=%d, onC=%d"), - progCounter,MAX_FLAGS, - sequenceCount, onThrowCount, onCloseCount); + DIAG(F("EXRAIL %db, fl=%d"),progCounter,MAX_FLAGS); new RMFT2(0); // add the startup route } @@ -461,7 +426,7 @@ RMFT2::RMFT2(int progCtr) { invert=false; timeoutFlag=false; stackDepth=0; - onTurnoutId=-1; // Not handling an ONTHROW/ONCLOSE + onEventStartPosition=-1; // Not handling an ONxxx // chain into ring of RMFTs if (loopTask==NULL) { @@ -1013,6 +978,13 @@ int16_t RMFT2::getSignalSlot(VPIN id) { } /* static */ void RMFT2::doSignal(VPIN id,char 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); if (sigslot<0) return; @@ -1027,6 +999,7 @@ int16_t RMFT2::getSignalSlot(VPIN id) { VPIN greenpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+3); if (diag) DIAG(F("signal %d %d %d %d"),sigid,redpin,amberpin,greenpin); + if (sigid & SERVO_SIGNAL_FLAG) { // A servo signal, the pin numbers are actually servo positions // 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) { // Hunt for an ONTHROW/ONCLOSE for this turnout - int pc= (closed?onCloseLookup:onThrowLookup)->find(turnoutId); - if (pc<0) return; - - // 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 + if (closed) handleEvent(F("CLOSE"),onCloseLookup,turnoutId); + else handleEvent(F("THROW"),onThrowLookup,turnoutId); } + void RMFT2::activateEvent(int16_t addr, bool activate) { // 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; - // Check we dont already have a task running this address + // Check we dont already have a task running this handler RMFT2 * task=loopTask; while(task) { - if (task->onActivateAddr==addr) { - DIAG(F("Recursive ON(DE)ACTIVATE for %d"),addr); + if (task->onEventStartPosition==pc) { + DIAG(F("Recursive ON%S(%d)"),reason, id); return; } task=task->next; if (task==loopTask) break; } - task->onActivateAddr=addr; // flag for recursion detector task=new RMFT2(pc); // new task starts at this instruction + task->onEventStartPosition=pc; // flag for recursion detector } void RMFT2::printMessage2(const FSH * msg) { DIAG(F("EXRAIL(%d) %S"),loco,msg); } - - diff --git a/EXRAIL2.h b/EXRAIL2.h index ba7facd..6bbae23 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -53,6 +53,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, OPCODE_ROUTE,OPCODE_AUTOMATION,OPCODE_SEQUENCE, OPCODE_ENDTASK,OPCODE_ENDEXRAIL, OPCODE_SET_TRACK, + OPCODE_ONRED,OPCODE_ONAMBER,OPCODE_ONGREEN, // OPcodes below this point are skip-nesting IF operations // 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_IF,OPCODE_IFNOT, 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 int16_t getSignalSlot(VPIN id); 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 * pausingTask; void delayMe(long millisecs); @@ -144,7 +148,6 @@ private: void printMessage(uint16_t id); // Built by RMFTMacros.h void printMessage2(const FSH * msg); - static bool diag; static const FLASH byte RouteCode[]; static const FLASH int16_t SignalDefinitions[]; @@ -154,7 +157,10 @@ private: static LookList * onCloseLookup; static LookList * onActivateLookup; static LookList * onDeactivateLookup; - + static LookList * onRedLookup; + static LookList * onAmberLookup; + static LookList * onGreenLookup; + // Local variables - exist for each instance/task RMFT2 *next; // loop chain @@ -172,8 +178,7 @@ private: bool forward; bool invert; byte speedo; - int16_t onTurnoutId; - int16_t onActivateAddr; + int onEventStartPosition; byte stackDepth; int callStack[MAX_STACK_DEPTH]; }; diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index bdd6682..f5b7603 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -79,9 +79,12 @@ #undef LCN #undef ONACTIVATE #undef ONACTIVATEL +#undef ONAMBER #undef ONDEACTIVATE #undef ONDEACTIVATEL #undef ONCLOSE +#undef ONGREEN +#undef ONRED #undef ONTHROW #undef PARSE #undef PAUSE @@ -183,9 +186,12 @@ #define LCN(msg) #define ONACTIVATE(addr,subaddr) #define ONACTIVATEL(linear) +#define ONAMBER(signal_id) #define ONDEACTIVATE(addr,subaddr) #define ONDEACTIVATEL(linear) #define ONCLOSE(turnout_id) +#define ONGREEN(signal_id) +#define ONRED(signal_id) #define ONTHROW(turnout_id) #define PAUSE #define PIN_TURNOUT(id,pin,description...) diff --git a/EXRAILMacros.h b/EXRAILMacros.h index e953936..5354226 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -263,9 +263,12 @@ const FLASH int16_t RMFT2::SignalDefinitions[] = { #define LCN(msg) PRINT(msg) #define ONACTIVATE(addr,subaddr) OPCODE_ONACTIVATE,V(addr<<2|subaddr), #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 ONDEACTIVATE(addr,subaddr) OPCODE_ONDEACTIVATE,V(addr<<2|subaddr), #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 PAUSE OPCODE_PAUSE,0,0, #define PIN_TURNOUT(id,pin,description...) OPCODE_PINTURNOUT,V(id),OPCODE_PAD,V(pin),