CRC 16 generation and confusion
Philip Gamblin
Posts: 202
This subject has come up a couple times, and was recently on the Javelin
Stamp list as well. Here's a bit of code I used in a Stamp-to-PC
program:
Calc_CRC:
crc = (crc & $FF00) | (aByte ^ (crc & $FF))
FOR idx = 0 TO 7
IF (crc.BIT0 = 0) THEN
crc = crc >> 1
ELSE
crc = (crc >> 1) ^ $A001
ENDIF
NEXT
RETURN
The crc value is initialized to $0000 before looping through the bytes
in the package, sending them one at a time to the Calc_CRC routine.
I'll post the other demo in the file section as that algorithm was
described and provided with a small packet and expected CRC (and yes,
the PBASIC implementation works).
-- Jon Williams
-- Applications Engineer, Parallax
-- Dallas Office
·Philip Gamblin's Program
' {$STAMP BS2}
' {$PBASIC 2.5}
' {$PORT COM4}
'SERIN Rpin {\Fpin}, Baudmode, {Plabel,} {Timeout, Tlabel,} [noparse][[/noparse]InputData]
'SEROUT Tpin {\Fpin}, Baudmode, {Pace,} {Timeout, Tlabel,} [noparse][[/noparse]OutputData]
start:
······· cntr············ VAR··········· Byte
······· x··············· VAR··········· Byte
······· IO·············· VAR··········· Byte
······· IO1············· VAR··········· Byte
······· IO2············· VAR··········· Byte
······· addr············ VAR··········· Byte
······· funct··········· VAR··········· Byte
······· bytecnt········· VAR··········· Byte
······· RecDat·········· VAR··········· Byte(10)
······· Tx_CRC·········· VAR··········· Word
······· CRC_Reg········· VAR··········· Word
······· crclo··········· VAR··········· Byte
······· crchi··········· VAR··········· Byte
······· 'LSB············· VAR··········· Tx_CRC.LOWBIT''
' initialize VARs
······ IO = $AA
······ IO1 = $FF
······ IO2 =$AA
Chirp:
······· FREQOUT 0,500,3500
······· PAUSE 500
DatIn:
······· SERIN 2\10,396,[noparse][[/noparse]WAIT(":"),RecDat(0),RecDat(1),RecDat(2),RecDat(3),· 'Receive data to array
··················· RecDat(4),RecDat(5),RecDat(6),RecDat(7)]
······· Tx_Crc.LOWBYTE =· RecDat(7)········································ 'capture the Master CRC
······· Tx_CRC.HIGHBYTE = RecDat(6)
······· CRC_Reg=$FFFF························································· ·· 'Reset CRC_Reg
······· 'GOSUB CRC_Gen······················································· ··· 'Skipped the routine
··························································································· · 'because it doesn't work
······· PAUSE 200
········ IF RecDat(0)<$7e OR RecDat(0)>$7e THEN Chirp··················' Chirp is address is wrong
······· SEROUT 16,396,[noparse][[/noparse]":",$7e,funct,bytecnt,IO2,IO1,IO,crclo,crchi]
'DEBUG"*****************************************",CR
'DEBUG HEX2 ? addr,CR
'DEBUG HEX2 ? dataddrhi,CR
'DEBUG HEX2 ? dataddrlo,CR
'DEBUG HEX2 ? ptshi,CR
'DEBUG HEX2 ? ptslo,CR
'DEBUG HEX2 ? crchi,CR
'DEBUG HEX2 ? crclo,CR
' DEBUG HEX2?IO
CRC_Gen:
···········
········· FOR x= 0 TO 5······························ ···· 'this counter is for the 5 bytes in the Master Message
············ ·CRC_Reg.LOWBYTE=(CRC_Reg.LOWBYTE ^ RecDat(x)) '
·············· FOR Cntr = 1 TO 8
·············· CRC_Reg=CRC_Reg>>1
·············· CRC_Reg.BIT15=0
········································
·············· ·SELECT CRC_Reg.BIT0
··················· CASE = 0
······················· CRC_Reg=CRC_Reg/2
······················· CRC_Reg.BIT15=0
··················· CASE =1
······················· CRC_Reg= CRC_Reg ^ $A001
··············· ENDSELECT
············ · NEXT
······· ··· NEXT
········ '· DEBUG HEX4? CRC_Reg
········ '· DEBUG HEX2? RecDat(0)
········ '· DEBUG HEX2? RecDat(1)
········ '· DEBUG HEX2? RecDat(2)
········ '· DEBUG HEX2? RecDat(3)
········ '· DEBUG HEX2? RecDat(4)
········ '· DEBUG HEX2? RecDat(5)
········· ' DEBUG HEX2? RecDat(6)
········· ' DEBUG HEX2? RecDat(7)
········· ' DEBUG HEX4? Tx_CRC
·········· 'DEBUG HEX2? RecDat(8)
······ ' GOTO DatIn
·
Stamp list as well. Here's a bit of code I used in a Stamp-to-PC
program:
Calc_CRC:
crc = (crc & $FF00) | (aByte ^ (crc & $FF))
FOR idx = 0 TO 7
IF (crc.BIT0 = 0) THEN
crc = crc >> 1
ELSE
crc = (crc >> 1) ^ $A001
ENDIF
NEXT
RETURN
The crc value is initialized to $0000 before looping through the bytes
in the package, sending them one at a time to the Calc_CRC routine.
I'll post the other demo in the file section as that algorithm was
described and provided with a small packet and expected CRC (and yes,
the PBASIC implementation works).
-- Jon Williams
-- Applications Engineer, Parallax
-- Dallas Office
·Philip Gamblin's Program
' {$STAMP BS2}
' {$PBASIC 2.5}
' {$PORT COM4}
'SERIN Rpin {\Fpin}, Baudmode, {Plabel,} {Timeout, Tlabel,} [noparse][[/noparse]InputData]
'SEROUT Tpin {\Fpin}, Baudmode, {Pace,} {Timeout, Tlabel,} [noparse][[/noparse]OutputData]
start:
······· cntr············ VAR··········· Byte
······· x··············· VAR··········· Byte
······· IO·············· VAR··········· Byte
······· IO1············· VAR··········· Byte
······· IO2············· VAR··········· Byte
······· addr············ VAR··········· Byte
······· funct··········· VAR··········· Byte
······· bytecnt········· VAR··········· Byte
······· RecDat·········· VAR··········· Byte(10)
······· Tx_CRC·········· VAR··········· Word
······· CRC_Reg········· VAR··········· Word
······· crclo··········· VAR··········· Byte
······· crchi··········· VAR··········· Byte
······· 'LSB············· VAR··········· Tx_CRC.LOWBIT''
' initialize VARs
······ IO = $AA
······ IO1 = $FF
······ IO2 =$AA
Chirp:
······· FREQOUT 0,500,3500
······· PAUSE 500
DatIn:
······· SERIN 2\10,396,[noparse][[/noparse]WAIT(":"),RecDat(0),RecDat(1),RecDat(2),RecDat(3),· 'Receive data to array
··················· RecDat(4),RecDat(5),RecDat(6),RecDat(7)]
······· Tx_Crc.LOWBYTE =· RecDat(7)········································ 'capture the Master CRC
······· Tx_CRC.HIGHBYTE = RecDat(6)
······· CRC_Reg=$FFFF························································· ·· 'Reset CRC_Reg
······· 'GOSUB CRC_Gen······················································· ··· 'Skipped the routine
··························································································· · 'because it doesn't work
······· PAUSE 200
········ IF RecDat(0)<$7e OR RecDat(0)>$7e THEN Chirp··················' Chirp is address is wrong
······· SEROUT 16,396,[noparse][[/noparse]":",$7e,funct,bytecnt,IO2,IO1,IO,crclo,crchi]
'DEBUG"*****************************************",CR
'DEBUG HEX2 ? addr,CR
'DEBUG HEX2 ? dataddrhi,CR
'DEBUG HEX2 ? dataddrlo,CR
'DEBUG HEX2 ? ptshi,CR
'DEBUG HEX2 ? ptslo,CR
'DEBUG HEX2 ? crchi,CR
'DEBUG HEX2 ? crclo,CR
' DEBUG HEX2?IO
CRC_Gen:
···········
········· FOR x= 0 TO 5······························ ···· 'this counter is for the 5 bytes in the Master Message
············ ·CRC_Reg.LOWBYTE=(CRC_Reg.LOWBYTE ^ RecDat(x)) '
·············· FOR Cntr = 1 TO 8
·············· CRC_Reg=CRC_Reg>>1
·············· CRC_Reg.BIT15=0
········································
·············· ·SELECT CRC_Reg.BIT0
··················· CASE = 0
······················· CRC_Reg=CRC_Reg/2
······················· CRC_Reg.BIT15=0
··················· CASE =1
······················· CRC_Reg= CRC_Reg ^ $A001
··············· ENDSELECT
············ · NEXT
······· ··· NEXT
········ '· DEBUG HEX4? CRC_Reg
········ '· DEBUG HEX2? RecDat(0)
········ '· DEBUG HEX2? RecDat(1)
········ '· DEBUG HEX2? RecDat(2)
········ '· DEBUG HEX2? RecDat(3)
········ '· DEBUG HEX2? RecDat(4)
········ '· DEBUG HEX2? RecDat(5)
········· ' DEBUG HEX2? RecDat(6)
········· ' DEBUG HEX2? RecDat(7)
········· ' DEBUG HEX4? Tx_CRC
·········· 'DEBUG HEX2? RecDat(8)
······ ' GOTO DatIn
·
Comments
Post Edited (Philip Gamblin) : 12/7/2005 5:14:55 PM GMT