// DLSDialler.bcpl -- Dial-out support

//	Last modified August 23, 1981  1:54 PM by Taft
//	Last modified August 11, 1983  10:03 PM by Diebert

get "DLSDriver.decl"

external
[
// Outgoing procedures
CreateDCLM; DialOut

// Incoming procedures
ControlIn; ControlOut; UpdateCarrierOn
SetTimer; TimerHasExpired; Dismiss
CallSwat; Noop

// Incoming statics
lbTable; CtxRunning
]



// ---------------------------------------------------------------------------
let DialOut(dlb, phoneNumber) = valof
// ---------------------------------------------------------------------------
// Places a call for the data line designated by dlb (which must be a
// dial-out line), using the phone number in the vector phoneNumber:
//	phoneNumber!0 = number of digits
//	phoneNumber!1 to phoneNumber!n = the digits
// Returns zero if successful (callee answered and carrier is on), or an
// error code if unsuccessful (busy, no carrier, timeout, dialler in use).
// Data Terminal Ready should be off at the time of the call.
// It will be on upon return if successful and off if unsuccessful.
[
let dclm = dlb>>DLB.dclm
if dclm eq 0 then CallSwat()
if dclm>>DCLM.inUse ne 0 resultis ecDiallerInUse
dclm>>DCLM.inUse = CtxRunning
ControlOut(dclm>>DCLM.lineDPR, false)  // Drop Digit Present
ControlOut(dclm>>DCLM.lineCRQ, true)  // Raise Call Request
ControlOut(dlb>>DLB.otherLine, true)  // Raise Data Terminal Ready

// DialOut (cont'd)

// Dial the number
let timer = nil
for i = 1 to phoneNumber!0+2 do
   [
   // Wait for dialler to raise Present Next Digit
   SetTimer(lv timer, 1500)  // 15 seconds
      [
      Dismiss(1)
      if CallAborted(dlb, lv timer) resultis ecDiallerTimeout
      if ControlIn(dclm>>DCLM.linePND) break
      ] repeat

   // Present the digit and raise Digit Present
   let digit = selecton i into
      [
      case 1: (dlb>>DLB.modemType lshift 2) & 07b	// mask off other modem type bit
      case 2: dlb>>DLB.modemAddress
      default: phoneNumber!(i-2)
      ]
   for b = 0 to 3 do
      ControlOut(dclm>>DCLM.lineNB↑b,
       ((digit & 1 lshift b) eq 0? dataZero, dataOne))
   ControlOut(dclm>>DCLM.lineDPR, true)

   // Wait for dialler to drop Present Next Digit
      [
      Dismiss(1)
      if CallAborted(dlb, lv timer) resultis ecDiallerTimeout
      unless ControlIn(dclm>>DCLM.linePND) break
      ] repeat

   // Drop Digit Present in preparation for next digit
   ControlOut(dclm>>DCLM.lineDPR, false)
   ]

// Wait for modem at other end to answer
// Wait 90 seconds for international numbers (start with 0), 30 secons
// for others.
SetTimer(lv timer, (phoneNumber!1 eq 0? 9000, 3000))
   [
   Dismiss(1)
   if CallAborted(dlb, lv timer) resultis ecDiallerNoAnswer
   if ControlIn(dlb>>DLB.otherLine) break  // Test Clear to Send
   ] repeat

// Call has completed successfully and dataset now controls the line
ControlOut(dclm>>DCLM.lineCRQ, false)  // Drop Call Request
dclm>>DCLM.inUse = 0
UpdateCarrierOn(Noop)  // Make sure software state is up-to-date
resultis 0
]

// ---------------------------------------------------------------------------
and CallAborted(dlb, lvTimer) = valof
// ---------------------------------------------------------------------------
[
let dclm = dlb>>DLB.dclm
unless ControlIn(dclm>>DCLM.lineACR) % TimerHasExpired(lvTimer) resultis false
ControlOut(dclm>>DCLM.lineCRQ, false)  // Drop Call Request
ControlOut(dlb>>DLB.otherLine, false)  // Drop Data Terminal Ready
dclm>>DCLM.inUse = 0
resultis true
]