/******************************************
*					  *
* 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 */

}
                               