// // srecord - manipulate eprom load files // Copyright (C) 2000-2002, 2006, 2007 Peter Miller // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or (at // your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // // // Implemented from scratch from // "A painless guide to CRC error detection algorithms" // http://www.repairfaq.org/filipg/LINK/F_crc_v3.html // // See also http://www.joegeluso.com/software/articles/ccitt.htm // // See test/01/t0150a.sh for test vectors. // #include // HACK #include // HACK #include // // The CRC polynomial. This is used by CCITT and XMODEM, but not X.25 // #define POLYNOMIAL 0x1021 static unsigned short table[256]; // // Use a seed of 0xFFFF when augmenting manually (i.e. augmenting by 16 // zero bits by processing two zero bytes at the end of the data), but a // seed of 0x1D0F when the augmenting is done by shifting where the XOR // appears in the updcrc function. // // The 0x1D0F value is calculated by using the manual augmentation // updcrc function: // ubdcrc(0, updcrc(0, 0xFFFF)) // #if 1 static unsigned short const ccitt_seed = 0xFFFF; #else static unsigned short const ccitt_seed = 0x1D0F; #endif static unsigned short const xmodem_seed = 0; static void calculate_table() { if (table[1]) return; for (unsigned b = 0; b < 256; ++b) { unsigned short v = b << 8; for (unsigned j = 0; j < 8; ++j) v = (v & 0x8000) ? ((v << 1) ^ POLYNOMIAL) : (v << 1); table[b] = v; } } crc16::crc16(bool ccitt, bool aug) : state(ccitt ? ccitt_seed : xmodem_seed), augment(aug) { calculate_table(); } crc16::crc16(const crc16 &arg) : state(arg.state), augment(arg.augment) { } crc16 & crc16::operator=(const crc16 &arg) { if (this != &arg) { state = arg.state; augment = arg.augment; } return *this; } crc16::~crc16() { } #if 0 // // This is the simplest possible implementation. It can be used to // validate the two following table-driven implementations. // static unsigned short updcrc(unsigned char c, unsigned short state) { for (unsigned i = 0; i < 8; ++i) { bool xor_flag = !!(state & 0x8000); state <<= 1; if (c & 0x80) state |= 1; if (xor_flag) state ^= POLYNOMIAL; c <<= 1; } return state; } #endif // // This version of updcrc doesn't augment automagically, you must // do it explicitly in the get() method. It is a more intuitave // implementation and the "augmentation included" implementation below. // // See "A painless guide to CRC error detection algorithms", // chapter 10, http://www.repairfaq.org/filipg/LINK/F_crc_v33.html#CRCV_002 // for an explanation. // static inline unsigned short updcrc(unsigned char c, unsigned short state) { return ((state << 8) | c) ^ table[state >> 8]; } #if 0 // // This version of updcrc means that the 16-zero-bit augmentation has // already happened. There is no need to explicitly do it in the get() // method. This is deep voodoo even for folks who actually understand // XOR arithmetic. // // See "A painless guide to CRC error detection algorithms", // chapter 11, http://www.repairfaq.org/filipg/LINK/F_crc_v33.html#CRCV_003 // for an explanation. // static inline unsigned short updcrc(unsigned char c, unsigned short state) { return (state << 8) ^ table[(state >> 8) ^ c]; } #endif void crc16::next(unsigned char ch) { state = updcrc(ch, state); } void crc16::nextbuf(const void *data, size_t nbytes) { unsigned char *dp = (unsigned char *)data; while (nbytes > 0) { state = updcrc(*dp++, state); --nbytes; } } unsigned short crc16::get() const { if (augment) { return updcrc(0, updcrc(0, state)); } return state; }