home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / SYSTEM / GETTIME.ZIP / COMUNIT.PAS next >
Encoding:
Pascal/Delphi Source File  |  1990-12-10  |  8.9 KB  |  409 lines

  1. unit comunit;
  2. interface
  3. type baud=(B300,B1200,B2400);
  4.      bits=5..8;
  5.      stopbits=1..2;
  6.      parity=(no_par, odd_par, even_par);
  7.      comport = 1..2;
  8.      Qlength = 100..32000;
  9.  
  10. var
  11.   echo_on: boolean;
  12.   display_error: boolean;
  13.   status_change_proc: procedure;
  14.   break_proc: procedure;
  15.   getln_timeout: real;
  16.  
  17. procedure initcom (cport: comport; Qlen: Qlength;
  18.    baudx: baud; bitsx: bits; stopx: stopbits; parx: parity);
  19. procedure resetcom(baudx: baud; bitsx: bits; stopx: stopbits; parx: parity);
  20. procedure end_com;
  21. function dcd: boolean;
  22. function ri: boolean;
  23. function dsr: boolean;
  24. function cts: boolean;
  25. function ch_in_ready: boolean;
  26. function com_error: byte;
  27. function line_status: byte;
  28. procedure hangup;
  29. function get_com : char;
  30. procedure put_com (c: char);
  31. procedure send(s: string);
  32. procedure sendln(s: string);
  33. procedure show_status;
  34. function getln: string;
  35. procedure send_break;
  36. procedure do_nothing;
  37.  
  38. implementation
  39. uses queues, stopwatch, crt, dos, hexdump;
  40.  
  41. var
  42.   in_q, out_q: queue;
  43.   dcdstat, ristat, dsrstat, ctsstat: boolean;
  44.   com_ctl_byte: byte;
  45.   com_error_byte: byte;
  46.   x,y: byte;
  47.   regs: registers;
  48.   portbase, baud_port, tran_reg, rcv_reg,
  49.   baud_div, int_enable_reg, int_id_reg,
  50.   line_ctl_reg, modem_ctl_reg,
  51.   line_stat_reg, modem_stat_reg: word;
  52.   sysintnr: 0..4;
  53.   ExitSave: pointer;
  54.   old_int_vec: pointer;
  55.   break_occurred, status_changed: boolean;
  56.   old_int_ctl_reg: byte;
  57.  
  58. procedure DisInt; inline($FA);
  59.  
  60. procedure EnaInt; inline($FB);
  61.  
  62. function line_status: byte;
  63. begin
  64.   line_status := port[line_stat_reg];
  65. end;
  66.  
  67. procedure set_status_bits;
  68. var b: byte;
  69. begin
  70.    b := port[modem_stat_reg];
  71.    dcdstat := (b and $80) <> 0;
  72.    ristat := (b and $40) <> 0;
  73.    dsrstat := (b and $20) <> 0;
  74.    ctsstat := (b and $10) <> 0;
  75. end;
  76.  
  77. procedure add_str_to_in_Q (s: string);
  78. var i: byte;
  79.     ch: char;
  80. begin
  81.   for i := 1 to length(s) do insertQ(s[i], in_Q);
  82.   insertQ(#13, in_Q);
  83.   insertq(#10, in_Q);
  84. end;
  85.  
  86. procedure int_hand(ES, BP: word);
  87. interrupt;
  88.  
  89. var
  90.   int_id, int_type, b: byte ;
  91.   ch: char;
  92. begin
  93.   int_id := port[int_id_reg];
  94.   while (int_id and $01) = $00 do begin
  95.     case int_id and $06 of
  96.       $06: {break_cond} begin
  97.         b := port[line_stat_reg];
  98.         if display_error then begin
  99.           if (b and $80)<>0 then
  100.              add_str_to_in_Q('Timeout error occurred.');
  101.           if (b and $10)<>0 then
  102.              add_str_to_in_Q('Break received');
  103.           if (b and $08)<>0 then
  104.              add_str_to_in_Q('Framing error occurred.');
  105.           if (b and $04)<>0 then
  106.              add_str_to_in_Q('Parity error occurred.');
  107.           if (b and $02)<>0 then
  108.              add_str_to_in_Q('Overrun error occurred.');
  109.         end
  110.         else begin
  111.           if (b and $10)<>0 then
  112.              break_occurred := true
  113.           else
  114.              com_error_byte := b;
  115.         end;
  116.       end;
  117.       $04: begin {receive ready}
  118.         ch := char (port[rcv_reg] );
  119.         insertQ (ch, in_q);
  120.         end;
  121.       $02: begin {send ready}
  122.         remove (ch, out_q);
  123.         port[tran_reg] := byte(ch);
  124.         if empty (out_q) then begin
  125.            port[int_enable_reg]:=port[int_enable_reg] and $0D;
  126.            end;
  127.         end;
  128.       $00: begin {status change}
  129.         set_status_bits;
  130.         status_changed := true;
  131.         end;
  132.     end;
  133.     int_id := port[int_id_reg];
  134.   end;
  135.   port[$20] := $20;
  136. end;
  137.  
  138.  
  139. procedure initcom (cport: comport; Qlen: Qlength;
  140.    baudx: baud; bitsx: bits; stopx: stopbits; parx: parity);
  141.    var ch: char;
  142. begin
  143.  
  144.   if sysintnr <> 0 then
  145.      end_com;
  146.  
  147.   if cport = 1 then
  148.      portbase := memw[$40:$00]
  149.   else
  150.      portbase := memw[$40:$02];
  151.   if portbase = $03f8 then
  152.     sysintnr := 4
  153.   else if portbase = $02f8 then
  154.     sysintnr := 3
  155.   else begin
  156.     writeln ('ERROR: invalid port base');
  157.     halt;
  158.   end;
  159.   baud_port := portbase;
  160.   tran_reg := portbase;
  161.   rcv_reg := portbase;
  162.   baud_div := portbase;
  163.   int_enable_reg := portbase + 1;
  164.   int_id_reg := portbase + 2;
  165.   line_ctl_reg := portbase + 3;
  166.   modem_ctl_reg := portbase + 4;
  167.   line_stat_reg := portbase + 5;
  168.   modem_stat_reg := portbase + 6;
  169.  
  170.   resetcom(baudx, bitsx, stopx, parx);
  171.  
  172.   initQ(in_Q, Qlen);
  173.   initQ(out_Q, Qlen);
  174.   DisInt;
  175.   {clear out any pending read or write}
  176.   if (port[line_stat_reg] and 1) <> 0 then begin
  177.      ch := char(port[rcv_reg]);
  178.   end;
  179.   if (port[line_stat_reg] and $20) <> 0 then
  180.      port[tran_reg] := 0;
  181.   old_int_ctl_reg := port[$21];
  182.   if sysintnr = 3 then begin
  183.      GetIntVec ($0B, old_int_vec);
  184.      SetIntVec ($0B, @int_hand);
  185.      port[$21] := port[$21] and $F7;
  186.   end
  187.   else begin
  188.      GetIntVec ($0C, old_int_vec);
  189.      SetIntVec ($0c, @int_hand);
  190.      port[$21] := port[$21] and $EF;
  191.   end;
  192.   port[modem_ctl_reg] := $0B;
  193.   port[int_enable_reg] := $0D;
  194.   set_status_bits;
  195.   EnaInt;
  196.   status_change_proc;
  197. end;
  198.  
  199. procedure resetcom(baudx: baud; bitsx: bits; stopx: stopbits; parx: parity);
  200. const bauddiv: array[baud] of word = ($0180, $0060, $0030);
  201.       bitsA: array[bits] of byte = (0,1,2,3);
  202.       stopA: array[stopbits] of byte = (0,4);
  203.       parA: array[parity] of byte = (0,$08,$18);
  204. var bdiv: word;
  205. begin
  206.   DisInt;
  207.   port[line_ctl_reg]:=$80; { set baud rate };
  208.   bdiv := bauddiv[baudx];
  209.   port[baud_port] := lo(bdiv);
  210.   port[baud_port + 1] := hi(bdiv);
  211.   com_ctl_byte := bitsA[bitsx] or stopA[stopx] or parA[parx];
  212.   port[line_ctl_reg]:=com_ctl_byte;
  213.   EnaInt;
  214. end;
  215.  
  216. procedure end_com;
  217. begin
  218.   if sysintnr <> 0 then begin
  219.      DisInt;
  220.      port[int_enable_reg] := 0;
  221.      port[line_ctl_reg] := 3;
  222.      port[$21] := old_int_ctl_reg;
  223.      if sysintnr = 3 then begin
  224.         SetIntVec ($0B, old_int_vec);
  225.      end
  226.      else begin
  227.        SetIntVec ($0C, old_int_vec);
  228.      end;
  229.      sysintnr := 0;
  230.      EnaInt;
  231.      doneQ(in_Q);
  232.      doneQ (out_Q);
  233.      sysintnr := 0;
  234.   end;
  235. end;
  236.  
  237. {$F+}
  238. procedure my_exit_proc;
  239. begin
  240.   ExitProc := ExitSave;
  241.   end_com;
  242. end;
  243.  
  244. procedure do_nothing;
  245. begin
  246. end;
  247. {$F-}
  248.  
  249. function dcd: boolean;
  250. begin
  251.   dcd := dcdstat;
  252. end;
  253.  
  254. function ri: boolean;
  255. begin
  256.   ri := ristat;
  257. end;
  258.  
  259. function dsr: boolean;
  260. begin
  261.   dsr := dsrstat;
  262. end;
  263.  
  264. function cts: boolean;
  265. begin
  266.   cts := ctsstat;
  267. end;
  268.  
  269. function ch_in_ready: boolean;
  270. begin
  271.    if break_occurred then begin
  272.       break_occurred := false;
  273.       break_proc;
  274.    end;
  275.    if status_changed then begin
  276.       status_changed := false;
  277.       status_change_proc;
  278.    end;
  279.    ch_in_ready := not empty(in_q);
  280. end;
  281.  
  282. function com_error: byte;
  283. begin
  284.   com_error := com_error_byte;
  285.   com_error_byte := 0;
  286. end;
  287.  
  288. procedure hangup;
  289. var c: clock;
  290. begin
  291.   if dcd then begin
  292.      startclock(c);
  293.      port[modem_ctl_reg]:=$0A;
  294.      repeat
  295.      until (not dcd) or (stopclock(c)>15);
  296.      if dcd then writeln ('ERROR: timeout on hangup')
  297.      else port[modem_ctl_reg] := $0B;
  298.   end;
  299. end;
  300.  
  301. function get_com: char;
  302.   var c: char;
  303. begin
  304.   DisInt;
  305.   remove (c, in_q);
  306.   EnaInt;
  307.   get_com := c;
  308. end;
  309.  
  310. procedure put_com (c: char);
  311. var was_empty: boolean;
  312. begin
  313.   if echo_on then write (c);
  314.   DisInt;
  315.   was_empty := empty (out_Q);
  316.   insertQ (c, out_Q);
  317.   if was_empty then
  318.      port[int_enable_reg] := port[int_enable_reg] or $02;
  319.   EnaInt;
  320. end;
  321.  
  322. procedure special_key;
  323. var c1: char;
  324. {procedure to handle special keys.  Currently it just bypasses any.}
  325. begin
  326.   c1 := readkey;
  327. end;
  328.  
  329. procedure send(s: string);
  330. var i: byte;
  331. begin
  332.   for i:=1 to length(s) do
  333.      put_com(s[i]);
  334. end;
  335.  
  336. procedure sendln(s: string);
  337. begin
  338.   send(s);
  339.   put_com(#13);
  340.   put_com(#10);
  341. end;
  342.  
  343. function getln: string;
  344. var s: string[80];
  345.     b: byte;
  346.     c: char;
  347.     cl: clock;
  348. begin
  349.   s[0]:=#0;
  350.   b:=0;
  351.   startclock(cl);
  352.   repeat
  353.     if ch_in_ready then begin
  354.       c := get_com;
  355.       write(c);
  356.       if c<>#13 then begin
  357.         inc(b);
  358.         s[b]:=c;
  359.       end;
  360.     end;
  361.   until (c=#13) or (b=80) or (stopclock(cl)>getln_timeout);
  362.   if c=#13 then begin
  363.      repeat
  364.      until ch_in_ready or (stopclock(cl)>getln_timeout);
  365.      if ch_in_ready then begin
  366.         c:= get_com;
  367.         write(c)
  368.      end;
  369.   end;
  370.   s[0]:=char(b);
  371.   getln := s;
  372. end;
  373.  
  374. procedure show_status;
  375.   var x,y, oldattr: byte;
  376. begin
  377.   x := wherex; y := wherey;
  378.   window(1,25,80,25);
  379.   oldattr := textattr;
  380.   textattr := ((textattr and $07) * 16) + (textattr and $70) div 16;
  381.   ClrEol;
  382.   write ('DCD: ', DCD:5, '   RI: ', ri:5, '   DSR: ', dsr:5,
  383.      '   CTS: ', cts:5);
  384.   window (1,1,80,24);
  385.   gotoxy(x,y);
  386.   textattr := oldattr;
  387. end;
  388.  
  389. procedure send_break;
  390. begin
  391.   port[line_ctl_reg] := com_ctl_byte or $40;
  392.   milliwait(100);
  393.   port[line_ctl_reg] := com_ctl_byte;
  394. end;
  395.  
  396.  
  397.  
  398. begin
  399.   echo_on := false;
  400.   display_error := false;
  401.   com_error_byte := 0;
  402.   sysintnr := 0;
  403.   getln_timeout := 15;
  404.   ExitSave := ExitProc;
  405.   ExitProc := @my_exit_proc;
  406.   status_change_proc := show_status;
  407.   break_proc := do_nothing;
  408. end.
  409.