CRC16 with StringVector data creates random CRC

Discussion specific to the DIP and TQFP packaged ZX devices like the ZX-40, ZX-44, ZX-32 and ZX-328 series. The differences between these devices is primarily the packaging and pinout so most issues will apply to all devices.
Post Reply
drapal
Posts: 25
Joined: 24 January 2006, 8:07 AM
Location: Denver

CRC16 with StringVector data creates random CRC

Post by drapal »

Code Similar to following:

Code: Select all

Public xapKeys As StringVectorData ({
   "xap-header", 
   "xap-header.class", 
...
})

Dim i as Integer, s as String, crc As UnsignedInteger

For I = 1 to UBound(xapKeys)
  s = xapKeys(i)  ' Local copy because CRC16 can't handle StringVector
  crc = CRC16(s, Len(s), &h8005, 0, 0)
  Debug.Print CStrHex(crc)
Next

s = "xap-header.class"
crc = CRC16(s, Len(s), &h8005, 0, 0)
Debug.Print CStrHex(crc)

The two Debug.Print values give different CRC values. If I placed a:

Code: Select all

Debug.Print CStr(StrCompare(s, xapKeys(i)))
After the second Debug.Print, it shows that the two strings are the same.

Confused as always...
mikep
Posts: 796
Joined: 24 September 2005, 15:54 PM

Post by mikep »

In this case ZBasic did exactly what you told it to do and actually gave you the correct result. Unfortunately it didn't match what you intended and once again computers look stupid. I took the liberty of changing your code slightly to match the example CRC in the system library reference manual and applying a workaround to get the required result.

Code: Select all

Option TargetDevice zx24ae

Public xapKeys As StringVectorData ({
   "123456789",
   "xap-header.class"
})

Sub Main()

	Dim i as Integer, s as String, crc As UnsignedInteger
	Dim ba(1 to 20) as Byte

	For I = 1 to UBound(xapKeys)
		s = xapKeys(i)  ' Local copy because CRC16 can't handle StringVector
		Call GetProgMem(CLng(StrAddress(s)), ba , Len(s))
		crc = CRC16(ba, Len(s), &h8005, 0, CInt(zxCRCRefIn or zxCRCRefOut))
		Debug.Print CStrHex(crc)
	Next

	s = "123456789"
	Call GetProgMem(CLng(StrAddress(s)), ba , Len(s))
	crc = CRC16(ba, Len(s), &h8005, 0, CInt(zxCRCRefIn or zxCRCRefOut))
	Debug.Print CStrHex(crc)
End Sub
Here is what went wrong. The variable s does not contain a string, it contains a 4 byte string data structure as described in section 3.23.2 of the reference manual. If you use the library function StrType() you will find that the string is of type &he2 in both cases - i.e. it is stored in program memory. The constant string is not in RAM as you might expect - only its data structure.

CRC16 only works against RAM so your code calculated the CRC value of RAM memory starting at the address of the string data structure for s. Not surprisingly the result is different and even if you reduce the length down to 4 bytes it is still incorrect because the two strings have different program memory addresses.

The corrected program copies the string out of program memory into a RAM byte array. If you really need the CRC values for strings in program memory, it might be better to precalculate the CRC values and store them in an IntegerVectorData array.

BTW I changed the CRC flags from 0 to CInt(zxCRCRefIn or zxCRCRefOut) which is correct value for CRC16 calculation and gives the same result (0xbb3d) documented system library manual. The example code in the manual is incorrect and needs to be changed.
Mike Perks
drapal
Posts: 25
Joined: 24 January 2006, 8:07 AM
Location: Denver

Thanks, but this is very confusing...

Post by drapal »

I understand your changes to the code, but it's more that the manual entry that is a problem. I use the pop-up help in the IDE (mostly), and the pop-up says the first parameter is "ByRef data As AnyType" which is clearly not what was intended (Needs to say "ByRef data As Byte").
mikep
Posts: 796
Joined: 24 September 2005, 15:54 PM

Re: Thanks, but this is very confusing...

Post by mikep »

drapal wrote:I understand your changes to the code, but it's more that the manual entry that is a problem.
This one is up to Don. There are a number of different solutions to the problem now we understand it. The API documentation could be changed as you suggest or the implementation could be changed to work with Strings stored in program memory. Changing the API signature still requires testing and eventually shipping of a new ZBasic.api file for the IDE.

The documentation error in CRC16 also needs to be fixed.
Mike Perks
Post Reply