/****************************************************************************** * * * Cyclic Redundancy Check (CRC) functions * * * ******************************************************************************/ /* * crc_clear: * This function clears the CRC to zero. It should be called prior to * the start of the processing of a block for both received messages, * and messages to be transmitted. * * Calling sequence: * * short crc; * crc = crc_clear(); */ short crc_clear() { return(0); } /* * crc_update: * this function must be called once for each character which is * to be included in the CRC for messages to be transmitted. * This function is called once for each character which is included * in the CRC of a received message, AND once for each of the two CRC * characters at the end of the received message. If the resulting * CRC is zero, then the message has been correctly received. * * Calling sequence: * * crc = crc_update(crc,next_char); */ short crc_update(crc,crc_char) short crc; char crc_char; { long x; short i; /* "x" will contain the character to be processed in bits 0-7 and the CRC */ /* in bits 8-23. Bit 24 will be used to test for overflow, and then cleared */ /* to prevent the sign bit of "x" from being set to 1. Bits 25-31 are not */ /* used. ("x" is treated as though it is a 32 bit register). */ x = ((long)crc << 8) + crc_char; /* Get the CRC and the character */ /* Repeat the following loop 8 times (for the 8 bits of the character). */ for(i = 0;i < 8;i++) { /* Shift the high-order bit of the character into the low-order bit of the */ /* CRC, and shift the high-order bit of the CRC into bit 24. */ x = x << 1; /* Shift "x" left one bit */ /* Test to see if the old high-order bit of the CRC was a 1. */ if(x & 0x01000000) /* Test bit 24 of "x" */ /* If the old high-order bit of the CRC was a 1, exclusive-or it with a one */ /* to set it to 0, and exclusive-or the CRC with hex 1021 to produce the */ /* CCITT-recommended CRC generator of: X**16 + X**12 + X**5 + 1. To produce */ /* the CRC generator of: X**16 + X**15 + X**2 + 1, change the constant from */ /* 0x01102100 to 0x01800500. This will exclusive-or the CRC with hex 8005 */ /* and produce the same CRC that IBM uses for their synchronous transmission */ /* protocols. */ x = x ^ 0x01102100; /* Exclusive-or "x" with a...*/ /* ...constant of hex 01102100 */ /* And repeat 8 times. */ } /* End of "for" loop */ /* Return the CRC as the 16 low-order bits of this function's value. */ return(((x & 0x00ffff00) >> 8)); /* AND off the unneeded bits and... */ /* ...shift the result 8 bits to the right */ } /* * crc_finish: * This function must be called once after all the characters in a block * have been processed for a message which is to be TRANSMITTED. It * returns the calculated CRC bytes, which should be transmitted as the * two characters following the block. The first of these 2 bytes * must be taken from the high-order byte of the CRC, and the second * must be taken from the low-order byte of the CRC. This routine is NOT * called for a message which has been RECEIVED. * * Calling sequence: * * crc = crc_finish(crc); */ short crc_finish(crc) short crc; { /* Call crc_update twice, passing it a character of hex 00 each time, to */ /* flush out the last 16 bits from the CRC calculation, and return the */ /* result as the value of this function. */ return(crc_update(crc_update(crc,'\0'),'\0')); } /* * This is a sample of the use of the CRC functions, which calculates the * CRC for a 1-character message block, and then passes the resulting CRC back * into the CRC functions to see if the "received" 1-character message and CRC * are correct. */ main() { short crc; /* The calculated CRC */ char crc_char; /* The 1-character message */ char x, y; /* 2 places to hold the 2 "received" CRC bytes */ crc_char = 'A'; /* Define the 1-character message */ crc = crc_clear(); /* Reset the CRC to "transmit" a new message */ crc = crc_update(crc,crc_char); /* Update the CRC for the first... */ /* ...(and only) character of the message */ crc = crc_finish(crc); /* Finish the transmission calculation */ x = (char)((crc & 0xff00) >> 8); /* Extract the high-order CRC byte */ y = (char)(crc & 0x00ff); /* And extract the low-order byte */ printf("%04x\n",crc); /* Print the results */ crc = crc_clear(); /* Prepare to "receive" a message */ crc = crc_update(crc,crc_char); /* Update the CRC for the first... */ /* ...(and only) character of the message */ crc = crc_update(crc,x); /* Pass both bytes of the "received"... */ crc = crc_update(crc,y); /* ...CRC through crc_update, too */ printf("%04x\n",crc); /* If the result was 0, then the message... */ /* ...was received without error */ } eceived without error */ }