45 if (pkt.packet_header.
is_pkt)
47 return StringPrintf(
"[cmd:%u]", pkt.command_header.
cmd);
53 options +=
"[marklin]";
61 options +=
"[long_preamble]";
65 options +=
"[sense_ack]";
70 StringPrintf(
"[repeat %u times]", pkt.packet_header.
rept_count + 1);
74 return options +
" no payload";
76 if (bin_payload || pkt.packet_header.
is_marklin)
79 for (
unsigned i = 0; i < pkt.
dlc; ++i)
81 options += StringPrintf(
"%02x ", pkt.
payload[i]);
91 bool is_idle_packet =
false;
92 bool is_basic_accy_packet =
false;
93 bool is_unknown_packet =
false;
94 bool is_svc_packet =
false;
95 unsigned accy_address = 0;
104 using namespace dcc::Defs;
105 is_svc_packet =
true;
106 uint8_t cmd = pkt.
payload[ofs];
107 int cv = (((pkt.
payload[ofs] & 0x3) << 8) | pkt.
payload[ofs + 1]) + 1;
108 int reg = (pkt.
payload[ofs] & 0x7) + 1;
112 pkt.packet_header.
skip_ec ? pkt.
dlc - ofs - 1 : pkt.
dlc - ofs;
113 if (num_bytes == 3 && (cmd & DCC_SVC_MASK) == DCC_SVC_WRITE)
115 options += StringPrintf(
116 "[svc] Direct Write Byte CV %d = %d", cv, pkt.
payload[ofs + 2]);
119 else if (num_bytes == 3 && (cmd & DCC_SVC_MASK) == DCC_SVC_VERIFY)
121 options += StringPrintf(
"[svc] Direct Verify Byte CV %d =?= %d", cv,
125 else if (num_bytes == 3 &&
126 ((cmd & DCC_SVC_MASK) == DCC_SVC_BIT_MANIPULATE) &&
127 ((pkt.
payload[ofs + 2] & DCC_SVC_BITVAL_MASK) ==
128 DCC_SVC_BITVAL_WRITE))
130 int bitnum = pkt.
payload[ofs + 2] & 7;
131 int bitval = pkt.
payload[ofs + 2] & DCC_SVC_BITVAL_VALUE ? 1 : 0;
132 options += StringPrintf(
133 "[svc] Direct Write Bit CV %d bit %d = %d", cv, bitnum, bitval);
136 else if (num_bytes == 3 &&
137 ((cmd & DCC_SVC_MASK) == DCC_SVC_BIT_MANIPULATE) &&
138 ((pkt.
payload[ofs + 2] & DCC_SVC_BITVAL_MASK) ==
139 DCC_SVC_BITVAL_VERIFY))
141 int bitnum = pkt.
payload[ofs + 2] & 7;
142 int bitval = pkt.
payload[ofs + 2] & DCC_SVC_BITVAL_VALUE ? 1 : 0;
144 StringPrintf(
"[svc] Direct Verify Bit CV %d bit %d =?= %d", cv,
148 else if (num_bytes == 2 &&
149 (cmd & DCC_SVC_PAGED_MASK) == DCC_SVC_PAGED_WRITE)
151 options += StringPrintf(
"[svc] Paged Write Byte Reg %d = %d", reg,
155 else if (num_bytes == 2 &&
156 (cmd & DCC_SVC_PAGED_MASK) == DCC_SVC_PAGED_VERIFY)
158 options += StringPrintf(
"[svc] Paged Verify Byte Reg %d =?= %d",
165 is_svc_packet =
false;
173 else if (pkt.
payload[ofs] == 0xff)
175 options +=
" Idle packet";
179 options += StringPrintf(
" unexpected[0x%02x]", pkt.
payload[ofs]);
181 is_idle_packet =
true;
183 else if (pkt.
payload[ofs] == 0)
185 options +=
" Broadcast";
192 else if ((pkt.
payload[ofs] & 0x80) == 0)
194 options += StringPrintf(
" Short Address %u", pkt.
payload[ofs]);
197 else if ((pkt.
payload[ofs] & 0xC0) == 0x80)
200 is_basic_accy_packet =
true;
201 accy_address = (pkt.
payload[ofs] & 0b111111) << 3;
207 unsigned addr = pkt.
payload[ofs] & 0x3F;
212 options += StringPrintf(
" Long Address %u", addr);
213 }
else if (pkt.
payload[ofs] == 254) {
214 options +=
" Logon packet";
215 is_unknown_packet =
true;
216 while (ofs < pkt.
dlc)
218 options += StringPrintf(
" 0x%02x", pkt.
payload[ofs++]);
220 }
else if (pkt.
payload[ofs] == 253) {
221 options +=
" Advanced extended packet";
222 is_unknown_packet =
true;
223 while (ofs < pkt.
dlc)
225 options += StringPrintf(
" 0x%02x", pkt.
payload[ofs++]);
228 uint8_t cmd = pkt.
payload[ofs];
229 if (!is_unknown_packet)
233 if (is_basic_accy_packet && ((cmd & 0x80) == 0x80))
235 accy_address |= cmd & 0b111;
237 bool is_activate = cmd & 1;
239 accy_address |= ((~cmd) & 0b111) << 9;
240 unsigned user_address =
241 Defs::accy_address_binary_to_user(accy_address >> 1);
243 accy_address & 1 ?
"closed/normal/on" :
"thrown/reverse/off";
244 const char* a_d = is_activate ?
"activate" :
"deactivate";
245 options += StringPrintf(
246 " Accy %u (user %u %s) %s", accy_address, user_address, n_r, a_d);
248 else if (is_unknown_packet || is_svc_packet)
251 else if ((cmd & 0xC0) == 0x40)
254 bool is_forward = (cmd & 0x20) != 0;
256 options += is_forward ?
'F' :
'R';
257 uint8_t speed = ((cmd & 0xF) << 1) | ((cmd & 0x10) >> 4);
267 options +=
" E-STOP";
270 options +=
" E-STOP'";
273 options += StringPrintf(
" %u", speed - 3);
276 else if (cmd == 0x3F) {
278 uint8_t val = pkt.
payload[ofs];
280 bool is_forward = (val & 0x80) != 0;
281 uint8_t speed = val & 0x7F;
282 options +=
" SPD128 ";
283 options += is_forward ?
'F' :
'R';
290 options +=
" E-STOP";
293 options += StringPrintf(
" %u", speed - 1);
296 else if ((cmd >> 5) == 0b100)
299 options += StringPrintf(
" F[0-4]=%d%d%d%d%d", (cmd >> 4) & 1,
300 (cmd >> 0) & 1, (cmd >> 1) & 1, (cmd >> 2) & 1, (cmd >> 3) & 1);
302 else if ((cmd >> 5) == 0b101)
307 options +=
" F[5-8]=";
311 options +=
" F[9-12]=";
313 options += StringPrintf(
"%d%d%d%d", (cmd >> 0) & 1, (cmd >> 1) & 1,
314 (cmd >> 2) & 1, (cmd >> 3) & 1);
316 else if ((cmd >> 5) == 0b110)
319 uint8_t c = cmd & 0x1F;
320 if ((c & ~1) == 0b11110)
324 options +=
" F[21-28]=";
328 options +=
" F[13-20]=";
332 for (
int i = 0; i < 8; ++i, c >>= 1)
333 options +=
'0' + (c & 1);
340 else if (cmd == 0 && is_idle_packet)
343 else if ((cmd >> 4) == 0b1110)
346 options +=
" POM CV";
347 unsigned kk = (cmd >> 2) & 3;
348 unsigned cv = (cmd & 3) << 8;
351 options += StringPrintf(
"%d", cv + 1);
352 uint8_t d = pkt.
payload[ofs++];
358 options += StringPrintf(
" resvd %02x", d);
363 options += StringPrintf(
" read/verify %d", d);
368 options += StringPrintf(
" write = %d", d);
373 unsigned bit = d & 7;
374 unsigned value = (d >> 3) & 1;
375 if ((d & 0xE0) != 0xE0)
377 options += StringPrintf(
" bit manipulate unknown (%02x)", d);
380 if ((d & 0x10) == 0x10)
382 options += StringPrintf(
" bit %d write = %d", bit, value);
386 options += StringPrintf(
" bit %d verify ?= %d", bit, value);
394 if (ofs == pkt.
dlc && (pkt.packet_header.
skip_ec == 0 || is_unknown_packet))
398 else if (((ofs + 1) == pkt.
dlc) && pkt.packet_header.
skip_ec == 1)
401 for (
unsigned i = 0; i + 1 < pkt.
dlc; ++i)
407 options += StringPrintf(
" [bad EC expected 0x%02x actual 0x%02x]",
413 options += StringPrintf(
" [bad dlc, exp %u, actual %u]", ofs+1, pkt.
dlc);
414 while (ofs < pkt.
dlc)
416 options += StringPrintf(
" 0x%02x", pkt.
payload[ofs++]);
421 options +=
" [csum err]";