I2CPORT.PAS
unit i2cport;
interface
uses
sysutils;
CONST
MaxIOcard = 3;
MaxIOchip = 7;
MaxIOchannel = 64;
MaxDACchannel = 32;
MaxADchannel = 16;
MaxDAchannel = 4;
VAR
printerPort : Integer;
StatusPort : Integer;
ControlPort : Integer;
I2CbusDelay : Integer;
IOconfig : ARRAY[0..MaxIOchip] OF Integer;
IOdata : ARRAY[0..MaxIOchip] OF Integer;
IO : ARRAY[1..MaxIOchannel] OF Integer;
DAC : ARRAY[1..MaxDACchannel] OF Integer;
AD : ARRAY[1..MaxADchannel] OF Integer;
DA : ARRAY[1..MaxDAchannel] OF Integer;
ADDAchipCode : ARRAY[0..MaxIOcard] OF Integer;
DACchipCode : ARRAY[0..MaxIOcard] OF Integer;
IOChipCode : ARRAY[0..MaxIOchip] OF Integer;
procedure i2cinit;
procedure SelectI2CprinterPort;
procedure i2cbusnotbusy;
procedure ConfigAllIOasInput;
procedure ClearAllIO;
procedure ReadAll;
procedure ReadAllIO;
procedure IOoutput(chipno,datavar:integer);
procedure i2cstart;
procedure i2cstop;
procedure i2coutput(serdata:integer);
procedure i2cclockpulse;
procedure ReadIOchip(chipno:integer);
function i2cinput:integer;
procedure ConfigIOchipAsOutput(ChipNo:integer);
procedure ClearIOchip(chipno:integer);
procedure SetIOchip(chipno:integer);
procedure clearIOchannel(channelno:integer);
procedure setIOchannel(channelno:integer);
function right(str: string; len : integer):string;
function leftVB(str: string; len : integer):string;
function mid(str: string; start:integer;len:integer):string;
function DecimaltoBinary(decNum:integer):string;
function BNOT(binstr:string):string;
function DecimaltoBinaryNOT(decNum:integer):string;
function BinarytoDecimal(binstr:string):integer;
function BINNOT(decnum:integer):integer;
function VBstrings(num:integer;c:string): string;
function VBSHL(dec,positions:integer):integer;
procedure k8000getready;
procedure outPP(PortAddress:smallint;Value:smallint);
function inPP(PortAddress:smallint):smallint;
procedure testrunninglights;
{$IFDEF LINUX}
{external library calls using libprtio.so.1
get the library from
http://users.netonecom.net/~bbcat/Kylix.shtml
}
function openParPort(portN : PChar) : Integer; cdecl; external 'libprtio.so.1';
{$EXTERNALSYM openParPort}
procedurecloseParPort(prtPort : Integer); cdecl; external 'libprtio.so.1';
{$EXTERNALSYMcloseParPort}
procedure wrControlPort(prtPort : Integer; c : Byte); cdecl; external 'libprtio.so.1';
{$EXTERNALSYMwrControlPort}
functionrdStatusPort(prtPort : Integer) : Byte; cdecl; external 'libprtio.so.1';
{$EXTERNALSYMrdStatusPort}
functionrdControlPort(prtPort : Integer) : Byte; cdecl; external 'libprtio.so.1';
{$EXTERNALSYMrdControlPort}
function OpenPort : Boolean;
procedure ClosePort;
procedure writeControl(c : Byte);
function readStatus : Byte;
function readControl : Byte;
{$ENDIF}
implementation
{$IFDEFLINUX}
procedureoutPP(PortAddress:smallint;Value:smallint);
var
ByteValue:Byte;
begin
ByteValue:=Byte(Value);
writeControl(Bytevalue);
end;
function inPP(PortAddress:smallint):smallint;
var
ByteValue:byte;
begin
if PortAddress = 890 then
Bytevalue := readControl
else
Bytevalue := readStatus;
inPP:=smallint(ByteValue) and $00FF;
end;
procedure ClosePort;
begin
if (printerPort <> 0) and (printerPort <> -1) then closeParPort(printerPort);
end;
functionOpenPort : Boolean;
var
i : Integer;
begin
if (printerPort <> 0) and (printerPort <> -1) then closeParPort(printerPort);
//change the string to suit your configuration
i := openParPort(PChar('/dev/parport0'));
if i = -1 then Result := False
else begin
printerPort := i;
Result := True;
end;
end;
procedurewriteControl(c : Byte);
begin
if (printerPort <> 0) and (printerPort <> -1) then
wrControlPort(printerPort,c)
end;
functionreadStatus : Byte;
begin
if (printerPort <> 0) and (printerPort <> -1) then
Result := rdStatusPort(printerPort)
else Result := 0;
end;
functionreadControl:Byte;
begin
if (printerPort <> 0) and (printerPort <> -1) then
Result := rdControlPort(printerPort)
else Result := 0;
end;
{$ENDIF}
{$IFDEFWIN32}
{Code copied from Jan Axelson web-site
http://www.lvr.com/jansfaq.htm}
procedure outPP(PortAddress:smallint;Value:smallint);
var
ByteValue:Byte;
begin
ByteValue:=Byte(Value);
asm
push dx
mov dx,PortAddress
mov al, ByteValue
out dx,al
pop dx
end;
end;
function inPP(PortAddress:smallint):smallint;
var
ByteValue:byte;
begin
asm
push dx
mov dx, PortAddress
in al,dx
mov ByteValue,al
pop dx
end;
inPP:=smallint(ByteValue) and $00FF;
end;
{$ENDIF}
{K8000 VB code ported to Pascal
http://www.velleman.be/kits/k8000.htm
http://www.velleman.be/company/download.asp
}
procedure k8000getready;
var
cardno : integer;
chipno : integer;
begin
for cardno := 0 to MaxIOcard do
begin
DACchipcode[cardno] := 64 + 2*cardno;
ADDAchipCode[CardNo] := 144 + 2 * CardNo;
end;
For ChipNo := 0 To MaxIOchip do
begin
IOChipCode[ChipNo] := 112 + 2 * ChipNo;
end;
I2CInit;
end;
procedure i2cinit;
begin
SelectI2CprinterPort;
I2Cbusdelay := 1;
I2CBusNotBusy;
ConfigAllIOasInput ;
ReadAll;
end;
procedure SelectI2CprinterPort;
begin
Statusport := 889;
Controlport := 890;
end;
procedure i2cbusnotbusy;
var
i : integer;
begin
outPP(Controlport, 4);
For i := 0 To I2Cbusdelay do
begin
// replace this with a timer maybe
end;
end;
procedure ConfigAllIOasInput;
var
chipno : integer;
begin
For ChipNo := 0 To MaxIOchip do
begin
IOconfig[ChipNo] := 0;
end;
ClearAllIO;
end;
procedure ClearAllIO;
var
chipno : integer;
begin
For ChipNo := 0 To MaxIOchip do
begin
IOoutput(ChipNo, 0);
end;
end;
procedure IOoutput(chipno,datavar:integer);
var
temp,startchannel,channel: integer;
datvar : string;
begin
temp := datavar;
datavar := Binnot(temp) Or IOconfig[ChipNo]; //look into this
i2cstart;
temp := IOchipcode[chipno];
i2coutput(temp);
i2cclockpulse;
temp := datavar;
i2coutput(temp);
i2cclockpulse;
i2cstop;
IOdata[ChipNo] := (IOdata[ChipNo] And IOconfig[ChipNo]) Or BINNOT(Datavar);
StartChannel := ChipNo * 8 + 1 ;
temp := IOdata[chipno];
Datvar := DecimalToBinary(Temp);
for channel := 0 to 7 do
begin
if mid(datvar,8-channel,1) = '1' then
IO[startchannel + channel] := 1
else
IO[startchannel + channel] := 0;
end;
end;
procedure ReadAll;
begin
ReadAllIO;
end;
procedure ReadAllIO;
var
chipno : integer;
begin
for chipno := 0 to maxIOchip do
begin
ReadIOchip(ChipNo);
end;
end;
procedure ReadIOchip(chipno:integer);
var
datavar,startchannel,temp,channel:integer;
datvar:string;
begin
i2cstart;
datavar := IOchipcode[chipno] or 1;
i2coutput(datavar);
i2cclockpulse;
IOdata[chipno] := i2cInput;
IOdata[chipno] := BINNOT(IODATA[chipno]);
i2cclockpulse;
i2cstop;
startchannel := chipno*8 + 1;
temp := IOdata[chipno];
datvar := decimaltobinary(temp);
for channel := 0 to 7 do
begin
if mid(datvar,8-channel,1) = '1' then
IO[startchannel + channel] := 1
else
IO[startchannel + channel] := 0;
end;
end;
procedure i2cstart;
var
i : integer;
begin
outPP(Controlport,6);
for i := 0 to i2cbusdelay do
begin
end;
end;
procedure i2cstop;
var
i : integer;
begin
outPP(controlport,14);
for i := 0 to i2cbusdelay do
begin
end;
outPP(controlport,6);
for i := 0 to i2cbusdelay do
begin
end;
outPP(controlport,4);
for i := 0 to i2cbusdelay do
begin
end;
end;
procedure i2coutput(serdata:integer);
var
temp,j,dataout,i : integer;
serdat : string;
begin
temp := serdata;
serdat := decimaltobinary(temp);
for j := 1 to 8 do
begin
If Mid(Serdat, j, 1) = '1' Then
DataOut := 12
Else
DataOut := 14;
outPP(Controlport, DataOut);
For i := 0 To I2Cbusdelay do
begin
end;
dataout := inPP(Controlport) and 7;
outPP(controlport,dataout);
For i := 0 To I2Cbusdelay do
begin
end;
dataout := inPP(Controlport) or 8;
outPP(controlport,dataout);
For i := 0 To I2Cbusdelay do
begin
end;
end;
end;
procedure i2cclockpulse;
var
i : integer;
begin
outPP(controlport,12);
For i := 0 To I2Cbusdelay do
begin
end;
outPP(controlport,4);
For i := 0 To I2Cbusdelay do
begin
end;
outPP(controlport,12);
For i := 0 To I2Cbusdelay do
begin
end;
end;
function i2cinput:integer;
var
serdata,j,i,inputdata : integer;
begin
serdata := 0;
for j := 1 to 8 do
begin
serdata := VBSHL(serdata,1);
outPP(controlport,4);
for i := 0 to i2cbusdelay do
begin
end;
inputdata := inPP(statusport) and 16;
if inputdata <> 0 then
serdata := serdata or 1;
outPP(controlport,12);
for i := 0 to i2cbusdelay do
begin
end;
end;
i2cinput := serdata;
end;
procedure ConfigIOchipAsOutput(ChipNo:integer);
begin
IOconfig[chipno] := 0;
clearIOchip(chipno);
end;
procedure ClearIOchip(chipno:integer);
begin
IOoutput(chipno,0);
end;
procedure SetIOchip(chipno:integer);
begin
IOoutput(chipno,255);
end;
procedure clearIOchannel(channelno:integer);
var
channel,datavar,chipno : integer;
begin
chipno := (channelno - 1) div 8;
channel := (channelno - 1) mod 8;
datavar := IOdata[chipno] and binnot(VBSHL(1,channel));
IOoutput(chipno,datavar);
end;
procedure setIOchannel(channelno:integer);
var
chipno,channel,datavar:integer;
begin
chipno := (channelno - 1) div 8;
channel := (channelno - 1) mod 8;
datavar := VBSHL(1,channel) or IOdata[chipno];
IOoutput(chipno,datavar);
end;
function right(str: string; len : integer):string;
var
s : array[0..255] of Char;
l,m : integer;
temp : string;
begin
l := length(str);
StrPCopy(s, str);
for m := (l - len) to l do
begin
temp := temp + s[m];
end;
right := temp;
end;
function leftVB(str: string; len : integer):string;
var
s : array[0..255] of Char;
m : integer;
temp : string;
begin
StrPCopy(s, str);
for m := 0 to len-1 do
begin
temp := temp + s[m];
end;
leftVB := temp;
end;
function mid(str: string; start:integer;len:integer):string;
var
s : array[0..255] of Char;
m : integer;
temp : string;
begin
StrPCopy(s, str);
for m := start-1 to start+len-2 do
begin
temp := temp + s[m];
end;
mid := temp;
end;
function DecimaltoBinary(decNum:integer):string;
var
binstr : string;
i : integer;
factor : array[1..8] of integer;
begin
factor[1] := 128; factor[2] := 64; factor[3] := 32; factor[4] := 16;
factor[5] := 8; factor[6] := 4;factor[7] := 2; factor[8] := 1;
binstr := '';
for i := 1 to 8 do
begin
if factor[i] > decNum then
binstr := binstr + '0'
else
begin
binstr := binstr + '1';
decNum := decNum - factor[i];
end;
end;
DecimaltoBinary := binstr;
end;
function BNOT(binstr:string):string;
var
i : integer;
temp : string;
begin
temp := '';
for i := 1 to length(binstr) do
begin
if mid(binstr,i,1) = '0' then
temp := temp + '1'
else
temp := temp + '0';
end;
BNOT := temp;
end;
function DecimaltoBinaryNOT(decNum:integer):string;
var
temp : string;
begin
temp := decimalToBinary(decNum);
temp := BNOT(temp);
DecimaltoBinaryNOT := temp;
end;
function BinarytoDecimal(binstr:string):integer;
var
weight,i,sum : integer;
begin
sum := 0;
weight := 1;
for i := 8 downto 1 do
begin
if mid(binstr,i,1) = '1' then
sum := sum + weight;
weight := weight*2;
end;
BinarytoDecimal := sum;
end;
function BINNOT(decnum:integer):integer;
var
temp : string;
begin
temp := decimaltobinaryNOT(decnum);
BINNOT := BinarytoDecimal(temp);
end;
function VBSHL(dec,positions:integer):integer;
var
temp : string;
begin
temp := '';
temp := right( (decimaltobinary(dec) + VBstrings(positions,'0')) ,8);
VBSHL := binarytodecimal(temp);
end;
function VBstrings(num:integer;c:string): string;
begin
VBstrings := stringofchar('0',num);
end;
procedure testrunninglights;
var
i,j,pausefactor,pause,pause2,p : integer;
begin
{$IFDEF LINUX}
openport;
{$ENDIF}
k8000getready;
ConfigIOchipAsOutput(0);
ConfigIOchipAsOutput(1);
pausefactor := 10000;
i := 1;
j:= 0;
repeat
if i = 1 then p := 16 else p := i - 1;
clearIOchannel(p);
setIOchannel(i);
if pausefactor <> 0 then
begin
for pause := 0 to pausefactor do
begin
for pause2 := 0 to 10000 do
begin
end;
end;
end;
if i = 16 then i := 1 else i := i + 1;
j := j+1;
until j >= 32;
{$IFDEF LINUX}
closeport;
{$ENDIF}
end;
end.
Generated by PasToWeb, a tool by Marco Cantù.