1 //
2 // srecord - manipulate eprom load files
3 // Copyright (C) 2000-2003, 2006-2010, 2012 Peter Miller
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or (at
8 // your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 //
18 //
19 // See http://www.joegeluso.com/software/articles/ccitt.htm for a great
20 // write-up on the CRC16 calculation.
21 //
22 
23 #ifndef SRECORD_CRC16_H
24 #define SRECORD_CRC16_H
25 
26 #include <stddef.h>
27 
28 namespace srecord
29 {
30 
31 /**
32   * The crc16 class is used to represent the running value of a 16-bit
33   * cyclic redundancy check of series of bytes.
34   *
35   * Note: this CRC16 works for systems that process the leaast
36   * significant bit of each byte first, and working to wards the most
37   * significant bit.
38   *
39   * If you were expecting MSB first (you may not even know it) this
40   * code will give you "wrong" answers.  Try using the bitrev filter.
41   */
42 class crc16
43 {
44 public:
45     // See http://en.wikipedia.org/wiki/Cyclic_redundancy_check
46     // for table of polynomials.
47     enum
48     {
49         /**
50           * X.25, V.41, HDLC, XMODEM, Bluetooth, SD, CRC-CCITT
51           */
52         polynomial_ccitt = 0x1021,
53 
54         /**
55           * CRC-16-IBM, Bisync, Modbus, USB, ANSI X3.28, CRC-16-ANSI
56           */
57         polynomial_ansi = 0x8005,
58 
59         /**
60           * CRC-16-DNP, DNP, IEC 870, M-Bus
61           */
62         polynomial_dnp = 0x3D65,
63 
64         /**
65           * CRC-16-DECT
66           */
67         polynomial_dect = 0x0589,
68 
69         /**
70           * CRC-16-T10-DIF, SCSI DIF
71           */
72         polynomial_t10_dif = 0x8BB7,
73     };
74 
75     /**
76       * The polynomial_by_name class method is used to take the name
77       * of a CRC-16 polynamlial, and return the value of the CRC-16
78       * polynomial corresponding to that name.
79       */
80     static int polynomial_by_name(const char *name);
81 
82     enum seed_mode_t
83     {
84         seed_mode_ccitt,
85         seed_mode_xmodem,
86         seed_mode_broken
87     };
88 
89     /**
90       * The destructor.
91       */
92     virtual ~crc16();
93 
94     enum bit_direction_t
95     {
96         bit_direction_most_to_least,
97         bit_direction_least_to_most,
98     };
99 
100     /**
101       * The default constructor.
102       *
103       * @param seed_mode
104       *     This selects which CRC16 calculation seed is to be used.
105       * @param augment
106       *     This is true if the 16-zero-bit augmentation is desired.
107       *     This is the default.  False if no augmentation is desired.
108       * @param polynomial
109       *     The checksum polynomial.
110       * @param bitdir
111       *     The direction of bits in a characters as they pass through
112       *     the algorithm.
113       */
114     crc16(seed_mode_t seed_mode = seed_mode_ccitt, bool augment = true,
115         unsigned short polynomial = polynomial_ccitt,
116         bit_direction_t bitdir = bit_direction_most_to_least);
117 
118     /**
119       * The copy constructor.
120       */
121     crc16(const crc16 &);
122 
123     /**
124       * The assignment operator.
125       */
126     crc16 &operator=(const crc16 &);
127 
128     /**
129       * The get method is used to obtain the running value of the cyclic
130       * redundancy check.
131       */
132     unsigned short get() const;
133 
134     /**
135       * The next method is used to advance the state by one byte.
136       */
137     void next(unsigned char);
138 
139     /**
140       * The nextbuf method is used to advance the state by a series of bytes.
141       */
142     void nextbuf(const void *, size_t);
143 
144     /**
145       * The print_table method may be used to print the table being used.
146       * This is principally for debugging the table generation process.
147       */
148     void print_table(void) const;
149 
150 private:
151     /**
152       * The state instance variable is used to remember the running
153       * value of the 16-bit cyclic redundancy check.
154       */
155     unsigned short state;
156 
157     /**
158       * The augment instance variable is used to remember whether or
159       * not the 16 zero bits of augmentation are to be processed before
160       * reporting the result.
161       */
162     bool augment;
163 
164     /**
165       * The polynomial instance variable is used to remember the CRC
166       * polynomial being calculated with.  Note that if the bitdir is
167       * low-to-high then the bits in the polynomial will be reversed.
168       */
169     unsigned short polynomial;
170 
171     /**
172       * The bitdir instance variable is sued to remember the direction
173       * of bits in a characters as they pass through the algorithm.
174       */
175     bit_direction_t bitdir;
176 
177     /**
178       * The table instance variable is used to remember the results of 8
179       * shift-and-process operations for each byte value.  This is used
180       * to improve efficiency.  It is filled in the the #calculate_table
181       * method, called from the constructor.
182       */
183     unsigned short table[256];
184 
185     /**
186       * The calculate_table method is called by the constructor to fill
187       * in the #table instance variable.
188       */
189     void calculate_table(void);
190 
191     /**
192       * The updcrc method is to add another byte of data to the running
193       * CRC state.  It is called by the #next and next_buf methods.
194       */
195     inline unsigned short updcrc(unsigned char c, unsigned short state) const;
196 };
197 
198 };
199 
200 #endif // SRECORD_CRC16_H
201