unit i2c;

{ -------------------------- } interface { ------------------------- }

uses
  Ppar;
  
const
  I2C_SDAOUT = 7;		{ Bit 7 of the data port }
  I2C_SDAIN  = PPAR_BUSY;
  I2C_SCLOUT = PPAR_SELECT;
  I2C_SCLIN  = PPAR_ERROR;
  
  { These compensate the external hardware connected to the parport }
  I2C_INV_SDAIN = true;
  I2C_INV_SDAOUT = true;
  I2C_INV_SCLOUT = true;
  I2C_INV_SCLIN = false;	{ There are two inverters, so no inversion }

type
  i2c_port = object (par_port)
    procedure Initialize(paddr: word);
    procedure SetSDA(state: boolean);
    function  GetSDA: boolean;
    procedure SetSCL(state: boolean);
    function  GetSCL: boolean;
    procedure Start;
    procedure Stop;
    function  ByteSent(b: byte): boolean;
  end;


{ -------------------------- } implementation { -------------------- }

procedure i2c_port.Initialize(paddr: word);
begin
  inherited Initialize(paddr);
  SetSCL(true);
  SetSDA(true);
end;

procedure i2c_port.SetSDA(state: boolean);
begin
  SetDataBit(I2C_SDAOUT, state xor I2C_INV_SDAOUT);
end;

function i2c_port.GetSDA: boolean;
begin
  GetSDA := GetStatusBit(I2C_SDAIN) xor I2C_INV_SDAIN;
end;

procedure i2c_port.SetSCL(state: boolean);
begin
  SetControlBit(I2C_SCLOUT, state xor I2C_INV_SCLOUT);
end;

function i2c_port.GetSCL: boolean;
begin
  GetSCL := GetStatusBit(I2C_SCLIN) xor I2C_INV_SCLIN;
end;

procedure i2c_port.Start;
begin
  SetSDA(false);
end;

procedure i2c_port.Stop;
begin
  SetSDA(false);
  SetSCL(true);
  SetSDA(true);
end;

function i2c_port.ByteSent(b: byte): boolean;
var
  bit: integer;
begin
  for bit := 7 downto 0 do begin
    SetSDA((b and (1 shl bit)) <> 0);
    SetSCL(true);
    SetSCL(false);
  end;
  SetSDA(true);
  SetSCL(true);
  ByteSent := not GetSDA;
  SetSCL(false);
end;

begin
end.
