mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-07-29 18:33:44 +02:00
Compare commits
22 Commits
master-pac
...
devel-more
Author | SHA1 | Date | |
---|---|---|---|
|
c99eac6ada | ||
|
c93dd75323 | ||
|
519cabffb6 | ||
|
aa4306123d | ||
|
ccbff56355 | ||
|
e0aa16ff2c | ||
|
6b0dc272ea | ||
|
9602c32ea7 | ||
|
1235c288dc | ||
|
001c4664c1 | ||
|
9786ea9b3a | ||
|
6a35daab6b | ||
|
afff10df28 | ||
|
b9ce166028 | ||
|
0a96320fd0 | ||
|
9a6e1707e7 | ||
|
64a34b3a32 | ||
|
19f4869401 | ||
|
bcdf9cb1c5 | ||
|
701f4e852f | ||
|
657fb7009c | ||
|
e131a9cce8 |
@@ -56,8 +56,7 @@ template<typename... Targs> void CommandDistributor::broadcastReply(clientType t
|
||||
#ifdef CD_HANDLE_RING
|
||||
// wifi or ethernet ring streams with multiple client types
|
||||
RingStream * CommandDistributor::ring=0;
|
||||
CommandDistributor::clientType CommandDistributor::clients[8]={
|
||||
NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE};
|
||||
CommandDistributor::clientType CommandDistributor::clients[MAX_NUM_TCP_CLIENTS]={ NONE_TYPE }; // 0 is and must be NONE_TYPE
|
||||
|
||||
// Parse is called by Withrottle or Ethernet interface to determine which
|
||||
// protocol the client is using and call the appropriate part of dcc++Ex
|
||||
|
@@ -36,13 +36,13 @@
|
||||
|
||||
class CommandDistributor {
|
||||
public:
|
||||
enum clientType: byte {NONE_TYPE,COMMAND_TYPE,WITHROTTLE_TYPE};
|
||||
enum clientType: byte {NONE_TYPE=0,COMMAND_TYPE,WITHROTTLE_TYPE};
|
||||
private:
|
||||
static void broadcastToClients(clientType type);
|
||||
static StringBuffer * broadcastBufferWriter;
|
||||
#ifdef CD_HANDLE_RING
|
||||
static RingStream * ring;
|
||||
static clientType clients[8];
|
||||
static clientType clients[MAX_NUM_TCP_CLIENTS];
|
||||
#endif
|
||||
public :
|
||||
static void parse(byte clientId,byte* buffer, RingStream * ring);
|
||||
|
2
DCC.cpp
2
DCC.cpp
@@ -309,7 +309,6 @@ void DCC::setAccessory(int address, byte port, bool gate, byte onoff /*= 2*/) {
|
||||
b[0] = address % 64 + 128;
|
||||
b[1] = ((((address / 64) % 8) << 4) + (port % 4 << 1) + gate % 2) ^ 0xF8;
|
||||
if (onoff != 0) {
|
||||
DIAG(F("DCC::setAccessory(%d,%d,%d) ON"), address, port, gate);
|
||||
DCCWaveform::mainTrack.schedulePacket(b, 2, 3); // Repeat on packet three times
|
||||
#if defined(EXRAIL_ACTIVE)
|
||||
RMFT2::activateEvent(address<<2|port,gate);
|
||||
@@ -317,7 +316,6 @@ void DCC::setAccessory(int address, byte port, bool gate, byte onoff /*= 2*/) {
|
||||
}
|
||||
if (onoff != 1) {
|
||||
b[1] &= ~0x08; // set C to 0
|
||||
DIAG(F("DCC::setAccessory(%d,%d,%d) OFF"), address, port, gate);
|
||||
DCCWaveform::mainTrack.schedulePacket(b, 2, 3); // Repeat off packet three times
|
||||
}
|
||||
}
|
||||
|
12
DCCACK.cpp
12
DCCACK.cpp
@@ -67,24 +67,16 @@ CALLBACK_STATE DCCACK::callbackState=READY;
|
||||
ACK_CALLBACK DCCACK::ackManagerCallback;
|
||||
|
||||
void DCCACK::Setup(int cv, byte byteValueOrBitnum, ackOp const program[], ACK_CALLBACK callback) {
|
||||
// On ESP32 the joined track is hidden from sight (it has type MAIN)
|
||||
// and because of that we need first check if track was joined and
|
||||
// then unjoin if necessary. This requires that the joined flag is
|
||||
// cleared when the prog track is removed.
|
||||
ackManagerRejoin=TrackManager::isJoined();
|
||||
//DIAG(F("Joined is %d"), ackManagerRejoin);
|
||||
if (ackManagerRejoin) {
|
||||
// Change from JOIN must zero resets packet.
|
||||
TrackManager::setJoin(false);
|
||||
DCCWaveform::progTrack.clearResets();
|
||||
}
|
||||
|
||||
progDriver=TrackManager::getProgDriver();
|
||||
//DIAG(F("Progdriver is %d"), progDriver);
|
||||
if (progDriver==NULL) {
|
||||
if (ackManagerRejoin) {
|
||||
DIAG(F("Joined but no Prog track"));
|
||||
TrackManager::setJoin(false);
|
||||
}
|
||||
TrackManager::setJoin(ackManagerRejoin);
|
||||
callback(-3); // we dont have a prog track!
|
||||
return;
|
||||
}
|
||||
|
@@ -402,8 +402,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
||||
|| (p[activep] > 1) || (p[activep] < 0) // invalid activate 0|1
|
||||
) break;
|
||||
// Honour the configuration option (config.h) which allows the <a> command to be reversed
|
||||
// Because of earlier confusion we need to do the same thing under both defines
|
||||
#if defined(DCC_ACCESSORY_COMMAND_REVERSE) || defined(DCC_ACCESSORY_RCN_213)
|
||||
#ifdef DCC_ACCESSORY_COMMAND_REVERSE
|
||||
DCC::setAccessory(address, subaddress,p[activep]==0,onoff);
|
||||
#else
|
||||
DCC::setAccessory(address, subaddress,p[activep]==1,onoff);
|
||||
|
30
DCCRMT.cpp
30
DCCRMT.cpp
@@ -86,14 +86,6 @@ void setDCCBit0Long(rmt_item32_t* item) {
|
||||
item->duration1 = DCC_0_HALFPERIOD + DCC_0_HALFPERIOD/10;
|
||||
}
|
||||
|
||||
// special short one to trigger scope
|
||||
void setDCCBit1Short(rmt_item32_t* item) {
|
||||
item->level0 = 1;
|
||||
item->duration0 = DCC_1_HALFPERIOD/2;
|
||||
item->level1 = 0;
|
||||
item->duration1 = DCC_1_HALFPERIOD/2;
|
||||
}
|
||||
|
||||
void setEOT(rmt_item32_t* item) {
|
||||
item->val = 0;
|
||||
}
|
||||
@@ -143,17 +135,11 @@ RMTChannel::RMTChannel(pinpair pins, bool isMain) {
|
||||
// preamble
|
||||
preambleLen = plen+2; // plen 1 bits, one 0 bit and one EOF marker
|
||||
preamble = (rmt_item32_t*)malloc(preambleLen*sizeof(rmt_item32_t));
|
||||
#ifdef SCOPE
|
||||
for (byte n=0; n<plen; n++) {
|
||||
if (n == 0)
|
||||
setDCCBit1Short(preamble + n); // start of preamble 1 bit short version
|
||||
else
|
||||
setDCCBit1(preamble + n);
|
||||
}
|
||||
setDCCBit0Long(preamble + plen); // start of packet 0 bit long version
|
||||
#else
|
||||
for (byte n=0; n<plen; n++)
|
||||
setDCCBit1(preamble + n); // preamble bits
|
||||
#ifdef SCOPE
|
||||
setDCCBit0Long(preamble + plen); // start of packet 0 bit long version
|
||||
#else
|
||||
setDCCBit0(preamble + plen); // start of packet 0 bit normal version
|
||||
#endif
|
||||
setEOT(preamble + plen + 1); // EOT marker
|
||||
@@ -218,7 +204,6 @@ void RMTChannel::RMTprefill() {
|
||||
const byte transmitMask[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
|
||||
|
||||
int RMTChannel::RMTfillData(const byte buffer[], byte byteCount, byte repeatCount=0) {
|
||||
int ret = 0;
|
||||
//int RMTChannel::RMTfillData(dccPacket packet) {
|
||||
// dataReady: Signals to then interrupt routine. It is set when
|
||||
// we have data in the channel buffer which can be copied out
|
||||
@@ -226,14 +211,9 @@ int RMTChannel::RMTfillData(const byte buffer[], byte byteCount, byte repeatCoun
|
||||
// the caller of this function if the data has been sent enough
|
||||
// times (0 to 3 means 1 to 4 times in total).
|
||||
if (dataRepeat > 0) // we have still old work to do
|
||||
ret = dataRepeat;
|
||||
return dataRepeat;
|
||||
if (dataReady == true) // the packet is not copied out yet
|
||||
ret = 1000;
|
||||
if (buffer[0] == 129) {
|
||||
DIAG(F("RMTfillData 129 %d %d"), buffer[1], ret);
|
||||
}
|
||||
if (ret > 0)
|
||||
return ret;
|
||||
return 1000;
|
||||
if (DATA_LEN(byteCount) > maxDataLen) { // this would overun our allocated memory for data
|
||||
DIAG(F("Can not convert DCC bytes # %d to DCC bits %d, buffer too small"), byteCount, maxDataLen);
|
||||
return -1; // something very broken, can not convert packet
|
||||
|
7
DCCRMT.h
7
DCCRMT.h
@@ -39,13 +39,6 @@ class RMTChannel {
|
||||
void RMTprefill();
|
||||
//int RMTfillData(dccPacket packet);
|
||||
int RMTfillData(const byte buffer[], byte byteCount, byte repeatCount);
|
||||
inline void waitForDataCopy() {
|
||||
while(1) {
|
||||
if (dataReady == false)
|
||||
break;
|
||||
//DIAG(F("%d %d"), dataReady, dataRepeat);
|
||||
} //do nothing and wait for interrupt to happen
|
||||
};
|
||||
inline bool busy() {
|
||||
if (dataRepeat > 0) // we have still old work to do
|
||||
return true;
|
||||
|
@@ -80,7 +80,7 @@ int DCCTimer::freeMemory() {
|
||||
|
||||
#include "esp_idf_version.h"
|
||||
#if ESP_IDF_VERSION_MAJOR > 4
|
||||
#error "DCC-EX does not support compiling with IDF version 5.0 or later. Downgrade your ESP32 library to a version that contains IDF version 4. Arduino ESP32 library 3.0.0 is too new. Downgrade to one of 2.0.9 to 2.0.17"
|
||||
#error "DCC-EX does not support compiling with IDF version 5.0 or later. Downgrade your ESP32 library to a version that contains IDE version 4. Arduino ESP32 library 3.0.0 is too new. Downgrade to one of 2.0.9 to 2.0.17"
|
||||
#endif
|
||||
|
||||
#include "DIAG.h"
|
||||
|
@@ -280,13 +280,6 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea
|
||||
if (byteCount > MAX_PACKET_SIZE) return; // allow for chksum
|
||||
|
||||
byte checksum = 0;
|
||||
if(isMainTrack) {
|
||||
if (rmtMainChannel != NULL)
|
||||
rmtMainChannel->waitForDataCopy();
|
||||
} else {
|
||||
if (rmtProgChannel != NULL)
|
||||
rmtProgChannel->waitForDataCopy();
|
||||
}
|
||||
for (byte b = 0; b < byteCount; b++) {
|
||||
checksum ^= buffer[b];
|
||||
pendingPacket[b] = buffer[b];
|
||||
|
20
EXRAIL.h
20
EXRAIL.h
@@ -1,23 +1,3 @@
|
||||
/*
|
||||
* © 2021 Fred Decker
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef EXRAIL_H
|
||||
#define EXRAIL_H
|
||||
|
||||
|
26
EXRAIL2.cpp
26
EXRAIL2.cpp
@@ -4,7 +4,6 @@
|
||||
* © 2021-2023 Harald Barth
|
||||
* © 2020-2023 Chris Harlow
|
||||
* © 2022-2023 Colin Murdoch
|
||||
* © 2025 Morten Nielsen
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
@@ -313,7 +312,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
|
||||
case OPCODE_EXTTTURNTABLE: {
|
||||
VPIN id=operand;
|
||||
VPIN pin=getOperand(progCounter,1);
|
||||
int home=getOperand(progCounter,2);
|
||||
int home=getOperand(progCounter,3);
|
||||
setTurntableHiddenState(EXTTTurntable::create(id,pin));
|
||||
Turntable *tto=Turntable::get(id);
|
||||
tto->addPosition(0,0,home);
|
||||
@@ -678,14 +677,13 @@ void RMFT2::loop2() {
|
||||
break;
|
||||
|
||||
case OPCODE_SET:
|
||||
killBlinkOnVpin(operand);
|
||||
IODevice::write(operand,true);
|
||||
break;
|
||||
|
||||
case OPCODE_RESET:
|
||||
{
|
||||
auto count=getOperand(1);
|
||||
for (uint16_t i=0;i<count;i++) {
|
||||
killBlinkOnVpin(operand+i);
|
||||
IODevice::write(operand+i,opcode==OPCODE_SET);
|
||||
}
|
||||
}
|
||||
killBlinkOnVpin(operand);
|
||||
IODevice::write(operand,false);
|
||||
break;
|
||||
|
||||
case OPCODE_BLINK:
|
||||
@@ -872,14 +870,6 @@ void RMFT2::loop2() {
|
||||
DCC::changeFn(operand,getOperand(1));
|
||||
break;
|
||||
|
||||
case OPCODE_XFWD:
|
||||
DCC::setThrottle(operand,getOperand(1), true);
|
||||
break;
|
||||
|
||||
case OPCODE_XREV:
|
||||
DCC::setThrottle(operand,getOperand(1), false);
|
||||
break;
|
||||
|
||||
case OPCODE_DCCACTIVATE: {
|
||||
// operand is address<<3 | subaddr<<1 | active
|
||||
int16_t addr=operand>>3;
|
||||
@@ -1337,7 +1327,7 @@ void RMFT2::clockEvent(int16_t clocktime, bool change) {
|
||||
void RMFT2::powerEvent(int16_t track, bool overload) {
|
||||
// Hunt for an ONOVERLOAD for this item
|
||||
if (Diag::CMD)
|
||||
DIAG(F("powerEvent : %c"), track + 'A');
|
||||
DIAG(F("powerEvent : %c"), track);
|
||||
if (overload) {
|
||||
onOverloadLookup->handleEvent(F("POWER"),track);
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* © 2020-2022 Chris Harlow
|
||||
* © 2022-2023 Colin Murdoch
|
||||
* © 2023 Harald Barth
|
||||
* © 2025 Morten Nielsen
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
@@ -46,7 +45,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,OPCODE_TOGGLE_TURNOUT,
|
||||
OPCODE_ENDIF,OPCODE_ELSE,
|
||||
OPCODE_DELAY,OPCODE_DELAYMINS,OPCODE_DELAYMS,OPCODE_RANDWAIT,
|
||||
OPCODE_FON,OPCODE_FOFF,OPCODE_XFON,OPCODE_XFOFF,
|
||||
OPCODE_FTOGGLE,OPCODE_XFTOGGLE,OPCODE_XFWD,OPCODE_XREV,
|
||||
OPCODE_FTOGGLE,OPCODE_XFTOGGLE,
|
||||
OPCODE_RED,OPCODE_GREEN,OPCODE_AMBER,OPCODE_DRIVE,
|
||||
OPCODE_SERVO,OPCODE_SIGNAL,OPCODE_TURNOUT,OPCODE_WAITFOR,
|
||||
OPCODE_PAD,OPCODE_FOLLOW,OPCODE_CALL,OPCODE_RETURN,
|
||||
|
@@ -2,7 +2,6 @@
|
||||
* © 2020-2022 Chris Harlow. All rights reserved.
|
||||
* © 2022-2023 Colin Murdoch
|
||||
* © 2023 Harald Barth
|
||||
* © 2025 Morten Nielsen
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
@@ -195,8 +194,6 @@
|
||||
#undef XFOFF
|
||||
#undef XFON
|
||||
#undef XFTOGGLE
|
||||
#undef XREV
|
||||
#undef XFWD
|
||||
|
||||
#ifndef RMFT2_UNDEF_ONLY
|
||||
#define ACTIVATE(addr,subaddr)
|
||||
@@ -222,7 +219,7 @@
|
||||
#define CONFIGURE_SERVO(vpin,pos1,pos2,profile)
|
||||
#define DCC_SIGNAL(id,add,subaddr)
|
||||
#define DCCX_SIGNAL(id,redAspect,amberAspect,greenAspect)
|
||||
#define DCC_TURNTABLE(id,home,description...)
|
||||
#define DCC_TURNTABLE(id,home,description)
|
||||
#define DEACTIVATE(addr,subaddr)
|
||||
#define DEACTIVATEL(addr)
|
||||
#define DELAY(mindelay)
|
||||
@@ -236,7 +233,7 @@
|
||||
#define ENDTASK
|
||||
#define ESTOP
|
||||
#define EXRAIL
|
||||
#define EXTT_TURNTABLE(id,vpin,home,description...)
|
||||
#define EXTT_TURNTABLE(id,vpin,home,description)
|
||||
#define FADE(pin,value,ms)
|
||||
#define FOFF(func)
|
||||
#define FOLLOW(route)
|
||||
@@ -312,7 +309,7 @@
|
||||
#define READ_LOCO
|
||||
#define RED(signal_id)
|
||||
#define RESERVE(blockid)
|
||||
#define RESET(pin,count...)
|
||||
#define RESET(pin)
|
||||
#define RESUME
|
||||
#define RETURN
|
||||
#define REV(speed)
|
||||
@@ -338,7 +335,7 @@
|
||||
#define SERVO2(id,position,duration)
|
||||
#define SERVO_SIGNAL(vpin,redpos,amberpos,greenpos)
|
||||
#define SERVO_TURNOUT(id,pin,activeAngle,inactiveAngle,profile,description...)
|
||||
#define SET(pin,count...)
|
||||
#define SET(pin)
|
||||
#define SET_TRACK(track,mode)
|
||||
#define SET_POWER(track,onoff)
|
||||
#define SETLOCO(loco)
|
||||
@@ -368,7 +365,5 @@
|
||||
#define XFOFF(cab,func)
|
||||
#define XFON(cab,func)
|
||||
#define XFTOGGLE(cab,func)
|
||||
#define XFWD(cab,speed)
|
||||
#define XREV(cab,speed)
|
||||
|
||||
#endif
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* © 2020-2022 Chris Harlow
|
||||
* © 2022-2023 Colin Murdoch
|
||||
* © 2023 Harald Barth
|
||||
* © 2025 Morten Nielsen
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
@@ -517,7 +516,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
|
||||
#ifndef IO_NO_HAL
|
||||
#define EXTT_TURNTABLE(id,vpin,home,description...) OPCODE_EXTTTURNTABLE,V(id),OPCODE_PAD,V(vpin),OPCODE_PAD,V(home),
|
||||
#endif
|
||||
#define FADE(pin,value,ms) OPCODE_SERVO,V(pin),OPCODE_PAD,V(value),OPCODE_PAD,V((int16_t)PCA9685::ProfileType::UseDuration|(int16_t)PCA9685::ProfileType::NoPowerOff),OPCODE_PAD,V(ms/100L),
|
||||
#define FADE(pin,value,ms) OPCODE_SERVO,V(pin),OPCODE_PAD,V(value),OPCODE_PAD,V(PCA9685::ProfileType::UseDuration|PCA9685::NoPowerOff),OPCODE_PAD,V(ms/100L),
|
||||
#define FOFF(func) OPCODE_FOFF,V(func),
|
||||
#define FOLLOW(route) OPCODE_FOLLOW,V(route),
|
||||
#define FON(func) OPCODE_FON,V(func),
|
||||
@@ -608,7 +607,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
|
||||
#define READ_LOCO OPCODE_READ_LOCO1,0,0,OPCODE_READ_LOCO2,0,0,
|
||||
#define RED(signal_id) OPCODE_RED,V(signal_id),
|
||||
#define RESERVE(blockid) OPCODE_RESERVE,V(blockid),
|
||||
#define RESET(pin,count...) OPCODE_RESET,V(pin),OPCODE_PAD,V(#count[0] ? count+0: 1),
|
||||
#define RESET(pin) OPCODE_RESET,V(pin),
|
||||
#define RESUME OPCODE_RESUME,0,0,
|
||||
#define RETURN OPCODE_RETURN,0,0,
|
||||
#define REV(speed) OPCODE_REV,V(speed),
|
||||
@@ -636,7 +635,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
|
||||
#define SERVO2(id,position,ms) OPCODE_SERVO,V(id),OPCODE_PAD,V(position),OPCODE_PAD,V(PCA9685::Instant),OPCODE_PAD,V(ms/100L),
|
||||
#define SERVO_SIGNAL(vpin,redpos,amberpos,greenpos)
|
||||
#define SERVO_TURNOUT(id,pin,activeAngle,inactiveAngle,profile,description...) OPCODE_SERVOTURNOUT,V(id),OPCODE_PAD,V(pin),OPCODE_PAD,V(activeAngle),OPCODE_PAD,V(inactiveAngle),OPCODE_PAD,V(PCA9685::ProfileType::profile),
|
||||
#define SET(pin,count...) OPCODE_SET,V(pin),OPCODE_PAD,V(#count[0] ? count+0: 1),
|
||||
#define SET(pin) OPCODE_SET,V(pin),
|
||||
#define SET_TRACK(track,mode) OPCODE_SET_TRACK,V(TRACK_MODE_##mode <<8 | TRACK_NUMBER_##track),
|
||||
#define SET_POWER(track,onoff) OPCODE_SET_POWER,V(TRACK_POWER_##onoff),OPCODE_PAD, V(TRACK_NUMBER_##track),
|
||||
#define SETLOCO(loco) OPCODE_SETLOCO,V(loco),
|
||||
@@ -666,8 +665,6 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
|
||||
#define XFOFF(cab,func) OPCODE_XFOFF,V(cab),OPCODE_PAD,V(func),
|
||||
#define XFON(cab,func) OPCODE_XFON,V(cab),OPCODE_PAD,V(func),
|
||||
#define XFTOGGLE(cab,func) OPCODE_XFTOGGLE,V(cab),OPCODE_PAD,V(func),
|
||||
#define XFWD(cab,speed) OPCODE_XFWD,V(cab),OPCODE_PAD,V(speed),
|
||||
#define XREV(cab,speed) OPCODE_XREV,V(cab),OPCODE_PAD,V(speed),
|
||||
|
||||
// Build RouteCode
|
||||
const int StringMacroTracker2=__COUNTER__;
|
||||
|
200
EXmDNS.cpp
Normal file
200
EXmDNS.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* © 2024 Harald Barth
|
||||
* © 2024 Paul M. Antoine
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "EthernetInterface.h"
|
||||
#ifdef DO_MDNS
|
||||
#include "EXmDNS.h"
|
||||
|
||||
// fixed values for mDNS
|
||||
static IPAddress mdnsMulticastIPAddr = IPAddress(224, 0, 0, 251);
|
||||
#define MDNS_SERVER_PORT 5353
|
||||
|
||||
// dotToLen()
|
||||
// converts stings of form ".foo.barbar.x" to a string with the
|
||||
// dots replaced with lenght. So string above would result in
|
||||
// "\x03foo\x06barbar\x01x" in C notation. If not NULL, *substr
|
||||
// will point to the beginning of the last component, in this
|
||||
// example that would be "\x01x".
|
||||
//
|
||||
static void dotToLen(char *str, char **substr) {
|
||||
char *dotplace = NULL;
|
||||
char *s;
|
||||
byte charcount = 0;
|
||||
for (s = str;/*see break*/ ; s++) {
|
||||
if (*s == '.' || *s == '\0') {
|
||||
// take care of accumulated
|
||||
if (dotplace != NULL && charcount != 0) {
|
||||
*dotplace = charcount;
|
||||
}
|
||||
if (*s == '\0')
|
||||
break;
|
||||
if (substr && *s == '.')
|
||||
*substr = s;
|
||||
// set new values
|
||||
dotplace = s;
|
||||
charcount = 0;
|
||||
} else {
|
||||
charcount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MDNS::MDNS(EthernetUDP& udp) {
|
||||
_udp = &udp;
|
||||
}
|
||||
MDNS::~MDNS() {
|
||||
_udp->stop();
|
||||
if (_name) free(_name);
|
||||
if (_serviceName) free(_serviceName);
|
||||
if (_serviceProto) free(_serviceProto);
|
||||
}
|
||||
int MDNS::begin(const IPAddress& ip, char* name) {
|
||||
// if we were called very soon after the board was booted, we need to give the
|
||||
// EthernetShield (WIZnet) some time to come up. Hence, we delay until millis() is at
|
||||
// least 3000. This is necessary, so that if we need to add a service record directly
|
||||
// after begin, the announce packet does not get lost in the bowels of the WIZnet chip.
|
||||
//while (millis() < 3000)
|
||||
// delay(100);
|
||||
|
||||
_ipAddress = ip;
|
||||
_name = (char *)malloc(strlen(name)+2);
|
||||
byte n;
|
||||
for(n = 0; n<strlen(name); n++)
|
||||
_name[n+1] = name[n];
|
||||
_name[n+1] = '\0';
|
||||
_name[0] = '.';
|
||||
dotToLen(_name, NULL);
|
||||
return _udp->beginMulticast(mdnsMulticastIPAddr, MDNS_SERVER_PORT);
|
||||
}
|
||||
|
||||
int MDNS::addServiceRecord(const char* name, uint16_t port, MDNSServiceProtocol_t proto) {
|
||||
// we ignore proto, assume TCP
|
||||
(void)proto;
|
||||
_serviceName = (char *)malloc(strlen(name) + 2);
|
||||
byte n;
|
||||
for(n = 0; n<strlen(name); n++)
|
||||
_serviceName[n+1] = name[n];
|
||||
_serviceName[n+1] = '\0';
|
||||
_serviceName[0] = '.';
|
||||
_serviceProto = NULL; //to be filled in
|
||||
dotToLen(_serviceName, &_serviceProto);
|
||||
_servicePort = port;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char dns_rr_services[] = "\x09_services\x07_dns-sd\x04_udp\x05local";
|
||||
static char dns_rr_tcplocal[] = "\x04_tcp\x05local";
|
||||
static char *dns_rr_local = dns_rr_tcplocal + dns_rr_tcplocal[0] + 1;
|
||||
|
||||
typedef struct _DNSHeader_t
|
||||
{
|
||||
uint16_t xid;
|
||||
uint16_t flags; // flags condensed
|
||||
uint16_t queryCount;
|
||||
uint16_t answerCount;
|
||||
uint16_t authorityCount;
|
||||
uint16_t additionalCount;
|
||||
} __attribute__((__packed__)) DNSHeader_t;
|
||||
|
||||
//
|
||||
// MDNS::run()
|
||||
// This broadcasts whatever we got evey BROADCASTTIME seconds.
|
||||
// Why? Too much brokenness i all mDNS implementations available
|
||||
//
|
||||
void MDNS::run() {
|
||||
static long int lastrun = BROADCASTTIME * 1000UL;
|
||||
unsigned long int now = millis();
|
||||
if (!(now - lastrun > BROADCASTTIME * 1000UL)) {
|
||||
return;
|
||||
}
|
||||
lastrun = now;
|
||||
DNSHeader_t dnsHeader = {0, 0, 0, 0, 0, 0};
|
||||
// DNSHeader_t dnsHeader = { 0 };
|
||||
|
||||
_udp->beginPacket(mdnsMulticastIPAddr, MDNS_SERVER_PORT);
|
||||
|
||||
// dns header
|
||||
dnsHeader.flags = HTONS((uint16_t)0x8400); // Response, authorative
|
||||
dnsHeader.answerCount = HTONS(4 /*5 if TXT but we do not do that */);
|
||||
_udp->write((uint8_t*)&dnsHeader, sizeof(DNSHeader_t));
|
||||
|
||||
// rr #1, the PTR record from generic _services.x.local to service.x.local
|
||||
_udp->write((uint8_t*)dns_rr_services, sizeof(dns_rr_services));
|
||||
|
||||
byte buf[10];
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x0c; //PTR
|
||||
buf[2] = 0x00;
|
||||
buf[3] = 0x01; //IN
|
||||
*((uint32_t*)(buf+4)) = HTONL(120); //TTL in sec
|
||||
*((uint16_t*)(buf+8)) = HTONS( _serviceProto[0] + 1 + strlen(dns_rr_tcplocal) + 1);
|
||||
_udp->write(buf, 10);
|
||||
|
||||
_udp->write(_serviceProto,_serviceProto[0]+1);
|
||||
_udp->write(dns_rr_tcplocal, strlen(dns_rr_tcplocal)+1);
|
||||
|
||||
// rr #2, the PTR record from proto.x to name.proto.x
|
||||
_udp->write(_serviceProto,_serviceProto[0]+1);
|
||||
_udp->write(dns_rr_tcplocal, strlen(dns_rr_tcplocal)+1);
|
||||
*((uint16_t*)(buf+8)) = HTONS(strlen(_serviceName) + strlen(dns_rr_tcplocal) + 1); // recycle most of buf
|
||||
_udp->write(buf, 10);
|
||||
|
||||
_udp->write(_serviceName, strlen(_serviceName));
|
||||
_udp->write(dns_rr_tcplocal, strlen(dns_rr_tcplocal)+1);
|
||||
// rr #3, the SRV record for the service that points to local name
|
||||
_udp->write(_serviceName, strlen(_serviceName));
|
||||
_udp->write(dns_rr_tcplocal, strlen(dns_rr_tcplocal)+1);
|
||||
|
||||
buf[1] = 0x21; // recycle most of buf but here SRV
|
||||
buf[2] = 0x80; // cache flush
|
||||
*((uint16_t*)(buf+8)) = HTONS(strlen(_name) + strlen(dns_rr_local) + 1 + 6);
|
||||
_udp->write(buf, 10);
|
||||
|
||||
byte srv[6];
|
||||
// priority and weight
|
||||
srv[0] = srv[1] = srv[2] = srv[3] = 0;
|
||||
// port
|
||||
*((uint16_t*)(srv+4)) = HTONS(_servicePort);
|
||||
_udp->write(srv, 6);
|
||||
// target
|
||||
_udp->write(_name, _name[0]+1);
|
||||
_udp->write(dns_rr_local, strlen(dns_rr_local)+1);
|
||||
|
||||
// rr #4, the A record for the name.local
|
||||
_udp->write(_name, _name[0]+1);
|
||||
_udp->write(dns_rr_local, strlen(dns_rr_local)+1);
|
||||
|
||||
buf[1] = 0x01; // recycle most of buf but here A
|
||||
*((uint16_t*)(buf+8)) = HTONS(4);
|
||||
_udp->write(buf, 10);
|
||||
byte ip[4];
|
||||
ip[0] = _ipAddress[0];
|
||||
ip[1] = _ipAddress[1];
|
||||
ip[2] = _ipAddress[2];
|
||||
ip[3] = _ipAddress[3];
|
||||
_udp->write(ip, 4);
|
||||
|
||||
_udp->endPacket();
|
||||
_udp->flush();
|
||||
//
|
||||
}
|
||||
#endif //DO_MDNS
|
50
EXmDNS.h
Normal file
50
EXmDNS.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* © 2024 Harald Barth
|
||||
* © 2024 Paul M. Antoine
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifdef DO_MDNS
|
||||
#define BROADCASTTIME 15 //seconds
|
||||
|
||||
// We do this ourselves because every library is different and/or broken...
|
||||
#define HTONS(x) ((uint16_t)(((x) << 8) | (((x) >> 8) & 0xFF)))
|
||||
#define HTONL(x) ( ((uint32_t)(x) << 24) | (((uint32_t)(x) << 8) & 0xFF0000) | \
|
||||
(((uint32_t)(x) >> 8) & 0xFF00) | ((uint32_t)(x) >> 24) )
|
||||
|
||||
typedef enum _MDNSServiceProtocol_t
|
||||
{
|
||||
MDNSServiceTCP,
|
||||
MDNSServiceUDP
|
||||
} MDNSServiceProtocol_t;
|
||||
|
||||
class MDNS {
|
||||
public:
|
||||
MDNS(EthernetUDP& udp);
|
||||
~MDNS();
|
||||
int begin(const IPAddress& ip, char* name);
|
||||
int addServiceRecord(const char* name, uint16_t port, MDNSServiceProtocol_t proto);
|
||||
void run();
|
||||
private:
|
||||
EthernetUDP *_udp;
|
||||
IPAddress _ipAddress;
|
||||
char* _name;
|
||||
char* _serviceName;
|
||||
char* _serviceProto;
|
||||
int _servicePort;
|
||||
};
|
||||
#endif //DO_MDNS
|
@@ -31,13 +31,12 @@
|
||||
#include "CommandDistributor.h"
|
||||
#include "WiThrottle.h"
|
||||
#include "DCCTimer.h"
|
||||
#if __has_include ( "MDNS_Generic.h")
|
||||
#include "MDNS_Generic.h"
|
||||
#define DO_MDNS
|
||||
EthernetUDP udp;
|
||||
MDNS mdns(udp);
|
||||
#endif
|
||||
|
||||
#ifdef DO_MDNS
|
||||
#include "EXmDNS.h"
|
||||
EthernetUDP udp;
|
||||
MDNS mdns(udp);
|
||||
#endif
|
||||
|
||||
//extern void looptimer(unsigned long timeout, const FSH* message);
|
||||
#define looptimer(a,b)
|
||||
@@ -116,10 +115,10 @@ void EthernetInterface::setup()
|
||||
|
||||
outboundRing=new RingStream(OUTBOUND_RING_SIZE);
|
||||
#ifdef DO_MDNS
|
||||
mdns.begin(Ethernet.localIP(), WIFI_HOSTNAME); // hostname
|
||||
if (!mdns.begin(Ethernet.localIP(), (char *)WIFI_HOSTNAME))
|
||||
DIAG(F("mdns.begin fail")); // hostname
|
||||
mdns.addServiceRecord(WIFI_HOSTNAME "._withrottle", IP_PORT, MDNSServiceTCP);
|
||||
// Not sure if we need to run it once, but just in case!
|
||||
mdns.run();
|
||||
mdns.run(); // run it right away to get out info ASAP
|
||||
#endif
|
||||
connected=true;
|
||||
}
|
||||
@@ -144,7 +143,9 @@ void EthernetInterface::acceptClient() { // STM32 version
|
||||
return;
|
||||
}
|
||||
}
|
||||
DIAG(F("Ethernet OVERFLOW"));
|
||||
// reached here only if more than MAX_SOCK_NUM clients want to connect
|
||||
DIAG(F("Ethernet more than %d clients, not accepting new connection"), MAX_SOCK_NUM);
|
||||
client.stop();
|
||||
}
|
||||
#else
|
||||
void EthernetInterface::acceptClient() { // non-STM32 version
|
||||
|
@@ -3,7 +3,7 @@
|
||||
* © 2021 Neil McKechnie
|
||||
* © 2021 Mike S
|
||||
* © 2021 Fred Decker
|
||||
* © 2020-2022 Harald Barth
|
||||
* © 2020-2024 Harald Barth
|
||||
* © 2020-2024 Chris Harlow
|
||||
* © 2020 Gregor Baues
|
||||
* All rights reserved.
|
||||
@@ -31,24 +31,32 @@
|
||||
#define EthernetInterface_h
|
||||
|
||||
#include "defines.h"
|
||||
#if ETHERNET_ON == true
|
||||
#include "DCCEXParser.h"
|
||||
#include <Arduino.h>
|
||||
//#include <avr/pgmspace.h>
|
||||
#if defined (ARDUINO_TEENSY41)
|
||||
#include <NativeEthernet.h> //TEENSY Ethernet Treiber
|
||||
#include <NativeEthernetUdp.h>
|
||||
#ifndef MAX_SOCK_NUM
|
||||
#define MAX_SOCK_NUM 4
|
||||
#endif
|
||||
// can't use our MDNS because of a namespace clash with Teensy's NativeEthernet library!
|
||||
// #define DO_MDNS
|
||||
#elif defined (ARDUINO_NUCLEO_F429ZI) || defined (ARDUINO_NUCLEO_F439ZI) || defined (ARDUINO_NUCLEO_F4X9ZI)
|
||||
#include <LwIP.h>
|
||||
// #include "STM32lwipopts.h"
|
||||
#include <STM32Ethernet.h>
|
||||
#include <lwip/netif.h>
|
||||
extern "C" struct netif gnetif;
|
||||
#define STM32_ETHERNET
|
||||
#define MAX_SOCK_NUM 8
|
||||
#define MAX_SOCK_NUM MAX_NUM_TCP_CLIENTS
|
||||
#define DO_MDNS
|
||||
#else
|
||||
#include "Ethernet.h"
|
||||
#define DO_MDNS
|
||||
#endif
|
||||
|
||||
|
||||
#include "RingStream.h"
|
||||
|
||||
/**
|
||||
@@ -77,5 +85,5 @@ class EthernetInterface {
|
||||
static void dropClient(byte socketnum);
|
||||
|
||||
};
|
||||
|
||||
#endif // ETHERNET_ON
|
||||
#endif
|
||||
|
@@ -1 +1 @@
|
||||
#define GITHUB_SHA "master-packetloss-202501161204Z"
|
||||
#define GITHUB_SHA "devel-more-ether-202412052105Z"
|
||||
|
@@ -38,7 +38,6 @@
|
||||
#include "FSH.h"
|
||||
#include "I2CManager.h"
|
||||
#include "inttypes.h"
|
||||
#include "TemplateForEnums.h"
|
||||
|
||||
typedef uint16_t VPIN;
|
||||
// Limit VPIN number to max 32767. Above this number, printing often gives negative values.
|
||||
|
@@ -121,7 +121,6 @@ void _begin() {
|
||||
// Configuration isn't done frequently so we can use blocking I2C calls here, and so buffers can
|
||||
// be allocated from the stack to reduce RAM allocation.
|
||||
bool _configure(VPIN vpin, ConfigTypeEnum configType, int paramCount, int params[]) override {
|
||||
(void)configType; (void)params; // unused
|
||||
if(_verPrint) DIAG(F("_configure() driver IO_EXSensorCAM v0.%d.%d vpin: %d "), driverVer/100,driverVer%100,vpin);
|
||||
_verPrint=false; //only give driver versions once
|
||||
if (paramCount != 1) return false;
|
||||
|
@@ -129,7 +129,7 @@ class NeoPixel : public IODevice {
|
||||
public:
|
||||
|
||||
static void create(VPIN vpin, int nPins, uint16_t mode=(NEO_GRB | NEO_KHZ800), I2CAddress i2cAddress=0x60) {
|
||||
if (checkNoOverlap(vpin, nPins, i2cAddress)) new NeoPixel(vpin, nPins, mode, i2cAddress);
|
||||
if (checkNoOverlap(vpin, nPins, mode, i2cAddress)) new NeoPixel(vpin, nPins, mode, i2cAddress);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@@ -28,9 +28,12 @@
|
||||
#include "DCCTimer.h"
|
||||
#include <wiring_private.h>
|
||||
|
||||
#include "TemplateForEnums.h"
|
||||
// use powers of two so we can do logical and/or on the track modes in if clauses.
|
||||
// For example TRACK_MODE_DC_INV is (TRACK_MODE_DC|TRACK_MODIFIER_INV)
|
||||
template<class T> inline T operator~ (T a) { return (T)~(int)a; }
|
||||
template<class T> inline T operator| (T a, T b) { return (T)((int)a | (int)b); }
|
||||
template<class T> inline T operator& (T a, T b) { return (T)((int)a & (int)b); }
|
||||
template<class T> inline T operator^ (T a, T b) { return (T)((int)a ^ (int)b); }
|
||||
enum TRACK_MODE : byte {
|
||||
// main modes
|
||||
TRACK_MODE_NONE = 1, TRACK_MODE_MAIN = 2, TRACK_MODE_PROG = 4,
|
||||
|
82
README.md
82
README.md
@@ -1,39 +1,77 @@
|
||||
# What is DCC-EX?
|
||||
DCC-EX is a team of dedicated enthusiasts producing open source DCC & DC solutions for you to run your complete model railroad layout. Our easy to use, do-it-yourself, and free open source products run on off-the-shelf Arduino technology and are supported by numerous third party hardware and apps like JMRI, Engine Driver, wiThrottle, Rocrail and more.
|
||||
# What is DCC++ EX?
|
||||
DCC++ EX is the organization maintaining several codebases that together represent a fully open source DCC system. Currently, this includes the following:
|
||||
|
||||
Currently, our products include the following:
|
||||
* [CommandStation-EX](https://github.com/DCC-EX/CommandStation-EX/releases) - the latest take on the DCC++ command station for controlling your trains. Runs on an Arduino board, and includes advanced features such as a WiThrottle server implementation, turnout operation, general purpose inputs and outputs (I/O), and JMRI integration.
|
||||
* [exWebThrottle](https://github.com/DCC-EX/exWebThrottle) - a simple web based controller for your DCC++ command station.
|
||||
* [BaseStation-installer](https://github.com/DCC-EX/BaseStation-Installer) - an installer executable that takes care of downloading and installing DCC++ firmware onto your hardware setup.
|
||||
* [BaseStation-Classic](https://github.com/DCC-EX/BaseStation-Classic) - the original DCC++ software, packaged in a stable release. No active development, bug fixes only.
|
||||
|
||||
* [EX-CommandStation](https://github.com/DCC-EX/CommandStation-EX/releases)
|
||||
* [EX-WebThrottle](https://github.com/DCC-EX/exWebThrottle)
|
||||
* [EX-Installer](https://github.com/DCC-EX/EX-Installer)
|
||||
* [EX-MotoShield8874](https://dcc-ex.com/reference/hardware/motorboards/ex-motor-shield-8874.html#gsc.tab=0)
|
||||
* [EX-DCCInspector](https://github.com/DCC-EX/DCCInspector-EX)
|
||||
* [EX-Toolbox](https://github.com/DCC-EX/EX-Toolbox)
|
||||
* [EX-Turntable](https://github.com/DCC-EX/EX-Turntable)
|
||||
* [EX-IOExpander](https://github.com/DCC-EX/EX-IOExpander)
|
||||
* [EX-FastClock](https://github.com/DCC-EX/EX-FastClock)
|
||||
* [DCCEXProtocol](https://github.com/DCC-EX/DCCEXProtocol)
|
||||
A basic DCC++ EX hardware setup can use easy to find, widely avalable Arduino boards that you can assemble yourself.
|
||||
|
||||
Both CommandStation-EX and BaseStation-Classic support much of the NMRA Digital Command Control (DCC) [standards](http://www.nmra.org/dcc-working-group "NMRA DCC Working Group"), including:
|
||||
|
||||
* simultaneous control of multiple locomotives
|
||||
* 2-byte and 4-byte locomotive addressing
|
||||
* 28 or 128-step speed throttling
|
||||
* Activate/de-activate all accessory function addresses 0-2048
|
||||
* Control of all cab functions F0-F28 and F29-F68
|
||||
* Main Track: Write configuration variable bytes and set/clear specific configuration variable (CV) bits (aka Programming on Main or POM)
|
||||
* Programming Track: Same as the main track with the addition of reading configuration variable bytes
|
||||
* And many more custom features. see [What's new in CommandStation-EX?](#whats-new-in-commandstation-ex)
|
||||
|
||||
Details of these projects can be found on [our web site](https://dcc-ex.com/).
|
||||
|
||||
# What’s in this Repository?
|
||||
|
||||
This repository, CommandStation-EX, contains a complete DCC-EX *EX-CommmandStation* sketch designed for compiling and uploading into an Arduino Uno, Mega, or Nano.
|
||||
This repository, CommandStation-EX, contains a complete DCC++ EX Commmand Station sketch designed for compiling and uploading into an Arduino Uno, Mega, or Nano.
|
||||
|
||||
To utilize this sketch, you can use the following:
|
||||
|
||||
1. (recommended for all levels of user) our [automated installer](https://github.com/DCC-EX/EX-Installer)
|
||||
1. (beginner) our [automated installer](https://github.com/DCC-EX/BaseStation-Installer)
|
||||
2. (intermediate) download the latest version from the [releases page](https://github.com/DCC-EX/CommandStation-EX/releases)
|
||||
3. (advanced) use git clone on this repository
|
||||
|
||||
Refer to [our web site](https://https://dcc-ex.com/ex-commandstation/get-started/index.html#/) for the hardware required for this project.
|
||||
Not using the installer? Open the file "CommandStation-EX.ino" in the
|
||||
Arduino IDE. Please do not rename the folder containing the sketch
|
||||
code, nor add any files in that folder. The Arduino IDE relies on the
|
||||
structure and name of the folder to properly display and compile the
|
||||
code. Rename or copy config.example.h to config.h. If you do not have
|
||||
the standard setup, you must edit config.h according to the help texts
|
||||
in config.h.
|
||||
|
||||
**We seriously recommend using the EX-Installer**, however if you choose not to use the installer...
|
||||
## What's new in CommandStation-EX?
|
||||
|
||||
* Open the file ``CommandStation-EX.ino`` in the Arduino IDE or Visual Studio Code (VSC). Please do not rename the folder containing the sketch code, nor add any files in that folder. The Arduino IDE relies on the structure and name of the folder to properly display and compile the code.
|
||||
* Rename or copy ``config.example.h`` to ``config.h``.
|
||||
* You must edit ``config.h`` according to the help texts in ``config.h``.
|
||||
* WiThrottle server built in. Connect Engine Driver or WiThrottle clients directly to your Command Station (or through JMRI as before)
|
||||
* WiFi and Ethernet shield support
|
||||
* No more jumpers or soldering!
|
||||
* Direct support for all the most popular motor control boards including single pin (Arduino) or dual pin (IBT_2) type PWM inputs without the need for an adapter circuit
|
||||
* I2C Display support (LCD and OLED)
|
||||
* Improved short circuit detection and automatic reset from an overload
|
||||
* Current reading, sensing and ACK detection settings in milliAmps instead of just pin readings
|
||||
* Improved adherence to the NMRA DCC specification
|
||||
* Complete support for all the old commands and front ends like JMRI
|
||||
* Railcom cutout (beta)
|
||||
* Simpler, modular, faster code with an API Library for developers for easy expansion
|
||||
* New features and functions in JMRI
|
||||
* Ability to join MAIN and PROG tracks into one MAIN track to run your locos
|
||||
* "Drive-Away" feature - Throttles with support, like Engine Driver, can allow a loco to be programmed on a usable, electrically isolated programming track and then drive off onto the main track
|
||||
* Diagnostic commands to test decoders that aren't reading or writing correctly
|
||||
* Support for Uno, Nano, Mega, Nano Every and Teensy microcontrollers
|
||||
* User Functions: Filter regular commands (like a turnout or output command) and pass it to your own function or accessory
|
||||
* Support for LCN (layout control nodes)
|
||||
* mySetup.h file that acts like an Autoexec.Bat command to send startup commands to the CS
|
||||
* High Accuracty Waveform option for rock steady DCC signals
|
||||
* New current response outputs current in mA, overlimit current, and maximum board capable current. Support for new current meter in JMRI
|
||||
* USB Browser based EX-WebThrottle
|
||||
* New, simpler, function control command
|
||||
* Number of locos discovery command `<#>`
|
||||
* Emergency stop command <!>
|
||||
* Release cabs from memory command <-> all cabs, <- CAB> for just one loco address
|
||||
* Automatic slot (register) management
|
||||
* Automation (coming soon)
|
||||
|
||||
NOTE: DCC-EX is a major rewrite to the code. We started over and rebuilt it from the ground up! For what that means, you can read [HERE](https://dcc-ex.com/about/rewrite.html).
|
||||
|
||||
# More information
|
||||
You can learn more at the [DCC-EX website](https://dcc-ex.com/)
|
||||
You can learn more at the [DCC++ EX website](https://dcc-ex.com/)
|
||||
|
||||
- November 14, 2020
|
||||
|
101
STM32lwipopts.h.copyme
Normal file
101
STM32lwipopts.h.copyme
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* © 2024 Harald Barth
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
//
|
||||
// Rewrite of the STM32lwipopts.h file from STM
|
||||
// To be copied into where lwipopts_default.h resides
|
||||
// typically into STM32Ethernet/src/STM32lwipopts.h
|
||||
// or STM32Ethernet\src\STM32lwipopts.h
|
||||
// search for `lwipopts_default.h` and copy this file into the
|
||||
// same directory but name it STM32lwipopts.h
|
||||
//
|
||||
#ifndef __STM32LWIPOPTS_H__
|
||||
#define __STM32LWIPOPTS_H__
|
||||
|
||||
// include this here and then override things we do differnet
|
||||
#include "lwipopts_default.h"
|
||||
|
||||
// we can not include our "defines.h" here
|
||||
// so we need to duplicate that define
|
||||
#define MAX_NUM_TCP_CLIENTS_HERE 9
|
||||
|
||||
#ifdef MAX_NUM_TCP_CLIENTS
|
||||
#if MAX_NUM_TCP_CLIENTS != MAX_NUM_TCP_CLIENTS_HERE
|
||||
#error MAX_NUM_TCP_CLIENTS and MAX_NUM_TCP_CLIENTS_HERE must be same
|
||||
#endif
|
||||
#else
|
||||
#define MAX_NUM_TCP_CLIENTS MAX_NUM_TCP_CLIENTS_HERE
|
||||
#endif
|
||||
|
||||
// increase ARP cache
|
||||
#undef MEMP_NUM_APR_QUEUE
|
||||
#define MEMP_NUM_ARP_QUEUE MAX_NUM_TCP_CLIENTS+3 // one for each client (all on different HW) and a few extra
|
||||
|
||||
// Example for debug
|
||||
//#define LWIP_DEBUG 1
|
||||
//#define TCP_DEBUG LWIP_DBG_ON
|
||||
|
||||
// NOT STRICT NECESSARY ANY MORE BUT CAN BE USED TO SAVE RAM
|
||||
#undef MEM_LIBC_MALLOC
|
||||
#define MEM_LIBC_MALLOC 1 // use the same malloc as for everything else
|
||||
#undef MEMP_MEM_MALLOC
|
||||
#define MEMP_MEM_MALLOC 1 // uses malloc which means no pools which means slower but not mean 32KB up front
|
||||
|
||||
#undef MEMP_NUM_TCP_PCB
|
||||
#define MEMP_NUM_TCP_PCB MAX_NUM_TCP_CLIENTS+1 // one extra so we can reject number N+1 from our code
|
||||
#define MEMP_NUM_TCP_PCB_LISTEN 6
|
||||
|
||||
#undef MEMP_NUM_TCP_SEG
|
||||
#define MEMP_NUM_TCP_SEG MAX_NUM_TCP_CLIENTS
|
||||
|
||||
#undef MEMP_NUM_SYS_TIMEOUT
|
||||
#define MEMP_NUM_SYS_TIMEOUT MAX_NUM_TCP_CLIENTS+2
|
||||
|
||||
#undef PBUF_POOL_SIZE
|
||||
#define PBUF_POOL_SIZE MAX_NUM_TCP_CLIENTS
|
||||
|
||||
#undef LWIO_ICMP
|
||||
#define LWIP_ICMP 1
|
||||
#undef LWIP_RAW
|
||||
#define LWIP_RAW 1 /* PING changed to 1 */
|
||||
#undef DEFAULT_RAW_RECVMBOX_SIZE
|
||||
#define DEFAULT_RAW_RECVMBOX_SIZE 3 /* for ICMP PING */
|
||||
|
||||
#undef LWIP_DHCP
|
||||
#define LWIP_DHCP 1
|
||||
#undef LWIP_UDP
|
||||
#define LWIP_UDP 1
|
||||
|
||||
/*
|
||||
The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:
|
||||
- To use this feature let the following define uncommented.
|
||||
- To disable it and process by CPU comment the the checksum.
|
||||
*/
|
||||
|
||||
#if CHECKSUM_GEN_TCP == 1
|
||||
#error On STM32 TCP checksum should be in HW
|
||||
#endif
|
||||
|
||||
#undef LWIP_IGMP
|
||||
#define LWIP_IGMP 1
|
||||
|
||||
//#define SO_REUSE 1
|
||||
//#define SO_REUSE_RXTOALL 1
|
||||
|
||||
#endif /* __STM32LWIPOPTS_H__ */
|
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* © 2024, Harald Barth. All rights reserved.
|
||||
*
|
||||
* This file is part of DCC-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef TemplateForEnums
|
||||
#define TemplateForEnums
|
||||
template<class T> inline T operator~ (T a) { return (T)~(int)a; }
|
||||
template<class T> inline T operator| (T a, T b) { return (T)((int)a | (int)b); }
|
||||
template<class T> inline T operator& (T a, T b) { return (T)((int)a & (int)b); }
|
||||
template<class T> inline T operator^ (T a, T b) { return (T)((int)a ^ (int)b); }
|
||||
#endif
|
||||
|
@@ -246,6 +246,9 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr
|
||||
#endif
|
||||
#ifndef DISABLE_PROG
|
||||
if (mode & TRACK_MODE_PROG) {
|
||||
#else
|
||||
if (false) {
|
||||
#endif
|
||||
// only allow 1 track to be prog
|
||||
FOR_EACH_TRACK(t)
|
||||
if ( (track[t]->getMode() & TRACK_MODE_PROG) && t != trackToSet) {
|
||||
@@ -258,7 +261,6 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr
|
||||
} else {
|
||||
track[trackToSet]->makeProgTrack(false); // only the prog track knows it's type
|
||||
}
|
||||
#endif
|
||||
|
||||
// When a track is switched, we must clear any side effects of its previous
|
||||
// state, otherwise trains run away or just dont move.
|
||||
@@ -356,24 +358,11 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr
|
||||
applyDCSpeed(trackToSet);
|
||||
}
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#ifndef DISABLE_PROG
|
||||
if (tempProgTrack == trackToSet && oldmode & TRACK_MODE_MAIN && !(mode & TRACK_MODE_PROG)) {
|
||||
// If we just take away the prog track, the join should not
|
||||
// be active either. So do in effect an unjoin
|
||||
//DIAG(F("Unsync"));
|
||||
tempProgTrack = MAX_TRACKS+1;
|
||||
progTrackSyncMain=false;
|
||||
if (joinRelay!=UNUSED_PIN) digitalWrite(joinRelay,LOW);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
// Turn off power if we changed the mode of this track
|
||||
if (mode != oldmode) {
|
||||
if (mode != oldmode)
|
||||
track[trackToSet]->setPower(POWERMODE::OFF);
|
||||
}
|
||||
|
||||
streamTrackState(NULL,trackToSet);
|
||||
|
||||
//DIAG(F("TrackMode=%d"),mode);
|
||||
return true;
|
||||
}
|
||||
|
11
Turnouts.cpp
11
Turnouts.cpp
@@ -312,6 +312,12 @@
|
||||
*
|
||||
*************************************************************************************/
|
||||
|
||||
#if defined(DCC_TURNOUTS_RCN_213)
|
||||
const bool DCCTurnout::rcn213Compliant = true;
|
||||
#else
|
||||
const bool DCCTurnout::rcn213Compliant = false;
|
||||
#endif
|
||||
|
||||
// DCCTurnoutData contains data specific to this subclass that is
|
||||
// written to EEPROM when the turnout is saved.
|
||||
struct DCCTurnoutData {
|
||||
@@ -379,10 +385,7 @@
|
||||
// DCC++ Classic behaviour is that Throw writes a 1 in the packet,
|
||||
// and Close writes a 0.
|
||||
// RCN-213 specifies that Throw is 0 and Close is 1.
|
||||
#if defined(DCC_TURNOUTS_RCN_213)
|
||||
close = !close;
|
||||
#endif
|
||||
DCC::setAccessory(_dccTurnoutData.address, _dccTurnoutData.subAddress, close);
|
||||
DCC::setAccessory(_dccTurnoutData.address, _dccTurnoutData.subAddress, close ^ !rcn213Compliant);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -245,6 +245,8 @@ public:
|
||||
// Load a VPIN turnout definition from EEPROM. The common Turnout data has already been read at this point.
|
||||
static Turnout *load(struct TurnoutData *turnoutData);
|
||||
void print(Print *stream) override;
|
||||
// Flag whether DCC Accessory packets are to contain 1=close/0=throw(RCN-213) or 1=throw/0-close (DCC++ Classic)
|
||||
static const bool rcn213Compliant;
|
||||
|
||||
protected:
|
||||
bool setClosedInternal(bool close) override;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* © 2022 Paul M. Antoine
|
||||
* © 2021 Neil McKechnie
|
||||
* © 2020-2025 Harald Barth
|
||||
* © 2020-2023 Harald Barth
|
||||
* © 2020-2021 Fred Decker
|
||||
* © 2020-2021 Chris Harlow
|
||||
* © 2023 Nathan Kellenicki
|
||||
@@ -45,14 +45,15 @@ The configuration file for DCC-EX Command Station
|
||||
// the correct resistor could damage the sense pin on your Arduino or destroy
|
||||
// the device.
|
||||
//
|
||||
// DEFINE MOTOR_SHIELD_TYPE BELOW. THESE ARE EXAMPLES. Full list in MotorDrivers.h
|
||||
// DEFINE MOTOR_SHIELD_TYPE BELOW. THESE ARE EXAMPLES. FULL LIST IN MotorDrivers.h
|
||||
//
|
||||
// STANDARD_MOTOR_SHIELD : Arduino Motor shield Rev3 based on the L298 with 18V 2A per channel
|
||||
// POLOLU_MOTOR_SHIELD : Pololu MC33926 Motor Driver (not recommended for prog track)
|
||||
// FUNDUMOTO_SHIELD : Fundumoto Shield, no current sensing (not recommended, no short protection)
|
||||
// FIREBOX_MK1 : The Firebox MK1
|
||||
// FIREBOX_MK1S : The Firebox MK1S
|
||||
// IBT_2_WITH_ARDUINO : Arduino Motor Shield for PROG and IBT-2 for MAIN
|
||||
// EX8874_SHIELD : DCC-EX TI DRV8874 based motor shield
|
||||
// EXCSB1 : DCC-EX CSB-1 hardware
|
||||
// EXCSB1_WITH_EX8874 : DCC-EX CSB-1 hardware with DCC-EX TI DRV8874 shield
|
||||
// NO_SHIELD : CS without any motor shield (as an accessory only CS)
|
||||
// |
|
||||
// +-----------------------v
|
||||
//
|
||||
@@ -80,7 +81,7 @@ The configuration file for DCC-EX Command Station
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// NOTE: Not supported on Arduino Uno or Nano
|
||||
// NOTE: Only supported on Arduino Mega
|
||||
// Set to false if you not even want it on the Arduino Mega
|
||||
//
|
||||
#define ENABLE_WIFI true
|
||||
@@ -115,13 +116,13 @@ The configuration file for DCC-EX Command Station
|
||||
// Your password may not contain ``"'' (double quote, ASCII 0x22).
|
||||
#define WIFI_PASSWORD "Your network passwd"
|
||||
//
|
||||
// WIFI_HOSTNAME: You can change this if you have more than one
|
||||
// CS to make them show up with different names on the network.
|
||||
// Otherwise do not touch.
|
||||
// WIFI_HOSTNAME: You probably don't need to change this
|
||||
#define WIFI_HOSTNAME "dccex"
|
||||
//
|
||||
// WIFI_CHANNEL: The default channel is set to "1". If you need to use an
|
||||
// alternate channel (we recommend using only 1,6, or 11) you may change it here.
|
||||
// WIFI_CHANNEL: If the line "#define ENABLE_WIFI true" is uncommented,
|
||||
// WiFi will be enabled (Mega only). The default channel is set to "1" whether
|
||||
// this line exists or not. If you need to use an alternate channel (we recommend
|
||||
// using only 1,6, or 11) you may change it here.
|
||||
#define WIFI_CHANNEL 1
|
||||
//
|
||||
// WIFI_FORCE_AP: If you'd like to specify your own WIFI_SSID in AP mode, set this
|
||||
@@ -131,12 +132,21 @@ The configuration file for DCC-EX Command Station
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ENABLE_ETHERNET: Set to true if you have an Arduino Ethernet card (wired) based
|
||||
// on the W5100/W5500 ethernet chip or an STM32 CS with builin ethernet like the F429ZI.
|
||||
// This is not for Wifi. You will then need the Arduino Ethernet library as well.
|
||||
// ENABLE_ETHERNET: Set to true if you have an Arduino Ethernet card (wired). This
|
||||
// is not for Wifi. You will then need the Arduino Ethernet library as well
|
||||
//
|
||||
//#define ENABLE_ETHERNET true
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// MAX_NUM_TCP_CLIENTS: If you on STM32 Ethernet (and only there) want more than
|
||||
// 9 (*) TCP clients, change this number to for example 20 here **AND** in
|
||||
// STM32lwiopts.h and follow the instructions in STM32lwiopts.h
|
||||
//
|
||||
// (*) It would be 10 if there would not be a bug in LwIP by STM32duino.
|
||||
//
|
||||
//#define MAX_NUM_TCP_CLIENTS 20
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -269,10 +279,9 @@ The configuration file for DCC-EX Command Station
|
||||
// over DCC++. This #define likewise inverts the behaviour of the <a> command
|
||||
// for triggering DCC Accessory Decoders, so that <a addr subaddr 0> generates a
|
||||
// DCC packet with D=1 (close turnout) and <a addr subaddr 1> generates D=0
|
||||
// (throw turnout). This is the same as DCC_ACCESSORY_COMMAND_REVERSE
|
||||
// (throw turnout).
|
||||
//#define DCC_ACCESSORY_RCN_213
|
||||
|
||||
|
||||
//
|
||||
// HANDLING MULTIPLE SERIAL THROTTLES
|
||||
// The command station always operates with the default Serial port.
|
||||
// Diagnostics are only emitted on the default serial port and not broadcast.
|
||||
@@ -334,7 +343,7 @@ The configuration file for DCC-EX Command Station
|
||||
// to the sabertooth controller _as_well_. Default: Undefined.
|
||||
//
|
||||
//#define SABERTOOTH 1
|
||||
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SENSORCAM
|
||||
@@ -346,7 +355,7 @@ The configuration file for DCC-EX Command Station
|
||||
//#define SENSORCAM2_VPIN 600 //define other CAM's if installed.
|
||||
//#define CAM2 SENSORCAM2_VPIN+ //for EX-RAIL commands e.g. IFLT(CAM2 020,1)
|
||||
//
|
||||
// For smoother power-up, when using the CAM, you may need a STARTUP_DELAY.
|
||||
// That is described further above.
|
||||
// For smoother power-up, define a STARTUP_DELAY to allow CAM to initialise ref images
|
||||
//#define STARTUP_DELAY 5000 // up to 20sec. CS delay
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
21
defines.h
21
defines.h
@@ -239,4 +239,25 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_STM32)
|
||||
// The LwIP library for the STM32 wired ethernet has by default 10 TCP
|
||||
// clients defined but because of a bug in the library #11 is not
|
||||
// rejected but kicks out any old connection. By restricting our limit
|
||||
// to 9 the #10 will be rejected by our code so that the number can
|
||||
// never get to 11 which would kick an existing connection.
|
||||
// If you want to change this value, do that in
|
||||
// config.h AND in STM32lwipopts.h.
|
||||
#ifndef MAX_NUM_TCP_CLIENTS
|
||||
#define MAX_NUM_TCP_CLIENTS 9
|
||||
#endif
|
||||
#else
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
// Espressif LWIP stack
|
||||
#define MAX_NUM_TCP_CLIENTS 10
|
||||
#else
|
||||
// Wifi shields etc
|
||||
#define MAX_NUM_TCP_CLIENTS 8
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif //DEFINES_H
|
||||
|
@@ -12,10 +12,18 @@
|
||||
default_envs =
|
||||
mega2560
|
||||
uno
|
||||
unowifiR2
|
||||
nano
|
||||
samd21-dev-usb
|
||||
samd21-zero-usb
|
||||
ESP32
|
||||
Nucleo-F411RE
|
||||
Nucleo-F446RE
|
||||
Teensy3_2
|
||||
Teensy3_5
|
||||
Teensy3_6
|
||||
Teensy4_0
|
||||
Teensy4_1
|
||||
src_dir = .
|
||||
include_dir = .
|
||||
|
||||
@@ -96,7 +104,6 @@ lib_deps =
|
||||
${env.lib_deps}
|
||||
arduino-libraries/Ethernet
|
||||
SPI
|
||||
MDNS_Generic
|
||||
|
||||
lib_ignore = WiFi101
|
||||
WiFi101_Generic
|
||||
@@ -115,7 +122,6 @@ framework = arduino
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
arduino-libraries/Ethernet
|
||||
MDNS_Generic
|
||||
SPI
|
||||
lib_ignore = WiFi101
|
||||
WiFi101_Generic
|
||||
@@ -194,7 +200,7 @@ monitor_speed = 115200
|
||||
monitor_echo = yes
|
||||
|
||||
[env:Nucleo-F411RE]
|
||||
platform = ststm32 @ 17.6.0
|
||||
platform = ststm32 @ ^18.0.0
|
||||
board = nucleo_f411re
|
||||
framework = arduino
|
||||
lib_deps = ${env.lib_deps}
|
||||
@@ -203,7 +209,7 @@ monitor_speed = 115200
|
||||
monitor_echo = yes
|
||||
|
||||
[env:Nucleo-F446RE]
|
||||
platform = ststm32 @ 17.6.0
|
||||
platform = ststm32 @ ^18.0.0
|
||||
board = nucleo_f446re
|
||||
framework = arduino
|
||||
lib_deps = ${env.lib_deps}
|
||||
@@ -215,7 +221,7 @@ monitor_echo = yes
|
||||
; tested as yet
|
||||
;
|
||||
[env:Nucleo-F401RE]
|
||||
platform = ststm32 @ 17.6.0
|
||||
platform = ststm32 @ ^18.0.0
|
||||
board = nucleo_f401re
|
||||
framework = arduino
|
||||
lib_deps = ${env.lib_deps}
|
||||
@@ -228,7 +234,7 @@ monitor_echo = yes
|
||||
; installed before you can let PlatformIO see this
|
||||
;
|
||||
; [env:Nucleo-F413ZH]
|
||||
; platform = ststm32 @ 17.6.0
|
||||
; platform = ststm32 @ ^18.0.0
|
||||
; board = nucleo_f413zh
|
||||
; framework = arduino
|
||||
; lib_deps = ${env.lib_deps}
|
||||
@@ -240,7 +246,7 @@ monitor_echo = yes
|
||||
; installed before you can let PlatformIO see this
|
||||
;
|
||||
[env:Nucleo-F446ZE]
|
||||
platform = ststm32 @ 17.6.0
|
||||
platform = ststm32 @ ^18.0.0
|
||||
board = nucleo_f446ze
|
||||
framework = arduino
|
||||
lib_deps = ${env.lib_deps}
|
||||
@@ -252,7 +258,7 @@ monitor_echo = yes
|
||||
; installed before you can let PlatformIO see this
|
||||
;
|
||||
; [env:Nucleo-F412ZG]
|
||||
; platform = ststm32 @ 17.6.0
|
||||
; platform = ststm32 @ ^18.0.0
|
||||
; board = nucleo_f412zg
|
||||
; framework = arduino
|
||||
; lib_deps = ${env.lib_deps}
|
||||
@@ -264,19 +270,18 @@ monitor_echo = yes
|
||||
; Experimental - Ethernet work still in progress
|
||||
;
|
||||
[env:Nucleo-F429ZI]
|
||||
platform = ststm32 @ 17.6.0
|
||||
platform = ststm32 @ 19.0.0
|
||||
board = nucleo_f429zi
|
||||
framework = arduino
|
||||
lib_deps = ${env.lib_deps}
|
||||
stm32duino/STM32Ethernet @ ^1.4.0
|
||||
stm32duino/STM32duino LwIP @ ^2.1.3
|
||||
MDNS_Generic
|
||||
lib_ignore = WiFi101
|
||||
WiFi101_Generic
|
||||
WiFiEspAT
|
||||
WiFiMulti_Generic
|
||||
WiFiNINA_Generic
|
||||
build_flags = -std=c++17 -Os -g2 -Wunused-variable
|
||||
build_flags = -std=c++17 -Os -g2 -Wunused-variable -DCUSTOM_PERIPHERAL_PINS
|
||||
monitor_speed = 115200
|
||||
monitor_echo = yes
|
||||
upload_protocol = stlink
|
||||
@@ -284,7 +289,7 @@ upload_protocol = stlink
|
||||
; Experimental - Ethernet work still in progress
|
||||
;
|
||||
[env:Nucleo-F439ZI]
|
||||
platform = ststm32 @ 17.6.0
|
||||
platform = ststm32 @ 19.0.0
|
||||
; board = nucleo_f439zi
|
||||
; Temporarily treat it as an F429ZI (they are code compatible) until
|
||||
; the PR to PlatformIO to update the F439ZI JSON file is available
|
||||
@@ -294,13 +299,12 @@ framework = arduino
|
||||
lib_deps = ${env.lib_deps}
|
||||
stm32duino/STM32Ethernet @ ^1.4.0
|
||||
stm32duino/STM32duino LwIP @ ^2.1.3
|
||||
MDNS_Generic
|
||||
lib_ignore = WiFi101
|
||||
WiFi101_Generic
|
||||
WiFiEspAT
|
||||
WiFiMulti_Generic
|
||||
WiFiNINA_Generic
|
||||
build_flags = -std=c++17 -Os -g2 -Wunused-variable
|
||||
build_flags = -std=c++17 -Os -g2 -Wunused-variable -DCUSTOM_PERIPHERAL_PINS
|
||||
monitor_speed = 115200
|
||||
monitor_echo = yes
|
||||
upload_protocol = stlink
|
||||
|
13
version.h
13
version.h
@@ -3,18 +3,7 @@
|
||||
|
||||
#include "StringFormatter.h"
|
||||
|
||||
#define VERSION "5.4.X"
|
||||
// 5.4.X - bugfix branch
|
||||
// 5.4.0 - New version on master
|
||||
// 5.2.96 - EXRAIL additions XFWD() and XREV()
|
||||
// 5.2.95 - Release candidate for 5.4
|
||||
// 5.2.94 - Bugfix: Less confusion and simpler code around the RCN213 defines
|
||||
// 5.2.93 - Bugfix ESP32: clear progTrackSyncMain (join flag) when prog track is removed
|
||||
// 5.2.92 - Bugfix: FADE power off fix, EXRAIL power diagnostic fix.
|
||||
// 5.2.91 - Bugfix: Neopixel I2C overlap check
|
||||
// 5.2.90 - Bugfix: EXRAIL EXTT_TURNTABLE() now has description as optional in line with ocumentation (also fixed DCC_TURNTABLE)
|
||||
// 5.2.89 - EXRAIL SET(vpin[,npins]) RESET(vpin,[,npins]) pin range manipulation
|
||||
// 5.2.88 - Fix bug where EX-Turntable objects return incorrect angle for home with <JP x>
|
||||
#define VERSION "5.2.87"
|
||||
// 5.2.87 - CamParser and IO_EXSensorCam driver
|
||||
// 5.2.86 - IO_TCA8418 driver for keypad matrix input now fully functioning, including being able to use an interrupt pin
|
||||
// 5.2.85 - IO_TM1638 driver, SEG7 Exrail macro and _s7 segment pattern generator.
|
||||
|
Reference in New Issue
Block a user