CRC

Purpose: Generate a CCITT 16-bit CRC over a block of SRAM memory.
Assumes: The CRC generator polynomial is x15 + x13 + x0 (which is the value 0xA001 or 1010000000000001.)
Passed:    R25:R24  BYTE *   bPtrBuffer the pointer to the start of the SRAM buffer
R22  BYTE bCount  the number of bytes to include in the CRC
R20  BYTE bInit  0 specifies the initial CRC of 0x0000, anything else 0xFFFF
Returns: R25:R24  WORD wCRC the CRC value over the SRAM range
Alters: Only R20, in addition to R24, R25 and the FLAGS
Example: 
.ORG 0x1000

CRCDemo:
   ADIW    R26, 0              ; If the buffer pointer is NULL, there is nothing
   BREQ    ACRCDemo_Ret        ;  to do, so just exit
   MOVW    R24, R26            ; Only need to point R25:R24 at the buffer
   CALL    AParseValue         ; The ULONG result is in R25:R24:R23:R22; done
   SBRS    R21, BIT_PV_VALID   ;  if it doesn't contain a valid value
   RJMP    ACRCDemo_Ret
   MOVW    R30, R22            ; Save the target address: the R23:R22 portion
   MOVW    R24, R26            ; Point to the second string containing a value
   CALL    AParseValue         ; The second value is the byte count, which was
   SBRS    R21, BIT_PV_VALID   ;  just read into R25:R24:R23:R22; the CRC call
   RJMP    ACRCDemo_Ret        ;  only needs the R23:R22 portion, already setup
   MOVW    R24, R30            ; Move the saved buffer pointer back to R25:R24
   LDI     R20, -1             ; Initialize the CRC with 0xFFFF
   CALL    ACRC                ; Call to calculate the CRC
   CALL    ADumpRegs_Begin     ; The CRC was returned is R25:R24

CRCDemo_Ret:
   RET
Test it:
m>ES 0x700 = "Test string"
m>DS+ 0x700 16
SRAM contents:
0700:  54 65 73 74 20 73 74 72-69 6E 67 00 00 00 00 00  Test string.....
m>@ 0x1000 0x700 11

 10   32   54   76   98  1110 1312 1514 1716 1918 2120 2322 2524 2726 2928 3130
---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
0000 0161 0992 FF28-0004 0000 0000 4000-003C 0000 09FF 000B-BA4A 0000 0280 0700
m> 0x70B = 0xBA4A
m> 0x700 16
SRAM contents:
0700:  54 65 73 74 20 73 74 72-69 6E 67 4A BA 00 00 00  Test stringJ....
m>@ 0x1000 0x700 12  ; Including the first CRC BYTE, note the result:

 10   32   54   76   98  1110 1312 1514 1716 1918 2120 2322 2524 2726 2928 3130
---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
0000 04FB 093E FF28-0004 0000 0000 4000-003C 0000 09FF 000C-00BA 0000 0280 0700
m>@ 0x1000 0x700 13  ; Including both CRC BYTEs, note the result:

 10   32   54   76   98  1110 1312 1514 1716 1918 2120 2322 2524 2726 2928 3130
---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
0000 0349 0944 FF28-0004 0000 0000 4000-003C 0000 09FF 000D-0000 0000 0280 0700
m>                                                                              
Notes:The term "CRC" is an acronym, meaning Cyclic Redundancy Check. A CRC provides a way of detecting, but not correcting, bit errors in a block of data. Consider a data block to be simply a very long number. If that number is divided that by some known constant both before and after some event (e.g., data transmission and reception or storage and retrieval) and the remainders are identical, it approximates what a CRC is doing. Given a 16-bit "remainder", only one in 65,536 values will match. This is not precisely correct, mathematically, but it's a good mental model of how a CRC detects an error. There is much more information about CRCs on the web.
The RunningCRC system functions is able to calculate a 16-bit CRC over a range of SRAM, FLASH or EEPROM, as it does so one (1) BYTE at a time. This one only works on SRAM. A block could be copied from FLASH or EEPROM to SRAM and the CRC then calculated over the SRAM buffer using this function, but the source of any error could either be in copying or in storage.
When a CRC WORD is initialized to 0xFFFF, changes in blocks that begin with a series of zeros can be detected. When initialized to 0x0000, they cannot.
See the notes in the msTimerBYTE and SecTimerBYTE functions.
 
Dropin: 
(setup
code)
;   Setup for the CRC call:
; Passed:  R25:R24 BYTE * bPtrBuffer to the start of the buffer in SRAM
;              R22 BYTE   bCount is the number of BYTEs to include in the CRC
;              R20 BYTE   bInit: 0 to initialize CRC to 0, else init to 0xFFFF
; Returns: R25:R24 WORD   wCRC
; Alters:  R0, R24, R25 and the FLAGS (R25:R24 has the return value)
Also see:  The millis and SystemSeconds variables, the msTimerBYTE, SecTimerBYTE, msTimerWORD, and SecTimerWORD timers.