home *** CD-ROM | disk | FTP | other *** search
- {$D-} { Debug Information Off }
- {$S-} { Stack Checking Off }
- {$V-} { String Checking Off }
-
- Unit Async;
- { Part of BBS Onliner Interface }
- { Copyright (C) 1990 Andrew J. Mead
- All Rights Reserved. }
-
- { original version 9/5/90
- history found in IOLIB.PAS }
-
-
- INTERFACE
-
- Function CARRIER : boolean; { Carrier Detect function }
- Procedure DROPCARRIER; { Drop Carrier }
- Procedure ASYNCINT; Interrupt; { Comport Interrupt Routine }
- Procedure SENDCHAR(outchar : char); { Comport Output Routine }
- Function CHARREADY : boolean; { Character Ready for Input }
- Function READBUFFER : char; { Get Character from buffer }
- Procedure CLEARINBUFFER; { Empty input buffer }
- Procedure SETBUFFERSIZE(newsize : integer); { Set buffer size, defaul = 1k }
- Procedure INTINIT; { Install Comport Interrupt }
- Procedure INTEND; { Disable Comport Interrupt }
-
- IMPLEMENTATION
-
- Uses
- boidecl,
- iolib,
- dos;
-
- Const
- null = #0;
- maxbuffsize = 1024;
-
- THRoff = $00; { 8250 UART Transmitter Holding Register offset }
- RBRoff = $00; { 8250 UART Receiver Buffer Register offset }
-
- DLLoff = $00; { 8250 UART Divisor Latch Least Significant Byte offset }
- DLMoff = $01; { 8250 UART Divisor Latch Most Significant Byte offset }
-
- IERoff = $01; { 8250 UART Interrupt Enable Register offset }
- IIRoff = $02; { 8250 UART Interrupt Identification Register offset }
- LCRoff = $03; { 8250 UART Line Control Register offset }
- MCRoff = $04; { 8250 UART Modem Control Register offset }
- LSRoff = $05; { 8250 UART Line Status Register offset }
- MSRoff = $06; { 8250 UART Modem Status Register offset }
-
- PICCMD = $20; { 8259A Programmable Interrupt Controller Port }
- PICMSK = $21; { 8259A Programmable Interrupt Controller Port }
-
- RTSbit = $20; { Ready To Send bit in LSR }
- CTSbit = $10; { Clear To Send bit in MSR }
- DCDbit = $80; { Data Carrier Detect (RLSD) bit in MSR }
- DCval = $08; { changes carrier detect bit in MSR }
- DTRhigh = $00; { force DTR high value }
-
- Type
- portbufftype = array [1..maxbuffsize] of char;
-
- Var
- portbuffer : portbufftype; { Circular input buffer }
- bufflimit : integer; { Current maximum buffer size }
- buffsize : integer; { Number of character in buffer }
- buffend : integer; { Index pointing to last character in buffer }
- buffstart : integer; { Index pointing to first character in buffer }
- asyncvector : pointer; { original interrupt vector }
- IIRstatus : byte; { 8250 UART IIR status byte }
- LSRstatus : byte; { 8250 UART LCR status byte }
-
- Function CARRIER : boolean;
- { This function will return 'true' if a carrier is present.}
-
- begin {* fCarrier *}
- Carrier := dolocal or (not checkcd) or
- ((port[portadd + MSRoff] and DCDbit) = DCDbit)
- end; {* fCarrier *}
-
- Procedure DROPCARRIER;
- { This function will force the modem to hang up the phone.}
- var
- timebase : longint;
-
- begin {* DropCarrier *}
- TimerSet(timebase);
- repeat port[portadd + MCRoff] := DTRhigh
- until GetTimer(timebase,2)
- end; {* DropCarrier *}
-
- Procedure ASYNCINT;
- begin {* AsyncInt *}
- inline($FB); { STI }
- IIRstatus := port[portadd + IIRoff]; { read IIR status }
- if ((IIRstatus and $06) = $04) then { check to see if character waiting }
- begin { place character in buffer }
- if buffsize < bufflimit then
- begin
- portbuffer[buffend] := Char(Port[portadd + RBRoff]);
- if buffend < bufflimit then Inc(buffend) else buffend := 1;
- Inc(buffsize)
- end
- else LSRstatus := Port[portadd + RBRoff] { clear LSR status byte }
- end
- else if ((IIRstatus and $06) = $06) then LSRstatus := Port[portadd + RBRoff];
- inline($FA); { CLI }
- port[PICCMD] := $20 { reset 8259A PIC }
- end; {* AsyncInt *}
-
- Procedure SENDCHAR(outchar : char);
- var
- timecnt : word;
- timebase : longint;
-
- begin {* SendChar *}
- TimerSet(timebase);
- timecnt := 0;
- while (port[portadd + LSRoff] and RTSbit <> RTSbit) or { UART ready }
- (baudlock and (port[portadd + MSRoff] and CTSbit <> CTSbit)) do
- begin { ^^ modem ready }
- Inc(timecnt);
- if not Carrier then DoTimeOut(false)
- else if timecnt mod 1000 = 0 then if GetTimer(timebase,60) then DoTimeOut(false)
- end;
- port[portadd + RBRoff] := ord(outchar) { send character }
- end; {* SendChar *}
-
- Function CHARREADY : boolean;
- begin {* fCharReady *}
- CharReady := buffsize > 0
- end; {* fCharReady *}
-
- Function READBUFFER : char;
- var
- rb : char;
-
- begin {* fReadBuffer *}
- if CharReady then
- begin
- rb := portbuffer[buffstart];
- if buffstart < bufflimit then Inc(buffstart) else buffstart := 1;
- Dec(buffsize);
- ReadBuffer := rb
- end
- else ReadBuffer := null
- end; {* fReadBuffer *}
-
- Procedure CLEARINBUFFER;
- begin {* ClearInBuffer *}
- buffend := buffstart;
- buffsize := 0
- end; {* ClearInBuffer *}
-
- Procedure SETBUFFERSIZE(newsize : integer);
- begin {* SetBufferSize *}
- if (newsize > 1) and (newsize <= maxbuffsize) then
- begin
- buffstart := 1;
- ClearInBuffer;
- bufflimit := newsize
- end;
- end; {* SetBufferSize *}
-
- Procedure INTINIT;
- var
- inittemp : byte;
-
- begin {* IntInit *}
- fillchar(portbuffer,sizeof(portbuffer),32);
- buffend := 1;
- buffstart := 1;
- buffsize := 0;
- bufflimit := maxbuffsize;
- GetIntVec(portint,asyncvector); { save old interrupt vector }
- SetIntVec(portint,@AsyncInt); { install AsyncInt vector }
- Port[PICMSK] := Port[PICMSK] and initval; { access 8259A PIC }
- Port[portadd + LCRoff] := Port[portadd + LCRoff] and $7F;
- { disable divisor latch register }
- Port[portadd + IERoff] := $01; { enable interrupts }
- Port[portadd + MCRoff] := $0B; { set RTS, DTR and OUT2 }
- { Port[portadd + MSRoff] := $80; }
- inittemp := Port[portadd + LSRoff]; { reset LSR }
- Port[PICCMD] := $20 { reset 8259A PIC }
- end; {* IntInit *}
-
- Procedure INTEND;
- begin {* IntEnd *}
- SetIntVec(portint,asyncvector); { re-install old interrupt vector }
- Port[PICCMD] := $20 { reset 8259A PIC }
- end; {* IntEnd *}
-
- end. Unit