_STRUCTURED PROGRAMMING COLUMN_ by Jeff Duntemann [LISTING ONE] CONST COMPORT = 2; { 1 = COM1: 2 = COM2: } COMBASE = $2F8; PORTBASE = COMBASE OR (COMPORT SHL 8); { $3F8 for COM1: $2F8 for COM2: } { 8250 control registers, masks, etc. } RBR = PORTBASE; { 8250 Receive Buffer Register } THR = PORTBASE; { 8250 Transmit Holding Register } IER = PORTBASE + 1; { 8250 Interrupt Enable Register } LCR = PORTBASE + 3; { 8250 Line Control Register } MCR = PORTBASE + 4; { 8250 Modem Control Register } LSR = PORTBASE + 5; { 8250 Line Status Register } DLL = PORTBASE; { 8250 Divisor Latch LSB when DLAB=1 } DLM = PORTBASE + 1; { 8250 Divisor Latch MSB when DLAB=1 } DLAB = $80; { Value for Divisor Latch Access Bit } THRE = $20; { Value for Transmit Holding Register Empty bit } BAUD300 = 384; { Value for 300 baud operation } BAUD1200 = 96; { Value for 1200 baud operation } DTR = $01; { Value for Data Terminal Ready } RTS = $02; { Value for Ready To Send } NOPARITY = 0; { Comm format value for no parity } BITS8 = $03; { Comm format value for 8 bits } [LISTING TWO] {--------------------------------------------------------------} { POLLTERM } { by Jeff Duntemann } { Turbo Pascal V6.0 } { Last update 2/3/91 } { This is a *truly* dumb terminal program that operates by } { polling the serial port's registers and does NOT use } { interrupts. It's a good illustration of why interrupts are } { necessary... } { PollTerm can be set to use either COM1: or COM2: by setting } { the COMPORT constant to 1 (for COM1) or 2 (for COM2:) as } { as appropriate and recompiling. } {--------------------------------------------------------------} PROGRAM PollTerm; USES DOS,CRT; {$I REGISTERS.DEF } VAR Quit : Boolean; { Flag for exiting the program } HiBaud : Boolean; { True if 1200 baud is being used } KeyChar : Char; { Character from keyboard } CommChar : Char; { Character from the comm port } Divisor : Word; { Divisor value for setting baud rate } Clearit : Byte; { Dummy variable } NoShow : SET OF Char; { Don't show characters set } PROCEDURE SetRate(Divisor : Word); BEGIN { Set the DLAB flag to 1: } Port[LCR] := Port[LCR] OR DLAB; { Load the divisor latches: } Port[DLL] := Lo(Divisor); Port[DLM] := Hi(Divisor); { Clear the DLAB flag to 0:} Port[LCR] := Port[LCR] AND (NOT DLAB); END; FUNCTION InStat : Boolean; BEGIN { Bit 0 of LSR goes high when a char is waiting: } InStat := Boolean(Port[LSR] AND $01); END; FUNCTION OutStat : Boolean; BEGIN { Bit 5 of LSR goes high when the THR is ready for another char: } OutStat := ((LSR AND THRE) = THRE); END; FUNCTION InChar : Char; BEGIN InChar := Char(Port[RBR]); END; PROCEDURE OutChar(Ch : Char); { Send a character to the comm port } BEGIN Port[THR] := Byte(Ch) { Put character ito Transmit Holding Register } END; PROCEDURE UhUh; VAR I : Integer; BEGIN FOR I := 1 TO 2 DO BEGIN Sound(50); Delay(50); NoSound; Delay(50); END; END; {>>>>>POLLTERM MAIN PROGRAM<<<<<} BEGIN HiBaud := True; { PollTerm defaults to 1200 baud; if "300"} Divisor := BAUD1200; { is entered after "POLLTERM" on the } IF ParamCount > 0 THEN { command line, then 300 baud is used } IF ParamStr(1) = '300' THEN BEGIN HiBaud := False; Divisor := BAUD300 END; SetRate(Divisor); { Set the baud rate } Port[IER] := 0; { Disable 8259 interrupts } Port[LCR] := BITS8 OR NOPARITY; { Set word length and parity } Port[MCR] := DTR OR RTS; { Enable DTR, & RTS } Clearit := Port[RBR]; { Clear any garbage from RBR } Clearit := Port[LSR]; { Clear any garbage from LSR } DirectVideo := True; NoShow := [#0,#127]; { Don't display NUL or RUBOUT } ClrScr; Writeln('>>>POLLTERM by Jeff Duntemann'); Quit := False; { Exit POLLTERM when Quit goes to True } REPEAT IF InStat THEN { If a character comes in from the modem } BEGIN CommChar := InChar; { Go get character } CommChar := Char(Byte(CommChar) AND $7F); { Mask off high bit } IF NOT (CommChar IN NoShow) THEN { If we can show it,} Write(CommChar) { then show it! } END; IF KeyPressed THEN { If a character is typed at the keyboard } BEGIN KeyChar := ReadKey; { First, read the keystroke } IF KeyChar = Chr(0) THEN { We have an extended scan code here } UhUh { but we're not using it! } ELSE CASE Ord(KeyChar) OF 24 : Quit := True; { Ctrl-X: Exit PollTerm } 26 : ClrScr; { Ctrl-Z: Clear the screen } ELSE BEGIN WHILE NOT OutStat DO BEGIN END; { I.e., nothing } OutChar(KeyChar) END; END; { CASE } END UNTIL Quit END.