———

 
Translations of this page:
crc_16_1021.asm
;----------------------------------------------------------------------
; PIC CRC16 (CRC-CCITT-16 0x1021)
;
;
;
;
; Background:
;
; Ashley Roll posted some code on the piclist (http://www.piclist.com)
; that implemented "CRC16" - or the CRC-CCITT-16 algorithm for the polynomial
; 0x1021. Tony K�bek and I took a few rounds optimizing the code and
; we ended up with a PIC implementation that was only 17 instructions
; (and 17 cycles, i.e. unlooped)!
;
; After further investigations, I found that the algorithm can be
; expressed:
;
;
;  int x;
;
;  x = ((crc>>8) ^ data) & 0xff;
;  x ^= x>>4;
;
;  crc = (crc << 8) ^ (x << 12) ^ (x <<5) ^ x;
;
;  crc &= 0xffff;
;
; No claim is made here that this is the first time that this algorithm
; has been expressed this way. But, it's the first time I've seen like
; this. Using this as a guide, I wrote another routine in PIC assembly.
; Unfortunately, this one takes 17 cycles too.
;
; Digital Nemesis Pty Ltd
; www.digitalnemesis.com
; ash@digitalnemesis.com
;
; Original Code: Ashley Roll
; Optimisations: Scott Dattalo
;----------------------------------------------------------------------
 
	list      p=p16f84           ; list directive to define processor
	#include p16f84.inc
       ; processor specific variable definitions
;	__CONFIG   _CP_OFF & _WDT_OFF & _MCLRE_OFF & _IntRC_OSC
 
;----------------------------------------------------------------------
; Program Variables
; Note that we start at RAM location 0x07
;----------------------------------------------------------------------
	CBLOCK 0x0c
		CRC16_High			; The CRC Register
		CRC16_Low
 
		Index				; Temp registers used during CRC update, can
		Temp				; be reused when not calling CRC_Update
		Count
		CRC16_MessageByte
	ENDC
 
 
;----------------------------------------------------------------------
; Startup Code
	ORG     0x0000            ; coding begins here
;	MOVWF   OSCCAL            ; update register with factory cal value
 
	; Skip to the main code
	GOTO	BeginProgram
 
;----------------------------------------------------------------------
; CRC16 Lookup Table. This is actually the Low and High lookup tables
; conconated together to save a few words of ROM space.
;
; To access the Low table, Enter with 0 <= W <= 15
; To access the High table, Enter with 16 <= W <= 31
;
; This can easily be achieved by setting or clearing bit 4.
CRC16_Lookup:
	ANDLW 0x1F
	ADDWF PCL, F
 
	RETLW 0x00		; LOW Byte Data
	RETLW 0x21
	RETLW 0x42
	RETLW 0x63
	RETLW 0x84
	RETLW 0xA5
	RETLW 0xC6
	RETLW 0xE7
	RETLW 0x08
	RETLW 0x29
	RETLW 0x4A
	RETLW 0x6B
	RETLW 0x8C
	RETLW 0xAD
	RETLW 0xCE
	RETLW 0xEF
	RETLW 0x00		; HIGH Byte DATA
	RETLW 0x10
	RETLW 0x20
	RETLW 0x30
	RETLW 0x40
	RETLW 0x50
	RETLW 0x60
	RETLW 0x70
	RETLW 0x81
	RETLW 0x91
	RETLW 0xA1
	RETLW 0xB1
	RETLW 0xC1
	RETLW 0xD1
	RETLW 0xE1
	RETLW 0xF1
 
;----------------------------------------------------------------------
; CRC_Init Subroutine
CRC_Init:
	MOVLW	0xFF
	MOVWF	CRC16_High
	MOVWF	CRC16_Low
	RETLW	0
 
;----------------------------------------------------------------------
; Looped version:
;
; CRC_Update Subroutine
_CRC_Update:
	; Save the Message Byte in the W register
	MOVWF	CRC16_MessageByte
 
	; We need to perform two iterations each processing 4 bits from the
	; CRC16_MessageByte register. MSB first.
	MOVLW	2
	MOVWF	Count
 
CRC16_UpdateLoop:
	; Get the top 4 bits from the message byte and XOR it with the
	; top 4 bits extracted from the CRC register to generate the lookup index.
	; Note that on the second iteration the nibbles in the message byte
	; will have been swaped again so we are actually getting the low
	; nibble of the message byte
	MOVF	CRC16_High, W
	XORWF	CRC16_MessageByte, W
	ANDLW	0xF0
	MOVWF	Index			; Index = (CRC16_High ^ CRC16_MessageByte) & 0xF0
 
	; Shift the CRC Register left 4 bits
	MOVLW	0x0f
	ANDWF	CRC16_High, F
	SWAPF	CRC16_High, F
	SWAPF	CRC16_Low, F
	ANDWF	CRC16_Low, W
	IORWF	CRC16_High, F	; CRC16_High = (CRC16_High << 4) | (CRC16_Low >> 4)
	XORWF	CRC16_Low, F	; CRC16_Low = CRC16_Low << 4
 
	; Do the table lookups and XOR into the CRC Registers
 
	movf	Index,w
        btfsc   Index,7
         iorlw  1
 
        xorwf   CRC16_High,f
 
        swapf  Index,w
        addwf  Index,w
        addwf  Index,w
 
        xorwf   CRC16_Low,f
 
	; Swap the nibbles in the message byte so that next iteration we do the
	; low nibble
	SWAPF	CRC16_MessageByte, F
 
	; Check if we need to iterate again
	DECFSZ	Count, F
	GOTO	CRC16_UpdateLoop
	RETLW	0				; return Finished
 
;==============================================================
;
; Unrolled version
;
; W = CRC Message byte
; CRC16 - current 16-bit CRC check sum
;
; let CRC16 = abcd
;     Message Byte = xy
;
; where abcd, xy are nibble variables
;
; Upon exit,
;
;  a = c ^ (i1>>3) ^ i2
;  b = d ^ ((i1<<1)&0xf) ^ (i2>>3)
;  c = i1 ^ ((i2<<1)&0xf)
;  d = i2
;
; First compute the nibble array indices:
;  i1 = a ^ x
;  i2 = i1 ^ b ^ y
;
;
; Notation  (I) : (J)  is a byte with I= high nibble, J= low nibble
;
 
CRC_Update2:
	xorwf	CRC16_High,w	; (a^x):(b^y)
	movwf	Index		;
	andlw	0xf0		; W = (a^x):0
	swapf	Index,f		; Index = (b^y):(a^x)
	xorwf	Index,f		; Index = (a^b^x^y):(a^x) = i2:i1
 
 
  ; High byte
	rlf	Index,W		;
	rlf	Index,W		;
	andlw	0x1f		; W = (i1>>3) : (((i1<<1)&0xf) | (i2>>3))
	xorwf	CRC16_Low,w     ; W = (i1>>3)^c : ((((i1<<1)&0xf) | (i2>>3)) ^ d)
	movwf	CRC16_High      ; low nibble of high byte is done
 
	movf	Index,w
	andlw	0xf0		; W = i2 : 0
	xorwf	CRC16_High,f    ; High nibble is of high byte is done
 
  ; now low byte
	movwf	CRC16_Low	; Low = i2 : 0
	addwf	CRC16_Low,f     ; Low = (i2<<1) : 0
	swapf	Index,W         ; W = i1 : i2
	xorwf	CRC16_Low,f     ; Low = i1 ^ (i2<<1) : i2
 
	retlw	0
 
;==============================================================
;int crc_1021(int data)
;{
;
;  int x;
;
;  x = ((crc>>8) ^ data) & 0xff;
;  x ^= x>>4;
;
;  crc = (crc << 8) ^ (x << 12) ^ (x <<5) ^ x;
;
;  crc &= 0xffff;
;
;  return crc;
;
;}
 
 
CRC_Update
	xorwf	CRC16_High,w	; (a^x):(b^y)
	movwf	Index		;
	andlw	0xf0		; W = (a^x):0
	swapf	Index,f		; Index = (b^y):(a^x)
	xorwf	Index,f		; Index = (a^b^x^y):(a^x) = i2:i1
 
 
  ; High byte
	movf	Index,W
	andlw	0xf0
	xorwf	CRC16_Low,W
	movwf	CRC16_High
 
	rlf	Index,W		;
	rlf	Index,W		;
	xorwf	CRC16_High,f
	andlw	0xe0
	xorwf	CRC16_High,f
 
	swapf	Index,F
	xorwf	Index,W
	movwf	CRC16_Low
 
 
	retlw	0
 
;----------------------------------------------------------------------
; Beginnig of Main Program
;----------------------------------------------------------------------
BeginProgram:
 
	; Initialise the CRC registers
	CALL	CRC_Init
 
	; Test Vector: "123456789"
	; Result: 0x29B1
	MOVLW	'1'
	CALL	CRC_Update  ;c782
	MOVLW	'2'
	CALL	CRC_Update  ;3dba
	MOVLW	'3'
	CALL	CRC_Update  ;5bce
	MOVLW	'4'
	CALL	CRC_Update  ;5349
	MOVLW	'5'
	CALL	CRC_Update  ;4560
	MOVLW	'6'
	CALL	CRC_Update  ;2ef4
	MOVLW	'7'
	CALL	CRC_Update  ;7718
	MOVLW	'8'
	CALL	CRC_Update  ;a12b
	MOVLW	'9'
	CALL	CRC_Update  ;29b1
 
Forever:
	GOTO	Forever
 
	END
 
mcu/pic16/crc-16/crc-16/crc_16_1021.asm.txt · Last modified: 07.15.2011 18:09 by npelov
 
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki