[go: up one dir, main page]

File: crc32.cc

package info (click to toggle)
srecord 1.55-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 4,728 kB
  • ctags: 2,401
  • sloc: cpp: 23,402; sh: 6,520; makefile: 3,116; awk: 208; vhdl: 15
file content (198 lines) | stat: -rw-r--r-- 6,016 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
//
// srecord - manipulate eprom load files
// Copyright (C) 2000-2002, 2006-2010 Peter Miller
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// (I got this copy from http://www.gator.net/~garyg/C/CONTRIB/SNIP/
// but as always on the Internet, it is now gone.  So use the
//      Wayback Machine, http://www.archive.org/, or google for "crc_32"
//      and you should find it fairly quickly.  The same code also
//      appears in the ZModem sources, as well, but they seem to abuse
//      it slightly, and the way they initialize and terminate the CRC
//      doesn't give the same answers as the way everyone else uses it.)
//
// 32 BIT ANSI X3.66 CRC checksum
//
// This class may be used to compute the 32-bit CRC used as the frame
// check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 and
// FED-STD-1003, the U.S. versions of CCITT's X.25 link-level protocol).
// The 32-bit FCS was added via the Federal Register, 1 June 1982,
// p.23798.  I presume but don't know for certain that this polynomial
// is or will be included in CCITT V.41, which defines the 16-bit CRC
// (often called CRC-CCITT) polynomial.  FIPS PUB 78 says that the
// 32-bit FCS reduces otherwise undetected errors by a factor of 10^-5
// over 16-bit FCS.
//


#include <srecord/crc32.h>


static unsigned long ccitt_seed = 0xFFFFFFFF;
static unsigned long xmodem_seed = 0;


//
// Portions of the code in this file are derived from code which is
// "Copyright (C) 1986 Gary S. Brown.  You may use this program, or
// code or tables extracted from it, as desired without restriction."
//
// First, the polynomial itself and its table of feedback terms.  The
// polynomial is
// X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
// Note that we take it "backwards" and put the highest-order term in
// the lowest-order bit.  The X^32 term is "implied"; the LSB is the
// X^31 term, etc.  The X^0 term (usually shown as "+1") results in
// the MSB being 1.
//
#define POLYNOMIAL 0xedb88320

//
// Note that the usual hardware shift register implementation, which
// is what we're using (we're merely optimizing it by doing eight-bit
// chunks at a time) shifts bits into the lowest-order term.  In our
// implementation, that means shifting towards the right.  Why do we
// do it this way?  Because the calculated CRC must be transmitted in
// order from highest-order term to lowest-order term.  UARTs transmit
// characters in order from LSB to MSB.  By storing the CRC this way,
// we hand it to the UART in the order low-byte to high-byte; the UART
// sends each low-bit to hight-bit; and the result is transmission bit
// by bit from highest- to lowest-order term without requiring any bit
// shuffling on our part.  Reception works similarly.
//
// The feedback terms table consists of 256, 32-bit entries.
//
// The values must be right-shifted by eight bits by the "UPDC32"
// logic; the shift must be unsigned (bring in zeroes).
//

static unsigned long table[256];


static void
calculate_table()
{
    for (unsigned b = 0; b < 256; ++b)
    {
        unsigned long v = b;
        int i = 8;
        for (; --i >= 0; )
            v = (v & 1) ? ((v >> 1) ^ POLYNOMIAL) : (v >> 1);
        table[b] = v;
    }
}


static unsigned long
initial_state_from_seed_mode(srecord::crc32::seed_mode_t seed_mode)
{
    switch (seed_mode)
    {
    case srecord::crc32::seed_mode_ccitt:
        return ccitt_seed;

    case srecord::crc32::seed_mode_xmodem:
        return xmodem_seed;
    }
    return ccitt_seed;
}


srecord::crc32::crc32(seed_mode_t seed_mode) :
    state(initial_state_from_seed_mode(seed_mode))
{
    if (!table[1])
        calculate_table();
}


srecord::crc32::crc32(const crc32 &arg) :
    state(arg.state)
{
}


srecord::crc32 &
srecord::crc32::operator=(const crc32 &arg)
{
    if (this != &arg)
    {
        state = arg.state;
    }
    return *this;
}


srecord::crc32::~crc32()
{
}


static inline unsigned long
UPDC32(unsigned char octet, unsigned long crc)
{
    // The original code had this as a #define
    return table[(crc ^ octet) & 0xFF] ^ (crc >> 8);
}


void
srecord::crc32::next(unsigned char x)
{
    state = UPDC32(x, state);
}


void
srecord::crc32::nextbuf(const void *data, size_t nbytes)
{
    const unsigned char *dp = (const unsigned char *)data;
    while (nbytes > 0)
    {
        state = UPDC32(*dp, state);
        ++dp;
        --nbytes;
    }
}


unsigned long
srecord::crc32::get()
    const
{
#if 1
    return ~state;
#else
    //
    // The crc_32.c program floating around on the Internet prints
    // two numbers.  The first is calculated as follows (the second
    // is the CRC as returned 5 lines back).  It appears to be an
    // attempt to embed the crc into the data, and tell you what
    // the CRC should be if you calculate the CRC over the data and
    // the CRC.  However, it makes the assumption that you store
    // the CRC little-endian, and it doesn't do the final bit-not.
    //
    // To simulate this (or something very much like it) try
    //      srecord::cat <file> -lecrc32 <addr> -lecrc32 <addr+4>
    //
    unsigned long temp = state;
    temp = UPDC32( ~state    & 0xFF, temp);
    temp = UPDC32((~state >>  8) & 0xFF, temp);
    temp = UPDC32((~state >> 16) & 0xFF, temp);
    temp = UPDC32((~state >> 24) & 0xFF, temp);
    return temp; // I wonder why this isn't bit-not-ed?
#endif
}