1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-30 03:26:13 +01:00

updates from devel 5.2.47

updates from devel 5.2.47 x/SHA
This commit is contained in:
Ash-4 2024-04-09 23:11:54 -05:00 committed by GitHub
commit aa1e53035f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 258 additions and 26 deletions

View File

@ -800,6 +800,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
break; break;
#endif #endif
case '/': // implemented in EXRAIL parser
case 'L': // LCC interface implemented in EXRAIL parser case 'L': // LCC interface implemented in EXRAIL parser
break; // Will <X> if not intercepted by EXRAIL break; // Will <X> if not intercepted by EXRAIL

View File

@ -176,7 +176,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
/* static */ void RMFT2::begin() { /* static */ void RMFT2::begin() {
DIAG(F("EXRAIL RoutCode at =%P"),RouteCode); //DIAG(F("EXRAIL RoutCode at =%P"),RouteCode);
bool saved_diag=diag; bool saved_diag=diag;
diag=true; diag=true;
@ -373,7 +373,7 @@ RMFT2::RMFT2(int progCtr) {
speedo=0; speedo=0;
forward=true; forward=true;
invert=false; invert=false;
timeoutFlag=false; blinkState=not_blink_task;
stackDepth=0; stackDepth=0;
onEventStartPosition=-1; // Not handling an ONxxx onEventStartPosition=-1; // Not handling an ONxxx
@ -411,7 +411,7 @@ void RMFT2::createNewTask(int route, uint16_t cab) {
void RMFT2::driveLoco(byte speed) { void RMFT2::driveLoco(byte speed) {
if (loco<=0) return; // Prevent broadcast! if (loco<=0) return; // Prevent broadcast!
if (diag) DIAG(F("EXRAIL drive %d %d %d"),loco,speed,forward^invert); //if (diag) DIAG(F("EXRAIL drive %d %d %d"),loco,speed,forward^invert);
/* TODO..... /* TODO.....
power on appropriate track if DC or main if dcc power on appropriate track if DC or main if dcc
if (TrackManager::getMainPowerMode()==POWERMODE::OFF) { if (TrackManager::getMainPowerMode()==POWERMODE::OFF) {
@ -491,6 +491,23 @@ void RMFT2::loop() {
void RMFT2::loop2() { void RMFT2::loop2() {
if (delayTime!=0 && millis()-delayStart < delayTime) return; if (delayTime!=0 && millis()-delayStart < delayTime) return;
// special stand alone blink task
if (compileFeatures & FEATURE_BLINK) {
if (blinkState==blink_low) {
IODevice::write(blinkPin,HIGH);
blinkState=blink_high;
delayMe(getOperand(1));
return;
}
if (blinkState==blink_high) {
IODevice::write(blinkPin,LOW);
blinkState=blink_low;
delayMe(getOperand(2));
return;
}
}
// Normal progstep following tasks continue here.
byte opcode = GET_OPCODE; byte opcode = GET_OPCODE;
int16_t operand = getOperand(0); int16_t operand = getOperand(0);
@ -511,6 +528,10 @@ void RMFT2::loop2() {
Turnout::setClosed(operand, true); Turnout::setClosed(operand, true);
break; break;
case OPCODE_TOGGLE_TURNOUT:
Turnout::setClosed(operand, Turnout::isThrown(operand));
break;
#ifndef IO_NO_HAL #ifndef IO_NO_HAL
case OPCODE_ROTATE: case OPCODE_ROTATE:
uint8_t activity; uint8_t activity;
@ -560,39 +581,39 @@ void RMFT2::loop2() {
break; break;
case OPCODE_AT: case OPCODE_AT:
timeoutFlag=false; blinkState=not_blink_task;
if (readSensor(operand)) break; if (readSensor(operand)) break;
delayMe(50); delayMe(50);
return; return;
case OPCODE_ATGTE: // wait for analog sensor>= value case OPCODE_ATGTE: // wait for analog sensor>= value
timeoutFlag=false; blinkState=not_blink_task;
if (IODevice::readAnalogue(operand) >= (int)(getOperand(1))) break; if (IODevice::readAnalogue(operand) >= (int)(getOperand(1))) break;
delayMe(50); delayMe(50);
return; return;
case OPCODE_ATLT: // wait for analog sensor < value case OPCODE_ATLT: // wait for analog sensor < value
timeoutFlag=false; blinkState=not_blink_task;
if (IODevice::readAnalogue(operand) < (int)(getOperand(1))) break; if (IODevice::readAnalogue(operand) < (int)(getOperand(1))) break;
delayMe(50); delayMe(50);
return; return;
case OPCODE_ATTIMEOUT1: // ATTIMEOUT(vpin,timeout) part 1 case OPCODE_ATTIMEOUT1: // ATTIMEOUT(vpin,timeout) part 1
timeoutStart=millis(); timeoutStart=millis();
timeoutFlag=false; blinkState=not_blink_task;
break; break;
case OPCODE_ATTIMEOUT2: case OPCODE_ATTIMEOUT2:
if (readSensor(operand)) break; // success without timeout if (readSensor(operand)) break; // success without timeout
if (millis()-timeoutStart > 100*getOperand(1)) { if (millis()-timeoutStart > 100*getOperand(1)) {
timeoutFlag=true; blinkState=at_timeout;
break; // and drop through break; // and drop through
} }
delayMe(50); delayMe(50);
return; return;
case OPCODE_IFTIMEOUT: // do next operand if timeout flag set case OPCODE_IFTIMEOUT: // do next operand if timeout flag set
skipIf=!timeoutFlag; skipIf=blinkState!=at_timeout;
break; break;
case OPCODE_AFTER: // waits for sensor to hit and then remain off for 0.5 seconds. (must come after an AT operation) case OPCODE_AFTER: // waits for sensor to hit and then remain off for 0.5 seconds. (must come after an AT operation)
@ -624,13 +645,25 @@ void RMFT2::loop2() {
break; break;
case OPCODE_SET: case OPCODE_SET:
killBlinkOnVpin(operand);
IODevice::write(operand,true); IODevice::write(operand,true);
break; break;
case OPCODE_RESET: case OPCODE_RESET:
killBlinkOnVpin(operand);
IODevice::write(operand,false); IODevice::write(operand,false);
break; break;
case OPCODE_BLINK:
// Start a new task to blink this vpin
killBlinkOnVpin(operand);
{
auto newtask=new RMFT2(progCounter);
newtask->blinkPin=operand;
newtask->blinkState=blink_low; // will go high on first call
}
break;
case OPCODE_PAUSE: case OPCODE_PAUSE:
DCC::setThrottle(0,1,true); // pause all locos on the track DCC::setThrottle(0,1,true); // pause all locos on the track
pausingTask=this; pausingTask=this;
@ -816,6 +849,10 @@ void RMFT2::loop2() {
if (loco) DCC::setFn(loco,operand,false); if (loco) DCC::setFn(loco,operand,false);
break; break;
case OPCODE_FTOGGLE:
if (loco) DCC::changeFn(loco,operand);
break;
case OPCODE_DRIVE: case OPCODE_DRIVE:
{ {
byte analogSpeed=IODevice::readAnalogue(operand) *127 / 1024; byte analogSpeed=IODevice::readAnalogue(operand) *127 / 1024;
@ -831,6 +868,10 @@ void RMFT2::loop2() {
DCC::setFn(operand,getOperand(1),false); DCC::setFn(operand,getOperand(1),false);
break; break;
case OPCODE_XFTOGGLE:
DCC::changeFn(operand,getOperand(1));
break;
case OPCODE_DCCACTIVATE: { case OPCODE_DCCACTIVATE: {
// operand is address<<3 | subaddr<<1 | active // operand is address<<3 | subaddr<<1 | active
int16_t addr=operand>>3; int16_t addr=operand>>3;
@ -1025,7 +1066,7 @@ void RMFT2::loop2() {
case OPCODE_ROUTE: case OPCODE_ROUTE:
case OPCODE_AUTOMATION: case OPCODE_AUTOMATION:
case OPCODE_SEQUENCE: case OPCODE_SEQUENCE:
if (diag) DIAG(F("EXRAIL begin(%d)"),operand); //if (diag) DIAG(F("EXRAIL begin(%d)"),operand);
break; break;
case OPCODE_AUTOSTART: // Handled only during begin process case OPCODE_AUTOSTART: // Handled only during begin process
@ -1105,7 +1146,7 @@ int16_t RMFT2::getSignalSlot(int16_t id) {
/* static */ void RMFT2::doSignal(int16_t id,char rag) { /* static */ void RMFT2::doSignal(int16_t id,char rag) {
if (!(compileFeatures & FEATURE_SIGNAL)) return; // dont compile code below if (!(compileFeatures & FEATURE_SIGNAL)) return; // dont compile code below
if (diag) DIAG(F(" doSignal %d %x"),id,rag); //if (diag) DIAG(F(" doSignal %d %x"),id,rag);
// Schedule any event handler for this signal change. // Schedule any event handler for this signal change.
// This will work even without a signal definition. // This will work even without a signal definition.
@ -1125,7 +1166,7 @@ int16_t RMFT2::getSignalSlot(int16_t id) {
VPIN redpin=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigpos+2); VPIN redpin=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigpos+2);
VPIN amberpin=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigpos+4); VPIN amberpin=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigpos+4);
VPIN greenpin=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigpos+6); VPIN greenpin=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigpos+6);
if (diag) DIAG(F("signal %d %d %d %d %d"),sigid,id,redpin,amberpin,greenpin); //if (diag) DIAG(F("signal %d %d %d %d %d"),sigid,id,redpin,amberpin,greenpin);
VPIN sigtype=sigid & ~SIGNAL_ID_MASK; VPIN sigtype=sigid & ~SIGNAL_ID_MASK;
@ -1133,7 +1174,7 @@ int16_t RMFT2::getSignalSlot(int16_t id) {
// A servo signal, the pin numbers are actually servo positions // A servo signal, the pin numbers are actually servo positions
// Note, setting a signal to a zero position has no effect. // Note, setting a signal to a zero position has no effect.
int16_t servopos= rag==SIGNAL_RED? redpin: (rag==SIGNAL_GREEN? greenpin : amberpin); int16_t servopos= rag==SIGNAL_RED? redpin: (rag==SIGNAL_GREEN? greenpin : amberpin);
if (diag) DIAG(F("sigA %d %d"),id,servopos); //if (diag) DIAG(F("sigA %d %d"),id,servopos);
if (servopos!=0) IODevice::writeAnalogue(id,servopos,PCA9685::Bounce); if (servopos!=0) IODevice::writeAnalogue(id,servopos,PCA9685::Bounce);
return; return;
} }
@ -1167,16 +1208,19 @@ int16_t RMFT2::getSignalSlot(int16_t id) {
if (redpin) { if (redpin) {
bool redval=(rag==SIGNAL_RED || rag==SIMAMBER); bool redval=(rag==SIGNAL_RED || rag==SIMAMBER);
if (!aHigh) redval=!redval; if (!aHigh) redval=!redval;
killBlinkOnVpin(redpin);
IODevice::write(redpin,redval); IODevice::write(redpin,redval);
} }
if (amberpin) { if (amberpin) {
bool amberval=(rag==SIGNAL_AMBER); bool amberval=(rag==SIGNAL_AMBER);
if (!aHigh) amberval=!amberval; if (!aHigh) amberval=!amberval;
killBlinkOnVpin(amberpin);
IODevice::write(amberpin,amberval); IODevice::write(amberpin,amberval);
} }
if (greenpin) { if (greenpin) {
bool greenval=(rag==SIGNAL_GREEN || rag==SIMAMBER); bool greenval=(rag==SIGNAL_GREEN || rag==SIMAMBER);
if (!aHigh) greenval=!greenval; if (!aHigh) greenval=!greenval;
killBlinkOnVpin(greenpin);
IODevice::write(greenpin,greenval); IODevice::write(greenpin,greenval);
} }
} }
@ -1248,7 +1292,7 @@ void RMFT2::rotateEvent(int16_t turntableId, bool change) {
void RMFT2::clockEvent(int16_t clocktime, bool change) { void RMFT2::clockEvent(int16_t clocktime, bool change) {
// Hunt for an ONTIME for this time // Hunt for an ONTIME for this time
if (Diag::CMD) if (Diag::CMD)
DIAG(F("Looking for clock event at : %d"), clocktime); DIAG(F("clockEvent at : %d"), clocktime);
if (change) { if (change) {
onClockLookup->handleEvent(F("CLOCK"),clocktime); onClockLookup->handleEvent(F("CLOCK"),clocktime);
onClockLookup->handleEvent(F("CLOCK"),25*60+clocktime%60); onClockLookup->handleEvent(F("CLOCK"),25*60+clocktime%60);
@ -1258,12 +1302,31 @@ void RMFT2::clockEvent(int16_t clocktime, bool change) {
void RMFT2::powerEvent(int16_t track, bool overload) { void RMFT2::powerEvent(int16_t track, bool overload) {
// Hunt for an ONOVERLOAD for this item // Hunt for an ONOVERLOAD for this item
if (Diag::CMD) if (Diag::CMD)
DIAG(F("Looking for Power event on track : %c"), track); DIAG(F("powerEvent : %c"), track);
if (overload) { if (overload) {
onOverloadLookup->handleEvent(F("POWER"),track); onOverloadLookup->handleEvent(F("POWER"),track);
} }
} }
// This function is used when setting pins so that a SET or RESET
// will cause any blink task on that pin to terminate.
// It will be compiled out of existence if no BLINK feature is used.
void RMFT2::killBlinkOnVpin(VPIN pin) {
if (!(compileFeatures & FEATURE_BLINK)) return;
RMFT2 * task=loopTask;
while(task) {
if (
(task->blinkState==blink_high || task->blinkState==blink_low)
&& task->blinkPin==pin) {
task->kill();
return;
}
task=task->next;
if (task==loopTask) return;
}
}
void RMFT2::startNonRecursiveTask(const FSH* reason, int16_t id,int pc) { void RMFT2::startNonRecursiveTask(const FSH* reason, int16_t id,int pc) {
// Check we dont already have a task running this handler // Check we dont already have a task running this handler
RMFT2 * task=loopTask; RMFT2 * task=loopTask;

View File

@ -33,7 +33,7 @@
// or more OPCODE_PAD instructions with the subsequent parameters. This wastes a byte but makes // 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. // searching easier as a parameter can never be confused with an opcode.
// //
enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,OPCODE_TOGGLE_TURNOUT,
OPCODE_FWD,OPCODE_REV,OPCODE_SPEED,OPCODE_INVERT_DIRECTION, OPCODE_FWD,OPCODE_REV,OPCODE_SPEED,OPCODE_INVERT_DIRECTION,
OPCODE_RESERVE,OPCODE_FREE, OPCODE_RESERVE,OPCODE_FREE,
OPCODE_AT,OPCODE_AFTER, OPCODE_AT,OPCODE_AFTER,
@ -41,9 +41,11 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
OPCODE_ATGTE,OPCODE_ATLT, OPCODE_ATGTE,OPCODE_ATLT,
OPCODE_ATTIMEOUT1,OPCODE_ATTIMEOUT2, OPCODE_ATTIMEOUT1,OPCODE_ATTIMEOUT2,
OPCODE_LATCH,OPCODE_UNLATCH,OPCODE_SET,OPCODE_RESET, OPCODE_LATCH,OPCODE_UNLATCH,OPCODE_SET,OPCODE_RESET,
OPCODE_BLINK,
OPCODE_ENDIF,OPCODE_ELSE, OPCODE_ENDIF,OPCODE_ELSE,
OPCODE_DELAY,OPCODE_DELAYMINS,OPCODE_DELAYMS,OPCODE_RANDWAIT, OPCODE_DELAY,OPCODE_DELAYMINS,OPCODE_DELAYMS,OPCODE_RANDWAIT,
OPCODE_FON,OPCODE_FOFF,OPCODE_XFON,OPCODE_XFOFF, OPCODE_FON,OPCODE_FOFF,OPCODE_XFON,OPCODE_XFOFF,
OPCODE_FTOGGLE,OPCODE_XFTOGGLE,
OPCODE_RED,OPCODE_GREEN,OPCODE_AMBER,OPCODE_DRIVE, OPCODE_RED,OPCODE_GREEN,OPCODE_AMBER,OPCODE_DRIVE,
OPCODE_SERVO,OPCODE_SIGNAL,OPCODE_TURNOUT,OPCODE_WAITFOR, OPCODE_SERVO,OPCODE_SIGNAL,OPCODE_TURNOUT,OPCODE_WAITFOR,
OPCODE_PAD,OPCODE_FOLLOW,OPCODE_CALL,OPCODE_RETURN, OPCODE_PAD,OPCODE_FOLLOW,OPCODE_CALL,OPCODE_RETURN,
@ -98,12 +100,21 @@ enum thrunger: byte {
thrunge_lcd, // Must be last!! thrunge_lcd, // Must be last!!
}; };
enum BlinkState: byte {
not_blink_task,
blink_low, // blink task running with pin LOW
blink_high, // blink task running with pin high
at_timeout // ATTIMEOUT timed out flag
};
// Flag bits for compile time features. // Flag bits for compile time features.
static const byte FEATURE_SIGNAL= 0x80; static const byte FEATURE_SIGNAL= 0x80;
static const byte FEATURE_LCC = 0x40; static const byte FEATURE_LCC = 0x40;
static const byte FEATURE_ROSTER= 0x20; static const byte FEATURE_ROSTER= 0x20;
static const byte FEATURE_ROUTESTATE= 0x10; static const byte FEATURE_ROUTESTATE= 0x10;
static const byte FEATURE_STASH = 0x08; static const byte FEATURE_STASH = 0x08;
static const byte FEATURE_BLINK = 0x04;
// Flag bits for status of hardware and TPL // Flag bits for status of hardware and TPL
@ -192,6 +203,7 @@ private:
static LookList* LookListLoader(OPCODE op1, static LookList* LookListLoader(OPCODE op1,
OPCODE op2=OPCODE_ENDEXRAIL,OPCODE op3=OPCODE_ENDEXRAIL); OPCODE op2=OPCODE_ENDEXRAIL,OPCODE op3=OPCODE_ENDEXRAIL);
static uint16_t getOperand(int progCounter,byte n); static uint16_t getOperand(int progCounter,byte n);
static void killBlinkOnVpin(VPIN pin);
static RMFT2 * loopTask; static RMFT2 * loopTask;
static RMFT2 * pausingTask; static RMFT2 * pausingTask;
void delayMe(long millisecs); void delayMe(long millisecs);
@ -244,10 +256,10 @@ private:
union { union {
unsigned long waitAfter; // Used by OPCODE_AFTER unsigned long waitAfter; // Used by OPCODE_AFTER
unsigned long timeoutStart; // Used by OPCODE_ATTIMEOUT unsigned long timeoutStart; // Used by OPCODE_ATTIMEOUT
VPIN blinkPin; // Used by blink tasks
}; };
bool timeoutFlag;
byte taskId; byte taskId;
BlinkState blinkState; // includes AT_TIMEOUT flag.
uint16_t loco; uint16_t loco;
bool forward; bool forward;
bool invert; bool invert;

View File

@ -38,6 +38,7 @@
#undef ATTIMEOUT #undef ATTIMEOUT
#undef AUTOMATION #undef AUTOMATION
#undef AUTOSTART #undef AUTOSTART
#undef BLINK
#undef BROADCAST #undef BROADCAST
#undef CALL #undef CALL
#undef CLEAR_STASH #undef CLEAR_STASH
@ -66,6 +67,7 @@
#undef FOLLOW #undef FOLLOW
#undef FON #undef FON
#undef FORGET #undef FORGET
#undef FTOGGLE
#undef FREE #undef FREE
#undef FWD #undef FWD
#undef GREEN #undef GREEN
@ -164,8 +166,10 @@
#undef START #undef START
#undef STASH #undef STASH
#undef STEALTH #undef STEALTH
#undef STEALTH_GLOBAL
#undef STOP #undef STOP
#undef THROW #undef THROW
#undef TOGGLE_TURNOUT
#undef TT_ADDPOSITION #undef TT_ADDPOSITION
#undef TURNOUT #undef TURNOUT
#undef TURNOUTL #undef TURNOUTL
@ -180,6 +184,7 @@
#undef WITHROTTLE #undef WITHROTTLE
#undef XFOFF #undef XFOFF
#undef XFON #undef XFON
#undef XFTOGGLE
#ifndef RMFT2_UNDEF_ONLY #ifndef RMFT2_UNDEF_ONLY
#define ACTIVATE(addr,subaddr) #define ACTIVATE(addr,subaddr)
@ -196,6 +201,7 @@
#define ATTIMEOUT(sensor_id,timeout_ms) #define ATTIMEOUT(sensor_id,timeout_ms)
#define AUTOMATION(id,description) #define AUTOMATION(id,description)
#define AUTOSTART #define AUTOSTART
#define BLINK(vpin,onDuty,offDuty)
#define BROADCAST(msg) #define BROADCAST(msg)
#define CALL(route) #define CALL(route)
#define CLEAR_STASH(id) #define CLEAR_STASH(id)
@ -225,6 +231,7 @@
#define FON(func) #define FON(func)
#define FORGET #define FORGET
#define FREE(blockid) #define FREE(blockid)
#define FTOGGLE(func)
#define FWD(speed) #define FWD(speed)
#define GREEN(signal_id) #define GREEN(signal_id)
#define HAL(haltype,params...) #define HAL(haltype,params...)
@ -322,8 +329,10 @@
#define START(route) #define START(route)
#define STASH(id) #define STASH(id)
#define STEALTH(code...) #define STEALTH(code...)
#define STEALTH_GLOBAL(code...)
#define STOP #define STOP
#define THROW(id) #define THROW(id)
#define TOGGLE_TURNOUT(id)
#define TT_ADDPOSITION(turntable_id,position,value,angle,description...) #define TT_ADDPOSITION(turntable_id,position,value,angle,description...)
#define TURNOUT(id,addr,subaddr,description...) #define TURNOUT(id,addr,subaddr,description...)
#define TURNOUTL(id,addr,description...) #define TURNOUTL(id,addr,description...)
@ -338,4 +347,6 @@
#define WITHROTTLE(msg) #define WITHROTTLE(msg)
#define XFOFF(cab,func) #define XFOFF(cab,func)
#define XFON(cab,func) #define XFON(cab,func)
#define XFTOGGLE(cab,func)
#endif #endif

View File

@ -36,7 +36,7 @@
void RMFT2::ComandFilter(Print * stream, byte & opcode, byte & paramCount, int16_t p[]) { void RMFT2::ComandFilter(Print * stream, byte & opcode, byte & paramCount, int16_t p[]) {
(void)stream; // avoid compiler warning if we don't access this parameter (void)stream; // avoid compiler warning if we don't access this parameter
bool reject=false;
switch(opcode) { switch(opcode) {
case 'D': case 'D':
@ -47,8 +47,7 @@ void RMFT2::ComandFilter(Print * stream, byte & opcode, byte & paramCount, int16
break; break;
case '/': // New EXRAIL command case '/': // New EXRAIL command
reject=!parseSlash(stream,paramCount,p); if (parseSlash(stream,paramCount,p)) opcode=0;
opcode=0;
break; break;
case 'A': // <A address aspect> case 'A': // <A address aspect>
@ -106,9 +105,11 @@ void RMFT2::ComandFilter(Print * stream, byte & opcode, byte & paramCount, int16
} }
if (paramCount==1) { // <L eventid> LCC event arrived from adapter if (paramCount==1) { // <L eventid> LCC event arrived from adapter
int16_t eventid=p[0]; int16_t eventid=p[0];
reject=eventid<0 || eventid>=countLCCLookup; bool reject = eventid<0 || eventid>=countLCCLookup;
if (!reject) startNonRecursiveTask(F("LCC"),eventid,onLCCLookup[eventid]); if (!reject) {
opcode=0; startNonRecursiveTask(F("LCC"),eventid,onLCCLookup[eventid]);
opcode=0;
}
} }
break; break;
@ -182,12 +183,20 @@ bool RMFT2::parseSlash(Print * stream, byte & paramCount, int16_t p[]) {
StringFormatter::send(stream, F("<* EXRAIL STATUS")); StringFormatter::send(stream, F("<* EXRAIL STATUS"));
RMFT2 * task=loopTask; RMFT2 * task=loopTask;
while(task) { while(task) {
if ((compileFeatures & FEATURE_BLINK)
&& (task->blinkState==blink_high || task->blinkState==blink_low)) {
StringFormatter::send(stream,F("\nID=%d,PC=%d,BLINK=%d"),
(int)(task->taskId),task->progCounter,task->blinkPin
);
}
else {
StringFormatter::send(stream,F("\nID=%d,PC=%d,LOCO=%d%c,SPEED=%d%c"), StringFormatter::send(stream,F("\nID=%d,PC=%d,LOCO=%d%c,SPEED=%d%c"),
(int)(task->taskId),task->progCounter,task->loco, (int)(task->taskId),task->progCounter,task->loco,
task->invert?'I':' ', task->invert?'I':' ',
task->speedo, task->speedo,
task->forward?'F':'R' task->forward?'F':'R'
); );
}
task=task->next; task=task->next;
if (task==loopTask) break; if (task==loopTask) break;
} }

View File

@ -145,6 +145,12 @@ static_assert(!hasdup(compileTimeSequenceList[0],1),"Duplicate SEQUENCE/ROUTE/AU
#include "myAutomation.h" #include "myAutomation.h"
// Pass 1g Implants STEALTH_GLOBAL in correct place
#include "EXRAIL2MacroReset.h"
#undef STEALTH_GLOBAL
#define STEALTH_GLOBAL(code...) code
#include "myAutomation.h"
// Pass 1h Implements HAL macro by creating exrailHalSetup function // Pass 1h Implements HAL macro by creating exrailHalSetup function
// Also allows creating EXTurntable object // Also allows creating EXTurntable object
#include "EXRAIL2MacroReset.h" #include "EXRAIL2MacroReset.h"
@ -202,6 +208,8 @@ bool exrailHalSetup() {
#define PICKUP_STASH(id) | FEATURE_STASH #define PICKUP_STASH(id) | FEATURE_STASH
#undef STASH #undef STASH
#define STASH(id) | FEATURE_STASH #define STASH(id) | FEATURE_STASH
#undef BLINK
#define BLINK(vpin,onDuty,offDuty) | FEATURE_BLINK
const byte RMFT2::compileFeatures = 0 const byte RMFT2::compileFeatures = 0
#include "myAutomation.h" #include "myAutomation.h"
@ -451,6 +459,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#define ATTIMEOUT(sensor_id,timeout) OPCODE_ATTIMEOUT1,0,0,OPCODE_ATTIMEOUT2,V(sensor_id),OPCODE_PAD,V(timeout/100L), #define ATTIMEOUT(sensor_id,timeout) OPCODE_ATTIMEOUT1,0,0,OPCODE_ATTIMEOUT2,V(sensor_id),OPCODE_PAD,V(timeout/100L),
#define AUTOMATION(id, description) OPCODE_AUTOMATION, V(id), #define AUTOMATION(id, description) OPCODE_AUTOMATION, V(id),
#define AUTOSTART OPCODE_AUTOSTART,0,0, #define AUTOSTART OPCODE_AUTOSTART,0,0,
#define BLINK(vpin,onDuty,offDuty) OPCODE_BLINK,V(vpin),OPCODE_PAD,V(onDuty),OPCODE_PAD,V(offDuty),
#define BROADCAST(msg) PRINT(msg) #define BROADCAST(msg) PRINT(msg)
#define CALL(route) OPCODE_CALL,V(route), #define CALL(route) OPCODE_CALL,V(route),
#define CLEAR_STASH(id) OPCODE_CLEAR_STASH,V(id), #define CLEAR_STASH(id) OPCODE_CLEAR_STASH,V(id),
@ -484,6 +493,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#define FON(func) OPCODE_FON,V(func), #define FON(func) OPCODE_FON,V(func),
#define FORGET OPCODE_FORGET,0,0, #define FORGET OPCODE_FORGET,0,0,
#define FREE(blockid) OPCODE_FREE,V(blockid), #define FREE(blockid) OPCODE_FREE,V(blockid),
#define FTOGGLE(func) OPCODE_FTOGGLE,V(func),
#define FWD(speed) OPCODE_FWD,V(speed), #define FWD(speed) OPCODE_FWD,V(speed),
#define GREEN(signal_id) OPCODE_GREEN,V(signal_id), #define GREEN(signal_id) OPCODE_GREEN,V(signal_id),
#define HAL(haltype,params...) #define HAL(haltype,params...)
@ -518,6 +528,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#define LCD(id,msg) PRINT(msg) #define LCD(id,msg) PRINT(msg)
#define SCREEN(display,id,msg) PRINT(msg) #define SCREEN(display,id,msg) PRINT(msg)
#define STEALTH(code...) PRINT(dummy) #define STEALTH(code...) PRINT(dummy)
#define STEALTH_GLOBAL(code...)
#define LCN(msg) PRINT(msg) #define LCN(msg) PRINT(msg)
#define MESSAGE(msg) PRINT(msg) #define MESSAGE(msg) PRINT(msg)
#define MOVETT(id,steps,activity) OPCODE_SERVO,V(id),OPCODE_PAD,V(steps),OPCODE_PAD,V(EXTurntable::activity),OPCODE_PAD,V(0), #define MOVETT(id,steps,activity) OPCODE_SERVO,V(id),OPCODE_PAD,V(steps),OPCODE_PAD,V(EXTurntable::activity),OPCODE_PAD,V(0),
@ -595,6 +606,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#define STASH(id) OPCODE_STASH,V(id), #define STASH(id) OPCODE_STASH,V(id),
#define STOP OPCODE_SPEED,V(0), #define STOP OPCODE_SPEED,V(0),
#define THROW(id) OPCODE_THROW,V(id), #define THROW(id) OPCODE_THROW,V(id),
#define TOGGLE_TURNOUT(id) OPCODE_TOGGLE_TURNOUT,V(id),
#ifndef IO_NO_HAL #ifndef IO_NO_HAL
#define TT_ADDPOSITION(id,position,value,angle,description...) OPCODE_TTADDPOSITION,V(id),OPCODE_PAD,V(position),OPCODE_PAD,V(value),OPCODE_PAD,V(angle), #define TT_ADDPOSITION(id,position,value,angle,description...) OPCODE_TTADDPOSITION,V(id),OPCODE_PAD,V(position),OPCODE_PAD,V(value),OPCODE_PAD,V(angle),
#endif #endif
@ -611,6 +623,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#endif #endif
#define XFOFF(cab,func) OPCODE_XFOFF,V(cab),OPCODE_PAD,V(func), #define XFOFF(cab,func) OPCODE_XFOFF,V(cab),OPCODE_PAD,V(func),
#define XFON(cab,func) OPCODE_XFON,V(cab),OPCODE_PAD,V(func), #define XFON(cab,func) OPCODE_XFON,V(cab),OPCODE_PAD,V(func),
#define XFTOGGLE(cab,func) OPCODE_XFTOGGLE,V(cab),OPCODE_PAD,V(func),
// Build RouteCode // Build RouteCode
const int StringMacroTracker2=__COUNTER__; const int StringMacroTracker2=__COUNTER__;

View File

@ -0,0 +1,98 @@
BLINK(vpin, onMs,offMs)
which will start a vpin blinking until such time as it is SET, RESET or set by a signal operation such as RED, AMBER, GREEN.
BLINK returns immediately, the blinking is autonomous.
This means a signal that always blinks amber could be done like this:
SIGNAL(30,31,32)
ONAMBER(30) BLINK(31,500,500) DONE
The RED or GREEN calls will turn off the amber blink automatically.
Alternatively a signal that has normal AMBER and flashing AMBER could be like this:
#define FLASHAMBER(signal) \
AMBER(signal) \
BLINK(signal+1,500,500)
(Caution: this assumes that the amber pin is redpin+1)
==
FTOGGLE(function)
Toggles the current loco function (see FON and FOFF)
XFTOGGLE(loco,function)
Toggles the function on given loco. (See XFON, XFOFF)
TOGGLE_TURNOUT(id)
Toggles the turnout (see CLOSE, THROW)
STEALTH_GLOBAL(code)
ADVANCED C++ users only.
Inserts code such as static variables and functions that
may be utilised by multiple STEALTH operations.
// 5.2.34 - <A address aspect> Command fopr DCC Extended Accessories.
This command sends an extended accessory packet to the track, Normally used to set
a signal aspect. Aspect numbers are undefined as sdtandards except for 0 which is
always considered a stop.
// - Exrail ASPECT(address,aspect) for above.
The ASPECT command sents an aspect to a DCC accessory using the same logic as
<A aspect address>.
// - EXRAIL DCCX_SIGNAL(Address,redAspect,amberAspect,greenAspect)
This defines a signal (with id same as dcc address) that can be operated
by the RED/AMBER/GREEN commands. In each case the command uses the signal
address to refer to the signal and the aspect chosen depends on the use of the RED
AMBER or GREEN command sent. Other aspects may be sent but will require the
direct use of the ASPECT command.
The IFRED/IFAMBER/IFGREEN and ONRED/ONAMBER/ONGREEN commands contunue to operate
as for any other signal type. It is important to be aware that use of the ASPECT
or <A> commands will correctly set the IF flags and call the ON handlers if ASPECT
is used to set one of the three aspects defined in the DCCX_SIGNAL command.
Direct use of other aspects does not affect the signal flags.
ASPECT and <A> can be used withput defining any signal if tyhe flag management or
ON event handlers are not required.
// 5.2.33 - Exrail CONFIGURE_SERVO(vpin,pos1,pos2,profile)
This macro offsers a more convenient way of performing the HAL call in halSetup.h
In halSetup.h --- IODevice::configureServo(101,300,400,PCA9685::slow);
In myAutomation.h --- CONFIGURE_SERVO(101,300,400,slow)
// 5.2.32 - Railcom Cutout (Initial trial Mega2560 only)
This cutout will only work on a Mega2560 with a single EX8874 motor shield
configured in the normal way with the main track brake pin on pin 9.
<C RAILCOM ON> Turns on the cutout mechanism.
<C RAILCOM OFF> Tirns off the cutout. (This is the default)
<C RAILCOM DEBUG> ONLY to be used by developers used for waveform diagnostics.
(In DEBUG mode the main track idle packets are replaced with reset packets, This
makes it far easier to see the preambles and cutouts on a logic analyser or scope.)
// 5.2.31 - Exrail JMRI_SENSOR(vpin [,count]) creates <S> types.
This Macro causes the creation of JMRI <S> type sensors in a way that is
simpler than repeating lines of <S> commands.
JMRI_SENSOR(100) is equenvelant to <S 100 100 1>
JMRI_SENSOR(100,16) will create <S> type sensors for vpins 100-115.
// 5.2.26 - Silently ignore overridden HAL defaults
// - include HAL_IGNORE_DEFAULTS macro in EXRAIL
The HAL_IGNORE_DEFAULTS command, anywhere in myAutomation.h will
prevent the startup code from trying the default I2C sensors/servos.
// 5.2.24 - Exrail macro asserts to catch
// : duplicate/missing automation/route/sequence/call ids
// : latches and reserves out of range
// : speeds out of range
Causes compiler time messages for EXRAIL issues that would normally
only be discovered by things going wrong at run time.
// 5.2.13 - EXRAIL STEALTH
Permits a certain level of C++ code to be embedded as a single step in
an exrail sequence. Serious engineers only.
// 5.2.9 - EXRAIL STASH feature
// - Added ROUTE_DISABLED macro in EXRAIL

View File

@ -211,6 +211,19 @@ The configuration file for DCC-EX Command Station
// #define DISABLE_VDPY // #define DISABLE_VDPY
// #define ENABLE_VDPY // #define ENABLE_VDPY
/////////////////////////////////////////////////////////////////////////////////////
// DISABLE / ENABLE DIAG
//
// To diagose different errors, you can turn on differnet messages. This costs
// program memory which we do not have enough on the Uno and Nano, so it is
// by default DISABLED on those. If you think you can fit it (for example
// having disabled some of the features above) you can enable it with
// ENABLE_DIAG. You can even disable it on all other CPUs with
// DISABLE_DIAG
//
// #define DISABLE_DIAG
// #define ENABLE_DIAG
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
// REDEFINE WHERE SHORT/LONG ADDR break is. According to NMRA the last short address // REDEFINE WHERE SHORT/LONG ADDR break is. According to NMRA the last short address
// is 127 and the first long address is 128. There are manufacturers which have // is 127 and the first long address is 128. There are manufacturers which have

View File

@ -220,9 +220,15 @@
// //
#if defined(ARDUINO_AVR_NANO) || defined(ARDUINO_AVR_UNO) #if defined(ARDUINO_AVR_NANO) || defined(ARDUINO_AVR_UNO)
#define IO_NO_HAL // HAL too big whatever you disable otherwise #define IO_NO_HAL // HAL too big whatever you disable otherwise
#ifndef ENABLE_VDPY #ifndef ENABLE_VDPY
#define DISABLE_VDPY #define DISABLE_VDPY
#endif #endif
#ifndef ENABLE_DIAG
#define DISABLE_DIAG
#endif
#endif #endif
#if __has_include ( "myAutomation.h") #if __has_include ( "myAutomation.h")

View File

@ -3,7 +3,13 @@
#include "StringFormatter.h" #include "StringFormatter.h"
#define VERSION "5.3.8" #define VERSION "5.3.9"
// 5.2.47 - EXRAIL additions:
// STEALTH_GLOBAL
// BLINK
// TOGGLE_TURNOUT
// FTOGGLE, XFTOGGLE
// Reduced code-developmenmt DIAG noise
// 5.2.46 - Support for extended consist CV20 in <R> and <W id> // 5.2.46 - Support for extended consist CV20 in <R> and <W id>
// - New cmd <W CONSIST id [REVERSE]> to handle long/short consist ids // - New cmd <W CONSIST id [REVERSE]> to handle long/short consist ids
// 5.2.45 - ESP32 Trackmanager reset cab number to 0 when track is not DC // 5.2.45 - ESP32 Trackmanager reset cab number to 0 when track is not DC