In CCS PCH v4.137 for the PIC18F458 the results are as follows:
C version: size of 182 bytes with an average 80 instruction cycles per character.
Assembly version: size of 74 bytes with an average 25 instruction cycles per character.

Quote:

;----------------------------------------------------------------------
; 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
;----------------------------------------------------------------------

// If we get here the test between the two CRC methods succeeded
while(1);
}

Edit 1: Changed 'len' to 'Len' so code will compile when case sensitive.
Edit 2: Added link to Scott Dattalo's website
Edit Jan-2012: Commented the line '&= 0xFFFF' in the C example as it is only required on a processor with more than 16 bits.
Edit Nov-2012:
- Added test functions, including the original C-code
- Retrieve the SFR0 and POSTINC registers using the new getenv function.
Updated code with user comments from below:
- Reversed the sequence in the union so the output of the assembly version matches that of the C version.
- Replaced the two rlcf instructions by a single rlncf for the PIC18 (thanks niels_J)

Last edited by ckielstra on Fri Nov 16, 2012 4:12 pm; edited 6 times in total

Dargar

Joined: 12 Dec 2003Posts: 25

Posted: Wed Nov 02, 2005 10:22 am

Thank you, we will most likely use this in our current project.
Credits for the code will be left in as shown in the "Quote" field in your post.

Thanks for the code, I did test it and it works fine, but I have a problem.
I need to apply the algorithm to a buffer of 516 bytes. When I used it with
8 bytes of total data this runs OK. I think that the problem is with FSR,
I'm using a PIC18F4620 and the size of memory block is 256 bytes.
Can you help me ? Thanks.

el_tigre

Joined: 23 Dec 2007Posts: 12Location: Bs As : Argentina

Posted: Sun Nov 02, 2008 3:32 pm

I did´t.
The code for 18F4620 and data buffer >256 bytes is:
Thanks for the code !!!

The XOR function is equivalent to multiplication, I'm not in a position to translate from the CRC algoritm to a corresponding multiplication.

I don't find that Excel lends itself easily to bit wise logic.

There are many ways Excel could be used to perform the CRC conversion.

A macro using VB or entirely in VB would work.

In Excel a single formula for the CRC calculation would be unwieldy. I would do the job in stages which can be easily tested. I'm not going to do it for you, but the following should help. Using the KISS principal, (1) convert the input variables to binary, (2) perform the logic operations, then (3) convert back to decimal.

1) Convert to binary.

To convert variable a to binary one bit at a time, the Excel formula "=MOD(INT(a/2^n),2)" generates the nth bit of a. The result is either a 0 or a 1.

2) Perform bit wise logic operation again one bit at a time.

To perform a XOR b in Excel use the formula "=IF((bit n of a) = (bit n of b) , 0, 1 )". The result is 0 if both bits are the same and 1 if different.

3) The shifts and conversion to decimal are relatively trivial.

Mike Walne

niels_J

Joined: 16 Nov 2012Posts: 1

Posted: Fri Nov 16, 2012 5:05 am

Thanks a lot for this ingenious code. It made my bootloader fit in the boot page. It is also very much faster than the equivalent C-code, which I tried first. I have implemented it in an .asm file and can confirm that it verifies OK against the C-code and a very different code on a PC, which was checked against http://www.lammertbies.nl/comm/info/crc-calculation.html CRC-CCITT (0xFFFF).
While trying to understand the code I found I could replace the two rlcf with one rlncf on a PIC18. I have also added my own comments to the code. Hope this can help someone.

Code:

#include <p18F2520.inc>
; C18 uses FRS1 and FSR2 for stack pointers. FSR0 for indexing and other .
; It should be safe to use FSR0 here
LIST R=DEC ; Default radix is hex

; Make sure these are located in access RAM. Declared near in Main.c
EXTERN PgmData ; (struct Adr[2]; Byte[64])
EXTERN CRC16H, CRC16L