2011-12-18 15:04:21 +01:00

292 lines
5.5 KiB
Plaintext

! CRC-12 Pruefsummenberechnung
!
! Verwendetes Generatorpolynom: G(x)=x^12+x^11+x^3+x^2+x+1 (== 1100000001111)
let
! Diverse Register
var r24 : array 24 of Integer; ! 3 zu checkende bytes
var r36 : array 36 of Integer; ! r24 mit angehaengten Nullen
var r13 : array 13 of Integer; ! Generatorpolynom
var rcs : array 13 of Integer; ! Gesamtchecksumme
! Generator in Bitschreibweise und als Integersumme
const G ~ [1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1];
var g : Integer;
! Potenzen schlagen wir nach
const pot8 ~ [128, 64, 32, 16, 8, 4, 2, 1];
const pot13 ~ [4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1];
! Drei einzulesende Bytes -> r24
var chr1 : Char;
var chr2 : Char;
var chr3 : Char;
! Triangle ist gut im "hinter der Datei lesen", also doch selber machen
var readbehindeof : Boolean;
! "counter" zaehlt die 1024-Byte-Blocks in "blocks"
var counter : Integer;
var blocks : Integer;
! "i" wie Integer-Hilfsvariable
var i : Integer;
! Gesamtchecksumme als Int
var checksum : Integer;
! Debug
proc showr13() ~
begin
i := 0;
while (i<13) do
begin
putint(r13[i]);
i := i+1;
end;
puteol();
end;
! Debug
proc showr24() ~
begin
i := 0;
while (i<24) do
begin
putint(r24[i]);
i := i+1;
end;
puteol();
end;
! Debug
proc showr36() ~
begin
i := 0;
while (i<36) do
begin
putint(r36[i]);
i := i+1;
end;
puteol();
end;
! XOR zweier Bits
func xor(val1: Integer, val2: Integer) : Integer ~
if (val1 \= val2) then
1
else
0
;
! CRC-12 auf 3 Bytes berechnen
proc crc() ~
let
var i : Integer;
var j : Integer;
var k : Integer
in
begin
! r36 von links auffüllen, Rest nullen
i := 0;
while (i < 24) do
begin
r36[i] := r24[i];
i := i + 1;
end;
while (i < 36) do
begin
r36[i] := 0;
i := i + 1;
end;
! Division Modulo 2 (eigentlich XOR)
j := 0;
while (j < 22) do
begin
i := 0;
k := 0;
while (i < 13) do
begin
k := r36[i+j] * pot13[i] + k;
i := i + 1;
end;
if (k >= g) then
begin
i := 0;
while (i < 13) do
begin
r36[i+j] := xor(r36[i+j], r13[i]);
i := i + 1;
end;
end
else
begin
i := 0;
while (i < 13) do
begin
r36[i+j] := xor(r36[i+j], 0); ! sprich: einfach weitergehen und nix machen
i := i + 1;
end;
end;
j := j + 1;
end;
! Leider noch unbefriedigend...
! Gesamtchecksumme erreicht schnell 2^12-1,
! evtl. faellt mir noch was besseres ein
! (Triangle gibt bei Zahlen > maxint einfach 0 aus, hmmm....)
i := 0;
while (i < 13) do
begin
! r13[i] := r36[i+24];
rcs[i] := xor(r13[i], rcs[i]);
i := i + 1;
end;
end;
! Lese Wert nach r24, wobei place=1=linkesByte=MSB, place=2=mittleresByte, und place=3=rechtesByte=LSB
proc load(place: Integer, val: Integer) ~
let
var i : Integer;
var j : Integer;
var v : Integer;
! Ist Bit mit Wertigkeit div gesetzt?
func bitset(val: Integer, div: Integer) : Integer ~
if (div = 0) then
0
else
if ((val / div) > 0) then
1
else
0
in
begin
v := val;
i := (place-1)*8;
j := 0;
! ganzes Byte in r24 einsetzen
while (j < 8) do
begin
r24[i] := bitset(v, pot8[j]);
if (r24[i] = 1) then
v := v - pot8[j]
else
;
i := i + 1;
j := j + 1;
end;
end;
! 24 bits einlesen, falls möglich
proc readin() ~
let
var n1 : Integer;
var n2 : Integer;
var n3 : Integer;
var i : Integer;
var testeof : Boolean
in
begin
counter := 0;
blocks := 1;
readbehindeof := false;
eof(var testeof);
while \testeof do
begin
chr1 := ' ';
chr2 := ' ';
chr3 := ' ';
get(var chr1);
get(var chr2);
get(var chr3);
n1 := ord(chr1);
n2 := ord(chr2);
n3 := ord(chr3);
! Falls wir ueber das Dateiende hinausgelesen haben,
! dann von hinten den "Muell" wegmachen und fuer uns
! in "readbehindoef" klarstellen, dass wir definitiv
! fertig sind
if (n3 < 0) then
begin
counter := counter-1;
n3 := 0;
if (n2 < 0) then
begin
counter := counter-1;
n2 := 0;
if (n1 < 0) then
begin
readbehindeof := true;
counter := counter-1;
n1 := 0;
end
else
;
end
else
;
end
else
;
! nun die Bytes ins Register r24 schieben und die CRC darueber berechnen
if (\ readbehindeof) then
begin
load(1, n1);
load(2, n2);
load(3, n3);
crc();
end
else
;
! und als Bonus die Anzahl der 1k-Bloecke bestimmen
counter := counter+3;
if (counter >= 1024) then
begin
counter := 0;
blocks := blocks + 1;
end
else
;
eof(var testeof);
end;
end
in
begin
! Initalisierungen, Generatorpolynom -> r13 und als Integer
i := 0;
g := 0;
checksum := 0;
while (i < 13) do
begin
rcs[i] := 1;
r13[i] := G[i];
g := (r13[i] * pot13[i]) + g;
i := i + 1;
end;
! von STDIN lesen und CRC-12 berechnen
readin();
! Checksumme aus der Bitschreibweise errechnen
i := 0;
while (i < 12) do
begin
checksum := rcs[i+1] * pot13[i+1] + checksum;
i := i + 1;
end;
! Checksumme und Blocks ausgeben
putint(checksum);
put(' ');
putint(blocks);
puteol();
end;