i Need a function that generates the Maxim/Dallas 1-Wire CRC 8bit-Code like this page: http://www.datastat.com/sysadminjournal/maximcrc.cgi
For that problem I found an little Excel Calculator for solution. It works correctly, but I got the Problem to translate it into PHP language.
Original VB Code:
Private Sub ROMCRC_Click()
Dim InHex, OutBinStr As String
Dim OutBinArr(1 To 56) As Integer
Dim OutDec, i, CRC(1 To 8), CRCTemp As Integer
InHex = Range("ROMByte1").Value & Range("ROMByte2").Value & Range("ROMByte3").Value & Range("ROMByte4").Value & Range("ROMByte5").Value & Range("ROMByte6").Value & Range("ROMByte7").Value
OutBinStr = HexToBin(InHex)
' Convert string to array, LSB = OutBinArr(1)
For i = 1 To 56
OutBinArr(57 - i) = Mid$(OutBinStr, i, 1) ' Split(OutBinStr)
Next i
'Initialize CRC
For i = 1 To 8
CRC(i) = 0
Next i
'Calculate CRC
For i = 1 To 56
CRCTemp = CRC(1) Xor OutBinArr(i)
CRC(1) = CRC(2)
CRC(2) = CRC(3)
CRC(3) = CRC(4) Xor CRCTemp
CRC(4) = CRC(5) Xor CRCTemp
CRC(5) = CRC(6)
CRC(6) = CRC(7)
CRC(7) = CRC(8)
CRC(8) = CRCTemp
Next i
DecCRC = BinToDec(CRC)
Range("ROMCRCValue").Value = DecCRC
End Sub
Private Function HexToBin(hstr)
'convert hex string to binary string
cnvarr = Array("0000", "0001", "0010", "0011", _
"0100", "0101", "0110", "0111", "1000", _
"1001", "1010", "1011", "1100", "1101", _
"1110", "1111")
bstr = ""
For i = 1 To Len(hstr)
hdgt = Mid(hstr, i, 1)
cix = CInt("&H" & hdgt)
bstr = bstr & cnvarr(cix)
Next
HexToBin = bstr
End Function
Function BinToDec(bstr)
'convert 8 bit Binary number to Decimal
Dim j, Out As Integer
Out = 0
For j = 1 To 8
Out = Out + bstr(j) * 2 ^ (j - 1)
Next j
BinToDec = Out
End Function
My PHP test code:
protected function HexToBin($hstr) {
//convert hex string to binary string
$cnvarr = array(
'0000',
'0001',
'0010',
'0011',
'0100',
'0101',
'0110',
'0111',
'1000',
'1001',
'1010',
'1011',
'1100',
'1101',
'1110',
'1111'
);
$bstr = "";
for ($i = 1; $i <= strlen($hstr); $i++) {
$hdgt = substr($hstr, $i, 1);
$cix = intval($hdgt);
echo $cix.'|';
$bstr .= $cnvarr[$cix];
}
return $bstr;
}
protected function createHash($data) {
//$OutBinStr = $this->HexToBin($data);
$OutBinStr = hex2bin($data);
$OutBinArr = array();
$crc = array();
//Convert string to array, LSB = OutBinArr(1)
for ($i = 1; $i <= 56; $i++) {
$OutBinArr[57 - $i] = substr($OutBinStr, $i - 1, 1);
}
//initialize crc
for ($i = 1; $i <= 8; $i++) {
$crc[$i] = 0;
}
// calculate
for ($i = 1; $i <= 56; $i++) {
$CRCTemp = $crc[1] ^ $OutBinArr[$i];
$crc[1] = $crc[2];
$crc[2] = $crc[3];
$crc[3] = $crc[4] ^ $CRCTemp;
$crc[4] = $crc[5] ^ $CRCTemp;
$crc[5] = $crc[6];
$crc[6] = $crc[7];
$crc[7] = $crc[8];
$crc[8] = $CRCTemp;
}
return implode('', $crc);
}
Example call:
$buttonId = '0000145D6E0F01';
echo $this->createHash($buttonId);
I thank you if you have any Ideas why the Script does not generate the correct crc.
Thank you, nice regards Michael
Your HexToBin()
was generating wrong string. The for
loop for substr()
started with 1 instead of 0. See substr manual.
Imploding $crc resulted an reverse bit order value.
<?PHP
function HexToBin($hstr){
$hstr = str_replace(' ','',$hstr);
$hArr = str_split($hstr);
$bstr = "";
foreach($hArr AS $c){
$cix = sprintf("0x0{$c}");
// echo sprintf("%04b|",hexdec($cix));
$bstr .= sprintf("%04b",hexdec($cix));
}
return $bstr;
}
function createHash($data){
$OutBinStr = HexToBin($data);
$crc = array_fill(0,8,0);
$OutBinArr = array_reverse(str_split($OutBinStr));
// calculate
foreach($OutBinArr AS $i){
$CRCTemp = $crc[0] ^ $i;
$crc[0] = $crc[1];
$crc[1] = $crc[2];
$crc[2] = $crc[3] ^ $CRCTemp;
$crc[3] = $crc[4] ^ $CRCTemp;
$crc[4] = $crc[5];
$crc[5] = $crc[6];
$crc[6] = $crc[7];
$crc[7] = $CRCTemp;
}
$crc = array_reverse($crc);
return implode('', $crc);
}
$buttonId = '00 00 14 5D 6E 0F 01'; // 59 => 3B
// $buttonId = '12 AA 12 5F 14 A2 12 12'; // 109 => 6D
$crc = bindec(createHash($buttonId));
printf("\n%d => %X",$crc,$crc);
?>