1 using System;
2
3 namespace Communication.IO.Tools
4 {
5 /// <summary>
6 /// Tool to calculate and add CRC codes to a string
7 ///
8 /// ***************************************************************************
9 /// Copyright (c) 2003 Thoraxcentrum, Erasmus MC, The Netherlands.
10 ///
11 /// Written by Marcel de Wijs with help from a lot of others,
12 /// especially Stefan Nelwan
13 ///
14 /// This code is for free. I ported it from several different sources to C#.
15 ///
16 /// For comments: [EMAIL="Marcel_de_Wijs@hotmail.com"]Marcel_de_Wijs@hotmail.com[/EMAIL]
17 /// ***************************************************************************
18 /// </summary>
19 public class CRCTool
20 {
21 // 'order' [1..32] is the CRC polynom order, counted without the leading '1' bit
22 // 'polynom' is the CRC polynom without leading '1' bit
23 // 'direct' [0,1] specifies the kind of algorithm: 1=direct, no augmented zero bits
24 // 'crcinit' is the initial CRC value belonging to that algorithm
25 // 'crcxor' is the final XOR value
26 // 'refin' [0,1] specifies if a data byte is reflected before processing (UART) or not
27 // 'refout' [0,1] specifies if the CRC will be reflected before XOR
28 // Data character string
29 // For CRC-CCITT : order = 16, direct=1, poly=0x1021, CRCinit = 0xFFFF, crcxor=0; refin =0, refout=0
30 // For CRC16: order = 16, direct=1, poly=0x8005, CRCinit = 0x0, crcxor=0x0; refin =1, refout=1
31 // For CRC32: order = 32, direct=1, poly=0x4c11db7, CRCinit = 0xFFFFFFFF, crcxor=0xFFFFFFFF; refin =1, refout=1
32 // Default : CRC-CCITT
33
34 private int order = 16;
35 private ulong polynom = 0x1021;
36 private int direct = 1;
37 private ulong crcinit = 0xFFFF;
38 private ulong crcxor = 0x0;
39 private int refin = 0;
40 private int refout = 0;
41
42 private ulong crcmask;
43 private ulong crchighbit;
44 private ulong crcinit_direct;
45 private ulong crcinit_nondirect;
46 private ulong [] crctab = new ulong[256];
47
48 // Enumeration used in the init function to specify which CRC algorithm to use
49 public enum CRCCode{CRC_CCITT, CRC16, CRC32};
50
51 public CRCTool()
52 {
53 //
54 // TODO: Add constructor logic here
55 //
56 }
57
58 public void Init(CRCCode CodingType)
59 {
60 switch( CodingType )
61 {
62 case CRCCode.CRC_CCITT:
63 order = 16; direct=1; polynom=0x1021; crcinit = 0xFFFF; crcxor=0; refin =0; refout=0;
64 break;
65 case CRCCode.CRC16:
66 order = 16; direct=1; polynom=0x8005; crcinit = 0x0; crcxor=0x0; refin =1; refout=1;
67 break;
68 case CRCCode.CRC32:
69 order = 32; direct=1; polynom=0x4c11db7; crcinit = 0xFFFFFFFF; crcxor=0xFFFFFFFF; refin =1; refout=1;
70 break;
71 }
72
73 // Initialize all variables for seeding and builing based upon the given coding type
74 // at first, compute constant bit masks for whole CRC and CRC high bit
75
76 crcmask = ((((ulong)1<<(order-1))-1)<<1)|1;
77 crchighbit = (ulong)1<<(order-1);
78
79 // generate lookup table
80 generate_crc_table();
81
82 ulong bit, crc;
83 int i;
84 if ( direct == 0 )
85 {
86 crcinit_nondirect = crcinit;
87 crc = crcinit;
88 for (i=0; i<order; i++)
89 {
90 bit = crc & crchighbit;
91 crc<<= 1;
92 if ( bit != 0 )
93 {
94 crc^= polynom;
95 }
96 }
97 crc&= crcmask;
98 crcinit_direct = crc;
99 }
100 else
101 {
102 crcinit_direct = crcinit;
103 crc = crcinit;
104 for (i=0; i<order; i++)
105 {
106 bit = crc & 1;
107 if (bit != 0)
108 {
109 crc^= polynom;
110 }
111 crc >>= 1;
112 if (bit != 0)
113 {
114 crc|= crchighbit;
115 }
116 }
117 crcinit_nondirect = crc;
118 }
119 }
120
121
122 /// <summary>
123 /// 4 ways to calculate the crc checksum. If you have to do a lot of encoding
124 /// you should use the table functions. Since they use precalculated values, which
125 /// saves some calculating.
126 /// </summary>.
127 public ulong crctablefast (byte[] p)
128 {
129 // fast lookup table algorithm without augmented zero bytes, e.g. used in pkzip.
130 // only usable with polynom orders of 8, 16, 24 or 32.
131 ulong crc = crcinit_direct;
132 if ( refin != 0 )
133 {
134 crc = reflect(crc, order);
135 }
136 if ( refin == 0 )
137 {
138 for ( int i = 0; i < p.Length; i++ )
139 {
140 crc = (crc << 8) ^ crctab[ ((crc >> (order-8)) & 0xff) ^ p[i]];
141 }
142 }
143 else
144 {
145 for ( int i = 0; i < p.Length; i++ )
146 {
147 crc = (crc >> 8) ^ crctab[ (crc & 0xff) ^ p[i]];
148 }
149 }
150 if ( (refout^refin) != 0 )
151 {
152 crc = reflect(crc, order);
153 }
154 crc^= crcxor;
155 crc&= crcmask;
156 return(crc);
157 }
158
159 public ulong crctable (byte[] p)
160 {
161 // normal lookup table algorithm with augmented zero bytes.
162 // only usable with polynom orders of 8, 16, 24 or 32.
163 ulong crc = crcinit_nondirect;
164 if ( refin != 0 )
165 {
166 crc = reflect(crc, order);
167 }
168 if ( refin == 0 )
169 {
170 for ( int i = 0; i < p.Length; i++ )
171 {
172 crc = ((crc << 8) | p[i]) ^ crctab[ (crc >> (order-8)) & 0xff ];
173 }
174 }
175 else
176 {
177 for ( int i = 0; i < p.Length; i++ )
178 {
179 crc = (ulong)(( (int)(crc >> 8) | (p[i] << (order-8))) ^ (int)crctab[ crc & 0xff ]);
180 }
181 }
182 if ( refin == 0 )
183 {
184 for ( int i = 0; i < order/8; i++ )
185 {
186 crc = (crc << 8) ^ crctab[ (crc >> (order-8)) & 0xff];
187 }
188 }
189 else
190 {
191 for ( int i = 0; i < order/8; i++ )
192 {
193 crc = (crc >> 8) ^ crctab[crc & 0xff];
194 }
195 }
196
197 if ( (refout^refin) != 0 )
198 {
199 crc = reflect(crc, order);
200 }
201 crc^= crcxor;
202 crc&= crcmask;
203
204 return(crc);
205 }
206
207 public ulong crcbitbybit(byte[] p)
208 {
209 // bit by bit algorithm with augmented zero bytes.
210 // does not use lookup table, suited for polynom orders between 1...32.
211 int i;
212 ulong j, c, bit;
213 ulong crc = crcinit_nondirect;
214
215 for (i=0; i<p.Length; i++)
216 {
217 c = (ulong)p[i];
218 if ( refin != 0 )
219 {
220 c = reflect(c, 8);
221 }
222
223 for (j=0x80; j != 0; j>>=1)
224 {
225 bit = crc & crchighbit;
226 crc<<= 1;
227 if ( (c & j) != 0)
228 {
229 crc|= 1;
230 }
231 if ( bit != 0 )
232 {
233 crc^= polynom;
234 }
235 }
236 }
237
238 for ( i=0; (int)i < order; i++)
239 {
240
241 bit = crc & crchighbit;
242 crc<<= 1;
243 if ( bit != 0 ) crc^= polynom;
244 }
245
246 if ( refout != 0 )
247 {
248 crc=reflect(crc, order);
249 }
250 crc^= crcxor;
251 crc&= crcmask;
252
253 return(crc);
254 }
255
256 public ulong crcbitbybitfast(byte[] p)
257 {
258 // fast bit by bit algorithm without augmented zero bytes.
259 // does not use lookup table, suited for polynom orders between 1...32.
260 int i;
261 ulong j, c, bit;
262 ulong crc = crcinit_direct;
263
264 for (i = 0; i < p.Length; i++)
265 {
266 c = (ulong)p[i];
267 if ( refin != 0)
268 {
269 c = reflect(c, 8);
270 }
271
272 for ( j = 0x80; j > 0; j >>= 1 )
273 {
274 bit = crc & crchighbit;
275 crc <<= 1;
276 if ( (c & j) > 0 ) bit^= crchighbit;
277 if ( bit > 0 ) crc^= polynom;
278 }
279 }
280
281 if ( refout > 0)
282 {
283 crc=reflect( crc, order );
284 }
285 crc^= crcxor;
286 crc&= crcmask;
287
288 return(crc);
289 }
290
291
292 /// <summary>
293 /// CalcCRCITT is an algorithm found on the web for calculating the CRCITT checksum
294 /// It is included to demonstrate that although it looks different it is the same
295 /// routine as the crcbitbybit* functions. But it is optimized and preconfigured for CRCITT.
296 /// </summary>
297 public ushort CalcCRCITT(byte[] p)
298 {
299 uint uiCRCITTSum = 0xFFFF;
300 uint uiByteValue;
301
302 for (int iBufferIndex = 0; iBufferIndex < p.Length; iBufferIndex++)
303 {
304 uiByteValue = ( (uint) p[iBufferIndex] << 8);
305 for ( int iBitIndex = 0; iBitIndex < 8; iBitIndex++ )
306 {
307 if ( ( (uiCRCITTSum^uiByteValue) & 0x8000) != 0 )
308 {
309 uiCRCITTSum = (uiCRCITTSum <<1 ) ^ 0x1021;
310 }
311 else
312 {
313 uiCRCITTSum <<= 1;
314 }
315 uiByteValue <<=1;
316 }
317 }
318 return (ushort)uiCRCITTSum;
319 }
320
321
322 #region subroutines
323 private ulong reflect (ulong crc, int bitnum)
324 {
325
326 // reflects the lower 'bitnum' bits of 'crc'
327
328 ulong i, j=1, crcout = 0;
329
330 for ( i = (ulong)1 <<(bitnum-1); i != 0; i>>=1)
331 {
332 if ( ( crc & i ) != 0 )
333 {
334 crcout |= j;
335 }
336 j<<= 1;
337 }
338 return (crcout);
339 }
340
341 private void generate_crc_table()
342 {
343
344 // make CRC lookup table used by table algorithms
345
346 int i, j;
347 ulong bit, crc;
348
349 for (i=0; i<256; i++)
350 {
351 crc=(ulong)i;
352 if ( refin !=0 )
353 {
354 crc=reflect(crc, 8);
355 }
356 crc<<= order-8;
357
358 for (j=0; j<8; j++)
359 {
360 bit = crc & crchighbit;
361 crc<<= 1;
362 if ( bit !=0 ) crc^= polynom;
363 }
364
365 if (refin != 0)
366 {
367 crc = reflect(crc, order);
368 }
369 crc&= crcmask;
370 crctab[i]= crc;
371 }
372 }
373 #endregion
374 }
375 }
Edited by dargueta, 12 December 2011 - 02:13 AM.
Please use [code][/code] tags!