Skip to content

Commit

Permalink
accessory packet issues.
Browse files Browse the repository at this point in the history
  • Loading branch information
Asbelos committed Feb 17, 2024
1 parent 7e4093f commit dcd3326
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 23 deletions.
40 changes: 29 additions & 11 deletions DCC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion DCC.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class DCC
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
Expand Down
17 changes: 6 additions & 11 deletions DCCEXParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,17 +385,12 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
}
return;

case 'A': // EXTENDED ACCESSORY <A address value>
{
// 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 <A address value>
// 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 <T ...>
if (parseT(stream, params, p))
Expand Down

0 comments on commit dcd3326

Please sign in to comment.