Ok, I finally understand Ashley Roll's CRC code from enough to modify it: http://www.digitalnemesis.com/ash/projects/EmbeddedCRC16/default.htm Here is a modified vesion of "piccrc.asm" which I call "piccrcr.asm". The difference being that the table is using a poly of 8005 and contains "built-in" reflection, as described here: http://www.geocities.com/SiliconValley/Pines/8659/crc.htm#r11 Besides the table, the only other code difference is that the CRC is shifted right 4 bits at a time rather than left. Not sure if you can do attachments to this list, so the code is included at the end of the message. I can share my modified version of "gentable.c", too, if others are curious how a reflected table is generated. Ok, so this is nowhere near 17 instructions, but hey, it *works*. :) Tony, I'm not so sure that the table can be calculated as per your earlier optimizations. But feel free to look for a pattern. :) BTW, I hope this code is in the public domain so that I am free to use it in my project. Oh, and finally, this code works on a real PIC, too, not just the simulator. Here's the output from the serial port: 80 A001 75 27A0 8A DFA6 0B BD1E 75 EFFC C7 D3AE AA C3D2 75 BA82 C7 F37B 55 1C73 43 141C 1C 0014 14 0000 -Dave ---- Start: piccrcr.asm ---- ;---------------------------------------------------------------------- ; PIC CRC16 Implementation with Restricted Table Size ; ; Digital Nemesis Pty Ltd ; www.digitalnemesis.com ; ash@digitalnemesis.com ; ; Original Code: Ashley Roll ; Optimisations: Scott Dattalo ; Reflected version: Dave Dribin ;---------------------------------------------------------------------- list p=12c508 ; list directive to define processor #include ; processor specific variable definitions __CONFIG _CP_OFF & _WDT_OFF & _MCLRE_OFF & _IntRC_OSC ;---------------------------------------------------------------------- ; Program Variables ; Note that we start at RAM location 0x07 ;---------------------------------------------------------------------- CBLOCK 0x07 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. ; ; This is a table for the CRC-16 with a polynomial of 8005 and the ; inputs and outputs reflected. ; CRC16_Lookup: ANDLW 0x1F ADDWF PCL, F RETLW 0x00 ; LOW Byte DATA RETLW 0x01 RETLW 0x01 RETLW 0x00 RETLW 0x01 RETLW 0x00 RETLW 0x00 RETLW 0x01 RETLW 0x01 RETLW 0x00 RETLW 0x00 RETLW 0x01 RETLW 0x00 RETLW 0x01 RETLW 0x01 RETLW 0x00 RETLW 0x00 ; HIGH Byte Data RETLW 0xCC RETLW 0xD8 RETLW 0x14 RETLW 0xF0 RETLW 0x3C RETLW 0x28 RETLW 0xE4 RETLW 0xA0 RETLW 0x6C RETLW 0x78 RETLW 0xB4 RETLW 0x50 RETLW 0x9C RETLW 0x88 RETLW 0x44 ;---------------------------------------------------------------------- ; CRC_Init Subroutine CRC_Init: MOVLW 0x00 MOVWF CRC16_High MOVWF CRC16_Low RETLW 0 ;---------------------------------------------------------------------- ; 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 low 4 bits from the message byte and XOR it with the ; low 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_Low, W XORWF CRC16_MessageByte, W ANDLW 0x0F MOVWF Index ; Index = (CRC16_Low ^ CRC16_MessageByte) & 0x0F ;; CRC16 is composed of the following nybbles: S T U V ;; where CRC16_High = S T and CRC16_Low = U V ;; Shift the CRC Register right 4 bits MOVLW 0xf0 ; W = F 0 ANDWF CRC16_Low, F ; CRC16_Low = U 0 SWAPF CRC16_Low, F ; CRC16_Low = 0 U SWAPF CRC16_High, F ; CRC16_High = T S ANDWF CRC16_High, W ; W = T 0 IORWF CRC16_Low, F ; CRC16_Low = T U XORWF CRC16_High, F ; CRC16_High = 0 S, thus CRC16 = 0 S T U ; Do the table lookups and XOR into the CRC Registers MOVF Index, W CALL CRC16_Lookup XORWF CRC16_Low, F ; CRC16_Low = CRC16_Low ^ CRC16_LookupLow[t] MOVF Index, W IORLW 0x10 ; Access High Table CALL CRC16_Lookup XORWF CRC16_High, F ; CRC16_High = CRC16_High ^ CRC16_LookupHigh[t] ; 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 ;---------------------------------------------------------------------- ; Beginnig of Main Program ;---------------------------------------------------------------------- BeginProgram: ; Initialise the CRC registers CALL CRC_Init MOVLW 0x80 ; crc = 00 00 CALL CRC_Update MOVLW 0x75 ; crc = a0 01 CALL CRC_Update MOVLW 0x8a ; crc = 27 a0 CALL CRC_Update MOVLW 0x0b ; crc = df a6 CALL CRC_Update MOVLW 0x75 ; crc = bd 1e CALL CRC_Update MOVLW 0xc7 ; crc = ef fc CALL CRC_Update MOVLW 0xaa ; crc = d3 ae CALL CRC_Update MOVLW 0x75 ; crc = c3 d2 CALL CRC_Update MOVLW 0xc7 ; crc = ba 82 CALL CRC_Update MOVLW 0x55 ; crc = f3 7b CALL CRC_Update MOVLW 0x43 ; crc = 1c 73 CALL CRC_Update MOVLW 0x1c ; crc = 14 1c CALL CRC_Update MOVLW 0x14 ; crc = 00 14 CALL CRC_Update NOP ; crc = 00 00 Forever: GOTO Forever END ----- End: piccrcr.asm ----- -- http://www.piclist.com hint: PICList Posts must start with ONE topic: [PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads