diff --git a/libuavcan/include/uavcan/internal/data_type.hpp b/libuavcan/include/uavcan/internal/data_type.hpp index 27d07c1be7..3f084e7e1a 100644 --- a/libuavcan/include/uavcan/internal/data_type.hpp +++ b/libuavcan/include/uavcan/internal/data_type.hpp @@ -4,6 +4,7 @@ #pragma once +#include #include #include @@ -17,6 +18,40 @@ enum DataTypeKind NumDataTypeKinds }; +/** + * CRC-64-WE + * Description: http://reveng.sourceforge.net/crc-catalogue/17plus.htm#crc.cat-bits.64 + * Initial value: 0xFFFFFFFFFFFFFFFF + * Poly: 0x42F0E1EBA9EA3693 + * Reverse: no + * Output xor: 0xFFFFFFFFFFFFFFFF + * Check: 0x62EC59E3F1A4F00A + */ +class DataTypeSignatureCRC +{ + uint64_t crc_; + +public: + DataTypeSignatureCRC() : crc_(0xFFFFFFFFFFFFFFFF) { } + + void add(uint8_t byte) + { + static const uint64_t Poly = 0x42F0E1EBA9EA3693; + crc_ ^= uint64_t(byte) << 56; + for (int i = 0; i < 8; i++) + crc_ = (crc_ & (uint64_t(1) << 63)) ? (crc_ << 1) ^ Poly : crc_ << 1; + } + + void add(const uint8_t* bytes, unsigned int len) + { + assert(bytes); + while (len--) + add(*bytes++); + } + + uint64_t get() const { return crc_ ^ 0xFFFFFFFFFFFFFFFF; } +}; + struct DataTypeHash { diff --git a/libuavcan/test/data_type.cpp b/libuavcan/test/data_type.cpp new file mode 100644 index 0000000000..845f889974 --- /dev/null +++ b/libuavcan/test/data_type.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#include +#include + + +TEST(DataTypeSignatureCRC, Correctness) +{ + uavcan::DataTypeSignatureCRC crc; + + ASSERT_EQ(0xFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFF, crc.get()); + + crc.add('1'); + crc.add('2'); + crc.add('3'); + crc.add(reinterpret_cast("456789"), 6); + + ASSERT_EQ(0x62EC59E3F1A4F00A, crc.get()); +}