CRCModule

A module providing CRC routines for various uses.

Instructions for use provided in the module comments. Note the #option required when using the table versions of the code.

{
*****************************************************************************
*  Name    : CRC.BAS  Swordfish MODULE                                      *
*  Author  : Thomas D. Estes                                                *
*  Date    : 12/31/2008                                                     *
*  Version : 1.1                                                            *
*  Notes   : What in the world am I doing working on crc routines on        *
*          : New Years eve?  Get a life Tom!                                *
*****************************************************************************
V1.0 12/31/2008 Dallas/Maxim DALcrc8SF, DALcrc8AL, DALcrc8LU
                Dallas/Maxim DALcrc16SF, DALcrc16AL, DALcrc16LU
                Sensirion SHTcrc8SF, SHTcrc8AL
                SMBus SMBcrc8SF, SMBcrc8LU

V1.1 1/7/2009 adds Sensiron SHTcrc8LU
                   SMBus SMBcrc8AL
                   CCITT CCITTcrc16SF
                   MODBUS MODBUScrc16SF
                   CRC16 CRC16SF

This module provides CRC calculations for various crc schemes.

Several variations of each calculation are provided.  A Swordfish
version (always), a Swordfish encapsulated assembly language version (sometimes)
and a table based SF version (sometimes) may be provided.
In general the assembly language version is twice as fast as the Swordfish
version.  The table based versions are generally 4 times faster than the
assembly version.  These of course require large tables to be stored in
program memory and operate a byte at a time rather than a bit at a time.

Each call requires the data byte to be added to the crc and the starting or
cumulative crc value.  The function returns the crc.  So you would want
to call them by crc = CRC.xxxcrcxx(data_to_be_added,crc).  That way crc
continues to accumulate assuming that is what you want.

Time to execute each routine is given in cpu clock ticks.  The number
includes instructions to start and stop the timer so the actual numbers
are slightly smaller than those given.

************NOTE************NOTE*************NOTE*************NOTE**************
Check your implementation carefully.  Many schemes want the CRC to be
initialized with certain registers or values.  Some want the end result
rotated, complemented, reversed or bytes swapped in 16 bit implementations.
There are many input/output schemes so make sure to understand yours.

Feel free to add other CRC schemes to it but when you do please increase the
version by .1 and notify everyone by a message to the SF forum.
}
Module CRC

Include "system.bas"

//need to include an option to indicate the look up tables will be needed
//more specifically which look up table is needed
//without this the tables would be compiled into all crc code
#option LUTable = None  //assume no look up tables are to be loaded

#if isoption(LUTable) And Not (LUTable in (None, DAL8, DAL16, SMB8, SHT8))
    #error LUTable, "Invalid Option, LUTable must be None DAL8 DAL16 SHT8 SMB8"
#endif

#if LUTable = DAL8
    Const DAL8Table(256) As Byte = 
    ($00,$5E,$BC,$E2,$61,$3F,$DD,$83,$C2,$9C,$7E,$20,$A3,$FD,$1F,$41,
    $9D,$C3,$21,$7F,$FC,$A2,$40,$1E,$5F,$01,$E3,$BD,$3E,$60,$82,$DC,
    $23,$7D,$9F,$C1,$42,$1C,$FE,$A0,$E1,$BF,$5D,$03,$80,$DE,$3C,$62,
    $BE,$E0,$02,$5C,$DF,$81,$63,$3D,$7C,$22,$C0,$9E,$1D,$43,$A1,$FF,
    $46,$18,$FA,$A4,$27,$79,$9B,$C5,$84,$DA,$38,$66,$E5,$BB,$59,$07,
    $DB,$85,$67,$39,$BA,$E4,$06,$58,$19,$47,$A5,$FB,$78,$26,$C4,$9A,
    $65,$3B,$D9,$87,$04,$5A,$B8,$E6,$A7,$F9,$1B,$45,$C6,$98,$7A,$24,
    $F8,$A6,$44,$1A,$99,$C7,$25,$7B,$3A,$64,$86,$D8,$5B,$05,$E7,$B9,
    $8C,$D2,$30,$6E,$ED,$B3,$51,$0F,$4E,$10,$F2,$AC,$2F,$71,$93,$CD,
    $11,$4F,$AD,$F3,$70,$2E,$CC,$92,$D3,$8D,$6F,$31,$B2,$EC,$0E,$50,
    $AF,$F1,$13,$4D,$CE,$90,$72,$2C,$6D,$33,$D1,$8F,$0C,$52,$B0,$EE,
    $32,$6C,$8E,$D0,$53,$0D,$EF,$B1,$F0,$AE,$4C,$12,$91,$CF,$2D,$73,
    $CA,$94,$76,$28,$AB,$F5,$17,$49,$08,$56,$B4,$EA,$69,$37,$D5,$8B,
    $57,$09,$EB,$B5,$36,$68,$8A,$D4,$95,$CB,$29,$77,$F4,$AA,$48,$16,
    $E9,$B7,$55,$0B,$88,$D6,$34,$6A,$2B,$75,$97,$C9,$4A,$14,$F6,$A8,
    $74,$2A,$C8,$96,$15,$4B,$A9,$F7,$B6,$E8,$0A,$54,$D7,$89,$6B,$35)
{
*****************************************************************************
*  Name    : Function DALcrc8LU  Dallas/Maxim CRC8 SF Look Up table         *
*  Date    : 12/31/2008                                                     *
*  Version : 1.0                                                            *
*  Notes   : Requires 13 cpu clocks                                         *
*          : Requires the 256 byte table DAL8Table be in program memory     *
*****************************************************************************
}
Public Function DALcrc8LU(pDataByte As Byte,pCRC As Byte) As Byte
    pDataByte = pDataByte Xor pCRC
    Result = DAL8Table(pDataByte)
End Function

#elseif LUTable = DAL16
    Const DAL16HiTable(256) As Byte =
    ($00,$C0,$C1,$01,$C3,$03,$02,$C2,$C6,$06,$07,$C7,$05,$C5,$C4,$04,
    $CC,$0C,$0D,$CD,$0F,$CF,$CE,$0E,$0A,$CA,$CB,$0B,$C9,$09,$08,$C8,
    $D8,$18,$19,$D9,$1B,$DB,$DA,$1A,$1E,$DE,$DF,$1F,$DD,$1D,$1C,$DC,
    $14,$D4,$D5,$15,$D7,$17,$16,$D6,$D2,$12,$13,$D3,$11,$D1,$D0,$10,
    $F0,$30,$31,$F1,$33,$F3,$F2,$32,$36,$F6,$F7,$37,$F5,$35,$34,$F4,
    $3C,$FC,$FD,$3D,$FF,$3F,$3E,$FE,$FA,$3A,$3B,$FB,$39,$F9,$F8,$38,
    $28,$E8,$E9,$29,$EB,$2B,$2A,$EA,$EE,$2E,$2F,$EF,$2D,$ED,$EC,$2C,
    $E4,$24,$25,$E5,$27,$E7,$E6,$26,$22,$E2,$E3,$23,$E1,$21,$20,$E0,
    $A0,$60,$61,$A1,$63,$A3,$A2,$62,$66,$A6,$A7,$67,$A5,$65,$64,$A4,
    $6C,$AC,$AD,$6D,$AF,$6F,$6E,$AE,$AA,$6A,$6B,$AB,$69,$A9,$A8,$68,
    $78,$B8,$B9,$79,$BB,$7B,$7A,$BA,$BE,$7E,$7F,$BF,$7D,$BD,$BC,$7C,
    $B4,$74,$75,$B5,$77,$B7,$B6,$76,$72,$B2,$B3,$73,$B1,$71,$70,$B0,
    $50,$90,$91,$51,$93,$53,$52,$92,$96,$56,$57,$97,$55,$95,$94,$54,
    $9C,$5C,$5D,$9D,$5F,$9F,$9E,$5E,$5A,$9A,$9B,$5B,$99,$59,$58,$98,
    $88,$48,$49,$89,$4B,$8B,$8A,$4A,$4E,$8E,$8F,$4F,$8D,$4D,$4C,$8C,
    $44,$84,$85,$45,$87,$47,$46,$86,$82,$42,$43,$83,$41,$81,$80,$40)
    Const DAL16LoTable(256) As Byte =
    ($00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$00,$C1,$81,$40,
    $01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$01,$C0,$80,$41,
    $01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$01,$C0,$80,$41,
    $00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$00,$C1,$81,$40,
    $01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$01,$C0,$80,$41,
    $00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$00,$C1,$81,$40,
    $00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$00,$C1,$81,$40,
    $01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$01,$C0,$80,$41,
    $01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$01,$C0,$80,$41,
    $00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$00,$C1,$81,$40,
    $00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$00,$C1,$81,$40,
    $01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$01,$C0,$80,$41,
    $00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$00,$C1,$81,$40,
    $01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$01,$C0,$80,$41,
    $01,$C0,$80,$41,$00,$C1,$81,$40,$00,$C1,$81,$40,$01,$C0,$80,$41,
    $00,$C1,$81,$40,$01,$C0,$80,$41,$01,$C0,$80,$41,$00,$C1,$81,$40)
{
*****************************************************************************
*  Name    : Function Dalcrc16LU  Dallas/Maxim CRC16 SF Look Up Table       *
*  Date    : 12/31/2008                                                     *
*  Version : 1.0                                                            *
*  Notes   : Requires 27 cpu clocks                                         *
*          : Requires 2 256 byte tables DAL16HiTable and DAL16LoTable       *
*          : be in program memory                                           *
*****************************************************************************
}
Public Function DALcrc16LU(pDataByte As Byte,pCRC As Word) As Word
    Dim CRCLo As Byte
    Dim CRCHi As Byte
    Dim OldCRCHi As Byte
    CRCLo = pCRC.byte0
    CRCHi = pCRC.byte1
    OldCRCHi = CRCHi
    pDataByte = pDataByte Xor CRClo
    CRCHi = DAL16HiTable(pDataByte)
    CRCLo = DAL16LoTable(pDataByte)
    CRCLo = CRCLo Xor OldCRCHi
    Result.byte0 = CRCLo
    Result.byte1 = CRCHi
End Function

#elseif LUTable = SMB8
    Const SMB8Table(256) As Byte =
    ($00,$07,$0E,$09,$1C,$1B,$12,$15,$38,$3F,$36,$31,$24,$23,$2A,$2D,
    $70,$77,$7E,$79,$6C,$6B,$62,$65,$48,$4F,$46,$41,$54,$53,$5A,$5D,
    $E0,$E7,$EE,$E9,$FC,$FB,$F2,$F5,$D8,$DF,$D6,$D1,$C4,$C3,$CA,$CD,
    $90,$97,$9E,$99,$8C,$8B,$82,$85,$A8,$AF,$A6,$A1,$B4,$B3,$BA,$BD,
    $C7,$C0,$C9,$CE,$DB,$DC,$D5,$D2,$FF,$F8,$F1,$F6,$E3,$E4,$ED,$EA,
    $B7,$B0,$B9,$BE,$AB,$AC,$A5,$A2,$8F,$88,$81,$86,$93,$94,$9D,$9A,
    $27,$20,$29,$2E,$3B,$3C,$35,$32,$1F,$18,$11,$16,$03,$04,$0D,$0A,
    $57,$50,$59,$5E,$4B,$4C,$45,$42,$6F,$68,$61,$66,$73,$74,$7D,$7A,
    $89,$8E,$87,$80,$95,$92,$9B,$9C,$B1,$B6,$BF,$B8,$AD,$AA,$A3,$A4,
    $F9,$FE,$F7,$F0,$E5,$E2,$EB,$EC,$C1,$C6,$CF,$C8,$DD,$DA,$D3,$D4,
    $69,$6E,$67,$60,$75,$72,$7B,$7C,$51,$56,$5F,$58,$4D,$4A,$43,$44,
    $19,$1E,$17,$10,$05,$02,$0B,$0C,$21,$26,$2F,$28,$3D,$3A,$33,$34,
    $4E,$49,$40,$47,$52,$55,$5C,$5B,$76,$71,$78,$7F,$6A,$6D,$64,$63,
    $3E,$39,$30,$37,$22,$25,$2C,$2B,$06,$01,$08,$0F,$1A,$1D,$14,$13,
    $AE,$A9,$A0,$A7,$B2,$B5,$BC,$BB,$96,$91,$98,$9F,$8A,$8D,$84,$83,
    $DE,$D9,$D0,$D7,$C2,$C5,$CC,$CB,$E6,$E1,$E8,$EF,$FA,$FD,$F4,$F3)
{
*****************************************************************************
*  Name    : Function SMBcrc8LU  SMBus CRC8 SF look up table                *
*  Date    : 12/31/2008                                                     *
*  Version : 1.0                                                            *
*  Notes   : Requires 13 cpu clocks                                         *
*          : Requires the 256 byte table SMB8Table be in program memory     *
*****************************************************************************
}
Public Function SMBcrc8LU(pDataByte As Byte,PCRC As Byte) As Byte
    pDataByte = pDataByte Xor pCRC
    Result = SMB8Table(pDataByte)
End Function

#elseif LUTable = SHT8
    Const SHT8Table(256) As Byte =
    ($00,$31,$62,$53,$C4,$F5,$A6,$97,$B9,$88,$DB,$EA,$7D,$4C,$1F,$2E,
    $43,$72,$21,$10,$87,$B6,$E5,$D4,$FA,$CB,$98,$A9,$3E,$0F,$5C,$6D,
    $86,$B7,$E4,$D5,$42,$73,$20,$11,$3F,$0E,$5D,$6C,$FB,$CA,$99,$A8,
    $C5,$F4,$A7,$96,$01,$30,$63,$52,$7C,$4D,$1E,$2F,$B8,$89,$DA,$EB,
    $3D,$0C,$5F,$6E,$F9,$C8,$9B,$AA,$84,$B5,$E6,$D7,$40,$71,$22,$13,
    $7E,$4F,$1C,$2D,$BA,$8B,$D8,$E9,$C7,$F6,$A5,$94,$03,$32,$61,$50,
    $BB,$8A,$D9,$E8,$7F,$4E,$1D,$2C,$02,$33,$60,$51,$C6,$F7,$A4,$95,
    $F8,$C9,$9A,$AB,$3C,$0D,$5E,$6F,$41,$70,$23,$12,$85,$B4,$E7,$D6,
    $7A,$4B,$18,$29,$BE,$8F,$DC,$ED,$C3,$F2,$A1,$90,$07,$36,$65,$54,
    $39,$08,$5B,$6A,$FD,$CC,$9F,$AE,$80,$B1,$E2,$D3,$44,$75,$26,$17,
    $FC,$CD,$9E,$AF,$38,$09,$5A,$6B,$45,$74,$27,$16,$81,$B0,$E3,$D2,
    $BF,$8E,$DD,$EC,$7B,$4A,$19,$28,$06,$37,$64,$55,$C2,$F3,$A0,$91,
    $47,$76,$25,$14,$83,$B2,$E1,$D0,$FE,$CF,$9C,$AD,$3A,$0B,$58,$69,
    $04,$35,$66,$57,$C0,$F1,$A2,$93,$BD,$8C,$DF,$EE,$79,$48,$1B,$2A,
    $C1,$F0,$A3,$92,$05,$34,$67,$56,$78,$49,$1A,$2B,$BC,$8D,$DE,$EF,
    $82,$B3,$E0,$D1,$46,$77,$24,$15,$3B,$0A,$59,$68,$FF,$CE,$9D,$AC)
{
*****************************************************************************
*  Name    : Function SHTcrc8LU  Sensirion CRC8 SF look up table            *
*  Date    : 1/7/2009                                                       *
*  Version : 1.0                                                            *
*  Notes   : Requires 13 cpu clocks                                         *
*          : Requires the 256 byte table SHT8Table be in program memory     *
*****************************************************************************
}
Public Function SHTcrc8LU(pDataByte As Byte,PCRC As Byte) As Byte
    pDataByte = pDataByte Xor pCRC
    Result = SHT8Table(pDataByte)
End Function
#endif


{
*****************************************************************************
*  Name    : Function SHTcrc8SF  Sensirion CRC8 SwordFish                   *
*  Date    : 12/31/2008                                                     *
*  Version : 1.0                                                            *
*  Notes   : Requires a minimum 126 maximum 130 cpu clocks                  *
*          :                                                                *
*****************************************************************************
}
Public Function SHTcrcSF(pDataByte,pCRC As Byte) As Byte
    Dim BitNo As Byte
    Dim TestBit As Bit
    For BitNo = 0 To 7
        TestBit = pCRC.7 Xor pDataByte.7
        pDataByte = pDataByte << 1
        If TestBit = 0 GoTo No_XOR
        pCRC = pCRC Xor $18
No_XOR:
        pCRC = pCRC << 1
        pCRC.0 = TestBit
    Next
    Result = pCRC 
End Function

{
*****************************************************************************
*  Name    : Function SHTcrc8AL  Sensirion CRC8 SF encapsulataed assembly   *
*  Date    : 12/31/2008                                                     *
*  Version : 1.0                                                            *
*  Notes   : Requires a minimum 56 maximum 68 cpu clocks                    *
*          :                                                                *
*****************************************************************************
}
Public Function SHTcrcAL(pDataByte As D0,pCRC As D1) As Byte
//D0 through D3 (or through D23 if needed) are system variables available
//to assembly routines in subs or functions without concern for bank switching.
//Include system.bas to access them.
    Dim BitNo As D2
    Dim TempByte As D3
ASM
    MOVLW   8
    MOVWF   BitNo       ;//Do this For all 8 bits of DataByte
SHTCRCLOOP
    MOVF    pCRC,0      ;//Put CRC into W
    XORWF   pDataByte,0 ;//Xor CRC With TestByte
    MOVWF   TempByte    ;//Put results In TempByte
    RLCF    TempByte,1  ;//Shift TempByte.7 into Carry Bit
    BTFSS   STATUS,C    ;//If Carry = 1, do polynomial Math
    GoTo    SHTCRCSHIFT ;//Otherwise just Shift CRC And CRCByte
    MOVF    pCRC,0      ;//Get latest copy of CRC
    XORLW   0x18        ;//Compliment feedback bits
    MOVWF   pCRC        ;//Keep a copy of results
SHTCRCSHIFT
    RLCF    pCRC,1      ;//Rotate CRC into carry
    RLCF    pDataByte,1 ;//Rotate DataByte, carry shifts In but Not important
    DECFSZ  BitNo,1     ;//Keep track of #times through loop
    GoTo    SHTCRCLOOP  ;//Go To Start If Not looped through the 8 bits
End ASM
    Result = pCRC
End Function

{
*****************************************************************************
*  Name    : Function DALcrc8SF  Dallas/Maxim CRC8 SwordFish                *
*  Date    : 12/31/2008                                                     *
*  Version : 1.0                                                            *
*  Notes   : Requires a minimum 126 maximum 130 cpu clocks                  *
*          :                                                                *
*****************************************************************************
}
Public Function DALcrc8SF(pDataByte,pCRC As Byte) As Byte
    Dim BitNo As Byte
    Dim TestBit As Bit

    For BitNo = 0 To 7              //Do for all 8 bits in data byte
    TestBit = pCRC.0 Xor pDataByte.0//XOR bit0 of data byte and crc
    pDataByte = pDataByte >> 1      //Position data byte for next bit test
    If TestBit = 0 GoTo DalShift    //If test bit not set, just shift CRC
    pCRC = pCRC Xor $18             //If set, compliment feedback bits
DalShift:                           //Shift right the CRC byte
    pCRC = pCRC >> 1                //CRC bit 0 to bit bucket
    pCRC.7 = TestBit                //Test bit rotates into CRC bit 7
    Next
    Result = pCRC
End Function

{
*****************************************************************************
*  Name    : Function DALcrc8AL  Dallas/Maxim CRC8 SF encapuslated assembly *
*  Date    : 12/31/2008                                                     *
*  Version : 1.0                                                            *
*  Notes   : Requires a minimum 56 maximum 68 cpu clocks                    *
*          :                                                                *
*****************************************************************************
}
Public Function DALcrc8AL(pDataByte As D0,pCRC As D1) As Byte
    Dim BitNo As D2
    Dim TempByte As D3
ASM
    MOVLW 8
    MOVWF   BitNo       ;//Do this For all 8 bits
DALCRCLOOP
    MOVF    pCRC,0      ;//Put CRC into W
    XORWF   pDataByte,0 ;//Xor CRC With DataByte
    MOVWF   TempByte    ;//Put results in TempByte
    RRCF    TempByte,1  ;//Shift TempByte.0 into Carry Bit
    BTFSS   STATUS,C    ;//If Carry = 1, account for feedback gates
    GoTo    DALCRCSHIFT ;//Otherwise just shift CRC And TestByte
    MOVF    pCRC,0      ;//Get latest copy of CRC
    XORLW   0x18        ;//Compliment feedback bits
    MOVWF   pCRC        ;//Keep a copy of results
DALCRCSHIFT
    RRCF    pCRC,1      ;//Rotate CRC incorporating carry
    RRCF    pDataByte,1 ;//Rotate DataByte, carry shifts in but Not important
    DECFSZ  BitNo,1     ;//Keep track of #times through loop
    GoTo    DALCRCLOOP  ;//Go To start If Not looped through the 8 bits
End ASM
    Result = pCRC    
End Function

{
*****************************************************************************
*  Name    : Function DALcrc16SF  Dallas/Maxim CRC16 Swordfish              *
*  Date    : 12/31/2008                                                     *
*  Version : 1.0                                                            *
*  Notes   : Requires a minimum 133 maximum 201 cpu clocks                  *
*          :                                                                *
*****************************************************************************
}
Public Function DALcrc16SF(pDataByte As Byte,pCRC As Word) As Word
    Dim BitNo As Byte
    Dim TestBit As Bit
    For BitNo = 0 To 7                  //do for all 8 bits in Data Byte
    TestBit = pDataByte.0 Xor pCRC.0    //XOR bit0 of Data Byte and Low CRC
    pDataByte = pDataByte >> 1          //position Data Byte for next bit test
    If TestBit = 0 GoTo Dal16Shift      //if Test Bit not set, just shift CRC's
    pCRC.14 = pCRC.14 Xor 1             //if TestBit set, compliment bits 14
    pCRC.1 = pCRC.1 Xor 1               //and 1 of CRC (feedback bits)
Dal16Shift: 
    pCRC = pCRC >> 1                    //shift right the CRC word
    pCRC.15 = TestBit                   //replace bit 15 of CRC with TestBit
    Next
    Result = pCRC
End Function

{
*****************************************************************************
*  Name    : Function DALcrc16AL Dallas/Maxim CRC16 SF encapsulated assembly*
*  Date    : 12/31/2008                                                     *
*  Version : 1.0                                                            *
*  Notes   : Requires a minimum 65 maximum 89 cpu clocks                    *
*          :                                                                *
*****************************************************************************
}
Public Function Access DALcrc16AL(pDataByte As Byte,pCRC As Word) As Word
//couldn't use system variables here as pCRC needed to be passed as a word
//hence use of Access instead
    Dim CRCLo As Byte
    Dim CRCHi As Byte
    Dim BitNo As Byte
    Dim TestByte As Byte
    CRCLo = pCRC.byte0
    CRCHi = pCRC.byte1
ASM
    MOVLW   8
    MOVWF   BitNo          ;//Do this For all 8 bits of CRCByte
DAL16CRCLOOP
    MOVF    CRCLo,0        ;//Put CRCLo into W
    XORWF   pDataByte,0    ;//Xor CRCLo With CRCData
    MOVWF   TestByte       ;//Put results in TestByte
    RRCF    TestByte,1     ;//Shift TestByte.0 into Carry Bit
    BTFSS   STATUS,C       ;//If Carry = 1, account For EXOR feedback gates
    GoTo    DAL16CRCSHIFT  ;//Otherwise just shift CRCs And CRCByte
    MOVF    CRCHi,0        ;//Get latest copy of CRCHi
    XORLW   0x40           ;//Compliment CRCHi.6
    MOVWF   CRCHi          ;//Keep a copy of results
    MOVF    CRCLo,0        ;//Get latest copy of CRCL0
    XORLW   0x02           ;//Compliment CRCLo.1
    MOVWF   CRCLo          ;//Keep a copy of results
DAL16CRCSHIFT
    RRCF    CRCHi,1        ;//Rotate both CRCs As a Word, incorporate
    RRCF    CRCLo,1        ;//c flag into CRCHi.7
    RRCF    pDataByte,1    ;//Shift remaining data bits right once
    DECFSZ  BitNo,1        ;//Keep track of #times through loop
    GoTo    DAL16CRCLOOP   ;//Go To start If Not looped through the 8 bits
End ASM
    Result.byte0 = CRCLo
    Result.byte1 = CRCHi
End Function

{
*****************************************************************************
*  Name    : Function SMBcrc8SF  SMBus CRC8 SwordFish                       *
*  Date    : 12/31/2008                                                     *
*  Version : 1.0                                                            *
*  Notes   : Requires a minimum 55 maximum 67 cpu clocks                    *
*          :                                                                *
*****************************************************************************
}
Public Function SMBcrc8SF(pDataByte As Byte,pCRC As Byte) As Byte
    Dim BitNo As Byte
    pDataByte = pDataByte Xor pCRC          //xor new byte and old crc to get remainder + byte
    For BitNo = 0 To 7                      //check all 8 bits
        If pDataByte.7 =1 Then              //if bit 7 is a 1
            pDataByte = pDataByte << 1      //shift it out
            pDataByte = pDataByte Xor $07   //then xor with the polynomial
        Else                                //if the bit is not a 1
            pDataByte = pDataByte << 1      //just shift it out
        End If
    Next                                    //check next bit
    Result = pDataByte
End Function

{
*****************************************************************************
*  Name    : Function SMBcrc8AL  Sensirion CRC8 SF encapuslated assembly    *
*  Date    : 1/7/2009                                                       *
*  Version : 1.0                                                            *
*  Notes   : Requires a minimum 41 maximum 52 cpu clocks                    *
*          :                                                                *
*****************************************************************************
}
Public Function SMBcrc8AL(pDataByte As D0,pCRC As D1) As Byte
    Dim BitNo As D2
ASM
    MOVLW   8
    MOVWF   BitNo       ;//Do this For all 8 bits 
    MOVF    pCRC,0      ;//CRC to W
    XORWF   pDataByte,1 ;//Xor CRC With DataByte, result to DataByte
SMBCRCLOOP
    BCF     STATUS,0    ;//clear carry so zero will rotate in
    RLCF    pDataByte,1 ;//rotate results to DataByte, Bit 7 is in carry
    BTFSS   STATUS,0    ;//test bit 7
    GoTo    SMBCRCNOSHIFT ;//Otherwise just shift DataByte
    MOVF    pDataByte,0 ;//get working copy
    XORLW   0x07        ;//Compliment feedback bits
    MOVWF   pDataByte   ;//Keep a copy of results
SMBCRCNOSHIFT
    DECFSZ  BitNo,1     ;//Keep track of #times through loop
    GoTo    SMBCRCLOOP  ;//Go To start If Not looped through the 8 bits
End ASM
    Result = pDataByte    
End Function

{
*****************************************************************************
*  Name    : Function CCITTcrc16SF  CCITT CRC16 Swordfish                   *
*  Date    : 1/15/2009                                                      *
*  Version : 1.0                                                            *
*  Notes   : Normally CRC is initialized to $FFFF                           *
*          : X.25, v.41, CDMA, Bluetooth, XMODEM, HDLC, PPP, IrDA, BACnet,  *
*          : others?  please add if you know                                *
*****************************************************************************
}
Public Function CCITTcrc16SF(pDataByte As Byte,pCRC As Word) As Word
    Dim TempWord As Word
    Dim Index As Byte
    TempWord = pDataByte << 8
    pCRC = pCRC Xor TempWord
    For Index = 0 To 7
        If pCRC.15 = 1 Then
            pCRC = (PCRC << 1) Xor $1021
        Else
            pCRC = PCRC << 1
        End If
    Next
    Result = pCRC
End Function

{
*****************************************************************************
*  Name    : Function MODBUScrc16SF  MODBUS CRC16 Swordfish                 *
*  Date    : 1/15/2009                                                      *
*  Version : 1.0                                                            *
*  Notes   : Normally CRC is initialized to $FFFF                           *
*          :                                                                *
*****************************************************************************
}
Public Function MODBUScrc16SF(pDataByte As Byte,pCRC As Word) As Word
    Dim TempWord As Word
    Dim Index As Byte
    TempWord = $00FF And pDataByte
    pCRC = pCRC Xor TempWord
    For Index = 0 To 7
        If pCRC.0 = 1 Then
            pCRC = (pCRC >> 1) Xor $A001
        Else
            pCRC = pCRC >> 1
        End If
    Next
    Result = pCRC
End Function


{
*****************************************************************************
*  Name    : Function CRC16SF  CRC16 Swordfish                              *
*  Date    : 1/15/2009                                                      *
*  Version : 1.0                                                            *
*  Notes   : Normally CRC is initialized to $0                              *
*          : IBM, SDLC, USB, others?  please add if you know                *
*****************************************************************************
}
Public Function CRC16SF(pDataByte As Byte,pCRC As Word) As Word
    Dim TempWord As Word
    Dim Index As Byte
    TempWord = $00FF And pDataByte
    pCRC = pCRC Xor TempWord
    For Index = 0 To 7
        If pCRC.0 = 1 Then
            pCRC = (pCRC >> 1) Xor $A001
        Else
            pCRC = pCRC >> 1
        End If
    Next
    Result = pCRC
End Function