-- DialupImpl.mesa (last edited by Danielson: January 20, 1981 3:50 PM) -- DIRECTORY Dialup: FROM "Dialup" USING [Outcome, RetryCount], Process: FROM "Process" USING [MsecToTicks, SetTimeout], RS366Face: FROM "RS366Face" USING [ GetDialerCount, GetStatus, SetStatus, GetStatusBits, SetStatusBits]; DialupImpl: MONITOR IMPORTS Process, RS366Face EXPORTS Dialup = BEGIN -- various definitions timer, oneTick: CONDITION; abortRequested: PACKED ARRAY [0..15] OF BOOLEAN ← ALL[FALSE]; -- procedures (listed alphabetically) AbortCall: PUBLIC ENTRY PROCEDURE [dialerNumber: CARDINAL] = BEGIN abortRequested[dialerNumber] ← TRUE; END; Dial: PUBLIC ENTRY PROCEDURE [ dialerNumber: CARDINAL, number: LONG STRING, retries: Dialup.RetryCount] RETURNS [outcome: Dialup.Outcome] = BEGIN stringIndex: CARDINAL; setStatusBits: RS366Face.SetStatusBits; getStatusBits: RS366Face.GetStatusBits; abortRequested[dialerNumber] ← FALSE; -- Validate parameters -- IF RS366Face.GetDialerCount[] <= dialerNumber THEN RETURN[dialerNotPresent]; IF number.length > 31 THEN RETURN[formatError]; -- Make certain that the dialer has power -- IF ~RS366Face.GetStatus[dialerNumber].powerIndication THEN RETURN[dialerNotPresent]; BEGIN THROUGH [0..retries] DO -- Dial the phone number retries-1 times setStatusBits ← ResetDialer[dialerNumber]; IF (RS366Face.GetStatus[dialerNumber]).dataLineOccupied THEN RETURN[dataLineOccupied]; setStatusBits.callRequest ← TRUE; RS366Face.SetStatus[dialerNumber, setStatusBits]; BEGIN FOR stringIndex IN [0..number.length) DO THROUGH [0..200) DO -- 10 second timeout getStatusBits ← RS366Face.GetStatus[dialerNumber]; IF getStatusBits.presentNextDigit THEN EXIT; IF getStatusBits.abandonCallAndRetry THEN GO TO retry; IF abortRequested[dialerNumber] THEN GO TO abortDialing; WAIT oneTick; REPEAT FINISHED => GOTO dialingTimeout; ENDLOOP; SELECT number[stringIndex] FROM IN ['0..'9] => setStatusBits.digit ← LOOPHOLE[number[stringIndex] - '0]; '* => setStatusBits.digit ← 10; '# => setStatusBits.digit ← 11; '= => setStatusBits.digit ← 12; -- EON -- '< => setStatusBits.digit ← 13; -- SEP..await dial tone -- '> => -- timeout..pause before next digit -- BEGIN WaitFor[6000]; LOOP; END; ENDCASE => GOTO formatError; RS366Face.SetStatus[dialerNumber, setStatusBits]; setStatusBits.digitPresent ← TRUE; RS366Face.SetStatus[dialerNumber, setStatusBits]; THROUGH [0..200) DO -- 10 second timeout getStatusBits ← RS366Face.GetStatus[dialerNumber]; IF ~getStatusBits.presentNextDigit THEN EXIT; IF getStatusBits.abandonCallAndRetry THEN GO TO retry; IF abortRequested[dialerNumber] THEN GO TO abortDialing; WAIT oneTick; REPEAT FINISHED => GOTO dialingTimeout; ENDLOOP; setStatusBits.digitPresent ← FALSE; RS366Face.SetStatus[dialerNumber, setStatusBits]; ENDLOOP; -- go on to next digit -- Wait until dialer has transferred control of communication line to the data set. THROUGH [0..2000) DO --100 second timeout getStatusBits ← RS366Face.GetStatus[dialerNumber]; IF getStatusBits.callOriginationStatus THEN EXIT; IF getStatusBits.abandonCallAndRetry THEN GO TO retry; IF abortRequested[dialerNumber] THEN GOTO abortDialing; WAIT oneTick; REPEAT FINISHED => GOTO transferTimeout; ENDLOOP; -- Modem now in control...idle dialer -- setStatusBits ← [FALSE, FALSE, 0]; RS366Face.SetStatus[dialerNumber, setStatusBits]; RETURN[success]; EXITS retry => NULL; END; ENDLOOP; outcome ← failure; EXITS abortDialing => outcome ← aborted; dialingTimeout => outcome ← dialingTimeout; formatError => outcome ← formatError; transferTimeout => outcome ← transferTimeout; END; [] ← ResetDialer[dialerNumber]; RETURN; END; GetDialerCount: PUBLIC PROCEDURE RETURNS [numberOfDialers: CARDINAL] = BEGIN RETURN[RS366Face.GetDialerCount[]]; END; ResetDialer: PRIVATE INTERNAL PROCEDURE [dialerNumber: CARDINAL] RETURNS [setStatusBits: RS366Face.SetStatusBits] = BEGIN -- Resets setStatusBits and hangs up phone -- setStatusBits ← [callRequest: FALSE, digitPresent: FALSE, digit: 0]; RS366Face.SetStatus[dialerNumber, setStatusBits]; THROUGH [0..200) DO -- 10 second timeout for phone to be hung up -- IF ~(RS366Face.GetStatus[dialerNumber]).dataLineOccupied THEN RETURN; WAIT oneTick; ENDLOOP; END; WaitFor: PRIVATE INTERNAL PROCEDURE [milliseconds: CARDINAL] = BEGIN Process.SetTimeout[@timer, Process.MsecToTicks[milliseconds]]; WAIT timer; END; Process.SetTimeout[@oneTick, 1]; END. LOG Time: October 18, 1978 8:47 AM By: Schwartz Action: Created file Time: May 30, 1980 3:00 PM By: Schwartz Action: Remove all pre-Amargosa log entries, and change abortRequested to an array to allow support of multiple dialers. Time: July 10, 1980 10:55 AM By: Danielson Action: Modified to support use RS366Face interface. Time: January 20, 1981 3:51 PM By: Danielson Action: Added GetDialerCount procedure to allow client to determine number of dialers.