How is the E1.20 checksum calculated?
The 0xCC checksum is the unsigned 16-bit sum of Start Code through Parameter Data, modulo 0x10000, excluding checksum slots. A miss prints expected versus received and stays FAIL.
This site's adder is additiveChecksum16 in lib/rdm/checksum.ts. Each body byte is added, then masked with & 0xffff. That mask is modulo 0x10000. It is not a CRC. It is not a two's-complement subtract.
The stored value is two big-endian bytes. Their offset is Message Length. On a 26-byte IDENTIFY that offset is 24. Byte 24 is the high byte. Byte 25 is the low byte.
Fields can still be named after a miss. parseRdmFrame still fills UID, command class, and PID. ok stays false. The checksum field shows FAIL, not a corrected value.
Which bytes go into a 0xCC checksum?
Bytes 0 through Message Length minus one. Message Length sits at offset 2 and does not count the two checksum slots.
The body starts at Start Code 0xCC. It ends at the last parameter data byte. PDL 0 means the body is exactly 24 bytes. Manufacturer PID payloads still sit in that window. Unknown command class bytes still sit in that window. The adder does not skip a field it cannot name.
| Window | Bytes | This parser |
|---|---|---|
| 0xCC body | slice(0, messageLength) | Unsigned 16-bit additive sum |
| Checksum slots | 2 bytes BE at messageLength | Compared. Not added. |
| DUB | 12 EUID bytes after 0xAA | Same adder. No 0xFE preamble. |
| ENTTEC wrap | 0x7E ... 0xE7 | Detect and refuse. No checksum. |
How does Message Length set the checksum window?
Message Length is the byte at offset 2. It counts Start Code through parameter data. Frame size is that value plus two.
PDL must equal Message Length minus 24. Those two rules run before a checksum is trusted. A truncated UART line that still starts CC 01 will not get a fake PASS from a short sum.
If captured size is not Message Length plus two, this parser emits a length error. It does not shrink the window to the bytes you happened to paste. It does not pad zeros to force 26 slots.
How do I calculate a checksum for GET IDENTIFY?
Load Example is a 26-byte GET IDENTIFY_DEVICE from the same encoder the tests use. Sum the first 24 bytes. Compare with the last two as big-endian.
cc 01 18 09 c8 a0 10 00 00 09 c8 01 00 cd f9 01 01 00 00 00 20 10 00 00 05 30
Walk those 24 body bytes in order. Keep a 16-bit running total. After offset 23 the total on this sample is 0x0530. Then read the stored slots.
| Offset | Byte | Running sum after this byte |
|---|---|---|
| 0 | 0xcc | 0x00cc |
| 1 | 0x01 | 0x00cd |
| 2 | 0x18 | 0x00e5 |
| 3 | 0x09 | 0x00ee |
| 4 | 0xc8 | 0x01b6 |
| 5 | 0xa0 | 0x0256 |
| 6 | 0x10 | 0x0266 |
| 7 | 0x00 | 0x0266 |
| 8 | 0x00 | 0x0266 |
| 9 | 0x09 | 0x026f |
| 10 | 0xc8 | 0x0337 |
| 11 | 0x01 | 0x0338 |
| 12 | 0x00 | 0x0338 |
| 13 | 0xcd | 0x0405 |
| 14 | 0xf9 | 0x04fe |
| 15 | 0x01 | 0x04ff |
| 16 | 0x01 | 0x0500 |
| 17 | 0x00 | 0x0500 |
| 18 | 0x00 | 0x0500 |
| 19 | 0x00 | 0x0500 |
| 20 | 0x20 | 0x0520 |
| 21 | 0x10 | 0x0530 |
| 22 | 0x00 | 0x0530 |
| 23 | 0x00 | 0x0530 |
| Slot | Value from this encoder |
|---|---|
| Message Length | 24 |
| Expected sum | 0x0530 |
| Stored checksum | 0x0530 |
| Result | PASS |

UID, PID, and command class can still render on that FAIL. The decode is not rewritten to PASS. Do not edit destination UID to chase a match until expected versus received is understood.
What if I include the checksum bytes in the sum?
You get a number that is not stored in the PDU. On this GET IDENTIFY that inclusive total is 0x0565. The slots still hold 0x0530.
Handheld calculators that "sum the whole paste" hit this trap. 0x0565 is 0x0530 plus 0x05 plus 0x30, then masked to 16 bits. This parser never compares against that wider sum.
The same trap exists on a longer frame. Adding the two checksum slots always moves the total. It never produces the value those slots were written to hold.
How does a GET_RESPONSE change the checksum window?
IDENTIFY GET_RESPONSE adds one flag byte. Message Length becomes 25. The extra 0x01 is inside the sum. Checksum slots move to the end of that longer body.
cc 01 19 09 c8 01 00 cd f9 09 c8 a0 10 00 00 01 00 00 00 00 21 10 00 01 01 05 33
This response is 27 bytes. Expected sum is 0x0533. Stored checksum is 0x0533. Command class 0x21 does not change the adder. Only the window length changes.
DEVICE_LABEL GET_RESPONSE is the same rule with a larger PDL. ASCII in the dump column is still body bytes. Checksum still stops before the last two slots. A pretty label with a FAIL checksum is a truncated paste or a typed nybble, not a decoder bug.
Why does my RDM packet checksum fail?
Common misses are checksum slots, leftover bytes, ENTTEC headers, or DUB 0xFE preambles. This parser names fields anyway. The decode stays FAIL.
- Confirm the dump starts CC 01, or is a DUB 0xFE/0xAA body, not 0x7E ... 0xE7.
- Read Message Length at offset 2. Frame size must be that value plus two.
- Confirm PDL equals Message Length minus 24.
- Sum only the body. Stop before the checksum slots.
- Compare expected versus received. Do not rewrite UID bytes to force a match.
A checksum miss is not a length miss. CHECKSUM_MISMATCH prints both 16-bit values. INVALID_MESSAGE_LENGTH and INVALID_PDL fire when those rules break. Fix length first.
How is a Discovery Unique Branch checksum calculated?
It is the additive 16-bit sum of the twelve encoded UID bytes after 0xAA. Preamble 0xFE bytes are not in the sum.

fe fe fe fe fe fe fe aa ab 5d ea dd aa f5 ba 55 aa 55 aa 55 af 57 fb 7f
This sample has 7 preamble bytes, then 0xAA, then EUID ab 5d ea dd aa f5 ba 55 aa 55 aa 55. The 12-byte sum is 0x077b.
Flip the last encoded checksum byte and the code is DUB_CHECKSUM_MISMATCH. Expected 0x077b, received 0x0780. One dump cannot prove two responders versus a bad paste.
How are DUB checksum bytes encoded?
Each UID byte is stored as value OR 0xAA and value OR 0x55. Decode AND-merges the pair. The 16-bit checksum is encoded the same way into four bytes.
Sum the twelve encoded bytes, not the six decoded UID bytes. Summing 09c8:a0100000 as raw UID will not match 0x077b. Including the 0xFE preamble will not match either.
Mute and un-mute still travel as 0xCC PDUs with command class 0x10 or 0x11. Those use the 0xCC body window, not this DUB window. Do not feed a mute into the 12-EUID adder.
What happens if I sum an ENTTEC 0x7E-0xE7 wrapper?
This tool detects that envelope and refuses to unwrap it. A checksum is never run across widget headers.
Wrapping Load Example as 0x7E plus the PDU plus 0xE7 makes enttec with code ENTTEC_WRAPPED. Inner RDM may be fine. This page will not pretend it already stripped the widget.
Strip the wrap in capture software, then paste the 0xCC or DUB body. See the hex dump guide for dump shapes.
Can leftover bytes after 26 slots still PASS?
No. Extra bytes after a complete frame are reported. A passing sum on the first 26 slots is not enough.
Two Load Example pastes concatenated still checksum the first PDU. This parser then emits LEFTOVER_BYTES (). First-frame checksum pass is true. The overall decode is not PASS.
Concatenated GET plus GET_RESPONSE is the usual leftover paste. Decode one PDU at a time. Transaction numbers then tell you they belong together.
What should I paste next?
Paste the PDU in the RDM Packet Decoder Online. Read expected versus received on FAIL. Bytes stay in this browser.
If checksum is the only error, compare the two 16-bit values before rewriting UID. If length or PDL also fail, fix those first. Dialect questions belong on the hex dump guide, not in a wider checksum window.
Frequently asked questions
How is the E1.20 checksum calculated?
The 0xCC checksum is the unsigned 16-bit sum of Start Code through Parameter Data, modulo 0x10000, excluding checksum slots. A miss prints expected versus received and stays FAIL.
Does the 0xCC sum include checksum bytes?
No. Sum bytes 0 through Message Length minus one. Compare that total to the two big-endian bytes at offset Message Length.
What if I add the checksum slots into the total?
You get a number that is not stored in the PDU. On this GET IDENTIFY Load Example that wrong total is 0x0565. The slots still hold 0x0530.
How is a Discovery Unique Branch checksum calculated?
Sum the twelve encoded UID bytes after the 0xAA separator. Do not add preamble 0xFE bytes. The four checksum slots are nibble-encoded, then compared.
Why does my RDM packet checksum fail?
Common misses are checksum slots, leftover bytes, ENTTEC 0x7E-0xE7 headers, and DUB 0xFE preambles. This parser still names fields. The decode stays FAIL.
Can leftover bytes after 26 slots still PASS?
No. Extra bytes after a complete frame are reported. A passing sum on the first 26 slots is not enough.
