F´ Flight Software - C/C++ Documentation devel
A framework for building embedded system applications to NASA flight quality standards.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
lib_crc.c
Go to the documentation of this file.
1#include "lib_crc.h"
2
3
4
5 /*******************************************************************\
6 * *
7 * Library : lib_crc *
8 * File : lib_crc.c *
9 * Author : Lammert Bies 1999-2008 *
10 * E-mail : info@lammertbies.nl *
11 * Language : ANSI C *
12 * *
13 * *
14 * Description *
15 * =========== *
16 * *
17 * The file lib_crc.c contains the private and public func- *
18 * tions used for the calculation of CRC-16, CRC-CCITT and *
19 * CRC-32 cyclic redundancy values. *
20 * *
21 * *
22 * Dependencies *
23 * ============ *
24 * *
25 * lib_crc.h CRC definitions and prototypes *
26 * *
27 * *
28 * Modification history *
29 * ==================== *
30 * *
31 * Date Version Comment *
32 * *
33 * 2008-04-20 1.16 Added CRC-CCITT calculation for Kermit *
34 * *
35 * 2007-04-01 1.15 Added CRC16 calculation for Modbus *
36 * *
37 * 2007-03-28 1.14 Added CRC16 routine for Sick devices *
38 * *
39 * 2005-12-17 1.13 Added CRC-CCITT with initial 0x1D0F *
40 * *
41 * 2005-05-14 1.12 Added CRC-CCITT with start value 0 *
42 * *
43 * 2005-02-05 1.11 Fixed bug in CRC-DNP routine *
44 * *
45 * 2005-02-04 1.10 Added CRC-DNP routines *
46 * *
47 * 1999-02-21 1.01 Added FALSE and TRUE mnemonics *
48 * *
49 * 1999-01-22 1.00 Initial source *
50 * *
51 \*******************************************************************/
52
53
54
55 /*******************************************************************\
56 * *
57 * #define P_xxxx *
58 * *
59 * The CRC's are computed using polynomials. The coefficients *
60 * for the algorithms are defined by the following constants. *
61 * *
62 \*******************************************************************/
63
64#define P_16 0xA001
65#define P_32 0xEDB88320L
66#define P_CCITT 0x1021
67#define P_DNP 0xA6BC
68#define P_KERMIT 0x8408
69#define P_SICK 0x8005
70
71
72
73 /*******************************************************************\
74 * *
75 * static int crc_tab...init *
76 * static unsigned ... crc_tab...[] *
77 * *
78 * The algorithms use tables with precalculated values. This *
79 * speeds up the calculation dramatically. The first time the *
80 * CRC function is called, the table for that specific calcu- *
81 * lation is set up. The ...init variables are used to deter- *
82 * mine if the initialization has taken place. The calculated *
83 * values are stored in the crc_tab... arrays. *
84 * *
85 * The variables are declared static. This makes them invisi- *
86 * ble for other modules of the program. *
87 * *
88 \*******************************************************************/
89
95
96static unsigned short crc_tab16[256];
97static unsigned long crc_tab32[256];
98static unsigned short crc_tabccitt[256];
99static unsigned short crc_tabdnp[256];
100static unsigned short crc_tabkermit[256];
101
102
103
104 /*******************************************************************\
105 * *
106 * static void init_crc...tab(); *
107 * *
108 * Three local functions are used to initialize the tables *
109 * with values for the algorithm. *
110 * *
111 \*******************************************************************/
112
113static void init_crc16_tab( void );
114static void init_crc32_tab( void );
115static void init_crcccitt_tab( void );
116static void init_crcdnp_tab( void );
117static void init_crckermit_tab( void );
118
119
120
121 /*******************************************************************\
122 * *
123 * unsigned short update_crc_ccitt( unsigned long crc, char c ); *
124 * *
125 * The function update_crc_ccitt calculates a new CRC-CCITT *
126 * value based on the previous value of the CRC and the next *
127 * byte of the data to be checked. *
128 * *
129 \*******************************************************************/
130
131unsigned short update_crc_ccitt( unsigned short crc, char c ) {
132
133 unsigned short tmp, short_c;
134
135 short_c = 0x00ff & (unsigned short) c;
136
138
139 tmp = (crc >> 8) ^ short_c;
140 crc = (unsigned short)((crc << 8) ^ crc_tabccitt[tmp]);
141
142 return crc;
143
144} /* update_crc_ccitt */
145
146
147
148 /*******************************************************************\
149 * *
150 * unsigned short update_crc_sick( *
151 * unsigned long crc, char c, char prev_byte ); *
152 * *
153 * The function update_crc_sick calculates a new CRC-SICK *
154 * value based on the previous value of the CRC and the next *
155 * byte of the data to be checked. *
156 * *
157 \*******************************************************************/
158
159unsigned short update_crc_sick( unsigned short crc, char c, char prev_byte ) {
160
161 unsigned short short_c, short_p;
162
163 short_c = 0x00ff & (unsigned short) c;
164 short_p = (unsigned short)(( 0x00ff & (unsigned short) prev_byte ) << 8);
165
166 if ( crc & 0x8000 ) crc = (unsigned short)(( crc << 1 ) ^ P_SICK);
167 else crc = (unsigned short)(crc << 1);
168
169 crc &= 0xffff;
170 crc ^= ( short_c | short_p );
171
172 return crc;
173
174} /* update_crc_sick */
175
176
177
178 /*******************************************************************\
179 * *
180 * unsigned short update_crc_16( unsigned short crc, char c ); *
181 * *
182 * The function update_crc_16 calculates a new CRC-16 value *
183 * based on the previous value of the CRC and the next byte *
184 * of the data to be checked. *
185 * *
186 \*******************************************************************/
187
188unsigned short update_crc_16( unsigned short crc, char c ) {
189
190 unsigned short tmp, short_c;
191
192 short_c = 0x00ff & (unsigned short) c;
193
195
196 tmp = crc ^ short_c;
197 // Note: when masking by 0xff, range is limited to unsigned char
198 // which fits within unsigned int.
199 crc = (crc >> 8) ^ crc_tab16[ (unsigned int)(tmp & 0xff) ];
200
201 return crc;
202
203} /* update_crc_16 */
204
205
206
207 /*******************************************************************\
208 * *
209 * unsigned short update_crc_kermit( unsigned short crc, char c ); *
210 * *
211 * The function update_crc_kermit calculates a new CRC value *
212 * based on the previous value of the CRC and the next byte *
213 * of the data to be checked. *
214 * *
215 \*******************************************************************/
216
217unsigned short update_crc_kermit( unsigned short crc, char c ) {
218
219 unsigned short tmp, short_c;
220
221 short_c = 0x00ff & (unsigned short) c;
222
224
225 tmp = crc ^ short_c;
226 crc = (crc >> 8) ^ crc_tabkermit[ tmp & 0xff ];
227
228 return crc;
229
230} /* update_crc_kermit */
231
232
233
234 /*******************************************************************\
235 * *
236 * unsigned short update_crc_dnp( unsigned short crc, char c ); *
237 * *
238 * The function update_crc_dnp calculates a new CRC-DNP value *
239 * based on the previous value of the CRC and the next byte *
240 * of the data to be checked. *
241 * *
242 \*******************************************************************/
243
244unsigned short update_crc_dnp( unsigned short crc, char c ) {
245
246 unsigned short tmp, short_c;
247
248 short_c = 0x00ff & (unsigned short) c;
249
251
252 tmp = crc ^ short_c;
253 crc = (crc >> 8) ^ crc_tabdnp[ tmp & 0xff ];
254
255 return crc;
256
257} /* update_crc_dnp */
258
259
260
261 /*******************************************************************\
262 * *
263 * unsigned long update_crc_32( unsigned long crc, char c ); *
264 * *
265 * The function update_crc_32 calculates a new CRC-32 value *
266 * based on the previous value of the CRC and the next byte *
267 * of the data to be checked. *
268 * *
269 \*******************************************************************/
270
271unsigned long update_crc_32( unsigned long crc, char c ) {
272
273 unsigned long tmp, long_c;
274
275 long_c = 0x000000ffL & (unsigned long) c;
276
278
279 tmp = crc ^ long_c;
280 crc = (crc >> 8) ^ crc_tab32[ tmp & 0xff ];
281
282 return crc;
283
284} /* update_crc_32 */
285
286
287
288 /*******************************************************************\
289 * *
290 * static void init_crc16_tab( void ); *
291 * *
292 * The function init_crc16_tab() is used to fill the array *
293 * for calculation of the CRC-16 with values. *
294 * *
295 \*******************************************************************/
296
297static void init_crc16_tab( void ) {
298
299 int i, j;
300 unsigned short crc, c;
301
302 for (i=0; i<256; i++) {
303
304 crc = 0;
305 c = (unsigned short) i;
306
307 for (j=0; j<8; j++) {
308
309 if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ P_16;
310 else crc = crc >> 1;
311
312 c = c >> 1;
313 }
314
315 crc_tab16[i] = crc;
316 }
317
319
320} /* init_crc16_tab */
321
322
323
324 /*******************************************************************\
325 * *
326 * static void init_crckermit_tab( void ); *
327 * *
328 * The function init_crckermit_tab() is used to fill the array *
329 * for calculation of the CRC Kermit with values. *
330 * *
331 \*******************************************************************/
332
333static void init_crckermit_tab( void ) {
334
335 int i, j;
336 unsigned short crc, c;
337
338 for (i=0; i<256; i++) {
339
340 crc = 0;
341 c = (unsigned short) i;
342
343 for (j=0; j<8; j++) {
344
345 if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ P_KERMIT;
346 else crc = crc >> 1;
347
348 c = c >> 1;
349 }
350
351 crc_tabkermit[i] = crc;
352 }
353
355
356} /* init_crckermit_tab */
357
358
359
360 /*******************************************************************\
361 * *
362 * static void init_crcdnp_tab( void ); *
363 * *
364 * The function init_crcdnp_tab() is used to fill the array *
365 * for calculation of the CRC-DNP with values. *
366 * *
367 \*******************************************************************/
368
369static void init_crcdnp_tab( void ) {
370
371 int i, j;
372 unsigned short crc, c;
373
374 for (i=0; i<256; i++) {
375
376 crc = 0;
377 c = (unsigned short) i;
378
379 for (j=0; j<8; j++) {
380
381 if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ P_DNP;
382 else crc = crc >> 1;
383
384 c = c >> 1;
385 }
386
387 crc_tabdnp[i] = crc;
388 }
389
391
392} /* init_crcdnp_tab */
393
394
395
396 /*******************************************************************\
397 * *
398 * static void init_crc32_tab( void ); *
399 * *
400 * The function init_crc32_tab() is used to fill the array *
401 * for calculation of the CRC-32 with values. *
402 * *
403 \*******************************************************************/
404
405static void init_crc32_tab( void ) {
406
407 int i, j;
408 unsigned long crc;
409
410 for (i=0; i<256; i++) {
411
412 crc = (unsigned long) i;
413
414 for (j=0; j<8; j++) {
415
416 if ( crc & 0x00000001L ) crc = ( crc >> 1 ) ^ P_32;
417 else crc = crc >> 1;
418 }
419
420 crc_tab32[i] = crc;
421 }
422
424
425} /* init_crc32_tab */
426
427
428
429 /*******************************************************************\
430 * *
431 * static void init_crcccitt_tab( void ); *
432 * *
433 * The function init_crcccitt_tab() is used to fill the array *
434 * for calculation of the CRC-CCITT with values. *
435 * *
436 \*******************************************************************/
437
438static void init_crcccitt_tab( void ) {
439
440 int i, j;
441 unsigned short crc, c;
442
443 for (i=0; i<256; i++) {
444
445 crc = 0;
446 c = (unsigned short)(((unsigned short) i) << 8);
447
448 for (j=0; j<8; j++) {
449
450 if ( (crc ^ c) & 0x8000 ) crc = (unsigned short)(( crc << 1 ) ^ P_CCITT);
451 else crc = (unsigned short)(crc << 1);
452
453 c = (unsigned short)(c << 1);
454 }
455
456 crc_tabccitt[i] = crc;
457 }
458
460
461} /* init_crcccitt_tab */
unsigned short update_crc_ccitt(unsigned short crc, char c)
Definition lib_crc.c:131
unsigned short update_crc_kermit(unsigned short crc, char c)
Definition lib_crc.c:217
static void init_crcdnp_tab(void)
Definition lib_crc.c:369
static void init_crc32_tab(void)
Definition lib_crc.c:405
unsigned short update_crc_sick(unsigned short crc, char c, char prev_byte)
Definition lib_crc.c:159
unsigned long update_crc_32(unsigned long crc, char c)
Definition lib_crc.c:271
static void init_crcccitt_tab(void)
Definition lib_crc.c:438
unsigned short update_crc_dnp(unsigned short crc, char c)
Definition lib_crc.c:244
#define P_16
Definition lib_crc.c:64
#define P_KERMIT
Definition lib_crc.c:68
unsigned short update_crc_16(unsigned short crc, char c)
Definition lib_crc.c:188
static unsigned short crc_tabdnp[256]
Definition lib_crc.c:99
static void init_crc16_tab(void)
Definition lib_crc.c:297
static int crc_tab16_init
Definition lib_crc.c:90
static void init_crckermit_tab(void)
Definition lib_crc.c:333
static int crc_tab32_init
Definition lib_crc.c:91
static unsigned short crc_tab16[256]
Definition lib_crc.c:96
static int crc_tabccitt_init
Definition lib_crc.c:92
static unsigned long crc_tab32[256]
Definition lib_crc.c:97
#define P_CCITT
Definition lib_crc.c:66
#define P_32
Definition lib_crc.c:65
#define P_DNP
Definition lib_crc.c:67
#define P_SICK
Definition lib_crc.c:69
static int crc_tabdnp_init
Definition lib_crc.c:93
static int crc_tabkermit_init
Definition lib_crc.c:94
static unsigned short crc_tabkermit[256]
Definition lib_crc.c:100
static unsigned short crc_tabccitt[256]
Definition lib_crc.c:98
#define CRC_FALSE
Definition lib_crc.h:58
#define CRC_TRUE
Definition lib_crc.h:59