! 15 Aug 89
! mdmhayes.cmd - TERM script language sample Hayes-compatible modem dialer
!
!	8/15/89 change baud rate from CONNECT response
!	4/3/89 original version
!
!	This script emulates TERM's built-in Hayes dialer, except it can
!	support modem-level call progress reporting
!	It can be used as a base for building your own specialized modem
!	drivers.  This dialer script has three entry procedures:
!		call [number] [redials] [dtimeout]
!		hangup [ddtr]
!		answer [code]
!	This script could be executed initially with the command:
!		MODEM mdmhayes

! CALL <number> [<redials> [<timeout>]]
!
! <number>	is the phone number to call
! <redials>	is the number of redials which should occur.  Note that if you
!		handle redials internally, you should ONLY return a 0 or a 2
! <timeout>	is the length of time to wait for an answering modem
!
! Defaulting of these values, if any, so that this routine may be accessed via
! a direct call (do mdmhayes@call number) rather than the connect command,
! can be accomplished simply, as shown below the "on abort ... endon"
!
! Return values:		0	Normal exit after connect.
!				1	Dial error.  Do proc call redial times.
!				2	Call was aborted.
!			All others	Same as 1.
!
proc call

! The first statement in any call command should be the "on abort ... endon" to
! allow a user to abort the call, yet leave the modem in a known state, which
! is, preferrably, hung-up and waiting for another command.
on abort
	? "Call aborted, hanging up"
	xmit "\r"			! return usually aborts a dial
	flush
	return 2
endon

! blow up if called with no number in case not CONNECT or CALL command
if "$1"=""
	? "You MUST give at least a phone number when calling this procedure"
endif

! set defaults, if necessary
setvar	P_redl	3			! default to 3 redials on N.C.
setvar	P_timr	60			! default timer to 60 seconds
if "$2"!=""
	setvar P_redl val("$2")		! sneaky convert of redials
endif
if "$3"!=""
	setvar P_timr val("$3")		! sneaky convert of dtimeout
endif

	? "Calling $1"			! Tell them who we are calling

* IMPORTANT: due to the initialization string used on the next program line,
* the maximum allowable "dtimeout" period before an answer MUST be received
* is 60 seconds.  If you need a longer time and your modem will support it
* (most of the will NOT, and some are less than 60 seconds), set this value
* higher.
	xmit "ATV1E0M1Q0S7=60\r"
	wait "OK",1
	if _timeout			! it's NOT alive
		? "Modem not responding"
		return 1		! dial error
	endif

	wait 1
	xmit "ATDT$1\r"

	repeat
		cread x,P_timr
	until _timeout | (len(x)>0 & x!="RING")		! ignore empty or RING

	if _timeout					! timed out
		? "No carrier, hanging up"
		xmit "\r"		! return usually aborts a dial
		set dtr off
		wait 1
		xmit "+++"
		wait "OK",2
		xmit "ATHZ\r\r"
		wait "OK",1
		if _timeout
			xmit "ATHZ\r\r"
			wait "OK",1
		endif
		set dtr on
		flush
		return 1		! dial error
	endif

*	? "len is $(len(x)), string is >$(x)<"

	switch
	case left(x,7)="CONNECT"	! any connect message beginning
		if len(x) > 8
		  if val(midstr(x,9,1)) >= 0
			setvar b midstr(x,9,len(x)-8)
		  	? "Call Connected at $(b) Baud"
			baud $b
		  endif
		else
		  ? "Call Connected"
		endif
		return 0		! call connected
	case x="ERROR"			! uh-oh
		? "The modem returned an error code.  This usually indicates"
		? "that the modem is not entirely Hayes compatible, or that"
		? "the modem cable is incorrect.  Be sure also that if the"
		? "modem expects a certain wordlength/parity, that you set"
		? "TERM to the proper values before trying to dial."
		return 0		! abort the call
	case x="BUSY"
		? "Number dialed is busy"
	case x="NO CARRIER" | x="NO ANSWER"
		? "Modem hardware timeout expired without carrier or answer"
	case x="NO DIALTONE"
		? "No Dialtone on phone line, hanging up"
	default
		? "Unexpected modem message: $x"
		? "'No connection' assumed"
	endswitch
	xmit "\r"			! return usually aborts a dial
	flush
	return 1
endproc call

!
! hangup
!
proc hangup
	? "Hanging up phone"
	xmit "\r"			! return usually aborts a dial
	set dtr off
	wait 1
	xmit "+++"
	wait "OK",2
	xmit "ATHZ\r\r"
	wait "OK",1
	if _timeout
		xmit "ATHZ\r\r"
		wait "OK",1
	endif
	set dtr on
	flush
endproc hangup

!
! answer [code]
!
proc answer
	on abort
	  display "Answer aborted"
	  return 2
	endon
	if "$1"=""
		? "Usage: @answer [now wait off auto]"
		return 1
	endif
	setvar code "$1"
	if code = "wait"		! wait for ring BLOWNOUT
		xmit "ATS0=1\r"		! only change answer option
		wait "OK",1
		if _timeout
			? "Cannot wait for ring, modem not responding"
			return 1
		endif
		flush
		? "Waiting for ring, \^C to abort"
		dwait "CONNECT"
		? "Answering phone"
		flush
		wait 1
		return 0
	elseif code = "auto"		! autoanswer ON
		xmit "ATS0=1\r"
		wait "OK",1
		if _timeout
			? "Autoanswer NOT set, modem not responding"
			return 1
		endif
		flush
	elseif code = "now"		! answer NOW
		xmit "ATA\r"
		wait "CONNECT",1
		if _timeout
			? "Modem not responding, Answer aborted"
		else
			? "Answering phone"
		endif
		return 0
	elseif code = "off"		! autoanswer OFF
		xmit "ATS0=0\r"		! only change answer option
		wait "OK",1
		if _timeout
			? "Autoanswer NOT reset, modem not responding"
			return 1
		endif
		flush
	endif
endproc answer
