From f5ce7276bd36900c761470d647027a2a86431850 Mon Sep 17 00:00:00 2001 From: Wijnand Modderman-Lenstra Date: Fri, 11 Dec 2015 23:57:27 +0100 Subject: [PATCH] Added CRC algos --- crc/crc16/ctc16.go | 62 +++++++++++++++++++++++++++++++ crc/quadres_16_7/quadres_16_7.go | 63 ++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 crc/crc16/ctc16.go create mode 100644 crc/quadres_16_7/quadres_16_7.go diff --git a/crc/crc16/ctc16.go b/crc/crc16/ctc16.go new file mode 100644 index 0000000..d53a6e7 --- /dev/null +++ b/crc/crc16/ctc16.go @@ -0,0 +1,62 @@ +// Package crc16 implements the 16-bit cyclic redundancy check, or CRC-16, +// checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for +// information. +package crc16 + +// Predefined polynomnials +const ( + // Used by X.25, V.41, HDLC FCS, XMODEM, Bluetooth, PACTOR, SD, ... + CCITT = 0x8408 +) + +// Table is a 256-word table representing the polynomial for efficient processing. +type Table [256]uint16 + +var ( + CCITTTable = makeTable(CCITT) +) + +// MakeTable returns the Table constructed from the specified polynomial. +func MakeTable(poly uint16) *Table { + return makeTable(poly) +} + +// makeTable returns the Table constructed from the specified polynomial. +func makeTable(poly uint16) *Table { + t := new(Table) + for i := 0; i < 256; i++ { + crc := uint16(i) + for j := 0; j < 8; j++ { + if crc&1 == 1 { + crc = (crc >> 1) ^ poly + } else { + crc >>= 1 + } + } + t[i] = crc + } + return t +} + +// Update returns the result of adding the bytes in p to the crc. +func Update(crc uint16, tab *Table, p []byte) uint16 { + return update(crc, tab, p) +} + +func update(crc uint16, tab *Table, p []byte) uint16 { + crc = ^crc + for _, v := range p { + crc = tab[byte(crc)^v] ^ (crc >> 8) + } + return ^crc +} + +// Checksum returns the CRC-16 checksum of data using the polynomial represented by the Table. +func Checksum(data []byte, tab *Table) uint16 { + return Update(0, tab, data) +} + +// ChecksumCCITT returns the CRC-16 checksum of data using the CCITT polynomial. +func ChecksumCCITT(data []byte) uint16 { + return update(0, CCITTTable, data) +} diff --git a/crc/quadres_16_7/quadres_16_7.go b/crc/quadres_16_7/quadres_16_7.go new file mode 100644 index 0000000..abe187d --- /dev/null +++ b/crc/quadres_16_7/quadres_16_7.go @@ -0,0 +1,63 @@ +// Package quadres_16_7 implements the quadratic residue (16, 7, 6) parity check. +package quadres_16_7 + +import "github.com/pd0mz/go-dmr/bit" + +var ( + validDataParities = [128]bit.Bits{} +) + +type Codeword struct { + Data bit.Bits + Parity bit.Bits +} + +func NewCodeword(bits bit.Bits) *Codeword { + if len(bits) < 16 { + return nil + } + + return &Codeword{ + Data: bits[:7], + Parity: bits[7:16], + } +} + +func ParityBits(bits bit.Bits) bit.Bits { + parity := make(bit.Bits, 9) + // Multiplying the generator matrix with the given data bits. + // See DMR AI spec. page 134. + parity[0] = bits[1] ^ bits[2] ^ bits[3] ^ bits[4] + parity[1] = bits[2] ^ bits[3] ^ bits[4] ^ bits[5] + parity[2] = bits[0] ^ bits[3] ^ bits[4] ^ bits[5] ^ bits[6] + parity[3] = bits[2] ^ bits[3] ^ bits[5] ^ bits[6] + parity[4] = bits[1] ^ bits[2] ^ bits[6] + parity[5] = bits[0] ^ bits[1] ^ bits[4] + parity[6] = bits[0] ^ bits[1] ^ bits[2] ^ bits[5] + parity[7] = bits[0] ^ bits[1] ^ bits[2] ^ bits[3] ^ bits[6] + parity[8] = bits[0] ^ bits[2] ^ bits[4] ^ bits[5] ^ bits[6] + return parity +} + +func Check(bits bit.Bits) bool { + codeword := NewCodeword(bits) + if codeword == nil { + return false + } + + var dataval uint8 + for col := uint8(0); col < 7; col++ { + if codeword.Data[col] == 1 { + dataval |= (1 << (7 - col)) + } + } + + return codeword.Parity.Equal(validDataParities[dataval]) +} + +func init() { + for i := byte(0); i < 128; i++ { + bits := bit.NewBits([]byte{i}) + validDataParities[i] = ParityBits(bits) + } +}