#if defined(ARDUINO)
#include <Arduino.h>
#endif
#if !defined(KINETISK)
#if !defined(ARDUINO)
#define PROGMEM
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
template <typename T>
static constexpr unsigned short pgm_read_word(T addr) noexcept {
return *(const unsigned short *)(addr);
};
template <typename T>
static constexpr unsigned long pgm_read_dword(T addr) noexcept {
return *(const unsigned long *)(addr);
};
#endif
#include "FastCRC.h"
#include "FastCRC_tables.h"
static inline
uint32_t REV16( uint32_t value)
{
return (value >> 8) | ((value & 0xff) << 8);
}
static inline
uint32_t REV32( uint32_t value)
{
value = (value >> 16) | ((value & 0xffff) << 16);
return ((value >> 8) & 0xff00ff) | ((value & 0xff00ff) << 8);
}
FastCRC7::FastCRC7(){}
uint8_t FastCRC7::crc7_upd(const uint8_t *data, size_t datalen)
{
uint8_t crc = seed;
if (datalen) do {
crc = pgm_read_byte(&crc_table_crc7[crc ^ *data]);
data++;
} while (--datalen);
seed = crc;
return crc >> 1;
}
uint8_t FastCRC7::crc7(const uint8_t *data, const size_t datalen)
{
seed = 0x00;
return crc7_upd(data, datalen);
}
FastCRC8::FastCRC8(){}
uint8_t FastCRC8::smbus_upd(const uint8_t *data, size_t datalen)
{
uint8_t crc = seed;
if (datalen) do {
crc = pgm_read_byte(&crc_table_smbus[crc ^ *data]);
data++;
} while (--datalen);
seed = crc;
return crc;
}
uint8_t FastCRC8::smbus(const uint8_t *data, const size_t datalen)
{
seed = 0x00;
return smbus_upd(data, datalen);
}
uint8_t FastCRC8::maxim_upd(const uint8_t *data, size_t datalen)
{
uint8_t crc = seed;
if (datalen) do {
crc = pgm_read_byte(&crc_table_maxim[crc ^ *data]);
data++;
} while (--datalen);
seed = crc;
return crc;
}
uint8_t FastCRC8::maxim(const uint8_t *data, const size_t datalen)
{
seed = 0x00;
return maxim_upd(data, datalen);
}
FastCRC16::FastCRC16(){}
#define crc_n4(crc, data, table) crc ^= data; \
crc = pgm_read_word(&table[(crc & 0xff) + 0x300]) ^ \
pgm_read_word(&table[((crc >> 8) & 0xff) + 0x200]) ^ \
pgm_read_word(&table[((data >> 16) & 0xff) + 0x100]) ^ \
pgm_read_word(&table[data >> 24]);
uint16_t FastCRC16::ccitt_upd(const uint8_t *data, size_t len)
{
uint16_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_ccitt[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
crc_n4(crc, ((uint32_t *)data)[0], crc_table_ccitt);
crc_n4(crc, ((uint32_t *)data)[1], crc_table_ccitt);
crc_n4(crc, ((uint32_t *)data)[2], crc_table_ccitt);
crc_n4(crc, ((uint32_t *)data)[3], crc_table_ccitt);
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_ccitt[(crc & 0xff) ^ *data++]);
}
seed = crc;
crc = REV16(crc);
return crc;
}
uint16_t FastCRC16::ccitt(const uint8_t *data,const size_t datalen)
{
seed = 0xffff;
return ccitt_upd(data, datalen);
}
uint16_t FastCRC16::mcrf4xx_upd(const uint8_t *data, size_t len)
{
uint16_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_mcrf4xx[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
crc_n4(crc, ((uint32_t *)data)[0], crc_table_mcrf4xx);
crc_n4(crc, ((uint32_t *)data)[1], crc_table_mcrf4xx);
crc_n4(crc, ((uint32_t *)data)[2], crc_table_mcrf4xx);
crc_n4(crc, ((uint32_t *)data)[3], crc_table_mcrf4xx);
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_mcrf4xx[(crc & 0xff) ^ *data++]);
}
seed = crc;
return crc;
}
uint16_t FastCRC16::mcrf4xx(const uint8_t *data,const size_t datalen)
{
seed = 0;
return mcrf4xx_upd(data, datalen);
}
uint16_t FastCRC16::modbus_upd(const uint8_t *data, size_t len)
{
uint16_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_modbus[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
crc_n4(crc, ((uint32_t *)data)[0], crc_table_modbus);
crc_n4(crc, ((uint32_t *)data)[1], crc_table_modbus);
crc_n4(crc, ((uint32_t *)data)[2], crc_table_modbus);
crc_n4(crc, ((uint32_t *)data)[3], crc_table_modbus);
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_modbus[(crc & 0xff) ^ *data++]);
}
seed = crc;
return crc;
}
uint16_t FastCRC16::modbus(const uint8_t *data, const size_t datalen)
{
seed = 0xffff;
return modbus_upd(data, datalen);
}
uint16_t FastCRC16::kermit_upd(const uint8_t *data, size_t len)
{
uint16_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_kermit[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
crc_n4(crc, ((uint32_t *)data)[0], crc_table_kermit);
crc_n4(crc, ((uint32_t *)data)[1], crc_table_kermit);
crc_n4(crc, ((uint32_t *)data)[2], crc_table_kermit);
crc_n4(crc, ((uint32_t *)data)[3], crc_table_kermit);
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_kermit[(crc & 0xff) ^ *data++]);
}
seed = crc;
return crc;
}
uint16_t FastCRC16::kermit(const uint8_t *data, const size_t datalen)
{
seed = 0x0000;
return kermit_upd(data, datalen);
}
uint16_t FastCRC16::xmodem_upd(const uint8_t *data, size_t len)
{
uint16_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_xmodem[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
crc_n4(crc, ((uint32_t *)data)[0], crc_table_xmodem);
crc_n4(crc, ((uint32_t *)data)[1], crc_table_xmodem);
crc_n4(crc, ((uint32_t *)data)[2], crc_table_xmodem);
crc_n4(crc, ((uint32_t *)data)[3], crc_table_xmodem);
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_xmodem[(crc & 0xff) ^ *data++]);
}
seed = crc;
crc = REV16(crc);
return crc;
}
uint16_t FastCRC16::xmodem(const uint8_t *data, const size_t datalen)
{
seed = 0x0000;
return xmodem_upd(data, datalen);
}
uint16_t FastCRC16::x25_upd(const uint8_t *data, size_t len)
{
uint16_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_x25[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
crc_n4(crc, ((uint32_t *)data)[0], crc_table_x25);
crc_n4(crc, ((uint32_t *)data)[1], crc_table_x25);
crc_n4(crc, ((uint32_t *)data)[2], crc_table_x25);
crc_n4(crc, ((uint32_t *)data)[3], crc_table_x25);
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_x25[(crc & 0xff) ^ *data++]);
}
seed = crc;
crc = ~crc;
return crc;
}
uint16_t FastCRC16::x25(const uint8_t *data, const size_t datalen)
{
seed = 0xffff;
return x25_upd(data, datalen);
}
FastCRC32::FastCRC32(){}
#define crc_n4d(crc, data, table) crc ^= data; \
crc = pgm_read_dword(&table[(crc & 0xff) + 0x300]) ^ \
pgm_read_dword(&table[((crc >> 8) & 0xff) + 0x200]) ^ \
pgm_read_dword(&table[((crc >> 16) & 0xff) + 0x100]) ^ \
pgm_read_dword(&table[(crc >> 24) & 0xff]);
#define crcsm_n4d(crc, data, table) crc ^= data; \
crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \
crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \
crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \
crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]);
#if CRC_BIGTABLES
#define CRC_TABLE_CRC32 crc_table_crc32_big
#else
#define CRC_TABLE_CRC32 crc_table_crc32
#endif
uint32_t FastCRC32::crc32_upd(const uint8_t *data, size_t len)
{
uint32_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CRC32[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
#if CRC_BIGTABLES
crc_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CRC32);
crc_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CRC32);
crc_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CRC32);
crc_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CRC32);
#else
crcsm_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CRC32);
crcsm_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CRC32);
crcsm_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CRC32);
crcsm_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CRC32);
#endif
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CRC32[(crc & 0xff) ^ *data++]);
}
seed = crc;
crc = ~crc;
return crc;
}
uint32_t FastCRC32::crc32(const uint8_t *data, const size_t datalen)
{
seed = 0xffffffff;
return crc32_upd(data, datalen);
}
#if CRC_BIGTABLES
#define CRC_TABLE_CKSUM crc_table_cksum_big
#else
#define CRC_TABLE_CKSUM crc_table_cksum
#endif
uint32_t FastCRC32::cksum_upd(const uint8_t *data, size_t len)
{
uint32_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CKSUM[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
#if CRC_BIGTABLES
crc_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CKSUM);
crc_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CKSUM);
crc_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CKSUM);
crc_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CKSUM);
#else
crcsm_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CKSUM);
crcsm_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CKSUM);
crcsm_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CKSUM);
crcsm_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CKSUM);
#endif
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CKSUM[(crc & 0xff) ^ *data++]);
}
seed = crc;
crc = ~REV32(crc);
return crc;
}
uint32_t FastCRC32::cksum(const uint8_t *data, const size_t datalen)
{
seed = 0x00;
return cksum_upd(data, datalen);
}
#endif