mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-24 16:46:13 +01:00
Compare commits
24 Commits
dba5d35aa2
...
4fcd81a118
Author | SHA1 | Date | |
---|---|---|---|
|
4fcd81a118 | ||
|
eb450dbd89 | ||
|
a0562fdf5c | ||
|
7ee2c29a52 | ||
|
dca023ffd7 | ||
|
4eef9581fe | ||
|
ab393047c1 | ||
|
1ac104704e | ||
|
2f8e915b1e | ||
|
44d8154223 | ||
|
01919b33df | ||
|
26ddd27ecf | ||
|
2c64f10da8 | ||
|
25426d076d | ||
|
3453da0671 | ||
|
fb226311e5 | ||
|
6392c74ead | ||
|
25f8852af6 | ||
|
9842ea8a42 | ||
|
fa0aa27d46 | ||
|
4b2c0702a4 | ||
|
e27cceeb74 | ||
|
247763ac00 | ||
|
e327e0ae8d |
|
@ -351,7 +351,7 @@ void DCCACK::callback(int value) {
|
||||||
|
|
||||||
switch (callbackState) {
|
switch (callbackState) {
|
||||||
case AFTER_READ:
|
case AFTER_READ:
|
||||||
if (ackManagerRejoin && autoPowerOff) {
|
if (ackManagerRejoin && !autoPowerOff) {
|
||||||
progDriver->setPower(POWERMODE::OFF);
|
progDriver->setPower(POWERMODE::OFF);
|
||||||
callbackStart=millis();
|
callbackStart=millis();
|
||||||
callbackState=WAITING_30;
|
callbackState=WAITING_30;
|
||||||
|
|
|
@ -25,6 +25,79 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
List of single character OPCODEs in use for reference.
|
||||||
|
|
||||||
|
When determining a new OPCODE for a new feature, refer to this list as the source of truth.
|
||||||
|
|
||||||
|
Once a new OPCODE is decided upon, update this list.
|
||||||
|
|
||||||
|
Character, Usage
|
||||||
|
/, |EX-R| interactive commands
|
||||||
|
-, Remove from reminder table
|
||||||
|
=, |TM| configuration
|
||||||
|
!, Emergency stop
|
||||||
|
@, Reserved for future use - LCD messages to JMRI
|
||||||
|
#, Request number of supported cabs/locos; heartbeat
|
||||||
|
+, WiFi AT commands
|
||||||
|
?, Reserved for future use
|
||||||
|
0, Track power off
|
||||||
|
1, Track power on
|
||||||
|
a, DCC accessory control
|
||||||
|
A,
|
||||||
|
b, Write CV bit on main
|
||||||
|
B, Write CV bit
|
||||||
|
c, Request current command
|
||||||
|
C,
|
||||||
|
d,
|
||||||
|
D, Diagnostic commands
|
||||||
|
e, Erase EEPROM
|
||||||
|
E, Store configuration in EEPROM
|
||||||
|
f, Loco decoder function control (deprecated)
|
||||||
|
F, Loco decoder function control
|
||||||
|
g,
|
||||||
|
G,
|
||||||
|
h,
|
||||||
|
H, Turnout state broadcast
|
||||||
|
i, Reserved for future use - Turntable object broadcast
|
||||||
|
I, Reserved for future use - Turntable object command and control
|
||||||
|
j, Throttle responses
|
||||||
|
J, Throttle queries
|
||||||
|
k, Reserved for future use - Potentially Railcom
|
||||||
|
K, Reserved for future use - Potentially Railcom
|
||||||
|
l, Loco speedbyte/function map broadcast
|
||||||
|
L,
|
||||||
|
m,
|
||||||
|
M, Write DCC packet
|
||||||
|
n,
|
||||||
|
N,
|
||||||
|
o,
|
||||||
|
O, Output broadcast
|
||||||
|
p, Broadcast power state
|
||||||
|
P, Write DCC packet
|
||||||
|
q, Sensor deactivated
|
||||||
|
Q, Sensor activated
|
||||||
|
r, Broadcast address read on programming track
|
||||||
|
R, Read CVs
|
||||||
|
s, Display status
|
||||||
|
S, Sensor configuration
|
||||||
|
t, Cab/loco update command
|
||||||
|
T, Turnout configuration/control
|
||||||
|
u, Reserved for user commands
|
||||||
|
U, Reserved for user commands
|
||||||
|
v,
|
||||||
|
V, Verify CVs
|
||||||
|
w, Write CV on main
|
||||||
|
W, Write CV
|
||||||
|
x,
|
||||||
|
X, Invalid command
|
||||||
|
y,
|
||||||
|
Y, Output broadcast
|
||||||
|
z,
|
||||||
|
Z, Output configuration/control
|
||||||
|
*/
|
||||||
|
|
||||||
#include "StringFormatter.h"
|
#include "StringFormatter.h"
|
||||||
#include "DCCEXParser.h"
|
#include "DCCEXParser.h"
|
||||||
#include "DCC.h"
|
#include "DCC.h"
|
||||||
|
@ -383,10 +456,14 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
||||||
|
|
||||||
#ifndef DISABLE_PROG
|
#ifndef DISABLE_PROG
|
||||||
case 'w': // WRITE CV on MAIN <w CAB CV VALUE>
|
case 'w': // WRITE CV on MAIN <w CAB CV VALUE>
|
||||||
|
if (params != 3)
|
||||||
|
break;
|
||||||
DCC::writeCVByteMain(p[0], p[1], p[2]);
|
DCC::writeCVByteMain(p[0], p[1], p[2]);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 'b': // WRITE CV BIT ON MAIN <b CAB CV BIT VALUE>
|
case 'b': // WRITE CV BIT ON MAIN <b CAB CV BIT VALUE>
|
||||||
|
if (params != 4)
|
||||||
|
break;
|
||||||
DCC::writeCVBitMain(p[0], p[1], p[2], p[3]);
|
DCC::writeCVBitMain(p[0], p[1], p[2], p[3]);
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
@ -417,8 +494,10 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
||||||
DCC::setLocoId(p[0],callback_Wloco);
|
DCC::setLocoId(p[0],callback_Wloco);
|
||||||
else if (params == 4) // WRITE CV ON PROG <W CV VALUE [CALLBACKNUM] [CALLBACKSUB]>
|
else if (params == 4) // WRITE CV ON PROG <W CV VALUE [CALLBACKNUM] [CALLBACKSUB]>
|
||||||
DCC::writeCVByte(p[0], p[1], callback_W4);
|
DCC::writeCVByte(p[0], p[1], callback_W4);
|
||||||
else // WRITE CV ON PROG <W CV VALUE>
|
else if (params == 2) // WRITE CV ON PROG <W CV VALUE>
|
||||||
DCC::writeCVByte(p[0], p[1], callback_W);
|
DCC::writeCVByte(p[0], p[1], callback_W);
|
||||||
|
else
|
||||||
|
break;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 'V': // VERIFY CV ON PROG <V CV VALUE> <V CV BIT 0|1>
|
case 'V': // VERIFY CV ON PROG <V CV VALUE> <V CV BIT 0|1>
|
||||||
|
@ -438,7 +517,9 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'B': // WRITE CV BIT ON PROG <B CV BIT VALUE CALLBACKNUM CALLBACKSUB>
|
case 'B': // WRITE CV BIT ON PROG <B CV BIT VALUE CALLBACKNUM CALLBACKSUB> or <B CV BIT VALUE>
|
||||||
|
if (params != 3 && params != 5)
|
||||||
|
break;
|
||||||
if (!stashCallback(stream, p, ringStream))
|
if (!stashCallback(stream, p, ringStream))
|
||||||
break;
|
break;
|
||||||
DCC::writeCVBit(p[0], p[1], p[2], callback_B);
|
DCC::writeCVBit(p[0], p[1], p[2], callback_B);
|
||||||
|
@ -570,12 +651,12 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
||||||
case ' ': // < >
|
case ' ': // < >
|
||||||
StringFormatter::send(stream, F("\n"));
|
StringFormatter::send(stream, F("\n"));
|
||||||
return;
|
return;
|
||||||
|
#ifndef DISABLE_DIAG
|
||||||
case 'D': // < >
|
case 'D': // < >
|
||||||
if (parseD(stream, params, p))
|
if (parseD(stream, params, p))
|
||||||
return;
|
return;
|
||||||
return;
|
break;
|
||||||
|
#endif
|
||||||
case '=': // <= Track manager control >
|
case '=': // <= Track manager control >
|
||||||
if (TrackManager::parseJ(stream, params, p))
|
if (TrackManager::parseJ(stream, params, p))
|
||||||
return;
|
return;
|
||||||
|
|
28
EXRAIL2.cpp
28
EXRAIL2.cpp
|
@ -2,7 +2,7 @@
|
||||||
* © 2021 Neil McKechnie
|
* © 2021 Neil McKechnie
|
||||||
* © 2021-2023 Harald Barth
|
* © 2021-2023 Harald Barth
|
||||||
* © 2020-2023 Chris Harlow
|
* © 2020-2023 Chris Harlow
|
||||||
* © 2022 Colin Murdoch
|
* © 2022-2023 Colin Murdoch
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of CommandStation-EX
|
* This file is part of CommandStation-EX
|
||||||
|
@ -99,6 +99,7 @@ LookList * RMFT2::onClockLookup=NULL;
|
||||||
#ifndef IO_NO_HAL
|
#ifndef IO_NO_HAL
|
||||||
LookList * RMFT2::onRotateLookup=NULL;
|
LookList * RMFT2::onRotateLookup=NULL;
|
||||||
#endif
|
#endif
|
||||||
|
LookList * RMFT2::onOverloadLookup=NULL;
|
||||||
|
|
||||||
#define GET_OPCODE GETHIGHFLASH(RMFT2::RouteCode,progCounter)
|
#define GET_OPCODE GETHIGHFLASH(RMFT2::RouteCode,progCounter)
|
||||||
#define SKIPOP progCounter+=3
|
#define SKIPOP progCounter+=3
|
||||||
|
@ -183,6 +184,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
|
||||||
#ifndef IO_NO_HAL
|
#ifndef IO_NO_HAL
|
||||||
onRotateLookup=LookListLoader(OPCODE_ONROTATE);
|
onRotateLookup=LookListLoader(OPCODE_ONROTATE);
|
||||||
#endif
|
#endif
|
||||||
|
onOverloadLookup=LookListLoader(OPCODE_ONOVERLOAD);
|
||||||
|
|
||||||
// Second pass startup, define any turnouts or servos, set signals red
|
// Second pass startup, define any turnouts or servos, set signals red
|
||||||
// add sequences onRoutines to the lookups
|
// add sequences onRoutines to the lookups
|
||||||
|
@ -202,6 +204,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
|
||||||
case OPCODE_AT:
|
case OPCODE_AT:
|
||||||
case OPCODE_ATTIMEOUT2:
|
case OPCODE_ATTIMEOUT2:
|
||||||
case OPCODE_AFTER:
|
case OPCODE_AFTER:
|
||||||
|
case OPCODE_AFTEROVERLOAD:
|
||||||
case OPCODE_IF:
|
case OPCODE_IF:
|
||||||
case OPCODE_IFNOT: {
|
case OPCODE_IFNOT: {
|
||||||
int16_t pin = (int16_t)operand;
|
int16_t pin = (int16_t)operand;
|
||||||
|
@ -259,7 +262,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
|
||||||
case OPCODE_EXTTTURNTABLE: {
|
case OPCODE_EXTTTURNTABLE: {
|
||||||
VPIN id=operand;
|
VPIN id=operand;
|
||||||
VPIN pin=getOperand(progCounter,1);
|
VPIN pin=getOperand(progCounter,1);
|
||||||
int home=getOperand(progCounter,2);
|
int home=getOperand(progCounter,3);
|
||||||
setTurntableHiddenState(EXTTTurntable::create(id,pin));
|
setTurntableHiddenState(EXTTTurntable::create(id,pin));
|
||||||
Turntable *tto=Turntable::get(id);
|
Turntable *tto=Turntable::get(id);
|
||||||
tto->addPosition(0,0,home);
|
tto->addPosition(0,0,home);
|
||||||
|
@ -738,6 +741,16 @@ void RMFT2::loop2() {
|
||||||
if (millis()-waitAfter < 500 ) return;
|
if (millis()-waitAfter < 500 ) return;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OPCODE_AFTEROVERLOAD: // waits for the power to be turned back on - either by power routine or button
|
||||||
|
if (!TrackManager::isPowerOn(operand)) {
|
||||||
|
// reset timer to half a second and keep waiting
|
||||||
|
waitAfter=millis();
|
||||||
|
delayMe(50);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (millis()-waitAfter < 500 ) return;
|
||||||
|
break;
|
||||||
|
|
||||||
case OPCODE_LATCH:
|
case OPCODE_LATCH:
|
||||||
setFlag(operand,LATCH_FLAG);
|
setFlag(operand,LATCH_FLAG);
|
||||||
break;
|
break;
|
||||||
|
@ -1060,6 +1073,7 @@ void RMFT2::loop2() {
|
||||||
case OPCODE_TTADDPOSITION: // Turntable position definition ignored at runtime
|
case OPCODE_TTADDPOSITION: // Turntable position definition ignored at runtime
|
||||||
case OPCODE_ONROTATE:
|
case OPCODE_ONROTATE:
|
||||||
#endif
|
#endif
|
||||||
|
case OPCODE_ONOVERLOAD:
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1221,6 +1235,16 @@ void RMFT2::clockEvent(int16_t clocktime, bool change) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RMFT2::powerEvent(int16_t track, bool overload) {
|
||||||
|
// Hunt for an ONOVERLOAD for this item
|
||||||
|
if (Diag::CMD)
|
||||||
|
DIAG(F("Looking for Power event on track : %c"), track);
|
||||||
|
if (overload) {
|
||||||
|
handleEvent(F("POWER"),onOverloadLookup,track);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) {
|
void RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) {
|
||||||
int pc= handlers->find(id);
|
int pc= handlers->find(id);
|
||||||
if (pc<0) return;
|
if (pc<0) return;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* © 2021 Neil McKechnie
|
* © 2021 Neil McKechnie
|
||||||
* © 2020-2022 Chris Harlow
|
* © 2020-2022 Chris Harlow
|
||||||
* © 2022 Colin Murdoch
|
* © 2022-2023 Colin Murdoch
|
||||||
* © 2023 Harald Barth
|
* © 2023 Harald Barth
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -36,7 +36,8 @@
|
||||||
enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
|
enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
|
||||||
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_AUTOSTART,
|
OPCODE_AT,OPCODE_AFTER,
|
||||||
|
OPCODE_AFTEROVERLOAD,OPCODE_AUTOSTART,
|
||||||
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,
|
||||||
|
@ -67,6 +68,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
|
||||||
OPCODE_TTADDPOSITION,OPCODE_DCCTURNTABLE,OPCODE_EXTTTURNTABLE,
|
OPCODE_TTADDPOSITION,OPCODE_DCCTURNTABLE,OPCODE_EXTTTURNTABLE,
|
||||||
OPCODE_ONROTATE,OPCODE_ROTATE,OPCODE_IFTTPOSITION,OPCODE_WAITFORTT,
|
OPCODE_ONROTATE,OPCODE_ROTATE,OPCODE_IFTTPOSITION,OPCODE_WAITFORTT,
|
||||||
#endif
|
#endif
|
||||||
|
OPCODE_ONOVERLOAD,
|
||||||
|
|
||||||
// OPcodes below this point are skip-nesting IF operations
|
// OPcodes below this point are skip-nesting IF operations
|
||||||
// placed here so that they may be skipped as a group
|
// placed here so that they may be skipped as a group
|
||||||
|
@ -136,6 +138,7 @@ class LookList {
|
||||||
static void changeEvent(int16_t id, bool change);
|
static void changeEvent(int16_t id, bool change);
|
||||||
static void clockEvent(int16_t clocktime, bool change);
|
static void clockEvent(int16_t clocktime, bool change);
|
||||||
static void rotateEvent(int16_t id, bool change);
|
static void rotateEvent(int16_t id, bool change);
|
||||||
|
static void powerEvent(int16_t track, bool overload);
|
||||||
static const int16_t SERVO_SIGNAL_FLAG=0x4000;
|
static const int16_t SERVO_SIGNAL_FLAG=0x4000;
|
||||||
static const int16_t ACTIVE_HIGH_SIGNAL_FLAG=0x2000;
|
static const int16_t ACTIVE_HIGH_SIGNAL_FLAG=0x2000;
|
||||||
static const int16_t DCC_SIGNAL_FLAG=0x1000;
|
static const int16_t DCC_SIGNAL_FLAG=0x1000;
|
||||||
|
@ -202,6 +205,7 @@ private:
|
||||||
#ifndef IO_NO_HAL
|
#ifndef IO_NO_HAL
|
||||||
static LookList * onRotateLookup;
|
static LookList * onRotateLookup;
|
||||||
#endif
|
#endif
|
||||||
|
static LookList * onOverloadLookup;
|
||||||
|
|
||||||
// Local variables - exist for each instance/task
|
// Local variables - exist for each instance/task
|
||||||
RMFT2 *next; // loop chain
|
RMFT2 *next; // loop chain
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* © 2020-2022 Chris Harlow. All rights reserved.
|
* © 2020-2022 Chris Harlow. All rights reserved.
|
||||||
* © 2022 Colin Murdoch
|
* © 2022-2023 Colin Murdoch
|
||||||
* © 2023 Harald Barth
|
* © 2023 Harald Barth
|
||||||
*
|
*
|
||||||
* This file is part of CommandStation-EX
|
* This file is part of CommandStation-EX
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
#undef ACTIVATE
|
#undef ACTIVATE
|
||||||
#undef ACTIVATEL
|
#undef ACTIVATEL
|
||||||
#undef AFTER
|
#undef AFTER
|
||||||
|
#undef AFTEROVERLOAD
|
||||||
#undef ALIAS
|
#undef ALIAS
|
||||||
#undef AMBER
|
#undef AMBER
|
||||||
#undef ANOUT
|
#undef ANOUT
|
||||||
|
@ -96,6 +97,7 @@
|
||||||
#undef ONTIME
|
#undef ONTIME
|
||||||
#undef ONCLOCKTIME
|
#undef ONCLOCKTIME
|
||||||
#undef ONCLOCKMINS
|
#undef ONCLOCKMINS
|
||||||
|
#undef ONOVERLOAD
|
||||||
#undef ONGREEN
|
#undef ONGREEN
|
||||||
#undef ONRED
|
#undef ONRED
|
||||||
#undef ONROTATE
|
#undef ONROTATE
|
||||||
|
@ -162,6 +164,7 @@
|
||||||
#define ACTIVATE(addr,subaddr)
|
#define ACTIVATE(addr,subaddr)
|
||||||
#define ACTIVATEL(addr)
|
#define ACTIVATEL(addr)
|
||||||
#define AFTER(sensor_id)
|
#define AFTER(sensor_id)
|
||||||
|
#define AFTEROVERLOAD(track_id)
|
||||||
#define ALIAS(name,value...)
|
#define ALIAS(name,value...)
|
||||||
#define AMBER(signal_id)
|
#define AMBER(signal_id)
|
||||||
#define ANOUT(vpin,value,param1,param2)
|
#define ANOUT(vpin,value,param1,param2)
|
||||||
|
@ -189,7 +192,7 @@
|
||||||
#define ENDTASK
|
#define ENDTASK
|
||||||
#define ESTOP
|
#define ESTOP
|
||||||
#define EXRAIL
|
#define EXRAIL
|
||||||
#define EXTT_TURNTABLE(id,vpin,home,description)
|
#define EXTT_TURNTABLE(id,vpin,i2c_address,home,description)
|
||||||
#define FADE(pin,value,ms)
|
#define FADE(pin,value,ms)
|
||||||
#define FOFF(func)
|
#define FOFF(func)
|
||||||
#define FOLLOW(route)
|
#define FOLLOW(route)
|
||||||
|
@ -228,6 +231,7 @@
|
||||||
#define ONTIME(value)
|
#define ONTIME(value)
|
||||||
#define ONCLOCKTIME(hours,mins)
|
#define ONCLOCKTIME(hours,mins)
|
||||||
#define ONCLOCKMINS(mins)
|
#define ONCLOCKMINS(mins)
|
||||||
|
#define ONOVERLOAD(track_id)
|
||||||
#define ONDEACTIVATE(addr,subaddr)
|
#define ONDEACTIVATE(addr,subaddr)
|
||||||
#define ONDEACTIVATEL(linear)
|
#define ONDEACTIVATEL(linear)
|
||||||
#define ONCLOSE(turnout_id)
|
#define ONCLOSE(turnout_id)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* © 2021 Neil McKechnie
|
* © 2021 Neil McKechnie
|
||||||
* © 2020-2022 Chris Harlow
|
* © 2020-2022 Chris Harlow
|
||||||
* © 2022 Colin Murdoch
|
* © 2022-2023 Colin Murdoch
|
||||||
* © 2023 Harald Barth
|
* © 2023 Harald Barth
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -70,9 +70,12 @@
|
||||||
#include "myAutomation.h"
|
#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
|
||||||
#include "EXRAIL2MacroReset.h"
|
#include "EXRAIL2MacroReset.h"
|
||||||
#undef HAL
|
#undef HAL
|
||||||
#define HAL(haltype,params...) haltype::create(params);
|
#define HAL(haltype,params...) haltype::create(params);
|
||||||
|
#undef EXTT_TURNTABLE
|
||||||
|
#define EXTT_TURNTABLE(id,vpin,i2c_address,home,description...) EXTurntable::create(vpin,1,i2c_address);
|
||||||
void exrailHalSetup() {
|
void exrailHalSetup() {
|
||||||
#include "myAutomation.h"
|
#include "myAutomation.h"
|
||||||
}
|
}
|
||||||
|
@ -194,7 +197,7 @@ const FSH * RMFT2::getTurnoutDescription(int16_t turnoutid) {
|
||||||
#undef DCC_TURNTABLE
|
#undef DCC_TURNTABLE
|
||||||
#define DCC_TURNTABLE(id,home,description...) O_DESC(id,description)
|
#define DCC_TURNTABLE(id,home,description...) O_DESC(id,description)
|
||||||
#undef EXTT_TURNTABLE
|
#undef EXTT_TURNTABLE
|
||||||
#define EXTT_TURNTABLE(id,vpin,home,description...) O_DESC(id,description)
|
#define EXTT_TURNTABLE(id,vpin,i2c_address,home,description...) O_DESC(id,description)
|
||||||
|
|
||||||
const FSH * RMFT2::getTurntableDescription(int16_t turntableId) {
|
const FSH * RMFT2::getTurntableDescription(int16_t turntableId) {
|
||||||
switch (turntableId) {
|
switch (turntableId) {
|
||||||
|
@ -283,6 +286,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = {
|
||||||
#define ACTIVATE(addr,subaddr) OPCODE_DCCACTIVATE,V(addr<<3 | subaddr<<1 | 1),
|
#define ACTIVATE(addr,subaddr) OPCODE_DCCACTIVATE,V(addr<<3 | subaddr<<1 | 1),
|
||||||
#define ACTIVATEL(addr) OPCODE_DCCACTIVATE,V((addr+3)<<1 | 1),
|
#define ACTIVATEL(addr) OPCODE_DCCACTIVATE,V((addr+3)<<1 | 1),
|
||||||
#define AFTER(sensor_id) OPCODE_AT,V(sensor_id),OPCODE_AFTER,V(sensor_id),
|
#define AFTER(sensor_id) OPCODE_AT,V(sensor_id),OPCODE_AFTER,V(sensor_id),
|
||||||
|
#define AFTEROVERLOAD(track_id) OPCODE_AFTEROVERLOAD,V(TRACK_NUMBER_##track_id),
|
||||||
#define ALIAS(name,value...)
|
#define ALIAS(name,value...)
|
||||||
#define AMBER(signal_id) OPCODE_AMBER,V(signal_id),
|
#define AMBER(signal_id) OPCODE_AMBER,V(signal_id),
|
||||||
#define ANOUT(vpin,value,param1,param2) OPCODE_SERVO,V(vpin),OPCODE_PAD,V(value),OPCODE_PAD,V(param1),OPCODE_PAD,V(param2),
|
#define ANOUT(vpin,value,param1,param2) OPCODE_SERVO,V(vpin),OPCODE_PAD,V(value),OPCODE_PAD,V(param1),OPCODE_PAD,V(param2),
|
||||||
|
@ -313,7 +317,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = {
|
||||||
#define ESTOP OPCODE_SPEED,V(1),
|
#define ESTOP OPCODE_SPEED,V(1),
|
||||||
#define EXRAIL
|
#define EXRAIL
|
||||||
#ifndef IO_NO_HAL
|
#ifndef IO_NO_HAL
|
||||||
#define EXTT_TURNTABLE(id,vpin,home,description...) OPCODE_EXTTTURNTABLE,V(id),OPCODE_PAD,V(vpin),OPCODE_PAD,V(home),
|
#define EXTT_TURNTABLE(id,vpin,i2c_address,home,description...) OPCODE_EXTTTURNTABLE,V(id),OPCODE_PAD,V(vpin),OPCODE_PAD,V(i2c_address),OPCODE_PAD,V(home),
|
||||||
#endif
|
#endif
|
||||||
#define FADE(pin,value,ms) OPCODE_SERVO,V(pin),OPCODE_PAD,V(value),OPCODE_PAD,V(PCA9685::ProfileType::UseDuration|PCA9685::NoPowerOff),OPCODE_PAD,V(ms/100L),
|
#define FADE(pin,value,ms) OPCODE_SERVO,V(pin),OPCODE_PAD,V(value),OPCODE_PAD,V(PCA9685::ProfileType::UseDuration|PCA9685::NoPowerOff),OPCODE_PAD,V(ms/100L),
|
||||||
#define FOFF(func) OPCODE_FOFF,V(func),
|
#define FOFF(func) OPCODE_FOFF,V(func),
|
||||||
|
@ -356,6 +360,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = {
|
||||||
#define ONTIME(value) OPCODE_ONTIME,V(value),
|
#define ONTIME(value) OPCODE_ONTIME,V(value),
|
||||||
#define ONCLOCKTIME(hours,mins) OPCODE_ONTIME,V((STRIP_ZERO(hours)*60)+STRIP_ZERO(mins)),
|
#define ONCLOCKTIME(hours,mins) OPCODE_ONTIME,V((STRIP_ZERO(hours)*60)+STRIP_ZERO(mins)),
|
||||||
#define ONCLOCKMINS(mins) ONCLOCKTIME(25,mins)
|
#define ONCLOCKMINS(mins) ONCLOCKTIME(25,mins)
|
||||||
|
#define ONOVERLOAD(track_id) OPCODE_ONOVERLOAD,V(TRACK_NUMBER_##track_id),
|
||||||
#define ONDEACTIVATE(addr,subaddr) OPCODE_ONDEACTIVATE,V(addr<<2|subaddr),
|
#define ONDEACTIVATE(addr,subaddr) OPCODE_ONDEACTIVATE,V(addr<<2|subaddr),
|
||||||
#define ONDEACTIVATEL(linear) OPCODE_ONDEACTIVATE,V(linear+3),
|
#define ONDEACTIVATEL(linear) OPCODE_ONDEACTIVATE,V(linear+3),
|
||||||
#define ONGREEN(signal_id) OPCODE_ONGREEN,V(signal_id),
|
#define ONGREEN(signal_id) OPCODE_ONGREEN,V(signal_id),
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
#define GITHUB_SHA "devel-202308102205Z"
|
#define GITHUB_SHA "devel-202308302157Z"
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
|
|
||||||
class PCA9555 : public GPIOBase<uint16_t> {
|
class PCA9555 : public GPIOBase<uint16_t> {
|
||||||
public:
|
public:
|
||||||
static void create(VPIN vpin, int nPins, uint8_t I2CAddress, int interruptPin=-1) {
|
static void create(VPIN vpin, uint8_t nPins, I2CAddress i2cAddress, int interruptPin=-1) {
|
||||||
new PCA9555(vpin, min(nPins,16), I2CAddress, interruptPin);
|
if (checkNoOverlap(vpin, nPins, i2cAddress)) new PCA9555(vpin,nPins, i2cAddress, interruptPin);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* © 2021 Fred Decker
|
* © 2021 Fred Decker
|
||||||
* © 2020-2023 Harald Barth
|
* © 2020-2023 Harald Barth
|
||||||
* © 2020-2021 Chris Harlow
|
* © 2020-2021 Chris Harlow
|
||||||
|
* © 2023 Colin Murdoch
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of CommandStation-EX
|
* This file is part of CommandStation-EX
|
||||||
|
@ -26,6 +27,7 @@
|
||||||
#include "DCCWaveform.h"
|
#include "DCCWaveform.h"
|
||||||
#include "DCCTimer.h"
|
#include "DCCTimer.h"
|
||||||
#include "DIAG.h"
|
#include "DIAG.h"
|
||||||
|
#include "EXRAIL2.h"
|
||||||
|
|
||||||
unsigned long MotorDriver::globalOverloadStart = 0;
|
unsigned long MotorDriver::globalOverloadStart = 0;
|
||||||
|
|
||||||
|
@ -614,6 +616,8 @@ void MotorDriver::checkPowerOverload(bool useProgLimit, byte trackno) {
|
||||||
power_sample_overload_wait *= 2;
|
power_sample_overload_wait *= 2;
|
||||||
if (power_sample_overload_wait > POWER_SAMPLE_RETRY_MAX)
|
if (power_sample_overload_wait > POWER_SAMPLE_RETRY_MAX)
|
||||||
power_sample_overload_wait = POWER_SAMPLE_RETRY_MAX;
|
power_sample_overload_wait = POWER_SAMPLE_RETRY_MAX;
|
||||||
|
DIAG(F("Calling EXRAIL"));
|
||||||
|
RMFT2::powerEvent(trackno, true); // Tell EXRAIL we have an overload
|
||||||
// power on test
|
// power on test
|
||||||
DIAG(F("TRACK %c POWER RESTORE (after %4M)"), trackno + 'A', mslpc);
|
DIAG(F("TRACK %c POWER RESTORE (after %4M)"), trackno + 'A', mslpc);
|
||||||
setPower(POWERMODE::ALERT);
|
setPower(POWERMODE::ALERT);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* © 2022 Chris Harlow
|
* © 2022 Chris Harlow
|
||||||
* © 2022 Harald Barth
|
* © 2022 Harald Barth
|
||||||
|
* © 2023 Colin Murdoch
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of DCC++EX
|
* This file is part of DCC++EX
|
||||||
|
@ -53,7 +54,7 @@ bool TrackManager::progTrackSyncMain=false;
|
||||||
bool TrackManager::progTrackBoosted=false;
|
bool TrackManager::progTrackBoosted=false;
|
||||||
int16_t TrackManager::joinRelay=UNUSED_PIN;
|
int16_t TrackManager::joinRelay=UNUSED_PIN;
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
byte TrackManager::tempProgTrack=MAX_TRACKS+1;
|
byte TrackManager::tempProgTrack=MAX_TRACKS+1; // MAX_TRACKS+1 is the unused flag
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ANALOG_READ_INTERRUPT
|
#ifdef ANALOG_READ_INTERRUPT
|
||||||
|
@ -505,7 +506,12 @@ void TrackManager::setJoin(bool joined) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tempProgTrack != MAX_TRACKS+1) {
|
if (tempProgTrack != MAX_TRACKS+1) {
|
||||||
|
// as setTrackMode with TRACK_MODE_PROG defaults to
|
||||||
|
// power off, we will take the current power state
|
||||||
|
// of our track and then preserve that state.
|
||||||
|
POWERMODE tPTmode = track[tempProgTrack]->getPower(); //get current power status of this track
|
||||||
setTrackMode(tempProgTrack, TRACK_MODE_PROG);
|
setTrackMode(tempProgTrack, TRACK_MODE_PROG);
|
||||||
|
track[tempProgTrack]->setPower(tPTmode); //set track status as it was before
|
||||||
tempProgTrack = MAX_TRACKS+1;
|
tempProgTrack = MAX_TRACKS+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -513,3 +519,10 @@ void TrackManager::setJoin(bool joined) {
|
||||||
progTrackSyncMain=joined;
|
progTrackSyncMain=joined;
|
||||||
if (joinRelay!=UNUSED_PIN) digitalWrite(joinRelay,joined?HIGH:LOW);
|
if (joinRelay!=UNUSED_PIN) digitalWrite(joinRelay,joined?HIGH:LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TrackManager::isPowerOn(byte t) {
|
||||||
|
if (track[t]->getPower()!=POWERMODE::ON)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* © 2022 Chris Harlow
|
* © 2022 Chris Harlow
|
||||||
* © 2022 Harald Barth
|
* © 2022 Harald Barth
|
||||||
|
* © 2023 Colin Murdoch
|
||||||
|
*
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of CommandStation-EX
|
* This file is part of CommandStation-EX
|
||||||
|
@ -77,6 +79,7 @@ class TrackManager {
|
||||||
static void reportCurrent(Print* stream);
|
static void reportCurrent(Print* stream);
|
||||||
static void reportObsoleteCurrent(Print* stream);
|
static void reportObsoleteCurrent(Print* stream);
|
||||||
static void streamTrackState(Print* stream, byte t);
|
static void streamTrackState(Print* stream, byte t);
|
||||||
|
static bool isPowerOn(byte t);
|
||||||
|
|
||||||
static int16_t joinRelay;
|
static int16_t joinRelay;
|
||||||
static bool progTrackSyncMain; // true when prog track is a siding switched to main
|
static bool progTrackSyncMain; // true when prog track is a siding switched to main
|
||||||
|
|
|
@ -219,7 +219,11 @@
|
||||||
// The HAL is disabled by default on Nano and Uno platforms, because of limited flash space.
|
// The HAL is disabled by default on Nano and Uno platforms, because of limited flash space.
|
||||||
//
|
//
|
||||||
#if defined(ARDUINO_AVR_NANO) || defined(ARDUINO_AVR_UNO)
|
#if defined(ARDUINO_AVR_NANO) || defined(ARDUINO_AVR_UNO)
|
||||||
#define IO_NO_HAL
|
#if defined(DISABLE_DIAG) && defined(DISABLE_EEPROM) && defined(DISABLE_PROG)
|
||||||
|
#warning you have sacrificed DIAG for HAL
|
||||||
|
#else
|
||||||
|
#define IO_NO_HAL
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __has_include ( "myAutomation.h")
|
#if __has_include ( "myAutomation.h")
|
||||||
|
|
|
@ -51,7 +51,7 @@ void halSetup() {
|
||||||
// Create a 20x4 LCD display device as display number 2
|
// Create a 20x4 LCD display device as display number 2
|
||||||
// (line 0 is written by EX-RAIL 'SCREEN(2, 0, "text")').
|
// (line 0 is written by EX-RAIL 'SCREEN(2, 0, "text")').
|
||||||
|
|
||||||
// HALDisplay<LiquidCrystal>(2, 0x27, 20, 4);
|
// HALDisplay<LiquidCrystal>::create(2, 0x27, 20, 4);
|
||||||
|
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
|
|
12
version.h
12
version.h
|
@ -3,8 +3,16 @@
|
||||||
|
|
||||||
#include "StringFormatter.h"
|
#include "StringFormatter.h"
|
||||||
|
|
||||||
#define VERSION "5.0.1"
|
#define VERSION "5.1.5"
|
||||||
// 5.0.1 - Check bad AT firmware version
|
// 5.1.5 - Added turntable object and EXRAIL commands
|
||||||
|
// - <I ...>, <JO ...>, <JP ...> - turntable commands
|
||||||
|
// - DCC_TURNTABLE, EXTT_TURNTABLE, IFTTPOSITION, ONROTATE, ROTATE, ROTATE_DCC, TT_ADDPOSITION, WAITFORTT EXRAIL
|
||||||
|
// 5.1.4 - Added ONOVERLOAD & AFTEROVERLOAD to EXRAIL
|
||||||
|
// 5.1.3 - Make parser more fool proof
|
||||||
|
// 5.1.2 - Bugfix: ESP32 30ms off time
|
||||||
|
// 5.1.1 - Check bad AT firmware version
|
||||||
|
// - Update IO_PCA9555.h reflecting IO_MCP23017.h changes to support PCA9548 mux
|
||||||
|
// 5.0.1 - Bugfix: execute 30ms off time before rejoin
|
||||||
// 5.0.0 - Make 4.2.69 the 5.0.0 release
|
// 5.0.0 - Make 4.2.69 the 5.0.0 release
|
||||||
// 4.2.69 - Bugfix: Make <!> work in DC mode
|
// 4.2.69 - Bugfix: Make <!> work in DC mode
|
||||||
// 4.2.68 - Rename track mode OFF to NONE
|
// 4.2.68 - Rename track mode OFF to NONE
|
||||||
|
|
Loading…
Reference in New Issue
Block a user