www.dattalo.com technical software pic crc16

7
29/6/2014 www.dattalo.com/technical/software/pic/crc16.asm http://www.dattalo.com/technical/software/pic/crc16.asm 1/7 list p=p16f84 #include p16f84.inc cblock 0x0c ;Variables for the optimized CRC16 computation crcHi crcLo index temp ;Variables for the looped CRC16 computation wCrc:2 bLoop bNewByte ;Variables for running a comparison between the ;two algorithms. test_byte test_crcHi test_crcLo endc org 0 goto main ;======================================================================== ; CRC-16 ; ; References: ; http://www.repairfaq.org/filipg/LINK/F_crc_v3.html ; http://www.netrino.com/Connecting/2000-01/ ; ; According to the above references, the CRC-16 algorithm is the reversed ; CRC algorithm for the polynomial 0x8005. To be complete, the parameters ; for the CRC-16 algorithm are: ; ; Width: 16 bits ; Polynomial: 0x8005 ; Initial: 0x0000 ; Xor out: 0x0000 ; Reflected data: yes ; Reflected remainder: yes ; ; The 'reflected' refers to a detail in the implementation of the algorithm ; (which is described in the above references). The simple (i.e. easy to ; understand, but slow) algorithm reverses the bit pattern of the polynomial ; for the reversed CRC algorithms. This simple algorithm can be shown to be ; implemented by: ; ; wCrc ^= bNewByte; ; ; bLoop = 8; ; do ; { ; if(wCrc & 1) { ; wCrc >>= 1;

Upload: esmael-prado

Post on 19-Jan-2016

17 views

Category:

Documents


0 download

TRANSCRIPT

29/6/2014 www.dattalo.com/technical/software/pic/crc16.asm

http://www.dattalo.com/technical/software/pic/crc16.asm 1/7

list p=p16f84 #include p16f84.inc

cblock 0x0c

;Variables for the optimized CRC16 computation crcHi crcLo index temp

;Variables for the looped CRC16 computation wCrc:2 bLoop bNewByte

;Variables for running a comparison between the ;two algorithms.

test_byte test_crcHi test_crcLo endc

org 0 goto main

;========================================================================; CRC-16;; References:; http://www.repairfaq.org/filipg/LINK/F_crc_v3.html; http://www.netrino.com/Connecting/2000-01/;; According to the above references, the CRC-16 algorithm is the reversed; CRC algorithm for the polynomial 0x8005. To be complete, the parameters; for the CRC-16 algorithm are: ;; Width: 16 bits; Polynomial: 0x8005; Initial: 0x0000; Xor out: 0x0000; Reflected data: yes; Reflected remainder: yes;; The 'reflected' refers to a detail in the implementation of the algorithm; (which is described in the above references). The simple (i.e. easy to ; understand, but slow) algorithm reverses the bit pattern of the polynomial; for the reversed CRC algorithms. This simple algorithm can be shown to be; implemented by:;; wCrc ̂= bNewByte;;; bLoop = 8;; do; {; if(wCrc & 1) {; wCrc >>= 1;

29/6/2014 www.dattalo.com/technical/software/pic/crc16.asm

http://www.dattalo.com/technical/software/pic/crc16.asm 2/7

; wCrc ̂= 0xA001;; } else; wCrc >>= 1;;; } while (--bLoop);;; The 8005 polynomial is reversed and becomes A001. ;; This simple algorithm takes a byte as its input and operates on each bit; in succession. It's possible to compute this loop much more efficiently. ; Most (all?) implementations I've seen use look up tables to speed things ; up. However, it's possible to speed up the computation using boolean; arithmetic too. And on a PIC processor where look up tables are relatively ; expensive, the boolean arithmetic approach is both faster and takes less; program memory.;; Given: Assume the looped implementation shown above is correct.;; How can boolean equations be written to generate the same result?;; It helps to describe the algorithm. To compute the CRC for the next byte; of a message, we first start off by xor'ing it with the current CRC value.; We then loop 8 times and at each iteration, we examine the current CRC; value. If its least significant bit is set, then we shift the CRC right 1; bit position and xor it with the reversed polynomial A001. If the least; significant bit is not set, then we simply shift the CRC right 1 position; but don't xor it with anything.;; It's convenient to unroll the loop and express the bit manipulation ; operations using a table:;; ; Input byte --> n7 n6 n5 n4 n3 n2 n1 n0; Initial CRC --> wf we wd wc wb wa w9 w8 w7 w6 w5 w4 w3 w2 w1 w0; --------------------------------------------------; a0 0 a0 0 0 0 0 0 0 0 0 0 0 0 0 a0; a1 0 a1 0 0 0 0 0 0 0 0 0 0 0 0 a1; a2 0 a2 0 0 0 0 0 0 0 0 0 0 0 0 a2; a3 0 a3 0 0 0 0 0 0 0 0 0 0 0 0 a3; a4 0 a4 0 0 0 0 0 0 0 0 0 0 0 0 a4; a5 0 a5 0 0 0 0 0 0 0 0 0 0 0 0 a5; a6 0 a6 0 0 0 0 0 0 0 0 0 0 0 0 a6; a7 0 a7 0 0 0 0 0 0 0 0 0 0 0 0 a7; --------------------------------------------------; wf we wd wc wb wa w9 w8 w7 w6 w5 w4 w3 w2 w1 w0 <-- Final CRC;; In this table, each column corresponds to a bit position. The 8-bit input is; shown at the top as bits n7 through n0. The Initial CRC is shown at the top; as bits wf through w0. The next 8 rows are the polynomial. The bit pattern; for A001 is 1010 0000 0000 0001 and you can see how the a_i's align with; this pattern. The reason for the a_i's is that it provides a symbolic way; to express whether the polynomial will be XOR'd or not at each iteration.; In other words, if the poylnomial is not XOR'd then the a_i's will be zero; (xor'ing with a 0 is a no-operation). If the polynomial is xor'd then the ; a_i's will be a 1. ;; Finally, the last row in the table is the resulting CRC. The way the table; works is that each bit in the final CRC is result of XOR'ing all of the bits; in the bit column. For example, the final w0 bit is a7̂w8. All 16-bits of; the final equation are: ;

29/6/2014 www.dattalo.com/technical/software/pic/crc16.asm

http://www.dattalo.com/technical/software/pic/crc16.asm 3/7

; w0 = w8' ̂ a7 w8 = a0 ̂ a2; w1 = w9' w9 = a1 ̂ a3; w2 = wa' wa = a2 ̂ a4; w3 = wb' wb = a3 ̂ a5; w4 = wc' wc = a4 ̂ a6; w5 = wd' wd = a5 ̂ a7; w6 = we' ̂ a0 we = a6; w7 = wf' ̂ a1 wf = a7;; The next step is to determine the values for a_i. Each a_i is equal to the ; LSB of the CRC value from the previous iteration of the loop. For example,; when the loop first begins, the lsb of the CRC is n0 ̂ w0. Thus a0 = n0̂w0.; If n0̂w0 is a binary 1, then the bit pattern 1010 0000 0000 0001 will be ; XOR'd with the shifted CRC. This means for the next iteration the LSB of ; the CRC will depend on w1̂n1 and it will depend on a0. Specifically,; a1 = n1̂w1̂a0. This can be read off the table by examining the bit column; just to the right of the a1 (i.e. the column with n1). Here are all of the; equations ;; a0 = n0̂w0; a1 = n1̂w1̂a0 ; a2 = n2̂w2̂a1 ; a3 = n3̂w3̂a2 ; a4 = n4̂w4̂a3 ; a5 = n5̂w5̂a4 ; a6 = n6̂w6̂a5 ; a7 = n7̂w7̂a6 ;; And to simplify things just a bit, let all of n̂w combinations be call 'i'.;; a0 = i0; a1 = i1̂a0 ; a2 = i2̂a1 ; a3 = i3̂a2 ; a4 = i4̂a3 ; a5 = i5̂a4 ; a6 = i6̂a5 ; a7 = i7̂a6 ;; These 8 equations for the a's can be solved in terms of the i's:;; a0 = i0; a1 = i1̂i0 ; a2 = i2̂i1̂i0; a3 = i3̂i2̂i1̂i0; a4 = i4̂i3̂i2̂i1̂i0; a5 = i5̂i4̂i3̂i2̂i1̂i0; a6 = i6̂i5̂i4̂i3̂i2̂i1̂i0; a7 = i7̂i6̂i5̂i4̂i3̂i2̂i1̂i0;; And finally, these expressions for the a's can be substituted into; the equations for the final CRC:;; w0 = w8' ̂ i7̂i6̂i5̂i4̂i3̂i2̂i1̂i0 w8 = i1 ̂ i2; w1 = w9' w9 = i2 ̂ i3; w2 = wa' wa = i3 ̂ i4; w3 = wb' wb = i4 ̂ i5; w4 = wc' wc = i5 ̂ i6; w5 = wd' wd = i6 ̂ i7; w6 = we' ̂ i0 we = i6̂i5̂i4̂i3̂i2̂i1̂i0; w7 = wf' ̂ i0 ̂ i1 wf = i7̂i6̂i5̂i4̂i3̂i2̂i1̂i0

29/6/2014 www.dattalo.com/technical/software/pic/crc16.asm

http://www.dattalo.com/technical/software/pic/crc16.asm 4/7

;; That completes the derivation or the boolean equations. Next, let's derive; a C program that implements these:;;; unsigned int i;; unsigned int p;;; i = (wCrc ̂ bNewByte) & 0xff;;; /* Compute the parity of i: */; p = i ̂ (i>>4);; p = p ̂ (p>>2);; p = p ̂ (p>>1) & 1; ;; p = p ? 0xc001 : 0x0000;;; wCrc = (wCrc>>8) ̂ p ̂ (i<<6) ̂ (i<<7);;;; Input: W = new 8-bit byte ; crcLo:crcHi - current 16-bit CRC;; Output:; crcLo:crcHi - updated 16-bit CRC;; Memory used:; index; temp;; Cycles:; 23 (excluding return)

CRC16: XORWF crcLo,W MOVWF index

MOVF crcHi,W MOVWF crcLo ;crcLo = crc >> 8

CLRF temp ;Holds the CRC pattern for the low byte CLRC ; RRF index,W ;W = 0.i7.i6.i5.i4.i3.i2.i1 C=i0 XORWF index,F ;F = 0i7.i7i6.i6i5.i5i4.i4i3.i3i2.i2i1.i1i0 RRF temp,F ;t = i0.0.0.0.0.0.0.0 C=0 RRF index,W ;W = 0.0i7.i7i6.i6i5.i5i4.i4i3.i3i2.i2i1 C=i1i0 MOVWF crcHi ;crcHi = 0.0i7.i7i6.i6i5.i5i4.i4i3.i3i2.i2i1 RRF temp,F ;t = i1i0.i0.0.0.0.0.0.0 C=0

RLF index,F ;W = i7i6.i6i5.i5i4.i4i3.i3i2.i2i1.i1i0.0 C=i7 XORWF index,F ;F = X.X.i7i6i5i4.X.X.X.i3i2i1i0.X SWAPF index,W ;F = X.X.i3i2i1i0.X.X.X.i7i6i5i4.X XORWF index,F ;F = X.X.P.X.X.X.P.X where P= parity(index)

; at this point, the parity of the index byte is now at bits 1 and 5 of index.

MOVF temp,W ;W = i1i0.i0.0.0.0.0.0.0 BTFSC index,1 ;If P==1 XORLW 1 ;W = i1i0.i0.0.0.0.0.0.P

29/6/2014 www.dattalo.com/technical/software/pic/crc16.asm

http://www.dattalo.com/technical/software/pic/crc16.asm 5/7

XORWF crcLo,F ;crcLo = (crc>>8) ̂ i1i0.i0.0.0.0.0.0.P

MOVLW 0xC0 BTFSC index,1 XORWF crcHi,F ;crcHi = P.Pi7.i7i6.i6i5.i5i4.i4i3.i3i2.i2i1

return

;------------------------------------------------------------------------;; vUpdateCrc - looped implementation of the CRC-16 algorithm;; Written by Johan Bodin. ; ;void vUpdateCrc (char bNewByte) ;{CRC16_looped MOVWF bNewByte ; char bLoop; ; ; wCrc.low8 ̂= bNewByte; XORWF wCrc,F ; ; bLoop = 8; MOVLW .8 MOVWF bLoop ; do ; { ; Carry = 0;m001 CLRC ; rr (wCrc.high8); RRF wCrc+1,F ; rr (wCrc.low8); RRF wCrc,F ; if (Carry) SKPC GOTO m002 ; wCrc ̂= 0xA001; MOVLW .160 XORWF wCrc+1,F MOVLW .1 XORWF wCrc,F ; } while (--bLoop);m002 DECFSZ bLoop,F GOTO m001 ;} RETURN ;========================================================================initCrc: MOVF test_crcLo,W MOVWF crcLo MOVWF wCrc

MOVF test_crcHi,W MOVWF crcHi MOVWF wCrc+1

return

29/6/2014 www.dattalo.com/technical/software/pic/crc16.asm

http://www.dattalo.com/technical/software/pic/crc16.asm 6/7

main: clrf crcLo clrf crcHi

movlw '1' call CRC16

movlw '2' call CRC16

movlw '3' call CRC16

movlw '4' call CRC16

movlw '5' call CRC16

movlw '6' call CRC16

movlw '7' call CRC16

movlw '8' call CRC16

movlw '9' call CRC16

; crc should be 0xBB3D

clrf test_byte clrf test_crcLo clrf test_crcHiloop: call initCrc

movf test_byte,W call CRC16 movf test_byte,W call CRC16_looped

; compare movf crcLo,W xorwf wCrc,W skpz goto failed movf crcHi,W xorwf wCrc+1,W skpz goto failed

decfsz test_byte,F goto loop

clrwdt decfsz test_crcLo,F

29/6/2014 www.dattalo.com/technical/software/pic/crc16.asm

http://www.dattalo.com/technical/software/pic/crc16.asm 7/7

goto loop decfsz test_crcHi,F goto loop

passed: goto passedfailed: goto failed

end