home *** CD-ROM | disk | FTP | other *** search
- {$A-,B-,D-,E-,F-,I-,L-,N-,O-,R-,S-,V-}
- {$M 65520, 0, 655360}
- unit eco_comm;
-
- interface
-
- uses
- dos;
-
-
- {- standard baudrates: -}
- {- 50, 75, 110, 134 (134.5), 150, 300, 600, 1200, 1800, 2000, 2400, 3600, -}
- {- 4800, 7200, 9600, 19200, 38400, 57600, 115200 -}
-
-
- function opencom {- open a comport for communication -}
- (nr : byte; {- internal portnumber: 0-7 -}
- address : word; {- port address in hex: 000-3f8 -}
- irqnum : byte; {- port irq number: 0-7 (255 for no irq) -}
- baudrate : longint; {- baudrate: (see table) -}
- paritybit : char; {- parity : 'O','E' or 'N' -}
- databits : byte; {- databits: 5-8 -}
- stopbits : byte; {- stopbits: 1-2 -}
- buffersize : word; {- size of input buffer: 0-65535 -}
- handshake : boolean) {- true to use hardware handshake -}
- : boolean; {- returns true if ok -}
-
- procedure closecom {- close a open comport -}
- (nr : byte); {- internal portnumber: 0-7 -}
-
- procedure resetcom {- reset a open comport incl. buffer -}
- (nr : byte); {- internal portnumber: 0-7 -}
-
- procedure comsettings {- change settings for a open comport -}
- (nr : byte; {- internal portnumber: 0-7 -}
- baudrate : longint; {- baudrate: (see table) -}
- paritybit : char; {- parity : 'O','E' or 'N' -}
- databits : byte; {- databits: 5-8 -}
- stopbits : byte; {- stopbits: 1-2 -}
- handshake : boolean); {- true to use hardware handshake -}
-
- function comaddress {- return the address for a comport (bios) -}
- (comport : byte) {- comport: 1-8 -}
- : word; {- address found for comport (0 if none) -}
-
- function writecom {- writes a character to a port -}
- (nr : byte; {- internal portnumber: 0-7 -}
- ch : char) {- character to be written to port -}
- : boolean; {- true if character send -}
-
- function writecomstring {- writes a string to a port -}
- (nr : byte; {- internal portnumber: 0-7 -}
- st : string) {- string to be written to port -}
- : boolean; {- true if string send -}
-
- function checkcom {- check if any character is arrived -}
- (nr : byte; {- internal portnumber: 0-7 -}
- var ch : char) {- character arrived -}
- : boolean; {- returns true and character if any -}
-
- function comerror {- returns status of the last operation -}
- : integer; {- 0 = ok -}
- {- 1 = not enough memory -}
- {- 2 = port not open -}
- {- 3 = port already used once -}
- {- 4 = selected irq already used once -}
- {- 5 = invalid port -}
- {- 6 = timeout -}
- {- 7 = port failed loopback test -}
- {- 8 = port failed irq test -}
-
- function testcom {- performs a loopback and irq test on a port -}
- (nr : byte) {- internal port number: 0-7 -}
- : boolean; {- true if port test ok -}
- {- note: this test is performed during opencom -}
- {- if enabled (testcom is by default enabled -}
- {- during opencom, but can be disabled with -}
- {- the disabletestcom rutine) -}
-
- procedure enabletestcom; {- enable testcom during openport (default on) -}
-
- procedure disabletestcom; {- disable testcom during openport -}
-
- function comused {- check whether or not a port is open -}
- (nr : byte) {- internal port number: 0-7 -}
- : boolean; {- true if port is open and in use -}
- {- note: this rutine can not test whether or -}
- {- not a comport is used by another application-}
-
- function irqused {- check whether or not an irq is used -}
- (irqnum : byte) {- irq number: 0-7 -}
- : boolean; {- true if irq is used -}
- {- note: this rutine can not test whether or -}
- {- not an irq is used by another application -}
-
- function irqinuse {- test irq in use on the pic -}
- (irqnum : byte) {- irq number: 0-7 -}
- : boolean; {- true if irq is used -}
-
- procedure setirqpriority {- set the irq priority level on the pic -}
- (irqnum : byte); {- irq number: 0-7 -}
- {- the irqnum specified will get the highest -}
- {- priority, the following irq number will then-}
- {- have the next highest priotity and so on -}
-
- procedure clearbuffer {- clear the input buffer for a open port -}
- (nr : byte); {- internal port number: 0-7 -}
-
-
-
-
-
- implementation
-
-
-
-
-
-
- type
- buffer = array[1..65535] of byte; {- dummy type for interrupt buffer -}
-
- portrec = record {- portdata type -}
- inuse : boolean; {- true if port is used -}
- addr : word; {- selected address -}
- irq : byte; {- selected irq number -}
- oldirq : byte; {- status of irq before initcom -}
- hshake : boolean; {- hardware handshake on/off -}
-
- buf : ^buffer; {- pointer to allocated buffer -}
- bufsize : word; {- size of allocated buffer -}
- oldvec : pointer; {- saved old interrupt vector -}
-
- baud : longint; {- selected baudrate -}
- parity : char; {- selected parity -}
- databit : byte; {- selected number of databits -}
- stopbit : byte; {- selected number of stopbits -}
-
- inptr : word; {- pointer to buffer input index -}
- outptr : word; {- pointer to buffer output index -}
-
- reg0 : byte; {- saved uart register 0 -}
- reg1 : array[1..2] of byte; {- saved uart register 1's -}
- reg2 : byte; {- saved uart register 2 -}
- reg3 : byte; {- saved uart register 3 -}
- reg4 : byte; {- saved uart register 4 -}
- reg6 : byte; {- saved uart register 6 -}
- end;
-
- var
- comresult : integer; {- last error (call comerror) -}
- exitchainp : pointer; {- saved exitproc pointer -}
- oldport21 : byte; {- saved pic status -}
- ports : array[0..7] of portrec; {- the 8 ports supported -}
-
- const
- pic = $20; {- pic control address -}
- eoi = $20; {- pic control byte -}
- testcomenabled : boolean = true; {- test port during opencom -}
-
- procedure disableinterrupts; {- disable interrupt -}
- begin
- inline($fa); {- cli (clear interruptflag) -}
- end;
-
- procedure enableinterrupts; {- enable interrupts -}
- begin
- inline($fb); {- sti (set interrupt flag) -}
- end;
-
- procedure port0int; interrupt; {- interrupt rutine port 0 -}
-
- begin
- with ports[0] do
- begin
- buf^[inptr] := port[addr]; {- read data from port -}
- inc(inptr); {- count one step forward.. }
- if inptr > bufsize then inptr := 1; { .. in buffer -}
- end;
- port[pic] := eoi; {- send eoi to pic -}
- end;
-
- procedure port1int; interrupt; {- interrupt rutine port 1 -}
-
- begin
- with ports[1] do
- begin
- buf^[inptr] := port[addr]; {- read data from port -}
- inc(inptr); {- count one step forward.. }
- if inptr > bufsize then inptr := 1; { .. in buffer -}
- end;
- port[pic] := eoi; {- send eoi to pic -}
- end;
-
- procedure port2int; interrupt; {- interrupt rutine port 2 -}
-
- begin
- with ports[2] do
- begin
- buf^[inptr] := port[addr]; {- read data from port -}
- inc(inptr); {- count one step forward.. }
- if inptr > bufsize then inptr := 1; { .. in buffer -}
- end;
- port[pic] := eoi; {- send eoi to pic -}
- end;
-
- procedure port3int; interrupt; {- interrupt rutine port 3 -}
-
- begin
- with ports[3] do
- begin
- buf^[inptr] := port[addr]; {- read data from port -}
- inc(inptr); {- count one step forward.. }
- if inptr > bufsize then inptr := 1; { .. in buffer -}
- end;
- port[pic] := eoi; {- send eoi to pic -}
- end;
-
- procedure port4int; interrupt; {- interrupt rutine port 4 -}
-
- begin
- with ports[4] do
- begin
- buf^[inptr] := port[addr]; {- read data from port -}
- inc(inptr); {- count one step forward.. }
- if inptr > bufsize then inptr := 1; { .. in buffer -}
- end;
- port[pic] := eoi; {- send eoi to pic -}
- end;
-
- procedure port5int; interrupt; {- interrupt rutine port 5 -}
-
- begin
- with ports[5] do
- begin
- buf^[inptr] := port[addr]; {- read data from port -}
- inc(inptr); {- count one step forward.. }
- if inptr > bufsize then inptr := 1; { .. in buffer -}
- end;
- port[pic] := eoi; {- send eoi to pic -}
- end;
-
-
-
-
- procedure port6int; interrupt; {- interrupt rutine port 6 -}
-
- begin
- with ports[6] do
- begin
- buf^[inptr] := port[addr]; {- read data from port -}
- inc(inptr); {- count one step forward.. }
- if inptr > bufsize then inptr := 1; { .. in buffer -}
- end;
- port[pic] := eoi; {- send eoi to pic -}
- end;
-
- procedure port7int; interrupt; {- interrupt rutine port 7 -}
-
- begin
- with ports[7] do
- begin
- buf^[inptr] := port[addr]; {- read data from port -}
- inc(inptr); {- count one step forward.. }
- if inptr > bufsize then inptr := 1; { .. in buffer -}
- end;
- port[pic] := eoi; {- send eoi to pic -}
- end;
-
- procedure initport(nr : byte; savestatus : boolean); {- port initialize -}
-
- var
- divider : word; {- baudrate divider number -}
- ctrlbits : byte; {- uart control byte -}
-
- begin
- with ports[nr] do
- begin
- divider := 115200 div baud; {- calc baudrate divider -}
-
- ctrlbits := databit - 5; {- insert databits -}
-
- if parity <> 'N' then
- begin
- ctrlbits := ctrlbits or $08; {- insert parity enable -}
- if parity = 'E' then {- enable even parity -}
- ctrlbits := ctrlbits or $10;
- end;
-
- if stopbit = 2 then
- ctrlbits := ctrlbits or $04; {- insert stopbits -}
-
- if savestatus then reg3 := port[addr + $03]; {- save register 3 -}
- port[addr + $03] := $80; {- baudrate change -}
-
- if savestatus then reg0 := port[addr + $00]; {- save lo baud -}
- port[addr + $00] := lo(divider); {- set lo baud -}
-
- if savestatus then reg1[2] := port[addr + $01]; {- save hi baud -}
- port[addr + $01] := hi(divider); {- set hi baud -}
-
- port[addr + $03] := ctrlbits; {- set control reg. -}
- if savestatus then reg6 := port[addr + $06]; {- save register 6 -}
- end;
- end;
-
- function irqused(irqnum : byte) : boolean;
-
- var
- count : byte;
- found : boolean;
-
- begin
- found := false; {- irq not found -}
- count := 0; {- start with port 0 -}
-
- while (count <= 7) and not found do {- count the 8 ports -}
- with ports[count] do
- begin
- if inuse then
- found := irqnum = irq; {- check irq match -}
- inc(count); {- next port -}
- end;
-
- irqused := found; {- return irq found -}
- end;
-
- procedure enabletestcom;
- begin
- testcomenabled := true;
- end;
-
- procedure disabletestcom;
- begin
- testcomenabled := false;
- end;
-
-
-
-
- function testcom(nr : byte) : boolean;
-
- var
- oldreg0 : byte;
- oldreg1 : byte;
- oldreg4 : byte;
- oldreg5 : byte;
- oldreg6 : byte;
- oldinptr : word;
- oldoutptr : word;
- timeout : integer;
-
- begin
- testcom := false;
-
- with ports[nr] do
- begin
- if inuse then
- begin
- oldinptr := inptr;
- oldoutptr := outptr;
- oldreg1 := port[addr + $01];
- oldreg4 := port[addr + $04];
- oldreg5 := port[addr + $05];
- oldreg6 := port[addr + $06];
-
- port[addr + $05] := $00;
- port[addr + $04] := port[addr + $04] or $10;
-
- oldreg0 := port[addr + $00];
- outptr := inptr;
-
- timeout := maxint;
- port[addr + $00] := oldreg0;
-
- while (port[addr + $05] and $01 = $00) and (timeout <> 0) do
- dec(timeout);
-
- if timeout <> 0 then
- begin
- if port[addr + $00] = oldreg0 then
- begin
- if irq in [0..7] then
- begin
- timeout := maxint;
- outptr := inptr;
-
- port[addr + $01] := $08;
- port[addr + $04] := $08;
- port[addr + $06] := port[addr + $06] or $01;
-
- while (inptr = outptr) and (timeout <> 0) do
- dec(timeout);
-
- port[addr + $01] := oldreg1;
-
- if (inptr <> outptr) then
- testcom := true
- else
- comresult := 8;
- end
- else
- testcom := true;
- end
- else
- comresult := 7; {- loopback test failed -}
- end
- else
- comresult := 6; {- timeout -}
-
- port[addr + $04] := oldreg4;
- port[addr + $05] := oldreg5;
- port[addr + $06] := oldreg6;
-
- for timeout := 1 to maxint do;
- if port[addr + $00] = 0 then;
-
- inptr := oldinptr;
- outptr := oldoutptr;
- end
- else
- comresult := 2; {- port not open -}
- end;
- end;
-
- procedure closecom(nr : byte);
-
- begin
- with ports[nr] do
- begin
- if inuse then
- begin
- inuse := false;
-
- if irq <> 255 then {- if interrupt used -}
- begin
- freemem(buf,bufsize); {- deallocate buffer -}
- disableinterrupts;
- port[$21] := port[$21] or ($01 shl irq) and oldirq; {-restore-}
- port[addr + $04] := reg4; {- disable uart out2 -}
- port[addr + $01] := reg1[1]; {- disable uart int. -}
- setintvec($08+irq,oldvec); {- restore int.vector-}
- enableinterrupts;
- end;
-
- port[addr + $03] := $80; {- uart baud set -}
- port[addr + $00] := reg0; {- reset lo baud -}
- port[addr + $01] := reg1[2]; {- reset hi baud -}
- port[addr + $03] := reg3; {- restore uart ctrl.-}
- port[addr + $06] := reg6; {- restore uart reg6 -}
- end
- else
- comresult := 2; {- port not in use -}
- end;
- end;
-
-
-
-
- function opencom
- (nr : byte; address : word; irqnum : byte; baudrate : longint;
- paritybit : char; databits, stopbits : byte; buffersize : word;
- handshake : boolean) : boolean;
-
- var
- intvec : pointer;
- olderr : integer;
-
- begin
- opencom := false;
-
- if (irqnum = 255) or
- ((irqnum in [0..7]) and (maxavail >= longint(buffersize))
- and not irqused(irqnum)) then
- with ports[nr] do
- begin
- if not inuse and (address <= $3f8) then
- begin
- inuse := true; {- port now in use -}
-
- addr := address; {- save parameters -}
- irq := irqnum;
- hshake := handshake;
- bufsize := buffersize;
- baud := baudrate;
- parity := paritybit;
- databit := databits;
- stopbit := stopbits;
-
- inptr := 1; {- reset inputpointer -}
- outptr := 1; {- reset outputpointer -}
-
- if (irq in [0..7]) and (bufsize > 0) then
- begin
- getmem(buf,bufsize); {- allocate buffer -}
- getintvec($08+irq,oldvec); {- save interrupt vector -}
-
- case nr of {- find the interrupt proc.-}
- 0 : intvec := @port0int;
- 1 : intvec := @port1int;
- 2 : intvec := @port2int;
- 3 : intvec := @port3int;
- 4 : intvec := @port4int;
- 5 : intvec := @port5int;
- 6 : intvec := @port6int;
- 7 : intvec := @port7int;
- end;
-
- reg1[1] := port[addr + $01]; {- save register 1 -}
- reg4 := port[addr + $04]; {- save register 4 -}
- oldirq := port[$21] or not ($01 shl irq); {- save pic irq-}
-
- disableinterrupts; {- disable interrupts -}
- setintvec($08+irq,intvec); {- set the interrupt vector-}
- port[addr + $04] := $08; {- enable out2 on port -}
- port[addr + $01] := $01; {- set port data avail.int.-}
- port[$21] := port[$21] and not ($01 shl irq); {- enable irq-}
- enableinterrupts; {- enable interrupts again -}
- end;
-
- initport(nr,true); {- initialize port -}
-
- if testcomenabled then
- begin
- if not testcom(nr) then
- begin
- olderr := comresult;
- closecom(nr);
- comresult := olderr;
- end
- else
- opencom := true;
- end
- else
- opencom := true;
-
- if port[addr + $00] = 0 then; {- remove any pending character -}
- if port[addr + $05] = 0 then; {- reset line status register -}
-
- port[addr + $04] := port[addr + $04] or $01; {- enable dtr -}
- end
- else if inuse then
- comresult := 3 {- port already in use -}
- else if (address > $3f8) then
- comresult := 5; {- invalid port address -}
- end
- else if (maxavail >= buffersize) then {- not enough memory -}
- comresult := 1
- else if irqused(irqnum) then {- irq already used -}
- comresult := 4;
- end;
-
- procedure resetcom(nr : byte);
-
- begin
- with ports[nr] do
- begin
- if inuse then {- is port defined ? -}
- begin
- inptr := 1; {- reset buffer pointers -}
- outptr := 1;
- initport(nr,false); {- reinitialize the port -}
-
- if port[addr + $00] = 0 then; {- remove any pending character -}
- if port[addr + $05] = 0 then; {- reset line status register -}
- end
- else
- comresult := 2; {- port not open -}
- end;
- end;
-
- procedure comsettings(nr : byte; baudrate : longint; paritybit : char;
- databits, stopbits : byte; handshake : boolean);
-
- begin
- with ports[nr] do
- begin
- if inuse then {- is port in use -}
- begin
- baud := baudrate; {- save parameters -}
- parity := paritybit;
- databit := databits;
- stopbit := stopbits;
- hshake := handshake;
-
- initport(nr,false); {- reinit port -}
- end
- else
- comresult := 2; {- port not in use -}
- end;
- end;
-
-
-
-
- function comaddress(comport : byte) : word;
-
- begin
- if comport in [1..8] then
- comaddress := memw[$40:(pred(comport) shl 1)] {- bios data table -}
- else
- comresult := 5; {- invalid port -}
- end;
-
- function writecom(nr : byte; ch : char) : boolean;
-
- var
- count : integer;
-
- begin
- writecom := true;
-
- with ports[nr] do
- if inuse then
- begin
- while port[addr + $05] and $20 = $00 do; {- wait until char send -}
-
- if not hshake then
- port[addr] := ord(ch) {- send char to port -}
- else
- begin
- port[addr + $04] := $0b; {- out2, dtr, rts -}
- count := maxint;
-
- while (port[addr + $06] and $10 = 0) and (count <> 0) do
- dec(count); {- wait for cts -}
-
- if count <> 0 then {- if not timeout -}
- port[addr] := ord(ch) {- send char to port -}
- else
- begin
- comresult := 6; {- timeout error -}
- writecom := false;
- end;
- end;
- end
- else
- begin
- comresult := 2; {- port not in use -}
- writecom := false;
- end;
- end;
-
- function writecomstring(nr : byte; st : string) : boolean;
-
- var
- ok : boolean;
- count : byte;
-
- begin
- if length(st) > 0 then {- any chars to send ? -}
- begin
- ok := true;
- count := 1;
- while (count <= length(st)) and ok do {- count chars -}
- begin
- ok := writecom(nr,st[count]); {- send char -}
- inc(count); {- next character -}
- end;
- writecomstring := ok; {- return status -}
- end;
- end;
-
- function checkcom(nr : byte; var ch : char) : boolean;
-
- begin
- with ports[nr] do
- begin
- if inptr <> outptr then {- any char in buffer ? -}
- begin
- ch := chr(buf^[outptr]); {- get char from buffer -}
- inc(outptr); {- count outpointer up -}
- if outptr > bufsize then outptr := 1;
- checkcom := true;
- end
- else
- checkcom := false; {- no char in buffer -}
- end;
- end;
-
-
-
- function comerror : integer;
-
- begin
- comerror := comresult; {- return last error -}
- comresult := 0;
- end;
-
- function comused(nr : byte) : boolean;
-
- begin
- comused := ports[nr].inuse; {- return used status -}
- end;
-
- function irqinuse(irqnum : byte) : boolean;
-
- var
- irqon : byte;
- mask : byte;
-
- begin
- irqinuse := false;
-
- if irqnum in [0..7] then
- begin
- irqon := port[$21]; {-1111 0100-}
- mask := ($01 shl irqnum);
- irqinuse := irqon or not mask = not mask;
- end;
- end;
-
- procedure setirqpriority(irqnum : byte);
-
- begin
- if irqnum in [0..7] then
- begin
- if irqnum > 0 then dec(irqnum)
- else irqnum := 7;
-
- disableinterrupts;
- port[pic] := $c0 + irqnum;
- enableinterrupts;
- end;
- end;
-
- procedure clearbuffer(nr : byte);
-
- begin
- with ports[nr] do
- if inuse and (bufsize > 0) then
- begin
- outptr := inptr;
- end;
- end;
-
- procedure deinit;
-
- var
- count : byte;
-
- begin
- for count := 0 to 7 do closecom(count); {- close open ports -}
-
- disableinterrupts;
- port[$21] := oldport21; {- restore pic status -}
- port[$20] := $c7; {- irq0 1. priority -}
- enableinterrupts;
-
- exitproc := exitchainp; {- restore exitproc -}
- end;
-
- procedure init;
-
- var
- count : byte;
-
- begin
- comresult := 0;
- exitchainp := exitproc; {- save exitproc -}
- exitproc := @deinit; {- set exitproc -}
-
- for count := 0 to 7 do
- ports[count].inuse := false; {- no ports open -}
-
- oldport21 := port[$21]; {- save pic status -}
- end;
-
- {*****************************************************************************}
-
- begin
- init;
- end.
-
- etasync v.1.04, 9/4 1992 et-soft
- turbo pascal unit with support for up to 8 serial ports.
-
-