mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-02-16 22:19:14 +01:00
Merge branch 'EX-RAIL' into EX-RAIL-DC
This commit is contained in:
commit
60b9ba53d0
55
RMFT2.cpp
55
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) {
|
||||
@ -329,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;
|
||||
}
|
||||
|
||||
@ -524,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);
|
||||
@ -625,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.
|
||||
@ -674,26 +688,39 @@ 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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
11
RMFT2.h
11
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,
|
||||
@ -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[]) ;
|
||||
@ -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,11 @@ private:
|
||||
unsigned long delayTime;
|
||||
byte taskId;
|
||||
|
||||
int loco;
|
||||
uint16_t loco;
|
||||
bool forward;
|
||||
bool invert;
|
||||
int speedo;
|
||||
byte speedo;
|
||||
int16_t onTurnoutId;
|
||||
byte stackDepth;
|
||||
int callStack[MAX_STACK_DEPTH];
|
||||
};
|
||||
|
37
RMFTMacros.h
37
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,10 @@
|
||||
#define REV(speed)
|
||||
#define START(route)
|
||||
#define SENDLOCO(cab,route)
|
||||
#define SERIAL(msg)
|
||||
#define SERIAL1(msg)
|
||||
#define SERIAL2(msg)
|
||||
#define SERIAL3(msg)
|
||||
#define SERVO(id,position,profile)
|
||||
#define SERVO2(id,position,duration)
|
||||
#define SETLOCO(loco)
|
||||
@ -113,6 +118,8 @@
|
||||
#define UNJOIN
|
||||
#define UNLATCH(sensor_id)
|
||||
#define WAITFOR(pin)
|
||||
#define XFOFF(cab,func)
|
||||
#define XFON(cab,func)
|
||||
|
||||
#include "myAutomation.h"
|
||||
|
||||
@ -125,14 +132,24 @@
|
||||
|
||||
#undef EXRAIL
|
||||
#undef PRINT
|
||||
#undef LCN
|
||||
#undef SERIAL
|
||||
#undef SERIAL1
|
||||
#undef SERIAL2
|
||||
#undef SERIAL3
|
||||
#undef ENDEXRAIL
|
||||
#undef LCD
|
||||
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 LCD(id,msg) case (__COUNTER__ - StringMacroTracker1) : StringFormatter::lcd(id,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;
|
||||
#include "myAutomation.h"
|
||||
|
||||
// Setup for Pass 3: create main routes table
|
||||
@ -165,6 +182,7 @@ const int StringMacroTracker1=__COUNTER__;
|
||||
#undef JOIN
|
||||
#undef LATCH
|
||||
#undef LCD
|
||||
#undef LCN
|
||||
#undef ONCLOSE
|
||||
#undef ONTHROW
|
||||
#undef PAUSE
|
||||
@ -184,6 +202,10 @@ const int StringMacroTracker1=__COUNTER__;
|
||||
#undef SERVO2
|
||||
#undef FADE
|
||||
#undef SENDLOCO
|
||||
#undef SERIAL
|
||||
#undef SERIAL1
|
||||
#undef SERIAL2
|
||||
#undef SERIAL3
|
||||
#undef SETLOCO
|
||||
#undef SET
|
||||
#undef SPEED
|
||||
@ -196,6 +218,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
|
||||
@ -234,7 +258,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,
|
||||
@ -248,6 +273,10 @@ 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)
|
||||
#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),
|
||||
@ -263,6 +292,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__;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user