Clean up CRC class/interface, make more like boost::crc_basic.

This commit is contained in:
Jared Boone 2015-12-08 10:35:54 -08:00
parent c38beb70e5
commit 7cded79b59
3 changed files with 62 additions and 67 deletions

View File

@ -132,23 +132,18 @@ struct PacketTooLong {
struct CRCCheck { struct CRCCheck {
bool operator()(const ::Packet& packet) { bool operator()(const ::Packet& packet) {
const size_t fcs_length = 16;
const size_t data_and_fcs_length = packet.size() - 7; const size_t data_and_fcs_length = packet.size() - 7;
const size_t data_length = data_and_fcs_length - 16; const size_t data_length = data_and_fcs_length - fcs_length;
CRCFieldReader field_crc { packet }; CRCFieldReader field_crc { packet };
CRC<uint16_t> ais_fcs { 0x1021 }; CRC<uint16_t> ais_fcs { 0x1021, 0xffff, 0xffff };
uint16_t crc_calculated = 0xffff; for(size_t i=0; i<data_length; i+=8) {
ais_fcs.process_byte(field_crc.read(i, 8));
for(size_t i=0; i<data_length + 16; i+=8) {
if( i == data_length ) {
crc_calculated ^= 0xffff;
}
const uint8_t byte = field_crc.read(i, 8);
crc_calculated = ais_fcs.calculate_byte(crc_calculated, byte);
} }
return crc_calculated == 0x0000; return ais_fcs.checksum() == field_crc.read(data_length, fcs_length);
} }
}; };

View File

@ -87,22 +87,19 @@ bool Packet::crc_ok() const {
bool Packet::crc_ok_scm() const { bool Packet::crc_ok_scm() const {
CRC<uint16_t> ert_bch { 0x6f63 }; CRC<uint16_t> ert_bch { 0x6f63 };
size_t start_bit = 5; size_t start_bit = 5;
auto crc_calculated = ert_bch.calculate_byte(0x0000, reader_.read(0, start_bit)); ert_bch.process_byte(reader_.read(0, start_bit));
for(size_t i=start_bit; i<length(); i+=8) { for(size_t i=start_bit; i<length(); i+=8) {
const uint8_t byte = reader_.read(i, 8); ert_bch.process_byte(reader_.read(i, 8));
crc_calculated = ert_bch.calculate_byte(crc_calculated, byte);
} }
return crc_calculated == 0x0000; return ert_bch.checksum() == 0x0000;
} }
bool Packet::crc_ok_idm() const { bool Packet::crc_ok_idm() const {
CRC<uint16_t> ert_crc_ccitt { 0x1021 }; CRC<uint16_t> ert_crc_ccitt { 0x1021, 0xffff, 0x1d0f };
uint16_t crc_calculated = 0xffff;
for(size_t i=0; i<length(); i+=8) { for(size_t i=0; i<length(); i+=8) {
const uint8_t byte = reader_.read(i, 8); ert_crc_ccitt.process_byte(reader_.read(i, 8));
crc_calculated = ert_crc_ccitt.calculate_byte(crc_calculated, byte);
} }
return crc_calculated == 0x1d0f; return ert_crc_ccitt.checksum() == 0x0000;
} }
} /* namespace ert */ } /* namespace ert */

View File

@ -25,61 +25,74 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
/* Inspired by
* http://www.barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code
*
* ...then munged into a shape resembling boost::crc_basic.
* http://www.boost.org/doc/libs/release/libs/crc/
*/
template<typename T> template<typename T>
class CRC { class CRC {
public: public:
constexpr CRC( constexpr CRC(
const T polynomial/*, const T truncated_polynomial,
const T initial*/ const T initial_remainder = 0,
) : polynomial { polynomial }/*, const T final_xor_value = 0
initial { initial }*/ ) : truncated_polynomial { truncated_polynomial },
initial_remainder { initial_remainder },
final_xor_value { final_xor_value },
remainder { initial_remainder }
{ {
// CRC LSB must always be 1
} }
/*
template<typename U>
T calculate(const U& bits, const size_t length) {
if( length > bits.size() ) {
// Exception.
return 0;
}
T crc = 0; T get_initial_remainder() const {
return initial_remainder;
for(size_t i=0; i<length; i++) {
crc = feed_bit(crc, bits[i]);
}
return crc;
} }
*/
T calculate_byte(const T crc_in, const uint8_t data) { void reset(T new_initial_remainder) {
/* Inspired by remainder = new_initial_remainder;
* http://www.barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code }
*/
T remainder = crc_in; void reset() {
remainder = initial_remainder;
}
void process_bit(bool bit) {
remainder ^= bit << (width() - 1);
if( remainder & top_bit() ) {
remainder = (remainder << 1) ^ truncated_polynomial;
} else {
remainder = (remainder << 1);
}
}
void process_byte(const uint8_t data) {
remainder ^= data << (width() - 8); remainder ^= data << (width() - 8);
for(size_t bit=0; bit<8; bit++) { for(size_t bit=0; bit<8; bit++) {
if( remainder & top_bit() ) { if( remainder & top_bit() ) {
remainder = (remainder << 1) ^ polynomial; remainder = (remainder << 1) ^ truncated_polynomial;
} else { } else {
remainder = (remainder << 1); remainder = (remainder << 1);
} }
} }
return remainder;
} }
/*
T calculate(const uint8_t* const data, const size_t length) { void process_bytes(const uint8_t* const data, const size_t length) {
T remainder = initial; for(size_t i=0; i<length; i++) {
for(size_t byte=0; byte<length; ++byte) { process_byte(data[i]);
remainder = calculate_byte(remainder, data[byte]);
} }
return remainder;
} }
*/
T checksum() const {
return remainder ^ final_xor_value;
}
private: private:
const T polynomial; const T truncated_polynomial;
// const T initial; const T initial_remainder;
const T final_xor_value;
T remainder;
static constexpr size_t width() { static constexpr size_t width() {
return 8 * sizeof(T); return 8 * sizeof(T);
@ -88,16 +101,6 @@ private:
static constexpr T top_bit() { static constexpr T top_bit() {
return 1U << (width() - 1); return 1U << (width() - 1);
} }
/*
T feed_bit(const T crc_in, const uint_fast8_t bit) {
T crc_out = crc_in ^ (bit & 1);
if( crc_in & top_bit() ) {
return ((crc_in << 1) | (bit & 1)) ^ polynomial;
} else {
return (crc_in << 1) | (bit & 1);
}
}
*/
}; };