home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / turbopas / tp / utl2 / commcall.pzs / COMMCALL.PAS
Pascal/Delphi Source File  |  1994-07-23  |  6KB  |  307 lines

  1. {Communications routines for TURBO Pascal written by Alan Bishop
  2.  Handles standart COM1: ports with interrupt handling.  Includes
  3.  support for only one port, and with no overflow, parity, or other
  4.  such checking.  However, even some of the best communication programs
  5.  don't do this anyway, and I never use it.  If you make modifications,
  6.  please send me a copy if you have a simple way of doing it (CIS EMAIL,
  7.  Usenet, MCI Mail, etc)  Hope these are useful.
  8.  
  9. Alan Bishop - CIS      - 72405,647
  10.               Usenet   - bishop@ecsvax
  11.               MCI Mail - ABISHOP
  12. }
  13.  
  14. {$C-}
  15. program commcall;
  16.  
  17. const recv_buf_size = 2048;  {this may be changed to whatever size you need}
  18.  
  19. type buffer_pointer   = integer;  {just for readability}
  20.      smallstring      = string[2];  {for compatibility with my INKEY routine}
  21.      bigstring        = string[255];  {general purpose}
  22.      storage          = byte;  {readability}
  23.      check_bit        = (none,even);  {readability and expansion}
  24.  
  25. var buf_start, buf_end    : buffer_pointer;  {NOTE: these will change by them-
  26.                                              selves in the background}
  27.     recv_buffer           : array [1..recv_buf_size] of storage; {also self-
  28.                                                                   changing}
  29.     speed                 : integer;  {I don't know the top speed these
  30.                                        routines will handle}
  31.     dbits                 : 7..8;  {only ones most people use}
  32.     stop_bits             : 1..2;  {does anyone use 2?}
  33.     parity                : check_bit;  {even and none are the common ones}
  34.  
  35. procedure check_range(var range : integer);
  36.  
  37. {this is used to adjust buffer pointers}
  38.  
  39. begin
  40.  if range > recv_buf_size then range := 1;
  41. end;
  42.  
  43. function commpressed : boolean;
  44.  
  45. {like keypressed, but for the comm port}
  46.  
  47. begin
  48.  commpressed := (buf_start <> buf_end);
  49. end;
  50.  
  51. function cinkey : smallstring;
  52.  
  53. {returns nothing or a code from the buffer - 2 bytes are used for
  54.  ease of use with a two byte inkey routine}
  55.  
  56. var result : smallstring;
  57.     temp   : integer;
  58.  
  59. begin
  60.  if not commpressed then result := ''
  61.  else
  62.  begin
  63.   inline ($FA);  {very important}
  64.   temp := recv_buffer[buf_start];
  65.   buf_start := buf_start +1;
  66.   check_range(buf_start);
  67.   inline ($FB);  {very important}
  68.   result := chr(temp);
  69.  end;
  70.  cinkey := result;
  71. end;
  72.  
  73.  
  74. function carrier : boolean;
  75.  
  76. {true if carrier, false if not}
  77.  
  78. begin
  79.  carrier := odd(port[$3FE] shr 7);
  80. end;
  81.  
  82.  
  83. procedure set_up_recv_buffer;
  84.  
  85. {big procedure isn't it?}
  86.  
  87. begin
  88.  buf_start := 1;
  89.  buf_end   := 1;
  90. end;
  91.  
  92.  
  93. procedure set_baud(rate : integer);
  94.  
  95. {has no problems with non-standard bauds}
  96.  
  97. var a : byte;
  98.     divided : real;
  99.  
  100. begin
  101.  if rate<=9600 then
  102.  begin
  103.   speed := rate;
  104.   divided := 115200.0/rate;
  105.   rate := trunc(divided);
  106.   a := port[$3fb];
  107.   if a < 128 then a := a+128;
  108.   port[$3fb] := a;
  109.   port[$3f8] := lo(rate);
  110.   port[$3f9] := hi(rate);
  111.   port[$3fb] := a-128;
  112.  end;
  113. end;
  114.  
  115. procedure update_uart;
  116.  
  117. {uses dbits, stop_bits, and parity}
  118.  
  119. var a : byte;
  120.  
  121. begin
  122.  a := dbits-5;
  123.  if stop_bits = 2 then a := a + 4;
  124.  if parity = even then a := a + 24;
  125.  port[$3fb] := a;
  126. end;
  127.  
  128.  
  129. procedure init_port;
  130.  
  131. {sets up most anything necessary}
  132.  
  133. var a,b : integer;
  134.     buf_len : integer;
  135.  
  136. begin
  137.  update_uart;
  138.  port[$3f9] := 1;             {interupt enable}
  139.  a := port[$3fc];
  140.  if odd(a) then a := 1 else a := 0;   {keep terminal ready}
  141.  a := a+10;
  142.  port[$3fc] := a;                     {turn on req to send and out2}
  143.  a := port[$3fa];
  144.  port[$21]  := $c;
  145.  set_baud(1200);
  146.  buf_len := recv_buf_size;
  147.  
  148.  {this is the background routine}
  149.  
  150.  inline (
  151.   $1E/
  152.   $0E/
  153.   $1F/
  154.   $BA/*+23/
  155.   $B8/$0C/$25/
  156.   $CD/$21/
  157.   $8B/$BE/BUF_LEN/
  158.   $89/$3E/*+87/
  159.   $1F/
  160.   $2E/$8C/$1E/*+83/
  161.   $EB/$51/
  162.   $FB/
  163.   $1E/
  164.   $50/
  165.   $53/
  166.   $52/
  167.   $56/
  168.   $2E/$8E/$1E/*+70/
  169.   $BA/$F8/$03/
  170.   $EC/
  171.   $BE/RECV_BUFFER/
  172.   $8B/$1E/BUF_END/
  173.   $88/$40/$FF/
  174.   $43/
  175.   $E8/$22/$00/
  176.   $89/$1E/BUF_END/
  177.   $3B/$1E/BUF_START/
  178.   $75/$0C/
  179.   $8B/$1E/BUF_START/
  180.   $43/
  181.   $E8/$10/$00/
  182.   $89/$1E/BUF_START/
  183.   $BA/$20/$00/
  184.   $B0/$20/
  185.   $EE/
  186.   $5E/
  187.   $5A/
  188.   $5B/
  189.   $58/
  190.   $1F/
  191.   $CF/
  192.   $2E/$8B/$16/*+11/
  193.   $42/
  194.   $39/$DA/
  195.   $75/$03/
  196.   $BB/$01/$00/
  197.   $C3/
  198.   $00/$00/
  199.   $00/$01/
  200.   $90
  201.  );
  202. end;
  203.  
  204. procedure term_ready(state : boolean);
  205.  
  206. {send a true for on, false for off}
  207.  
  208. var a : byte;
  209.  
  210. begin
  211.  a := port[$3fc];
  212.  if odd(a) then a := a - 1;
  213.  a := a + ord(state);
  214.  port[$3fc] := a;
  215. end;
  216.  
  217. procedure remove_port;
  218.  
  219. {gets rid of most problems}
  220.  
  221. var a : byte;
  222.  
  223. begin
  224.  port[$3f9] := 0;
  225.  a := port[$3fc];
  226.  if odd(a) then a := 1 else a := 0;
  227.  port[$3fc] := a;
  228.  port[$21]  := $BC;
  229. end;
  230.  
  231. procedure write_byte(to_send : bigstring);
  232.  
  233. {sends out up to 255 bytes}
  234.  
  235. var a,b,c : byte;
  236.  
  237. begin
  238.  for b := 1 to length(to_send) do
  239.  begin
  240.   c := ord(to_send[b]);
  241.   repeat a := port[$3fd];
  242.   until odd(a shr 5);
  243.   port[$3f8] := c;
  244.  end;
  245. end;
  246.  
  247. procedure break;
  248.  
  249. {send a break}
  250.  
  251. var a,b : byte;
  252.  
  253. begin
  254.  a := port[$3fb];
  255.  b := a;
  256.  if b > 127 then b := b - 128;
  257.  if b <= 63 then b := b + 64;
  258.  port[$3fb] := b;
  259.  delay(400);
  260.  port[$3fb] := a;
  261. end;
  262.  
  263. procedure setup;
  264.  
  265. {initialize most stuff - you may want to replace this routine completely}
  266.  
  267. var a : byte;
  268.  
  269. begin
  270.  dbits        := 8;
  271.  parity       := none;
  272.  stop_bits    := 1;
  273.  speed        := 1200;
  274.  init_port;
  275.  term_ready(true);
  276. end;
  277.  
  278.  
  279. {    The following is a sample program illustrating the use of these
  280.      routines.  The '|' key exits and ESC sends a break.  Because
  281.      of TURBO's standard handling of function keys and other things
  282.      like that, they will also.
  283. }
  284.  
  285.  
  286. var leave : boolean;
  287.     a     : char;
  288.     b     : smallstring;
  289.  
  290. begin
  291.  setup;
  292.  leave := false;
  293.  while not leave do
  294.  begin
  295.   if keypressed then
  296.   begin
  297.    read(kbd,a);
  298.    if a = '|' then leave := true else
  299.    if a = chr(27) then break else
  300.    write_byte(a);
  301.   end;
  302.   if commpressed then write(cinkey);
  303.  end;
  304.  remove_port;
  305.  term_ready(false);
  306. end.
  307.