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