TITLE CRC16 - Cyclic Redundancy Checksum ;****************************************************************************** ;* * ;* * ;* Improved CRC16 Routine * ;* * ;* * ;* This routine performs CRC16 cyclic redundancy checksum calculations. * ;* It makes use of an idea given in the IEEE Micro publication by Aram * ;* Perez, and represents a considerable improvement over some of the * ;* methods used previously. It receives a 16-bit CRC in BC and * ;* the next data byte in E. It returns the updated CRC in BC. * ;* * ;* The first step is to XOR the data byte into the right half of the * ;* the CRC. Let the result of this be denoted by: * ;* * ;* a b c d e f g h i j k l m n o p * ;* * ;* After the eight CRC16 steps, with the x^16+x^15+x^2+1 polynomial, this * ;* should become: * ;* * ;* X i j k l m n o p 0 0 0 0 0 0 X * ;* + + + + + + + + + + + + + + + + * ;* 0 X i j k l m n o p 0 0 0 0 0 0 * ;* + + + + + + + + + + + + + + + + * ;* 0 0 0 0 0 0 0 0 a b c d e f g h * ;* * ;* where X represents the parity of the 8 bits i,j,k,l,m,n,o,p, and * ;* where + represents the XOR of the respective columns. The code below * ;* carries out this process directly, making use of the 8080's parity flag * ;* for finding X. [Note that since the routine uses this parity flag * ;* after an XRA instruction, the routine will work properly even on a * ;* Z80 microprocessor.] * ;* * ;****************************************************************************** ;* * ;* Entry: * ;* BC = old CRC16 * ;* E = next data byte * ;* * ;* CALL CRC16 * ;* * ;* Exit: * ;* BC = new CRC16 * ;* A, D, & E also affected * ;* * ;* * ;***************************************** R. Stafford - Aug. 9, 1983 ******** ; RSECT ROM INTERN CRC16 CRC16: EQU $ ; Assume the current 16 bit CRC is in BC and the next data byte in E. MOV A,E XRA C ;A now has [i j k l m n o p] & parity flag has X MOV C,B ;Put [a b c d e f g h] in C MOV D,A ;Put [i j k l m n o p] in D JPE CRCJ ;The parity flag has X (even on a Z80) XRI 2 ;XOR X into A in bit 1 CRCJ XRA D ;A now has [0 0 0 0 0 0 X 0] MOV E,A ;Now E = [0 0 0 0 0 0 X 0] RAR RAR ;Move X into carry flag MOV A,D ;Put [i j k l m n o p] back into A RAR MOV D,A ;Shift it to [X i j k l m n o] in D MOV A,E ;Get [0 0 0 0 0 0 X 0] from E RAR ;This sets carry to zero MOV E,A ;Put [p 0 0 0 0 0 0 X] back into E MOV A,D ;Now proceed with yet another shift RAR ;Get [0 X i j k l m n] in A MOV B,A ;Save it in B MOV A,E ;Then get [p 0 0 0 0 0 0 X] RAR ;Shift it to [o p 0 0 0 0 0 0] XRA E ;Then XOR in [p 0 0 0 0 0 0 X] XRA C ;Finally XOR in [a b c d e f g h] MOV C,A ;Establish this as the low byte of new CRC MOV A,D ;Now get [X i j k l m n o] XRA B ;XOR it with [0 X i j k l m n] MOV B,A ;This constitutes the upper byte of new CRC RET ;Return with updated CRC in BC ; End of CRC16