mirror of
https://github.com/TomHarte/CLK.git
synced 2026-04-20 10:17:05 +00:00
Shunt CRC XOR table generation to compile time.
This commit is contained in:
+28
-19
@@ -8,6 +8,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Carry.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
@@ -26,30 +29,41 @@ constexpr uint8_t reverse_byte(uint8_t byte) {
|
||||
}
|
||||
|
||||
/*! Provides a class capable of generating a CRC from source data. */
|
||||
template <typename IntType, IntType reset_value, IntType output_xor, bool reflect_input, bool reflect_output>
|
||||
template <
|
||||
typename IntType,
|
||||
IntType polynomial,
|
||||
IntType reset_value,
|
||||
IntType output_xor,
|
||||
bool reflect_input,
|
||||
bool reflect_output
|
||||
>
|
||||
class Generator {
|
||||
public:
|
||||
/*!
|
||||
Instantiates a CRC16 that will compute the CRC16 specified by the supplied
|
||||
@c polynomial and @c reset_value.
|
||||
*/
|
||||
constexpr Generator(IntType polynomial) noexcept: value_(reset_value) {
|
||||
const IntType top_bit = IntType(~(IntType(~0) >> 1));
|
||||
for(int c = 0; c < 256; c++) {
|
||||
IntType shift_value = IntType(c << multibyte_shift);
|
||||
for(int b = 0; b < 8; b++) {
|
||||
IntType exclusive_or = (shift_value&top_bit) ? polynomial : 0;
|
||||
shift_value = IntType(shift_value << 1) ^ exclusive_or;
|
||||
}
|
||||
xor_table[c] = shift_value;
|
||||
}
|
||||
}
|
||||
constexpr Generator() noexcept: value_(reset_value) {}
|
||||
|
||||
/// Resets the CRC to the reset value.
|
||||
void reset() { value_ = reset_value; }
|
||||
|
||||
/// Updates the CRC to include @c byte.
|
||||
void add(uint8_t byte) {
|
||||
static constexpr std::array<IntType, 256> xor_table = [] {
|
||||
std::array<IntType, 256> table{};
|
||||
constexpr IntType top_bit = Numeric::top_bit<IntType>();
|
||||
for(size_t c = 0; c < 256; c++) {
|
||||
IntType shift_value = IntType(c << multibyte_shift);
|
||||
for(int b = 0; b < 8; b++) {
|
||||
const IntType exclusive_or = (shift_value & top_bit) ? polynomial : 0;
|
||||
shift_value = IntType(shift_value << 1) ^ exclusive_or;
|
||||
}
|
||||
table[c] = shift_value;
|
||||
}
|
||||
return table;
|
||||
} ();
|
||||
|
||||
if constexpr (reflect_input) byte = reverse_byte(byte);
|
||||
value_ = IntType((value_ << 8) ^ xor_table[(value_ >> multibyte_shift) ^ byte]);
|
||||
}
|
||||
@@ -100,7 +114,6 @@ public:
|
||||
|
||||
private:
|
||||
static constexpr int multibyte_shift = (sizeof(IntType) * 8) - 8;
|
||||
IntType xor_table[256];
|
||||
IntType value_;
|
||||
};
|
||||
|
||||
@@ -108,15 +121,11 @@ private:
|
||||
Provides a generator of 16-bit CCITT CRCs, which amongst other uses are
|
||||
those used by the FM and MFM disk encodings.
|
||||
*/
|
||||
struct CCITT: public Generator<uint16_t, 0xffff, 0x0000, false, false> {
|
||||
CCITT(): Generator(0x1021) {}
|
||||
};
|
||||
using CCITT = Generator<uint16_t, 0x1021, 0xffff, 0x0000, false, false>;
|
||||
|
||||
/*!
|
||||
Provides a generator of "standard 32-bit" CRCs.
|
||||
*/
|
||||
struct CRC32: public Generator<uint32_t, 0xffffffff, 0xffffffff, true, true> {
|
||||
CRC32(): Generator(0x04c11db7) {}
|
||||
};
|
||||
using CRC32 = Generator<uint32_t, 0x04c11db7, 0xffffffff, 0xffffffff, true, true>;
|
||||
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace {
|
||||
constexpr int PLLClockRate = 1920000;
|
||||
}
|
||||
|
||||
Parser::Parser(): crc_(0x1021) {
|
||||
Parser::Parser() {
|
||||
shifter_.set_delegate(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ private:
|
||||
void process_pulse(const Storage::Tape::Pulse &) override;
|
||||
|
||||
bool did_update_shifter(int new_value, int length);
|
||||
CRC::Generator<uint16_t, 0x0000, 0x0000, false, false> crc_;
|
||||
CRC::Generator<uint16_t, 0x1021, 0x0000, 0x0000, false, false> crc_;
|
||||
Shifter shifter_;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user