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

Compare commits

..

No commits in common. "dad84aed6fcf23b27df8f5447d1d7fd5c4a544f8" and "dc78d4518ee9669b6e48fdef355d465782d474f5" have entirely different histories.

11 changed files with 113 additions and 170 deletions

View File

@ -209,7 +209,9 @@ int16_t CommandDistributor::retClockTime() {
void CommandDistributor::broadcastLoco(byte slot) {
DCC::LOCO * sp=&DCC::speedTable[slot];
broadcastReply(COMMAND_TYPE, F("<l %d %d %d %l>\n"), sp->loco,slot,sp->speedCode,sp->functions);
uint32_t func = sp->functions;
func = func & 0x1fffffff; // mask out bits 0-28
broadcastReply(COMMAND_TYPE, F("<l %d %d %d %l>\n"), sp->loco,slot,sp->speedCode,func);
#ifdef SABERTOOTH
if (Serial2 && sp->loco == SABERTOOTH) {
static uint8_t rampingmode = 0;

View File

@ -219,8 +219,7 @@ bool DCC::setFn( int cab, int16_t functionNumber, bool on) {
} else {
speedTable[reg].functions &= ~funcmask;
}
if (speedTable[reg].functions != previous) {
if (functionNumber <= 28)
if (speedTable[reg].functions != previous && functionNumber <= 28) {
updateGroupflags(speedTable[reg].groupFlags, functionNumber);
CommandDistributor::broadcastLoco(reg);
}
@ -236,14 +235,14 @@ void DCC::changeFn( int cab, int16_t functionNumber) {
speedTable[reg].functions ^= funcmask;
if (functionNumber <= 28) {
updateGroupflags(speedTable[reg].groupFlags, functionNumber);
}
CommandDistributor::broadcastLoco(reg);
}
}
// Report function state (used from withrottle protocol)
// returns 0 false, 1 true or -1 for do not know
int8_t DCC::getFn( int cab, int16_t functionNumber) {
if (cab<=0 || functionNumber>31)
if (cab<=0 || functionNumber>28)
return -1; // unknown
int reg = lookupSpeedTable(cab);
if (reg<0)

View File

@ -283,22 +283,25 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
return; // filterCallback asked us to ignore
case 't': // THROTTLE <t [REGISTER] CAB SPEED DIRECTION>
{
int16_t cab;
int16_t tspeed;
int16_t direction;
if (params==1) { // <t cab> display state
int16_t slot=DCC::lookupSpeedTable(p[0],false);
if (slot>=0)
CommandDistributor::broadcastLoco(slot);
if (slot>=0) {
DCC::LOCO * sp=&DCC::speedTable[slot];
StringFormatter::send(stream,F("<l %d %d %d %l>\n"),
sp->loco,slot,sp->speedCode,sp->functions);
}
else // send dummy state speed 0 fwd no functions.
StringFormatter::send(stream,F("<l %d -1 128 0>\n"),p[0]);
return;
}
int16_t cab;
int16_t tspeed;
int16_t direction;
if (params == 4)
{ // <t REGISTER CAB SPEED DIRECTION>
// ignore register p[0]
cab = p[1];
tspeed = p[2];
direction = p[3];

View File

@ -1 +1 @@
#define GITHUB_SHA "devel-z21-202403241544Z"
#define GITHUB_SHA "devel-z21-202403110817Z"

View File

@ -1,7 +1,7 @@
/*
* © 2022-2023 Paul M. Antoine
* © 2021 Fred Decker
* © 2020-2024 Harald Barth
* © 2020-2023 Harald Barth
* (c) 2020 Chris Harlow. All rights reserved.
* (c) 2021 Fred Decker. All rights reserved.
* (c) 2020 Harald Barth. All rights reserved.
@ -57,10 +57,6 @@
// of the brake pin on the motor bridge is inverted
// (HIGH == release brake)
// You can have a CS wihout any possibility to do any track signal.
// That's strange but possible.
#define NO_SHIELD F("No shield at all")
// Arduino STANDARD Motor Shield, used on different architectures:
#if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_STM32)

View File

@ -1,6 +1,6 @@
/*
* © 2022 Chris Harlow
* © 2022-2024 Harald Barth
* © 2022,2023 Harald Barth
* © 2023 Colin Murdoch
* All rights reserved.
*
@ -41,7 +41,7 @@
MotorDriver * TrackManager::track[MAX_TRACKS];
int16_t TrackManager::trackDCAddr[MAX_TRACKS];
int8_t TrackManager::lastTrack=-1;
byte TrackManager::lastTrack=0;
bool TrackManager::progTrackSyncMain=false;
bool TrackManager::progTrackBoosted=false;
int16_t TrackManager::joinRelay=UNUSED_PIN;
@ -499,10 +499,6 @@ void TrackManager::setTrackPower(TRACK_MODE trackmodeToMatch, POWERMODE powermod
// Set track power for this track, inependent of mode
void TrackManager::setTrackPower(POWERMODE powermode, byte t) {
MotorDriver *driver=track[t];
if (driver == NULL) { // track is not defined at all
DIAG(F("Error: Track %c does not exist"), t+'A');
return;
}
TRACK_MODE trackmode = driver->getMode();
POWERMODE oldpower = driver->getPower();
if (trackmode & TRACK_MODE_NONE) {

View File

@ -1,6 +1,6 @@
/*
* © 2022 Chris Harlow
* © 2022-2024 Harald Barth
* © 2022 Harald Barth
* © 2023 Colin Murdoch
*
* All rights reserved.
@ -46,7 +46,7 @@ const byte TRACK_POWER_1=1, TRACK_POWER_ON=1;
class TrackManager {
public:
static void Setup(const FSH * shieldName,
MotorDriver * track0=NULL,
MotorDriver * track0,
MotorDriver * track1=NULL,
MotorDriver * track2=NULL,
MotorDriver * track3=NULL,
@ -108,7 +108,7 @@ class TrackManager {
private:
static void addTrack(byte t, MotorDriver* driver);
static int8_t lastTrack;
static byte lastTrack;
static byte nextCycleTrack;
static void applyDCSpeed(byte t);

View File

@ -571,7 +571,7 @@ void WiThrottle::sendRoutes(Print* stream) {
void WiThrottle::sendFunctions(Print* stream, byte loco) {
int16_t locoid=myLocos[loco].cab;
int fkeys=32; // upper limit (send functions 0 to 31)
int fkeys=29;
myLocos[loco].functionToggles=1<<2; // F2 (HORN) is a non-toggle
#ifdef EXRAIL_ACTIVE

View File

@ -1,6 +1,6 @@
/*
* © 2023 Thierry Paris / Locoduino
* © 2023,2024 Harald Barth
* © 2023 Harald Barth
* All rights reserved.
*
* This file is part of CommandStation-EX
@ -385,44 +385,50 @@ void Z21Throttle::notifyLocoInfo(byte inMSB, byte inLSB) {
Z21Throttle::replyBuffer[3] = DCC::getThrottleSpeed(locoAddress); // RVVVVVVV R = forward VVVVVVV = speed
if (DCC::getThrottleDirection(locoAddress)) bitSet(Z21Throttle::replyBuffer[3], 7);
uint32_t functionMap = DCC::getFunctionMap(locoAddress);
Z21Throttle::replyBuffer[4] = B00000000; // 0DSLFGHJ D = double traction S = Smartsearch L = F0 F = F4 G = F3 H = F2 J = F1
if (DCC::getFn(locoAddress, 0)) bitSet(Z21Throttle::replyBuffer[4], 4);
if (DCC::getFn(locoAddress, 1)) bitSet(Z21Throttle::replyBuffer[4], 0);
if (DCC::getFn(locoAddress, 2)) bitSet(Z21Throttle::replyBuffer[4], 1);
if (DCC::getFn(locoAddress, 3)) bitSet(Z21Throttle::replyBuffer[4], 2);
if (DCC::getFn(locoAddress, 4)) bitSet(Z21Throttle::replyBuffer[4], 3);
// Byte 4: 0DSLFGHJ
// D = double traction S = Smartsearch L = F0 F = F4 G = F3 H = F2 J = F1
Z21Throttle::replyBuffer[4] = (functionMap >> 1) & 0xF; // function F1 to F5
if (functionMap & 1) // set F0 (Light)
Z21Throttle::replyBuffer[4] += 16;
functionMap >>=5; // shift out the 5 bits which are not needed any more
Z21Throttle::replyBuffer[5] = B00000000; // function F5 to F12 F5 is bit0
if (DCC::getFn(locoAddress, 5)) bitSet(Z21Throttle::replyBuffer[5], 0);
if (DCC::getFn(locoAddress, 6)) bitSet(Z21Throttle::replyBuffer[5], 1);
if (DCC::getFn(locoAddress, 7)) bitSet(Z21Throttle::replyBuffer[5], 2);
if (DCC::getFn(locoAddress, 8)) bitSet(Z21Throttle::replyBuffer[5], 3);
if (DCC::getFn(locoAddress, 9)) bitSet(Z21Throttle::replyBuffer[5], 4);
if (DCC::getFn(locoAddress, 10)) bitSet(Z21Throttle::replyBuffer[5],5);
if (DCC::getFn(locoAddress, 11)) bitSet(Z21Throttle::replyBuffer[5],6);
if (DCC::getFn(locoAddress, 12)) bitSet(Z21Throttle::replyBuffer[5],7);
Z21Throttle::replyBuffer[5] = functionMap & 0xFF; // function F5 to F12; F5 is bit0
functionMap >>=8; // shift out 8 more
Z21Throttle::replyBuffer[6] = functionMap & 0xFF; // function F13 to F20; F13 is bit0
functionMap >>=8; // shift out 8 more
Z21Throttle::replyBuffer[7] = functionMap & 0xFF; // function F21 to F28; F21 is bit0
functionMap >>=8; // shift out 8 more
Z21Throttle::replyBuffer[8] = functionMap & 0xFF; // function F29 to F31; F28 is bit0
Z21Throttle::replyBuffer[6] = B00000000; // function F13 to F20 F13 is bit0
if (DCC::getFn(locoAddress, 13)) bitSet(Z21Throttle::replyBuffer[6], 0);
if (DCC::getFn(locoAddress, 14)) bitSet(Z21Throttle::replyBuffer[6], 1);
if (DCC::getFn(locoAddress, 15)) bitSet(Z21Throttle::replyBuffer[6], 2);
if (DCC::getFn(locoAddress, 16)) bitSet(Z21Throttle::replyBuffer[6], 3);
if (DCC::getFn(locoAddress, 17)) bitSet(Z21Throttle::replyBuffer[6], 4);
if (DCC::getFn(locoAddress, 18)) bitSet(Z21Throttle::replyBuffer[6], 5);
if (DCC::getFn(locoAddress, 19)) bitSet(Z21Throttle::replyBuffer[6], 6);
if (DCC::getFn(locoAddress, 20)) bitSet(Z21Throttle::replyBuffer[6], 7);
notify(HEADER_LAN_XPRESS_NET, LAN_X_HEADER_LOCO_INFO, Z21Throttle::replyBuffer, 9, false);
Z21Throttle::replyBuffer[7] = B00000000; // function F21 to F28 F21 is bit0
if (DCC::getFn(locoAddress, 21)) bitSet(Z21Throttle::replyBuffer[7], 0);
if (DCC::getFn(locoAddress, 22)) bitSet(Z21Throttle::replyBuffer[7], 1);
if (DCC::getFn(locoAddress, 23)) bitSet(Z21Throttle::replyBuffer[7], 2);
if (DCC::getFn(locoAddress, 24)) bitSet(Z21Throttle::replyBuffer[7], 3);
if (DCC::getFn(locoAddress, 25)) bitSet(Z21Throttle::replyBuffer[7], 4);
if (DCC::getFn(locoAddress, 26)) bitSet(Z21Throttle::replyBuffer[7], 5);
if (DCC::getFn(locoAddress, 27)) bitSet(Z21Throttle::replyBuffer[7], 6);
if (DCC::getFn(locoAddress, 28)) bitSet(Z21Throttle::replyBuffer[7], 7);
notify(HEADER_LAN_XPRESS_NET, LAN_X_HEADER_LOCO_INFO, Z21Throttle::replyBuffer, 8, false);
}
void Z21Throttle::notifyTurnoutInfo(byte inMSB, byte inLSB) {
Z21Throttle::replyBuffer[0] = inMSB; // turnout address msb
Z21Throttle::replyBuffer[1] = inLSB; // turnout address lsb
Z21Throttle::replyBuffer[2] = B00000011; // 000000ZZ ZZ : 00 not switched 01 pos1 10 pos2 11 invalid
char c = '?';
uint16_t addr = (inMSB << 8) + inLSB + 1;
Turnout *tt = Turnout::get(addr);
if (tt) { // if the tt does not exist we fall through with replyBuffer set to invalid
if (tt->isClosed()) {
Z21Throttle::replyBuffer[2] = B00000010;
c = 'c';
} else {
Z21Throttle::replyBuffer[2] = B00000001;
c = 't';
}
}
if (Diag::Z21THROTTLE)
DIAG(F("Z21 Throttle %d : Turnoutinfo %d %c"), clientid, addr, c);
Z21Throttle::replyBuffer[2] = B00000000; // 000000ZZ ZZ : 00 not switched 01 pos1 10 pos2 11 invalid
notify(HEADER_LAN_XPRESS_NET, LAN_X_HEADER_TURNOUT_INFO, Z21Throttle::replyBuffer, 3, false);
}
@ -482,30 +488,6 @@ void Z21Throttle::setSpeed(byte inNbSteps, byte inDB1, byte inDB2, byte inDB3) {
notifyLocoInfo(inDB1, inDB2);
}
void Z21Throttle::setTurnout(byte addrMSB, byte addrLSB, byte command) {
// 1000A00P
// A=0 ... Deactivate turnout output
// A=1 ... Activate turnout output
// P=0 ... Select output 1 of the turnout
// P=1 ... Select output 2 of the turnout
// Q=0 ... Execute command immediately
// means that the client (app/mouse) does send activate and deactive
// Q=1 ... From Z21 FW V1.24: Insert turnout command into the queue of Z21
bool queue = (command & B00100000) != 0;
bool activate = (command & B00001000) != 0;
byte output = command & B00000001;
uint16_t addr = (addrMSB << 8) + addrLSB + 1;
if (Diag::Z21THROTTLE) DIAG(F("Z21 Throttle %d : turnout %d cmd 0x%x"), clientid, addr, command);
(void)queue; // We probably do not need to care (as we are a CS that maps to internal
// turnouts and not to accessory commands) about the difference.
if (activate) {
Turnout::setClosed(addr, output == 1);
} // else ignore the deactivate message
notifyTurnoutInfo(addrMSB, addrLSB); // sent for both activate and deactivate
}
//
// TODO Pass through a text message to avoid multi thread locks...
//
@ -641,13 +623,7 @@ void diagPacket(byte *networkPacket, int len) {
bool Z21Throttle::parse(byte *networkPacket, int len) {
bool done = false;
// same names as in Z21 LAN Protocol Specification
byte *DB;
byte *Data;
byte Xheader;
int Header;
byte *p = networkPacket;
int l = len;
@ -660,13 +636,12 @@ bool Z21Throttle::parse(byte *networkPacket, int len) {
}
if (l < 0) {
DIAG(F("ERROR: Xbus data exceeds UDP packet size: l < 0 pos=%d, l=%d"), p-networkPacket, l);
diagPacket(p, len);
diagPacket(networkPacket, len);
return false;
}
if (l > 0 && lengthData < 4) {
DIAG(F("WARNING: Xbus data does not fill UDP packet size: l > 0 pos=%d, l=%d, lengthData=%d"),
p-networkPacket, l, lengthData);
diagPacket(p, len);
DIAG(F("WARNING: Xbus data does not fill UDP packet size: l > 0 pos=%d, l=%d"), p-networkPacket, l);
diagPacket(networkPacket, len);
return true;
}
// length of the data = total length - length of length (!) - length of header
@ -677,36 +652,36 @@ bool Z21Throttle::parse(byte *networkPacket, int len) {
return false;
}
p += 2;
Header = GETINT16(p);
int header = GETINT16(p);
byte Xheader = 0;
p += 2;
// now p is at start of Data, networkPacket + 4
Data = p;
Xheader = Data[0];
DB = Data + 1;
DB = p;
byte DB0 = 0;
int nbLocos = CountLocos();
// set p for next round
p += lengthData;
if (l > 0 && Diag::Z21THROTTLEDATA) DIAG(F("next packet follows at pos=%d"), p-networkPacket);
if (Diag::Z21THROTTLEDATA &&
!((DB[0] == LAN_X_DB0_GET_STATUS) && (Xheader == LAN_X_HEADER_GENERAL)))
DIAG(F("%d <- lengthData:%d Header:0x%02x : 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"),
this->clientid, lengthData, Header,
(lengthData > 0)?Data[0]:0,
(lengthData > 1)?Data[1]:0,
(lengthData > 2)?Data[2]:0,
(lengthData > 3)?Data[3]:0,
(lengthData > 4)?Data[4]:0,
(lengthData > 5)?Data[5]:0,
(lengthData > 6)?Data[6]:0,
(lengthData > 7)?Data[7]:0,
(lengthData > 8)?Data[8]:0,
(lengthData > 9)?Data[9]:0);
if (Diag::Z21THROTTLEDATA && DB[1] != LAN_X_DB0_GET_STATUS)
DIAG(F("%d <- lengthData:%d header:0x%02x : 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"),
this->clientid, lengthData, header,
(lengthData > 0)?DB[0]:0,
(lengthData > 1)?DB[1]:0,
(lengthData > 2)?DB[2]:0,
(lengthData > 3)?DB[3]:0,
(lengthData > 4)?DB[4]:0,
(lengthData > 5)?DB[5]:0,
(lengthData > 6)?DB[6]:0,
(lengthData > 7)?DB[7]:0,
(lengthData > 8)?DB[8]:0,
(lengthData > 9)?DB[9]:0);
if (l > 0 && Diag::Z21THROTTLEDATA) DIAG(F("next packet follows"));
switch (Header) {
switch (header) {
case HEADER_LAN_XPRESS_NET:
Xheader = DB[0];
switch (Xheader) {
case LAN_X_HEADER_GENERAL:
switch (DB[0]) {
DB0 = DB[1];
switch (DB0) {
case LAN_X_DB0_GET_VERSION:
if (Diag::Z21THROTTLEVERBOSE) DIAG(F("%d GET_VERSION"), this->clientid);
break;
@ -744,28 +719,29 @@ bool Z21Throttle::parse(byte *networkPacket, int len) {
done = true;
break;
case LAN_X_HEADER_SET_LOCO:
switch (DB[0]) {
DB0 = DB[1];
switch (DB0) {
case LAN_X_DB0_LOCO_DCC14:
if (Diag::Z21THROTTLEVERBOSE) DIAG(F("%d LOCO DCC 14 SPEED"), this->clientid);
setSpeed(14, DB[1], DB[2], DB[3]);
setSpeed(14, DB[2], DB[3], DB[4]);
done = true;
break;
case LAN_X_DB0_LOCO_DCC28:
if (Diag::Z21THROTTLEVERBOSE) DIAG(F("%d LOCO DCC 28 SPEED"), this->clientid);
setSpeed(28, DB[1], DB[2], DB[3]);
setSpeed(28, DB[2], DB[3], DB[4]);
done = true;
break;
case LAN_X_DB0_LOCO_DCC128:
if (Diag::Z21THROTTLEVERBOSE) DIAG(F("%d LOCO DCC 128 SPEED"), this->clientid);
setSpeed(128, DB[1], DB[2], DB[3]);
setSpeed(128, DB[2], DB[3], DB[4]);
done = true;
break;
case LAN_X_DB0_SET_LOCO_FUNCTION:
if (Diag::Z21THROTTLEVERBOSE) DIAG(F("%d LOCO DCC FUNCTION"), this->clientid);
setFunction(DB[1], DB[2], DB[3]);
setFunction(DB[2], DB[3], DB[4]);
if (Diag::Z21THROTTLE) {
// Debug capacity to print data...
byte function = DB[3];
byte function = DB[4];
bitClear(function, 6);
bitClear(function, 7);
if (function == 12) { // why not ?
@ -778,15 +754,14 @@ bool Z21Throttle::parse(byte *networkPacket, int len) {
}
break;
case LAN_X_HEADER_GET_LOCO_INFO:
// XXX Should we switch(DB[0]) here?
if (Diag::Z21THROTTLEVERBOSE) DIAG(F("%d LOCO INFO: "), this->clientid);
notifyLocoInfo(DB[1], DB[2]);
notifyLocoInfo(DB[2], DB[3]);
done = true;
break;
case LAN_X_HEADER_GET_TURNOUT_INFO:
if (Diag::Z21THROTTLEVERBOSE) DIAG(F("%d TURNOUT INFO "), this->clientid);
notifyTurnoutInfo(DB[0], DB[1]);
notifyTurnoutInfo(DB[1], DB[2]);
done = true;
break;
@ -799,7 +774,7 @@ bool Z21Throttle::parse(byte *networkPacket, int len) {
if (TrackManager::getProgDriver() != NULL) {
if (Diag::Z21THROTTLEVERBOSE) DIAG(F("%d CV READ PROG "), this->clientid);
// DB0 should be 0x11
cvReadProg(DB[1], DB[2]);
cvReadProg(DB[2], DB[3]);
}
else {
//
@ -809,14 +784,14 @@ bool Z21Throttle::parse(byte *networkPacket, int len) {
// If no prog track, read on the main track !
if (Diag::Z21THROTTLEVERBOSE) DIAG(F("%d CV READ MAIN "), this->clientid);
// DB0 should be 0x11
cvReadMain(DB[1], DB[2]);
cvReadMain(DB[2], DB[3]);
}
done = true;
break;
case LAN_X_HEADER_CV_POM:
if (Diag::Z21THROTTLEVERBOSE) DIAG(F("%d CV READ POM"), this->clientid);
// DB0 should be 0x11
cvReadPom(DB[1], DB[2], DB[3], DB[4]);
cvReadPom(DB[2], DB[3], DB[4], DB[5]);
done = true;
break;
case LAN_X_HEADER_CV_WRITE:
@ -825,18 +800,13 @@ bool Z21Throttle::parse(byte *networkPacket, int len) {
done = true;
break;
case LAN_X_HEADER_SET_TURNOUT:
// XXX sent when operating a turnout
if (Diag::Z21THROTTLEVERBOSE) DIAG(F("%d SET TURNOUT "), this->clientid);
setTurnout(DB[0], DB[1], DB[2]);
done = true;
break;
case LAN_X_HEADER_READ_REGISTER:
case 0x22:
break;
}
break;
case HEADER_LAN_SET_BROADCASTFLAGS:
this->broadcastFlags = int32_t(Data[3] << 24 | Data[2] << 16 | Data[1] << 8 | Data[0]);
this->broadcastFlags = int32_t(DB[3] << 24 | DB[2] << 16 | DB[1] << 8 | DB[0]);
if (Diag::Z21THROTTLEDATA) DIAG(F("BROADCAST FLAGS %d : %s %s %s %s %s %s %s %s %s %s %s"), this->clientid,
(this->broadcastFlags & BROADCAST_BASE) ? "BASE " : "" ,
(this->broadcastFlags & BROADCAST_RBUS) ? "RBUS " : "" ,
@ -852,26 +822,14 @@ bool Z21Throttle::parse(byte *networkPacket, int len) {
done = true;
break;
case HEADER_LAN_GET_LOCOMODE:
{
if (Diag::Z21THROTTLEVERBOSE) {
uint16_t addr = (Data[0] << 8) + Data[1];
DIAG(F("%d GET LOCOMODE %d"), this->clientid, addr);
}
notifyLocoMode(Data[0], Data[1]); // big endian here, but resend the same as received, so no problem.
if (Diag::Z21THROTTLEVERBOSE) DIAG(F("%d GET LOCOMODE"), this->clientid);
notifyLocoMode(DB[0], DB[1]); // big endian here, but resend the same as received, so no problem.
done = true;
}
break;
case HEADER_LAN_SET_LOCOMODE:
{
// as we currently can not change loco mode, nothing to do
if (Diag::Z21THROTTLEVERBOSE) {
uint16_t addr = (Data[0] << 8) + Data[1];
DIAG(F("%d SET LOCOMODE %d"), this->clientid, addr);
}
notifyLocoMode(Data[0], Data[1]); // big endian here, but resend the same as received, so no problem.
if (Diag::Z21THROTTLEVERBOSE) DIAG(F("%d SET LOCOMODE"), this->clientid);
done = true;
}
break;
case HEADER_LAN_GET_HWINFO:
if (Diag::Z21THROTTLEVERBOSE) DIAG(F("%d GET HWINFO"), this->clientid);
@ -889,7 +847,6 @@ bool Z21Throttle::parse(byte *networkPacket, int len) {
done = true;
break;
case HEADER_LAN_GET_SERIAL_NUMBER:
// XXX this has been seen, return dummy number
case HEADER_LAN_GET_BROADCASTFLAGS:
case HEADER_LAN_GET_TURNOUTMODE:
case HEADER_LAN_SET_TURNOUTMODE:
@ -904,7 +861,7 @@ bool Z21Throttle::parse(byte *networkPacket, int len) {
}
if (!done) {
if (Diag::Z21THROTTLE) DIAG(F("Z21 Throttle %d : not treated : Header:%x Xheader:%x DB0:%x"), this->clientid, Header, Xheader, DB[0]);
if (Diag::Z21THROTTLE) DIAG(F("Z21 Throttle %d : not treated : header:%x Xheader:%x DB0:%x"), this->clientid, header, Xheader, DB0);
} else {
int newNbLocos = CountLocos();
if (nbLocos != newNbLocos)

View File

@ -145,7 +145,6 @@ class Z21Throttle {
void setSpeed(byte inNbSteps, byte inDB1, byte inDB2, byte inDB3);
void setFunction(byte inDB1, byte inDB2, byte inDB3);
void setTurnout(byte addrMSB, byte addrLSB, byte command);
void cvReadProg(byte inDB1, byte inDB2);
void cvWriteProg(byte inDB1, byte inDB2, byte inDB3);
void cvReadMain(byte inDB1, byte inDB2);
@ -183,7 +182,6 @@ class Z21Throttle {
#define LAN_GET_CONFIG 0x12
#define LAN_X_HEADER_GENERAL 0x21
#define LAN_X_HEADER_READ_REGISTER 0x22
#define LAN_X_HEADER_SET_STOP 0x80
#define LAN_X_HEADER_GET_FIRMWARE_VERSION 0xF1 //0x141 0x21 0x21 0x00
#define LAN_X_HEADER_GET_LOCO_INFO 0xE3
@ -194,7 +192,6 @@ class Z21Throttle {
#define LAN_X_HEADER_CV_WRITE 0x24
#define LAN_X_HEADER_CV_POM 0xE6
#define LAN_X_DB0_READ_REGISTER 0x11
#define LAN_X_DB0_GET_VERSION 0x21
#define LAN_X_DB0_GET_STATUS 0x24
#define LAN_X_DB0_SET_TRACK_POWER_OFF 0x80

View File

@ -3,14 +3,7 @@
#include "StringFormatter.h"
#define VERSION "5.X.Y"
// Z21: report the (unchanged) loco mode back after every attempted change
// Add turnout functionality to Z21
// Fix index of DB[] to comply with Roco documentation
// add READ_REGISTER name to Z21 parser
//
// 5.2.40 - Allow no shield
// 5.2.39 - Functions for DC frequency: Use func up to F31
#define VERSION "5.2.38"
// 5.2.38 - Exrail MESSAGE("text") to send a user message to all
// connected throttles (uses <m "text"> and withrottle Hmtext.
// 5.2.37 - Bugfix ESP32: Use BOOSTER_INPUT define