469,287 Members | 2,709 Online

# Help in translating a few lines of C

I have a customer that we need to send data files to using their
format. Below is a C routine they sent us for computing a CRC. I
tranlated it to the best of my ability to VB6 but can't reproduce their
results.

Here is the C routine.

#define CRC16_POLYNOMIAL 0xA001
crc16(INT16U byte, INT16U crc)
{
INT16U i;
INT16U crc_bit16;
for (i=0;<8;i++)
{
crc_bit16=((crc&0x01)^(byte&0x01));
crc=crc>>1;
if (crc_bit16)
{
crc=(crc^CRC16_POLYNOMIAL);
}
byte=byte>>1;
}
return(crc);
}

Here is my VB6 code

Function CRC(CRCIn As Long, ByteIn As Byte) As Long

Const CRC16Polynomial = &HA001
Dim CRCBit16 As Integer
Dim I As Integer
Dim WrkByte As Integer
Dim WrkCRC As Long

WrkByte = ByteIn
WrkCRC = CRCIn
For I = 0 To 7
CRCBit16 = ((WrkCRC And &H1) Xor (WrkByte And &H1))
WrkCRC = ShiftRight(WrkCRC, 1)
If CRCBit16 <> 0 Then
WrkCRC = (WrkCRC Xor CRC16Polynomial)
End If
WrkByte = ShiftRight(WrkByte, 1)
Next I
CRC = WrkCRC

END Function

And here is the routine that passes each byte through the CRC routine.

CRCIn = 0
CRC16 = 0
Open "C:\vbasic\shift.src\Page0.bin" For Binary As #1
For I = 1 To 30
A\$ = Input(1, 1)
ByteIn = Asc(A\$)
CRCIn = CRC16
CRC16 = CRC(CRCIn, ByteIn)
Next I

Page0.bin is a small 32 byte file as shown below. The last 2 bytes are
the CRC as computed by my customers C routine. From looking through
more of their code it appears the CRC is stored as an inverse for some
reason using C's ~ inverse operator.

31 07 49 6E 73 74 72 6F
6E 06 49 6E 53 70 65 63
FF FF FF FF FF FF FF FF
FF FF FF FF FF FF 19 95

I thought the source of the error is in my ShiftRight routine. I tried
roughly 6 different routines claiming to be C's >> equivelent and always
get the same results. Any help is appreciated.

Jul 17 '05 #1
17 5047 milesh wrote:
I have a customer that we need to send data files to using their
format. Below is a C routine they sent us for computing a CRC. I
tranlated it to the best of my ability to VB6 but can't reproduce their
results.

Here is the C routine.

<snip>

Some people might eventually answer this question, but I think it would
also be appropriate to post in comp.programming as well.

Jul 17 '05 #2
Where is the shiftright routine?

Show us the code!

Cheers
A.

"milesh" <mi****@unlistedspam.com> wrote in message
news:bm*******@dispatch.concentric.net...
I have a customer that we need to send data files to using their
format. Below is a C routine they sent us for computing a CRC. I
tranlated it to the best of my ability to VB6 but can't reproduce their
results.

Here is the C routine.

#define CRC16_POLYNOMIAL 0xA001
crc16(INT16U byte, INT16U crc)
{
INT16U i;
INT16U crc_bit16;
for (i=0;<8;i++)
{
crc_bit16=((crc&0x01)^(byte&0x01));
crc=crc>>1;
if (crc_bit16)
{
crc=(crc^CRC16_POLYNOMIAL);
}
byte=byte>>1;
}
return(crc);
}

Here is my VB6 code

Function CRC(CRCIn As Long, ByteIn As Byte) As Long

Const CRC16Polynomial = &HA001
Dim CRCBit16 As Integer
Dim I As Integer
Dim WrkByte As Integer
Dim WrkCRC As Long

WrkByte = ByteIn
WrkCRC = CRCIn
For I = 0 To 7
CRCBit16 = ((WrkCRC And &H1) Xor (WrkByte And &H1))
WrkCRC = ShiftRight(WrkCRC, 1)
If CRCBit16 <> 0 Then
WrkCRC = (WrkCRC Xor CRC16Polynomial)
End If
WrkByte = ShiftRight(WrkByte, 1)
Next I
CRC = WrkCRC

END Function

And here is the routine that passes each byte through the CRC routine.

CRCIn = 0
CRC16 = 0
Open "C:\vbasic\shift.src\Page0.bin" For Binary As #1
For I = 1 To 30
A\$ = Input(1, 1)
ByteIn = Asc(A\$)
CRCIn = CRC16
CRC16 = CRC(CRCIn, ByteIn)
Next I

Page0.bin is a small 32 byte file as shown below. The last 2 bytes are
the CRC as computed by my customers C routine. From looking through
more of their code it appears the CRC is stored as an inverse for some
reason using C's ~ inverse operator.

31 07 49 6E 73 74 72 6F
6E 06 49 6E 53 70 65 63
FF FF FF FF FF FF FF FF
FF FF FF FF FF FF 19 95

I thought the source of the error is in my ShiftRight routine. I tried
roughly 6 different routines claiming to be C's >> equivelent and always
get the same results. Any help is appreciated.

Jul 17 '05 #3
It might be that "INT16U" not corresopnds to VB:s "int". int16u is
possible a 16 bit unsigned integer, it might be declared like this
somewhere in their code: "typedef unsigned int int16u;" or maybe they
uses "systemC".

This might give you problem width the rightShift. For unsigned values,
the left most bit is always replaced with zeros after shift, but if
the value is signed, the left most bit is either replaced by ones (if
the leftmost bit is a one before the shift) or zeros (if the left most
bit is a zero before the shift). So, you need not an int, but an
unsigned int with 16 bytes. (I think vb int is 32 bit?)

If this can't be achived by vb, then you should implement your own
shift routine. A strange this is, that if vb int is 32 bits, this
should have no effect, and everythis should work out fine (if you do
less than 16 shifts)... (If int is 16 bit in vb, try first to replace
milesh <mi****@unlistedspam.com> wrote in message news:<bm*******@dispatch.concentric.net>...
I have a customer that we need to send data files to using their
format. Below is a C routine they sent us for computing a CRC. I
tranlated it to the best of my ability to VB6 but can't reproduce their
results.

Here is the C routine.

#define CRC16_POLYNOMIAL 0xA001
crc16(INT16U byte, INT16U crc)
{
INT16U i;
INT16U crc_bit16;
for (i=0;<8;i++)
{
crc_bit16=((crc&0x01)^(byte&0x01));
crc=crc>>1;
if (crc_bit16)
{
crc=(crc^CRC16_POLYNOMIAL);
}
byte=byte>>1;
}
return(crc);
}

Here is my VB6 code

Function CRC(CRCIn As Long, ByteIn As Byte) As Long

Const CRC16Polynomial = &HA001
Dim CRCBit16 As Integer
Dim I As Integer
Dim WrkByte As Integer
Dim WrkCRC As Long

WrkByte = ByteIn
WrkCRC = CRCIn
For I = 0 To 7
CRCBit16 = ((WrkCRC And &H1) Xor (WrkByte And &H1))
WrkCRC = ShiftRight(WrkCRC, 1)
If CRCBit16 <> 0 Then
WrkCRC = (WrkCRC Xor CRC16Polynomial)
End If
WrkByte = ShiftRight(WrkByte, 1)
Next I
CRC = WrkCRC

END Function

And here is the routine that passes each byte through the CRC routine.

CRCIn = 0
CRC16 = 0
Open "C:\vbasic\shift.src\Page0.bin" For Binary As #1
For I = 1 To 30
A\$ = Input(1, 1)
ByteIn = Asc(A\$)
CRCIn = CRC16
CRC16 = CRC(CRCIn, ByteIn)
Next I

Page0.bin is a small 32 byte file as shown below. The last 2 bytes are
the CRC as computed by my customers C routine. From looking through
more of their code it appears the CRC is stored as an inverse for some
reason using C's ~ inverse operator.

31 07 49 6E 73 74 72 6F
6E 06 49 6E 53 70 65 63
FF FF FF FF FF FF FF FF
FF FF FF FF FF FF 19 95

I thought the source of the error is in my ShiftRight routine. I tried
roughly 6 different routines claiming to be C's >> equivelent and always
get the same results. Any help is appreciated.

Jul 17 '05 #4
On 17 Oct 2003 00:34:35 -0700, d9****@efd.lth.se (Andreas) wrote:
It might be that "INT16U" not corresopnds to VB:s "int". int16u is
possible a 16 bit unsigned integer, it might be declared like this
somewhere in their code: "typedef unsigned int int16u;" or maybe they
uses "systemC".

This might give you problem width the rightShift. For unsigned values,
the left most bit is always replaced with zeros after shift, but if
the value is signed, the left most bit is either replaced by ones (if
the leftmost bit is a one before the shift) or zeros (if the left most
bit is a zero before the shift). So, you need not an int, but an
unsigned int with 16 bytes. (I think vb int is 32 bit?) VB Int is 16 bit
If this can't be achived by vb, then you should implement your own
shift routine. A strange this is, that if vb int is 32 bits, this
should have no effect, and everythis should work out fine (if you do
less than 16 shifts)... (If int is 16 bit in vb, try first to replace
your integers width long.) Or use a UDT - shove the low bytes into a 4 byte UDT
then Lset that into a UDT holding a Long, and multiply the Long by
two

milesh <mi****@unlistedspam.com> wrote in message news:<bm*******@dispatch.concentric.net>...
I have a customer that we need to send data files to using their
format. Below is a C routine they sent us for computing a CRC. I
tranlated it to the best of my ability to VB6 but can't reproduce their
results.

Here is the C routine.

#define CRC16_POLYNOMIAL 0xA001
crc16(INT16U byte, INT16U crc)
{
INT16U i;
INT16U crc_bit16;
for (i=0;<8;i++)
{
crc_bit16=((crc&0x01)^(byte&0x01));
crc=crc>>1;
if (crc_bit16)
{
crc=(crc^CRC16_POLYNOMIAL);
}
byte=byte>>1;
}
return(crc);
}

Here is my VB6 code

Function CRC(CRCIn As Long, ByteIn As Byte) As Long

Const CRC16Polynomial = &HA001
Dim CRCBit16 As Integer
Dim I As Integer
Dim WrkByte As Integer
Dim WrkCRC As Long

WrkByte = ByteIn
WrkCRC = CRCIn
For I = 0 To 7
CRCBit16 = ((WrkCRC And &H1) Xor (WrkByte And &H1))
WrkCRC = ShiftRight(WrkCRC, 1)
If CRCBit16 <> 0 Then
WrkCRC = (WrkCRC Xor CRC16Polynomial)
End If
WrkByte = ShiftRight(WrkByte, 1)
Next I
CRC = WrkCRC

END Function

And here is the routine that passes each byte through the CRC routine.

CRCIn = 0
CRC16 = 0
Open "C:\vbasic\shift.src\Page0.bin" For Binary As #1
For I = 1 To 30
A\$ = Input(1, 1)
ByteIn = Asc(A\$)
CRCIn = CRC16
CRC16 = CRC(CRCIn, ByteIn)
Next I

Page0.bin is a small 32 byte file as shown below. The last 2 bytes are
the CRC as computed by my customers C routine. From looking through
more of their code it appears the CRC is stored as an inverse for some
reason using C's ~ inverse operator.

31 07 49 6E 73 74 72 6F
6E 06 49 6E 53 70 65 63
FF FF FF FF FF FF FF FF
FF FF FF FF FF FF 19 95

I thought the source of the error is in my ShiftRight routine. I tried
roughly 6 different routines claiming to be C's >> equivelent and always
get the same results. Any help is appreciated.

Jul 17 '05 #5

Aristotelis E. Charalampakis wrote:
Where is the shiftright routine?

Show us the code!

All seemed to produce the same results so I'm not sure if thats where
the problem is. I keep thinking I must be overlooking something really
simple.

Jul 17 '05 #6
What do you get instead? It is difficult to identify a bug if you don't what the
output is, as well as what it should be. Maybe you are getting all zeros? Doubt
it, but don't know what you are getting.

"milesh" <mi****@unlistedspam.com> wrote in message
news:bm*******@dispatch.concentric.net...
I have a customer that we need to send data files to using their
format. Below is a C routine they sent us for computing a CRC. I
tranlated it to the best of my ability to VB6 but can't reproduce their
results.

Here is the C routine.

#define CRC16_POLYNOMIAL 0xA001
crc16(INT16U byte, INT16U crc)
{
INT16U i;
INT16U crc_bit16;
for (i=0;<8;i++)
{
crc_bit16=((crc&0x01)^(byte&0x01));
crc=crc>>1;
if (crc_bit16)
{
crc=(crc^CRC16_POLYNOMIAL);
}
byte=byte>>1;
}
return(crc);
}

Here is my VB6 code

Function CRC(CRCIn As Long, ByteIn As Byte) As Long

Const CRC16Polynomial = &HA001
Dim CRCBit16 As Integer
Dim I As Integer
Dim WrkByte As Integer
Dim WrkCRC As Long

WrkByte = ByteIn
WrkCRC = CRCIn
For I = 0 To 7
CRCBit16 = ((WrkCRC And &H1) Xor (WrkByte And &H1))
WrkCRC = ShiftRight(WrkCRC, 1)
If CRCBit16 <> 0 Then
WrkCRC = (WrkCRC Xor CRC16Polynomial)
End If
WrkByte = ShiftRight(WrkByte, 1)
Next I
CRC = WrkCRC

END Function

And here is the routine that passes each byte through the CRC routine.

CRCIn = 0
CRC16 = 0
Open "C:\vbasic\shift.src\Page0.bin" For Binary As #1
For I = 1 To 30
A\$ = Input(1, 1)
ByteIn = Asc(A\$)
CRCIn = CRC16
CRC16 = CRC(CRCIn, ByteIn)
Next I

Page0.bin is a small 32 byte file as shown below. The last 2 bytes are
the CRC as computed by my customers C routine. From looking through
more of their code it appears the CRC is stored as an inverse for some
reason using C's ~ inverse operator.

31 07 49 6E 73 74 72 6F
6E 06 49 6E 53 70 65 63
FF FF FF FF FF FF FF FF
FF FF FF FF FF FF 19 95

I thought the source of the error is in my ShiftRight routine. I tried
roughly 6 different routines claiming to be C's >> equivelent and always
get the same results. Any help is appreciated.

Jul 17 '05 #7

Steve Gerrard wrote:
What do you get instead? It is difficult to identify a bug if you don't what the
output is, as well as what it should be. Maybe you are getting all zeros? Doubt
it, but don't know what you are getting.

The original post showed what I should get. The last 2 bytes of the 32
byte data. No, not getting all 0's, just not the 19 95 that I should.
I'm not at work now and don't have VB6 on this computer but will post
the result I get. I was hoping someone is skilled at both VB6 and C++
and could see what I may have translated wrong as I do not know C at
all. Just looked up the areas of question. My guess is that it has
something to do with C's unsigned integers and how that plays in with
C's >> shiftright routine. I understand how C handles it but not sure
how to translate it to VB6.

Jul 17 '05 #8

"Miles" <un*****@unlistedspam.com> wrote in message

Steve Gerrard wrote:
What do you get instead? It is difficult to identify a bug if you don't what the output is, as well as what it should be. Maybe you are getting all zeros? Doubt it, but don't know what you are getting.

The original post showed what I should get. The last 2 bytes of the 32
byte data. No, not getting all 0's, just not the 19 95 that I should.
I'm not at work now and don't have VB6 on this computer but will post
the result I get. I was hoping someone is skilled at both VB6 and C++
and could see what I may have translated wrong as I do not know C at
all. Just looked up the areas of question. My guess is that it has
something to do with C's unsigned integers and how that plays in with
C's >> shiftright routine. I understand how C handles it but not sure
how to translate it to VB6.

Found the snag. Your definition of the const in the VB version produces a
negative number, not the intended value:
Const CRC16Polynomial = &HA001 ' equals -24575 in VB, not 40961 as
desired.

Note that in addition to inverting all the bits at the end, the CRC is stored in
your sample file in low byte, high byte order (i.e. flipped), a common practice.
The following modified version of your VB code produces a CRC of H9519, as
desired:

Private Sub Command1_Click()
Dim I As Integer
Dim CRC32 As Long
Dim CRC16 As Integer
Dim ByteIn As Byte
Dim A As String
Dim strIn() As String

Const Test As String = "&H31, &H07, &H49, &H6E, &H73, &H74, &H72, &H6F, &H6E,
&H06, &H49, &H6E, &H53, &H70, &H65, &H63, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF,
&HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF"

strIn = Split(Test, ",")

CRC32 = 0
For I = 0 To 29
A = strIn(I)
ByteIn = CInt(A)
CRC32 = CRC(CRC32, ByteIn)
Next I

'invert all bits
CRC32 = (CRC32 Xor &HFFFF)
'now get the 16 bit version
CRC16 = CRC32
Debug.Print CRC16, Hex(CRC16)

End Sub

Function CRC(CRCIn As Long, ByteIn As Byte) As Long

Const CRC16Polynomial As Long = 40961
Dim Bit As Boolean
Dim I As Integer
Dim WrkByte As Integer
Dim WrkCRC As Long

WrkByte = ByteIn
WrkCRC = CRCIn
For I = 0 To 7
Bit = ((WrkCRC And &H1) Xor (WrkByte And &H1))
WrkCRC = WrkCRC \ 2 'this is fine for shift right 1 bit
If Bit Then
WrkCRC = (WrkCRC Xor CRC16Polynomial)
End If
WrkByte = WrkByte \ 2
Next I
CRC = WrkCRC

End Function

That was fun.
Steve

Jul 17 '05 #9

Steve Gerrard wrote:
"Miles" <un*****@unlistedspam.com> wrote in message

Steve Gerrard wrote:
What do you get instead? It is difficult to identify a bug if you don't what
the
output is, as well as what it should be. Maybe you are getting all zeros?
Doubt
it, but don't know what you are getting.

The original post showed what I should get. The last 2 bytes of the 32
byte data. No, not getting all 0's, just not the 19 95 that I should.
I'm not at work now and don't have VB6 on this computer but will post
the result I get. I was hoping someone is skilled at both VB6 and C++
and could see what I may have translated wrong as I do not know C at
all. Just looked up the areas of question. My guess is that it has
something to do with C's unsigned integers and how that plays in with
C's >> shiftright routine. I understand how C handles it but not sure
how to translate it to VB6.

Found the snag. Your definition of the const in the VB version produces a
negative number, not the intended value:
Const CRC16Polynomial = &HA001 ' equals -24575 in VB, not 40961 as
desired.

Note that in addition to inverting all the bits at the end, the CRC is stored in
your sample file in low byte, high byte order (i.e. flipped), a common practice.
The following modified version of your VB code produces a CRC of H9519, as
desired:

Private Sub Command1_Click()
Dim I As Integer
Dim CRC32 As Long
Dim CRC16 As Integer
Dim ByteIn As Byte
Dim A As String
Dim strIn() As String

Const Test As String = "&H31, &H07, &H49, &H6E, &H73, &H74, &H72, &H6F, &H6E,
&H06, &H49, &H6E, &H53, &H70, &H65, &H63, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF,
&HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF"

strIn = Split(Test, ",")

CRC32 = 0
For I = 0 To 29
A = strIn(I)
ByteIn = CInt(A)
CRC32 = CRC(CRC32, ByteIn)
Next I

'invert all bits
CRC32 = (CRC32 Xor &HFFFF)
'now get the 16 bit version
CRC16 = CRC32
Debug.Print CRC16, Hex(CRC16)

End Sub

Function CRC(CRCIn As Long, ByteIn As Byte) As Long

Const CRC16Polynomial As Long = 40961
Dim Bit As Boolean
Dim I As Integer
Dim WrkByte As Integer
Dim WrkCRC As Long

WrkByte = ByteIn
WrkCRC = CRCIn
For I = 0 To 7
Bit = ((WrkCRC And &H1) Xor (WrkByte And &H1))
WrkCRC = WrkCRC \ 2 'this is fine for shift right 1 bit
If Bit Then
WrkCRC = (WrkCRC Xor CRC16Polynomial)
End If
WrkByte = WrkByte \ 2
Next I
CRC = WrkCRC

End Function

That was fun.
Steve

Jul 17 '05 #10

Steve Gerrard wrote:
Found the snag. Your definition of the const in the VB version produces a
negative number, not the intended value:
Const CRC16Polynomial = &HA001 ' equals -24575 in VB, not 40961 as
desired.
WrkCRC = WrkCRC \ 2 'this is fine for shift right 1 bit

I had seen several shift right routines for VB6. All were more complex
because they took into account the sign bit shifting as C's >> does so
thats why I didn't simply try \ 2. Not having unsigned integers in VB6
is sometimes a pain!

I'll run throught several sets of sample data tomorrow and let ya know
if it works every time! Appreciate the help.

Jul 17 '05 #11
Speechless?

"Miles" <un*****@unlistedspam.com> wrote in message

Steve Gerrard wrote:
"Miles" <un*****@unlistedspam.com> wrote in message

Steve Gerrard wrote:

What do you get instead? It is difficult to identify a bug if you don't
what
the
output is, as well as what it should be. Maybe you are getting all zeros?

Doubt
it, but don't know what you are getting.

The original post showed what I should get. The last 2 bytes of the 32
byte data. No, not getting all 0's, just not the 19 95 that I should.
I'm not at work now and don't have VB6 on this computer but will post
the result I get. I was hoping someone is skilled at both VB6 and C++
and could see what I may have translated wrong as I do not know C at
all. Just looked up the areas of question. My guess is that it has
something to do with C's unsigned integers and how that plays in with
C's >> shiftright routine. I understand how C handles it but not sure
how to translate it to VB6.

Found the snag. Your definition of the const in the VB version produces a
negative number, not the intended value:
Const CRC16Polynomial = &HA001 ' equals -24575 in VB, not 40961 as desired.

Note that in addition to inverting all the bits at the end, the CRC is stored in your sample file in low byte, high byte order (i.e. flipped), a common practice. The following modified version of your VB code produces a CRC of H9519, as
desired:

Private Sub Command1_Click()
Dim I As Integer
Dim CRC32 As Long
Dim CRC16 As Integer
Dim ByteIn As Byte
Dim A As String
Dim strIn() As String

Const Test As String = "&H31, &H07, &H49, &H6E, &H73, &H74, &H72, &H6F, &H6E, &H06, &H49, &H6E, &H53, &H70, &H65, &H63, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF"

strIn = Split(Test, ",")

CRC32 = 0
For I = 0 To 29
A = strIn(I)
ByteIn = CInt(A)
CRC32 = CRC(CRC32, ByteIn)
Next I

'invert all bits
CRC32 = (CRC32 Xor &HFFFF)
'now get the 16 bit version
CRC16 = CRC32
Debug.Print CRC16, Hex(CRC16)

End Sub

Function CRC(CRCIn As Long, ByteIn As Byte) As Long

Const CRC16Polynomial As Long = 40961
Dim Bit As Boolean
Dim I As Integer
Dim WrkByte As Integer
Dim WrkCRC As Long

WrkByte = ByteIn
WrkCRC = CRCIn
For I = 0 To 7
Bit = ((WrkCRC And &H1) Xor (WrkByte And &H1))
WrkCRC = WrkCRC \ 2 'this is fine for shift right 1 bit
If Bit Then
WrkCRC = (WrkCRC Xor CRC16Polynomial)
End If
WrkByte = WrkByte \ 2
Next I
CRC = WrkCRC

End Function

That was fun.
Steve

Jul 17 '05 #12
Speechless?

"Miles" <un*****@unlistedspam.com> wrote in message

Steve Gerrard wrote:
"Miles" <un*****@unlistedspam.com> wrote in message

Steve Gerrard wrote:

What do you get instead? It is difficult to identify a bug if you don't
what
the
output is, as well as what it should be. Maybe you are getting all zeros?

Doubt
it, but don't know what you are getting.

The original post showed what I should get. The last 2 bytes of the 32
byte data. No, not getting all 0's, just not the 19 95 that I should.
I'm not at work now and don't have VB6 on this computer but will post
the result I get. I was hoping someone is skilled at both VB6 and C++
and could see what I may have translated wrong as I do not know C at
all. Just looked up the areas of question. My guess is that it has
something to do with C's unsigned integers and how that plays in with
C's >> shiftright routine. I understand how C handles it but not sure
how to translate it to VB6.

Found the snag. Your definition of the const in the VB version produces a
negative number, not the intended value:
Const CRC16Polynomial = &HA001 ' equals -24575 in VB, not 40961 as desired.

Note that in addition to inverting all the bits at the end, the CRC is stored in your sample file in low byte, high byte order (i.e. flipped), a common practice. The following modified version of your VB code produces a CRC of H9519, as
desired:

Private Sub Command1_Click()
Dim I As Integer
Dim CRC32 As Long
Dim CRC16 As Integer
Dim ByteIn As Byte
Dim A As String
Dim strIn() As String

Const Test As String = "&H31, &H07, &H49, &H6E, &H73, &H74, &H72, &H6F, &H6E, &H06, &H49, &H6E, &H53, &H70, &H65, &H63, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF"

strIn = Split(Test, ",")

CRC32 = 0
For I = 0 To 29
A = strIn(I)
ByteIn = CInt(A)
CRC32 = CRC(CRC32, ByteIn)
Next I

'invert all bits
CRC32 = (CRC32 Xor &HFFFF)
'now get the 16 bit version
CRC16 = CRC32
Debug.Print CRC16, Hex(CRC16)

End Sub

Function CRC(CRCIn As Long, ByteIn As Byte) As Long

Const CRC16Polynomial As Long = 40961
Dim Bit As Boolean
Dim I As Integer
Dim WrkByte As Integer
Dim WrkCRC As Long

WrkByte = ByteIn
WrkCRC = CRCIn
For I = 0 To 7
Bit = ((WrkCRC And &H1) Xor (WrkByte And &H1))
WrkCRC = WrkCRC \ 2 'this is fine for shift right 1 bit
If Bit Then
WrkCRC = (WrkCRC Xor CRC16Polynomial)
End If
WrkByte = WrkByte \ 2
Next I
CRC = WrkCRC

End Function

That was fun.
Steve

Jul 17 '05 #13

"Miles" <un*****@unlistedspam.com> wrote in message

Steve Gerrard wrote:
Found the snag. Your definition of the const in the VB version produces a
negative number, not the intended value:
Const CRC16Polynomial = &HA001 ' equals -24575 in VB, not 40961 as desired.

WrkCRC = WrkCRC \ 2 'this is fine for shift right 1 bit

I had seen several shift right routines for VB6. All were more complex
because they took into account the sign bit shifting as C's >> does so
thats why I didn't simply try \ 2. Not having unsigned integers in VB6
is sometimes a pain!

I'll run throught several sets of sample data tomorrow and let ya know
if it works every time! Appreciate the help.

The Hex constant rang a bell the second time I looked at your code; I have seen
it once before. I don't know if there is a way to define a long Hex constant in
VB.

I agree not having unsigned integers is a pain, hence my use of integers and
longs instead of bytes and integers. I think the \ will only work correctly if
the integer is wider than it needs to be.
Jul 17 '05 #14
: The Hex constant rang a bell the second time I looked at your code; I have
seen
: it once before. I don't know if there is a way to define a long Hex
constant in
: VB.

Const CRC16Polynomial = &HA001& ' <<<<< trailing &

--

Randy Birch
MVP Visual Basic
http://www.mvps.org/vbnet/
Please respond only to the newsgroups so all can benefit.

Jul 17 '05 #15

Steve Gerrard wrote:
Private Sub Command1_Click()
Dim I As Integer
Dim CRC32 As Long
Dim CRC16 As Integer
Dim ByteIn As Byte
Dim A As String
Dim strIn() As String

Const Test As String = "&H31, &H07, &H49, &H6E, &H73, &H74, &H72, &H6F, &H6E,
&H06, &H49, &H6E, &H53, &H70, &H65, &H63, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF,
&HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF"

strIn = Split(Test, ",")

CRC32 = 0
For I = 0 To 29
A = strIn(I)
ByteIn = CInt(A)
CRC32 = CRC(CRC32, ByteIn)
Next I

'invert all bits
CRC32 = (CRC32 Xor &HFFFF)
'now get the 16 bit version
CRC16 = CRC32
Debug.Print CRC16, Hex(CRC16)

End Sub

Ok, I tested it with 3 sets of sample data I have. There is a bit of a
problem when converting to 16 bit (CRC16 = CRC32). Valid CRC's can
range from hex 0000 to hex FFFF or decimal 0 to 65535. VB6's integer
interprets this as +/- 32768. An overflow error occurs when ABS(CRC32)
is greater than 32768. One way I found to correct this is by the
following line.

CRC16 = Val("&H" & Hex\$(CRC32 And &HFFFF&))

Seems that converting it to a hex string and taking a value of it works
because it translates the sign bit correctly for 16 bit integers. I
don't like having to convert to string then back to integer but it does
work. Another way would be:

Select Case CRC32
Case Is < -32768
CRC16 = CRC32 + 65535
Case Is > 32768
CRC16 = CRC32 - 65535
Case Else
CRC16 = CRC32
End Select

This works fine too but is there a cleaner way to handle this?

Jul 17 '05 #16

"Randy Birch" <rg************@mvps.org> wrote in message
news:_X*********************@news01.bloor.is.net.c able.rogers.com...
: The Hex constant rang a bell the second time I looked at your code; I have
seen
: it once before. I don't know if there is a way to define a long Hex
constant in
: VB.

Const CRC16Polynomial = &HA001& ' <<<<< trailing &

--

Randy Birch
MVP Visual Basic
http://www.mvps.org/vbnet/
Please respond only to the newsgroups so all can benefit.

Oh man, that is so simple. Thanks.
Jul 17 '05 #17

"milesh" <mi****@unlistedspam.com> wrote in message
news:bn********@dispatch.concentric.net...

Steve Gerrard wrote:
Private Sub Command1_Click()
Dim I As Integer
Dim CRC32 As Long
Dim CRC16 As Integer
Dim ByteIn As Byte
Dim A As String
Dim strIn() As String

Const Test As String = "&H31, &H07, &H49, &H6E, &H73, &H74, &H72, &H6F, &H6E,
&H06, &H49, &H6E, &H53, &H70, &H65, &H63, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF,
&HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HFF"

strIn = Split(Test, ",")

CRC32 = 0
For I = 0 To 29
A = strIn(I)
ByteIn = CInt(A)
CRC32 = CRC(CRC32, ByteIn)
Next I

'invert all bits
CRC32 = (CRC32 Xor &HFFFF)
'now get the 16 bit version
CRC16 = CRC32
Debug.Print CRC16, Hex(CRC16)

End Sub

Ok, I tested it with 3 sets of sample data I have. There is a bit of a
problem when converting to 16 bit (CRC16 = CRC32). Valid CRC's can
range from hex 0000 to hex FFFF or decimal 0 to 65535. VB6's integer
interprets this as +/- 32768. An overflow error occurs when ABS(CRC32)
is greater than 32768. One way I found to correct this is by the
following line.

CRC16 = Val("&H" & Hex\$(CRC32 And &HFFFF&))

Seems that converting it to a hex string and taking a value of it works
because it translates the sign bit correctly for 16 bit integers. I
don't like having to convert to string then back to integer but it does
work. Another way would be:

Select Case CRC32
Case Is < -32768
CRC16 = CRC32 + 65535
Case Is > 32768
CRC16 = CRC32 - 65535
Case Else
CRC16 = CRC32
End Select

This works fine too but is there a cleaner way to handle this?

I like the select case better. I don't see a way around this, given the nature
of VB's integer. I think it should be 65536 that you add or subtract, to get the
same hex value out.
Jul 17 '05 #18

### This discussion thread is closed

Replies have been disabled for this discussion.