crc16
Has anybody written code for crc16 (crc-ccitt)·and·is willing to share?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
WWW.HAPB.NET
"Don't ask yourself what the world needs - ask yourself what makes you come alive, and then go do it." - H.T.Whitman
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
WWW.HAPB.NET
"Don't ask yourself what the world needs - ask yourself what makes you come alive, and then go do it." - H.T.Whitman
Comments
The routine calculates the CRC on all data plus the CRC values and returns zero if the data is OK, non-zero on error. I haven't run it for a long time but I believe it was working properly.
PUB doCRC | byteloop, bitloop, crc_value, ccitt, xorflag, mask, data_value
crc_value := 14192 ccitt := 4129
repeat byteloop from 0 to 513 data_value := sectorbuffer[noparse][[/noparse]byteloop] mask := 128 repeat bitloop from 0 to 7
xorflag := crc_value & 32768 crc_value <<= 1 if data_value & mask <> 0 crc_value++ mask >>= 1 if xorflag <> 0 crc_value ^= ccitt crc_value &= 65535
return crc_value
{{ ************************************* * CRC16 - Uses CCITT polynomial * Copyright (c) 2009, John Steven Denson * See MIT license agreement terms at end of file ************************************* }} { add comment tick before first char of this line for demo. CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 var 'byte value[noparse][[/noparse]3] long r obj debug: "fullduplexserial" pub main | i Debug.start(31, 30, 0, 115200) 'Start the debug terminal waitcnt(clkfreq*2+cnt) init(CCITT_POLY) r := get(@value, strsize(@value), 0) debug.str(string($d,$d,"CCITT CRC16 INIT $0000 -> $")) debug.hex(r, 4) r := get(@value, strsize(@value), CRC_INIT) debug.str(string($d,"CCITT CRC16 INIT $FFFF -> $")) debug.hex(r, 4) r := get(@value, strsize(@value), $1d0f) debug.str(string($d,"CCITT CRC16 INIT $1D0F -> $")) debug.hex(r, 4) dat value byte "000501",0 '} CON { start with -1 to detect blank array mycrc := crc.get(dptr, bc#BIOS_DBASE_SIZE-2,CRC_INIT) } CRC_INIT = $FFFF CCITT_POLY = $1021 DAT long crc_table word 0 [noparse][[/noparse]16*16] PUB init(poly) | ii, jj, mcrc, c {{ initialize table using polynomial @param poly - bitstream representing polynomial ex: 0x8404 }} repeat ii from 0 to 255 mcrc~ c := (ii << 8) & CRC_INIT repeat jj from 0 to 7 if ( (mcrc ^ c) & $8000 ) mcrc := (mcrc << 1) ^ poly else mcrc <<= 1 c <<= 1 mcrc &= CRC_INIT word[noparse][[/noparse]@crc_table+ii<<1] := mcrc PUB get(msg, len, val) | ii {{ Get CRC for len msg with intial ival @param msg - byte array message @param len - number of bytes in msg array @param val - initial crc value ... normally $FFFF @returns CCITT CRC16 }} repeat ii from 0 to len-1 val := CRC(val, byte[noparse][[/noparse]msg+ii]) val &= CRC_INIT return val PUB hash(key, mlen, mmask) | len {{ Get a CRC16 based hash of key of maximum length mlen key using mmask. This function will not create a perfect hash for all data. Other algorithms must be used in addition to guarantee uniqueness for keys. @param key - key byte array string @param mlen - maximum number of bytes in msg array @param mmask - mask used to defin 2^N hash table size @returns CCITT CRC16 based hash }} len := strsize(key) if len => mlen ' just calculate over the first VLEN bytes len := mlen result := get(key, len, CRC_INIT) result &= mmask PRI CRC(crcval, ch) | ii ii := (crcval >> 8) ^ ch result := ((crcval << 8) ^ word[noparse][[/noparse]@crc_table + ii<<1]) & CRC_INIT {{ TERMS OF USE: MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. }}
Corrected version. Use your own polynomial for init if you like. Init must happen before CRC16 calculation. A demo is enclosed in { } above.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
Propalyzer: Propeller PC Logic Analyzer
http://forums.parallax.com/showthread.php?p=788230
Post Edited (jazzed) : 4/17/2009 10:32:12 PM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
WWW.HAPB.NET
"Don't ask yourself what the world needs - ask yourself what makes you come alive, and then go do it." - H.T.Whitman
I think I am using your program incorrectly.· I am assiging "get(...)" to a variable and I am getting the incorrect CRC.· I modified the top to do a simple test and the r = $E415 when it should equal $2348 according to a·online CRC calculator. (http://www.lammertbies.nl/comm/info/crc-calculation.html?crc=000501&method=hex)
{{ ************************************* * CRC16 - Uses CCITT polynomial ************************************* }} CON { start with -1 to detect blank array mycrc := crc.get(dptr, 1024, CRC_INIT) } _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 CRC_INIT = $FFFF var byte value[noparse][[/noparse]3] long r obj debug: "fullduplexserial" pub main | i waitcnt(clkfreq+cnt) value[noparse][[/noparse]0] := $00 value[noparse][[/noparse]1] := $05 value[noparse][[/noparse]2] := $01 Debug.start(31, 30, 0, 9600) 'Start the debug terminal r := get(value, 3, $FFFF) debug.hex(r, 4) DAT { Rest of the code is exactly what you provided. }
Can you set me straight?
Thanks
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
WWW.HAPB.NET
"Don't ask yourself what the world needs - ask yourself what makes you come alive, and then go do it." - H.T.Whitman
One thing to note is you would need to pass the value by reference as in: r := get(@value, 3, $ffff) .... still get the wrong value though.
I'll post a corrected and more flexible version sometime today.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
Propalyzer: Propeller PC Logic Analyzer
http://forums.parallax.com/showthread.php?p=788230
I have tried playing with the code you provided and I am unable to get the correct CRC based on CRC site is use (http://www.lammertbies.nl/comm/info/crc-calculation.html?crc=000501&method=hex).· I am probably using it incorrectly.· I have made some assumptions and adjusted the code:
·- adjust byteloop to fit data size
·- crc_value is the initial value
·- ccitt is the poly
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 var byte value[noparse][[/noparse]3] long r obj debug: "fullduplexserial" pub main | i waitcnt(clkfreq+cnt) value[noparse][[/noparse]0] := $00 value[noparse][[/noparse]1] := $05 value[noparse][[/noparse]2] := $01 Debug.start(31, 30, 0, 9600) 'Start the debug terminal r := doCRC debug.hex(r, 4) PUB doCRC | byteloop, bitloop, crc_value, ccitt, xorflag, mask, data_value crc_value := $FFFF ccitt := $1021 repeat byteloop from 0 to 2 data_value := value[noparse][[/noparse]byteloop] mask := 128 repeat bitloop from 0 to 7 xorflag := crc_value & 32768 crc_value <<= 1 if data_value & mask <> 0 crc_value++ mask >>= 1 if xorflag <> 0 crc_value ^= ccitt crc_value &= 65535 return crc_value
Can you provide guidance?
Thanks
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
WWW.HAPB.NET
"Don't ask yourself what the world needs - ask yourself what makes you come alive, and then go do it." - H.T.Whitman
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
Propalyzer: Propeller PC Logic Analyzer
http://forums.parallax.com/showthread.php?p=788230
When I was learning how to get the floppy CRC to work, I found lots of variations in how CRCs are calculated. Some routines initialize the crc_value to 0, some to $FFFF, some to some other number. Some implementations invert results at some stage, some don't. And there are lots of different polynomials in use.
Floppy disks seem to initialize the crc_value to 14197 for the crc on the floppy header and to 14192 for the crc that follows the 512 bytes of data, but I've never found any documentation explaining why this is the case.
I'll hack around with your example and see if I can get it to work, and post what I find in a day or so.
David
This is great! You should post it in the obex since there has not been a CRC16 routine until now. Thanks
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
WWW.HAPB.NET
"Don't ask yourself what the world needs - ask yourself what makes you come alive, and then go do it." - H.T.Whitman
It, of course, includes the crc16 code....