1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2025-07-28 18:03:45 +02:00

Compare commits

...

30 Commits

Author SHA1 Message Date
Harald Barth
b4dbd439bb ED does not like letters in version string 2024-04-17 13:18:41 +02:00
Harald Barth
cfd04ad5c7 version 2024-04-02 00:03:07 +02:00
Harald Barth
501238d894 ESP32 Bugfix: Uninitialized stack variable. Will bite you with infinite loop if no tracks are defined 2024-04-02 00:02:09 +02:00
Harald Barth
dd2a916c83 version 2024-04-01 22:13:03 +02:00
Harald Barth
d21aef533b Make Z21 diag selectable from DCCEXParser 2024-04-01 22:12:05 +02:00
Harald Barth
7ebbe8bed2 ifdef NetworkClientUDP.h as well 2024-04-01 21:02:20 +02:00
Harald Barth
bbba53f3d1 version 2024-04-01 11:59:16 +02:00
Harald Barth
605d5826dc make Z21 support dependent on ESP32 to compile on all platforms 2024-04-01 11:57:57 +02:00
Harald Barth
e075df7164 Z21 error fix for turnout feedback 2024-04-01 11:10:54 +02:00
Harald Barth
b6a15aa5c3 version 2024-03-25 15:07:33 +01:00
Harald Barth
aacfff2e3d Z21 add turnout and sensor broadcasts 2024-03-25 15:05:14 +01:00
Harald Barth
dad84aed6f version update 2024-03-24 16:45:06 +01:00
Harald Barth
66d59c6a8a Allow no shield 2024-03-24 16:41:47 +01:00
Harald Barth
814d1045ba Z21: report the (unchanged) loco mode back after every attempted change 2024-03-24 16:34:26 +01:00
Harald Barth
bc8ab26b30 Add turnout functionality to Z21 2024-03-24 15:51:40 +01:00
Harald Barth
54e1bdb878 Fix index of DB[] to comply with Roco documentation 2024-03-24 12:18:28 +01:00
Harald Barth
e6dde5a11c add READ_REGISTER name to Z21 parser 2024-03-24 09:33:44 +01:00
Harald Barth
16362c14cc Functions for DC frequency: Use func up to F31 part 2 2024-03-17 06:11:58 +01:00
Harald Barth
900aa254c6 Support up to 31 functions and clean up genration of the LAN_X_HEADER_LOCO_INFO message 2024-03-11 15:46:12 +01:00
Harald Barth
d303831773 Functions for DC frequency: Use func up to F31 2024-03-11 15:09:37 +01:00
Harald Barth
dc78d4518e Merge branch 'devel' into devel-z21 2024-03-11 09:19:28 +01:00
Harald Barth
259452c5ac Merge branch 'devel' into devel-z21 2023-07-09 00:15:48 +02:00
Harald Barth
ddb4993355 version 2023-06-08 23:17:56 +02:00
Harald Barth
4896e6f040 remove unused circular buffer 2023-06-08 22:59:25 +02:00
Harald Barth
800972a57c restructure UDP packet receive 2023-06-08 22:55:45 +02:00
Harald Barth
fb22bcd99d version 2023-06-06 02:07:32 +02:00
Harald Barth
b467f6b7b1 Debug: Do not show heatbeat 2023-06-06 02:06:41 +02:00
Harald Barth
a6612b7f13 make BROADCAST_BASE default 2023-06-06 02:06:06 +02:00
Harald Barth
6f5e65bc02 bigger UDP buffers 2023-06-06 02:05:21 +02:00
Harald Barth
a3274caf49 copy in 2023-06-06 00:50:03 +02:00
19 changed files with 1369 additions and 35 deletions

View File

@@ -32,6 +32,10 @@
#include "TrackManager.h"
#include "StringFormatter.h"
#ifdef Z21_PROTOCOL
#include "Z21Throttle.h"
#endif
// variables to hold clock time
int16_t lastclocktime;
int8_t lastclockrate;
@@ -149,6 +153,9 @@ void CommandDistributor::broadcastToClients(clientType type) {
// Public broadcast functions below
void CommandDistributor::broadcastSensor(int16_t id, bool on ) {
#ifdef Z21_PROTOCOL
Z21Throttle::broadcastNotifySensor(id, on);
#endif
broadcastReply(COMMAND_TYPE, F("<%c %d>\n"), on?'Q':'q', id);
}
@@ -156,6 +163,9 @@ void CommandDistributor::broadcastTurnout(int16_t id, bool isClosed ) {
// For DCC++ classic compatibility, state reported to JMRI is 1 for thrown and 0 for closed;
// The string below contains serial and Withrottle protocols which should
// be safe for both types.
#ifdef Z21_PROTOCOL
Z21Throttle::broadcastNotifyTurnout(id, isClosed);
#endif
broadcastReply(COMMAND_TYPE, F("<H %d %d>\n"),id, !isClosed);
#ifdef CD_HANDLE_RING
broadcastReply(WITHROTTLE_TYPE, F("PTA%c%d\n"), isClosed?'2':'4', id);
@@ -209,9 +219,7 @@ int16_t CommandDistributor::retClockTime() {
void CommandDistributor::broadcastLoco(byte slot) {
DCC::LOCO * sp=&DCC::speedTable[slot];
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);
broadcastReply(COMMAND_TYPE, F("<l %d %d %d %l>\n"), sp->loco,slot,sp->speedCode,sp->functions);
#ifdef SABERTOOTH
if (Serial2 && sp->loco == SABERTOOTH) {
static uint8_t rampingmode = 0;

View File

@@ -219,8 +219,9 @@ bool DCC::setFn( int cab, int16_t functionNumber, bool on) {
} else {
speedTable[reg].functions &= ~funcmask;
}
if (speedTable[reg].functions != previous && functionNumber <= 28) {
updateGroupflags(speedTable[reg].groupFlags, functionNumber);
if (speedTable[reg].functions != previous) {
if (functionNumber <= 28)
updateGroupflags(speedTable[reg].groupFlags, functionNumber);
CommandDistributor::broadcastLoco(reg);
}
return true;
@@ -235,14 +236,14 @@ void DCC::changeFn( int cab, int16_t functionNumber) {
speedTable[reg].functions ^= funcmask;
if (functionNumber <= 28) {
updateGroupflags(speedTable[reg].groupFlags, functionNumber);
CommandDistributor::broadcastLoco(reg);
}
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>28)
if (cab<=0 || functionNumber>31)
return -1; // unknown
int reg = lookupSpeedTable(cab);
if (reg<0)

View File

@@ -283,25 +283,22 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
return; // filterCallback asked us to ignore
case 't': // THROTTLE <t [REGISTER] CAB SPEED DIRECTION>
{
if (params==1) { // <t cab> display state
int16_t slot=DCC::lookupSpeedTable(p[0],false);
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==1) { // <t cab> display state
int16_t slot=DCC::lookupSpeedTable(p[0],false);
if (slot>=0)
CommandDistributor::broadcastLoco(slot);
else // send dummy state speed 0 fwd no functions.
StringFormatter::send(stream,F("<l %d -1 128 0>\n"),p[0]);
return;
}
if (params == 4)
{ // <t REGISTER CAB SPEED DIRECTION>
// ignore register p[0]
cab = p[1];
tspeed = p[2];
direction = p[3];
@@ -1120,6 +1117,21 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[])
return true;
#ifdef HAS_ENOUGH_MEMORY
#ifdef Z21_PROTOCOL
case "Z21THROTTLE"_hk: // <D Z21THROTTLE ON/OFF>
case "Z21THR"_hk: // <D Z21THR ON/OFF>
Diag::Z21THROTTLE = onOff;
return true;
case "Z21THROTTLEVERBOSE"_hk: // <D Z21THROTTLEVERBOSE ON/OFF>
case "Z21THRV"_hk: // <D Z21THV ON/OFF>
Diag::Z21THROTTLEVERBOSE = onOff;
return true;
case "Z21THROTTLEDATA"_hk: // <D Z21THROTTLEDATA ON/OFF>
case "Z21THRD"_hk: // <D Z21THD ON/OFF>
Diag::Z21THROTTLEDATA = onOff;
return true;
#endif // Z21_PROTOCOL
case "WIFI"_hk: // <D WIFI ON/OFF>
Diag::WIFI = onOff;
return true;

View File

@@ -294,7 +294,7 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea
// The resets will be zero not only now but as well repeats packets into the future
clearResets(repeats+1);
{
int ret;
int ret = 0;
do {
if(isMainTrack) {
if (rmtMainChannel != NULL)

View File

@@ -1 +1 @@
#define GITHUB_SHA "devel-202402241957Z"
#define GITHUB_SHA "devel-z21-202404171118Z"

View File

@@ -1,7 +1,7 @@
/*
* © 2022-2023 Paul M. Antoine
* © 2021 Fred Decker
* © 2020-2023 Harald Barth
* © 2020-2024 Harald Barth
* (c) 2020 Chris Harlow. All rights reserved.
* (c) 2021 Fred Decker. All rights reserved.
* (c) 2020 Harald Barth. All rights reserved.
@@ -57,6 +57,10 @@
// 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)

39
NetworkClientUDP.h Normal file
View File

@@ -0,0 +1,39 @@
/*
* © 2024 Harald Barth
* All rights reserved.
*
* This file is part of CommandStation-EX
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* It is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
*/
#ifdef Z21_PROTOCOL
#include <WiFi.h>
#include <WiFiClient.h>
class NetworkClientUDP {
public:
NetworkClientUDP() {
};
bool ok() {
return (inUse);
};
bool inUse = true;
bool connected = false;
IPAddress remoteIP;
int remotePort;
static WiFiUDP client;
};
#endif

View File

@@ -25,6 +25,9 @@ bool Diag::ACK=false;
bool Diag::CMD=false;
bool Diag::WIFI=false;
bool Diag::WITHROTTLE=false;
bool Diag::Z21THROTTLE=false;
bool Diag::Z21THROTTLEVERBOSE=false;
bool Diag::Z21THROTTLEDATA=false;
bool Diag::ETHERNET=false;
bool Diag::LCN=false;

View File

@@ -28,6 +28,9 @@ class Diag {
static bool CMD;
static bool WIFI;
static bool WITHROTTLE;
static bool Z21THROTTLE;
static bool Z21THROTTLEVERBOSE;
static bool Z21THROTTLEDATA;
static bool ETHERNET;
static bool LCN;

View File

@@ -1,6 +1,6 @@
/*
* © 2022 Chris Harlow
* © 2022,2023 Harald Barth
* © 2022-2024 Harald Barth
* © 2023 Colin Murdoch
* All rights reserved.
*
@@ -41,7 +41,7 @@
MotorDriver * TrackManager::track[MAX_TRACKS];
int16_t TrackManager::trackDCAddr[MAX_TRACKS];
byte TrackManager::lastTrack=0;
int8_t TrackManager::lastTrack=-1;
bool TrackManager::progTrackSyncMain=false;
bool TrackManager::progTrackBoosted=false;
int16_t TrackManager::joinRelay=UNUSED_PIN;
@@ -498,7 +498,11 @@ 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];
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 Harald Barth
* © 2022-2024 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,
MotorDriver * track0=NULL,
MotorDriver * track1=NULL,
MotorDriver * track2=NULL,
MotorDriver * track3=NULL,
@@ -108,7 +108,7 @@ class TrackManager {
private:
static void addTrack(byte t, MotorDriver* driver);
static byte lastTrack;
static int8_t lastTrack;
static byte nextCycleTrack;
static void applyDCSpeed(byte t);

View File

@@ -123,7 +123,6 @@
return true;
}
#define DIAG_IO
// Static setClosed function is invoked from close(), throw() etc. to perform the
// common parts of the turnout operation. Code which is specific to a turnout
// type should be placed in the virtual function setClosedInternal(bool) which is

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=29;
int fkeys=32; // upper limit (send functions 0 to 31)
myLocos[loco].functionToggles=1<<2; // F2 (HORN) is a non-toggle
#ifdef EXRAIL_ACTIVE

View File

@@ -30,6 +30,10 @@
#include "RingStream.h"
#include "CommandDistributor.h"
#include "WiThrottle.h"
#ifdef Z21_PROTOCOL
#include "Z21Throttle.h"
#endif
/*
#include "soc/rtc_wdt.h"
#include "esp_task_wdt.h"
@@ -137,6 +141,7 @@ bool WifiESP::setup(const char *SSid,
bool havePassword = true;
bool haveSSID = true;
bool wifiUp = false;
IPAddress localIP;
uint8_t tries = 40;
//#ifdef SERIAL_BT_COMMANDS
@@ -195,7 +200,7 @@ bool WifiESP::setup(const char *SSid,
delay(500);
}
if (WiFi.status() == WL_CONNECTED) {
DIAG(F("Wifi STA IP 2nd try %s"),WiFi.localIP().toString().c_str());
DIAG(F("Wifi STA IP 2nd try %s"),(localIP=WiFi.localIP()).toString().c_str());
wifiUp = true;
} else {
DIAG(F("Wifi STA mode FAIL. Will revert to AP mode"));
@@ -256,9 +261,13 @@ bool WifiESP::setup(const char *SSid,
DIAG(F("Wifi setup failed to add withrottle service to mDNS"));
}
// server for WiThrottle and DCCEX protocol started here
server = new WiFiServer(port); // start listening on tcp port
server->begin();
// server started here
#ifdef Z21_PROTOCOL
// server for Z21 Protocol started here
Z21Throttle::setup(localIP, Z21_UDPPORT);
#endif
#ifdef WIFI_TASK_ON_CORE0
//start loop task
@@ -333,6 +342,9 @@ void WifiESP::loop() {
} // all clients
WiThrottle::loop(outboundRing);
#ifdef Z21_PROTOCOL
Z21Throttle::loop();
#endif
// something to write out?
clientId=outboundRing->read();

1001
Z21Throttle.cpp Normal file

File diff suppressed because it is too large Load Diff

224
Z21Throttle.h Normal file
View File

@@ -0,0 +1,224 @@
/*
* © 2023 Thierry Paris / Locoduino
* © 2023 Harald Barth
* All rights reserved.
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* It is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef Z21Throttle_h
#define Z21Throttle_h
#include "defines.h"
#ifdef Z21_PROTOCOL
//#include "CircularBuffer.hpp"
#include "NetworkClientUDP.h"
#define MAX_MTU 1460
#define UDPBYTE_SIZE 1500
#define UDP_BUFFERSIZE 2048
// Broadcast flags
#define BROADCAST_BASE 0x00000001
#define BROADCAST_RBUS 0x00000002
#define BROADCAST_RAILCOM 0x00000004
#define BROADCAST_SYSTEM 0x00000100
#define BROADCAST_BASE_LOCOINFO 0x00010000
#define BROADCAST_LOCONET 0x01000000
#define BROADCAST_LOCONET_LOCO 0x02000000
#define BROADCAST_LOCONET_SWITCH 0x04000000
#define BROADCAST_LOCONET_DETECTOR 0x08000000
#define BROADCAST_RAILCOM_AUTO 0x00040000
#define BROADCAST_CAN 0x00080000
struct MYLOCOZ21 {
char throttle; //indicates which throttle letter on client, '0' + clientid
int cab; //address of this loco
bool broadcastPending;
uint32_t functionMap;
uint32_t functionToggles;
};
class Z21Throttle {
public:
static void loop();
static Z21Throttle* getOrAddThrottle(int clientId);
static void broadcastNotifyTurnout(uint16_t addr, bool isClosed);
static void broadcastNotifySensor(uint16_t addr, bool state);
static void markForBroadcast(int cab);
static void forget(byte clientId);
static void findUniqThrottle(int id, char *u);
static void setup(IPAddress ip, int port);
void notifyCvNACK(int inCvAddress);
void notifyCvRead(int inCvAddress, int inValue);
bool parse(byte *networkPacket, int len);
static Z21Throttle *readWriteThrottle; // NULL if no throttle is reading or writing a CV...
static int cvAddress;
static int cvValue;
private:
Z21Throttle(int clientId);
~Z21Throttle();
static const int MAX_MY_LOCO=10; // maximum number of locos assigned to a single client
static const int HEARTBEAT_SECONDS=10; // heartbeat at 4secs to provide messaging transport
static const int ESTOP_SECONDS=20; // eStop if no incoming messages for more than 8secs
static Z21Throttle* firstThrottle;
static byte commBuffer[100];
static byte replyBuffer[20];
static char LorS(int cab);
static bool isThrottleInUse(int cab);
static void setSendTurnoutList();
bool areYouUsingThrottle(int cab);
Z21Throttle* nextThrottle;
int clientid;
char uniq[17] = "";
MYLOCOZ21 myLocos[MAX_MY_LOCO];
int CountLocos() {
int count = 0;
for (int loco=0;loco<MAX_MY_LOCO;loco++)
if (myLocos[loco].throttle != '\0')
count++;
return count;
}
bool initSent; // valid connection established
bool exRailSent; // valid connection established
uint16_t mostRecentCab;
int turnoutListHash; // used to check for changes to turnout list
bool lastPowerState; // last power state sent to this client
int32_t broadcastFlags = BROADCAST_BASE;
int getOrAddLoco(int cab);
void printLocomotives(bool addTab = false);
static void printThrottles(bool printLocomotives);
// sizes : [ 2 ][ 2 ][inLengthData]
// bytes : [length1, length2][Header1, Header2][Data........]
bool notify(unsigned int inHeader, byte* inpData, unsigned int inLengthData, bool inXorInData);
// sizes : [ 2 ][ 2 ][ 1 ][inLengthData]
// bytes : [length1, length2][Header1, Header2][XHeader][Data........]
bool notify(unsigned int inHeader, unsigned int inXHeader, byte* inpData, unsigned int inLengthData, bool inXorInData);
// sizes : [ 2 ][ 2 ][ 1 ][ 1 ][inLengthData]
// bytes : [length1, length2][Header1, Header2][XHeader][DB0][Data........]
bool notify(unsigned int inHeader, unsigned int inXHeader, byte inDB0, byte* inpData, unsigned int inLengthData, bool inXorInData);
void notifyStatus();
void notifyLocoInfo(byte inMSB, byte inLSB);
void notifyTurnoutInfo(uint16_t addr, bool isClosed);
void notifyTurnoutInfo(byte inMSB, byte inLSB);
void notifyTurnoutInfo(byte inMSB, byte inLSB, bool isClosed);
void notifySensor(uint16_t addr);
void notifySensor(uint16_t addr, bool state);
void notifyLocoMode(byte inMSB, byte inLSB);
void notifyFirmwareVersion();
void notifyHWInfo();
void write(byte* inpData, int inLengthData);
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);
void cvReadPom(byte inDB1, byte inDB2, byte inDB3, byte inDB4);
// callback stuff to support prog track acquire
static Z21Throttle * stashInstance;
static byte stashClient;
static char stashThrottleChar;
static void getLocoCallback(int16_t locoid);
};
#define Z21_UDPPORT 21105
#define Z21_TIMEOUT 60000 // if no activity during 1 minute, disconnect the throttle...
#define HEADER_LAN_GET_SERIAL_NUMBER 0x10
#define HEADER_LAN_LOGOFF 0x30
#define HEADER_LAN_XPRESS_NET 0x40
#define HEADER_LAN_SET_BROADCASTFLAGS 0x50
#define HEADER_LAN_GET_BROADCASTFLAGS 0x51
#define HEADER_LAN_SYSTEMSTATE_GETDATA 0x85 //0x141 0x21 0x24 0x05
#define HEADER_LAN_GET_HWINFO 0x1A
#define HEADER_LAN_GET_LOCOMODE 0x60
#define HEADER_LAN_SET_LOCOMODE 0x61
#define HEADER_LAN_GET_TURNOUTMODE 0x70
#define HEADER_LAN_SET_TURNOUTMODE 0x71
#define HEADER_LAN_RMBUS_DATACHANGED 0x80
#define HEADER_LAN_RMBUS_GETDATA 0x81
#define HEADER_LAN_RMBUS_PROGRAMMODULE 0x82
#define HEADER_LAN_RAILCOM_DATACHANGED 0x88
#define HEADER_LAN_RAILCOM_GETDATA 0x89
#define HEADER_LAN_LOCONET_DISPATCH_ADDR 0xA3
#define HEADER_LAN_LOCONET_DETECTOR 0xA4
#define LAN_GET_CONFIG 0x12
#define LAN_LOCONET_TYPE_DIGITRAX 0x80
#define LAN_LOCONET_TYPE_UHL_REPORTER 0x81
#define LAN_LOCONET_TYPE_UHL_LISSY 0x82
#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
#define LAN_X_HEADER_SET_LOCO 0xE4
#define LAN_X_HEADER_GET_TURNOUT_INFO 0x43
#define LAN_X_HEADER_SET_TURNOUT 0x53
#define LAN_X_HEADER_CV_READ 0x23
#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
#define LAN_X_DB0_SET_TRACK_POWER_ON 0x81
#define LAN_X_DB0_LOCO_DCC14 0x10
#define LAN_X_DB0_LOCO_DCC28 0x12
#define LAN_X_DB0_LOCO_DCC128 0x13
#define LAN_X_DB0_SET_LOCO_FUNCTION 0xF8
#define LAN_X_DB0_CV_POM_WRITE 0x30
#define LAN_X_DB0_CV_POM_ACCESSORY_WRITE 0x31
#define LAN_X_OPTION_CV_POM_WRITE_BYTE 0xEC
#define LAN_X_OPTION_CV_POM_WRITE_BIT 0xE8
#define LAN_X_OPTION_CV_POM_READ_BYTE 0xE4
// Replies to the controllers
#define HEADER_LAN_SYSTEMSTATE 0x84
#define LAN_X_HEADER_LOCO_INFO 0xEF
#define LAN_X_HEADER_TURNOUT_INFO 0x43
#define LAN_X_HEADER_FIRMWARE_VERSION 0xF3
#define LAN_X_HEADER_CV_NACK 0x61
#define LAN_X_HEADER_CV_RESULT 0x64
#define LAN_X_DB0_CV_NACK_SC 0x12
#define LAN_X_DB0_CV_NACK 0x13
#endif // Z21PROTOCOL
#endif

View File

@@ -300,6 +300,12 @@ The configuration file for DCC-EX Command Station
//
//#define BOOSTER_INPUT 26
// Z21 protocol support
// On ESP32 you have the possibility to use the Z21 app
// and other devices that use the Z21 protocol over IP/UDP.
//
//#define Z21_PROTOCOL
// SABERTOOTH
//
// This is a very special option and only useful if you happen to have a

View File

@@ -157,6 +157,14 @@
#define CPU_TYPE_ERROR
#endif
// Only ESP32 does support the Z21 protocol currently
#ifndef ARDUINO_ARCH_ESP32
#ifdef Z21_PROTOCOL
#warning "Z21 protocol can not be used on this platform, disabling"
#undef Z21_PROTOCOL
#endif
#endif
// replace board type if provided by compiler
#ifdef BOARD_NAME
#undef ARDUINO_TYPE

View File

@@ -3,7 +3,17 @@
#include "StringFormatter.h"
#define VERSION "5.2.38"
#define VERSION "5.99.99"
// Make Z21 diag selectable from DCCEXParser
// Z21 error fix for turnout feedback
// Z21 add turnout and sensor broadcasts
// 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
// 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