(* UNIT RemUnit;    Hacked for all seasons  07 Sep 83
   |xjm$d|nx|f8|ejb|.  *)

(* N O T I C E	 ***   N O T I C E   ***   N O T I C E	 ***   N O T I C E *)
(*									   *)
(*		      Copyright 1979 - 1983, RB&A.			   *)
(*									   *)
(*	  Use by USUS members for non-commercial purposes encouraged.	   *)
(*			All other rights reserved.			   *)
(*									   *)
(* N O T I C E	 ***   N O T I C E   ***   N O T I C E	 ***   N O T I C E *)

(*$C Copyright 1979 - 1983, RB&A.  All rights reserved.*)


(* NOTE:    RB&A has granted SAGE Computer Technology permission to	   *)
(*	    distribute this software to SAGE Computer users.  By	   *)
(*	    allowing SAGE to distribute for commercial purposes, RB&A	   *)
(*	    does not thereby authorize any third party to distribute	   *)
(*	    or use this software for commercial purposes.		   *)


(*$D Sage+    *) (* choose only one  *)
(*$D MBus-    *) (*   of these three *)
(*$D Osborne- *) (*	alternatives *)

(*$D Vadic+ *)	 (* choose only one  *)
(*$D Hayes- *)	 (*   of these three *)
(*$D EpROM- *)	 (*	alternatives *)

(*$I-*)		 (*$R-*)

(* Change log:
   07 Sep 83 CrSetDtr and CrSetRts par USUS News 5.  Thanks Bill Bonham.
   03 Aug 83 SmResponse takes parameter for keyboard pseudo-interrupt enable
   25 Jul 83 Masking no longer a function call, cosmetic cleanups
   20 Jul 83 MBus and Osborne support added
   19 Jul 83 CrBreak done for Sage-2
   08 Jul 83 SmResponse skip out for AttenChar added
   07 Jul 83 delay factor to 1185 (4.12) from 1600 (0.3e)
   07 Jul 83 Hook(TRUE) does SmRest before SmCommand
   07 Jul 83 CTS no longer forced true if OnHook but takes DSR & CxD
   06 Jul 83 Added Hayes command and response junk a'la BobP
   03 Jul 83 Hacked from Modula-2 Remote module
   *)
(*$L-*)(*$T R E M U N I T   -	Interface Declarations *)
(*$L+*)(*$P*)
UNIT RemUnit;

INTERFACE

TYPE
	CrDialResult		= (CrOffHook, CrDialError, CrNoAutoDial );
	CrBaudResult		= (CrBadParameter, CrBadRate, CrSetOk, CrSelectNotSupported);
	CrWhoAmI		= (CrOrig, CrAns);
	CrState			= (CrOn, CrOff, CrAuto);
	CrRemPort		= RECORD
	    Part1		: INTEGER;
	    Part2		: INTEGER
	    END;

VAR
	CrAttenChar		: CHAR;
	CrCurrentPort		: CrRemPort;


PROCEDURE CrCommInit (Dir	   : CrWhoAmI;
		      Atten	   : CHAR;
		  VAR RemExists	   : BOOLEAN;
		  VAR DialerExists : BOOLEAN);
PROCEDURE CrSetCommunications (Parity	  : BOOLEAN;
			       Even	  : BOOLEAN;
			       Rate	  : INTEGER;
			       CharBits	  : INTEGER;
			       StopBits	  : INTEGER;
			       Dir	  : CrWhoAmI;
			       Model	  : STRING;
			   VAR Rslt	  : CrBaudResult );
PROCEDURE CrCommQuit;
PROCEDURE CrPutRem (c : CHAR);
PROCEDURE CrAnswer;
PROCEDURE CrBreak;
PROCEDURE CrDial (Number : STRING; WaitChar : CHAR; VAR Rslt : CrDialResult);
PROCEDURE CrHook (OnHook : BOOLEAN);
PROCEDURE CrSetAddress (Port : CrRemPort);
PROCEDURE CrDelay (Tenths : INTEGER);
PROCEDURE CrSetDtr (Setting : CrState);
PROCEDURE CrSetRts (Setting : CrState);
FUNCTION  CrRemStat : BOOLEAN;
FUNCTION  CrGetRem : CHAR;
FUNCTION  CrCarrier : BOOLEAN;
FUNCTION  CrClearToSend : BOOLEAN;
FUNCTION  CrRinging : BOOLEAN;
FUNCTION  CrDialTone : BOOLEAN;
FUNCTION  CrKbStat : BOOLEAN;
FUNCTION  CrGetKb : CHAR;

IMPLEMENTATION
(*$L-*)(*$T R E M U N I T   -	Implementation Declarations *)
(*$L+*)(*$P*)

CONST
	DelayCount		= 1185;	    (* sec/10 on Sage 4.x *)
	RemIn			= 7;
	RemOut			= 8;
	NoControl		= 12;
	(*$B Sage *)
	SageConfigPort		= 128;	    (* see Sage manual *)
	TurnOn			= 8192;
	TurnOff			= 4096;
	(*$E Sage *)
	(*$B Hayes *)
	SmDefaults		= 'E Q V X1 S7=60 S10=30 S11=36 S12=40';
	(*			   ^ ^ ^  ^   ^	     ^	    ^	   ^
		 ~ Echo commands --' ^ |  |   |	     |	    |	   |
		   ~ Quiet results --' |  |   |	     |	    |	   |
		     ~ Verbal result --'  |   |	     |	    |	   |
			 eXtended result -'   |	     |	    |	   |
			   60sec CxD wait ----'	     |	    |	   |
			     3sec CxD loss delay ----'	    |	   |
			       36ms touch tone spacing -----'	   |
				 40/50 sec escape guard time ------'
	*)
	SmCmdOk			= 0;
	SmCmdConn		= 1;
	SmCmdRing		= 2;
	SmCmdNoCarr		= 3;
	SmCmdErr		= 4;
	SmCmdC1200		= 5;
	SmLongWait		= 600;
	(*$E Hayes *)
(*$P*)

TYPE
	(*$B Sage *)
	Config			= PACKED RECORD
	    Baud		: INTEGER;
	    InputFlow		: BOOLEAN;
	    OutputFlow		: BOOLEAN;
	    Fill0		: 0..63;
	    TimesClock		: 0..3;
	    BitsOver5		: 0..3;
	    EnabParity		: BOOLEAN;
	    EvenParity		: BOOLEAN;
	    SBits		: 1..3;
	    DsrRate		: INTEGER;
	    Fill1		: CHAR;
	    DsrTest		: 0..255
	    END;
	(*$E Sage *)
	(*$B Hayes *)
	SmCmdRslt		= SmCmdOk .. SmCmdC1200;
	SmKbdInt		= (SmKbdEnabled, SmKbdDisabled);
	(*$E Hayes *)
(*$P*)

VAR
	HookStat		: (HookOn, HookOff);
	Mask			: BOOLEAN;
	
	(* Parameters to SetCommunications *)
	ParityEnab		: BOOLEAN;
	ParityEven		: BOOLEAN;
	BuadRate		: INTEGER;
	BitsPerChar		: INTEGER;
	BitsPerStop		: INTEGER;
	Direction		: CrWhoAmI;
	ModelOptions		: STRING [255];
	
	(*$B Sage *)
	CallersConfig		: Config;
	StatRec			: PACKED RECORD
	    CharInQueue		: INTEGER;
	    Dummy0		: ARRAY [1..25] OF INTEGER;
	    Dummy1		: 0..127;
	    DataSetReady	: BOOLEAN;
	    Dummy2		: 0..3;
	    NoRinging		: BOOLEAN;
	    NoCarrier		: BOOLEAN;
	    Dummy3		: 0..15;
	    Dummy4		: ARRAY [27..29] OF INTEGER
	    END;
	CtrlByte		: PACKED ARRAY [0..0] OF CHAR;
	(*$E Sage *)
	(*$B Sage- *)
	StatRec			: RECORD
	    CharInQueue		: INTEGER;
	    Dummy0		: ARRAY [1..29] OF INTEGER
	    END;
	(*$E Sage- *)
	(*$B Hayes *)
	SmShortWait		: INTEGER;
	(*$E Hayes *)
(*$L-*)(*$T R E M U N I T   -	Assembly language interface *)
(*$L+*)(*$P*)

(*$B Sage- *)
(*   E X T E R N A L   P R O C E D U R E   D E C L A R A T I O N S   *)

PROCEDURE SetSpeed     (b1200 : BOOLEAN);			       EXTERNAL;

PROCEDURE Dtr	       (b : BOOLEAN);				       EXTERNAL;

PROCEDURE Rts	       (b : BOOLEAN);				       EXTERNAL;

PROCEDURE PutRem       (c : CHAR);				       EXTERNAL;

PROCEDURE Break;						       EXTERNAL;

FUNCTION  GetRem       : CHAR;					       EXTERNAL;

FUNCTION  Carrier      : BOOLEAN;				       EXTERNAL;

FUNCTION  ClearToSend  : BOOLEAN;				       EXTERNAL;

FUNCTION  RemStat      : BOOLEAN;				       EXTERNAL;

FUNCTION  Ringing      : BOOLEAN;				       EXTERNAL;
(*$E Sage- *)
(*$B Hayes+ *)
(*$L-*)(*$T R E M U N I T   -	Hayes SmartModem Put and Response *)
(*$L+*)(*$P*)

PROCEDURE SmPut (s : STRING);
VAR
	i			: INTEGER;
BEGIN
	FOR i := 1 TO LENGTH(s) DO
	    CrPutRem (s[i])
	END;



FUNCTION SmResponse (delay : INTEGER; kbd : SmKbdInt ) : SmCmdRslt;
VAR
	c			: CHAR;
BEGIN
	WHILE (NOT CrRemStat) AND (delay > 0) DO BEGIN
	    CrDelay (1);
	    delay := PRED(delay);
	    IF (kbd = SmKbdEnabled) AND CrKbStat THEN
		IF CrGetKb = CrAttenChar THEN
		    delay := 0
	    END;
	IF CrRemStat THEN BEGIN
	    c :=  CrGetRem;
	    IF (c >= '0') AND (c <= '5') THEN
		SmResponse := ORD(c) - ORD('0')
	    ELSE
		SmResponse := SmCmdErr
	    END
	ELSE
	    SmResponse := SmCmdErr
	END;
(*$L-*)(*$T R E M U N I T   -	Hayes SmartModem Command and Reset *)
(*$L+*)(*$P*)

FUNCTION SmCommand (cmd : STRING; delay : INTEGER; kbd : SmKbdInt) : SmCmdRslt;
BEGIN
	UNITCLEAR (RemOut);
	CrPutRem (CHR(13));
	SmPut ('AT ');
	SmPut (cmd);
	CrDelay (3);
	CrPutRem (CHR(13));
	CrDelay (1);
	UNITCLEAR (RemIn);
	SmCommand := SmResponse (delay, kbd)
	END;




FUNCTION SmReset : BOOLEAN;
VAR
	i			: INTEGER;
	r			: SmCmdRslt;
BEGIN
	i := 2;
	REPEAT
	    i := PRED(i);
	    r := SmCommand (SmDefaults, SmShortWait, SmKbdDisabled);
	    IF r <> SmCmdOk THEN BEGIN
		CrDelay (10);
		SmPut ('+++');
		CrDelay (18)
		END
	    UNTIL (r = SmCmdOk) OR (i <= 0);
	IF r = SmCmdOk THEN
	    SmReset := TRUE
	ELSE
	    SmReset := SmCommand (SmDefaults, SmShortWait, SmKbdDisabled) 
		       = SmCmdOk
	END;
(*$E Hayes+ *)
(*$L-*)(*$T R E M U N I T   -	Utility Procedures *)
(*$L+*)(*$P*)
(*$B Vadic *)

FUNCTION YorN (Str  : STRING) : BOOLEAN;
VAR
	Ch			: CHAR;
BEGIN
	WRITELN;
	WRITE (Str, ' ?	 [y/n] : ');
	REPEAT
	    Ch := CrGetKb
	    UNTIL Ch IN ['y', 'Y', 'n', 'N'];
	WRITE (Ch);
	WRITELN;
	YorN := Ch IN ['y', 'Y']
	END;
(*$E Vadic *)


PROCEDURE CrSetDtr;
CONST
	DTR			= 2;
BEGIN
	(*$B Sage+ *)
	CtrlByte[0] := CHR (DTR);
	IF Setting = CrOn THEN
	    UNITWRITE (RemOut, CtrlByte[0], 1, 0, TurnOn)
	ELSE
	    UNITWRITE (RemOut, CtrlByte[0], 1, 0, TurnOff)
	(*$E Sage+ *)
	(*$B Sage- *)
	Dtr (Setting = CrOn)
	(*$E Sage- *)
	END;



PROCEDURE CrSetRts;
CONST
	RTS			= 32;
BEGIN
	(*$B Sage+ *)
	CtrlByte[0] := CHR (RTS);
	IF Setting = CrOn THEN
	    UNITWRITE (RemOut, CtrlByte[0], 1, 0, TurnOn)
	ELSE
	    UNITWRITE (RemOut, CtrlByte[0], 1, 0, TurnOff)
	(*$E Sage+ *)
	(*$B Sage- *)
	Rts (Setting = CrOn)
	(*$E Sage- *)
	END;
(*$L-*)(*$T R E M U N I T   -	Status Functions *)
(*$L+*)(*$P*)

FUNCTION CrCarrier (* : BOOLEAN *);
BEGIN
	(*$B Sage *)
	UNITSTATUS (RemIn, StatRec, 1);
	CrCarrier := NOT StatRec.NoCarrier
	(*$E Sage *)
	(*$B Sage- *)
	CrCarrier := Carrier
	(*$E Sage- *)
	END;


FUNCTION CrClearToSend (* : BOOLEAN *);
BEGIN
	(*$B Sage *)
	UNITSTATUS (RemIn, StatRec, 1);
	WITH StatRec DO
	    CrClearToSend := DataSetReady AND NOT NoCarrier
	(*$E Sage *)
	(*$B Sage- *)
	CrClearToSend := ClearToSend
	(*$E Sage- *)
	END;


FUNCTION CrRemStat (* : BOOLEAN *);
BEGIN
	(*$B Osborne- *)
	UNITSTATUS (RemIn, StatRec, 1);
	CrRemStat := StatRec.CharInQueue > 0
	(*$E Osborne- *)
	(*$B Osborne *)
	CrRemStat := RemStat
	(*$E Osborne *)
	END;


FUNCTION CrKbStat (* : BOOLEAN *);
BEGIN
	(*$B Sage *)
	UNITSTATUS (1 (* Sage bug *), StatRec, 1);
	(*$E Sage *)
	(*$B Sage- *)
	UNITSTATUS (2, StatRec, 1);
	(*$E Sage- *)
	CrKbStat := StatRec.CharInQueue > 0
	END;
(*$L-*)(*$T R E M U N I T   -	Simple Put and Get Procedures *)
(*$L+*)(*$P*)

FUNCTION CrGetRem (* : CHAR *);
VAR
	Ch			: PACKED ARRAY [0..0] OF CHAR;
BEGIN
	(*$B Sage *)
	UNITREAD (RemIn, Ch[0], 1, 0, NoControl);
	(*$E Sage *)
	(*$B Sage- *)
	Ch[0] := GetRem;
	(*$E Sage- *)
	IF Mask THEN	(* face San Diego and remember R Kaufman *)
	    CrGetRem := CHR ( ORD ( ODD(ORD(Ch[0])) AND ODD(127) ) )
	ELSE
	    CrGetRem := Ch[0]
	END;


PROCEDURE CrPutRem (*c : CHAR*);
VAR
	Ch			: PACKED ARRAY [0..0] OF CHAR;
BEGIN
	(*$B Sage *)
	Ch[0] := c;
	UNITWRITE (RemOut, Ch[0], 1, 0, NoControl)
	(*$E Sage *)
	(*$B Sage- *)
	PutRem (c)
	(*$E Sage- *)
	END;


FUNCTION CrGetKb (* : CHAR *);
VAR
	Ch			: PACKED ARRAY [0..0] OF CHAR;
BEGIN
	UNITREAD (2, Ch[0], 1, 0, NoControl);
	CrGetKb := Ch[0]
	END;
(*$L-*)(*$T R E M U N I T   -	CrDelay and CrBreak  *)
(*$L+*)(*$P*)

PROCEDURE CrDelay (*Tenths : INTEGER*);
VAR
	i			: INTEGER;
	j			: INTEGER;
BEGIN
	FOR i := 1 TO Tenths DO
	    FOR j := 1 TO DelayCount DO
	END;




PROCEDURE CrBreak;
(*$B Sage *)
CONST
	TurnOn			= 8192;
	TurnOff			= 4096;
	Break			= 8;
VAR
	CtrlByte		: PACKED ARRAY [0..0] OF CHAR;
BEGIN
	CtrlByte[0] := CHR (Break);
	UNITWRITE (RemOut, CtrlByte[0], 1, 0, TurnOn);
	CrDelay (2);
	UNITWRITE (RemOut, CtrlByte[0], 1, 0, TurnOff)
(*$E Sage *)
(*$B Sage- *)
BEGIN
	Break
(*$E Sage- *)
	END;
(*$L-*)(*$T R E M U N I T   -	Ring Detection and Answering *)
(*$L+*)(*$P*)

FUNCTION CrRinging (* : BOOLEAN *);
BEGIN
	IF HookStat = HookOn THEN BEGIN
	    (*$B Vadic *)
	    (*$B Sage *)
	    UNITSTATUS (RemIn, StatRec, 0);
	    WITH StatRec DO
		CrRinging := NOT NoRinging
	    (*$E Sage *)
	    (*$B Sage- *)
	    CrRinging := Ringing
	    (*$E Sage- *)
	    (*$E Vadic *)
	    (*$B Hayes *)
	    CrRinging := SmResponse (3, SmKbdDisabled) = SmCmdRing
	    (*$E Hayes *)
	    (*$B EpROM *)
	    CrRinging := FALSE
	    (*$E EpROM *)
	    END
	ELSE
	    CrRinging := FALSE
	END;


PROCEDURE CrAnswer;
BEGIN
	Direction := CrAns;
	(*$B Hayes- *)
	CrHook (FALSE)
	(*$E Hayes- *)
	(*$B Hayes *)
	IF SmCommand ('A', SmLongWait, SmKbdEnabled) 
	   IN [SmCmdConn, SmCmdC1200] THEN
	    HookStat := HookOff
	ELSE
	    HookStat := HookOn
	(*$E Hayes *)
	END;
(*$L-*)(*$T R E M U N I T   -	Dial Tone Detection and Dialing *)
(*$L+*)(*$P*)

FUNCTION CrDialTone (* : BOOLEAN *);
BEGIN
	(*$B Vadic *)
	IF HookStat = HookOn THEN
	    CrDialTone := FALSE
	ELSE 
	    CrDialTone := YorN ('Get a good Dial Tone')
	(*$E Vadic *)
	(*$B Hayes *)
	CrDialTone := NOT (HookStat = HookOn)
	(*$E Hayes *)
	(*$B EpROM *)
	CrDialTone := FALSE
	(*$E EpROM *)
	END;


PROCEDURE CrDial(*Number   : STRING;
		  WaitChar : CHAR;
	      VAR Rslt	   : CrDialResult*);
VAR
	i			: INTEGER;
BEGIN
	(*$B Vadic *)
	WRITELN;
	WRITE ('Please Dial : ', Number);
	IF YorN ('Did you Succeed in Dialing') THEN
	    Rslt := CrOffHook
	ELSE
	    Rslt := CrDialError;
	HookStat := HookOff
	(*$E Vadic *)
	(*$B Hayes *)
	IF SmCommand (CONCAT('DT', Number), SmLongWait, SmKbdEnabled) 
	   IN [ SmCmdOk, SmCmdConn, SmCmdC1200 ] THEN
	    Rslt := CrOffHook
	ELSE
	    Rslt := CrDialError;
	HookStat := HookOff
	(*$E Hayes *)
	(*$B EpROM *)
	Rslt := CrDialError
	(*$E EpROM *)
	END;
(*$L-*)(*$T R E M U N I T   -	Hook On / Off *)
(*$L+*)(*$P*)
PROCEDURE CrHook (*OnHook : BOOLEAN*);
BEGIN
	IF OnHook THEN	BEGIN
	    (*$B Vadic *)
	    CrSetDtr (CrOff);
	    IF HookStat = HookOff THEN BEGIN
		HookStat := HookOn;
		WRITELN;
		WRITE ('Phone assumed On Hook in ');
		IF Direction = CrOrig THEN
		    WRITELN ('Originate mode.')
		ELSE
		    WRITELN ('Answer mode.')
		END
	    (*$E Vadic *)
	    (*$B Hayes *)
	    IF HookStat = HookOff THEN BEGIN
		IF SmReset THEN
		    IF SmCommand ('H', SmShortWait, SmKbdEnabled) 
		       = SmCmdOk THEN;
		HookStat := HookOn
		END
	    (*$E Hayes *)
	    (*$B EpROM *)
	    IF HookStat = HookOff THEN
		HookStat := HookOn
	    (*$E EpROM *)
	    END
	ELSE BEGIN
	    (*$B Vadic *)
	    CrSetDtr (CrOn);
	    IF HookStat = HookOn THEN BEGIN
		HookStat := HookOff;
		WRITELN;
		IF Direction = CrOrig THEN
		    WRITE ('Phone assumed Off Hook in Originate mode.')
		ELSE
		    WRITE ('Answering Phone.')
		END
	    (*$E Vadic *)
	    (*$B Hayes *)
	    IF HookStat = HookOn THEN BEGIN
		IF Direction = CrOrig THEN
		    IF SmCommand ('O', SmShortWait, SmKbdEnabled) 
		       = SmCmdOk THEN
		    ELSE
		ELSE IF SmCommand ('H1', SmShortWait, SmKbdEnabled) 
			= SmCmdOk THEN;
		HookStat := HookOff
		END
	    (*$E Hayes *)
	    (*$B EpROM *)
	    IF HookStat = HookOn THEN
		HookStat := HookOff
	    (*$E EpROM *)
	    END
	END;
(*$L-*)(*$T R E M U N I T   -	Set Communications  *)
(*$L+*)(*$P*)
PROCEDURE CrSetCommunications (*Parity	 : BOOLEAN;
				Even	 : BOOLEAN;
				Rate	 : INTEGER;
				CharBits : INTEGER;
				StopBits : INTEGER;
				Dir	 : CrWhoAmI;
				Model	 : STRING;
			    VAR Rslt	 : CrBaudResult *);
VAR
	i			: INTEGER;
	(*$B Sage *)
	MyConfig		: Config;
	(*$E Sage *)
BEGIN
	ParityEnab   := Parity;
	ParityEven   := Even;
	BuadRate     := Rate;
	BitsPerChar  := CharBits;
	BitsPerStop  := StopBits;
	Direction    := Dir;
	ModelOptions := Model;
	FOR i := 1 TO LENGTH (ModelOptions) DO
	    IF ModelOption[i] IN ['a'..'z'] THEN
		ModelOption[i] := CHR ( ORD(ModelOption[i])
					- ORD('a') + ORD('A') );
	Mask := POS ('MASK', ModelOptions) > 0;
	(*$B Sage *)
	MyConfig := CallersConfig;
	WITH MyConfig DO BEGIN
	    Baud       := 19200 DIV (Rate DIV 2);
	    InputFlow  := POS ('FLOWIN', ModelOptions) > 0;
	    OutputFlow := POS ('FLOWOUT', ModelOptions) > 0;
	    BitsOver5  := CharBits - 5;
	    EnabParity := Parity;
	    EvenParity := Even;
	    IF StopBits = 2 THEN
		SBits  := 2
	    ELSE
		SBits  := 1;
	    DsrTest    := 0
	    END;
	UNITWRITE (SageConfigPort, MyConfig, 8, 0, RemIn);
	(*$E Sage *)
	(*$B Sage- *)
	SetSpeed (Rate = 1200);
	(*$E Sage- *)
	Rslt := CrSetOk;
	(*$B Hayes *)
	SmShortWait := ROUND ( LN (19200.0 / Rate) * 7.13 )
	(*$E Hayes *)
	END;
(*$L-*)(*$T R E M U N I T   -	Init, Term, and Set Address  *)
(*$L+*)(*$P*)

PROCEDURE CrCommInit (*Dir	    : CrWhoAmI;
		       Atten	    : CHAR;
		   VAR RemExists    : BOOLEAN;
		   VAR DialerExists : BOOLEAN*);
VAR
	Rslt			: CrBaudResult;
BEGIN
	Direction    := Dir;
	CrAttenChar  := Atten;
	HookStat     := HookOn;
	UNITCLEAR (RemIn);
	RemExists := IORESULT = 0;
	UNITCLEAR (RemOut);
	RemExists := RemExists AND (IORESULT = 0);
	IF RemExists THEN BEGIN
	    CrSetCommunications ( FALSE,   (* Parity   *)
				  FALSE,   (* Even     *)
				   1200,   (* Rate     *)
				      8,   (* CharBits *)
				      1,   (* StopBits *)
				 CrOrig,   (* Dir      *)
				 'Mask',   (* Options  *)
				   Rslt	   (* Result code *) );
	    (*$B Hayes *)
	    DialerExists := SmReset
	    (*$E Hayes *)
	    (*$B Hayes- *)
	    DialerExists := FALSE
	    (*$E Hayes- *)
	    END
	ELSE
	    DialerExists := FALSE
	END;


PROCEDURE CrCommQuit;
BEGIN
	(*$B Vadic *)
	CrSetDtr (CrOff);
	(*$E Vadic *)
	CrHook (TRUE)
	END;



PROCEDURE CrSetAddress (*Port : CrRemPort*);
BEGIN
	CrCurrentPort := Port
	END;
(*$L-*)(*$T R E M U N I T   -	Body of Main Procedures *)
(*$L+*)(*$P*)

PROCEDURE Init;
VAR
	Exists			: BOOLEAN;
	Dial			: BOOLEAN;
BEGIN
	(*$B Hayes *)
	SmShortWait := 13;
	(*$E Hayes *)
	CrCommInit (CrOrig, CHR(1), Exists, Dial)
	END;


BEGIN (* Remote *)

	(*$B Sage *)
	UNITREAD (SageConfigPort, CallersConfig, 8, 0, RemIn);
	(*$E Sage *)
	Init;

	***;

	CrCommQuit;
	(*$B Sage *)
	UNITWRITE (SageConfigPort, CallersConfig, 8, 0, RemIn)
	(*$E Sage *)

	END.
                                                                                                                                              