Files
fluxengine/lib/crc.cc
David Given 84076674fd Add stateful decoders, which makes formats like the FB-100 much easier to work
with. Add a generic CRC tool allowing all the parameters to be set (currently
unused).
2019-04-12 00:13:56 +02:00

111 lines
1.8 KiB
C++

#include "globals.h"
#include "bytes.h"
#include "crc.h"
template <class T>
T reflect(T bin, unsigned width = sizeof(T)*8)
{
T bout = 0;
while (width--)
{
bout <<= 1;
bout |= (bin & 1);
bin >>= 1;
}
return bout;
}
uint64_t generic_crc(const struct crcspec& spec, const Bytes& bytes)
{
uint64_t crc = spec.init;
uint64_t top = 1LL << (spec.width-1);
uint64_t mask = (top<<1) - 1;
for (uint8_t b : bytes)
{
if (spec.refin)
b = reflect(b);
for (uint8_t i = 0x80; i != 0; i >>= 1)
{
uint64_t bit = crc & top;
crc <<= 1;
if (b & i)
bit ^= top;
if (bit)
crc ^= spec.poly;
}
}
if (spec.refout)
crc = reflect(crc, spec.width);
crc ^= spec.xorout;
return crc & mask;
}
uint16_t sumBytes(const Bytes& bytes)
{
ByteReader br(bytes);
uint16_t i = 0;
while (!br.eof())
i += br.read_8();
return i;
}
uint8_t xorBytes(const Bytes& bytes)
{
ByteReader br(bytes);
uint8_t i = 0;
while (!br.eof())
i ^= br.read_8();
return i;
}
uint16_t crc16(uint16_t poly, uint16_t crc, const Bytes& bytes)
{
ByteReader br(bytes);
while (!br.eof())
{
crc ^= br.read_8() << 8;
for (int i=0; i<8; i++)
crc = (crc & 0x8000) ? ((crc<<1)^poly) : (crc<<1);
}
return crc;
}
uint16_t crc16ref(uint16_t poly, uint16_t crc, const Bytes& bytes)
{
ByteReader br(bytes);
while (!br.eof())
{
crc ^= br.read_8();
for (int i=0; i<8; i++)
crc = (crc & 0x0001) ? ((crc>>1)^poly) : (crc>>1);
}
return crc;
}
/* Thanks to user202729 on StackOverflow for miraculously reverse engineering
* this. */
uint32_t crcbrother(const Bytes& bytes)
{
ByteReader br(bytes);
uint32_t crc = br.read_8();
while (!br.eof())
{
for (int i=0; i<8; i++)
crc = (crc & 0x800000) ? ((crc<<1)^BROTHER_POLY) : (crc<<1);
crc ^= br.read_8();
}
return crc & 0xFFFFFF;
}