diff --git a/server/src/hardware/protocol/z21/clientkernel.cpp b/server/src/hardware/protocol/z21/clientkernel.cpp index b032be92..4f78a39d 100644 --- a/server/src/hardware/protocol/z21/clientkernel.cpp +++ b/server/src/hardware/protocol/z21/clientkernel.cpp @@ -121,10 +121,11 @@ void ClientKernel::receive(const Message& message) { const auto& reply = static_cast(message); - const int maxFunc = reply.supportsF29F31() ? 31 : 28; - bool val[31 + 1] = {}; + //NOTE: there is also a function at index 0, hence +1 + const int functionIndexMax = std::min(reply.functionIndexMax(), LanXLocoInfo::supportedFunctionIndexMax); + bool val[LanXLocoInfo::supportedFunctionIndexMax + 1] = {}; - for(int i = 0; i <= maxFunc; i++) + for(int i = 0; i <= functionIndexMax; i++) { val[i] = reply.getFunction(i); } @@ -231,7 +232,7 @@ void ClientKernel::receive(const Message& message) EventLoop::call( [this, address=reply.address(), isEStop=reply.isEmergencyStop(), speed = reply.speedStep(), speedMax=reply.speedSteps(), - dir = reply.direction(), val, maxFunc, changes]() + dir = reply.direction(), val, functionIndexMax, changes]() { try { @@ -262,7 +263,7 @@ void ClientKernel::receive(const Message& message) //Function get always updated because we do not store a copy in cache //so there is no way to tell in advance if they changed - for(int i = 0; i <= maxFunc; i++) + for(int i = 0; i <= functionIndexMax; i++) { decoder->setFunctionValue(i, val[i]); } diff --git a/server/src/hardware/protocol/z21/messages.cpp b/server/src/hardware/protocol/z21/messages.cpp index 199c6b01..a3a8659c 100644 --- a/server/src/hardware/protocol/z21/messages.cpp +++ b/server/src/hardware/protocol/z21/messages.cpp @@ -195,7 +195,8 @@ std::string toString(const Message& message, bool raw) s.append("estop"); else s.append(std::to_string(locoInfo.speedStep())).append("/").append(std::to_string(locoInfo.speedSteps())); - for(uint8_t i = 0; i <= LanXLocoInfo::functionIndexMax; i++) + const uint8_t functionIndexMax = locoInfo.functionIndexMax(); + for(uint8_t i = 0; i <= functionIndexMax; i++) s.append(" f").append(std::to_string(i)).append("=").append(locoInfo.getFunction(i) ? "1" : "0"); s.append(" busy=").append(locoInfo.isBusy() ? "1" : "0"); break; diff --git a/server/src/hardware/protocol/z21/messages.hpp b/server/src/hardware/protocol/z21/messages.hpp index cd6635f5..d7f57c56 100644 --- a/server/src/hardware/protocol/z21/messages.hpp +++ b/server/src/hardware/protocol/z21/messages.hpp @@ -1121,7 +1121,7 @@ struct LanXLocoInfo : LanX static constexpr uint8_t directionFlag = 0x80; static constexpr uint8_t speedStepMask = 0x7F; static constexpr uint8_t flagF0 = 0x10; - static constexpr uint8_t functionIndexMax = 28; + static constexpr uint8_t supportedFunctionIndexMax = 31; ///< \sa functionIndexMax static constexpr uint8_t minMessageSize = 7 + 7; static constexpr uint8_t maxMessageSize = 7 + 14; @@ -1131,11 +1131,11 @@ struct LanXLocoInfo : LanX uint8_t db2 = 0; uint8_t speedAndDirection = 0; //db3 uint8_t db4 = 0; - uint8_t f5f12 = 0; //db5 - uint8_t f13f20 = 0; //db6 - uint8_t f21f28 = 0; //db7 - uint8_t f29f31 = 0; //db8 (firmware >= 1.42) - uint8_t checksum = 0; + uint8_t f5f12 = 0; //db5 + uint8_t f13f20 = 0; //db6 + uint8_t f21f28 = 0; //db7 + uint8_t db8 = 0; //db8 is f29f31 (firmware >= 1.42) otherwise checksum + uint8_t db9 = 0; //checksum (firmware >= 1.42) LanXLocoInfo() : LanX(sizeof(LanXLocoInfo), LAN_X_LOCO_INFO) @@ -1233,6 +1233,28 @@ struct LanXLocoInfo : LanX return dataLen() >= 15; } + /*! + * \brief Get maximum fuction index stored in this message + * \return Maximum index + * + * \note There is also a function at index 0 so count it + * + * Maximum function index depends on Z21 firmware protocol version + * versions < 1.42 support up to F28 + * versions >= 1.42 support up to F31 + * + * Messages are backward compatible but older version will only read + * up to their maximum function number + * + * We currently support up to F31 in trasmission and reception \sa supportedFunctionIndexMax + */ + inline uint8_t functionIndexMax() const + { + if(supportsF29F31()) + return 31; + return 28; + } + bool getFunction(uint8_t index) const { if(index == 0) @@ -1246,7 +1268,7 @@ struct LanXLocoInfo : LanX else if(index <= 28) return f21f28 & (1 << (index - 21)); else if(index <= 31 && supportsF29F31()) - return f29f31 & (1 << (index - 29)); + return db8 & (1 << (index - 29)); else return false; } @@ -1296,9 +1318,9 @@ struct LanXLocoInfo : LanX { const uint8_t flag = (1 << (index - 29)); if(value) - f29f31 |= flag; + db8 |= flag; else - f29f31 &= ~flag; + db8 &= ~flag; } }