I have this code written in C language, Which is representing CRC-16 algorithm using polynom 0x8005, I need to convert that code to PHP, I got stuck at the memcpypgm2ram part, I don't know what that function supposed to do and what's the equivalent to it in PHP. I have done this so far:
C code
const rom unsigned far int CRC16tbl [ 256 ] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 };
unsigned short addCRC(unsigned short crc, unsigned char dataByte)
{
unsigned int crc16int;
memcpypgm2ram(&crc16int, &CRC16tbl[ ( crc & 0xFF ) ^ dataByte ], 2); // Can't get idea behind this line
return ( ( crc >> 8 ) ^ crc16int ); //neither this line
}
unsigned short crc16_calc(char *pBuffer, unsigned short length)
{
unsigned short crc16 = 0;
while (length--)
crc16 = addCRC( crc16, *pBuffer++);
return crc16;
}
PHP Code:
public static function crc16Calc($buffer, $length){
$crc16 = 0;
while ($length--) {
$crc16 = $this->addCRC($crc16, $buffer++);
}
return $crc16;
}
public static function addCRC($crc , $data_byte){
$crc16;
// Need some help here
}
The first line in question does the following:
(crc & 0xFF)
zeroes all but the 8 least significant bits of the CRC, effectively truncating it to one byte (i.e. 0xAABB
becomes 0xBB
).(...) ^ dataByte
takes the XOR (exclusive or) of that with the new data byte.&CRC16tbl[...]
treats the result of the above as an index into the table, and produces a pointer to that location in the table.memcpypgm2ram
copies two bytes starting at the pointer from above into the variable crc16int
, effectively assigning to crc16int
a value from the table.From point 4, we can assume that the C environment that the code was written for uses 16-bit integers, and that it has separate memory for code and for data. memcpypgm2ram(a, b, len)
can be assumed to copy len
bytes from from code space (at pointer b
) to data space (at pointer a
). Most probably some sort of embedded platform was used to run the code.
(crc >> 8) ^ crc16int
shifts the 16-bit integer 8 places to the right, effectively taking the most significant byte (i.e. 0xAABB
becomes 0xAA
), then takes the XOR with the value that was read from the table.In PHP, this could be written as:
// values are integers between 0 and 0xFFFF
$crc16table = array(
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
// ... copy from question ...
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 );
// $crc is an integer between 0 and 0xFFFF
// $dataByte is an integer between 0 and 0xFF
// The result is an integer between 0 and 0xFFFF
function addCRC($crc, $dataByte) {
global $crc16table;
$index = ($crc & 0xFF) ^ $dataByte;
$crc16int = $crc16table[$index];
return ($crc >> 8) ^ $crc16int;
}
// $buffer is a string containing the binary data
// The result is an integer between 0 and 0xFFFF
function crc16Calc($buffer) {
$crc16 = 0;
$length = strlen($buffer);
for ($i = 0; $i < $length; $i++) {
// Use ord() to go from a length-1 string to an integer between 0 and 0xFF
$dataByte = ord($buffer[$i]);
$crc16 = addCRC($crc16, $dataByte);
}
return $crc16;
}
In case you need more explanation on the bitwise operators, it can be found on the PHP website.
Notice also how I changed the iteration in crc16Calc
. While in C it may be common to iterate by moving a pointer, PHP does not work that way. Instead, the buffer is passed in as a string with a known length strlen($buffer)
. *pBuffer++
cannot be directly translated to $buffer++
.