; MXO-UD10.ASM - UDS 212 A/D MODEM OVERLAY FOR MEX
;
; You will want to look this file over carefully. There are a number of
; things that will have to be done to adapt your computer overlay file
; for proper interaction with this modem overlay file.
;
;
; Edit this file for your preferences then follow the "TO USE:" example
; shown below.
;
;	TO USE: Assemble with ASM.COM or equivalent
;		assembler.  Then use MLOAD21.COM (or later) to combine
;		this overlay with the original MEXxx.COM file, and your
;		computer specific overlay file.( MXO-xxxx in the example
;		given below).
;
;		A>MLOAD21 MEX.COM=MEXxx.COM,MXO-UD10,MXO-xxxx
;
;	>>>>  Report bugs to fortfone rcp/m 414-563-9932 <<<<<<<<<<<< 
;
; =   =   =   =   =   =   =   =   =   =   =   =   =   =   =   =   =   =
;
YES	EQU	0FFH
NO	EQU	000H
;
;	UDSNEW - If yes, this is a revised UDS 212 A/D.  The new
;	models can be disconnected by sending the string 'XXXT' followed
;	by carriage return.  Older models can only be disconnected by
;	dropping DTR low for at least 60 msec.  Define UDSNEW to be yes
;	if you want to use the 'XXXT' disconnect string,  Define UDSNEW
;	to be NO to use the DTR disconnect method. (The computer overlay
;	must intercept the DISCV vector, drop DTR, then JMP to the original
;	DISCV vector address.)
;
UDSNEW	EQU	YES
;
;
;  *NOTES* As an owner of a UDS 212-A/D modem you are probably aware
;	of the consequences regarding training the modem at one baud rate
;	and then changing baud rates without untraining the modem first.
;	The poor thing will go crazy.  Using this overlay *requires* the
;	user to always disconnect a call before changing baud rates.
;	The Ctl-J + N command will disconnect the modem and then untrain 
;	the ACU.  Do *NOT* make a completed call, exit terminal mode
;	with Ctl-J + E, and then try to change baud rates. (Incomplete or
;	aborted calls don't count, the modem is automatically untrained
;	if the call isn't completed.)  If you're in doubt, enter terminal
;	mode and give the disconnect command, Ctl-J + N, this will insure
;	the modem is disconnected and 'untrained'.
;
;
; MEX11 if YES will compile the patches for the smartmodem entry points
;	that are new to MEX version 1.10 (MEX11)
;
MEX11	EQU	NO
;
;
BDOS		EQU	005H
CR:		EQU	0DH		;carriage return
LF:		EQU	0AH		;linefeed
;
; MEX service processor stuff
;
MEX	EQU	0D00H		; MEX SERVICE PROCESSOR ENTRY POINT
INMDM	EQU	255		;get char from port to A, CY=no more in 100 ms
TIMER	EQU	254		;delay 100ms * reg B
TMDINP	EQU	253		;B=# secs to wait for char, cy=no char
CHEKCC	EQU	252		;check for ^C from KBD, Z=present
SNDRDY	EQU	251		;test for modem-send ready
RCVRDY	EQU	250		;test for modem-receive ready
SNDCHR	EQU	249		;send a chara (B) to the modem (after sndrdy)
RCVCHR	EQU	248		;recv a char from modem (after rcvrdy)
LOOKUP	EQU	247		;table search: see CMDTBL comments for info
PARSFN	EQU	246		;parse filename from input stream
BDPARS	EQU	245		;parse baud-rate from input stream
SBLANK	EQU	244		;scan input stream to next non-blank
EVALA	EQU	243		;evaluate numeric from input stream
LKAHED	EQU	242		;get nxt char w/o removing from input
GNC	EQU	241		;get char from input, cy=1 if none
ILP	EQU	240		;inline print
DECOUT	EQU	239		;decimal output
PRBAUD	EQU	238		;print baud rate
;
CONOUT	EQU	2		; simulated BDOS functions, for MEX
PRINT	EQU	9
INBUF	EQU	10
;
;	PDIAL completion codes to be returned to MEX
;
PCARR	EQU	0	; CARRIER DETECT, CONNECTION MADE
PBSY	EQU	1	; PHONE IS BUSY
PNOANS	EQU	2	; NO ANSWER
PABRT	EQU	3	; KEYBD ABORT
PERR	EQU	4	; MODEM ERROR
;
;
;
;
;
	ORG 0162H		; MEX main overlay
DIALV:	JMP	PDIAL		;jump to modem dialing routine  162H
DISCV:	JMP	MDMDSC		;jump to modem disconnect routine    165H
;
; NOTE: User must drop DTR for at least 60 msec and then call MDMRST
; 	to properly disconnect the UDS 212 A/D
;
;
	ORG 0B00H
;
;	Entry point to dialing routine. This routine saves all the digits in
;	a buffer, dialing the number only after all digits/commands have been
;	received.  It then monitors the ACU call progress responses and returns
;	the proper success/failure codes to MEX.
;
PDIAL:	EI
	CPI	254
	JZ	STDIAL	; start of dialing sequence, reset pointers
	CPI	255
	JNZ	DDIGIT	; store digit, will dial the whole number later
;
;	all digits recieved, time to dial the number.
;
	XRA	A	; Null terminate the phone number
	CALL	DDIGIT
;
;
	CALL	FLUSH	; Flush the modem input
	MVI	B,3	; 0.3 second delay, Baud rate might have changed,
	MVI	C,TIMER	; this lets your UART adjust to the new rate (?).
	CALL	MEX
	CALL	FLUSH	; Flush input again.
;
;	First step is to train the modem to the current baud rate.
;
	CALL	MDMTRN	; Send the modem training command 'EN'
	JC	DLERR	; Exit upon training error.
;
;	Now dial the number
;
	MVI	A,'D'	; Dialing command = 'D'
	CALL	SEND1
	LXI	H,DNUMBR ; Send the phone number
	CALL	SNDSTR
	MVI	A,CR	; Send a Return to start the dialing procedure
	CALL	SEND1
;
;	Begin call progress monitoring
;
	MVI	B,20	; Delay 2 seconds, to let modem get started.
	MVI	C,TIMER
	CALL	MEX
;
	XRA	A	; clr the completion code flag
	STA	CCODE
;
;	Look for 'COMPLETE', 'BUSY', or 'ABORT' responses followed by
;	a cr,lf combination.  If there is no response from the modem in
;	25.5 seconds, report an error.
;
PDLP0:	MVI	B,0	; no response timeout counter 0=25.5 sec
PDLP1:	DCR	B
	JZ	DLERR	; Exit upon timeout error
	PUSH	B
	MVI	C,CHEKCC ; Check for Ctl-C from Keyboard
	CALL	MEX
	JZ	PDABRT
	MVI	C,INMDM
	CALL	MEX
	POP	B
	JC	PDLP1	; try again, if no chara
;
PDLP2:	CPI	'C'	; Check for the letter 'C' as in 'COMPLETE'
	JNZ	PDLP3
	STA	CCODE
;
PDLP3:	CPI	'Y'	; Check for the letter 'Y' as in 'BUSY'
	JNZ	PDLP4
	STA	CCODE
;
PDLP4:	CPI	LF	; Check for LF to terminate the response line
	JNZ	PDLP0	; reset timer and check for next chara
;
; LF has been received, if 'C' was received, we were a success, if not
; it was busy or aborted
;
	LDA	CCODE
	CPI	'C'
	JZ	PDOK
;
	CPI	'Y'
	JZ	PBUSY
; Default must be No answer/No ABT
	MVI	A,PNOANS
	JMP	MDMRST
;
PBUSY:	MVI	A,PBSY	; phone busy code
	JMP	MDMRST	; reset modem to untrained state
;
DLERR:	MVI	A,PERR	; modem error code
	JMP	MDMRST
;
PDABRT:	POP	B
	MVI	A,PABRT	; Keyboard abort code
;
;	MDMRST - Reset the ACU to an untrained state.  Aborts any
;	dialing operation in progress.
;
;	Send 'Q'. Send 'OG0'.
;	Send 3 space characters, for timing
;
MDMRST:	EI
	PUSH	PSW	; Save 'A', trashes all other reg's
	CALL	FLUSH
	MVI	A,'Q'	; Abort dialing in progress
	CALL	SEND1	;
	CALL	GCOLON	; Check if ACU is alive
	JC	MDMRS1	;
	LXI	H,CLRSTR ; Send the 'OG0' command string
	CALL	SNDSTR	; Send it if ACU was alive
MDMRS1:	CALL	FLUSH
	POP	PSW	; restore 'A'
	RET
;
PDOK:	MVI	A,PCARR
	RET
;
;	start the dialing process, reset the dial pointer
;
STDIAL:	LXI	H,DNUMBR
	SHLD	DPTR
	RET
;
;	Add a digit to the phone number string
;
DDIGIT:	LHLD	DPTR
	MOV	M,A
	INX	H
	SHLD	DPTR
	RET
;
;
TRNSTR:	DB	'EN',0
CLRSTR:	DB	'OG0   ',0
CCODE:	DB	0	; Completion code byte
DNUMBR:	DS	40	; storage for phone number
DPTR:	DW	DNUMBR	; Pointer into DNUMBR for next digit
;
;
; Support routines
;
;	Send null terminated string to modem
; 
SNDSTR:	MOV	A,M
	ORA	A
	RZ		; Null terminated string
	INX	H
	PUSH	H
	CALL	SEND1
	POP	H
	JMP	SNDSTR
;
;	Send One chara to modem
;
SEND1:	PUSH	PSW
SND1LP:	MVI	C,SNDRDY
	CALL	MEX
	JNZ	SND1LP
	POP	PSW
	MOV	B,A
	MVI	C,SNDCHR
	JMP	MEX
;
;	'Train' the modem ACU
;
MDMTRN:	LXI	H,TRNSTR	; Send the training string
	CALL	SNDSTR
	CALL	GCOLON	; Check for a ':' from the modem
	RC		; CY=1 indicates training error
	XRA	A	; CY=0
	RET
;
;	Get a colon response from the modem, if there is a character
;	timeout before receiving colon, return CY=1 to indicate error
;	All other characters are accepted, up to a maximum of 30
;
GCOLON:	MVI	C,INMDM
	MVI	B,30
GCOLP:	PUSH	B
	CALL	MEX
	POP	B
	RC		; return CY=1 upon modem timeout..
	CPI ':'
	RZ		; return CY=0 upon receving ':'
	DCR	B
	STC
	RZ		; return CY=1 upon too many characters
	JMP	GCOLP
;
FLUSH:	MVI	C,INMDM	; Read until there are no more charas in 100msec
	CALL	MEX
	JNC	FLUSH
	RET
;
;
MDMDSC:	PUSH	PSW
;
	IF UDSNEW
	  LXI	H,DSCSTR
	  CALL	SNDSTR
	  CALL	GCOLON
	ENDIF	; UDSNEW
;
	CALL	MDMRST	; untrain the modem ACU
	MVI	B,10	; 1 sec delay, let the command reach the modem and
	MVI	C,TIMER	; give it time to reset itself.
	CALL	MEX
	POP	PSW
	RET
;
DSCSTR:	DB	'XXXT',CR,0
;
;	NEW MEX1.10 Additional Code
;
	IF	MEX11
SSET:	  MVI	C,ILP
	  CALL	MEX
	  DB 	'SSET Command is not supported'
	  DB	CR,LF,0
DUMMY:	  RET
;
; MEX 1.10 Smartmodem patch points, not used for UDS 212 A/D
;
	ORG 0D55H	; Fixed at address 0D55H
	  DW	DUMMY	; SMINIT - not used.
	  DW	SSET	; SSET command not implemented.
	  DW	DUMMY	; SMEXIT - not used.
	ENDIF	; MEX11
;
	END
