diff --git a/RMFT2.cpp b/RMFT2.cpp index e302baf..92648da 100644 --- a/RMFT2.cpp +++ b/RMFT2.cpp @@ -77,7 +77,6 @@ RMFT2 * RMFT2::pausingTask=NULL; // Task causing a PAUSE. byte RMFT2::flags[MAX_FLAGS]; LookList * RMFT2::sequenceLookup=NULL; -LookList * RMFT2::signalLookup=NULL; LookList * RMFT2::onThrowLookup=NULL; LookList * RMFT2::onCloseLookup=NULL; LookList * RMFT2::onActivateLookup=NULL; @@ -122,17 +121,12 @@ LookList * RMFT2::onDeactivateLookup=NULL; int onCloseCount=0; int onActivateCount=0; int onDeactivateCount=0; - int signalCount=0; // first pass count sizes for fast lookup arrays for (progCounter=0;; SKIPOP) { byte opcode=GET_OPCODE; if (opcode==OPCODE_ENDEXRAIL) break; - switch (opcode) { - case OPCODE_SIGNAL: - signalCount++; - break; - + switch (opcode) { case OPCODE_ROUTE: case OPCODE_AUTOMATION: case OPCODE_SEQUENCE: @@ -162,14 +156,23 @@ LookList * RMFT2::onDeactivateLookup=NULL; // create lookups sequenceLookup=new LookList(sequenceCount); - signalLookup=new LookList(signalCount); onThrowLookup=new LookList(onThrowCount); onCloseLookup=new LookList(onCloseCount); onActivateLookup=new LookList(onActivateCount); onDeactivateLookup=new LookList(onDeactivateCount); // Second pass startup, define any turnouts or servos, set signals red - // add signals, sequences onRoutines to the lookups + // add sequences onRoutines to the lookups + for (int sigpos=0;;sigpos+=3) { + VPIN redpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos); + if (redpin==0) break; // end of signal list + VPIN amberpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+1); + VPIN greenpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+2); + IODevice::write(redpin,true); + if (amberpin) IODevice::write(amberpin,false); + IODevice::write(greenpin,false); + } + for (progCounter=0;; SKIPOP){ byte opcode=GET_OPCODE; if (opcode==OPCODE_ENDEXRAIL) break; @@ -186,18 +189,6 @@ LookList * RMFT2::onDeactivateLookup=NULL; break; } - - case OPCODE_SIGNAL: { - VPIN red=operand; - VPIN amber=GET_OPERAND(1); - VPIN green=GET_OPERAND(2); - IODevice::write(red,true); - if (amber) IODevice::write(amber,false); - IODevice::write(green,false); - signalLookup->add(red,progCounter); - break; - } - case OPCODE_TURNOUT: { VPIN id=operand; int addr=GET_OPERAND(1); @@ -256,9 +247,9 @@ LookList * RMFT2::onDeactivateLookup=NULL; } SKIPOP; // include ENDROUTES opcode - DIAG(F("EXRAIL %db, fl=%d seq=%d, sig=%d, onT=%d, onC=%d"), + DIAG(F("EXRAIL %db, fl=%d seq=%d, onT=%d, onC=%d"), progCounter,MAX_FLAGS, - sequenceCount, signalCount, onThrowCount, onCloseCount); + sequenceCount, onThrowCount, onCloseCount); new RMFT2(0); // add the startup route } @@ -871,7 +862,6 @@ void RMFT2::loop2() { case OPCODE_AUTOSTART: // Handled only during begin process case OPCODE_PAD: // Just a padding for previous opcode needing >1 operad byte. - case OPCODE_SIGNAL: // Signal definition ignore at run time case OPCODE_TURNOUT: // Turnout definition ignored at runtime case OPCODE_SERVOTURNOUT: // Turnout definition ignored at runtime case OPCODE_PINTURNOUT: // Turnout definition ignored at runtime @@ -913,19 +903,27 @@ void RMFT2::kill(const FSH * reason, int operand) { } /* static */ void RMFT2::doSignal(VPIN id,bool red, bool amber, bool green) { - // CAUTION: hides class member progCounter - int progCounter=signalLookup->find(id); - if (progCounter<0) return; - VPIN redpin=GET_OPERAND(0); - if (redpin!=id) return; // something wrong in lookup - VPIN amberpin=GET_OPERAND(1); - VPIN greenpin=GET_OPERAND(2); - // If amberpin is zero, synthesise amber from red+green - IODevice::write(redpin,red || (amber && (amberpin==0))); - if (amberpin) IODevice::write(amberpin,amber); - if (greenpin) IODevice::write(greenpin,green || (amber && (amberpin==0))); + //if (diag) DIAG(F(" dosignal %d"),id); + for (int sigpos=0;;sigpos+=3) { + VPIN redpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos); + //if (diag) DIAG(F("red=%d"),redpin); + if (redpin==0) { + DIAG(F("EXRAIL Signal %d not defined"), id); + return; // signal not found + } + if (redpin==id) { + VPIN amberpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+1); + VPIN greenpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+2); + //if (diag) DIAG(F("signal %d %d %d"),redpin,amberpin,greenpin); + // If amberpin is zero, synthesise amber from red+green + IODevice::write(redpin,red || (amber && (amberpin==0))); + if (amberpin) IODevice::write(amberpin,amber); + if (greenpin) IODevice::write(greenpin,green || (amber && (amberpin==0))); + return; + } } - +} + void RMFT2::turnoutEvent(int16_t turnoutId, bool closed) { // Hunt for an ONTHROW/ONCLOSE for this turnout int pc= (closed?onCloseLookup:onThrowLookup)->find(turnoutId); diff --git a/RMFT2.h b/RMFT2.h index 821fb7a..14704d0 100644 --- a/RMFT2.h +++ b/RMFT2.h @@ -22,7 +22,7 @@ #include "IODevice.h" // The following are the operation codes (or instructions) for a kind of virtual machine. -// Each instruction is normally 2 bytes long with an operation code followed by a parameter. +// Each instruction is normally 3 bytes long with an operation code followed by a parameter. // In cases where more than one parameter is required, the first parameter is followed by one // or more OPCODE_PAD instructions with the subsequent parameters. This wastes a byte but makes // searching easier as a parameter can never be confused with an opcode. @@ -53,9 +53,11 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, // Flag bits for status of hardware and TPL - static const byte SECTION_FLAG = 0x01; - static const byte LATCH_FLAG = 0x02; - static const byte TASK_FLAG = 0x04; + static const byte SECTION_FLAG = 0x80; + static const byte LATCH_FLAG = 0x40; + static const byte TASK_FLAG = 0x20; + static const byte SPARE_FLAG = 0x10; + static const byte COUNTER_MASK= 0x0F; static const byte MAX_STACK_DEPTH=4; @@ -95,7 +97,7 @@ private: static bool parseSlash(Print * stream, byte & paramCount, int16_t p[]) ; static void streamFlags(Print* stream); static void setFlag(VPIN id,byte onMask, byte OffMask=0); - static bool getFlag(VPIN id,byte mask); + static bool getFlag(VPIN id,byte mask); static int16_t progtrackLocoId; static void doSignal(VPIN id,bool red, bool amber, bool green); static void emitRouteDescription(Print * stream, char type, int id, const FSH * description); @@ -116,9 +118,9 @@ private: static bool diag; static const FLASH byte RouteCode[]; + static const FLASH int16_t SignalDefinitions[]; static byte flags[MAX_FLAGS]; static LookList * sequenceLookup; - static LookList * signalLookup; static LookList * onThrowLookup; static LookList * onCloseLookup; static LookList * onActivateLookup; diff --git a/RMFTMacros.h b/RMFTMacros.h index cc75af3..c4130ff 100644 --- a/RMFTMacros.h +++ b/RMFTMacros.h @@ -140,11 +140,18 @@ const FSH * RMFT2::getRosterFunctions(int16_t cabid) { } } +// Pass 8 Signal definitions +#include "RMFT2MacroReset.h" +#undef SIGNAL +#define SIGNAL(redpin,amberpin,greenpin) redpin,amberpin,greenpin, +const FLASH int16_t RMFT2::SignalDefinitions[] = { + #include "myAutomation.h" + 0,0,0 }; + // Last Pass : create main routes table // Only undef the macros, not dummy them. #define RMFT2_UNDEF_ONLY #include "RMFT2MacroReset.h" - // Define internal helper macros. // Everything we generate here has to be compile-time evaluated to // a constant. @@ -227,7 +234,7 @@ const FSH * RMFT2::getRosterFunctions(int16_t cabid) { #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 SETLOCO(loco) OPCODE_SETLOCO,V(loco), -#define SIGNAL(redpin,amberpin,greenpin) OPCODE_SIGNAL,V(redpin),OPCODE_PAD,V(amberpin),OPCODE_PAD,V(greenpin), +#define SIGNAL(redpin,amberpin,greenpin) #define SPEED(speed) OPCODE_SPEED,V(speed), #define START(route) OPCODE_START,V(route), #define STOP OPCODE_SPEED,V(0),