diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index e986406..c6ec193 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -343,6 +343,15 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) return; break; + case 'k': // exiting block + case 'K': // entering block + if (params!=2) break; +#ifdef EXRAIL_ACTIVE + // without EXrail, valid block commands are ignored + RMFT2::blockEvent(p[0],p[1],opcode=='K'); +#endif + return; + case 'w': // WRITE CV on MAIN DCC::writeCVByteMain(p[0], p[1], p[2]); return; diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index 30b1b6d..90ba9ce 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -90,6 +90,8 @@ LookList * RMFT2::onDeactivateLookup=NULL; LookList * RMFT2::onRedLookup=NULL; LookList * RMFT2::onAmberLookup=NULL; LookList * RMFT2::onGreenLookup=NULL; +LookList * RMFT2::onBlockEnterLookup=NULL; +LookList * RMFT2::onBlockExitLookup=NULL; #define GET_OPCODE GETFLASH(RMFT2::RouteCode+progCounter) #define GET_OPERAND(n) GETFLASHW(RMFT2::RouteCode+progCounter+1+(n*3)) @@ -153,7 +155,9 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { onRedLookup=LookListLoader(OPCODE_ONRED); onAmberLookup=LookListLoader(OPCODE_ONAMBER); onGreenLookup=LookListLoader(OPCODE_ONGREEN); - + onBlockEnterLookup=LookListLoader(OPCODE_ONBLOCKENTER); + onBlockExitLookup=LookListLoader(OPCODE_ONBLOCKEXIT); + // Second pass startup, define any turnouts or servos, set signals red // add sequences onRoutines to the lookups for (int sigpos=0;;sigpos+=4) { @@ -923,6 +927,8 @@ void RMFT2::loop2() { case OPCODE_ONCLOSE: // Turnout event catchers ignored here case OPCODE_ONTHROW: case OPCODE_ONACTIVATE: // Activate event catchers ignored here + case OPCODE_ONBLOCKENTER: + case OPCODE_ONBLOCKEXIT: case OPCODE_ONDEACTIVATE: case OPCODE_ONRED: case OPCODE_ONAMBER: @@ -1052,17 +1058,29 @@ void RMFT2::activateEvent(int16_t addr, bool activate) { if (activate) handleEvent(F("ACTIVATE"),onActivateLookup,addr); else handleEvent(F("DEACTIVATE"),onDeactivateLookup,addr); } + +void RMFT2::blockEvent(int16_t blockId, int16_t locoid, bool enterBlock) { + RMFT2 * task=enterBlock + ? handleEvent(F("BLOCKENTER"),onBlockEnterLookup,blockId) + : handleEvent(F("BLOCKEXIT"),onBlockExitLookup,blockId); + if (task) { + // set task info from locoid + byte speed=DCC::getThrottleSpeedByte(locoid); + task->speedo=speed & 0x7f; + task->forward=speed >> 7; + } +} -void RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) { +RMFT2 * RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) { int pc= handlers->find(id); - if (pc<0) return; + if (pc<0) return NULL; // Check we dont already have a task running this handler RMFT2 * task=loopTask; while(task) { if (task->onEventStartPosition==pc) { DIAG(F("Recursive ON%S(%d)"),reason, id); - return; + return NULL; } task=task->next; if (task==loopTask) break; @@ -1070,6 +1088,7 @@ void RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) { task=new RMFT2(pc); // new task starts at this instruction task->onEventStartPosition=pc; // flag for recursion detector + return task; } void RMFT2::printMessage2(const FSH * msg) { diff --git a/EXRAIL2.h b/EXRAIL2.h index 323ae57..c984620 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -54,6 +54,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, OPCODE_ENDTASK,OPCODE_ENDEXRAIL, OPCODE_SET_TRACK, OPCODE_ONRED,OPCODE_ONAMBER,OPCODE_ONGREEN, + OPCODE_ONBLOCKENTER,OPCODE_ONBLOCKEXIT, // OPcodes below this point are skip-nesting IF operations // placed here so that they may be skipped as a group @@ -107,6 +108,8 @@ class LookList { static void createNewTask(int route, uint16_t cab); static void turnoutEvent(int16_t id, bool closed); static void activateEvent(int16_t addr, bool active); + static void blockEvent(int16_t blockId, int16_t locoid, bool enterBlock); + static const int16_t SERVO_SIGNAL_FLAG=0x4000; static const int16_t ACTIVE_HIGH_SIGNAL_FLAG=0x2000; static const int16_t DCC_SIGNAL_FLAG=0x1000; @@ -136,7 +139,7 @@ private: 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 * handleEvent(const FSH* reason,LookList* handlers, int16_t id); static RMFT2 * loopTask; static RMFT2 * pausingTask; void delayMe(long millisecs); @@ -161,6 +164,8 @@ private: static LookList * onRedLookup; static LookList * onAmberLookup; static LookList * onGreenLookup; + static LookList * onBlockEnterLookup; + static LookList * onBlockExitLookup; // Local variables - exist for each instance/task diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index 0211e22..eb55a68 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -82,6 +82,8 @@ #undef ONACTIVATE #undef ONACTIVATEL #undef ONAMBER +#undef ONBLOCKENTER +#undef ONBLOCKEXIT #undef ONDEACTIVATE #undef ONDEACTIVATEL #undef ONCLOSE @@ -192,6 +194,8 @@ #define ONACTIVATE(addr,subaddr) #define ONACTIVATEL(linear) #define ONAMBER(signal_id) +#define ONBLOCKENTER(blockid) +#define ONBLOCKEXIT(blockid) #define ONDEACTIVATE(addr,subaddr) #define ONDEACTIVATEL(linear) #define ONCLOSE(turnout_id) diff --git a/EXRAILMacros.h b/EXRAILMacros.h index d5424c6..cb787d4 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -271,6 +271,8 @@ const FLASH int16_t RMFT2::SignalDefinitions[] = { #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 ONBLOCKENTER(blockid) OPCODE_ONBLOCKENTER,V(blockid), +#define ONBLOCKEXIT(blockid) OPCODE_ONBLOCKEXIT,V(blockid), #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), diff --git a/LCN.cpp b/LCN.cpp index efb49ff..361debf 100644 --- a/LCN.cpp +++ b/LCN.cpp @@ -16,13 +16,17 @@ * You should have received a copy of the GNU General Public License * along with CommandStation. If not, see . */ - +#include "defines.h" #include "LCN.h" #include "DIAG.h" #include "Turnouts.h" #include "Sensors.h" +#include "EXRAIL2.h" int LCN::id = 0; +int LCN::id1 = 0; +int LCN::id2 = 0; + Stream * LCN::stream=NULL; bool LCN::firstLoop=true; @@ -46,6 +50,12 @@ void LCN::loop() { if (ch >= 0 && ch <= '9') { // accumulate id value id = 10 * id + ch - '0'; } + else if (ch == ',') { + // push stack for new number + id2=id1; + id1=id; + id=0; + } else if (ch == 't' || ch == 'T') { // Turnout opcodes if (Diag::LCN) DIAG(F("LCN IN %d%c"),id,(char)ch); if (!Turnout::exists(id)) LCNTurnout::create(id); @@ -64,6 +74,16 @@ void LCN::loop() { ss->setState(ch == 'S'); id = 0; } + else if (ch == 'k' || ch == 'K') { + // block enter id1 by loco id + if (Diag::LCN) DIAG(F("LCN IN %d,%d%c"),id1,id,(char)ch); + +#ifdef EXRAIL_ACTIVE + // without EXrail, valid block commands are ignored + RMFT2::blockEvent(id1,id,ch=='K'); +#endif + id=0; + } else id = 0; // ignore any other garbage from LCN } } diff --git a/LCN.h b/LCN.h index 176d9a2..bc00c66 100644 --- a/LCN.h +++ b/LCN.h @@ -31,6 +31,8 @@ class LCN { static bool firstLoop; static Stream * stream; static int id; + static int id1; + static int id2; }; #endif