home *** CD-ROM | disk | FTP | other *** search
- program TTY;
-
- uses
- DOS,CRT;
-
- const
- RBR = $3F8; {Port address - RX Buffer Register}
- THR = $3F8; {Transmit Hold Register}
- DLL = $3F8; {Low byte of divisor}
- DLM = $3F9; {High Byte of Divisor}
- IER = $3F9; {Overlays INT Enable Register}
- LCR = $3FB; {Line Control Register}
- MCR = $3FC; {Modem Control Register}
- LSR = $3FD; {Line Status Register}
-
- BAUD300 = 384; {300 Baud Divisor}
- BAUD1200 = 96; {1200 Baud Divisor}
- RTS = $02; {Mask for ReadyToSend}
- ERBFI = $01; {Mask to enable Receive INT's}
- THRE = $20; {Mask for THRE}
- TWOSTOP = $04; {Mask for 2 stop bits (110 baud only)}
- ONESTOP = $00; {Mask for 1 stop bit}
- DTR = $01; {Mask for DTR}
- DLAB = $80; {Mask for DLAB}
- NOPARITY = $00; {Mask for no parity}
- EIGHTBITS = $03; {Mask for 8 bits/char}
-
- OCW1 = $21; {Mask for enable bits for 8259}
- OCW2 = $20; {Port for 8259 Commands}
- NSEOI = $20; {Non-specific End-Of-Interrupt Command}
- OUT2 = $08; {Mask for OUT2}
- IRQ4 = $10; {Mask to dis/enable hardware int level 4}
- PORT1INT = 12; {Int vector number for IRQ4}
-
- QUEUEMAX = 255; {Max queue subscript, 2^n-1}
-
- var
-
- queue : array [0..QUEUEMAX] of byte; {Circular buffer}
- queueIn : integer;
- queueOut : integer; {Buffer pointers}
- oldVector : pointer; {Storage for old INT vector}
- ch : char; {Keyboard Char}
- temp : integer;
-
- procedure InterruptsOn; inline($FB); {Turn on interrupts}
-
- {$IFOPT R+} {Don't forget to turn Range Checking on...}
- {$DEFINE RANGE}
- {$ENDIF}
-
- {$R-}
-
- procedure Port1ISR; Interrupt; {INT Service Routine for port 1}
- begin
- InterruptsOn;
- queueIn := Succ(queueIn) and QUEUEMAX;
- if queueIn = queueOut then {Queue full, put pointer back}
- queueIn := Pred(queueIn) and QUEUEMAX;
- queue[queueIn] := Port[RBR];
- Port[OCW2] := NSEOI
- end;
-
- {$IFDEF RANGE}
- {$R+}
- {$ENDIF}
-
- {$F+}
-
- Procedure RestoreIntVec; {Exit proc to restore int vector}
- begin {shutoff ints and drop dtr}
- Port[IER] := 0; {INTs off at UART}
- Port[OCW1] := Port[OCW1] or IRQ4; {INTs off at 8259}
- Port[MCR] := 0; {DTR, RTS, OUT2 off}
- SetIntVec(PORT1INT,oldVector)
- end;
-
- {$F-}
-
- begin
- Writeln('GEnie Borland RoundTable Sample Dumb Terminal');
- Writeln('Using COM1 at 1200 baud, 8 data bits, no parity, 1 stop bit');
- Writeln('Press Alt-X to exit.');
- CheckBreak := FALSE;
- DirectVideo := TRUE;
- queueIn := 0;
- queueOut := 0;
- Port[IER] := 0; {Disable UART INT's}
-
- {Here's where we take over the comm interrupt}
-
- GetIntVec(PORT1INT,oldVector);
- exitProc := Addr(RestoreIntVec);
- SetIntVec(PORT1INT,Addr(Port1ISR));
-
- {Initialize the UART}
-
- Port[LCR] := Port[LCR] or DLAB; {Allow access to Divisor}
- Port[DLL] := Lo(BAUD1200); {Baud Rate to 1200}
- Port[DLM] := Hi(BAUD1200); {Ditto...}
- Port[LCR] := EIGHTBITS or ONESTOP or NOPARITY;
- Port[MCR] := DTR or RTS or OUT2;
-
- {Turn on INTs at 8259}
-
- Port[OCW1] := Port[OCW1] and not (IRQ4);
- if Port[LSR] <> 0 then; {Clear any errors}
- if Port[RBR] <> 0 then; {Clear trash from RX buffer}
- Port[IER] := ERBFI; {Enable UART RX INTs}
- repeat
- while queueIN <> queueOut do
- begin
- temp := Succ(queueOut) and QUEUEMAX;
- Write(Char(queue[temp] and $7F)); {Strip Hi Bit}
- queueOut := TEMP;
- end;
- if KeyPressed then
- if Port[LSR] and THRE <> 0 then
- begin
- ch := ReadKey;
- if (ch = #0) and KeyPressed then
- begin
- ch := Readkey;
- if ch = #45 then
- Halt {Pressed Alt-X, exit}
- end
- else
- Port[THR] := Byte(ch)
- end
- until FALSE;
- end.
-