CRC Lookup Table Generation
Posted: 18 June 2010, 11:29 AM
In some circumstances, the iterative algorithm used by the built-in CRC16 and CRC32 functions may take too long for a particular application. In such cases, using a lookup table may provide the increase in speed that is needed. If you cannot find a lookup table for the particular CRC algorithm that you need, the code below can be used to generate the table if you know the Rocksoft model parameters for the CRC algorithm. The Rocksoft model parameters for some popular CRC algorithms can be found at http://regregex.bbcmicro.net/crc-catalogue.htm.
Code: Select all
#pragma warning(7:off)
'----------------------------------------------------------------------
'
' This code is intended to produce the data for a CRC lookup table
' in the form of an initialized ProgMem data table. The program
' is essentially a translation to ZBasic of the C code published
' by Ross Williams (see http://www.ross.net/crc/crcpaper.html).
' The code will only produce a suitable table for a CRC having
' Rocksoft model parameters refIn and refOut that are the same,
' either both True or both False. Only CRC widths 8, 16 and 32
' are supported.
'
' Once the program is configured (by modifying the Const definitions
' below), running it will output a 256-entry table. If you run
' this program in the ZBasic IDE, you can select the output using
' the mouse, copy it to the clipboard and then paste it into
' your program.
'
' This code is placed in the public domain by the author (Donald Kinzer)
' and may be used freely for any purpose. No warranty is made as to
' correctness nor as to suitability for any particular purpose. Use at
' your own risk.
'
'----------------------------------------------------------------------
'Rocksoft CRC model parameters
Private Const reflect as Boolean = False ' if the input (and output) are reflected
Private Const poly as UnsignedLong = &H31 ' the CRC polynomial
Private Const crcBits as Byte = 8 ' the number of bits in the CRC value
' output format control
Private Const hexFormat as Boolean = True ' if output shoud be in hexadecimal form
Private Const entriesPerLine as Byte = 16 ' number of entries per line in output
Sub Main()
If ((crcBits <> 8) And (crcBits <> 16) And (crcBits <> 32)) Then
Debug.Print "The CRC bit width must be 8, 16 or 32"
Else
' generate the lookup table
Dim i as UnsignedInteger
Dim entry as UnsignedLong
Dim cnt as Byte = 0
For i = 0 to 255
' compute and output an entry
entry = computeEntry(CByte(i))
Call outputEntry(entry)
' emit spacing, EOL, etc.
cnt = cnt + 1
If (i = 255) Then
Debug.Print
ElseIf (entriesPerLine > 1) And (cnt >= entriesPerLine) Then
Debug.Print ","
cnt = 0
Else
Debug.Print ", ";
End If
Next i
End If
End Sub
'
'' computeEntry
'
' Compute the Nth entry of the CRC lookup table.
'
Private Function computeEntry(ByVal n as Byte) as UnsignedLong
Const bitMask as UnsignedLong = Shl(1, crcBits - 1)
' compute the value of the entry
Dim val as UnsignedLong
If (reflect) Then
val = CULng(FlipBits(n))
Else
val = CULng(n)
End If
If (crcBits > 8) Then
val = Shl(val, crcBits - 8)
End If
Dim i as Byte
For i = 1 to 8
If ((val And bitMask) <> 0) Then
val = Shl(val, 1) Xor poly
Else
val = Shl(val, 1)
End If
Next i
computeEntry = val
End Function
'
'' outputEntry
'
' Output an entry of the CRC lookup table.
'
Private Sub outputEntry(ByVal entry as UnsignedLong)
' output the entry
Select Case crcBits
Case 8 ' 8-bit CRC
Dim val as Byte = LoByte(entry)
If (reflect) Then
val = FlipBits(val)
End If
If (hexFormat) Then
Debug.Print "&H"; CStrHex(val);
Else
Dim str as String = " " & CStr(val)
Debug.Print Right(str, 3);
End If
Case 16 ' 16-bit CRC
Dim val as UnsignedInteger = LoWord(entry)
If (reflect) Then
val = MakeWord(FlipBits(HiByte(val)), FlipBits(LoByte(val)))
End If
If (hexFormat) Then
Debug.Print "&H"; CStrHex(val);
Else
Dim str as String = " " & CStr(val)
Debug.Print Right(str, 5);
End If
Case 32 ' 32-bit CRC
If (reflect) Then
Dim lo as UnsignedInteger = HiWord(entry)
Dim hi as UnsignedInteger = LoWord(entry)
lo = MakeWord(FlipBits(HiByte(lo)), FlipBits(LoByte(lo)))
hi = MakeWord(FlipBits(HiByte(hi)), FlipBits(LoByte(hi)))
entry = MakeDWord(lo, hi)
End If
If (hexFormat) Then
Debug.Print "&H"; CStrHex(entry);
Else
Dim str as String = " " & CStr(entry)
Debug.Print Right(str, 10);
End If
End Select
End Sub