mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-07-28 18:03:45 +02:00
Compare commits
30 Commits
v5.5.37-De
...
devel-z21
Author | SHA1 | Date | |
---|---|---|---|
|
b4dbd439bb | ||
|
cfd04ad5c7 | ||
|
501238d894 | ||
|
dd2a916c83 | ||
|
d21aef533b | ||
|
7ebbe8bed2 | ||
|
bbba53f3d1 | ||
|
605d5826dc | ||
|
e075df7164 | ||
|
b6a15aa5c3 | ||
|
aacfff2e3d | ||
|
dad84aed6f | ||
|
66d59c6a8a | ||
|
814d1045ba | ||
|
bc8ab26b30 | ||
|
54e1bdb878 | ||
|
e6dde5a11c | ||
|
16362c14cc | ||
|
900aa254c6 | ||
|
d303831773 | ||
|
dc78d4518e | ||
|
259452c5ac | ||
|
ddb4993355 | ||
|
4896e6f040 | ||
|
800972a57c | ||
|
fb22bcd99d | ||
|
b467f6b7b1 | ||
|
a6612b7f13 | ||
|
6f5e65bc02 | ||
|
a3274caf49 |
@@ -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;
|
||||
|
9
DCC.cpp
9
DCC.cpp
@@ -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)
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
|
@@ -1 +1 @@
|
||||
#define GITHUB_SHA "devel-202402241957Z"
|
||||
#define GITHUB_SHA "devel-z21-202404171118Z"
|
||||
|
@@ -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
39
NetworkClientUDP.h
Normal 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
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
1001
Z21Throttle.cpp
Normal file
File diff suppressed because it is too large
Load Diff
224
Z21Throttle.h
Normal file
224
Z21Throttle.h
Normal 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
|
@@ -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
|
||||
|
@@ -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
|
||||
|
12
version.h
12
version.h
@@ -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
|
||||
|
Reference in New Issue
Block a user