mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-23 08:06:13 +01:00
Squashed commit of the following:
commit8987d622e6
Author: Asbelos <asbelos@btinternet.com> Date: Tue Apr 9 20:44:47 2024 +0100 doc note commit8f0a5c1ec0
Author: Asbelos <asbelos@btinternet.com> Date: Thu Apr 4 09:45:58 2024 +0100 Exrail notes commit94083b9ab8
Merge:72ef199
02bf50b
Author: Asbelos <asbelos@btinternet.com> Date: Thu Apr 4 09:08:26 2024 +0100 Merge branch 'devel' into devel_chris commit72ef199315
Author: Asbelos <asbelos@btinternet.com> Date: Thu Apr 4 09:06:50 2024 +0100 TOGGLE_TURNOUT commite69b777a2f
Author: Asbelos <asbelos@btinternet.com> Date: Wed Apr 3 15:17:40 2024 +0100 BLINK command commitc7ed47400d
Author: Asbelos <asbelos@btinternet.com> Date: Tue Apr 2 10:12:45 2024 +0100 FTOGGLE,XFTOGGLE commit7a93cf7be8
Author: Asbelos <asbelos@btinternet.com> Date: Fri Mar 29 13:21:35 2024 +0000 EXRAIL STEALTH_GLOBAL
This commit is contained in:
parent
263c3d01e3
commit
5ea6feb11a
|
@ -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
|
||||||
|
|
||||||
|
|
79
EXRAIL2.cpp
79
EXRAIL2.cpp
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -815,6 +848,10 @@ void RMFT2::loop2() {
|
||||||
case OPCODE_FOFF:
|
case OPCODE_FOFF:
|
||||||
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:
|
||||||
{
|
{
|
||||||
|
@ -830,6 +867,10 @@ void RMFT2::loop2() {
|
||||||
case OPCODE_XFOFF:
|
case OPCODE_XFOFF:
|
||||||
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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1264,6 +1308,25 @@ void RMFT2::powerEvent(int16_t track, bool overload) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
18
EXRAIL2.h
18
EXRAIL2.h
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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__;
|
||||||
|
|
38
Release_Notes/EXRAIL additions.md
Normal file
38
Release_Notes/EXRAIL additions.md
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
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 issumes 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.
|
||||||
|
|
98
Release_Notes/Exrail mods.txt
Normal file
98
Release_Notes/Exrail mods.txt
Normal 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
|
Loading…
Reference in New Issue
Block a user