diff --git a/DCC.cpp b/DCC.cpp index 61ddbc8..70e09af 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -88,7 +88,7 @@ void DCC::setThrottle2( uint16_t cab, byte speedCode) { uint8_t nB = 0; // DIAG(F("setSpeedInternal %d %x"),cab,speedCode); - if (cab > 127) + if (cab > HIGHEST_SHORT_ADDR) b[nB++] = highByte(cab) | 0xC0; // convert train number into a two-byte address b[nB++] = lowByte(cab); @@ -128,7 +128,7 @@ void DCC::setFunctionInternal(int cab, byte byte1, byte byte2) { byte b[4]; byte nB = 0; - if (cab > 127) + if (cab > HIGHEST_SHORT_ADDR) b[nB++] = highByte(cab) | 0xC0; // convert train number into a two-byte address b[nB++] = lowByte(cab); if (byte1!=0) b[nB++] = byte1; @@ -157,7 +157,7 @@ void DCC::setFn( int cab, int16_t functionNumber, bool on) { //non reminding advanced binary bit set byte b[5]; byte nB = 0; - if (cab > 127) + if (cab > HIGHEST_SHORT_ADDR) b[nB++] = highByte(cab) | 0xC0; // convert train number into a two-byte address b[nB++] = lowByte(cab); if (functionNumber <= 127) { @@ -266,7 +266,7 @@ void DCC::setAccessory(int address, byte number, bool activate) { void DCC::writeCVByteMain(int cab, int cv, byte bValue) { byte b[5]; byte nB = 0; - if (cab > 127) + if (cab > HIGHEST_SHORT_ADDR) b[nB++] = highByte(cab) | 0xC0; // convert train number into a two-byte address b[nB++] = lowByte(cab); @@ -287,7 +287,7 @@ void DCC::writeCVBitMain(int cab, int cv, byte bNum, bool bValue) { bValue = bValue % 2; bNum = bNum % 8; - if (cab > 127) + if (cab > HIGHEST_SHORT_ADDR) b[nB++] = highByte(cab) | 0xC0; // convert train number into a two-byte address b[nB++] = lowByte(cab); @@ -552,7 +552,7 @@ void DCC::setLocoId(int id,ACK_CALLBACK callback) { callback(-1); return; } - if (id<=127) + if (id<=HIGHEST_SHORT_ADDR) ackManagerSetup(id, SHORT_LOCO_ID_PROG, callback); else ackManagerSetup(id | 0xc000,LONG_LOCO_ID_PROG, callback); @@ -910,7 +910,7 @@ void DCC::ackManagerLoop() { case COMBINELOCOID: // ackManagerStash is cv17, ackManagerByte is CV 18 - callback( ackManagerByte + ((ackManagerStash - 192) << 8)); + callback( LONG_ADDR_MARKER | ( ackManagerByte + ((ackManagerStash - 192) << 8))); return; case ITSKIP: diff --git a/DCC.h b/DCC.h index 8cb5d97..fea9a1a 100644 --- a/DCC.h +++ b/DCC.h @@ -23,6 +23,16 @@ #include "MotorDrivers.h" #include "FSH.h" +#include "defines.h" +#ifndef HIGHEST_SHORT_ADDR +#define HIGHEST_SHORT_ADDR 127 +#else +#if HIGHEST_SHORT_ADDR > 127 +#error short addr greater than 127 does not make sense +#endif +#endif +const uint16_t LONG_ADDR_MARKER = 0x4000; + typedef void (*ACK_CALLBACK)(int16_t result); enum ackOp : byte diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index be95871..e581155 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -965,10 +965,21 @@ void DCCEXParser::callback_R(int16_t result) commitAsyncReplyStream(); } -void DCCEXParser::callback_Rloco(int16_t result) -{ - StringFormatter::send(getAsyncReplyStream(), F("\n"), result); - commitAsyncReplyStream(); +void DCCEXParser::callback_Rloco(int16_t result) { + const FSH * detail; + if (result<=0) { + detail=F("\n"); + } else { + bool longAddr=result & LONG_ADDR_MARKER; //long addr + if (longAddr) + result = result^LONG_ADDR_MARKER; + if (longAddr && result <= HIGHEST_SHORT_ADDR) + detail=F("\n"); + else + detail=F("\n"); + } + StringFormatter::send(getAsyncReplyStream(), detail, result); + commitAsyncReplyStream(); } void DCCEXParser::callback_Wloco(int16_t result) diff --git a/WiThrottle.cpp b/WiThrottle.cpp index 07017ba..8aabb82 100644 --- a/WiThrottle.cpp +++ b/WiThrottle.cpp @@ -51,6 +51,8 @@ #include "version.h" #include "RMFT2.h" +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) #define LOOPLOCOS(THROTTLECHAR, CAB) for (int loco=0;locomark(stashClient); - if (locoid<0) StringFormatter::send(stashStream,F("HMNo loco found on prog track\n")); + + if (locoid<=0) + StringFormatter::send(stashStream,F("HMNo loco found on prog track\n")); else { - char addcmd[20]={'M',stashThrottleChar,'+',LorS(locoid) }; - itoa(locoid,addcmd+4,10); - stashInstance->multithrottle(stashStream, (byte *)addcmd); - DCCWaveform::progTrack.setPowerMode(POWERMODE::ON); - DCC::setProgTrackSyncMain(true); // <1 JOIN> so we can drive loco away + // short or long + char addrchar; + if (locoid & LONG_ADDR_MARKER) { // long addr + locoid = locoid ^ LONG_ADDR_MARKER; + addrchar = 'L'; + } else + addrchar = 'S'; + if (addrchar == 'L' && locoid <= HIGHEST_SHORT_ADDR ) + StringFormatter::send(stashStream,F("HMLong addr <= " STR(HIGHEST_SHORT_ADDR) " not supported\n")); + else { + char addcmd[20]={'M',stashThrottleChar,'+', addrchar}; + itoa(locoid,addcmd+4,10); + stashInstance->multithrottle(stashStream, (byte *)addcmd); + DCCWaveform::progTrack.setPowerMode(POWERMODE::ON); + DCC::setProgTrackSyncMain(true); // <1 JOIN> so we can drive loco away + } } stashStream->commit(); } diff --git a/config.example.h b/config.example.h index e064db8..7adab25 100644 --- a/config.example.h +++ b/config.example.h @@ -138,6 +138,17 @@ The configuration file for DCC-EX Command Station // // #define DISABLE_EEPROM +///////////////////////////////////////////////////////////////////////////////////// +// 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 +// another view. Lenz CS for example have considered addresses long from 100. If +// you want to change to that mode, do +//#define HIGHEST_SHORT_ADDR 99 +// If you want to run all your locos addressed long format, you could even do a +//#define HIGHEST_SHORT_ADDR 0 +// We do not support to use the same address, for example 100(long) and 100(short) +// at the same time, there must be a border. + ///////////////////////////////////////////////////////////////////////////////////// // // DEFINE TURNOUTS/ACCESSORIES FOLLOW NORM RCN-213