Closed gpgib6 closed 4 years ago
The frame sync bytes include five reserved bits that have fixed values. Because these bits are fixed, they are included in the preamble to reduce false-positives when searching sample data, but they are actually part of the packet body and are necessary for the checksum.
The checksum is generated from bytes 2-10 and appended to the packet. If you then calculate the checksum over the packet and the provided checksum (bytes 2-12), the packet is valid if the calculated checksum is 0.
func TestChecksum(t *testing.T) {
// Standard checksum parameters for SCM.
bch := crc.NewCRC("BCH", 0, 0x6F63, 0)
// Allocate a packet. We're leaving off the sync words here.
pkt := make([]byte, 10)
// Fill the packet with random bytes except the checksum bytes.
rand.Read(pkt[:8])
// Calculate the checksum over the first 8 bytes.
check := bch.Checksum(pkt[:8])
t.Logf("%02X %04X\n", pkt, check)
// Append the checksum to the packet.
pkt[8] = uint8(check >> 8)
pkt[9] = uint8(check)
// Check that the packet is valid by calculating the checksum over the
// packet and the previously calculated checksum.
check = bch.Checksum(pkt)
t.Logf("%02X %04X\n", pkt, check)
if check != 0 {
t.Fatalf("invalid checksum 0x%04X != 0x%04X\n", check, 0)
}
}
$ go test -v -run=Checksum
=== RUN TestChecksum
--- PASS: TestChecksum (0.00s)
scm_test.go:100: F0B970E815CA48130000 7184
scm_test.go:109: F0B970E815CA48137184 0000
PASS
ok github.com/bemasher/rtlamr/scm 0.405s
thank you for clarifying this and the additional details!
the preamble is 21 bits so must in theory take up more than 2 bytes. but in the checksum (scm.go, line 76):
It looks like Bytes[0] and Bytes[1] are passed over to skip the preamble but wouldn't part of the preamble still be in Bytes[2]? Also it looks like the 16-bit checksum supplied by the meter is also passed to the internal checksum calculation of this code.