4

I need help in converting C code into PHP. The following is the C Code:

static const U16 crctab16[] = { 0x0000, 0x1189, ... };

U16 GetCrc16(const U8* pData, int nLength)
{
  U16 fcs = 0xffff;
  while(nLength > 0)
  {
    fcs = (fcs >> 8) ^ crctab16[fcs ^ *pData) & 0xff];
    nLength--; pData++;
  }
  return ~fcs;
}

I have the following PHP code that I have managed to convert thus far:

$crctab16 = array(0x0000, 0x1189, ... );

function getCrc16($pData)
{
    $hexdata = pack('H*',$pData);
    $nLength = strlen($hexdata);
    $fcs = 0xFFFF;
    $pos = 0;
    while($nLength > 0)
    {
        $fcs = ($fcs >> 8) ^ $crctab16[($fcs ^ $hexdata[$pos]) & 0xFF];
        $nLength--;
        $pos++;
    }
    return ~$fcs;
}

I have tried to run the following code:

$str = "0A1344010400010005"; 
var_dump(getCrc16($str));
var_dump(bin2hex(getCrc16($str))); // result supposed to be 08 45

It seems to be showing the wrong result. When I tried to substitute $str with other values, the result will always be the SAME.

I believe there might be something wrong with my PHP code. But, I cannot seem to figure out the cause of this.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
Heru S
  • 1,283
  • 2
  • 17
  • 28
  • 1
    Seems that you missed something here: C code: `crctab16[fcs ^ *pData) & 0xff];` PHP code: `$crctab16[($hexdata[$pos]) & 0xFF];` I don't see fcs in PHP code. – nhahtdh Jun 18 '12 at 07:33
  • @nhahtdh there is a `$fcs` assignment in the `getCrc16` function. – Heru S Jun 18 '12 at 07:37
  • 1
    Please check the 2 lines I refer to in my comment. – nhahtdh Jun 18 '12 at 07:38
  • @nhahtdh thanks for spotting that!! I have revised it but it seems to be generating the same result :(. – Heru S Jun 18 '12 at 07:42
  • 1
    The comments in the [PHP manual page for the crc32 function](http://php.net/manual/de/function.crc32.php) contain some working examples of crc16. – Carsten Jun 18 '12 at 07:44

3 Answers3

3

I have managed to figure out the solution for this. Thanks to @nhahtdh, @Carsten, and @odiszapc who have helped.

This is the correct PHP function:

function getCrc16($pData)
{
    $hexdata = pack('H*',$pData);
    $nLength = strlen($hexdata);
    $fcs = 0xFFFF;
    $pos = 0;
    while($nLength > 0)
    {
        $fcs = ($fcs >> 8) ^ $crctab16[($fcs ^ ord($hexdata[$pos])) & 0xFF];
        $nLength--;
        $pos++;
    }
    return ~$fcs;
}

It seems that I need to ord() function in the byte format data. I have figured this out following the CRC16 example provided by @Carsten.

Thank you so much guys!

Heru S
  • 1,283
  • 2
  • 17
  • 28
  • I'm working on the same packets but I get 2d39303738 instead of '08 45'; – kouton Apr 04 '13 at 13:27
  • I needed to process it further to get the Hex Values: echo 'Decimal of getCrc16 = ' . dechex($crc25) . '
    '; echo 'Decimal without ffff = ' . str_replace('ffff', '', dechex($crc25)) . '
    ';
    – kouton Apr 05 '13 at 06:36
2

Try this

function crc16($sStr, $aParams = array()){ 

 $aDefaults = array( 
   "polynome" => 0x1021, 
   "init" => 0xFFFF, 
   "xor_out" => 0, 
 ); 

 foreach ($aDefaults as $key => $val){ 
   if (!isset($aParams[$key])){ 
     $aParams[$key] = $val; 
   } 
 } 

 $sStr .= ""; 
 $crc = $aParams['init']; 
 $len = strlen($sStr); 
 $i = 0; 

 while ($len--){ 
   $crc ^= ord($sStr[$i++]) << 8; 
   $crc &= 0xffff; 

   for ($j = 0; $j < 8; $j++){ 
     $crc = ($crc & 0x8000) ? ($crc << 1) ^ $aParams['polynome'] : $crc << 1; 
     $crc &= 0xffff; 
   } 
 } 

 $crc ^= $aParams['xor_out']; 

 return $crc; 
}
odiszapc
  • 4,089
  • 2
  • 27
  • 42
  • Thanks for the input. But, may I know what I should input for `$sStr`? Also, this seems to be quite different from the CRC16 code provided in C. Will it work similarly? Thanks for the help! – Heru S Jun 18 '12 at 07:39
  • thanks for the input. I tried but it seems to give me different results than the above. It might be because of the different algorithm. I have posted what I have done and it is working correctly. Thanks for the help! – Heru S Jun 20 '12 at 18:26
0
Code fragment of the CRC-ITU lookup table algorithm implemented based on C language is as follow: 

static const U16 crctab16[] = {     0X0000, 0X1189, 0X2312, 0X329B, 0X4624, 0X57AD, 0X6536, 0X74BF,     0X8C48, 0X9DC1, 0XAF5A, 0XBED3, 0XCA6C, 0XDBE5, 0XE97E, 0XF8F7,     0X1081, 0X0108, 0X3393, 0X221A, 0X56A5, 0X472C, 0X75B7, 0X643E,     0X9CC9, 0X8D40, 0XBFDB, 0XAE52, 0XDAED, 0XCB64, 0XF9FF, 0XE876,     0X2102, 0X308B, 0X0210, 0X1399, 0X6726, 0X76AF, 0X4434, 0X55BD,     0XAD4A, 0XBCC3, 0X8E58, 0X9FD1, 0XEB6E, 0XFAE7, 0XC87C, 0XD9F5,     0X3183, 0X200A, 0X1291, 0X0318, 0X77A7, 0X662E, 0X54B5, 0X453C,     0XBDCB, 0XAC42, 0X9ED9, 0X8F50, 0XFBEF, 0XEA66, 0XD8FD, 0XC974,     0X4204, 0X538D, 0X6116, 0X709F, 0X0420, 0X15A9, 0X2732, 0X36BB,     0XCE4C, 0XDFC5, 0XED5E, 0XFCD7, 0X8868, 0X99E1, 0XAB7A, 0XBAF3,     0X5285, 0X430C, 0X7197, 0X601E, 0X14A1, 0X0528, 0X37B3, 0X263A,     0XDECD, 0XCF44, 0XFDDF, 0XEC56, 0X98E9, 0X8960, 0XBBFB, 0XAA72,     0X6306, 0X728F, 0X4014, 0X519D, 0X2522, 0X34AB, 0X0630, 0X17B9,     0XEF4E, 0XFEC7, 0XCC5C, 0XDDD5, 0XA96A, 0XB8E3, 0X8A78, 0X9BF1,     0X7387, 0X620E, 0X5095, 0X411C, 0X35A3, 0X242A, 0X16B1, 0X0738,     0XFFCF, 0XEE46, 0XDCDD, 0XCD54, 0XB9EB, 0XA862, 0X9AF9, 0X8B70,     0X8408, 0X9581, 0XA71A, 0XB693, 0XC22C, 0XD3A5, 0XE13E, 0XF0B7,     0X0840, 0X19C9, 0X2B52, 0X3ADB, 0X4E64, 0X5FED, 0X6D76, 0X7CFF,     0X9489, 0X8500, 0XB79B, 0XA612, 0XD2AD, 0XC324, 0XF1BF, 0XE036,     0X18C1, 0X0948, 0X3BD3, 0X2A5A, 0X5EE5, 0X4F6C, 0X7DF7, 0X6C7E,     0XA50A, 0XB483, 0X8618, 0X9791, 0XE32E, 0XF2A7, 0XC03C, 0XD1B5,     0X2942, 0X38CB, 0X0A50, 0X1BD9, 0X6F66, 0X7EEF, 0X4C74, 0X5DFD,     0XB58B, 0XA402, 0X9699, 0X8710, 0XF3AF, 0XE226, 0XD0BD, 0XC134,     0X39C3, 0X284A, 0X1AD1, 0X0B58, 0X7FE7, 0X6E6E, 0X5CF5, 0X4D7C,     0XC60C, 0XD785, 0XE51E, 0XF497, 0X8028, 0X91A1, 0XA33A, 0XB2B3,     0X4A44, 0X5BCD, 0X6956, 0X78DF, 0X0C60, 0X1DE9, 0X2F72, 0X3EFB,     0XD68D, 0XC704, 0XF59F, 0XE416, 0X90A9, 0X8120, 0XB3BB, 0XA232,     0X5AC5, 0X4B4C, 0X79D7, 0X685E, 0X1CE1, 0X0D68, 0X3FF3, 0X2E7A,     0XE70E, 0XF687, 0XC41C, 0XD595, 0XA12A, 0XB0A3, 0X8238, 0X93B1,     0X6B46, 0X7ACF, 0X4854, 0X59DD, 0X2D62, 0X3CEB, 0X0E70, 0X1FF9,     0XF78F, 0XE606, 0XD49D, 0XC514, 0XB1AB, 0XA022, 0X92B9, 0X8330,     0X7BC7, 0X6A4E, 0X58D5, 0X495C, 0X3DE3, 0X2C6A, 0X1EF1, 0X0F78, }; 

//  calculate the 16-bit CRC of data with predetermined length.

U16 GetCrc16(const U8* pData, int nLength) {     
  U16  fcs  =  0xffff;         //  initialization     
  while(nLength>0){         
    fcs = (fcs >> 8) ^ crctab16[(fcs ^ *pData) & 0xff];         
    nLength--;         
    pData++;     
  }     
  return  ~fcs;         //  negated 
} 
  • 1
    Welcome to Stack Overflow! While this code snippet may solve the question, [including an explanation](//meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, this reduces the readability of both the code and the explanations! – Claudia Jun 20 '17 at 15:41