(*********************************************)
(*                                           *)
(*  Talks to your modem. Called by TERM.PAS  *)
(*                                           *)
(*  This program is donated to the Public    *)
(*  Domain by MarshallSoft Computing, Inc.   *)
(*  It is provided as an example of the use  *)
(*  of the Personal Communications Library.  *)
(*                                           *)
(*********************************************)

unit Modem_IO;

interface

type
  String80 = String[80];


procedure SendTo( Port:Integer; ThisString:String80);
function  WaitFor( Port:Integer; ThisString:String80):Boolean;

implementation

uses PCL4P;

function BreakTest : Boolean;
begin
  if SioBrkKey then
    begin
      WriteLn('User BREAK');
      BreakTest := TRUE
    end
  else BreakTest := FALSE;
end;


procedure SendTo( Port: Integer; ThisString:String80);
const
   CR = 13;
var
   rc : Integer;
   i  : Integer;
   c  : Char;
begin
   rc := SioRxFlush(Port);
   rc := SioDelay(4);
   for i := 1 to Length(ThisString) do
      begin
         c := UpCase(ThisString[i]);
         case c of
            '!' : c := chr(CR);
            '~' : begin
                     (* delay 1/2 second *)
                     rc := SioDelay(9);
                     c := ' '
                  end;
             ' ': rc := SioDelay(3);
         end;
         (* transmit as 7 bit char *)
         rc := SioPutc(Port, chr(ord(c) and $7f));
         (* wait 3/18th of a second *)
         rc := SioDelay(3);
         (* wait 1 second for echo *)
         rc := SioGetc(Port,18);
         if rc > 0 then Write(chr(rc));
      end (* for *)
end; (* SendTo *)

Function WaitFor(Port:Integer; ThisString:String80): Boolean;
label WaitForExit;
const
  CR = 13;
  LF = 10;

var
  code : Integer;
  c : Char;
  i : Integer;
  rc: Integer;

procedure Flush;
label FlushExit;
var code : integer;
begin
  while TRUE do
    begin
       if BreakTest then exit;
       (* get next incoming character *)
       code := SioGetc(Port,38);
       if code = -1 then exit;
       (* skip CR & LF *)
       if (code <> CR) and (code <> LF) then
         begin
           (*writeln('Pushing ',chr(code),' [',code,']');*)
           rc := SioUnGetc(Port, code );
           goto FlushExit;
         end;
    end; (* while *)
FlushExit: end; (* Flush *)

begin (* WaitFor *)
  Write( chr(LF) );
  Flush;
  for i:= 1 to Length(ThisString) do
    begin
       (* control-BREAK ? *)
       if BreakTest then exit;
       (* c is expected character *)
       c := UpCase( ThisString[i] );
       (* wait 1 second for next character *)
       code := SioGetc(Port,18);
       if code = -1 then
          begin
             WaitFor := FALSE;
             goto WaitForExit;
          end;
       (* echo character from modem *)
       Write(chr(code));
       if chr(code) <> c then
          begin
             writeln('Expecting ',c,' not ',chr(code),'[',code,']');
             WaitFor := FALSE;
             goto WaitForExit;
          end;
    end; (* for *)
  (* a last character ? *)
  rc := SioGetc(Port,18);
  if rc > 0 then Write(chr(rc));
  WaitFor := TRUE;
WaitForExit: end; (* WaitFor *)

end.