diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 2c50ac1..a6a68d8 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -682,10 +682,10 @@ bool DCCEXParser::parseT(Print *stream, int16_t params, int16_t p[]) // By default turnout command uses 0=throw, 1=close, // but legacy DCC++ behaviour is 1=throw, 0=close. case 0: - state = Turnout::useLegacyTurnoutBehaviour; + state = Turnout::useClassicTurnoutCommands; break; case 1: - state = !Turnout::useLegacyTurnoutBehaviour; + state = !Turnout::useClassicTurnoutCommands; break; case HASH_KEYWORD_C: state = true; diff --git a/LCDDisplay.h b/LCDDisplay.h index 15ba524..6c6e150 100644 --- a/LCDDisplay.h +++ b/LCDDisplay.h @@ -21,9 +21,7 @@ #include #include "DisplayInterface.h" -#if __has_include ( "config.h") - #include "config.h" -#endif +#include "defines.h" // includes config.h as well // Allow maximum message length to be overridden from config.h #if !defined(MAX_MSG_SIZE) diff --git a/Turnouts.cpp b/Turnouts.cpp index 7b87153..a959cdd 100644 --- a/Turnouts.cpp +++ b/Turnouts.cpp @@ -20,13 +20,8 @@ * along with CommandStation. If not, see . */ -// Set the following definition to true for = throw and = close -// or to false for = close and = throw (the original way). -#ifndef USE_LEGACY_TURNOUT_BEHAVIOUR -#define USE_LEGACY_TURNOUT_BEHAVIOUR false -#endif -#include "defines.h" +#include "defines.h" // includes config.h #include "EEStore.h" #include "StringFormatter.h" #include "RMFT2.h" @@ -47,7 +42,12 @@ * Public static data */ int Turnout::turnoutlistHash = 0; - bool Turnout::useLegacyTurnoutBehaviour = USE_LEGACY_TURNOUT_BEHAVIOUR; + + #if defined(USE_RCN_213_TURNOUT_COMMANDS) + const bool Turnout::useClassicTurnoutCommands = false; + #else + const bool Turnout::useClassicTurnoutCommands = true; + #endif /* * Protected static functions @@ -74,9 +74,11 @@ turnoutlistHash++; } + // For DCC++ classic compatibility, state reported to JMRI is 1 for thrown and 0 for closed; + // if consistency with RCN-213 has been selected, it is 0 for thrown and 1 for closed. void Turnout::printState(Print *stream) { StringFormatter::send(stream, F("\n"), - _turnoutData.id, _turnoutData.closed ^ useLegacyTurnoutBehaviour); + _turnoutData.id, _turnoutData.closed ^ useClassicTurnoutCommands); } // Remove nominated turnout from turnout linked list and delete the object. @@ -279,10 +281,12 @@ return tt; } + // For DCC++ classic compatibility, state reported to JMRI is 1 for thrown and 0 for closed; + // if consistency with RCN-213 has been selected, it is 0 for thrown and 1 for closed. void ServoTurnout::print(Print *stream) { StringFormatter::send(stream, F("\n"), _turnoutData.id, _servoTurnoutData.vpin, _servoTurnoutData.thrownPosition, _servoTurnoutData.closedPosition, _servoTurnoutData.profile, - _turnoutData.closed ^ useLegacyTurnoutBehaviour); + _turnoutData.closed ^ useClassicTurnoutCommands); } // ServoTurnout-specific code for throwing or closing a servo turnout. @@ -312,6 +316,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 { @@ -363,19 +373,19 @@ void DCCTurnout::print(Print *stream) { StringFormatter::send(stream, F("\n"), _turnoutData.id, (((_dccTurnoutData.address-1) >> 2)+1), ((_dccTurnoutData.address-1) & 3), - _turnoutData.closed ^ useLegacyTurnoutBehaviour); - // Also report using classic DCC++ syntax for DCC accessory turnouts + _turnoutData.closed ^ useClassicTurnoutCommands); + // Also report using classic DCC++ syntax for DCC accessory turnouts, since JMRI expects this. StringFormatter::send(stream, F("\n"), _turnoutData.id, (((_dccTurnoutData.address-1) >> 2)+1), ((_dccTurnoutData.address-1) & 3), - _turnoutData.closed ^ useLegacyTurnoutBehaviour); + _turnoutData.closed ^ useClassicTurnoutCommands); } bool DCCTurnout::setClosedInternal(bool close) { // DCC++ Classic behaviour is that Throw writes a 1 in the packet, // and Close writes a 0. - // RCN-214 specifies that Throw is 0 and Close is 1. + // RCN-213 specifies that Throw is 0 and Close is 1. DCC::setAccessory((((_dccTurnoutData.address-1) >> 2) + 1), - ((_dccTurnoutData.address-1) & 3), close ^ useLegacyTurnoutBehaviour); + ((_dccTurnoutData.address-1) & 3), close ^ !rcn213Compliant); _turnoutData.closed = close; return true; } @@ -439,7 +449,7 @@ void VpinTurnout::print(Print *stream) { StringFormatter::send(stream, F("\n"), _turnoutData.id, _vpinTurnoutData.vpin, - _turnoutData.closed ^ useLegacyTurnoutBehaviour); + _turnoutData.closed ^ useClassicTurnoutCommands); } bool VpinTurnout::setClosedInternal(bool close) { @@ -503,6 +513,6 @@ void LCNTurnout::print(Print *stream) { StringFormatter::send(stream, F("\n"), _turnoutData.id, - _turnoutData.closed ^ useLegacyTurnoutBehaviour); + _turnoutData.closed ^ useClassicTurnoutCommands); } diff --git a/Turnouts.h b/Turnouts.h index 45f60a6..27b1444 100644 --- a/Turnouts.h +++ b/Turnouts.h @@ -104,8 +104,8 @@ public: * Static data */ static int turnoutlistHash; - static bool useLegacyTurnoutBehaviour; - + static const bool useClassicTurnoutCommands; + /* * Public base class functions */ @@ -182,11 +182,12 @@ private: } _servoTurnoutData; // 6 bytes // Constructor - ServoTurnout(uint16_t id, VPIN vpin, uint16_t thrownPosition, uint16_t closedPosition, uint8_t profile, bool closed = true); + ServoTurnout(uint16_t id, VPIN vpin, uint16_t thrownPosition, uint16_t closedPosition, uint8_t profile, bool closed); public: // Create function - static Turnout *create(uint16_t id, VPIN vpin, uint16_t thrownPosition, uint16_t closedPosition, uint8_t profile, bool closed = true); + // If the initial state isn't specified, use true for RCN-213 consistency and false for DCC++ classic compatibility. + static Turnout *create(uint16_t id, VPIN vpin, uint16_t thrownPosition, uint16_t closedPosition, uint8_t profile, bool closed = !useClassicTurnoutCommands); // Load a Servo turnout definition from EEPROM. The common Turnout data has already been read at this point. static Turnout *load(struct TurnoutData *turnoutData); @@ -223,6 +224,8 @@ public: static Turnout *load(struct TurnoutData *turnoutData); void print(Print *stream) override; + static const bool rcn213Compliant; + protected: bool setClosedInternal(bool close) override; void save() override; @@ -243,11 +246,12 @@ private: } _vpinTurnoutData; // 2 bytes // Constructor - VpinTurnout(uint16_t id, VPIN vpin, bool closed=true); + VpinTurnout(uint16_t id, VPIN vpin, bool closed); public: // Create function - static Turnout *create(uint16_t id, VPIN vpin, bool closed=true); + // If the initial state isn't specified, use true for RCN-213 consistency and false for DCC++ classic compatibility. + static Turnout *create(uint16_t id, VPIN vpin, bool closed=!useClassicTurnoutCommands); // Load a VPIN turnout definition from EEPROM. The common Turnout data has already been read at this point. static Turnout *load(struct TurnoutData *turnoutData); @@ -270,12 +274,13 @@ private: // struct LCNTurnoutData { // } _lcnTurnoutData; // 0 bytes - // Constructor - LCNTurnout(uint16_t id, bool closed=true); + // Constructor + LCNTurnout(uint16_t id, bool closed); public: // Create function - static Turnout *create(uint16_t id, bool closed=true); + // If the initial state isn't specified, use true for RCN-213 consistency and false for DCC++ classic compatibility. + static Turnout *create(uint16_t id, bool closed=!useClassicTurnoutCommands); bool setClosedInternal(bool close) override; diff --git a/config.example.h b/config.example.h index 0debbc2..3575cb0 100644 --- a/config.example.h +++ b/config.example.h @@ -129,4 +129,27 @@ The configuration file for DCC-EX Command Station #define SCROLLMODE 1 ///////////////////////////////////////////////////////////////////////////////////// +// +// DEFINE TURNOUTS/ACCESSORIES FOLLOW NORM RCN-213 +// +// According to norm RCN-213 a DCC packet with a 1 is closed/straight +// and one with a 0 is thrown/diverging. In DCC++ Classic, and in previous +// versions of DCC++EX, a throw command was implemented in the packet as +// '1' and a close command as '0'. The #define below makes the states +// match with the norm. But we don't want to cause havoc on existent layouts, +// so we define this only for new installations. If you don't want this, +// don't add it to your config.h. +#define DCC_TURNOUTS_RCN_213 +// In addition to the above, there is an option to allow the values in the commands +// sent and received from JMRI to be changed to be consistent with the definition in +// RCN-213. In DCC++ Classic and in previous versions of DCC++EX, a command +// requested a 'throw' and requested a 'close'. +// The macro below, when present, allows this behaviour to be reversed so that a +// requests the turnout to 'close' and requests it to 'throw'. +// This should only be used if the command processor (JMRI) writing to the serial port +// supports it, otherwise turnout operation commands received over the serial port +// will be reversed. +//#define USE_RCN_213_TURNOUT_COMMANDS + +/////////////////////////////////////////////////////////////////////////////////////