CRC-16 nach ARC (aka IBM/ANSI?) in PHP berechnen

Hi,

Ich hätte nicht gedacht, dass ich mit diese Aufgabenstellung solche Probleme bekommen und hätte eigentlich fertigen PHP Code dazu in Netz erwartet. Ich hoffe hier kann mir jemand helfen.

Zunächst zum Problem:
Ich möchte das Contact-ID Protocol, dass viele Alarmanlagen zur Kommunikation mit Notrufleitstellen verwenden in SYMCON „emulieren“, um (Status-)Meldung meiner Alarmanlage zu empfangen und auszuwerten. Das ganze ist recht simpel gestrickt und ich werden den kompletten Code dazu veröffentlichen. Was das Protokoll angeht, so muss ich empfangene Nachrichten mindestens bestätigen (ACK). Dazu muss ich die CRC über die Bestätigung berechnen und hier liegt mein Problem.

Verwendet wird CRC-16 (ARC) mit folgenden Parametern:

Input reflected: yes
Result reflected: yes
Polynom = 0x8005
Initial = 0x0000
Final xor = 0x0000

Die folgende Seite liefert bei Auswahl von CRC-16, Predefined „CRC16_ARC“ den richtigen Wert:
http://www.sunshine2k.de/coding/javascript/crc/crc_js.html

Hier ein Beispiel, dass die Funktion verdauen muss (als String): "ADM-CID"0001L0#224401[#224401|1601 01 000]
Ergebnis muss hier lauten: 496D (hex)

Diesen Code habe ich gefunden.

function crc16($data) { 
   $poly = 0x8005; 
   $xor = 0x0000; 
   $crc = 0x0000; 
   $len = strlen($data); 
   $i = 0; 
   while ($len--) { 
      $crc ^= ord($data[$i++]) << 8; 
      $crc &= 0xffff; 
      for ($j = 0; $j < 8; $j++){ 
         $crc = ($crc & 0x8000) ? ($crc << 1) ^ $poly : $crc << 1; 
         $crc &= 0xffff; 
      } 
   } 
   $crc ^= $xor; 
   return $crc; 
}

Der Code lässt sich zumindest mit dem Polynom, dem Startwert und dem Final XOR parametrieren. Ich denke der Grund warum noch nicht das richtige Ergebnis rauskommt, ist die Input und/oder Result Reflection, welche hier wahrscheinlich fehlt.

Kann mir da jemand helfen?

Bin doch noch im Netz fündig geworden.
2Uhr in der Nacht ist halt doch nicht die richtige Zeit für sowas…

// CRC-16_ARC with the following parameter:
// Poly = 0x8005
// Init = 0x0000
// Xor  = 0x0000
// Refin  = True
// Refout = True
// Output in Hex

function crc16($data) {
	$crc = 0x0000;      // Init
        $len = strlen($data);
        $i = 0;
        while ($len--) {
            $crc ^= reversebyte(ord($data[$i++])) << 8;
            $crc &= 0xffff;
            for ($j = 0; $j < 8; $j++){
                $crc = ($crc & 0x8000) ? ($crc << 1) ^ 0x8005 : $crc << 1;
                $crc &= 0xffff;
            }
        }
		// $crc ^= 0x0000;   // Final XOR
        $crc = reversebits($crc);
        $crc = dechex($crc);
	    return $crc;
    }

    function reversebyte($byte) {
        $ob = 0;
        $b = (1 << 7);
        for ($i = 0; $i <= 7; $i++) {
            if (($byte & $b) !== 0) {
                $ob |= (1 << $i);
            }
            $b >>= 1;
        }
        return $ob;
    }

    function reversebits($cc) {
        $ob = 0;
        $b = (1 << 15);
        for ($i = 0; $i <= 15; $i++) {
            if (($cc & $b) !== 0) {
                $ob |= (1 << $i);
            }
            $b >>= 1;
        }
        return $ob;
    }

echo crc16('"ADM-CID"0001L0#224401[#224401|1601 01 000]');