diff --git a/DCC.cpp b/DCC.cpp index ed2a803..8a6e8e0 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -278,21 +278,39 @@ void DCC::setAccessory(int address, byte port, bool gate, byte onoff /*= 2*/) { } } -void DCC::setExtendedAccessory(int16_t address, int16_t value, byte repeats) { +bool DCC::setExtendedAccessory(int16_t address, int16_t value, byte repeats) { + +/* From https://www.nmra.org/sites/default/files/s-9.2.1_2012_07.pdf + +The Extended Accessory Decoder Control Packet is included for the purpose of transmitting aspect control to signal +decoders or data bytes to more complex accessory decoders. Each signal head can display one aspect at a time. +{preamble} 0 10AAAAAA 0 0AAA0AA1 0 000XXXXX 0 EEEEEEEE 1 + +XXXXX is for a single head. A value of 00000 for XXXXX indicates the absolute stop aspect. All other aspects +represented by the values for XXXXX are determined by the signaling system used and the prototype being +modeled. +*/ +/* CAH Notes: +Thus in byte packet form the format is 10AAAAAA, 0AAA0AA1, 000XXXXX + +Note that the Basic accessory format mentions +"By convention these bits (bits 4-6 of the second data byte) are in ones complement" +but this note is absent from the advanced packet description. +The (~address) construct below applies this because this appears to be +required. + +*/ + if (address != (address & 0x7FF)) return false; // 11 bits + if (value != (value & 0x1F)) return false; // 5 bits - // format is 10AAAAAA, 0AAA0AA1, 000XXXXX - if (address != (address & 0x7F)) return; - if (value != (value & 0x1F)) return; byte b[3]; - b[0]= 0x80 | ((address & 0x7FF)>>5); - b[1]= 0x01 | ((address & 0x1c)<<2) | (address & 0x03)<<1; - b[2]=value & 0x1F; + b[0]= 0x80 | (address>>5); + b[1]= 0x01 | (((~address) & 0x1c)<<2) | ((address & 0x03)<<1); + b[2]=value; DCCWaveform::mainTrack.schedulePacket(b, sizeof(b), repeats); // Repeat on packet three times -#if defined(EXRAIL_ACTIVE) - // TODO RMFT2::activateExtendedEvent(address,value); -#endif -} + return true; + } // // writeCVByteMain: Write a byte with PoM on main. This writes diff --git a/DCC.h b/DCC.h index e1aeae6..aa93520 100644 --- a/DCC.h +++ b/DCC.h @@ -71,7 +71,7 @@ public: static uint32_t getFunctionMap(int cab); static void updateGroupflags(byte &flags, int16_t functionNumber); static void setAccessory(int address, byte port, bool gate, byte onoff = 2); - static void setExtendedAccessory(int16_t address, int16_t value, byte repeats=3); + static bool setExtendedAccessory(int16_t address, int16_t value, byte repeats=3); static bool writeTextPacket(byte *b, int nBytes); // ACKable progtrack calls bitresults callback 0,0 or -1, cv returns value or -1 diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index af6c4ee..db78d71 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -385,17 +385,12 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) } return; - case 'A': // EXTENDED ACCESSORY - { - // Note: if this happens to match a defined EXRAIL - // DCCX_SIGNAL, then EXRAIL will have intercepted - // this command alrerady. - if (params!=2) break; - if (p[0] != (p[0] & 0x7F)) break; - if (p[1] != (p[1] & 0x1F)) break; - DCC::setExtendedAccessory(p[0],p[1]); - } - return; + case 'A': // EXTENDED ACCESSORY + // Note: if this happens to match a defined EXRAIL + // DCCX_SIGNAL, then EXRAIL will have intercepted + // this command alrerady. + if (params==2 && DCC::setExtendedAccessory(p[0],p[1])) return; + break; case 'T': // TURNOUT if (parseT(stream, params, p))