{Communications routines for TURBO Pascal written by Alan Bishop Handles standart COM1: ports with interrupt handling. Includes support for only one port, and with no overflow, parity, or other such checking. However, even some of the best communication programs don't do this anyway, and I never use it. If you make modifications, please send me a copy if you have a simple way of doing it (CIS EMAIL, Usenet, MCI Mail, etc) Hope these are useful. Alan Bishop - CIS - 72405,647 Usenet - bishop@ecsvax MCI Mail - ABISHOP } {$C-} program commcall; const recv_buf_size = 2048; {this may be changed to whatever size you need} type buffer_pointer = integer; {just for readability} smallstring = string[2]; {for compatibility with my INKEY routine} bigstring = string[255]; {general purpose} storage = byte; {readability} check_bit = (none,even); {readability and expansion} var buf_start, buf_end : buffer_pointer; {NOTE: these will change by them- selves in the background} recv_buffer : array [1..recv_buf_size] of storage; {also self- changing} speed : integer; {I don't know the top speed these routines will handle} dbits : 7..8; {only ones most people use} stop_bits : 1..2; {does anyone use 2?} parity : check_bit; {even and none are the common ones} procedure check_range(var range : integer); {this is used to adjust buffer pointers} begin if range > recv_buf_size then range := 1; end; function commpressed : boolean; {like keypressed, but for the comm port} begin commpressed := (buf_start <> buf_end); end; function cinkey : smallstring; {returns nothing or a code from the buffer - 2 bytes are used for ease of use with a two byte inkey routine} var result : smallstring; temp : integer; begin if not commpressed then result := '' else begin inline ($FA); {very important} temp := recv_buffer[buf_start]; buf_start := buf_start +1; check_range(buf_start); inline ($FB); {very important} result := chr(temp); end; cinkey := result; end; function carrier : boolean; {true if carrier, false if not} begin carrier := odd(port[$3FE] shr 7); end; procedure set_up_recv_buffer; {big procedure isn't it?} begin buf_start := 1; buf_end := 1; end; procedure set_baud(rate : integer); {has no problems with non-standard bauds} var a : byte; divided : real; begin if rate<=9600 then begin speed := rate; divided := 115200.0/rate; rate := trunc(divided); a := port[$3fb]; if a < 128 then a := a+128; port[$3fb] := a; port[$3f8] := lo(rate); port[$3f9] := hi(rate); port[$3fb] := a-128; end; end; procedure update_uart; {uses dbits, stop_bits, and parity} var a : byte; begin a := dbits-5; if stop_bits = 2 then a := a + 4; if parity = even then a := a + 24; port[$3fb] := a; end; procedure init_port; {sets up most anything necessary} var a,b : integer; buf_len : integer; begin update_uart; port[$3f9] := 1; {interupt enable} a := port[$3fc]; if odd(a) then a := 1 else a := 0; {keep terminal ready} a := a+10; port[$3fc] := a; {turn on req to send and out2} a := port[$3fa]; port[$21] := $c; set_baud(1200); buf_len := recv_buf_size; {this is the background routine} inline ( $1E/ $0E/ $1F/ $BA/*+23/ $B8/$0C/$25/ $CD/$21/ $8B/$BE/BUF_LEN/ $89/$3E/*+87/ $1F/ $2E/$8C/$1E/*+83/ $EB/$51/ $FB/ $1E/ $50/ $53/ $52/ $56/ $2E/$8E/$1E/*+70/ $BA/$F8/$03/ $EC/ $BE/RECV_BUFFER/ $8B/$1E/BUF_END/ $88/$40/$FF/ $43/ $E8/$22/$00/ $89/$1E/BUF_END/ $3B/$1E/BUF_START/ $75/$0C/ $8B/$1E/BUF_START/ $43/ $E8/$10/$00/ $89/$1E/BUF_START/ $BA/$20/$00/ $B0/$20/ $EE/ $5E/ $5A/ $5B/ $58/ $1F/ $CF/ $2E/$8B/$16/*+11/ $42/ $39/$DA/ $75/$03/ $BB/$01/$00/ $C3/ $00/$00/ $00/$01/ $90 ); end; procedure term_ready(state : boolean); {send a true for on, false for off} var a : byte; begin a := port[$3fc]; if odd(a) then a := a - 1; a := a + ord(state); port[$3fc] := a; end; procedure remove_port; {gets rid of most problems} var a : byte; begin port[$3f9] := 0; a := port[$3fc]; if odd(a) then a := 1 else a := 0; port[$3fc] := a; port[$21] := $BC; end; procedure write_byte(to_send : bigstring); {sends out up to 255 bytes} var a,b,c : byte; begin for b := 1 to length(to_send) do begin c := ord(to_send[b]); repeat a := port[$3fd]; until odd(a shr 5); port[$3f8] := c; end; end; procedure break; {send a break} var a,b : byte; begin a := port[$3fb]; b := a; if b > 127 then b := b - 128; if b <= 63 then b := b + 64; port[$3fb] := b; delay(400); port[$3fb] := a; end; procedure setup; {initialize most stuff - you may want to replace this routine completely} var a : byte; begin dbits := 8; parity := none; stop_bits := 1; speed := 1200; init_port; term_ready(true); end; { The following is a sample program illustrating the use of these routines. The '|' key exits and ESC sends a break. Because of TURBO's standard handling of function keys and other things like that, they will also. } var leave : boolean; a : char; b : smallstring; begin setup; leave := false; while not leave do begin if keypressed then begin read(kbd,a); if a = '|' then leave := true else if a = chr(27) then break else write_byte(a); end; if commpressed then write(cinkey); end; remove_port; term_ready(false); end.