PROGRAM i2cscan;
{ Schaut, wer am I²C-Bus angeschlossen ist und zuhört. }
FROM vt USES i2c_serial;

CONST SAA5246 = $22;
      SAA4700 = $20;
      SAA1064 = $70;

VAR i,j: integer;
    buffer: ARRAY [1..20] OF Byte;
    rd,wr: Boolean;
    s: String[16];

PROCEDURE hexwrite(x: Byte);
var hi,lo: Byte;
    s: String[16];
BEGIN
  s := '123456789ABCDEF';  { 0 fehlt, macht aber nichts }
  hi := x SHR 4; lo := x AND $F;
  IF hi < 10 THEN Write(hi) ELSE Write(s[hi]);
  IF lo < 10 THEN Write(lo) ELSE Write(s[lo]);
END;

PROCEDURE identify(adr: Byte);
{ Nicht besonders aussagekräftig: die meisten Chips lassen sich auf -zig }
{ verschiedene Adressen einstellen, haben diese dann aber mit mehreren }
{ anderen gemeinsam. }
BEGIN
  IF adr IN [$20,$22] THEN Write('SAF1135/SAA4700/'); { VPS-Decoder }
  IF adr = $20 THEN Write('PCF8200/'); { Sprach-Synthesizer }
  IF adr = $22 THEN Write('SAA5243/SAA5246/'); { Videotext-Decoder }
  IF adr IN [$40..$4E] THEN Write('PCF8574/'); { 8 bit I/O Expander }
  IF adr IN [$40..$4E] THEN Write('TDA8444/'); { 8 × 6 bit D/A-Wandler }
  IF adr IN [$70,$72] THEN Write('PCF8576/'); { LCD-Treiber 1-4 × 40 }
  IF adr IN [$70..$7E] THEN Write('PCF8574A/'); { 8 bit I/O Expander }
  IF adr IN [$70..$76] THEN Write('SAA1064/'); { LED-Treiber/Busexpander }
  IF adr = $74 THEN Write('PCF8577/'); { LCD-Treiber 1-2 × 32 }
  IF adr = $76 THEN Write('PCF8577A/'); { LCD-Treiber 1-2 × 32 }
  IF adr IN [$78,$7A] THEN Write('PCF8578/'); { LCD-Punktmatrix-Treiber. }
  { Mögliche Konfigurationen: 32×8, 24×16, 16×24, 8×32. Als Erweiterung }
  { um jeweils 40 Spalten (ohne eigene Multiplexsteuerung): PCF8579. }
  IF adr IN [$7C,$7E] THEN Write('PCF8566/'); { LCD-Treiber 1-4 × 24 }
  IF adr IN [$80..$86] THEN Write('SAA1300/'); { Leistungstreiber 5×85 mA }
  IF adr = $88 THEN Write('TDA8442/'); { DAC u. Schalter für Farbdecoder }
  { Ausgänge: 4 analog, 2 binär, 1 Leistungsausgang 14 mA }
  IF adr IN [$90..$9E] THEN Write('PCF8591/'); { 8 bit DA/AD-Wandler }
  IF adr IN [$90..$9E] THEN Write('TDA8440/'); { AV-Quellenumschalter 2A, 1V }
  IF adr IN [$A0..$AE] THEN Write('PCF8570/PCF8571'); { 256/128 Byte SRAM }
  IF adr IN [$A0..$AE] THEN Write('PCF8581/PCF8582'); { 256/128 Byte EEPROM }
  IF adr IN [$A0,$A2] THEN Write('PCF8583/'); { Uhr/Kalender/256 Byte SRAM }
  IF adr IN [$B0..$BE] THEN Write('PCF8570C/'); { 256 Byte SRAM }
  IF adr IN [$D0..$D6] THEN Write('PCF8573/'); { Uhr/Kalender }
  Write(#8);
END;

PROCEDURE report(i2c_status: Byte);
BEGIN
  IF i2c_status>2 THEN
    WriteLn('I²C-Bus: Err',i2c_status,', ',i2c_error[i2c_status]);
END;

BEGIN
  i := Pos('-d',ParameterStr);
  IF i>0 THEN BEGIN
    s := Copy(ParameterStr,i+2,15);
    j := 1; WHILE s[j] IN ['0'..'9'] DO Inc(j);
    s[j] := #0;
    Val(s,busdelay,i);
  END;
  WriteLn('Teilnehmer am I²C-Bus:');
  FOR i := 0 TO 127 DO BEGIN
    i2cbusIO(2*i+1,^buffer,-1); rd := i2c_status=0;
    report(i2c_status);
    i2cbusIO(2*i,^buffer,0); wr := i2c_status=0;
    report(i2c_status);
    IF rd OR wr THEN BEGIN
      Write('Chip-Adresse $');
      IF rd AND wr THEN BEGIN
        hexwrite(2*i); Write('/$'); hexwrite(2*i+1); Write(': R/W  (');
      END ELSE IF rd THEN BEGIN
        hexwrite(2*i+1); Write(':  R only  (');
      END ELSE BEGIN
        hexwrite(2*i); Write(':  W only  (');
      END;
      identify(2*i); WriteLn(')');
    END;
  END;
END.

