From 9d5781a87ce1c7283722944c27228db93c2f514f Mon Sep 17 00:00:00 2001 From: Asbelos Date: Fri, 3 Sep 2021 21:33:53 +0100 Subject: [PATCH 1/7] Signal pin corrections --- RMFT2.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RMFT2.cpp b/RMFT2.cpp index 0d7d133..8c22b43 100644 --- a/RMFT2.cpp +++ b/RMFT2.cpp @@ -674,14 +674,14 @@ void RMFT2::kill(const FSH * reason, int operand) { byte opcode=GET_OPCODE; if (opcode==OPCODE_ENDEXRAIL) return; if (opcode!=OPCODE_SIGNAL) continue; - byte redpin=GET_OPERAND(1); + byte redpin=GET_OPERAND(0); if (redpin!=id)continue; - byte amberpin=GET_OPERAND(2); - byte greenpin=GET_OPERAND(3); + byte amberpin=GET_OPERAND(1); + byte 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(amberpin,green || (amber && (amberpin==0))); + if (greenpin) IODevice::write(greenpin,green || (amber && (amberpin==0))); return; } } From 99222bd37f5533c0128efae06a7abd9ebebfb667 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Fri, 3 Sep 2021 22:39:13 +0100 Subject: [PATCH 2/7] Turnout recursion test --- RMFT2.cpp | 20 +++++++++++++++++--- RMFT2.h | 5 +++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/RMFT2.cpp b/RMFT2.cpp index 8c22b43..2018532 100644 --- a/RMFT2.cpp +++ b/RMFT2.cpp @@ -275,6 +275,7 @@ RMFT2::RMFT2(int progCtr) { forward=true; invert=false; stackDepth=0; + onTurnoutId=0; // Not handling an ONTHROW/ONCLOSE // chain into ring of RMFTs if (loopTask==NULL) { @@ -685,15 +686,28 @@ void RMFT2::kill(const FSH * reason, int operand) { return; } } - void RMFT2::turnoutEvent(VPIN id, bool closed) { + void RMFT2::turnoutEvent(int16_t turnoutId, bool closed) { + + // 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; + } + // Hunt for an ONTHROW/ONCLOSE for this turnout byte huntFor=closed ? OPCODE_ONCLOSE : OPCODE_ONTHROW ; // caution hides class progCounter; for (int progCounter=0;; SKIPOP){ byte opcode=GET_OPCODE; if (opcode==OPCODE_ENDEXRAIL) return; if (opcode!=huntFor) continue; - if (id!=GET_OPERAND(0)) continue; - new RMFT2(progCounter); // new task starts at this instruction + if (turnoutId!=(int16_t)GET_OPERAND(0)) continue; + task=new RMFT2(progCounter); // new task starts at this instruction + task->onTurnoutId=turnoutId; // flag for recursion detector return; } } diff --git a/RMFT2.h b/RMFT2.h index 10c147a..bb205c3 100644 --- a/RMFT2.h +++ b/RMFT2.h @@ -68,7 +68,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, static void readLocoCallback(int16_t cv); static void emitWithrottleRouteList(Print* stream); static void createNewTask(int route, uint16_t cab); - static void turnoutEvent(VPIN id, bool closed); + static void turnoutEvent(int16_t id, bool closed); private: static void ComandFilter(Print * stream, byte & opcode, byte & paramCount, int16_t p[]); static bool parseSlash(Print * stream, byte & paramCount, int16_t p[]) ; @@ -106,10 +106,11 @@ private: unsigned long delayTime; byte taskId; - int loco; + int16_t loco; bool forward; bool invert; int speedo; + int16_t onTurnoutId; byte stackDepth; int callStack[MAX_STACK_DEPTH]; }; From 9ba13a62c9f53dfda3b99a4f614342e89022fa4e Mon Sep 17 00:00:00 2001 From: Asbelos Date: Sat, 4 Sep 2021 10:38:38 +0100 Subject: [PATCH 3/7] Negative sensor ids --- RMFT2.cpp | 13 +++++++++---- RMFT2.h | 6 +++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/RMFT2.cpp b/RMFT2.cpp index 2018532..bc9c01e 100644 --- a/RMFT2.cpp +++ b/RMFT2.cpp @@ -330,11 +330,16 @@ void RMFT2::driveLoco(byte speed) { speedo=speed; } -bool RMFT2::readSensor(int16_t sensorId) { - VPIN vpin=abs(sensorId); +bool RMFT2::readSensor(uint16_t sensorId) { + // Exrail operands are unsigned but we need the signed version as inserted by the macros. + int16_t sId=(int16_t) sensorId; + + VPIN vpin=abs(sId); if (getFlag(vpin,LATCH_FLAG)) return true; // latched on - bool s= IODevice::read(vpin) ^ (sensorId<0); - if (s && diag) DIAG(F("EXRAIL Sensor %d hit"),sensorId); + + // negative sensorIds invert the logic (e.g. for a break-beam sensor which goes OFF when detecting) + bool s= IODevice::read(vpin) ^ (sId<0); + if (s && diag) DIAG(F("EXRAIL Sensor %d hit"),sId); return s; } diff --git a/RMFT2.h b/RMFT2.h index bb205c3..26cdf1d 100644 --- a/RMFT2.h +++ b/RMFT2.h @@ -85,7 +85,7 @@ private: static RMFT2 * pausingTask; void delayMe(long millisecs); void driveLoco(byte speedo); - bool readSensor(int16_t sensorId); + bool readSensor(uint16_t sensorId); bool skipIfBlock(); bool readLoco(); void loop2(); @@ -106,10 +106,10 @@ private: unsigned long delayTime; byte taskId; - int16_t loco; + uint16_t loco; bool forward; bool invert; - int speedo; + byte speedo; int16_t onTurnoutId; byte stackDepth; int callStack[MAX_STACK_DEPTH]; From 222eca6524778c5346000432138ed331b6bd4ca7 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Mon, 6 Sep 2021 12:27:21 +0100 Subject: [PATCH 4/7] XFON/XFOFF macros --- RMFT2.cpp | 14 +++++++++++--- RMFT2.h | 2 +- RMFTMacros.h | 6 ++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/RMFT2.cpp b/RMFT2.cpp index bc9c01e..842b460 100644 --- a/RMFT2.cpp +++ b/RMFT2.cpp @@ -530,11 +530,19 @@ void RMFT2::loop2() { case OPCODE_FON: if (loco) DCC::setFn(loco,operand,true); break; - + case OPCODE_FOFF: if (loco) DCC::setFn(loco,operand,false); break; - + + case OPCODE_XFON: + DCC::setFn(operand,GET_OPERAND(1),true); + break; + + case OPCODE_XFOFF: + DCC::setFn(operand,GET_OPERAND(1),false); + break; + case OPCODE_FOLLOW: progCounter=locateRouteStart(operand); if (progCounter<0) kill(F("FOLLOW unknown"), operand); @@ -631,7 +639,7 @@ void RMFT2::loop2() { case OPCODE_ROUTE: case OPCODE_AUTOMATION: case OPCODE_SEQUENCE: - DIAG(F("EXRAIL begin(%d)"),operand); + if (diag) DIAG(F("EXRAIL begin(%d)"),operand); break; case OPCODE_PAD: // Just a padding for previous opcode needing >1 operad byte. diff --git a/RMFT2.h b/RMFT2.h index 26cdf1d..a254070 100644 --- a/RMFT2.h +++ b/RMFT2.h @@ -34,7 +34,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, OPCODE_LATCH,OPCODE_UNLATCH,OPCODE_SET,OPCODE_RESET, OPCODE_IF,OPCODE_IFNOT,OPCODE_ENDIF,OPCODE_IFRANDOM,OPCODE_IFRESERVE, OPCODE_DELAY,OPCODE_DELAYMINS,OPCODE_RANDWAIT, - OPCODE_FON,OPCODE_FOFF, + OPCODE_FON,OPCODE_FOFF,OPCODE_XFON,OPCODE_XFOFF, OPCODE_RED,OPCODE_GREEN,OPCODE_AMBER, OPCODE_SERVO,OPCODE_SIGNAL,OPCODE_TURNOUT,OPCODE_WAITFOR, OPCODE_PAD,OPCODE_FOLLOW,OPCODE_CALL,OPCODE_RETURN, diff --git a/RMFTMacros.h b/RMFTMacros.h index 3e1cde1..f638001 100644 --- a/RMFTMacros.h +++ b/RMFTMacros.h @@ -113,6 +113,8 @@ #define UNJOIN #define UNLATCH(sensor_id) #define WAITFOR(pin) +#define XFOFF(cab,func) +#define XFON(cab,func) #include "myAutomation.h" @@ -196,6 +198,8 @@ const int StringMacroTracker1=__COUNTER__; #undef UNJOIN #undef UNLATCH #undef WAITFOR +#undef XFOFF +#undef XFON // Define macros for route code creation #define V(val) ((int16_t)(val))&0x00FF,((int16_t)(val)>>8)&0x00FF @@ -263,6 +267,8 @@ const int StringMacroTracker1=__COUNTER__; #define UNJOIN OPCODE_UNJOIN,NOP, #define UNLATCH(sensor_id) OPCODE_UNLATCH,V(sensor_id), #define WAITFOR(pin) OPCODE_WAITFOR,V(pin), +#define XFOFF(cab,func) OPCODE_XFOFF,V(cab),OPCODE_PAD,V(func), +#define XFON(cab,func) OPCODE_XFON,V(cab),OPCODE_PAD,V(func), // PASS2 Build RouteCode const int StringMacroTracker2=__COUNTER__; From 81dc512c8608a54813a1afcb8206da6e950aef41 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Mon, 6 Sep 2021 12:30:25 +0100 Subject: [PATCH 5/7] Turnout print state and tell withrottle --- Turnouts.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Turnouts.cpp b/Turnouts.cpp index 41b6b39..6dbc402 100644 --- a/Turnouts.cpp +++ b/Turnouts.cpp @@ -119,7 +119,7 @@ // Send message to JMRI etc. over Serial USB. This is done here // to ensure that the message is sent when the turnout operation // is not initiated by a Serial command. - printState(id, &Serial); + tt->printState(&Serial); return true; } @@ -140,6 +140,8 @@ bool ok = tt->setClosedInternal(closeFlag); if (ok) { + turnoutlistHash++; // let withrottle know something changed + // Write byte containing new closed/thrown state to EEPROM if required. Note that eepromAddress // is always zero for LCN turnouts. if (EEStore::eeStore->data.nTurnouts > 0 && tt->_eepromAddress > 0) @@ -152,7 +154,7 @@ // Send message to JMRI etc. over Serial USB. This is done here // to ensure that the message is sent when the turnout operation // is not initiated by a Serial command. - printState(id, &Serial); + tt->printState(&Serial); } return ok; } @@ -214,7 +216,7 @@ // Display, on the specified stream, the current state of the turnout (1=thrown or 0=closed). /* static */ void Turnout::printState(uint16_t id, Print *stream) { Turnout *tt = get(id); - if (!tt) tt->printState(stream); + if (tt) tt->printState(stream); } From 9b3c6fe8969c3a714c0136ad9e57e3944701aa80 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Wed, 8 Sep 2021 16:21:04 +0100 Subject: [PATCH 6/7] LCN and SERIAL/1/2/3 --- RMFTMacros.h | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/RMFTMacros.h b/RMFTMacros.h index f638001..e02aece 100644 --- a/RMFTMacros.h +++ b/RMFTMacros.h @@ -83,6 +83,7 @@ #define JOIN #define LATCH(sensor_id) #define LCD(row,msg) +#define LCN(msg) #define ONCLOSE(turnout_id) #define ONTHROW(turnout_id) #define PAUSE @@ -97,6 +98,9 @@ #define REV(speed) #define START(route) #define SENDLOCO(cab,route) +#define SERIAL1(msg) +#define SERIAL2(msg) +#define SERIAL3(msg) #define SERVO(id,position,profile) #define SERVO2(id,position,duration) #define SETLOCO(loco) @@ -127,6 +131,10 @@ #undef EXRAIL #undef PRINT +#undef LCN +#undef SERIAL1 +#undef SERIAL2 +#undef SERIAL3 #undef ENDEXRAIL #undef LCD const int StringMacroTracker1=__COUNTER__; @@ -134,6 +142,10 @@ const int StringMacroTracker1=__COUNTER__; #define EXRAIL void RMFT2::printMessage(uint16_t id) { switch(id) { #define ENDEXRAIL default: DIAG(F("printMessage error %d %d"),id,StringMacroTracker1); return ; }} #define PRINT(msg) case (__COUNTER__ - StringMacroTracker1) : printMessage2(F(msg));break; +#define LCN(msg) case (__COUNTER__ - StringMacroTracker1) : StringFormatter::send(&LCN_SERIAL,F(msg));break; +#define SERIAL1(msg) case (__COUNTER__ - StringMacroTracker1) : StringFormatter::send(&Serial1,F(msg));break; +#define SERIAL2(msg) case (__COUNTER__ - StringMacroTracker1) : StringFormatter::send(L&Serial2,F(msg));break; +#define SERIAL3(msg) case (__COUNTER__ - StringMacroTracker1) : StringFormatter::send(&Serial3,F(msg));break; #define LCD(id,msg) case (__COUNTER__ - StringMacroTracker1) : StringFormatter::lcd(id,F(msg));break; #include "myAutomation.h" @@ -167,6 +179,7 @@ const int StringMacroTracker1=__COUNTER__; #undef JOIN #undef LATCH #undef LCD +#undef LCN #undef ONCLOSE #undef ONTHROW #undef PAUSE @@ -186,6 +199,9 @@ const int StringMacroTracker1=__COUNTER__; #undef SERVO2 #undef FADE #undef SENDLOCO +#undef SERIAL1 +#undef SERIAL2 +#undef SERIAL3 #undef SETLOCO #undef SET #undef SPEED @@ -238,7 +254,8 @@ const int StringMacroTracker1=__COUNTER__; #define INVERT_DIRECTION OPCODE_INVERT_DIRECTION,NOP, #define JOIN OPCODE_JOIN,NOP, #define LATCH(sensor_id) OPCODE_LATCH,V(sensor_id), -#define LCD(id,msg) OPCODE_PRINT,V(__COUNTER__ - StringMacroTracker2), +#define LCD(id,msg) PRINT(msg) +#define LCN(msg) PRINT(msg) #define ONCLOSE(turnout_id) OPCODE_ONCLOSE,V(turnout_id), #define ONTHROW(turnout_id) OPCODE_ONTHROW,V(turnout_id), #define PAUSE OPCODE_PAUSE,NOP, @@ -252,6 +269,9 @@ const int StringMacroTracker1=__COUNTER__; #define RETURN OPCODE_RETURN,NOP, #define REV(speed) OPCODE_REV,V(speed), #define SENDLOCO(cab,route) OPCODE_SENDLOCO,V(cab),OPCODE_PAD,V(route), +#define SERIAL1(msg) PRINT(msg) +#define SERIAL2(msg) PRINT(msg) +#define SERIAL3(msg) PRINT(msg) #define START(route) OPCODE_START,V(route), #define SERVO(id,position,profile) OPCODE_SERVO,V(id),OPCODE_PAD,V(position),OPCODE_PAD,V(PCA9685::profile),OPCODE_PAD,V(0), #define SERVO2(id,position,ms) OPCODE_SERVO,V(id),OPCODE_PAD,V(position),OPCODE_PAD,V(PCA9685::Instant),OPCODE_PAD,V(ms/100L), From f38bf512abc5b9efd8bda5addf037dbe9ccd0cc6 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Wed, 8 Sep 2021 16:29:58 +0100 Subject: [PATCH 7/7] Include SERIAL --- RMFTMacros.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/RMFTMacros.h b/RMFTMacros.h index e02aece..fc5140f 100644 --- a/RMFTMacros.h +++ b/RMFTMacros.h @@ -98,6 +98,7 @@ #define REV(speed) #define START(route) #define SENDLOCO(cab,route) +#define SERIAL(msg) #define SERIAL1(msg) #define SERIAL2(msg) #define SERIAL3(msg) @@ -132,6 +133,7 @@ #undef EXRAIL #undef PRINT #undef LCN +#undef SERIAL #undef SERIAL1 #undef SERIAL2 #undef SERIAL3 @@ -141,12 +143,13 @@ const int StringMacroTracker1=__COUNTER__; #define ALIAS(name,value) #define EXRAIL void RMFT2::printMessage(uint16_t id) { switch(id) { #define ENDEXRAIL default: DIAG(F("printMessage error %d %d"),id,StringMacroTracker1); return ; }} -#define PRINT(msg) case (__COUNTER__ - StringMacroTracker1) : printMessage2(F(msg));break; -#define LCN(msg) case (__COUNTER__ - StringMacroTracker1) : StringFormatter::send(&LCN_SERIAL,F(msg));break; +#define PRINT(msg) case (__COUNTER__ - StringMacroTracker1) : printMessage2(F(msg));break; +#define LCN(msg) case (__COUNTER__ - StringMacroTracker1) : StringFormatter::send(&LCN_SERIAL,F(msg));break; +#define SERIAL(msg) case (__COUNTER__ - StringMacroTracker1) : StringFormatter::send(&Serial,F(msg));break; #define SERIAL1(msg) case (__COUNTER__ - StringMacroTracker1) : StringFormatter::send(&Serial1,F(msg));break; #define SERIAL2(msg) case (__COUNTER__ - StringMacroTracker1) : StringFormatter::send(L&Serial2,F(msg));break; #define SERIAL3(msg) case (__COUNTER__ - StringMacroTracker1) : StringFormatter::send(&Serial3,F(msg));break; -#define LCD(id,msg) case (__COUNTER__ - StringMacroTracker1) : StringFormatter::lcd(id,F(msg));break; +#define LCD(id,msg) case (__COUNTER__ - StringMacroTracker1) : StringFormatter::lcd(id,F(msg));break; #include "myAutomation.h" // Setup for Pass 3: create main routes table @@ -199,6 +202,7 @@ const int StringMacroTracker1=__COUNTER__; #undef SERVO2 #undef FADE #undef SENDLOCO +#undef SERIAL #undef SERIAL1 #undef SERIAL2 #undef SERIAL3 @@ -269,6 +273,7 @@ const int StringMacroTracker1=__COUNTER__; #define RETURN OPCODE_RETURN,NOP, #define REV(speed) OPCODE_REV,V(speed), #define SENDLOCO(cab,route) OPCODE_SENDLOCO,V(cab),OPCODE_PAD,V(route), +#define SERIAL(msg) PRINT(msg) #define SERIAL1(msg) PRINT(msg) #define SERIAL2(msg) PRINT(msg) #define SERIAL3(msg) PRINT(msg)