PHP define function CALCULATE CRC-16 CCITT

Discussion in 'PHP' started by esgllcinc, Oct 31, 2012.

  1. #1
    DO anyone have a php function that will calculate CRC-16 CCITT checksum using the selected region.
     
    Solved! View solution.
    esgllcinc, Oct 31, 2012 IP
  2. ThePHPMaster

    ThePHPMaster Well-Known Member

    Messages:
    737
    Likes Received:
    52
    Best Answers:
    33
    Trophy Points:
    150
    #2
    ThePHPMaster, Oct 31, 2012 IP
  3. #3
    Try these:

    
    <?php
    // CCITT, X24
    define(CRC16POLYN,0x1021);
    define(CRC16POLYI,0x8408);
    
    // for "STANDARD" use 0x8005 and 0xA001
    
    function CRC16Normal($buffer) {
    	$result = 0xFFFF;
    	if ( ($length = strlen($buffer)) > 0) {
    		for ($offset = 0; $offset < $length; $offset++) {
    			$result ^= (ord($buffer[$offset]) << 8);
    			for ($bitwise = 0; $bitwise < 8; $bitwise++) {
    				if (($result <<= 1) & 0x10000) $result ^= CRC16POLYN;
    				$result &= 0xFFFF; /* gut the overflow as php has no 16 bit types */
    			}
    		}
    	}
    	return $result;
    }
    
    function CRC16Inverse($buffer) {
    	$result = 0xFFFF;
    	if ( ($length = strlen($buffer)) > 0) {
    		for ($offset = 0; $offset < $length; $offset++) {
    			$result ^= ord($buffer[$offset]);
    			for ($bitwise = 0; $bitwise < 8; $bitwise++) {
    				$lowBit = $result & 0x0001;
    				$result >>= 1;
    				if ($lowBit) $result ^= CRC16POLYI;
    			}
    		}
    	}
    	return $result;
    }
    
    
    echo '
    	0x',dechex(CRC16Normal('123456789')),' == 0x29B1<br />
    	0x',dechex(CRC16Normal('abc')),' == 0x514A<br />
    	0x',dechex(CRC16Normal('ABC')),' == 0xF508<br />
    	0x',dechex(CRC16Normal('This is a string')),' == 0x4BE9<br />
    	<br />
    	0x',dechex(CRC16Inverse('123456789')),' == 0x29B1<br />
    	0x',dechex(CRC16Inverse('abc')),' == 0x514A<br />
    	0x',dechex(CRC16Inverse('ABC')),' == 0xF508<br />
    	0x',dechex(CRC16Inverse('This is a string')),' == 0x4BE9<br />';
    ?>
    
    Code (markup):
    Should work good for you... and another of those routines that I really wish higher level languages gave you access to the carry flag on the processor :D

    Gave you both methods of reaching the same number -- just to show how it's done.
     
    deathshadow, Nov 1, 2012 IP
  4. esgllcinc

    esgllcinc Peon

    Messages:
    14
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #4
    This works as well and its shorter

    <?php
    function crc16($data)
     {
       $crc = 0xFFFF;
       for ($i = 0; $i < strlen($data); $i++)
       {
         $x = (($crc >> 8) ^ ord($data[$i])) & 0xFF;
         $x ^= $x >> 4;
         $crc = (($crc << 8) ^ ($x << 12) ^ ($x << 5) ^ $x) & 0xFFFF;
       }
       return $crc;
     }
    ?>
    Code (markup):
     
    esgllcinc, Nov 9, 2012 IP
  5. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #5
    Polynomial's hard coded though --- though it's a good trade when you only need CCITT and speed is more important than versatility.
     
    deathshadow, Nov 10, 2012 IP
  6. noobee80

    noobee80 Peon

    Messages:
    1
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    1
    #6
    hello@community,

    I have a question to this old post. :( First, THANKS for the code :):)
    I have a message in hex "80 00 00 03" crc-ccitt kermit. The checksum (checked with lammertbies.nl) is "f5 1f". When I use the the php-code above, I did not get that checksum. I know, that I do not have to use the polynom 0x1021. The right polynom is the revers one 0x8408. Also the result is not the right one for me. The correct result is "$result = 0x0000" instead of "$result = 0xFFFF". But that does not solve the problem. I did not get the right checksum for my message "80 00 00 03".
    Do I have to change the php-code or what is the error? Please help me
     
    noobee80, Oct 13, 2016 IP