Date: Tue, 14 Nov 2023 00:05:18 +0100
Subject: [PATCH 25/64] Trackmanager rework for simpler structure
---
CommandDistributor.cpp | 5 ++
DCCEXParser.cpp | 147 ++++++++++++-----------------------------
EXRAIL2.cpp | 4 +-
MotorDriver.h | 3 +-
TrackManager.cpp | 115 +++++++++++++++++++-------------
TrackManager.h | 15 ++---
6 files changed, 126 insertions(+), 163 deletions(-)
diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp
index cd9e89e..89c8714 100644
--- a/CommandDistributor.cpp
+++ b/CommandDistributor.cpp
@@ -248,6 +248,11 @@ void CommandDistributor::broadcastLoco(byte slot) {
}
void CommandDistributor::broadcastPower() {
+ char pstr[] = "? x";
+ for(byte t=0; t<8; t++)
+ if (TrackManager::getPower(t, pstr))
+ broadcastReply(COMMAND_TYPE, F("\n"),pstr);
+
bool main=TrackManager::getMainPower()==POWERMODE::ON;
bool prog=TrackManager::getProgPower()==POWERMODE::ON;
bool join=TrackManager::isJoined();
diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp
index 96596c6..3b91d86 100644
--- a/DCCEXParser.cpp
+++ b/DCCEXParser.cpp
@@ -553,131 +553,66 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
case '1': // POWERON <1 [MAIN|PROG|JOIN]>
{
- bool main=false;
- bool prog=false;
- bool join=false;
- bool singletrack=false;
- //byte t=0;
- if (params > 1) break;
- if (params==0) { // All
- main=true;
- prog=true;
- }
- if (params==1) {
- if (p[0]==HASH_KEYWORD_MAIN) { // <1 MAIN>
- main=true;
+ if (params > 1) break;
+ if (params==0) { // All
+ TrackManager::setTrackPower(TRACK_MODE_ALL, POWERMODE::ON);
+ }
+ if (params==1) {
+ if (p[0]==HASH_KEYWORD_MAIN) { // <1 MAIN>
+ TrackManager::setTrackPower(TRACK_MODE_MAIN, POWERMODE::ON);
}
#ifndef DISABLE_PROG
else if (p[0] == HASH_KEYWORD_JOIN) { // <1 JOIN>
- main=true;
- prog=true;
- join=true;
+ TrackManager::setJoin(true);
+ TrackManager::setTrackPower(TRACK_MODE_MAIN|TRACK_MODE_PROG, POWERMODE::ON);
}
else if (p[0]==HASH_KEYWORD_PROG) { // <1 PROG>
- prog=true;
+ TrackManager::setJoin(false);
+ TrackManager::setTrackPower(TRACK_MODE_PROG, POWERMODE::ON);
}
#endif
- //else if (p[0] >= 'A' && p[0] <= 'H') { // <1 A-H>
else if (p[0] >= HASH_KEYWORD_A && p[0] <= HASH_KEYWORD_H) { // <1 A-H>
- byte t = (p[0] - 'A');
- //DIAG(F("Processing track - %d "), t);
- if (TrackManager::isProg(t)) {
- main = false;
- prog = true;
- }
- else
- {
- main=true;
- prog=false;
- }
- singletrack=true;
- if (main) TrackManager::setTrackPower(false, false, POWERMODE::ON, t);
- if (prog) TrackManager::setTrackPower(true, false, POWERMODE::ON, t);
-
- StringFormatter::send(stream, F("<1 %c>\n"), t+'A');
- //CommandDistributor::broadcastPower();
- //TrackManager::streamTrackState(NULL,t);
- return;
+ byte t = (p[0] - 'A');
+ TrackManager::setTrackPower(POWERMODE::ON, t);
+ //StringFormatter::send(stream, F("\n"), t+'A');
}
-
else break; // will reply
- }
-
- if (!singletrack) {
- TrackManager::setJoin(join);
- if (join) TrackManager::setJoinPower(POWERMODE::ON);
- else {
- if (main) TrackManager::setMainPower(POWERMODE::ON);
- if (prog) TrackManager::setProgPower(POWERMODE::ON);
- }
- CommandDistributor::broadcastPower();
+ }
+ CommandDistributor::broadcastPower();
+ //TrackManager::streamTrackState(NULL,t);
- return;
- }
+ return;
+ }
- }
-
case '0': // POWEROFF <0 [MAIN | PROG] >
{
- bool main=false;
- bool prog=false;
- bool singletrack=false;
- //byte t=0;
- if (params > 1) break;
- if (params==0) { // All
- main=true;
- prog=true;
- }
- if (params==1) {
- if (p[0]==HASH_KEYWORD_MAIN) { // <0 MAIN>
- main=true;
- }
+ if (params > 1) break;
+ if (params==0) { // All
+ TrackManager::setJoin(false);
+ TrackManager::setTrackPower(TRACK_MODE_ALL, POWERMODE::OFF);
+ }
+ if (params==1) {
+ if (p[0]==HASH_KEYWORD_MAIN) { // <0 MAIN>
+ TrackManager::setJoin(false);
+ TrackManager::setTrackPower(TRACK_MODE_MAIN, POWERMODE::OFF);
+ }
#ifndef DISABLE_PROG
else if (p[0]==HASH_KEYWORD_PROG) { // <0 PROG>
- prog=true;
+ TrackManager::progTrackBoosted=false; // Prog track boost mode will not outlive prog track off
+ TrackManager::setTrackPower(TRACK_MODE_PROG, POWERMODE::OFF);
}
#endif
- //else if (p[0] >= 'A' && p[0] <= 'H') { // <1 A-H>
- else if (p[0] >= HASH_KEYWORD_A && p[0] <= HASH_KEYWORD_H) { // <1 A-H>
- byte t = (p[0] - 'A');
- //DIAG(F("Processing track - %d "), t);
- if (TrackManager::isProg(t)) {
- main = false;
- prog = true;
- }
- else
- {
- main=true;
- prog=false;
- }
- singletrack=true;
- TrackManager::setJoin(false);
- if (main) TrackManager::setTrackPower(false, false, POWERMODE::OFF, t);
- if (prog) {
- TrackManager::progTrackBoosted=false; // Prog track boost mode will not outlive prog track off
- TrackManager::setTrackPower(true, false, POWERMODE::OFF, t);
- }
- StringFormatter::send(stream, F("<0 %c>\n"), t+'A');
- //CommandDistributor::broadcastPower();
- //TrackManager::streamTrackState(NULL, t);
- return;
- }
-
- else break; // will reply
+ else if (p[0] >= HASH_KEYWORD_A && p[0] <= HASH_KEYWORD_H) { // <1 A-H>
+ byte t = (p[0] - 'A');
+ TrackManager::setJoin(false);
+ TrackManager::setTrackPower(POWERMODE::OFF, t);
+ //StringFormatter::send(stream, F("\n"), t+'A');
}
-
- if (!singletrack) {
- TrackManager::setJoin(false);
-
- if (main) TrackManager::setMainPower(POWERMODE::OFF);
- if (prog) {
- TrackManager::progTrackBoosted=false; // Prog track boost mode will not outlive prog track off
- TrackManager::setProgPower(POWERMODE::OFF);
- }
- CommandDistributor::broadcastPower();
- return;
- }
- }
+ else break; // will reply
+ }
+ CommandDistributor::broadcastPower();
+ return;
+ }
case '!': // ESTOP ALL
DCC::setThrottle(0,1,1); // this broadcasts speed 1(estop) and sets all reminders to speed 1.
diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp
index 8e6a6b5..933650c 100644
--- a/EXRAIL2.cpp
+++ b/EXRAIL2.cpp
@@ -636,10 +636,10 @@ void RMFT2::loop2() {
//byte thistrack=getOperand(1);
switch (operand) {
case TRACK_POWER_0:
- TrackManager::setTrackPower(TrackManager::isProg(getOperand(1)), false, POWERMODE::OFF, getOperand(1));
+ TrackManager::setTrackPower(POWERMODE::OFF, getOperand(1));
break;
case TRACK_POWER_1:
- TrackManager::setTrackPower(TrackManager::isProg(getOperand(1)), false, POWERMODE::ON, getOperand(1));
+ TrackManager::setTrackPower(POWERMODE::ON, getOperand(1));
break;
}
diff --git a/MotorDriver.h b/MotorDriver.h
index db2ccc5..19bfd13 100644
--- a/MotorDriver.h
+++ b/MotorDriver.h
@@ -35,7 +35,8 @@ template inline T operator& (T a, T b) { return (T)((int)a & (int)b); }
template inline T operator^ (T a, T b) { return (T)((int)a ^ (int)b); }
enum TRACK_MODE : byte {TRACK_MODE_NONE = 1, TRACK_MODE_MAIN = 2, TRACK_MODE_PROG = 4,
TRACK_MODE_DC = 8, TRACK_MODE_EXT = 16, TRACK_MODE_BOOST = 32,
- TRACK_MODE_INV = 64, TRACK_MODE_DCX = 72, TRACK_MODE_AUTOINV = 128};
+ TRACK_MODE_ALL = 62, // only to operate all tracks
+ TRACK_MODE_INV = 64, TRACK_MODE_DCX = 72 /*DC + INV*/, TRACK_MODE_AUTOINV = 128};
#define setHIGH(fastpin) *fastpin.inout |= fastpin.maskHIGH
#define setLOW(fastpin) *fastpin.inout &= fastpin.maskLOW
diff --git a/TrackManager.cpp b/TrackManager.cpp
index 8cdadb2..ff56001 100644
--- a/TrackManager.cpp
+++ b/TrackManager.cpp
@@ -471,51 +471,48 @@ std::vectorTrackManager::getMainDrivers() {
}
#endif
-void TrackManager::setPower2(bool setProg,bool setJoin, POWERMODE mode) {
- if (!setProg) mainPowerGuess=mode;
- FOR_EACH_TRACK(t) {
-
- TrackManager::setTrackPower(setProg, setJoin, mode, t);
-
- }
- return;
-}
-
-void TrackManager::setTrackPower(bool setProg, bool setJoin, POWERMODE mode, byte thistrack) {
-
- //DIAG(F("SetTrackPower Processing Track %d"), thistrack);
- MotorDriver * driver=track[thistrack];
- if (!driver) return;
-
- TRACK_MODE tm = track[thistrack]->getMode();
- if ( (tm & TRACK_MODE_MAIN)
- && !setProg ){
- // toggle brake before turning power on - resets overcurrent error
- // on the Pololu board if brake is wired to ^D2.
- // XXX see if we can make this conditional
- driver->setBrake(true);
- driver->setBrake(false); // DCC runs with brake off
- driver->setPower(mode);
- } else if ( (tm & TRACK_MODE_DC)
- && !(setProg || setJoin)){
- //DIAG(F("Processing track - %d setProg %d"), thistrack, setProg);
- driver->setBrake(true); // DC starts with brake on
- applyDCSpeed(thistrack); // speed match DCC throttles
- driver->setPower(mode);
- } else if ( (tm & TRACK_MODE_PROG)
- && (setProg || setJoin) ){
- driver->setBrake(true);
- driver->setBrake(false);
- driver->setPower(mode);
- } else if ( (tm & TRACK_MODE_EXT)
- || (tm & TRACK_MODE_BOOST)){
- driver->setBrake(true);
- driver->setBrake(false);
- driver->setPower(mode);
+// Set track power for all tracks with this mode
+void TrackManager::setTrackPower(TRACK_MODE trackmode, POWERMODE powermode) {
+ FOR_EACH_TRACK(t) {
+ MotorDriver *driver=track[t];
+ if (trackmode & driver->getMode()) {
+ if (powermode == POWERMODE::ON) {
+ if (trackmode & TRACK_MODE_DC) {
+ driver->setBrake(true); // DC starts with brake on
+ applyDCSpeed(t); // speed match DCC throttles
+ } else {
+ // toggle brake before turning power on - resets overcurrent error
+ // on the Pololu board if brake is wired to ^D2.
+ driver->setBrake(true);
+ driver->setBrake(false); // DCC runs with brake off
+ }
}
+ driver->setPower(powermode);
+ }
+ }
}
- void TrackManager::reportPowerChange(Print* stream, byte thistrack) {
+// Set track power for this track, inependent of mode
+void TrackManager::setTrackPower(POWERMODE powermode, byte t) {
+ MotorDriver *driver=track[t];
+ TRACK_MODE trackmode = driver->getMode();
+ if (trackmode & TRACK_MODE_DC) {
+ if (powermode == POWERMODE::ON) {
+ driver->setBrake(true); // DC starts with brake on
+ applyDCSpeed(t); // speed match DCC throttles
+ }
+ } else {
+ if (powermode == POWERMODE::ON) {
+ // toggle brake before turning power on - resets overcurrent error
+ // on the Pololu board if brake is wired to ^D2.
+ driver->setBrake(true);
+ driver->setBrake(false); // DCC runs with brake off
+ }
+ }
+ driver->setPower(powermode);
+}
+
+void TrackManager::reportPowerChange(Print* stream, byte thistrack) {
// This function is for backward JMRI compatibility only
// It reports the first track only, as main, regardless of track settings.
//
@@ -524,12 +521,38 @@ void TrackManager::setTrackPower(bool setProg, bool setJoin, POWERMODE mode, byt
track[0]->raw2mA(track[0]->getCurrentRaw(false)), maxCurrent, maxCurrent);
}
+// returns state of the one and only prog track
POWERMODE TrackManager::getProgPower() {
- FOR_EACH_TRACK(t)
- if (track[t]->getMode() & TRACK_MODE_PROG)
- return track[t]->getPower();
- return POWERMODE::OFF;
+ FOR_EACH_TRACK(t)
+ if (track[t]->getMode() & TRACK_MODE_PROG)
+ return track[t]->getPower(); // optimize: there is max one prog track
+ return POWERMODE::OFF;
+}
+
+// returns on if all are on. returns off otherwise
+POWERMODE TrackManager::getMainPower() {
+ POWERMODE result = POWERMODE::OFF;
+ FOR_EACH_TRACK(t) {
+ if (track[t]->getMode() & TRACK_MODE_MAIN) {
+ POWERMODE p = track[t]->getPower();
+ if (p == POWERMODE::OFF)
+ return POWERMODE::OFF; // done and out
+ if (p == POWERMODE::ON)
+ result = POWERMODE::ON;
+ }
}
+ return result;
+}
+
+bool TrackManager::getPower(byte t, char s[]) {
+ if (track[t]) {
+ s[0] = track[t]->getPower() == POWERMODE::ON ? '1' : '0';
+ s[2] = t + 'A';
+ return true;
+ }
+ return false;
+}
+
void TrackManager::reportObsoleteCurrent(Print* stream) {
// This function is for backward JMRI compatibility only
diff --git a/TrackManager.h b/TrackManager.h
index d1edca2..644c45a 100644
--- a/TrackManager.h
+++ b/TrackManager.h
@@ -62,23 +62,22 @@ class TrackManager {
static void setDCSignal(int16_t cab, byte speedbyte);
static MotorDriver * getProgDriver();
#ifdef ARDUINO_ARCH_ESP32
- static std::vectorgetMainDrivers();
+ static std::vectorgetMainDrivers();
#endif
- static void setPower2(bool progTrack,bool joinTrack,POWERMODE mode);
static void setPower(POWERMODE mode) {setMainPower(mode); setProgPower(mode);}
- static void setMainPower(POWERMODE mode) {setPower2(false,false,mode);}
- static void setProgPower(POWERMODE mode) {setPower2(true,false,mode);}
- static void setJoinPower(POWERMODE mode) {setPower2(false,true,mode);}
- static void setTrackPower(bool setProg, bool setJoin, POWERMODE mode, byte thistrack);
-
+ static void setTrackPower(POWERMODE mode, byte t);
+ static void setTrackPower(TRACK_MODE trackmode, POWERMODE powermode);
+ static void setMainPower(POWERMODE mode) {setTrackPower(TRACK_MODE_MAIN, mode);}
+ static void setProgPower(POWERMODE mode) {setTrackPower(TRACK_MODE_PROG, mode);}
static const int16_t MAX_TRACKS=8;
static bool setTrackMode(byte track, TRACK_MODE mode, int16_t DCaddr=0);
static bool parseJ(Print * stream, int16_t params, int16_t p[]);
static void loop();
- static POWERMODE getMainPower() {return mainPowerGuess;}
+ static POWERMODE getMainPower();
static POWERMODE getProgPower();
+ static bool getPower(byte t, char s[]);
static void setJoin(bool join);
static bool isJoined() { return progTrackSyncMain;}
static void setJoinRelayPin(byte joinRelayPin);
From 503378f1bbee6d8bb55d60ae3728a2b60f6a908b Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Tue, 14 Nov 2023 00:06:53 +0100
Subject: [PATCH 26/64] version 5.2.1
---
GITHUB_SHA.h | 2 +-
version.h | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h
index 867619e..71069ca 100644
--- a/GITHUB_SHA.h
+++ b/GITHUB_SHA.h
@@ -1 +1 @@
-#define GITHUB_SHA "devel-202311110712Z"
+#define GITHUB_SHA "devel-202311132306Z"
diff --git a/version.h b/version.h
index 4258cf4..5640feb 100644
--- a/version.h
+++ b/version.h
@@ -3,7 +3,8 @@
#include "StringFormatter.h"
-#define VERSION "5.2.0"
+#define VERSION "5.2.1"
+// 5.2.1 - Trackmanager rework for simpler structure
// 5.2.0 - ESP32: Autoreverse and booster mode support
// 5.1.21 - EXRAIL invoke multiple ON handlers for same event
// 5.1.20 - EXRAIL Tidy and ROUTE_STATE, ROUTE_CAPTION
From 763ef8be34743835308ad7eaad31a1d59db8b471 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Tue, 14 Nov 2023 11:12:14 +0100
Subject: [PATCH 27/64] prettier MAX_TRACKS
---
CommandDistributor.cpp | 2 +-
TrackManager.cpp | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp
index 89c8714..4269492 100644
--- a/CommandDistributor.cpp
+++ b/CommandDistributor.cpp
@@ -249,7 +249,7 @@ void CommandDistributor::broadcastLoco(byte slot) {
void CommandDistributor::broadcastPower() {
char pstr[] = "? x";
- for(byte t=0; t<8; t++)
+ for(byte t=0; t\n"),pstr);
diff --git a/TrackManager.cpp b/TrackManager.cpp
index ff56001..7c1e651 100644
--- a/TrackManager.cpp
+++ b/TrackManager.cpp
@@ -526,7 +526,7 @@ POWERMODE TrackManager::getProgPower() {
FOR_EACH_TRACK(t)
if (track[t]->getMode() & TRACK_MODE_PROG)
return track[t]->getPower(); // optimize: there is max one prog track
- return POWERMODE::OFF;
+ return POWERMODE::OFF;
}
// returns on if all are on. returns off otherwise
@@ -545,6 +545,8 @@ POWERMODE TrackManager::getMainPower() {
}
bool TrackManager::getPower(byte t, char s[]) {
+ if (t > lastTrack)
+ return false;
if (track[t]) {
s[0] = track[t]->getPower() == POWERMODE::ON ? '1' : '0';
s[2] = t + 'A';
From 1af5132e6aca4dea56636ba5df9f2533d538f17a Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Tue, 14 Nov 2023 11:16:54 +0100
Subject: [PATCH 28/64] version 5.2.1 timestamp
---
GITHUB_SHA.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h
index 71069ca..3f9b1e1 100644
--- a/GITHUB_SHA.h
+++ b/GITHUB_SHA.h
@@ -1 +1 @@
-#define GITHUB_SHA "devel-202311132306Z"
+#define GITHUB_SHA "devel-202311141013Z"
From 566ce1b7f80066d92e1873ad091ef221ccb11d9d Mon Sep 17 00:00:00 2001
From: Asbelos
Date: Tue, 14 Nov 2023 19:41:05 +0000
Subject: [PATCH 29/64] Virtual LCD phase 1
---
CommandDistributor.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++
CommandDistributor.h | 9 +++++++-
DCCEXParser.cpp | 6 +++++-
StringFormatter.cpp | 17 +++++++++++++++
StringFormatter.h | 1 -
5 files changed, 79 insertions(+), 3 deletions(-)
diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp
index 351a18d..788e4e6 100644
--- a/CommandDistributor.cpp
+++ b/CommandDistributor.cpp
@@ -105,6 +105,7 @@ void CommandDistributor::parse(byte clientId,byte * buffer, RingStream * stream
void CommandDistributor::forget(byte clientId) {
if (clients[clientId]==WITHROTTLE_TYPE) WiThrottle::forget(clientId);
clients[clientId]=NONE_TYPE;
+ if (virtualLCDClient==clientId) virtualLCDClient=RingStream::NO_CLIENT;
}
#endif
@@ -280,3 +281,51 @@ void CommandDistributor::broadcastRouteState(uint16_t routeId, byte state ) {
void CommandDistributor::broadcastRouteCaption(uint16_t routeId, const FSH* caption ) {
broadcastReply(COMMAND_TYPE, F("\n"),routeId,caption);
}
+
+Print * CommandDistributor::getVirtualLCDSerial(byte screen, byte row) {
+ Print * stream=virtualLCDSerial;
+ #ifdef CD_HANDLE_RING
+ rememberVLCDClient=RingStream::NO_CLIENT;
+ if (!stream && virtualLCDClient!=RingStream::NO_CLIENT) {
+ // If we are broadcasting from a wifi/eth process we need to complete its output
+ // before merging broadcasts in the ring, then reinstate it in case
+ // the process continues to output to its client.
+ if ((rememberVLCDClient = ring->peekTargetMark()) != RingStream::NO_CLIENT) {
+ ring->commit();
+ }
+ ring->mark(virtualLCDClient);
+ stream=ring;
+ }
+ #endif
+ if (stream) StringFormatter::send(stream,F("<@ %d %d \""), screen,row);
+ return stream;
+}
+
+void CommandDistributor::commitVirtualLCDSerial() {
+ #ifdef CD_HANDLE_RING
+ if (virtualLCDClient!=RingStream::NO_CLIENT) {
+ StringFormatter::send(ring,F("\">\n"));
+ ring->commit();
+ if (rememberVLCDClient!=RingStream::NO_CLIENT) ring->mark(rememberVLCDClient);
+ return;
+ }
+ #endif
+ StringFormatter::send(virtualLCDSerial,F("\">\n"));
+}
+
+void CommandDistributor::setVirtualLCDSerial(Print * stream) {
+ #ifdef CD_HANDLE_RING
+ virtualLCDClient=RingStream::NO_CLIENT;
+ if (stream && stream->availableForWrite()==RingStream::THIS_IS_A_RINGSTREAM) {
+ virtualLCDClient=((RingStream *) stream)->peekTargetMark();
+ virtualLCDSerial=nullptr;
+ return;
+ }
+ #endif
+ virtualLCDSerial=stream;
+}
+
+Print* CommandDistributor::virtualLCDSerial=nullptr;
+byte CommandDistributor::virtualLCDClient=0xFF;
+byte CommandDistributor::rememberVLCDClient=0;
+
diff --git a/CommandDistributor.h b/CommandDistributor.h
index 83bfbbd..359c0fe 100644
--- a/CommandDistributor.h
+++ b/CommandDistributor.h
@@ -60,8 +60,15 @@ public :
static void forget(byte clientId);
static void broadcastRouteState(uint16_t routeId,byte state);
static void broadcastRouteCaption(uint16_t routeId,const FSH * caption);
-
+ // Handling code for virtual LCD receiver.
+ static Print * getVirtualLCDSerial(byte screen, byte row);
+ static void commitVirtualLCDSerial();
+ static void setVirtualLCDSerial(Print * stream);
+ private:
+ static Print * virtualLCDSerial;
+ static byte virtualLCDClient;
+ static byte rememberVLCDClient;
};
#endif
diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp
index 96596c6..369d941 100644
--- a/DCCEXParser.cpp
+++ b/DCCEXParser.cpp
@@ -724,7 +724,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
return;
break;
#endif
- case '=': // TACK MANAGER CONTROL <= [params]>
+ case '=': // TRACK MANAGER CONTROL <= [params]>
if (TrackManager::parseJ(stream, params, p))
return;
break;
@@ -897,6 +897,10 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
case 'L': // LCC interface implemented in EXRAIL parser
break; // Will if not intercepted by EXRAIL
+ case '@': // JMRI saying "give me virtual LCD msgs"
+ CommandDistributor::setVirtualLCDSerial(stream);
+ return;
+
default: //anything else will diagnose and drop out to
DIAG(F("Opcode=%c params=%d"), opcode, params);
for (int i = 0; i < params; i++)
diff --git a/StringFormatter.cpp b/StringFormatter.cpp
index b40de1c..218e617 100644
--- a/StringFormatter.cpp
+++ b/StringFormatter.cpp
@@ -19,6 +19,7 @@
#include "StringFormatter.h"
#include
#include "DisplayInterface.h"
+#include "CommandDistributor.h"
bool Diag::ACK=false;
bool Diag::CMD=false;
@@ -45,6 +46,14 @@ void StringFormatter::lcd(byte row, const FSH* input...) {
send2(&USB_SERIAL,input,args);
send(&USB_SERIAL,F(" *>\n"));
+ // send to virtual LCD collector (if any)
+ Print * virtualLCD=CommandDistributor::getVirtualLCDSerial(0,row);
+ if (virtualLCD) {
+ va_start(args, input);
+ send2(virtualLCD,input,args);
+ CommandDistributor::commitVirtualLCDSerial();
+ }
+
DisplayInterface::setRow(row);
va_start(args, input);
send2(DisplayInterface::getDisplayHandler(),input,args);
@@ -52,6 +61,14 @@ void StringFormatter::lcd(byte row, const FSH* input...) {
void StringFormatter::lcd2(uint8_t display, byte row, const FSH* input...) {
va_list args;
+
+ // send to virtual LCD collector (if any)
+ Print * virtualLCD=CommandDistributor::getVirtualLCDSerial(display,row);
+ if (virtualLCD) {
+ va_start(args, input);
+ send2(virtualLCD,input,args);
+ CommandDistributor::commitVirtualLCDSerial();
+ }
DisplayInterface::setRow(display, row);
va_start(args, input);
diff --git a/StringFormatter.h b/StringFormatter.h
index 1231d54..25d15e2 100644
--- a/StringFormatter.h
+++ b/StringFormatter.h
@@ -54,6 +54,5 @@ class StringFormatter
private:
static void send2(Print * serial, const FSH* input,va_list args);
static void printPadded(Print* stream, long value, byte width, bool formatLeft);
-
};
#endif
From 6da3153dd5d1b7dfa218727d64153f4aed572b97 Mon Sep 17 00:00:00 2001
From: Colin Murdoch
Date: Wed, 15 Nov 2023 19:29:24 +0000
Subject: [PATCH 30/64] Define scroll rows in config
Allow the definition of MAX_CHARACTER_ROWS in config.h
---
Display.h | 2 ++
config.example.h | 8 ++++++++
2 files changed, 10 insertions(+)
diff --git a/Display.h b/Display.h
index af36d43..467424f 100644
--- a/Display.h
+++ b/Display.h
@@ -37,7 +37,9 @@
class Display : public DisplayInterface {
public:
Display(DisplayDevice *deviceDriver);
+#if !defined (MAX_CHARACTER_ROWS)
static const int MAX_CHARACTER_ROWS = 8;
+#endif
static const int MAX_CHARACTER_COLS = MAX_MSG_SIZE;
static const long DISPLAY_SCROLL_TIME = 3000; // 3 seconds
diff --git a/config.example.h b/config.example.h
index de31743..9909371 100644
--- a/config.example.h
+++ b/config.example.h
@@ -167,6 +167,14 @@ The configuration file for DCC-EX Command Station
// * #define SCROLLMODE 2 is by row (move up 1 row at a time).
#define SCROLLMODE 1
+// In order to avoid wasting memory the current scroll buffer is limited
+// to 8 lines. Some users wishing to display additional information
+// such as TrackManager power states have requested additional rows aware
+// of the warning that this will take extra RAM. if you wish to include additional rows
+// uncomment the following #define and set the number of lines you need.
+//#define MAX_CHARACTER_ROWS 12
+
+
/////////////////////////////////////////////////////////////////////////////////////
// DISABLE EEPROM
//
From b472230b47b86d169a21b26f4566e94c7eb4abf4 Mon Sep 17 00:00:00 2001
From: Colin Murdoch
Date: Wed, 15 Nov 2023 19:41:56 +0000
Subject: [PATCH 31/64] Update version.h
Updated version.h
---
version.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/version.h b/version.h
index 5640feb..3030981 100644
--- a/version.h
+++ b/version.h
@@ -3,7 +3,8 @@
#include "StringFormatter.h"
-#define VERSION "5.2.1"
+#define VERSION "5.2.2"
+// 5.2.2 - Added option to allow MAX_CHARACTER_ROWS to be defined in config.h
// 5.2.1 - Trackmanager rework for simpler structure
// 5.2.0 - ESP32: Autoreverse and booster mode support
// 5.1.21 - EXRAIL invoke multiple ON handlers for same event
From 7bd2ba9b418bb2f5768c5e572ee26242780e3353 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Thu, 16 Nov 2023 00:27:23 +0100
Subject: [PATCH 32/64] Bugfix: Catch stange input to parser
---
DCCEXParser.cpp | 23 +++++++++++++++++------
SerialManager.cpp | 17 +++++++++--------
2 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp
index 3b91d86..82a1042 100644
--- a/DCCEXParser.cpp
+++ b/DCCEXParser.cpp
@@ -210,8 +210,10 @@ int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], const byte
case 1: // skipping spaces before a param
if (hot == ' ')
break;
- if (hot == '\0' || hot == '>')
- return parameterCount;
+ if (hot == '\0')
+ return -1;
+ if (hot == '>')
+ return parameterCount;
state = 2;
continue;
@@ -304,14 +306,19 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
#ifndef DISABLE_EEPROM
(void)EEPROM; // tell compiler not to warn this is unused
#endif
+ byte params = 0;
if (Diag::CMD)
DIAG(F("PARSING:%s"), com);
int16_t p[MAX_COMMAND_PARAMS];
while (com[0] == '<' || com[0] == ' ')
com++; // strip off any number of < or spaces
byte opcode = com[0];
- byte params = splitValues(p, com, opcode=='M' || opcode=='P');
-
+ int16_t splitnum = splitValues(p, com, opcode=='M' || opcode=='P');
+ if (splitnum < 0 || splitnum >= MAX_COMMAND_PARAMS) // if arguments are broken, leave but via printing
+ goto out;
+ // Because of check above we are now inside byte size
+ params = splitnum;
+
if (filterCallback)
filterCallback(stream, opcode, params, p);
if (filterRMFTCallback && opcode!='\0')
@@ -833,14 +840,18 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
break; // Will if not intercepted by EXRAIL
default: //anything else will diagnose and drop out to
+ if (opcode >= ' ' && opcode <= '~') {
DIAG(F("Opcode=%c params=%d"), opcode, params);
for (int i = 0; i < params; i++)
DIAG(F("p[%d]=%d (0x%x)"), i, p[i], p[i]);
- break;
+ } else {
+ DIAG(F("Unprintable %x"), opcode);
+ }
+ break;
} // end of opcode switch
- // Any fallout here sends an
+out:// Any fallout here sends an
StringFormatter::send(stream, F("\n"));
}
diff --git a/SerialManager.cpp b/SerialManager.cpp
index bacfceb..88bc7cd 100644
--- a/SerialManager.cpp
+++ b/SerialManager.cpp
@@ -111,14 +111,15 @@ void SerialManager::loop2() {
bufferLength = 0;
buffer[0] = '\0';
}
- else if (ch == '>') {
- buffer[bufferLength] = '\0';
- DCCEXParser::parse(serial, buffer, NULL);
- inCommandPayload = false;
- break;
- }
- else if (inCommandPayload) {
- if (bufferLength < (COMMAND_BUFFER_SIZE-1)) buffer[bufferLength++] = ch;
+ else if (inCommandPayload) {
+ if (bufferLength < (COMMAND_BUFFER_SIZE-1))
+ buffer[bufferLength++] = ch;
+ if (ch == '>') {
+ buffer[bufferLength] = '\0';
+ DCCEXParser::parse(serial, buffer, NULL);
+ inCommandPayload = false;
+ break;
+ }
}
}
From 102d6078a7c290b05eb2d531bae5ab7bbbd37c78 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Thu, 16 Nov 2023 08:38:39 +0100
Subject: [PATCH 33/64] version 5.2.3
---
GITHUB_SHA.h | 2 +-
version.h | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h
index 3f9b1e1..2a558fc 100644
--- a/GITHUB_SHA.h
+++ b/GITHUB_SHA.h
@@ -1 +1 @@
-#define GITHUB_SHA "devel-202311141013Z"
+#define GITHUB_SHA "devel-202311160737Z"
diff --git a/version.h b/version.h
index 3030981..c14d2b0 100644
--- a/version.h
+++ b/version.h
@@ -3,7 +3,8 @@
#include "StringFormatter.h"
-#define VERSION "5.2.2"
+#define VERSION "5.2.3"
+// 5.2.3 - Bugfix: Catch stange input to parser
// 5.2.2 - Added option to allow MAX_CHARACTER_ROWS to be defined in config.h
// 5.2.1 - Trackmanager rework for simpler structure
// 5.2.0 - ESP32: Autoreverse and booster mode support
From 2ba5adc8b42bfd5323e09f4bf2b6585321129a8e Mon Sep 17 00:00:00 2001
From: Asbelos
Date: Fri, 17 Nov 2023 10:45:36 +0000
Subject: [PATCH 34/64] 5.2.3 @ and ROUTE_DISABLED
---
DCCEXParser.cpp | 4 ++++
EXRAIL2.cpp | 3 +++
EXRAIL2.h | 1 +
EXRAIL2MacroReset.h | 2 ++
EXRAILMacros.h | 3 +++
StringFormatter.cpp | 15 +++++++++------
version.h | 2 ++
7 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp
index 4ceedea..aed185b 100644
--- a/DCCEXParser.cpp
+++ b/DCCEXParser.cpp
@@ -115,6 +115,7 @@ Once a new OPCODE is decided upon, update this list.
#include "DCCTimer.h"
#include "EXRAIL2.h"
#include "Turntables.h"
+#include "version.h"
// This macro can't be created easily as a portable function because the
// flashlist requires a far pointer for high flash access.
@@ -841,6 +842,9 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
case '@': // JMRI saying "give me virtual LCD msgs"
CommandDistributor::setVirtualLCDSerial(stream);
+ StringFormatter::send(stream,
+ F("<@ 0 0 \"DCC-EX v" VERSION "\">\n"
+ "<@ 0 1 \"Lic GPLv3\">\n"));
return;
default: //anything else will diagnose and drop out to
diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp
index ccd4d9e..6f0a835 100644
--- a/EXRAIL2.cpp
+++ b/EXRAIL2.cpp
@@ -932,6 +932,9 @@ void RMFT2::loop2() {
case OPCODE_ROUTE_ACTIVE:
manageRouteState(operand,1);
break;
+ case OPCODE_ROUTE_DISABLED:
+ manageRouteState(operand,4);
+ break;
case OPCODE_ROUTE:
case OPCODE_AUTOMATION:
diff --git a/EXRAIL2.h b/EXRAIL2.h
index a4c0e5f..8f777f4 100644
--- a/EXRAIL2.h
+++ b/EXRAIL2.h
@@ -69,6 +69,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
OPCODE_LCC,OPCODE_LCCX,OPCODE_ONLCC,
OPCODE_ONOVERLOAD,
OPCODE_ROUTE_ACTIVE,OPCODE_ROUTE_INACTIVE,OPCODE_ROUTE_HIDDEN,
+ OPCODE_ROUTE_DISABLED,
// OPcodes below this point are skip-nesting IF operations
// placed here so that they may be skipped as a group
diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h
index ff8dc8d..ee240ed 100644
--- a/EXRAIL2MacroReset.h
+++ b/EXRAIL2MacroReset.h
@@ -129,6 +129,7 @@
#undef ROUTE_ACTIVE
#undef ROUTE_INACTIVE
#undef ROUTE_HIDDEN
+#undef ROUTE_DISABLED
#undef ROUTE_CAPTION
#undef SENDLOCO
#undef SEQUENCE
@@ -274,6 +275,7 @@
#define ROUTE_ACTIVE(id)
#define ROUTE_INACTIVE(id)
#define ROUTE_HIDDEN(id)
+#define ROUTE_DISABLED(id)
#define ROUTE_CAPTION(id,caption)
#define SENDLOCO(cab,route)
#define SEQUENCE(id)
diff --git a/EXRAILMacros.h b/EXRAILMacros.h
index 3c58699..6024290 100644
--- a/EXRAILMacros.h
+++ b/EXRAILMacros.h
@@ -108,6 +108,8 @@ void exrailHalSetup() {
#define ROUTE_INACTIVE(id) | FEATURE_ROUTESTATE
#undef ROUTE_HIDDEN
#define ROUTE_HIDDEN(id) | FEATURE_ROUTESTATE
+#undef ROUTE_DISABLED
+#define ROUTE_DISABLED(id) | FEATURE_ROUTESTATE
#undef ROUTE_CAPTION
#define ROUTE_CAPTION(id,caption) | FEATURE_ROUTESTATE
@@ -457,6 +459,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#define ROUTE_ACTIVE(id) OPCODE_ROUTE_ACTIVE,V(id),
#define ROUTE_INACTIVE(id) OPCODE_ROUTE_INACTIVE,V(id),
#define ROUTE_HIDDEN(id) OPCODE_ROUTE_HIDDEN,V(id),
+#define ROUTE_DISABLED(id) OPCODE_ROUTE_DISABLED,V(id),
#define ROUTE_CAPTION(id,caption) PRINT(caption)
#define SENDLOCO(cab,route) OPCODE_SENDLOCO,V(cab),OPCODE_PAD,V(route),
#define SEQUENCE(id) OPCODE_SEQUENCE, V(id),
diff --git a/StringFormatter.cpp b/StringFormatter.cpp
index 218e617..13b5825 100644
--- a/StringFormatter.cpp
+++ b/StringFormatter.cpp
@@ -39,15 +39,18 @@ void StringFormatter::diag( const FSH* input...) {
void StringFormatter::lcd(byte row, const FSH* input...) {
va_list args;
-
+ Print * virtualLCD=CommandDistributor::getVirtualLCDSerial(0,row);
+
// Issue the LCD as a diag first
- send(&USB_SERIAL,F("<* LCD%d:"),row);
- va_start(args, input);
- send2(&USB_SERIAL,input,args);
- send(&USB_SERIAL,F(" *>\n"));
+ // Unless the same serial is asking for the virtual @ respomnse
+ if (virtualLCD!=&USB_SERIAL) {
+ send(&USB_SERIAL,F("<* LCD%d:"),row);
+ va_start(args, input);
+ send2(&USB_SERIAL,input,args);
+ send(&USB_SERIAL,F(" *>\n"));
+ }
// send to virtual LCD collector (if any)
- Print * virtualLCD=CommandDistributor::getVirtualLCDSerial(0,row);
if (virtualLCD) {
va_start(args, input);
send2(virtualLCD,input,args);
diff --git a/version.h b/version.h
index c14d2b0..57d154a 100644
--- a/version.h
+++ b/version.h
@@ -4,6 +4,8 @@
#include "StringFormatter.h"
#define VERSION "5.2.3"
+// 5.2.4 - LCD macro will not do diag if that duplicates @ to same target.
+// - Added ROUTE_DISABLED macro in EXRAIL
// 5.2.3 - Bugfix: Catch stange input to parser
// 5.2.2 - Added option to allow MAX_CHARACTER_ROWS to be defined in config.h
// 5.2.1 - Trackmanager rework for simpler structure
From 74d11ccb1e9e30f395f18bafeed0f656650e2889 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Mon, 20 Nov 2023 09:27:57 +0100
Subject: [PATCH 35/64] Trackmanager: Do not treat TRACK_MODE_ALL as
TRACK_MODE_DC
---
TrackManager.cpp | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/TrackManager.cpp b/TrackManager.cpp
index 7c1e651..2f528bd 100644
--- a/TrackManager.cpp
+++ b/TrackManager.cpp
@@ -472,12 +472,13 @@ std::vectorTrackManager::getMainDrivers() {
#endif
// Set track power for all tracks with this mode
-void TrackManager::setTrackPower(TRACK_MODE trackmode, POWERMODE powermode) {
+void TrackManager::setTrackPower(TRACK_MODE trackmodeToMatch, POWERMODE powermode) {
FOR_EACH_TRACK(t) {
- MotorDriver *driver=track[t];
- if (trackmode & driver->getMode()) {
+ MotorDriver *driver=track[t];
+ TRACK_MODE trackmodeOfTrack = driver->getMode();
+ if (trackmodeToMatch & trackmodeOfTrack) {
if (powermode == POWERMODE::ON) {
- if (trackmode & TRACK_MODE_DC) {
+ if (trackmodeOfTrack & TRACK_MODE_DC) {
driver->setBrake(true); // DC starts with brake on
applyDCSpeed(t); // speed match DCC throttles
} else {
From a7096e782c148f0d07dc694612a9048c2818cdb4 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Mon, 20 Nov 2023 09:32:22 +0100
Subject: [PATCH 36/64] version 5.2.5
---
GITHUB_SHA.h | 2 +-
version.h | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h
index 2a558fc..e03b498 100644
--- a/GITHUB_SHA.h
+++ b/GITHUB_SHA.h
@@ -1 +1 @@
-#define GITHUB_SHA "devel-202311160737Z"
+#define GITHUB_SHA "devel-202311200731Z"
diff --git a/version.h b/version.h
index 57d154a..e3a71d2 100644
--- a/version.h
+++ b/version.h
@@ -3,7 +3,8 @@
#include "StringFormatter.h"
-#define VERSION "5.2.3"
+#define VERSION "5.2.5"
+// 5.2.5 - Trackmanager: Do not treat TRACK_MODE_ALL as TRACK_MODE_DC
// 5.2.4 - LCD macro will not do diag if that duplicates @ to same target.
// - Added ROUTE_DISABLED macro in EXRAIL
// 5.2.3 - Bugfix: Catch stange input to parser
From e6f33cfdee7aacc37e8071f3fe4e1659b77d8924 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Tue, 21 Nov 2023 11:51:26 +0100
Subject: [PATCH 37/64] Trackmanager broadcast power state on track mode change
---
DCCEXParser.cpp | 2 +-
TrackManager.cpp | 10 ++++++----
TrackManager.h | 2 +-
3 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp
index aed185b..8a81616 100644
--- a/DCCEXParser.cpp
+++ b/DCCEXParser.cpp
@@ -668,7 +668,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
break;
#endif
case '=': // TRACK MANAGER CONTROL <= [params]>
- if (TrackManager::parseJ(stream, params, p))
+ if (TrackManager::parseEqualSign(stream, params, p))
return;
break;
diff --git a/TrackManager.cpp b/TrackManager.cpp
index 2f528bd..58a5c30 100644
--- a/TrackManager.cpp
+++ b/TrackManager.cpp
@@ -350,7 +350,7 @@ void TrackManager::applyDCSpeed(byte t) {
track[t]->setDCSignal(speedByte);
}
-bool TrackManager::parseJ(Print *stream, int16_t params, int16_t p[])
+bool TrackManager::parseEqualSign(Print *stream, int16_t params, int16_t p[])
{
if (params==0) { // <=> List track assignments
@@ -397,8 +397,8 @@ bool TrackManager::parseJ(Print *stream, int16_t params, int16_t p[])
return false;
}
+// null stream means send to commandDistributor for broadcast
void TrackManager::streamTrackState(Print* stream, byte t) {
- // null stream means send to commandDistributor for broadcast
if (track[t]==NULL) return;
auto format=F("<= %d XXX>\n");
TRACK_MODE tm = track[t]->getMode();
@@ -433,10 +433,12 @@ void TrackManager::streamTrackState(Print* stream, byte t) {
format=F("<= %c DC %d>\n");
}
- if (stream)
+ if (stream) { // null stream means send to commandDistributor for broadcast
StringFormatter::send(stream,format,'A'+t, trackDCAddr[t]);
- else
+ } else {
CommandDistributor::broadcastTrackState(format,'A'+t, trackDCAddr[t]);
+ CommandDistributor::broadcastPower();
+ }
}
diff --git a/TrackManager.h b/TrackManager.h
index 644c45a..8092f0a 100644
--- a/TrackManager.h
+++ b/TrackManager.h
@@ -73,7 +73,7 @@ class TrackManager {
static const int16_t MAX_TRACKS=8;
static bool setTrackMode(byte track, TRACK_MODE mode, int16_t DCaddr=0);
- static bool parseJ(Print * stream, int16_t params, int16_t p[]);
+ static bool parseEqualSign(Print * stream, int16_t params, int16_t p[]);
static void loop();
static POWERMODE getMainPower();
static POWERMODE getProgPower();
From 29ea7460621b7948c45703121a131b6ea95662e2 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Tue, 21 Nov 2023 11:54:43 +0100
Subject: [PATCH 38/64] version 5.2.6
---
GITHUB_SHA.h | 2 +-
version.h | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h
index e03b498..683f81d 100644
--- a/GITHUB_SHA.h
+++ b/GITHUB_SHA.h
@@ -1 +1 @@
-#define GITHUB_SHA "devel-202311200731Z"
+#define GITHUB_SHA "devel-202311211053Z"
diff --git a/version.h b/version.h
index e3a71d2..0f26a21 100644
--- a/version.h
+++ b/version.h
@@ -3,7 +3,8 @@
#include "StringFormatter.h"
-#define VERSION "5.2.5"
+#define VERSION "5.2.6"
+// 5.2.6 - Trackmanager broadcast power state on track mode change
// 5.2.5 - Trackmanager: Do not treat TRACK_MODE_ALL as TRACK_MODE_DC
// 5.2.4 - LCD macro will not do diag if that duplicates @ to same target.
// - Added ROUTE_DISABLED macro in EXRAIL
From 4e1fad48325608888da61a2e30f9068366f0139e Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Tue, 21 Nov 2023 15:37:08 +0100
Subject: [PATCH 39/64] Trackmanager consolidate getModeName
---
CommandDistributor.cpp | 4 +--
CommandDistributor.h | 2 +-
EXRAILMacros.h | 16 +++++------
TrackManager.cpp | 63 ++++++++++++++++++++----------------------
TrackManager.h | 2 +-
5 files changed, 42 insertions(+), 45 deletions(-)
diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp
index fa70e0c..1f11e28 100644
--- a/CommandDistributor.cpp
+++ b/CommandDistributor.cpp
@@ -275,8 +275,8 @@ void CommandDistributor::broadcastRaw(clientType type, char * msg) {
broadcastReply(type, F("%s"),msg);
}
-void CommandDistributor::broadcastTrackState(const FSH* format,byte trackLetter, int16_t dcAddr) {
- broadcastReply(COMMAND_TYPE, format, trackLetter, dcAddr);
+void CommandDistributor::broadcastTrackState(const FSH* format, byte trackLetter, const FSH *modename, int16_t dcAddr) {
+ broadcastReply(COMMAND_TYPE, format, trackLetter, modename, dcAddr);
}
void CommandDistributor::broadcastRouteState(uint16_t routeId, byte state ) {
diff --git a/CommandDistributor.h b/CommandDistributor.h
index 359c0fe..e4dff5d 100644
--- a/CommandDistributor.h
+++ b/CommandDistributor.h
@@ -55,7 +55,7 @@ public :
static int16_t retClockTime();
static void broadcastPower();
static void broadcastRaw(clientType type,char * msg);
- static void broadcastTrackState(const FSH* format,byte trackLetter, int16_t dcAddr);
+ static void broadcastTrackState(const FSH* format,byte trackLetter, const FSH* modename, int16_t dcAddr);
template static void broadcastReply(clientType type, Targs... msg);
static void forget(byte clientId);
static void broadcastRouteState(uint16_t routeId,byte state);
diff --git a/EXRAILMacros.h b/EXRAILMacros.h
index 6024290..8edbd2b 100644
--- a/EXRAILMacros.h
+++ b/EXRAILMacros.h
@@ -121,14 +121,14 @@ const byte RMFT2::compileFeatures = 0
#include "EXRAIL2MacroReset.h"
#undef ROUTE
#define ROUTE(id, description) id,
-const int16_t HIGHFLASH RMFT2::routeIdList[]= {
+const int16_t HIGHFLASH const RMFT2::routeIdList[]= {
#include "myAutomation.h"
INT16_MAX};
// Pass 2a create throttle automation list
#include "EXRAIL2MacroReset.h"
#undef AUTOMATION
#define AUTOMATION(id, description) id,
-const int16_t HIGHFLASH RMFT2::automationIdList[]= {
+const int16_t HIGHFLASH const RMFT2::automationIdList[]= {
#include "myAutomation.h"
INT16_MAX};
@@ -150,7 +150,7 @@ const FSH * RMFT2::getRouteDescription(int16_t id) {
const int StringMacroTracker1=__COUNTER__;
#define THRUNGE(msg,mode) \
case (__COUNTER__ - StringMacroTracker1) : {\
- static const char HIGHFLASH thrunge[]=msg;\
+ static const char HIGHFLASH const thrunge[]=msg;\
strfar=(uint32_t)GETFARPTR(thrunge);\
tmode=mode;\
break;\
@@ -186,7 +186,7 @@ case (__COUNTER__ - StringMacroTracker1) : {\
#undef LCD
#define LCD(id,msg) \
case (__COUNTER__ - StringMacroTracker1) : {\
- static const char HIGHFLASH thrunge[]=msg;\
+ static const char HIGHFLASH const thrunge[]=msg;\
strfar=(uint32_t)GETFARPTR(thrunge);\
tmode=thrunge_lcd; \
lcdid=id;\
@@ -195,7 +195,7 @@ case (__COUNTER__ - StringMacroTracker1) : {\
#undef SCREEN
#define SCREEN(display,id,msg) \
case (__COUNTER__ - StringMacroTracker1) : {\
- static const char HIGHFLASH thrunge[]=msg;\
+ static const char HIGHFLASH const thrunge[]=msg;\
strfar=(uint32_t)GETFARPTR(thrunge);\
tmode=(thrunger)(thrunge_lcd+display); \
lcdid=id;\
@@ -274,7 +274,7 @@ const byte RMFT2::rosterNameCount=0
#include "EXRAIL2MacroReset.h"
#undef ROSTER
#define ROSTER(cabid,name,funcmap...) cabid,
-const int16_t HIGHFLASH RMFT2::rosterIdList[]={
+const int16_t HIGHFLASH const RMFT2::rosterIdList[]={
#include "myAutomation.h"
INT16_MAX};
@@ -314,7 +314,7 @@ const FSH * RMFT2::getRosterFunctions(int16_t id) {
#undef VIRTUAL_SIGNAL
#define VIRTUAL_SIGNAL(id) id,0,0,0,
-const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = {
+const HIGHFLASH int16_t const RMFT2::SignalDefinitions[] = {
#include "myAutomation.h"
0,0,0,0 };
@@ -503,7 +503,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
// Build RouteCode
const int StringMacroTracker2=__COUNTER__;
-const HIGHFLASH byte RMFT2::RouteCode[] = {
+const HIGHFLASH byte const RMFT2::RouteCode[] = {
#include "myAutomation.h"
OPCODE_ENDTASK,0,0,OPCODE_ENDEXRAIL,0,0 };
diff --git a/TrackManager.cpp b/TrackManager.cpp
index 58a5c30..a7998f4 100644
--- a/TrackManager.cpp
+++ b/TrackManager.cpp
@@ -397,46 +397,58 @@ bool TrackManager::parseEqualSign(Print *stream, int16_t params, int16_t p[])
return false;
}
-// null stream means send to commandDistributor for broadcast
-void TrackManager::streamTrackState(Print* stream, byte t) {
- if (track[t]==NULL) return;
- auto format=F("<= %d XXX>\n");
- TRACK_MODE tm = track[t]->getMode();
+const FSH* TrackManager::getModeName(TRACK_MODE tm) {
+ const FSH *modename=F("---");
+
if (tm & TRACK_MODE_MAIN) {
if(tm & TRACK_MODE_AUTOINV)
- format=F("<= %c MAIN A>\n");
+ modename=F("MAIN A");
else if (tm & TRACK_MODE_INV)
- format=F("<= %c MAIN I>\n");
+ modename=F("MAIN I>\n");
else
- format=F("<= %c MAIN>\n");
+ modename=F("MAIN");
}
#ifndef DISABLE_PROG
else if (tm & TRACK_MODE_PROG)
- format=F("<= %c PROG>\n");
+ modename=F("PROG");
#endif
else if (tm & TRACK_MODE_NONE)
- format=F("<= %c NONE>\n");
+ modename=F("NONE");
else if(tm & TRACK_MODE_EXT)
- format=F("<= %c EXT>\n");
+ modename=F("EXT");
else if(tm & TRACK_MODE_BOOST) {
if(tm & TRACK_MODE_AUTOINV)
- format=F("<= %c B A>\n");
+ modename=F("B A");
else if (tm & TRACK_MODE_INV)
- format=F("<= %c B I>\n");
+ modename=F("B I");
else
- format=F("<= %c B>\n");
+ modename=F("B");
}
else if (tm & TRACK_MODE_DC) {
if (tm & TRACK_MODE_INV)
- format=F("<= %c DCX %d>\n");
+ modename=F("DCX");
else
- format=F("<= %c DC %d>\n");
+ modename=F("DC");
}
+ return modename;
+}
+// null stream means send to commandDistributor for broadcast
+void TrackManager::streamTrackState(Print* stream, byte t) {
+ const FSH *format;
+
+ if (track[t]==NULL) return;
+ TRACK_MODE tm = track[t]->getMode();
+ if (tm & TRACK_MODE_DC)
+ format=F("<= %c %S %d>\n");
+ else
+ format=F("<= %c %S>\n");
+
+ const FSH *modename=getModeName(tm);
if (stream) { // null stream means send to commandDistributor for broadcast
- StringFormatter::send(stream,format,'A'+t, trackDCAddr[t]);
+ StringFormatter::send(stream,format,'A'+t, modename, trackDCAddr[t]);
} else {
- CommandDistributor::broadcastTrackState(format,'A'+t, trackDCAddr[t]);
+ CommandDistributor::broadcastTrackState(format,'A'+t, modename, trackDCAddr[t]);
CommandDistributor::broadcastPower();
}
@@ -641,18 +653,3 @@ int16_t TrackManager::returnDCAddr(byte t) {
return (trackDCAddr[t]);
}
-const char* TrackManager::getModeName(byte Mode) {
-
- //DIAG(F("PowerMode %d"), Mode);
-
-switch (Mode)
- {
- case 1: return "NONE";
- case 2: return "MAIN";
- case 4: return "PROG";
- case 8: return "DC";
- case 16: return "DCX";
- case 32: return "EXT";
- default: return "----";
- }
-}
diff --git a/TrackManager.h b/TrackManager.h
index 8092f0a..f2a357d 100644
--- a/TrackManager.h
+++ b/TrackManager.h
@@ -91,7 +91,7 @@ class TrackManager {
static bool isProg(byte t);
static byte returnMode(byte t);
static int16_t returnDCAddr(byte t);
- static const char* getModeName(byte Mode);
+ static const FSH* getModeName(TRACK_MODE Mode);
static int16_t joinRelay;
static bool progTrackSyncMain; // true when prog track is a siding switched to main
From 263ed18b253faff69227a843ad5fd419c4487027 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Tue, 21 Nov 2023 15:37:47 +0100
Subject: [PATCH 40/64] version tag
---
GITHUB_SHA.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h
index 683f81d..1fc5a39 100644
--- a/GITHUB_SHA.h
+++ b/GITHUB_SHA.h
@@ -1 +1 @@
-#define GITHUB_SHA "devel-202311211053Z"
+#define GITHUB_SHA "devel-202311211437Z"
From e7c4af5d4a64c49ce637c5f7cd65b045e75e5265 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Tue, 21 Nov 2023 21:16:20 +0100
Subject: [PATCH 41/64] back out wrong const change
---
EXRAILMacros.h | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/EXRAILMacros.h b/EXRAILMacros.h
index 8edbd2b..6024290 100644
--- a/EXRAILMacros.h
+++ b/EXRAILMacros.h
@@ -121,14 +121,14 @@ const byte RMFT2::compileFeatures = 0
#include "EXRAIL2MacroReset.h"
#undef ROUTE
#define ROUTE(id, description) id,
-const int16_t HIGHFLASH const RMFT2::routeIdList[]= {
+const int16_t HIGHFLASH RMFT2::routeIdList[]= {
#include "myAutomation.h"
INT16_MAX};
// Pass 2a create throttle automation list
#include "EXRAIL2MacroReset.h"
#undef AUTOMATION
#define AUTOMATION(id, description) id,
-const int16_t HIGHFLASH const RMFT2::automationIdList[]= {
+const int16_t HIGHFLASH RMFT2::automationIdList[]= {
#include "myAutomation.h"
INT16_MAX};
@@ -150,7 +150,7 @@ const FSH * RMFT2::getRouteDescription(int16_t id) {
const int StringMacroTracker1=__COUNTER__;
#define THRUNGE(msg,mode) \
case (__COUNTER__ - StringMacroTracker1) : {\
- static const char HIGHFLASH const thrunge[]=msg;\
+ static const char HIGHFLASH thrunge[]=msg;\
strfar=(uint32_t)GETFARPTR(thrunge);\
tmode=mode;\
break;\
@@ -186,7 +186,7 @@ case (__COUNTER__ - StringMacroTracker1) : {\
#undef LCD
#define LCD(id,msg) \
case (__COUNTER__ - StringMacroTracker1) : {\
- static const char HIGHFLASH const thrunge[]=msg;\
+ static const char HIGHFLASH thrunge[]=msg;\
strfar=(uint32_t)GETFARPTR(thrunge);\
tmode=thrunge_lcd; \
lcdid=id;\
@@ -195,7 +195,7 @@ case (__COUNTER__ - StringMacroTracker1) : {\
#undef SCREEN
#define SCREEN(display,id,msg) \
case (__COUNTER__ - StringMacroTracker1) : {\
- static const char HIGHFLASH const thrunge[]=msg;\
+ static const char HIGHFLASH thrunge[]=msg;\
strfar=(uint32_t)GETFARPTR(thrunge);\
tmode=(thrunger)(thrunge_lcd+display); \
lcdid=id;\
@@ -274,7 +274,7 @@ const byte RMFT2::rosterNameCount=0
#include "EXRAIL2MacroReset.h"
#undef ROSTER
#define ROSTER(cabid,name,funcmap...) cabid,
-const int16_t HIGHFLASH const RMFT2::rosterIdList[]={
+const int16_t HIGHFLASH RMFT2::rosterIdList[]={
#include "myAutomation.h"
INT16_MAX};
@@ -314,7 +314,7 @@ const FSH * RMFT2::getRosterFunctions(int16_t id) {
#undef VIRTUAL_SIGNAL
#define VIRTUAL_SIGNAL(id) id,0,0,0,
-const HIGHFLASH int16_t const RMFT2::SignalDefinitions[] = {
+const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = {
#include "myAutomation.h"
0,0,0,0 };
@@ -503,7 +503,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
// Build RouteCode
const int StringMacroTracker2=__COUNTER__;
-const HIGHFLASH byte const RMFT2::RouteCode[] = {
+const HIGHFLASH byte RMFT2::RouteCode[] = {
#include "myAutomation.h"
OPCODE_ENDTASK,0,0,OPCODE_ENDEXRAIL,0,0 };
From 2c1b3e0a8fc4f43d0d48527a940de34d30dc9a4a Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Tue, 21 Nov 2023 21:16:42 +0100
Subject: [PATCH 42/64] version tag
---
GITHUB_SHA.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h
index 1fc5a39..3710cad 100644
--- a/GITHUB_SHA.h
+++ b/GITHUB_SHA.h
@@ -1 +1 @@
-#define GITHUB_SHA "devel-202311211437Z"
+#define GITHUB_SHA "devel-202311212016Z"
From 478e9661bb2110b3bbb50c49c6ccb8ec30f565cf Mon Sep 17 00:00:00 2001
From: Asbelos
Date: Tue, 21 Nov 2023 21:14:54 +0000
Subject: [PATCH 43/64] EXRAIL ling segment
---
EXRAIL2.h | 2 +-
EXRAILMacros.h | 16 ++++++++--------
FSH.h | 3 +++
3 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/EXRAIL2.h b/EXRAIL2.h
index 8f777f4..5249f72 100644
--- a/EXRAIL2.h
+++ b/EXRAIL2.h
@@ -203,7 +203,7 @@ private:
uint16_t getOperand(byte n);
static bool diag;
- static const HIGHFLASH byte RouteCode[];
+ static const HIGHFLASH3 byte RouteCode[];
static const HIGHFLASH int16_t SignalDefinitions[];
static byte flags[MAX_FLAGS];
static Print * LCCSerial;
diff --git a/EXRAILMacros.h b/EXRAILMacros.h
index 8edbd2b..9048973 100644
--- a/EXRAILMacros.h
+++ b/EXRAILMacros.h
@@ -121,14 +121,14 @@ const byte RMFT2::compileFeatures = 0
#include "EXRAIL2MacroReset.h"
#undef ROUTE
#define ROUTE(id, description) id,
-const int16_t HIGHFLASH const RMFT2::routeIdList[]= {
+const int16_t HIGHFLASH RMFT2::routeIdList[]= {
#include "myAutomation.h"
INT16_MAX};
// Pass 2a create throttle automation list
#include "EXRAIL2MacroReset.h"
#undef AUTOMATION
#define AUTOMATION(id, description) id,
-const int16_t HIGHFLASH const RMFT2::automationIdList[]= {
+const int16_t HIGHFLASH RMFT2::automationIdList[]= {
#include "myAutomation.h"
INT16_MAX};
@@ -150,7 +150,7 @@ const FSH * RMFT2::getRouteDescription(int16_t id) {
const int StringMacroTracker1=__COUNTER__;
#define THRUNGE(msg,mode) \
case (__COUNTER__ - StringMacroTracker1) : {\
- static const char HIGHFLASH const thrunge[]=msg;\
+ static const char HIGHFLASH thrunge[]=msg;\
strfar=(uint32_t)GETFARPTR(thrunge);\
tmode=mode;\
break;\
@@ -186,7 +186,7 @@ case (__COUNTER__ - StringMacroTracker1) : {\
#undef LCD
#define LCD(id,msg) \
case (__COUNTER__ - StringMacroTracker1) : {\
- static const char HIGHFLASH const thrunge[]=msg;\
+ static const char HIGHFLASH thrunge[]=msg;\
strfar=(uint32_t)GETFARPTR(thrunge);\
tmode=thrunge_lcd; \
lcdid=id;\
@@ -195,7 +195,7 @@ case (__COUNTER__ - StringMacroTracker1) : {\
#undef SCREEN
#define SCREEN(display,id,msg) \
case (__COUNTER__ - StringMacroTracker1) : {\
- static const char HIGHFLASH const thrunge[]=msg;\
+ static const char HIGHFLASH thrunge[]=msg;\
strfar=(uint32_t)GETFARPTR(thrunge);\
tmode=(thrunger)(thrunge_lcd+display); \
lcdid=id;\
@@ -274,7 +274,7 @@ const byte RMFT2::rosterNameCount=0
#include "EXRAIL2MacroReset.h"
#undef ROSTER
#define ROSTER(cabid,name,funcmap...) cabid,
-const int16_t HIGHFLASH const RMFT2::rosterIdList[]={
+const int16_t HIGHFLASH RMFT2::rosterIdList[]={
#include "myAutomation.h"
INT16_MAX};
@@ -314,7 +314,7 @@ const FSH * RMFT2::getRosterFunctions(int16_t id) {
#undef VIRTUAL_SIGNAL
#define VIRTUAL_SIGNAL(id) id,0,0,0,
-const HIGHFLASH int16_t const RMFT2::SignalDefinitions[] = {
+const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = {
#include "myAutomation.h"
0,0,0,0 };
@@ -503,7 +503,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
// Build RouteCode
const int StringMacroTracker2=__COUNTER__;
-const HIGHFLASH byte const RMFT2::RouteCode[] = {
+const HIGHFLASH3 byte RMFT2::RouteCode[] = {
#include "myAutomation.h"
OPCODE_ENDTASK,0,0,OPCODE_ENDEXRAIL,0,0 };
diff --git a/FSH.h b/FSH.h
index d031935..280d37e 100644
--- a/FSH.h
+++ b/FSH.h
@@ -56,6 +56,7 @@ typedef __FlashStringHelper FSH;
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
// AVR_MEGA memory deliberately placed at end of link may need _far functions
#define HIGHFLASH __attribute__((section(".fini2")))
+#define HIGHFLASH3 __attribute__((section(".fini3")))
#define GETFARPTR(data) pgm_get_far_address(data)
#define GETHIGHFLASH(data,offset) pgm_read_byte_far(GETFARPTR(data)+offset)
#define GETHIGHFLASHW(data,offset) pgm_read_word_far(GETFARPTR(data)+offset)
@@ -63,6 +64,7 @@ typedef __FlashStringHelper FSH;
// AVR_UNO/NANO runtime does not support _far functions so just use _near equivalent
// as there is no progmem above 32kb anyway.
#define HIGHFLASH PROGMEM
+#define HIGHFLASH3 PROGMEM
#define GETFARPTR(data) ((uint32_t)(data))
#define GETHIGHFLASH(data,offset) pgm_read_byte_near(GETFARPTR(data)+(offset))
#define GETHIGHFLASHW(data,offset) pgm_read_word_near(GETFARPTR(data)+(offset))
@@ -80,6 +82,7 @@ typedef __FlashStringHelper FSH;
typedef char FSH;
#define FLASH
#define HIGHFLASH
+#define HIGHFLASH3
#define GETFARPTR(data) ((uint32_t)(data))
#define GETFLASH(addr) (*(const byte *)(addr))
#define GETHIGHFLASH(data,offset) (*(const byte *)(GETFARPTR(data)+offset))
From ac4af407aa26b8773d2fc074d641f4dcaf243a15 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Tue, 21 Nov 2023 22:47:48 +0100
Subject: [PATCH 44/64] On ESP32, the inversion is already done in HW
---
MotorDriver.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/MotorDriver.h b/MotorDriver.h
index 19bfd13..07ff93f 100644
--- a/MotorDriver.h
+++ b/MotorDriver.h
@@ -156,8 +156,10 @@ class MotorDriver {
// from outside interrupt
void setBrake( bool on, bool interruptContext=false);
__attribute__((always_inline)) inline void setSignal( bool high) {
+#ifndef ARDUINO_ARCH_ESP32
if (invertPhase)
high = !high;
+#endif
if (trackPWM) {
DCCTimer::setPWM(signalPin,high);
}
From d0df9f3c33d10e30ca54f939758f5c8394b39582 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Tue, 21 Nov 2023 22:48:35 +0100
Subject: [PATCH 45/64] version tag
---
GITHUB_SHA.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h
index 3710cad..d69d7ae 100644
--- a/GITHUB_SHA.h
+++ b/GITHUB_SHA.h
@@ -1 +1 @@
-#define GITHUB_SHA "devel-202311212016Z"
+#define GITHUB_SHA "devel-202311212148Z"
From 4308739c2b7663e47411c6624f626e4087cef268 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Tue, 21 Nov 2023 23:04:05 +0100
Subject: [PATCH 46/64] version 5.2.7
---
version.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/version.h b/version.h
index 0f26a21..b2829c7 100644
--- a/version.h
+++ b/version.h
@@ -3,7 +3,10 @@
#include "StringFormatter.h"
-#define VERSION "5.2.6"
+#define VERSION "5.2.7"
+// 5.2.7 - Bugfix: EXRAIL ling segment
+// - Bugfix: Back out wrongly added const
+// - Bugfix ESP32: Do not inverse DCX direction signal twice
// 5.2.6 - Trackmanager broadcast power state on track mode change
// 5.2.5 - Trackmanager: Do not treat TRACK_MODE_ALL as TRACK_MODE_DC
// 5.2.4 - LCD macro will not do diag if that duplicates @ to same target.
From 03db06f2ee52bc0838b37f581ae20195d335d4e4 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Wed, 22 Nov 2023 10:53:34 +0100
Subject: [PATCH 47/64] Bugfix: Do not turn on track with trackmode NONE
---
TrackManager.cpp | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/TrackManager.cpp b/TrackManager.cpp
index a7998f4..846c163 100644
--- a/TrackManager.cpp
+++ b/TrackManager.cpp
@@ -511,12 +511,15 @@ void TrackManager::setTrackPower(TRACK_MODE trackmodeToMatch, POWERMODE powermod
void TrackManager::setTrackPower(POWERMODE powermode, byte t) {
MotorDriver *driver=track[t];
TRACK_MODE trackmode = driver->getMode();
- if (trackmode & TRACK_MODE_DC) {
+ if (trackmode & TRACK_MODE_NONE) {
+ driver->setBrake(true); // Track is unused. Brake is good to have.
+ powermode = POWERMODE::OFF; // Track is unused. Force it to OFF
+ } else if (trackmode & TRACK_MODE_DC) { // includes inverted DC (called DCX)
if (powermode == POWERMODE::ON) {
driver->setBrake(true); // DC starts with brake on
applyDCSpeed(t); // speed match DCC throttles
}
- } else {
+ } else /* MAIN PROG EXT BOOST */ {
if (powermode == POWERMODE::ON) {
// toggle brake before turning power on - resets overcurrent error
// on the Pololu board if brake is wired to ^D2.
From ef47257d67afc8b66f33b0cbbaea10e4cdddb6e7 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Wed, 22 Nov 2023 10:54:01 +0100
Subject: [PATCH 48/64] version tag
---
GITHUB_SHA.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h
index d69d7ae..42f43fd 100644
--- a/GITHUB_SHA.h
+++ b/GITHUB_SHA.h
@@ -1 +1 @@
-#define GITHUB_SHA "devel-202311212148Z"
+#define GITHUB_SHA "devel-202311220953Z"
From b478056a9fbbe9b0f45ba49fd2748f080d78f99f Mon Sep 17 00:00:00 2001
From: Asbelos
Date: Thu, 23 Nov 2023 09:00:49 +0000
Subject: [PATCH 49/64] Fix @ reporting on startup
---
CommandDistributor.cpp | 2 +-
CommandStation-EX.ino | 2 +-
Display_Implementation.h | 4 +++-
myHalKCS.cpp | 1 +
4 files changed, 6 insertions(+), 3 deletions(-)
create mode 100644 myHalKCS.cpp
diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp
index 1f11e28..aef024b 100644
--- a/CommandDistributor.cpp
+++ b/CommandDistributor.cpp
@@ -330,7 +330,7 @@ void CommandDistributor::setVirtualLCDSerial(Print * stream) {
virtualLCDSerial=stream;
}
-Print* CommandDistributor::virtualLCDSerial=nullptr;
+Print* CommandDistributor::virtualLCDSerial=&USB_SERIAL;
byte CommandDistributor::virtualLCDClient=0xFF;
byte CommandDistributor::rememberVLCDClient=0;
diff --git a/CommandStation-EX.ino b/CommandStation-EX.ino
index 77e8f40..205babf 100644
--- a/CommandStation-EX.ino
+++ b/CommandStation-EX.ino
@@ -87,7 +87,7 @@ void setup()
DISPLAY_START (
// This block is still executed for DIAGS if display not in use
- LCD(0,F("DCC-EX v%S"),F(VERSION));
+ LCD(0,F("DCC-EX v" VERSION));
LCD(1,F("Lic GPLv3"));
);
diff --git a/Display_Implementation.h b/Display_Implementation.h
index ca19bd7..6a3c995 100644
--- a/Display_Implementation.h
+++ b/Display_Implementation.h
@@ -54,7 +54,9 @@
xxx; \
t->refresh();}
#else
- #define DISPLAY_START(xxx) {}
+ #define DISPLAY_START(xxx) { \
+ xxx; \
+ }
#endif
#endif // LCD_Implementation_h
diff --git a/myHalKCS.cpp b/myHalKCS.cpp
new file mode 100644
index 0000000..a330ae7
--- /dev/null
+++ b/myHalKCS.cpp
@@ -0,0 +1 @@
+// If you are planning to use multiple mux devices, perhaps it is good to use the 3-position syntax for all.
From 784934024ef9a0b7db67fcf831a02688102e021b Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Thu, 23 Nov 2023 10:47:43 +0100
Subject: [PATCH 50/64] Bugfix: Do not turn off all tracks on change ; give
better power messages
---
CommandDistributor.cpp | 53 +++++++++++++++++++++++++++++++++++-------
TrackManager.cpp | 16 +++++++------
TrackManager.h | 5 +++-
3 files changed, 57 insertions(+), 17 deletions(-)
diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp
index 1f11e28..a30fcd3 100644
--- a/CommandDistributor.cpp
+++ b/CommandDistributor.cpp
@@ -254,21 +254,56 @@ void CommandDistributor::broadcastPower() {
if (TrackManager::getPower(t, pstr))
broadcastReply(COMMAND_TYPE, F("\n"),pstr);
+ byte trackcount=0;
+ byte oncount=0;
+ byte offcount=0;
+ for(byte t=0; t\n"),state,reason);
+ if (join) {
+ reason = F("JOIN");
+ broadcastReply(COMMAND_TYPE, F("\n"),reason);
+ } else {
+ if (main) {
+ //reason = F("MAIN");
+ broadcastReply(COMMAND_TYPE, F("\n"));
+ }
+ if (prog) {
+ //reason = F("PROG");
+ broadcastReply(COMMAND_TYPE, F("\n"));
+ }
+ }
+
+ if (state != '2')
+ broadcastReply(COMMAND_TYPE, F("\n"),state);
#ifdef CD_HANDLE_RING
- broadcastReply(WITHROTTLE_TYPE, F("PPA%c\n"), main?'1':'0');
+ // send '1' if all main are on, otherwise global state (which in that case is '0' or '2')
+ broadcastReply(WITHROTTLE_TYPE, F("PPA%c\n"), main?'1': state);
#endif
- LCD(2,F("Power %S%S"),state=='1'?F("On"):F("Off"),reason);
+
+ LCD(2,F("Power %S %S"),state=='1'?F("On"): ( state=='0'? F("Off") : F("SC") ),reason);
}
void CommandDistributor::broadcastRaw(clientType type, char * msg) {
diff --git a/TrackManager.cpp b/TrackManager.cpp
index 846c163..ac44c76 100644
--- a/TrackManager.cpp
+++ b/TrackManager.cpp
@@ -54,7 +54,6 @@ const int16_t HASH_KEYWORD_INV = 11857;
MotorDriver * TrackManager::track[MAX_TRACKS];
int16_t TrackManager::trackDCAddr[MAX_TRACKS];
-POWERMODE TrackManager::mainPowerGuess=POWERMODE::OFF;
byte TrackManager::lastTrack=0;
bool TrackManager::progTrackSyncMain=false;
bool TrackManager::progTrackBoosted=false;
@@ -210,6 +209,9 @@ void TrackManager::setDCSignal(int16_t cab, byte speedbyte) {
bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr) {
if (trackToSet>lastTrack || track[trackToSet]==NULL) return false;
+ // Remember track mode we came from for later
+ TRACK_MODE oldmode = track[trackToSet]->getMode();
+
//DIAG(F("Track=%c Mode=%d"),trackToSet+'A', mode);
// DC tracks require a motorDriver that can set brake!
if (mode & TRACK_MODE_DC) {
@@ -262,7 +264,7 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr
track[t]->setPower(POWERMODE::OFF);
track[t]->setMode(TRACK_MODE_NONE);
track[t]->makeProgTrack(false); // revoke prog track special handling
- streamTrackState(NULL,t);
+ streamTrackState(NULL,t);
}
track[trackToSet]->makeProgTrack(true); // set for prog track special handling
} else {
@@ -270,7 +272,6 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr
}
track[trackToSet]->setMode(mode);
trackDCAddr[trackToSet]=dcAddr;
- streamTrackState(NULL,trackToSet);
// When a track is switched, we must clear any side effects of its previous
// state, otherwise trains run away or just dont move.
@@ -337,10 +338,11 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr
applyDCSpeed(trackToSet);
}
- // Normal running tracks are set to the global power state
- track[trackToSet]->setPower(
- (mode & (TRACK_MODE_MAIN | TRACK_MODE_DC | TRACK_MODE_EXT | TRACK_MODE_BOOST)) ?
- mainPowerGuess : POWERMODE::OFF);
+ // Turn off power if we changed the mode of this track
+ if (mode != oldmode)
+ track[trackToSet]->setPower(POWERMODE::OFF);
+ streamTrackState(NULL,trackToSet);
+
//DIAG(F("TrackMode=%d"),mode);
return true;
}
diff --git a/TrackManager.h b/TrackManager.h
index f2a357d..12adb4e 100644
--- a/TrackManager.h
+++ b/TrackManager.h
@@ -77,9 +77,13 @@ class TrackManager {
static void loop();
static POWERMODE getMainPower();
static POWERMODE getProgPower();
+ static inline POWERMODE getPower(byte t) { return track[t]->getPower(); }
static bool getPower(byte t, char s[]);
static void setJoin(bool join);
static bool isJoined() { return progTrackSyncMain;}
+ static inline bool isActive (byte tr) {
+ if (tr > lastTrack) return false;
+ return track[tr]->getMode() & (TRACK_MODE_MAIN|TRACK_MODE_PROG|TRACK_MODE_DC|TRACK_MODE_BOOST|TRACK_MODE_EXT);}
static void setJoinRelayPin(byte joinRelayPin);
static void sampleCurrent();
static void reportGauges(Print* stream);
@@ -108,7 +112,6 @@ class TrackManager {
static void addTrack(byte t, MotorDriver* driver);
static byte lastTrack;
static byte nextCycleTrack;
- static POWERMODE mainPowerGuess;
static void applyDCSpeed(byte t);
static int16_t trackDCAddr[MAX_TRACKS]; // dc address if TRACK_MODE_DC
From a16214790ee5cc003204c80864a6e6afe43711b2 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Thu, 23 Nov 2023 10:49:15 +0100
Subject: [PATCH 51/64] version 5.2.8
---
GITHUB_SHA.h | 2 +-
version.h | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h
index 42f43fd..28aa3fe 100644
--- a/GITHUB_SHA.h
+++ b/GITHUB_SHA.h
@@ -1 +1 @@
-#define GITHUB_SHA "devel-202311220953Z"
+#define GITHUB_SHA "devel-202311230948Z"
diff --git a/version.h b/version.h
index b2829c7..a39bdc3 100644
--- a/version.h
+++ b/version.h
@@ -3,7 +3,9 @@
#include "StringFormatter.h"
-#define VERSION "5.2.7"
+#define VERSION "5.2.8"
+// 5.2.8 - Bugfix: Do not turn off all tracks on change
+// give better power messages
// 5.2.7 - Bugfix: EXRAIL ling segment
// - Bugfix: Back out wrongly added const
// - Bugfix ESP32: Do not inverse DCX direction signal twice
From 2075bc50e827851c2ed8ad5f918c945377f6320f Mon Sep 17 00:00:00 2001
From: Asbelos
Date: Thu, 23 Nov 2023 10:41:35 +0000
Subject: [PATCH 52/64] EXRAIL basic stash implementation
---
EXRAIL2.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++--
EXRAIL2.h | 4 ++++
EXRAIL2MacroReset.h | 12 ++++++++++--
EXRAILMacros.h | 13 +++++++++++++
myHalKCS.cpp | 1 -
5 files changed, 71 insertions(+), 5 deletions(-)
delete mode 100644 myHalKCS.cpp
diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp
index 6f0a835..f085700 100644
--- a/EXRAIL2.cpp
+++ b/EXRAIL2.cpp
@@ -86,6 +86,8 @@ LookList * RMFT2::onRotateLookup=NULL;
LookList * RMFT2::onOverloadLookup=NULL;
byte * RMFT2::routeStateArray=nullptr;
const FSH * * RMFT2::routeCaptionArray=nullptr;
+int16_t * RMFT2::stashArray=nullptr;
+int16_t RMFT2::maxStashId=0;
// getOperand instance version, uses progCounter from instance.
uint16_t RMFT2::getOperand(byte n) {
@@ -232,6 +234,12 @@ if (compileFeatures & FEATURE_SIGNAL) {
IODevice::configureInput((VPIN)pin,true);
break;
}
+ case OPCODE_STASH:
+ case OPCODE_CLEAR_STASH:
+ case OPCODE_PICKUP_STASH: {
+ maxStashId=max(maxStashId,((int16_t)operand));
+ break;
+ }
case OPCODE_ATGTE:
case OPCODE_ATLT:
@@ -311,8 +319,14 @@ if (compileFeatures & FEATURE_SIGNAL) {
}
}
SKIPOP; // include ENDROUTES opcode
-
- DIAG(F("EXRAIL %db, fl=%d"),progCounter,MAX_FLAGS);
+
+ if (compileFeatures & FEATURE_STASH) {
+ // create the stash array from the highest id found
+ if (maxStashId>0) stashArray=(int16_t*)calloc(maxStashId+1, sizeof(int16_t));
+ //TODO check EEPROM and fetch stashArray
+ }
+
+ DIAG(F("EXRAIL %db, fl=%d, stash=%d"),progCounter,MAX_FLAGS, maxStashArray);
// Removed for 4.2.31 new RMFT2(0); // add the startup route
diag=saved_diag;
@@ -935,6 +949,34 @@ void RMFT2::loop2() {
case OPCODE_ROUTE_DISABLED:
manageRouteState(operand,4);
break;
+
+ case OPCODE_STASH:
+ if (compileFeatures & FEATURE_STASH)
+ stashArray[operand] = invert? -loco : loco;
+ break;
+
+ case OPCODE_CLEAR_STASH:
+ if (compileFeatures & FEATURE_STASH)
+ stashArray[operand] = 0;
+ break;
+
+ case OPCODE_CLEAR_ALL_STASH:
+ if (compileFeatures & FEATURE_STASH)
+ for (int i=0;i<=maxStashId;i++) stashArray[operand]=0;
+ break;
+
+ case OPCODE_PICKUP_STASH:
+ if (compileFeatures & FEATURE_STASH) {
+ int16_t x=stashArray[operand];
+ if (x>=0) {
+ loco=x;
+ invert=false;
+ break;
+ }
+ loco=-x;
+ invert=true;
+ }
+ break;
case OPCODE_ROUTE:
case OPCODE_AUTOMATION:
diff --git a/EXRAIL2.h b/EXRAIL2.h
index 5249f72..30a2f45 100644
--- a/EXRAIL2.h
+++ b/EXRAIL2.h
@@ -70,6 +70,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
OPCODE_ONOVERLOAD,
OPCODE_ROUTE_ACTIVE,OPCODE_ROUTE_INACTIVE,OPCODE_ROUTE_HIDDEN,
OPCODE_ROUTE_DISABLED,
+ OPCODE_STASH,OPCODE_CLEAR_STASH,OPCODE_CLEAR_ALL_STASH,OPCODE_PICKUP_STASH,
// OPcodes below this point are skip-nesting IF operations
// placed here so that they may be skipped as a group
@@ -102,6 +103,7 @@ enum thrunger: byte {
static const byte FEATURE_LCC = 0x40;
static const byte FEATURE_ROSTER= 0x20;
static const byte FEATURE_ROUTESTATE= 0x10;
+ static const byte FEATURE_STASH = 0x08;
// Flag bits for status of hardware and TPL
@@ -229,6 +231,8 @@ private:
static void manageRouteCaption(uint16_t id, const FSH* caption);
static byte * routeStateArray;
static const FSH ** routeCaptionArray;
+ static int16_t * stashArray;
+ static int16_t maxStashId;
// Local variables - exist for each instance/task
RMFT2 *next; // loop chain
diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h
index ee240ed..9d23f04 100644
--- a/EXRAIL2MacroReset.h
+++ b/EXRAIL2MacroReset.h
@@ -39,6 +39,8 @@
#undef AUTOSTART
#undef BROADCAST
#undef CALL
+#undef CLEAR_STASH
+#undef CLEAR_ALL_STASH
#undef CLOSE
#undef DCC_SIGNAL
#undef DCC_TURNTABLE
@@ -108,6 +110,7 @@
#undef ONCHANGE
#undef PARSE
#undef PAUSE
+#undef PICKUP_STASH
#undef PIN_TURNOUT
#undef PRINT
#ifndef DISABLE_PROG
@@ -152,6 +155,7 @@
#undef SIGNALH
#undef SPEED
#undef START
+#undef STASH
#undef STOP
#undef THROW
#undef TT_ADDPOSITION
@@ -184,7 +188,9 @@
#define AUTOMATION(id,description)
#define AUTOSTART
#define BROADCAST(msg)
-#define CALL(route)
+#define CALL(route)
+#define CLEAR_STASH(id)
+#define CLEAR_ALL_STASH(id)
#define CLOSE(id)
#define DCC_SIGNAL(id,add,subaddr)
#define DCC_TURNTABLE(id,home,description)
@@ -256,6 +262,7 @@
#define PIN_TURNOUT(id,pin,description...)
#define PRINT(msg)
#define PARSE(msg)
+#define PICKUP_STASH(id)
#ifndef DISABLE_PROG
#define POM(cv,value)
#endif
@@ -297,7 +304,8 @@
#define SIGNAL(redpin,amberpin,greenpin)
#define SIGNALH(redpin,amberpin,greenpin)
#define SPEED(speed)
-#define START(route)
+#define START(route)
+#define STASH(id)
#define STOP
#define THROW(id)
#define TT_ADDPOSITION(turntable_id,position,value,angle,description...)
diff --git a/EXRAILMacros.h b/EXRAILMacros.h
index 0e9842c..ac76efc 100644
--- a/EXRAILMacros.h
+++ b/EXRAILMacros.h
@@ -113,6 +113,15 @@ void exrailHalSetup() {
#undef ROUTE_CAPTION
#define ROUTE_CAPTION(id,caption) | FEATURE_ROUTESTATE
+#undef CLEAR_STASH
+#define CLEAR_STASH(id) | FEATURE_STASH
+#undef CLEAR_ALL_STASH
+#define CLEAR_ALL_STASH | FEATURE_STASH
+#undef PICKUP_STASH
+#define PICKUP_STASH(id) | FEATURE_STASH
+#undef STASH
+#define STASH(id) | FEATURE_STASH
+
const byte RMFT2::compileFeatures = 0
#include "myAutomation.h"
;
@@ -353,6 +362,8 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#define AUTOSTART OPCODE_AUTOSTART,0,0,
#define BROADCAST(msg) PRINT(msg)
#define CALL(route) OPCODE_CALL,V(route),
+#define CLEAR_STASH(id) OPCODE_CLEAR_STASH,V(id),
+#define CLEAR_ALL_STASH OPCODE_CLEAR_ALL_STASH,V(0),
#define CLOSE(id) OPCODE_CLOSE,V(id),
#ifndef IO_NO_HAL
#define DCC_TURNTABLE(id,home,description...) OPCODE_DCCTURNTABLE,V(id),OPCODE_PAD,V(home),
@@ -435,6 +446,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#define ONTHROW(turnout_id) OPCODE_ONTHROW,V(turnout_id),
#define ONCHANGE(sensor_id) OPCODE_ONCHANGE,V(sensor_id),
#define PAUSE OPCODE_PAUSE,0,0,
+#define PICKUP_STASH(id) OPCODE_PICKUP_STASH,V(id),
#define PIN_TURNOUT(id,pin,description...) OPCODE_PINTURNOUT,V(id),OPCODE_PAD,V(pin),
#ifndef DISABLE_PROG
#define POM(cv,value) OPCODE_POM,V(cv),OPCODE_PAD,V(value),
@@ -482,6 +494,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#define SIGNALH(redpin,amberpin,greenpin)
#define SPEED(speed) OPCODE_SPEED,V(speed),
#define START(route) OPCODE_START,V(route),
+#define STASH(id) OPCODE_STASH,V(id),
#define STOP OPCODE_SPEED,V(0),
#define THROW(id) OPCODE_THROW,V(id),
#ifndef IO_NO_HAL
diff --git a/myHalKCS.cpp b/myHalKCS.cpp
deleted file mode 100644
index a330ae7..0000000
--- a/myHalKCS.cpp
+++ /dev/null
@@ -1 +0,0 @@
-// If you are planning to use multiple mux devices, perhaps it is good to use the 3-position syntax for all.
From a5ccb2e29e297d3743f3b8e8a3edcc17fd807842 Mon Sep 17 00:00:00 2001
From: Asbelos
Date: Thu, 23 Nov 2023 14:15:58 +0000
Subject: [PATCH 53/64] EXRAIL STASH
---
DCCEXParser.cpp | 7 +++++++
EXRAIL2.cpp | 2 +-
EXRAIL2Parser.cpp | 41 +++++++++++++++++++++++++++++++++++++++--
version.h | 4 +++-
4 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp
index 8a81616..abbf54a 100644
--- a/DCCEXParser.cpp
+++ b/DCCEXParser.cpp
@@ -160,6 +160,7 @@ const int16_t HASH_KEYWORD_C='C';
const int16_t HASH_KEYWORD_G='G';
const int16_t HASH_KEYWORD_H='H';
const int16_t HASH_KEYWORD_I='I';
+const int16_t HASH_KEYWORD_M='M';
const int16_t HASH_KEYWORD_O='O';
const int16_t HASH_KEYWORD_P='P';
const int16_t HASH_KEYWORD_R='R';
@@ -729,6 +730,12 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
StringFormatter::send(stream, F("\n"));
return;
+ case HASH_KEYWORD_M: // intercepted by EXRAIL
+ if (params>1) break; // invalid cant do
+ // requests stash size so say none.
+ StringFormatter::send(stream,F("\n"));
+ return;
+
case HASH_KEYWORD_R: // returns rosters
StringFormatter::send(stream, F(" commands to do the following:
// - Implement RMFT specific commands/diagnostics
@@ -149,7 +151,33 @@ void RMFT2::ComandFilter(Print * stream, byte & opcode, byte & paramCount, int16
opcode=0;
return;
}
- break;
+ break;
+ case HASH_KEYWORD_M:
+ // NOTE: we only need to handle valid calls here because
+ // DCCEXParser has to have code to handle the cases where
+ // exrail isnt involved anyway.
+ // This entire code block is compiled out if STASH macros not used
+ if (!(compileFeatures & FEATURE_STASH)) return;
+ if (paramCount==1) { //
+ StringFormatter::send(stream,F("\n"),maxStashId);
+ opcode=0;
+ break;
+ }
+ if (paramCount==2) { //
+ if (p[1]<=0 || p[1]>maxStashId) break;
+ StringFormatter::send(stream,F("\n"),
+ p[1],stashArray[p[1]]);
+ opcode=0;
+ break;
+ }
+ if (paramCount==3) { //
+ if (p[1]<=0 || p[1]>maxStashId) break;
+ stashArray[p[1]]=p[2];
+ opcode=0;
+ break;
+ }
+ break;
+
default:
break;
}
@@ -195,6 +223,15 @@ bool RMFT2::parseSlash(Print * stream, byte & paramCount, int16_t p[]) {
sigid & SIGNAL_ID_MASK);
}
}
+
+ if (compileFeatures & FEATURE_STASH) {
+ for (int i=1;i<=maxStashId;i++) {
+ if (stashArray[i])
+ StringFormatter::send(stream,F("\nSTASH[%d] Loco=%d"),
+ i, stashArray[i]);
+ }
+ }
+
StringFormatter::send(stream,F(" *>\n"));
return true;
}
diff --git a/version.h b/version.h
index a39bdc3..2d89cd0 100644
--- a/version.h
+++ b/version.h
@@ -3,7 +3,9 @@
#include "StringFormatter.h"
-#define VERSION "5.2.8"
+#define VERSION "5.2.9"
+// 5.2.9 - Bugfix LCD startup with no LCD, uses <@
+// 5.2.9 - EXRAIL STASH feature
// 5.2.8 - Bugfix: Do not turn off all tracks on change
// give better power messages
// 5.2.7 - Bugfix: EXRAIL ling segment
From c8e307db7a63a0a3c16a990e32d6fc1cdab2245d Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Thu, 23 Nov 2023 22:11:00 +0100
Subject: [PATCH 54/64] remove unused TrackManager::reportPowerChange(...)
---
TrackManager.cpp | 9 ---------
TrackManager.h | 1 -
2 files changed, 10 deletions(-)
diff --git a/TrackManager.cpp b/TrackManager.cpp
index ac44c76..4021240 100644
--- a/TrackManager.cpp
+++ b/TrackManager.cpp
@@ -532,15 +532,6 @@ void TrackManager::setTrackPower(POWERMODE powermode, byte t) {
driver->setPower(powermode);
}
-void TrackManager::reportPowerChange(Print* stream, byte thistrack) {
- // This function is for backward JMRI compatibility only
- // It reports the first track only, as main, regardless of track settings.
- //
- int maxCurrent=track[0]->raw2mA(track[0]->getRawCurrentTripValue());
- StringFormatter::send(stream, F("\n"),
- track[0]->raw2mA(track[0]->getCurrentRaw(false)), maxCurrent, maxCurrent);
-}
-
// returns state of the one and only prog track
POWERMODE TrackManager::getProgPower() {
FOR_EACH_TRACK(t)
diff --git a/TrackManager.h b/TrackManager.h
index 12adb4e..dd38b72 100644
--- a/TrackManager.h
+++ b/TrackManager.h
@@ -88,7 +88,6 @@ class TrackManager {
static void sampleCurrent();
static void reportGauges(Print* stream);
static void reportCurrent(Print* stream);
- static void reportPowerChange(Print* stream, byte thistrack);
static void reportObsoleteCurrent(Print* stream);
static void streamTrackState(Print* stream, byte t);
static bool isPowerOn(byte t);
From 697f228a05d990e028d4085ab1c6d36553d46519 Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Thu, 23 Nov 2023 22:14:24 +0100
Subject: [PATCH 55/64] Save progmem with DISABLE_VDPY on Uno
---
DCCEXParser.cpp | 4 +++-
StringFormatter.cpp | 11 ++++++++---
config.example.h | 12 ++++++++++++
defines.h | 9 ++++-----
4 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp
index abbf54a..f3cdfb2 100644
--- a/DCCEXParser.cpp
+++ b/DCCEXParser.cpp
@@ -847,13 +847,14 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
case 'L': // LCC interface implemented in EXRAIL parser
break; // Will if not intercepted by EXRAIL
+#ifndef DISABLE_VDPY
case '@': // JMRI saying "give me virtual LCD msgs"
CommandDistributor::setVirtualLCDSerial(stream);
StringFormatter::send(stream,
F("<@ 0 0 \"DCC-EX v" VERSION "\">\n"
"<@ 0 1 \"Lic GPLv3\">\n"));
return;
-
+#endif
default: //anything else will diagnose and drop out to
if (opcode >= ' ' && opcode <= '~') {
DIAG(F("Opcode=%c params=%d"), opcode, params);
@@ -1064,6 +1065,7 @@ bool DCCEXParser::parseS(Print *stream, int16_t params, int16_t p[])
}
bool DCCEXParser::parseC(Print *stream, int16_t params, int16_t p[]) {
+ (void)stream; // arg not used, maybe later?
if (params == 0)
return false;
switch (p[0])
diff --git a/StringFormatter.cpp b/StringFormatter.cpp
index 13b5825..9c69877 100644
--- a/StringFormatter.cpp
+++ b/StringFormatter.cpp
@@ -39,8 +39,11 @@ void StringFormatter::diag( const FSH* input...) {
void StringFormatter::lcd(byte row, const FSH* input...) {
va_list args;
+#ifndef DISABLE_VDPY
Print * virtualLCD=CommandDistributor::getVirtualLCDSerial(0,row);
-
+#else
+ Print * virtualLCD=NULL;
+#endif
// Issue the LCD as a diag first
// Unless the same serial is asking for the virtual @ respomnse
if (virtualLCD!=&USB_SERIAL) {
@@ -50,13 +53,14 @@ void StringFormatter::lcd(byte row, const FSH* input...) {
send(&USB_SERIAL,F(" *>\n"));
}
+#ifndef DISABLE_VDPY
// send to virtual LCD collector (if any)
if (virtualLCD) {
va_start(args, input);
send2(virtualLCD,input,args);
CommandDistributor::commitVirtualLCDSerial();
}
-
+#endif
DisplayInterface::setRow(row);
va_start(args, input);
send2(DisplayInterface::getDisplayHandler(),input,args);
@@ -66,12 +70,14 @@ void StringFormatter::lcd2(uint8_t display, byte row, const FSH* input...) {
va_list args;
// send to virtual LCD collector (if any)
+#ifndef DISABLE_VDPY
Print * virtualLCD=CommandDistributor::getVirtualLCDSerial(display,row);
if (virtualLCD) {
va_start(args, input);
send2(virtualLCD,input,args);
CommandDistributor::commitVirtualLCDSerial();
}
+#endif
DisplayInterface::setRow(display, row);
va_start(args, input);
@@ -250,4 +256,3 @@ void StringFormatter::printHex(Print * stream,uint16_t value) {
result[4]='\0';
stream->print(result);
}
-
\ No newline at end of file
diff --git a/config.example.h b/config.example.h
index 9909371..89d6c1f 100644
--- a/config.example.h
+++ b/config.example.h
@@ -199,6 +199,18 @@ The configuration file for DCC-EX Command Station
//
// #define DISABLE_PROG
+/////////////////////////////////////////////////////////////////////////////////////
+// DISABLE / ENABLE VDPY
+//
+// The Virtual display "VDPY" feature is by default enabled everywhere
+// but on Uno and Nano. If you think you can fit it (for example
+// having disabled some of the features above) you can enable it with
+// ENABLE_VDPY. You can even disable it on all other CPUs with
+// DISABLE_VDPY
+//
+// #define DISABLE_VDPY
+// #define ENABLE_VDPY
+
/////////////////////////////////////////////////////////////////////////////////////
// REDEFINE WHERE SHORT/LONG ADDR break is. According to NMRA the last short address
// is 127 and the first long address is 128. There are manufacturers which have
diff --git a/defines.h b/defines.h
index e90d7f4..14dd1c5 100644
--- a/defines.h
+++ b/defines.h
@@ -219,11 +219,10 @@
// 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(DISABLE_DIAG) && defined(DISABLE_EEPROM) && defined(DISABLE_PROG)
- #warning you have sacrificed DIAG for HAL
- #else
- #define IO_NO_HAL
- #endif
+#define IO_NO_HAL // HAL too big whatever you disable otherwise
+#ifndef ENABLE_VDPY
+#define DISABLE_VDPY
+#endif
#endif
#if __has_include ( "myAutomation.h")
From ebaf1b984ef66084b5534083ef1a81500c57b79d Mon Sep 17 00:00:00 2001
From: Harald Barth
Date: Thu, 23 Nov 2023 22:15:03 +0100
Subject: [PATCH 56/64] version tag
---
GITHUB_SHA.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h
index 28aa3fe..42d5594 100644
--- a/GITHUB_SHA.h
+++ b/GITHUB_SHA.h
@@ -1 +1 @@
-#define GITHUB_SHA "devel-202311230948Z"
+#define GITHUB_SHA "devel-202311232114Z"
From 96fdbfdc89843a75ec69a1b8ded71161ba1de2e1 Mon Sep 17 00:00:00 2001
From: Asbelos
Date: Sun, 26 Nov 2023 12:31:41 +0000
Subject: [PATCH 57/64] Trainbrains block occupancy
---
IODevice.h | 2 +
IO_trainbrains.h | 98 ++++++++++++++++++++++++++++++++++++++++++++++++
version.h | 4 +-
3 files changed, 103 insertions(+), 1 deletion(-)
create mode 100644 IO_trainbrains.h
diff --git a/IODevice.h b/IODevice.h
index 74fe49b..d12fafd 100644
--- a/IODevice.h
+++ b/IODevice.h
@@ -542,8 +542,10 @@ protected:
#include "IO_MCP23017.h"
#include "IO_PCF8574.h"
#include "IO_PCF8575.h"
+#include "IO_PCA9555.h"
#include "IO_duinoNodes.h"
#include "IO_EXIOExpander.h"
+#include "IO_trainbrains.h"
#endif // iodevice_h
diff --git a/IO_trainbrains.h b/IO_trainbrains.h
new file mode 100644
index 0000000..058fe02
--- /dev/null
+++ b/IO_trainbrains.h
@@ -0,0 +1,98 @@
+/*
+ * © 2023, Chris Harlow. All rights reserved.
+ * © 2021, Neil McKechnie. All rights reserved.
+ *
+ * This file is part of DCC++EX API
+ *
+ * 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 .
+ */
+
+#ifndef io_trainbrains_h
+#define io_trainbrains_h
+
+#include "IO_GPIOBase.h"
+#include "FSH.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ * IODevice subclass for trainbrains 3-block occupancy detector.
+ * For details see http://trainbrains.eu
+ */
+
+ enum TrackUnoccupancy
+{
+ TRACK_UNOCCUPANCY_UNKNOWN = 0,
+ TRACK_OCCUPIED = 1,
+ TRACK_UNOCCUPIED = 2
+};
+
+class Trainbrains02 : public GPIOBase {
+public:
+ static void create(VPIN vpin, uint8_t nPins, I2CAddress i2cAddress) {
+ if (checkNoOverlap(vpin, nPins, i2cAddress)) new Trainbrains02(vpin, nPins, i2cAddress);
+ }
+
+private:
+ // Constructor
+ Trainbrains02(VPIN vpin, uint8_t nPins, I2CAddress i2cAddress, int interruptPin=-1)
+ : GPIOBase((FSH *)F("Trainbrains02"), vpin, nPins, i2cAddress, interruptPin)
+ {
+ requestBlock.setRequestParams(_I2CAddress, inputBuffer, sizeof(inputBuffer),
+ outputBuffer, sizeof(outputBuffer));
+
+ outputBuffer[0] = (uint8_t)_I2CAddress; // strips away the mux part.
+ outputBuffer[1] =14;
+ outputBuffer[2] =1;
+ outputBuffer[3] =0; // This is the channel updated at each poling call
+ outputBuffer[4] =0;
+ outputBuffer[5] =0;
+ outputBuffer[6] =0;
+ outputBuffer[7] =0;
+ outputBuffer[8] =0;
+ outputBuffer[9] =0;
+ }
+
+ void _writeGpioPort() override {}
+
+ void _readGpioPort(bool immediate) override {
+ // cycle channel on device each time
+ outputBuffer[3]=channelInProgress+1; // 1-origin
+ channelInProgress++;
+ if(channelInProgress>=_nPins) channelInProgress=0;
+
+ if (immediate) {
+ _processCompletion(I2CManager.read(_I2CAddress, inputBuffer, sizeof(inputBuffer),
+ outputBuffer, sizeof(outputBuffer)));
+ } else {
+ // Queue new request
+ requestBlock.wait(); // Wait for preceding operation to complete
+ // Issue new request to read GPIO register
+ I2CManager.queueRequest(&requestBlock);
+ }
+ }
+
+ // This function is invoked when an I/O operation on the requestBlock completes.
+ void _processCompletion(uint8_t status) override {
+ if (status != I2C_STATUS_OK) inputBuffer[6]=TRACK_UNOCCUPANCY_UNKNOWN;
+ if (inputBuffer[6] == TRACK_UNOCCUPIED ) _portInputState |= 0x01 <
Date: Mon, 27 Nov 2023 08:15:07 +0100
Subject: [PATCH 58/64] Change from TrackManager::returnMode to
TrackManager::getMode
---
GITHUB_SHA.h | 2 +-
TrackManager.cpp | 2 +-
TrackManager.h | 2 +-
version.h | 3 ++-
4 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h
index 42d5594..23c6a6e 100644
--- a/GITHUB_SHA.h
+++ b/GITHUB_SHA.h
@@ -1 +1 @@
-#define GITHUB_SHA "devel-202311232114Z"
+#define GITHUB_SHA "devel-202311270714Z"
diff --git a/TrackManager.cpp b/TrackManager.cpp
index 4021240..7d2b36b 100644
--- a/TrackManager.cpp
+++ b/TrackManager.cpp
@@ -641,7 +641,7 @@ bool TrackManager::isProg(byte t) {
return false;
}
-byte TrackManager::returnMode(byte t) {
+TRACK_MODE TrackManager::getMode(byte t) {
return (track[t]->getMode());
}
diff --git a/TrackManager.h b/TrackManager.h
index dd38b72..6310030 100644
--- a/TrackManager.h
+++ b/TrackManager.h
@@ -92,7 +92,7 @@ class TrackManager {
static void streamTrackState(Print* stream, byte t);
static bool isPowerOn(byte t);
static bool isProg(byte t);
- static byte returnMode(byte t);
+ static TRACK_MODE getMode(byte t);
static int16_t returnDCAddr(byte t);
static const FSH* getModeName(TRACK_MODE Mode);
diff --git a/version.h b/version.h
index 3937937..e8a5e81 100644
--- a/version.h
+++ b/version.h
@@ -3,7 +3,8 @@
#include "StringFormatter.h"
-#define VERSION "5.2.10"
+#define VERSION "5.2.11"
+// 5.2.11 - Change from TrackManager::returnMode to TrackManager::getMode
// 5.2.10 - Include trainbrains.eu block unoccupancy driver
// - include IO_PCA9555
// 5.2.9 - Bugfix LCD startup with no LCD, uses <@
From 07fd4bc309c333e9fccc98f4287ec1866a8cd0aa Mon Sep 17 00:00:00 2001
From: Asbelos
Date: Mon, 27 Nov 2023 16:49:02 +0000
Subject: [PATCH 59/64] Window
---
DCC.cpp | 2 +-
DCCWaveform.cpp | 67 +++++++++++++++++++++++++++++++------------------
DCCWaveform.h | 4 ++-
3 files changed, 46 insertions(+), 27 deletions(-)
diff --git a/DCC.cpp b/DCC.cpp
index 30fcf5f..e576812 100644
--- a/DCC.cpp
+++ b/DCC.cpp
@@ -595,7 +595,7 @@ void DCC::loop() {
void DCC::issueReminders() {
// if the main track transmitter still has a pending packet, skip this time around.
- if ( DCCWaveform::mainTrack.getPacketPending()) return;
+ if (!DCCWaveform::mainTrack.isReminderWindowOpen()) return;
// Move to next loco slot. If occupied, send a reminder.
int reg = lastLocoReminder+1;
if (reg > highestUsedReg) reg = 0; // Go to start of table
diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp
index 4a99997..0e9667a 100644
--- a/DCCWaveform.cpp
+++ b/DCCWaveform.cpp
@@ -106,6 +106,7 @@ void DCCWaveform::interruptHandler() {
DCCWaveform::DCCWaveform( byte preambleBits, bool isMain) {
isMainTrack = isMain;
packetPending = false;
+ reminderWindowOpen = false;
memcpy(transmitPacket, idlePacket, sizeof(idlePacket));
state = WAVE_START;
// The +1 below is to allow the preamble generator to create the stop bit
@@ -127,9 +128,15 @@ void DCCWaveform::interrupt2() {
if (remainingPreambles > 0 ) {
state=WAVE_MID_1; // switch state to trigger LOW on next interrupt
remainingPreambles--;
+
+ // As we get to the end of the preambles, open the reminder window.
+ // This delays any reminder insertion until the last moment so
+ // that the reminder doesn't block a more urgent packet.
+ reminderWindowOpen=transmitRepeats==0 && remainingPreambles<4 && remainingPreambles>1;
+ if (remainingPreambles==1) promotePendingPacket();
// Update free memory diagnostic as we don't have anything else to do this time.
// Allow for checkAck and its called functions using 22 bytes more.
- DCCTimer::updateMinimumFreeMemoryISR(22);
+ else DCCTimer::updateMinimumFreeMemoryISR(22);
return;
}
@@ -148,30 +155,9 @@ void DCCWaveform::interrupt2() {
if (bytes_sent >= transmitLength) {
// end of transmission buffer... repeat or switch to next message
bytes_sent = 0;
+ // preamble for next packet will start...
remainingPreambles = requiredPreambles;
-
- if (transmitRepeats > 0) {
- transmitRepeats--;
}
- else if (packetPending) {
- // Copy pending packet to transmit packet
- // a fixed length memcpy is faster than a variable length loop for these small lengths
- // for (int b = 0; b < pendingLength; b++) transmitPacket[b] = pendingPacket[b];
- memcpy( transmitPacket, pendingPacket, sizeof(pendingPacket));
-
- transmitLength = pendingLength;
- transmitRepeats = pendingRepeats;
- packetPending = false;
- clearResets();
- }
- else {
- // Fortunately reset and idle packets are the same length
- memcpy( transmitPacket, isMainTrack ? idlePacket : resetPacket, sizeof(idlePacket));
- transmitLength = sizeof(idlePacket);
- transmitRepeats = 0;
- if (getResets() < 250) sentResetsSincePacket++; // only place to increment (private!)
- }
- }
}
}
#pragma GCC pop_options
@@ -193,8 +179,39 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea
packetPending = true;
clearResets();
}
-bool DCCWaveform::getPacketPending() {
- return packetPending;
+
+bool DCCWaveform::isReminderWindowOpen() {
+ return reminderWindowOpen && ! packetPending;
+}
+
+void DCCWaveform::promotePendingPacket() {
+ // fill the transmission packet from the pending packet
+
+ // Just keep going if repeating
+ if (transmitRepeats > 0) {
+ transmitRepeats--;
+ return;
+ }
+
+ if (packetPending) {
+ // Copy pending packet to transmit packet
+ // a fixed length memcpy is faster than a variable length loop for these small lengths
+ // for (int b = 0; b < pendingLength; b++) transmitPacket[b] = pendingPacket[b];
+ memcpy( transmitPacket, pendingPacket, sizeof(pendingPacket));
+
+ transmitLength = pendingLength;
+ transmitRepeats = pendingRepeats;
+ packetPending = false;
+ clearResets();
+ return;
+ }
+
+ // nothing to do, just send idles or resets
+ // Fortunately reset and idle packets are the same length
+ memcpy( transmitPacket, isMainTrack ? idlePacket : resetPacket, sizeof(idlePacket));
+ transmitLength = sizeof(idlePacket);
+ transmitRepeats = 0;
+ if (getResets() < 250) sentResetsSincePacket++; // only place to increment (private!)
}
#endif
diff --git a/DCCWaveform.h b/DCCWaveform.h
index 1dad1b2..2202b53 100644
--- a/DCCWaveform.h
+++ b/DCCWaveform.h
@@ -76,11 +76,13 @@ class DCCWaveform {
};
#endif
void schedulePacket(const byte buffer[], byte byteCount, byte repeats);
- bool getPacketPending();
+ bool isReminderWindowOpen();
+ void promotePendingPacket();
private:
#ifndef ARDUINO_ARCH_ESP32
volatile bool packetPending;
+ volatile bool reminderWindowOpen;
volatile byte sentResetsSincePacket;
#else
volatile uint32_t resetPacketBase;
From 3f4099520aaa75c56f7bdbc3a222f094acc4210e Mon Sep 17 00:00:00 2001
From: Asbelos
Date: Tue, 28 Nov 2023 19:57:14 +0000
Subject: [PATCH 60/64] ESP32 update for reminders
---
DCCWaveform.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp
index 0e9667a..93b21a2 100644
--- a/DCCWaveform.cpp
+++ b/DCCWaveform.cpp
@@ -283,15 +283,15 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea
}
}
-bool DCCWaveform::getPacketPending() {
+bool DCCWaveform::isReminderWindowOpen() {
if(isMainTrack) {
if (rmtMainChannel == NULL)
- return true;
- return rmtMainChannel->busy();
+ return false;
+ return !rmtMainChannel->busy();
} else {
if (rmtProgChannel == NULL)
- return true;
- return rmtProgChannel->busy();
+ return false;
+ return !rmtProgChannel->busy();
}
}
void IRAM_ATTR DCCWaveform::loop() {
From 753567427ed99de4bd7a1016826c1439d79062d4 Mon Sep 17 00:00:00 2001
From: pmantoine
Date: Thu, 30 Nov 2023 14:38:16 +0800
Subject: [PATCH 61/64] ESP32 LCD messages, STM32 minor updates
---
DCCTimerSTM32.cpp | 15 ++++++++++-----
WifiESP32.cpp | 12 +++++++++---
version.h | 5 ++++-
3 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/DCCTimerSTM32.cpp b/DCCTimerSTM32.cpp
index f2d51ff..f24adc2 100644
--- a/DCCTimerSTM32.cpp
+++ b/DCCTimerSTM32.cpp
@@ -50,11 +50,16 @@ HardwareSerial Serial6(PA12, PA11); // Rx=PA12, Tx=PA11 -- CN10 pins 12 and 14
// via the debugger on the Nucleo-64. It is therefore unavailable for other DCC-EX uses like WiFi, DFPlayer, etc.
// On the F446RE, Serial3 and Serial5 are easy to use:
HardwareSerial Serial3(PC11, PC10); // Rx=PC11, Tx=PC10 -- USART3 - F446RE
-HardwareSerial Serial5(PD2, PC12); // Rx=PC7, Tx=PC6 -- UART5 - F446RE
+HardwareSerial Serial5(PD2, PC12); // Rx=PD2, Tx=PC12 -- UART5 - F446RE
// On the F446RE, Serial4 and Serial6 also use pins we can't readily map while using the Arduino pins
-#elif defined(ARDUINO_NUCLEO_F412ZG) || defined(ARDUINO_NUCLEO_F413ZH) || defined(ARDUINO_NUCLEO_F429ZI) || defined(ARDUINO_NUCLEO_F446ZE)
+#elif defined(ARDUINO_NUCLEO_F412ZG) || defined(ARDUINO_NUCLEO_F413ZH) || defined(ARDUINO_NUCLEO_F446ZE) || \
+ defined(ARDUINO_NUCLEO_F429ZI) || defined(ARDUINO_NUCLEO_F439ZI)
// Nucleo-144 boards don't have Serial1 defined by default
HardwareSerial Serial6(PG9, PG14); // Rx=PG9, Tx=PG14 -- USART6
+HardwareSerial Serial5(PD2, PC12); // Rx=PD2, Tx=PC12 -- UART5
+#if !defined(ARDUINO_NUCLEO_F412ZG)
+ HardwareSerial Serial2(PD6, PD5); // Rx=PD6, Tx=PD5 -- UART5
+#endif
// Serial3 is defined to use USART3 by default, but is in fact used as the diag console
// via the debugger on the Nucleo-144. It is therefore unavailable for other DCC-EX uses like WiFi, DFPlayer, etc.
#else
@@ -215,9 +220,9 @@ void DCCTimer::clearPWM() {
}
void DCCTimer::getSimulatedMacAddress(byte mac[6]) {
- volatile uint32_t *serno1 = (volatile uint32_t *)0x1FFF7A10;
- volatile uint32_t *serno2 = (volatile uint32_t *)0x1FFF7A14;
- // volatile uint32_t *serno3 = (volatile uint32_t *)0x1FFF7A18;
+ volatile uint32_t *serno1 = (volatile uint32_t *)UID_BASE;
+ volatile uint32_t *serno2 = (volatile uint32_t *)UID_BASE+4;
+ // volatile uint32_t *serno3 = (volatile uint32_t *)UID_BASE+8;
volatile uint32_t m1 = *serno1;
volatile uint32_t m2 = *serno2;
diff --git a/WifiESP32.cpp b/WifiESP32.cpp
index 28a15fe..f0a857f 100644
--- a/WifiESP32.cpp
+++ b/WifiESP32.cpp
@@ -163,7 +163,9 @@ bool WifiESP::setup(const char *SSid,
delay(500);
}
if (WiFi.status() == WL_CONNECTED) {
- DIAG(F("Wifi STA IP %s"),WiFi.localIP().toString().c_str());
+ // DIAG(F("Wifi STA IP %s"),WiFi.localIP().toString().c_str());
+ DIAG(F("Wifi in STA mode"));
+ LCD(7, F("IP: %s"), WiFi.softAPIP().toString().c_str());
wifiUp = true;
} else {
DIAG(F("Could not connect to Wifi SSID %s"),SSid);
@@ -209,8 +211,12 @@ bool WifiESP::setup(const char *SSid,
if (WiFi.softAP(strSSID.c_str(),
havePassword ? password : strPass.c_str(),
channel, false, 8)) {
- DIAG(F("Wifi AP SSID %s PASS %s"),strSSID.c_str(),havePassword ? password : strPass.c_str());
- DIAG(F("Wifi AP IP %s"),WiFi.softAPIP().toString().c_str());
+ // DIAG(F("Wifi AP SSID %s PASS %s"),strSSID.c_str(),havePassword ? password : strPass.c_str());
+ DIAG(F("Wifi in AP mode"));
+ LCD(5, F("Wifi: %s"), strSSID.c_str());
+ LCD(6, F("PASS: %s"),havePassword ? password : strPass.c_str());
+ // DIAG(F("Wifi AP IP %s"),WiFi.softAPIP().toString().c_str());
+ LCD(7, F("IP: %s"),WiFi.softAPIP().toString().c_str());
wifiUp = true;
APmode = true;
} else {
diff --git a/version.h b/version.h
index e8a5e81..a0cb16a 100644
--- a/version.h
+++ b/version.h
@@ -3,7 +3,10 @@
#include "StringFormatter.h"
-#define VERSION "5.2.11"
+#define VERSION "5.2.12"
+// 5.2.12 - ESP32 add AP mode LCD messages with SSID/PW for
+// - STM32 change to UID_BASE constants in DCCTimerSTM32 rather than raw hex addresses for UID registers
+// - STM32 extra UART/USARTs for larger Nucleo models
// 5.2.11 - Change from TrackManager::returnMode to TrackManager::getMode
// 5.2.10 - Include trainbrains.eu block unoccupancy driver
// - include IO_PCA9555
From 763c9d8ae6d2d46fe09cbaff4f4ac82bef94496a Mon Sep 17 00:00:00 2001
From: Asbelos
Date: Thu, 30 Nov 2023 11:32:39 +0000
Subject: [PATCH 62/64] STEALTH
---
EXRAIL2MacroReset.h | 2 ++
EXRAILMacros.h | 3 +++
version.h | 3 ++-
3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h
index 9d23f04..7811a0d 100644
--- a/EXRAIL2MacroReset.h
+++ b/EXRAIL2MacroReset.h
@@ -156,6 +156,7 @@
#undef SPEED
#undef START
#undef STASH
+#undef STEALTH
#undef STOP
#undef THROW
#undef TT_ADDPOSITION
@@ -306,6 +307,7 @@
#define SPEED(speed)
#define START(route)
#define STASH(id)
+#define STEALTH(code...)
#define STOP
#define THROW(id)
#define TT_ADDPOSITION(turntable_id,position,value,angle,description...)
diff --git a/EXRAILMacros.h b/EXRAILMacros.h
index ac76efc..f79693d 100644
--- a/EXRAILMacros.h
+++ b/EXRAILMacros.h
@@ -210,6 +210,8 @@ case (__COUNTER__ - StringMacroTracker1) : {\
lcdid=id;\
break;\
}
+#undef STEALTH
+#define STEALTH(code...) case (__COUNTER__ - StringMacroTracker1) : {code} return;
#undef WITHROTTLE
#define WITHROTTLE(msg) THRUNGE(msg,thrunge_withrottle)
@@ -422,6 +424,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
OPCODE_PAD,V((((uint64_t)sender)>>0)&0xFFFF),
#define LCD(id,msg) PRINT(msg)
#define SCREEN(display,id,msg) PRINT(msg)
+#define STEALTH(code...) PRINT(dummy)
#define LCN(msg) PRINT(msg)
#define MOVETT(id,steps,activity) OPCODE_SERVO,V(id),OPCODE_PAD,V(steps),OPCODE_PAD,V(EXTurntable::activity),OPCODE_PAD,V(0),
#define ONACTIVATE(addr,subaddr) OPCODE_ONACTIVATE,V(addr<<2|subaddr),
diff --git a/version.h b/version.h
index a0cb16a..0304500 100644
--- a/version.h
+++ b/version.h
@@ -3,7 +3,8 @@
#include "StringFormatter.h"
-#define VERSION "5.2.12"
+#define VERSION "5.2.13"
+// 5.2.13 - EXRAIL STEALTH
// 5.2.12 - ESP32 add AP mode LCD messages with SSID/PW for
// - STM32 change to UID_BASE constants in DCCTimerSTM32 rather than raw hex addresses for UID registers
// - STM32 extra UART/USARTs for larger Nucleo models
From a69017f8bbd71aa09e1c8bd53f6b44fe8d62d677 Mon Sep 17 00:00:00 2001
From: Asbelos
Date: Thu, 30 Nov 2023 19:48:02 +0000
Subject: [PATCH 63/64] Optional DISABLE_FUNCTION_REMINDERS
---
DCC.cpp | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/DCC.cpp b/DCC.cpp
index e576812..60c07df 100644
--- a/DCC.cpp
+++ b/DCC.cpp
@@ -620,14 +620,23 @@ bool DCC::issueReminder(int reg) {
case 1: // remind function group 1 (F0-F4)
if (flags & FN_GROUP_1)
setFunctionInternal(loco,0, 128 | ((functions>>1)& 0x0F) | ((functions & 0x01)<<4)); // 100D DDDD
+#ifdef DISABLE_FUNCTION_REMINDERS
+ flags&= ~FN_GROUP_1; // dont send them again
+#endif
break;
case 2: // remind function group 2 F5-F8
if (flags & FN_GROUP_2)
setFunctionInternal(loco,0, 176 | ((functions>>5)& 0x0F)); // 1011 DDDD
+#ifdef DISABLE_FUNCTION_REMINDERS
+ flags&= ~FN_GROUP_2; // dont send them again
+#endif
break;
case 3: // remind function group 3 F9-F12
if (flags & FN_GROUP_3)
setFunctionInternal(loco,0, 160 | ((functions>>9)& 0x0F)); // 1010 DDDD
+#ifdef DISABLE_FUNCTION_REMINDERS
+ flags&= ~FN_GROUP_3; // dont send them again
+#endif
break;
case 4: // remind function group 4 F13-F20
if (flags & FN_GROUP_4)
From 08f0a2b37de4297e045f7a2597c1b6786242b077 Mon Sep 17 00:00:00 2001
From: Asbelos
Date: Thu, 30 Nov 2023 19:56:58 +0000
Subject: [PATCH 64/64] 5.2.13
---
version.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/version.h b/version.h
index 0304500..a6265d8 100644
--- a/version.h
+++ b/version.h
@@ -3,7 +3,9 @@
#include "StringFormatter.h"
-#define VERSION "5.2.13"
+#define VERSION "5.2.14"
+// 5.2.14 - Reminder window DCC packet optimization
+// - Optional #define DISABLE_FUNCTION_REMINDERS
// 5.2.13 - EXRAIL STEALTH
// 5.2.12 - ESP32 add AP mode LCD messages with SSID/PW for
// - STM32 change to UID_BASE constants in DCCTimerSTM32 rather than raw hex addresses for UID registers