Converting a 16 bit CRC function from C++ to C# (fixed, thanks!)

promposive

Senior member
Jun 15, 2004
912
0
71
Trying to get this CRC code working in C#, seem to be having some problems.. Maybe you can spot my problem?

Background:
Trying to use a STX2 satellite transmitter with a Netduino Plus.

Sample results: (this is what I'm trying to achieve)
0xAA 0x05 0x05 CRC : 0x74 0x93
0xAA 0x05 0x01 CRC : 0x50 0xD5

My Results:
0xAA 0x05 0x05 CRC : 0x6C 0x8B
0xAA 0x05 0x01 CRC : 0x2A 0xAF

Original C code:
Code:
/*******************************************************************************
* COMPONENT NAME:
* crc16
*
* DESCRIPTION:
* This function computes a 16 bit CRC value for an array of bytes. The value that is returned by this
* function needs to be inverted before it gets placed into the packet. The CRC
* goes at the end of the packet, low byte first. For example:
*
* crc = ~crc16(0xFFFF, msgbuf, length);
*
* msgbuf[length] = (uint8_t)(crc & 0xFF);
* msgbuf[length + 1] = (uint8_t)(crc >> 8);
*
* When calling this function to check the validity of a packet received from
* the STX2, the caller should expect the value 0xF0B8 (#defined as CRC_OK) to
* be returned if the packet is valid.
*
* INPUTS:
* crc - the value to start computing the CRC with. This allows for chaining
* together of CRC values computed for multiple arrays of data. The
* initial value should be FFFFh (#defined as CRC_INIT).
* ptr - the pointer to the array of bytes to compute the CRC for
* length - the length of the data array
*
* OUTPUTS:
* returns - the computed 16 bit crc value
*******************************************************************************/
        uint16_t crc16(uint16_t crc, uint8_t* ptr, int length)
        {
            auto uint16_t i;
            while(length--)
            {
                crc = crc ^ (uint16_t) *ptr++;
                for(i=0;i<8;i++)
                {
                    if(crc & 0x0001)
                        crc = (crc >> 1) ^ 0x8408;
                    else
                        crc >>= 1;
                }
            }
            return crc;
        }

unsigned char Input[5];
uint16_t CrcValue=0;

Input[0]=0xAA;
Input[1]=0x05;
Input[2]=0x01;
Input[3]=0x00;
Input[4]=0x00;
CrcValue=~crc16(0xFFFF,Input,3);
Input[3]=(uint8_t) (CrcValue&0xFF);
Input[4]=(uint8_t) (CrcValue>>8);

My C# code:
Code:
 public ushort CRC16(byte[] bytes)
        {
            ushort crc = 0xFFFF; //(ushort.maxvalue, 65535)

            for (int j = 0; j < bytes.Length; j++)
            {
                crc = (ushort)(crc ^ bytes[j]);
                for (int i = 0; i < 8; i++)
                {
                    if ((crc & 0x0001) == 1)
                        crc = (ushort)((crc >> 1) ^ 0x8408);
                    else
                        crc >>= 1;
                }
            }
            return crc;
        }

            byte[] testBytes = new byte[] { 0xAA, 0x05, 0x05 };
            ushort crc = CRC16(testBytes);
            Console.WriteLine("CRC: " + crc);
            Console.WriteLine("CRC byte 1: " + (crc & 0xFF));
            Console.WriteLine("CRC byte 2: " + (crc >> 8));

            testBytes = new byte[] { 0xAA, 0x05, 0x01 };
            crc = CRC16(testBytes);
            Console.WriteLine("CRC: " + crc + "\r\n");
            Console.WriteLine("CRC byte 1: " + (crc & 0xFF));
            Console.WriteLine("CRC byte 2: " + (crc >> 8));
 
Last edited:

Schmide

Diamond Member
Mar 7, 2002
5,690
926
126
Code:
Input[0]=0xAA;
Input[1]=0x05;
Input[2]=[COLOR="Red"]0x01[/COLOR];

Code:
byte[] testBytes = new byte[] { 0xAA, 0x05, [COLOR="Red"]0x05[/COLOR] };

This looks like a source data problem?

^ not the issue sorry i didn't notice the second call but what about this.

Code:
CrcValue=[COLOR="Red"]~[/COLOR]crc16(0xFFFF,Input,3);
Code:
ushort crc = CRC16(testBytes);

The first function is bitwise notting the value, the second not so much?
 
Last edited:

promposive

Senior member
Jun 15, 2004
912
0
71
Looks like bitwise complement is not defined for unsigned short, http://msdn.microsoft.com/en-us/library/d2bd4x66.aspx
so i have to cast to uint and then cast result to ushort, results in a weird looking cast lol

Anyway, fixed it by doing this:
return (ushort)~(uint)crc;

Code:
        public ushort CRC16(byte[] bytes)
        {
            ushort crc = 0xFFFF; //(ushort.maxvalue, 65535)

            for (int j = 0; j < bytes.Length; j++)
            {
                crc = (ushort)(crc ^ bytes[j]);
                for (int i = 0; i < 8; i++)
                {
                    if ((crc & 0x0001) == 1)
                        crc = (ushort)((crc >> 1) ^ 0x8408);
                    else
                        crc >>= 1;
                }
            }
            return (ushort)~(uint)crc;
        }