dkinzer Site Admin
Joined: 03 Sep 2005
Posts: 2499
Location: Portland, OR
|
|
Posted: 07 December 2005, 3:51 AM Post subject: CRC Routines |
|
|
The two attached files implement different CRC algorithms: CRC-16 and CRC-16/CCITT. Which algorithm you choose depends largely on the particulars of your application. For example, if you are interfacing with a device that uses a particular algorithm you'll need to use the same one. The CRC-16/CCITT implementation is faster due its unique approach that is effectively a parallel CRC computation. The CRC-16 implementation uses an iterative approach.
Both files are intended to be used as part of a larger project so there is no .pjt file included in the .zip files. However, for testing purposes each file has a Main() that implements a simple test case, computing the CRC value for a message and checking it against the expected result.
| Description: |
| CRC-16/CCITT Implementation |
|
 Download |
| Filename: |
crc_ccitt.zip |
| Filesize: |
6.97 KB |
| Downloaded: |
3678 Time(s) |
| Description: |
|
 Download |
| Filename: |
crc_16.zip |
| Filesize: |
7.78 KB |
| Downloaded: |
3707 Time(s) |
|
|
mikep
Joined: 24 Sep 2005
Posts: 765
Location: Austin, TX
|
|
Posted: 08 December 2005, 0:24 AM Post subject: |
|
|
I had a look at these two helper functions and have some comments:
- In crc_ccitt.bas, the calculation buffer crcBytes only needs to be 2 bytes long versus 4 bytes.
- I wanted to see what the overhead was of calling a separate function just to calculate the CRC for a single character at a time (crc_ccitt_byte) versus doing it all at once for a buffer. A performance test shows that for Don's test buffer the average execution time (1000 iterations) is 2.66ms versus 2.15 ms - a saving of 15% which is not that significant.
- However taking the buffer theme a little further, one use case for CRC calulations is to calculate the CRC for bytes as they are sent or received over some communication channel. There is an obvious relation that
| Code: | | CRC(b1) + CRC(b) = CRC(b1+b2) |
So I changed the signature and implementation of the calculation routine so that the "current" crc value can be passed in each time: | Code: | Public Sub crcBuffer(ByRef crcval as UnsignedInteger, ByRef dataBuf() as Byte, ByVal dataLen as UnsignedInteger)
' calculate for each byte in the data buffer
Dim idx as UnsignedInteger
For idx = 1 To DataLen
' define aliases for the result
Dim crcBytes(1 to 2) as Byte
Dim crcRes as UnsignedInteger Alias crcBytes(1)
Dim crcResL as Byte Alias crcBytes(1)
Dim crcResH as Byte Alias crcBytes(2)
' calculate the CRC and update the passed in value
crcResH = LoByte(crcval)
crcResL = dataBuf(idx) Xor HiByte(crcval)
crcResL = crcResL Xor Shr(crcResL, 4)
crcRes = crcRes Xor Shl(CUInt(crcResL), 5)
crcResH = crcResH Xor Shl(crcResL, 4)
crcval = crcRes
Next idx
End Sub | The code is 'stripped down' to save space in this message.
Here is some example test code (borrowed from Don's original) that calculates the CRC of two logical buffers and accumulates the result. The constant split is used to split the original buffer into the two parts.
| Code: | ' copy the test data to the buffer
Call GetEEPRom(crcTestData.DataAddress, buf, SizeOf(crcTestData))
const split as UnsignedInteger = 4
' compute the CRC value
crc = &Hffff
Call crcBuffer(crc, buf, split)
Call crcBuffer(crc, CbyteArray(memAddressu(buf)+split), CUInt(Sizeof(buf))-split)
|
|
|