# README
crcutil
When communicating with hardware devices like integrated circuits, often CRC sums need to be calculated with polynomials of orders lower than 32, like 3, 4, 6, 8 or 16. Sometimes the so-called reflected form of algorithms has to be used on the wire, sometimes the normal form — or even both forms in the same protocol; in some cases obscure additional reflections need to be performed.
As the Go standard library offers no support for these smaller widths of CRCs — also its crc32 implementation implements solely the commonly used reflected form of the algorithm, and does not provide a generic way to specify initial values or final XORing —, this module tries to provide that functionality in a generic way.
Using the type Poly
, a polynomial may be specified by its word value and bit width,
and whether the word refers to the normal, reflected, or a reciprocal representation.
A value of type Poly
may be converted to other representations, e.g. from normal to reflected form, using the corresponding method.
From a Poly
, a lookup table may be created that may be used directly, if the amount of data is very small, like e.g. in case of a CRC-3.
A Model
specifies a CRC algorithm: the polynomial,
the initial value (resp. optional initial inversion) to be used,
and whether a final operation like inversion (XORing) shall be applied. From a static Model
,
an Inst
may be created that allows to calculate a checksum over an amount of data.
There exist sub-packages poly{n}
and crc{n}
that provide concrete versions of the generic Poly
and Model
types for some common values of bit widths and word types.
One example for a predefined Model
is crc8.SAEJ1850
, which uses poly8.SAEJ1850
with initial and final bitwise inversion. Another example is crc16.Modbus
, based on the reversed form of poly16.IBM
.
Example
As a real example, the LED driver circuit Infineon TLD7002-16ES uses both a CRC-3 in reflected form and a CRC-8 (SAEJ1850) in normal form in the same serial protocol.
CRC-3
The CRC-3 polynomial x³ + x¹ + 1 (GSM, value = 0b11
= 3) can be created in the following equivalent ways:
p := poly3.GSM // using predefined polynomial
p := poly3.New(0b11) // 0b11 = 2¹ + 2°
p := &poly8.Poly{Word: 0b11, Width: 3}
p := &Poly[uint8]{Word: 0b11, Width: 3} // using the generic type
Since the 3-bit polynomial can be represented by an 8-bit value,
the poly3
internally uses poly8.Poly
,
like shown in the third line above.
If we wanted to create a lookup table for five bits of data, with an initial value of 5 — as defined by the specification — encoded into the table, we could write
p := poly3.GSM.ReversedForm()
tab := p.MakeTable(crcutil.WithInitialValue(5), crcutil.WithDataWidth(5))
To get the CRC-sum of a 5-bit value of 13 it would be sufficient to
evaluate tab[13]
.
For more details see the example for func (*Poly[T]) MakeTable()
in the documentation.
CRC-8-SAE-J1850
To calculate a checksum over some bytes using the SAE-J1850 polynomial x⁸ + x⁴ + x³ + x² + 1, follow this example (compare the result the one listed at AUTOSAR Specification of CRC Routines, p.24):
// create an instance
crc := crc8.SAEJ1850.New()
// insert some bytes
crc.Write([]byte{0xF2, 0x01, 0x83})
fmt.Printf("0x02x\n", crc.Sum())
// => 0x37
Implicit +1 notation
Functions FromImplicit1Notation
and FromImplicit1NotationReciprocal
create a Poly
from a polynomial word in Koopman's implicit +1 notation,
which may be helpful when using polynomials with specific Hamming Distance
properties from the tables provided by Philip Koopman.
hash.Hash interface
For an implementation aligned with Go's hash.Hash
interface, see github.com/knieriem/hash, which is a thin wrapper
around crcutil
.