0

This example program is written in C language. It is used to generate a 16-bit FCS number based on CRC-16/IBM-SDLC. I'm trying to write the same in JAVA. Can someone help me with this or provide some idea on this? I don't know the C language.

Example I/O from C language: Key:10530237 16-Bit FCS Number: 9588 The I/O is two bytes and hexadecimal form.

Input Output
1234 DEC1
1111 8206
4143 2066
C language code:
unsigned short crcgen (data, length)
    char *data; /* address of the key */ 
    int length; /* key length   */
{
    unsigned char crcbytel, crcbyte2, r1; 
    char *ptr;
    int i;
    union byte_to_word
    {
        char bytes[2]; 
        unsigned short  ret;
    } return_val;
    ptr = data; 
    crcbyte1 = 0xFF 
    crcbyte2 = 0xFF
    for (i=0; i<length; i++)
    {
        r1 = *ptr++ ^ crcbyte2; 
        r1 = (r1 << 4) ^ r1;
        crcbyte2 = (r1 << 4) | (r1 >> 4); 
        crcbyte2 = (crcbyte2 & 0x0F ) ^ crcbyte1; 
        crcbyte1 = r1;
        r1 = (r1 << 3) | (r1 >> 5);
        crcbyte2 = crcbyte2 ^ (r1 & 0xF8);
         
        crcbyte1 = crcbyte1 ^ (r1 & 0x07);
    }
        
    return_val.bytes[0] = ˜crcbyte2; 
    return_val.bytes[1] = ˜crcbyte1; 
    return(return_val.ret);
}

I have looked at some answers but it did not help and not able to get that output. Convert C CRC16 to Java CRC16 and https://www.source-code.biz/snippets/java/crc16/

The Code that I tried:

  private static final int POLYNOMIAL   = 0x8408;
private static final int PRESET_VALUE = 0xFFFF;
public static void main(String[] args) throws IOException {
    // FileRead.read();
    int crc = 0xFFFF;          // initial value
    int polynomial = 0x1021;   // 0001 0000 0010 0001  (0, 5, 12)

    // byte[] testBytes = "123456789".getBytes("ASCII");

    byte[] buffer = "10530237".getBytes("ASCII");

    System.out.println(FileRead.crc16(buffer));
}

public static int crc16(byte[] data)
{
    int current_crc_value = PRESET_VALUE;
    for (int i = 0; i < data.length; i++ )
    {
        current_crc_value ^= data[i] & 0xFF;
        for (int j = 0; j < 8; j++)
        {
            if ((current_crc_value & 1) != 0)
            {
                current_crc_value = (current_crc_value >>> 1) ^ POLYNOMIAL;
            }
            else
            {
                current_crc_value = current_crc_value >>> 1;
            }
        }
    }
    current_crc_value = ~current_crc_value;

    return current_crc_value & 0xFFFF;
}

It returns 34134 instead of 9588.

zhh
  • 2,346
  • 1
  • 11
  • 22
siva
  • 197
  • 4
  • 10
  • You might want to fix the code formatting if you want someone to read the question. Also why is the C code written in 1980s archaic dinosaur style? Where did you get this code from? It's unlikely a trustworthy source. – Lundin Nov 05 '21 at 08:54
  • The original code seems to be missing some semi-colons. Does it compile at all? I'm not very familiar with the old K&R style of C. But if I remember correctly, semicolons have never been optional. And please fix the indentation. It will make so much more likely that you get help. – Codo Nov 05 '21 at 08:57
  • Yeah. Upon closer inspection the C code is complete slop. It's pseudo-code at best. Also, whoever wrote it didn't grasp endianess. It's just broken code, you can't build anything based on it. – Lundin Nov 05 '21 at 09:00
  • It seems you missed quite lot of "<<" and ">> » operation in your code translation. Those are means to set some bits to 0 inside r1 byte number. – Ptit Xav Nov 05 '21 at 09:15

1 Answers1

2

There's nothing wrong with your translation. It's because you didn't pass the correct "two bytes and hexadecimal form" parameter. Change buffer to

byte[] buffer = {0x10, 0x53, 0x02, 0x37 };

BTW, this may help you deal with the string input.

zhh
  • 2,346
  • 1
  • 11
  • 22