summaryrefslogtreecommitdiffstats
path: root/contrib/lib_crc.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/lib_crc.c')
-rw-r--r--contrib/lib_crc.c459
1 files changed, 459 insertions, 0 deletions
diff --git a/contrib/lib_crc.c b/contrib/lib_crc.c
new file mode 100644
index 0000000..8f71ffb
--- /dev/null
+++ b/contrib/lib_crc.c
@@ -0,0 +1,459 @@
+#include "lib_crc.h"
+
+
+
+ /*******************************************************************\
+ * *
+ * Library : lib_crc *
+ * File : lib_crc.c *
+ * Author : Lammert Bies 1999-2008 *
+ * E-mail : info@lammertbies.nl *
+ * Language : ANSI C *
+ * *
+ * *
+ * Description *
+ * =========== *
+ * *
+ * The file lib_crc.c contains the private and public func- *
+ * tions used for the calculation of CRC-16, CRC-CCITT and *
+ * CRC-32 cyclic redundancy values. *
+ * *
+ * *
+ * Dependencies *
+ * ============ *
+ * *
+ * lib_crc.h CRC definitions and prototypes *
+ * *
+ * *
+ * Modification history *
+ * ==================== *
+ * *
+ * Date Version Comment *
+ * *
+ * 2008-04-20 1.16 Added CRC-CCITT calculation for Kermit *
+ * *
+ * 2007-04-01 1.15 Added CRC16 calculation for Modbus *
+ * *
+ * 2007-03-28 1.14 Added CRC16 routine for Sick devices *
+ * *
+ * 2005-12-17 1.13 Added CRC-CCITT with initial 0x1D0F *
+ * *
+ * 2005-05-14 1.12 Added CRC-CCITT with start value 0 *
+ * *
+ * 2005-02-05 1.11 Fixed bug in CRC-DNP routine *
+ * *
+ * 2005-02-04 1.10 Added CRC-DNP routines *
+ * *
+ * 1999-02-21 1.01 Added FALSE and TRUE mnemonics *
+ * *
+ * 1999-01-22 1.00 Initial source *
+ * *
+ \*******************************************************************/
+
+
+
+ /*******************************************************************\
+ * *
+ * #define P_xxxx *
+ * *
+ * The CRC's are computed using polynomials. The coefficients *
+ * for the algorithms are defined by the following constants. *
+ * *
+ \*******************************************************************/
+
+#define P_16 0xA001
+#define P_32 0xEDB88320L
+#define P_CCITT 0x1021
+#define P_DNP 0xA6BC
+#define P_KERMIT 0x8408
+#define P_SICK 0x8005
+
+
+
+ /*******************************************************************\
+ * *
+ * static int crc_tab...init *
+ * static unsigned ... crc_tab...[] *
+ * *
+ * The algorithms use tables with precalculated values. This *
+ * speeds up the calculation dramaticaly. The first time the *
+ * CRC function is called, the table for that specific calcu- *
+ * lation is set up. The ...init variables are used to deter- *
+ * mine if the initialization has taken place. The calculated *
+ * values are stored in the crc_tab... arrays. *
+ * *
+ * The variables are declared static. This makes them invisi- *
+ * ble for other modules of the program. *
+ * *
+ \*******************************************************************/
+
+static int crc_tab16_init = FALSE;
+static int crc_tab32_init = FALSE;
+static int crc_tabccitt_init = FALSE;
+static int crc_tabdnp_init = FALSE;
+static int crc_tabkermit_init = FALSE;
+
+static unsigned short crc_tab16[256];
+static unsigned long crc_tab32[256];
+static unsigned short crc_tabccitt[256];
+static unsigned short crc_tabdnp[256];
+static unsigned short crc_tabkermit[256];
+
+
+
+ /*******************************************************************\
+ * *
+ * static void init_crc...tab(); *
+ * *
+ * Three local functions are used to initialize the tables *
+ * with values for the algorithm. *
+ * *
+ \*******************************************************************/
+
+static void init_crc16_tab( void );
+static void init_crc32_tab( void );
+static void init_crcccitt_tab( void );
+static void init_crcdnp_tab( void );
+static void init_crckermit_tab( void );
+
+
+
+ /*******************************************************************\
+ * *
+ * unsigned short update_crc_ccitt( unsigned long crc, char c ); *
+ * *
+ * The function update_crc_ccitt calculates a new CRC-CCITT *
+ * value based on the previous value of the CRC and the next *
+ * byte of the data to be checked. *
+ * *
+ \*******************************************************************/
+
+unsigned short update_crc_ccitt( unsigned short crc, char c ) {
+
+ unsigned short tmp, short_c;
+
+ short_c = 0x00ff & (unsigned short) c;
+
+ if ( ! crc_tabccitt_init ) init_crcccitt_tab();
+
+ tmp = (crc >> 8) ^ short_c;
+ crc = (crc << 8) ^ crc_tabccitt[tmp];
+
+ return crc;
+
+} /* update_crc_ccitt */
+
+
+
+ /*******************************************************************\
+ * *
+ * unsigned short update_crc_sick( *
+ * unsigned long crc, char c, char prev_byte ); *
+ * *
+ * The function update_crc_sick calculates a new CRC-SICK *
+ * value based on the previous value of the CRC and the next *
+ * byte of the data to be checked. *
+ * *
+ \*******************************************************************/
+
+unsigned short update_crc_sick( unsigned short crc, char c, char prev_byte ) {
+
+ unsigned short short_c, short_p;
+
+ short_c = 0x00ff & (unsigned short) c;
+ short_p = ( 0x00ff & (unsigned short) prev_byte ) << 8;
+
+ if ( crc & 0x8000 ) crc = ( crc << 1 ) ^ P_SICK;
+ else crc = crc << 1;
+
+ crc &= 0xffff;
+ crc ^= ( short_c | short_p );
+
+ return crc;
+
+} /* update_crc_sick */
+
+
+
+ /*******************************************************************\
+ * *
+ * unsigned short update_crc_16( unsigned short crc, char c ); *
+ * *
+ * The function update_crc_16 calculates a new CRC-16 value *
+ * based on the previous value of the CRC and the next byte *
+ * of the data to be checked. *
+ * *
+ \*******************************************************************/
+
+unsigned short update_crc_16( unsigned short crc, char c ) {
+
+ unsigned short tmp, short_c;
+
+ short_c = 0x00ff & (unsigned short) c;
+
+ if ( ! crc_tab16_init ) init_crc16_tab();
+
+ tmp = crc ^ short_c;
+ crc = (crc >> 8) ^ crc_tab16[ tmp & 0xff ];
+
+ return crc;
+
+} /* update_crc_16 */
+
+
+
+ /*******************************************************************\
+ * *
+ * unsigned short update_crc_kermit( unsigned short crc, char c ); *
+ * *
+ * The function update_crc_kermit calculates a new CRC value *
+ * based on the previous value of the CRC and the next byte *
+ * of the data to be checked. *
+ * *
+ \*******************************************************************/
+
+unsigned short update_crc_kermit( unsigned short crc, char c ) {
+
+ unsigned short tmp, short_c;
+
+ short_c = 0x00ff & (unsigned short) c;
+
+ if ( ! crc_tabkermit_init ) init_crckermit_tab();
+
+ tmp = crc ^ short_c;
+ crc = (crc >> 8) ^ crc_tabkermit[ tmp & 0xff ];
+
+ return crc;
+
+} /* update_crc_kermit */
+
+
+
+ /*******************************************************************\
+ * *
+ * unsigned short update_crc_dnp( unsigned short crc, char c ); *
+ * *
+ * The function update_crc_dnp calculates a new CRC-DNP value *
+ * based on the previous value of the CRC and the next byte *
+ * of the data to be checked. *
+ * *
+ \*******************************************************************/
+
+unsigned short update_crc_dnp( unsigned short crc, char c ) {
+
+ unsigned short tmp, short_c;
+
+ short_c = 0x00ff & (unsigned short) c;
+
+ if ( ! crc_tabdnp_init ) init_crcdnp_tab();
+
+ tmp = crc ^ short_c;
+ crc = (crc >> 8) ^ crc_tabdnp[ tmp & 0xff ];
+
+ return crc;
+
+} /* update_crc_dnp */
+
+
+
+ /*******************************************************************\
+ * *
+ * unsigned long update_crc_32( unsigned long crc, char c ); *
+ * *
+ * The function update_crc_32 calculates a new CRC-32 value *
+ * based on the previous value of the CRC and the next byte *
+ * of the data to be checked. *
+ * *
+ \*******************************************************************/
+
+unsigned long update_crc_32( unsigned long crc, char c ) {
+
+ unsigned long tmp, long_c;
+
+ long_c = 0x000000ffL & (unsigned long) c;
+
+ if ( ! crc_tab32_init ) init_crc32_tab();
+
+ tmp = crc ^ long_c;
+ crc = (crc >> 8) ^ crc_tab32[ tmp & 0xff ];
+
+ return crc;
+
+} /* update_crc_32 */
+
+
+
+ /*******************************************************************\
+ * *
+ * static void init_crc16_tab( void ); *
+ * *
+ * The function init_crc16_tab() is used to fill the array *
+ * for calculation of the CRC-16 with values. *
+ * *
+ \*******************************************************************/
+
+static void init_crc16_tab( void ) {
+
+ int i, j;
+ unsigned short crc, c;
+
+ for (i=0; i<256; i++) {
+
+ crc = 0;
+ c = (unsigned short) i;
+
+ for (j=0; j<8; j++) {
+
+ if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ P_16;
+ else crc = crc >> 1;
+
+ c = c >> 1;
+ }
+
+ crc_tab16[i] = crc;
+ }
+
+ crc_tab16_init = TRUE;
+
+} /* init_crc16_tab */
+
+
+
+ /*******************************************************************\
+ * *
+ * static void init_crckermit_tab( void ); *
+ * *
+ * The function init_crckermit_tab() is used to fill the array *
+ * for calculation of the CRC Kermit with values. *
+ * *
+ \*******************************************************************/
+
+static void init_crckermit_tab( void ) {
+
+ int i, j;
+ unsigned short crc, c;
+
+ for (i=0; i<256; i++) {
+
+ crc = 0;
+ c = (unsigned short) i;
+
+ for (j=0; j<8; j++) {
+
+ if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ P_KERMIT;
+ else crc = crc >> 1;
+
+ c = c >> 1;
+ }
+
+ crc_tabkermit[i] = crc;
+ }
+
+ crc_tabkermit_init = TRUE;
+
+} /* init_crckermit_tab */
+
+
+
+ /*******************************************************************\
+ * *
+ * static void init_crcdnp_tab( void ); *
+ * *
+ * The function init_crcdnp_tab() is used to fill the array *
+ * for calculation of the CRC-DNP with values. *
+ * *
+ \*******************************************************************/
+
+static void init_crcdnp_tab( void ) {
+
+ int i, j;
+ unsigned short crc, c;
+
+ for (i=0; i<256; i++) {
+
+ crc = 0;
+ c = (unsigned short) i;
+
+ for (j=0; j<8; j++) {
+
+ if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ P_DNP;
+ else crc = crc >> 1;
+
+ c = c >> 1;
+ }
+
+ crc_tabdnp[i] = crc;
+ }
+
+ crc_tabdnp_init = TRUE;
+
+} /* init_crcdnp_tab */
+
+
+
+ /*******************************************************************\
+ * *
+ * static void init_crc32_tab( void ); *
+ * *
+ * The function init_crc32_tab() is used to fill the array *
+ * for calculation of the CRC-32 with values. *
+ * *
+ \*******************************************************************/
+
+static void init_crc32_tab( void ) {
+
+ int i, j;
+ unsigned long crc;
+
+ for (i=0; i<256; i++) {
+
+ crc = (unsigned long) i;
+
+ for (j=0; j<8; j++) {
+
+ if ( crc & 0x00000001L ) crc = ( crc >> 1 ) ^ P_32;
+ else crc = crc >> 1;
+ }
+
+ crc_tab32[i] = crc;
+ }
+
+ crc_tab32_init = TRUE;
+
+} /* init_crc32_tab */
+
+
+
+ /*******************************************************************\
+ * *
+ * static void init_crcccitt_tab( void ); *
+ * *
+ * The function init_crcccitt_tab() is used to fill the array *
+ * for calculation of the CRC-CCITT with values. *
+ * *
+ \*******************************************************************/
+
+static void init_crcccitt_tab( void ) {
+
+ int i, j;
+ unsigned short crc, c;
+
+ for (i=0; i<256; i++) {
+
+ crc = 0;
+ c = ((unsigned short) i) << 8;
+
+ for (j=0; j<8; j++) {
+
+ if ( (crc ^ c) & 0x8000 ) crc = ( crc << 1 ) ^ P_CCITT;
+ else crc = crc << 1;
+
+ c = c << 1;
+ }
+
+ crc_tabccitt[i] = crc;
+ }
+
+ crc_tabccitt_init = TRUE;
+
+} /* init_crcccitt_tab */