;DIAL.ASM  V3.0   BY JEFF HAMMERSLEY
;
;CP/M - PMMI CONSOLE, STORED, AND PRESET AUTODIALING
;PROGRAM.
;
;  THIS PROGRAM CONTAINS MANY FEATURES FOUND IN WARD
;CHRISTENSEN'S MODEM PROGRAM 8/6/79 AND THE ORIGINATE-
;ANSWER DEMO. PROGRAM DISTRIBUTED BY PMMI FOR THEIR
;MM103 MODEM (4/2/79). FULL CREDIT MUST BE GIVEN TO
;THESE INDIVIDUALS FOR THEIR GROUND WORK.
;
;MODIFICATION HISTORY:
;
;07/31/81 ENTERED NEW TABLE OF NUMBERS TO DIAL
;	  ENTERED COMMAND '?' TO PRINT TABLE. (JCG)
;
;06/23/80 CORRECTED EDITING ERRORS IN COMMENTS AND
;	  SET MODEM PORT NUMBERS TO PMMI STANDARD. (KBP)
;
;06/22/80 CORRECTED ERROR IN SELECTING 'A' (REQUIRES NO OFFSET) 
;	  ALSO CLEANED UP PHONELIST, NOLONGER LEAVES 'GARBAGE' IN AREA.
;	  AND IT IS EASIER TO KEEP TRACK OF DATA AREA. BY HANK SZYSZKA
;
;03/08/80 RINGBACK REWRITTEN.  (BY COMMITTEE DECISION, THE FANCY
;	  FOOTWORK PREVIOUSLY DONE TO IDENTIFY BUSY AND FAR END
;	  RINGING HAS BEEN REMOVED IN FAVOR OF A MORE RELIABLE,
;	  SIMPLE CARRIER OR TONE IDENTIFICATION).  (JH)
;
;12/16/79 EXTENDED NUMBER LIST ASCII INFO.  (JH)
;
;11/21/79 BASIC TIMING MODS.  (JH)
;
;12/04/79 EQUATE AND LABEL FOR 20PPS DIALING (JH)
;
;09/21/79 ORIGINALLY WRITTEN BY JEFF HAMMERSLEY
;
;***********************************************************
;   EQUATES
;
MCTLP	 EQU	0C0H	;PMMI VALUES
MSNDB    EQU	1	;BIT TO TEST FOR SEND
MSNDR	 EQU	1	;VALUE WHEN READY
MRCVB    EQU	2	;BIT TO TEST FOR RECEIVE
MRCVR	 EQU	2	;VALUE WHEN READY
MDATP    EQU	0C1H	;DATA PORT
BAUDRP	 EQU	0C2H	;BAUD RATE OUTPUT
MCTL2	 EQU	0C3H	;SECOND CTL PORT
;
ORIGM	 EQU	1DH	;8 DATA, NO PARITY, ORIG
;
NUMPPS	 EQU	125	;125=20PPS, 250=10PPS
PULSE	 EQU	80H	;TIMER PULSE MASK
MAKE	 EQU	01H	;TEL LINE MAKE (OFF HOOK)
BRK	 EQU	00H	;TEL LINE BREAK (ON HOOK)
INTER	 EQU	7	;INTERDIGIT TIME
CLEAR	 EQU	3FH	;CLEAR MODEM TO IDLE
DTDET	 EQU	2FH	;SWITCH ON DIAL TONE DETECT
DTMSK	 EQU	01H	;DIAL TONE MASK
DTR3	 EQU	07FH	;DATA TERMINAL READY (300 baud)
CTSBT	 EQU	04H	;CLEAR TO SEND BIT
BAUDRT	 EQU	52	;BAUD RATE = 300
TRATE	 EQU	255	;TIMER RATE = 0.1 SEC/PULSE
;
;** RINGBACK TIMING EQUATES **
;(MAY REQUIRE OPTIMIZATION TO YOUR LOCAL OR LONG DISTANCE SITUATION)
;
;ROUTINE DIALING
NATOUT	 EQU	200	;# OF SEC*10 TO WAIT BEFORE GIVING NO ANSWER MESSAGE
;
;RINGBACK
RBLMT	 EQU	70	;# OF SEC*10 TO WAIT BEFORE GIVING NO RING HEARD MESS.
RBWAIT	 EQU	50	;# OF SEC*10 DELAY BEFORE REDIALING NUMBER
;
;
DISCCH	 EQU	'D'-40H	;CTL-D DISCONNECTS MODEM RTN TO CP/M
RESTAR   EQU	'C'-40H	;CTL-C ABORT TO CONSOLE PHONE # ENTRY
ESCTCP   EQU	'E'-40H	;CTL-E RTN TO CPM WITHOUT DISCONNECT
LSTCHR	 EQU	'P'-40H	;CTL-P TURN ON/OFF LIST DEVICE (SPEED >300 BAUD)
RBKCHA	 EQU	'R'	;RINGBACK SEQUENCE
;
TIMESH	 EQU	0	;PUT 1 HERE TO PULL BIT 7 HIGH
LSTDEV	 EQU	1	;PUT 1 HERE IF YOU HAVE A LIST DEVICE CAPABLE
			; OF SPEED >300 BAUD
;
;DEFINE ASCII CHARACTERS USED
;
LF  	 EQU	10	;LINEFEED
CR	 EQU	13	;CARRIAGE RETURN
BELL	 EQU	07	;BELL
; 
;*********************************************************
;
	ORG	100H
;
;INIT PRIVATE STACK
	LXI	H,0	;HL=0
	DAD	SP	;HL=STACK FROM CP/M
	SHLD	STACK	;..SAVE IT
;
RESTRT	LXI	SP,STACK ;SP=MY STACK
	CALL	START	;GO PRINT ID
	DB	1AH,0,0,0,0,0 ;ADM-3 SCREEN CLEAR 
	DB	0,0,0,0,0,0	;NULLS FOR SCREEN CLEAR
	DB	'DIAL PROGRAM ver 3.0'
	DB	CR,LF,'$'
;
START	POP	D	;GET ID MESSAGE
	CALL	PRTMSG	;PRINT IT
;
;INITIALIZE JUMPS TO CP/M CBIOS
;
	CALL	INITAD
;
;CHECK FOR PRIMARY OPTIONS OF EITHER X OR #
	LXI	D,FCB+1	;GET FIRST OPTION
	LDAX	D
	CPI	'X'	;IS IT 'X' ?
	JZ	EXAM	;YES, EXAMPLE PRINT
	CPI	'#'	;IS IT '#' ?
	JZ	DISCON	;YES, DISCONNECT
	CPI	'?'	;IS IT '?'
	JZ	PRTLST	;YES, PRINT PHONE LIST
;
;CLEAR MODEM TO IDLE
	MVI	A,CLEAR
	OUT	MCTL2
	MVI	A,BRK	;GO ON HOOK IF NOT ALREADY THERE
	OUT	MCTLP
	MVI	B,25	;SET UP TIMER
	CALL	TIMER
;
;HELP PRINT
	LXI	D,MENU	;PRINT CTRL-CHAR. CODES
	CALL	PRTMSG
;
;EVALUATE OPTION SELECTED
;
PRIOPT:	XRA	A
	STA	NFLAG	;ZERO NUMBER FLAG
	LXI	D,FCB+1	;GET 1ST OPTION CHAR.
	LDAX	D	; FOUND IN FCB
	STA	OPTION	;SAVE IT
	CPI	40H	;IS IT >= A
	JNC	GTHAN	;YES (IT MAY BE A LETTER)
	JMP	CKNUM	;NO, SEE IF A NUMBER
;
GTHAN	CPI	5BH	;IF <= Z THEN IT IS A LETTER
	JC	LETTER
	JMP	CKNUM	;SEE IF IT IS ANOTHER CHAR. > Z
;
LETTER	CALL	ORIGMD	;GO OFF HOOK, IDENT. DIAL TONE
	LXI	H,00	;LOAD H-L RESET TO ZERO
	LDA	OPTION	;GET OPTION CHAR.
	CPI	'A'	;IS IT AN 'A' (NO  OFFSET REQ)
	JZ	NOFFS	;YES, THE BYPASS OFFSET.
	LXI	D,30	;SET D-E TO OFFSET VALUE
	SUI	41H	;SUBTRACT 41H FROM LETTER TO GET #
			; OF 30 BYTE BLOCKS TO SKIP
	MOV	B,A	;MOVE TO B
;
LOOP	DAD	D	;ADD OFFSET
	DCR	B
	JNZ	LOOP	;ADD APPROPRIATE # UNTIL DONE
;
NOFFS	LXI	D,NUMLST ;GET PHONE NUMBER LIST ORIGIN
	DAD	D	;ADD TO OFFSET IN H-L
	XCHG		;MOVE RESULT TO D-E
	JMP	PROCS	;READ AND DIAL PRESET NUMBER
;
CKNUM	CALL	ORIGMD	;GO OFF HOOK, IDENT. DIAL TONE
	LXI	H,NUMBR	;LOAD H-L WITH LOCATION OF CURRENT # BUFF
	SHLD	NBP	;SAVE IN BUFF POINTER
	LDA	FCB+1	;GET FIRST CHARACTER AGAIN
	LXI	D,DBUF+2
;
CKNM	CPI	'R'	;IS IT RINGBACK?
	JZ	RINGBK	;YES
	CPI	2FH	;IF CHAR. >='0'
	JNC	GT0	;YES
	CPI	' '	;IS IT A SPACE?
	JZ	QDONE	;YES, CK IF DONE OR CONSOLE ENTRY
	ORA	A	;IS IT BINARY 0? (END OF DBUF)
	JZ	QDONE	;YES, DONE
	CPI	'-'	;IS IT DASH?
	JZ	IGN	;IGNORE
	JMP	BDCHR	;NO, MUST BE A BAD CHAR.
;
GT0	CPI	3AH	;IS IT <= 9 ?
	JC	NUM	;YES
	JMP	BDCHR	;MUST BE A BAD CHAR.
;
NUM	CALL	TYPE	;PRINT DIGIT
	CALL	DIAL	;DIAL THE DIGIT
	MVI	A,0FFH	; FLIP NUMBER FLAG (NOTES IF ANY # DIALED)
	STA	NFLAG	;
;
IGNRE	INX	D	;GET ANOTHER CHAR. FROM DBUF
	LDAX 	D	;
	JMP	CKNM	;IF FIRST CHARACTER IS A NUMBER ASSUME THAT THE REST
			;ARE AND SO GO GET ANOTHER.
IGN	CALL	TYPE	;PRINT '-'
	JMP	IGNRE
;
QDONE	LDA	NFLAG	;IS THIS THE FIRST CHAR. POSITION?
	ORA	A	; IF SO, AND IT IS A BLANK, ASSUME
	JZ	CNSLE	; THAT WE WANT CONSOLE INPUT
	JMP	DIALE	;NO, IT ISN'T- SO STORE AN EOF CHAR. IN
			; CURRENT NUMBER BUFFER
			;DIALING ENDED WAIT FOR ANSWER
;
CNSLE:	LXI	D,PMESS	;ENTER PHONE NUMBER MESSAGE
	CALL	PRTMSG
	MVI	D,255	;25 SECONDS - TOTAL DIALING TIME ALLOWED
;
CNSL1	CALL	STAT	;CHAR. ENTERED?
	JNZ	CNSL2	;YES
;
;ALLOW ONLY 255 TIME ELEMENTS TO DIAL
	MVI	B,1
	CALL	TIMER
	DCR	D
	JZ	HEXIT	;ABORT- TAKING TOO LONG TO DIAL
	JMP	CNSL1
;
CNSL2	CALL	KEYIN	; GET IT
	CALL	SPECL	;ABORT?, REDIAL? etc.
	CALL	TYPE	; PRINT IT ON TERMINAL
	CPI	2FH	; >=0 ?
	JNC	NM0	;YES
	CPI	' '	;IGNORE SPACES
	JZ	CNSL1	;
	CPI	'-'	;IGNORE DASHES
	JZ	CNSL1	;
	CPI	CR	;IF 'CR', THEN END OF NUMBER
	JZ	NEND	;
	JMP	BDCHR	;MUST BE A BAD CHAR.
;
NEND	CALL	CRLF	;PRINT A CRLF
	JMP	DIALE	;END OF DIALING
;
NM0	CPI	3AH	; <= 9 ?
	JC	CSLE	;FOUND A NUM. 0-9
	CPI	'R'	;RINGBACK MODE
	JZ	RINGBK	;
	JMP	BDCHR	;MUST BE A BAD CHAR.
;
CSLE	CALL	DIAL	;DIAL DIGIT
	JMP	CNSL1	;GET ANOTHER
;
;  DIAL STORED NUMBER REFERENCED BY D-E, THEN
;   PRINT TRAILING INFO.
PROCS:	XRA	A	;ZERO	ACC.
	STA	PFLAG	;ZERO PRINT FLAG
	LXI	H,NUMBR	;GET NUM BUFF START
	SHLD	NBP	;SAVE IN POINTER
;
PRCS1	LDA	PFLAG	;IS PRINT FLAG ON ?(=FFH)
	CPI	0FFH
	LDAX	D	;LOAD ACC WITH 1ST CHARACTER REF. BY D-E
	JZ	INCR	;IF PFLAG ON THEN PRINT ONLY
	CPI	'*'	;EMPTY NUMBER SLOT
	JZ	NONUM
	CPI	' '	;BLANK?
	JZ	INCR	;PRINT AND ADVANCE
	CPI	'-'	;DASH?
	JZ	INCR	;PRINT AND ADVANCE
	CPI	'"'	;REST TO BE PRINT ONLY?
	JZ	PSET	;YES
	CPI	2FH	; >=0
	JNC	GTH	;YES
	CPI	'$'	;EOF ?
	JZ	DIALE	;END OF DIALING
	JMP	BDCHR	;MUST BE A BAD CHAR.
;
DIGIT	CALL	TYPE	;PRINT DIGIT
	CALL	DIAL	;DIAL IT
	JMP	INCR1
;
GTH	CPI	3AH	;<=9 ?
	JC	DIGIT	;DIAL THE NUMBER
	DCX	D	;ADJUST POINTER TO 1 LESS
			; THAN LOC. OF 'R'
	CPI	'R'	;RINGBACK?
	JZ	RBPRT	;YES
	JMP	BDCHR	;BAD CHARACTER
;
RBPRT	INX	D	;RINGBACK PRINT SEQ.
	LDAX	D	;GET CHAR.
	CPI	'"'	;NON-PRINTING
	JZ	RBPRT
	CPI	'$'	;END?
	JZ	RBPR1	;YES
	CALL	TYPE	;PRINT IT
	JMP	RBPRT	;GET ANOTHER
;
RBPR1	MVI	A,LF	;
	CALL	TYPE
	JMP	RINGBK	;TO RINGBACK ROUTINE
;
INCR	CPI	'$'	;EOF CHAR.?
	JZ	DIALE	;DIALEND
	CALL	TYPE
;
INCR1	INX	D
	JMP	PRCS1
;
NONUM	LXI	D,NMESS	;NO NUMBER LISTED MESSAGE
	CALL	PRTMSG
	JMP	HEXIT	
;
PSET	MVI	A,0FFH	;LOAD PRINT ONLY FLAG
	STA	PFLAG
	JMP	INCR1	;GET NEXT CHAR.(DON'T PRINT  ")
;
;  GO TO ORIGINATE MODE AND IDENTIFY THE DIAL TONE
;***********************************************************
;
ORIGMD:	MVI	A,MAKE	;GO OFF HOOK IN ORGINATE MODE
	OUT	MCTLP	;
	MVI	A,DTDET	;SWITCH IN DIAL TONE DETECT FILTERS
	OUT	MCTL2
; WAIT FOR DIAL TONE (TIME OUT)
	MVI	D,DTMSK	;LOAD MASK FOR DIAL TONE PRESENCE
	CALL	WAT15
	LXI	D,DMESS	;DIAL TONE DETECTED MESSAGE
	CALL	PRTMSG	;PRINT ROUTINE
	RET
;
;  AUTO-DIAL ROUTINE
;*********************************************************
;
DIAL	ANI	0FH	;CONVERT TO BINARY
	LHLD	NBP	;GET BUFF POINTER
	MOV	M,A	;SAVE DIGIT IN BUFF
	INX	H	;INCRE. BUFF POINTER
	SHLD	NBP	;SAVE BUFF. POINTER
;
DIALR	CPI	0	;IF 0 CONVERT TO 10
	JNZ	DIALS
	MVI	A,10
;
DIALS	MOV	C,A	;LOAD C WITH #
	MVI	A,NUMPPS ;SET UP TIMER PULSE RATE
	OUT	BAUDRP
;
DIALC	IN	BAUDRP	;WAIT IF TIMER PULSE NOT = 0
	ANI	PULSE
	JNZ	DIALC
;
DIALB	IN	BAUDRP	;WAIT UNTIL TRANSITION TO 1 FOR SYNC
	ANI	PULSE
	JZ	DIALB
;
MKPLSE	MVI	A,MAKE	;START WITH A MAKE
	OUT	MCTLP
;
TIMEM	IN	BAUDRP	;WAIT FOR MAKE INTERVAL TO END
	ANI	PULSE
	JNZ	TIMEM
	MVI	A,BRK	;BREAK
	OUT	MCTLP
;
TIMEB	IN	BAUDRP	;WAIT FOR BREAK PULSE INTERVAL
	ANI	PULSE
	JZ	TIMEB
	DCR	C	;MORE PULSES FOR THIS DIGIT?
	JNZ	MKPLSE	;YES
; LAST PULSE WAIT FOR INTERDIGIT TIME
	MVI	A,MAKE
	OUT	MCTLP
	MVI	A,NUMPPS
	MVI	B,INTER	;INTERDIGIT INTERVAL = 7 GEN.
	CALL	TIMER2
	RET
;
BUSY:	LXI	D,BMESS	;PHONE BUSY MESSAGE
	CALL	PRTMSG
	LXI	D,NAMES2
	JMP	ABORT2
;
DIALE:	MVI	A,'$'	;PUT INTO CURRENT NUMBER BUFF.
	LHLD	NBP	;GET BUFF POINTER
	MOV	M,A	;SAVE EOF CHAR.
;
DTRON:	CALL	CRLF	;PRINT A CRLF
	MVI	A,DTR3	;TURN ON DTR AT APPROPRIATE BAUD RATE
	OUT	MCTL2
	MVI	B,1	;WAIT FOR MODEM TO TURN ON DTR
	CALL	TIMER
;SET UP UART
	MVI	A,ORIGM	;8bits, No parity, orig 
	OUT	MCTLP
;
;WAIT FOR CLEAR TO SEND OR RINGTONE
	MVI	C,NATOUT ;SET FOR X SEC
	MVI	D,CTSBT	;CARRRIER MASK BIT
;
DZ1	MVI	B,1	;SET TIMER FOR 0.1 SEC
	CALL	TIMER
	IN	BAUDRP	;GET STATUS
	STA	MSTAT	;SAVE STATUS
	ANA	D	;CARRIER ?
	JZ	CARRIER	;YES
	CALL	STAT	;KEYBOARD INPUT?
	JZ	DZZ	;NO
	CALL	KEYIN	;YES,GET IT
	CALL	SPECL	;ABORT CHAR.?
;
DZZ	DCR	C	;GET NEXT INTERVAL
	JNZ	DZ1	;
	JMP	ABORT	;TIME EXPIRED, NO ANSWER
			; OR BUSY
;
CARRIER:
	CALL	WAT15	;ALLOW 15 SECONDS FOR CTS
	IN	MDATP	;CLEAR OUT DATA GARBAGE
;PRINT CARRIER RECEIVED MESSAGE
	LXI	D,CMESS
	CALL	PRTMSG
;
;SET BAUD RATE (USUALLY 300)
	MVI	A,BAUDRT
	OUT	BAUDRP
;
;**********************************************************
; MAIN COMMUNICATION SECTION
;**********************************************************
;
TERM	CALL	LOSS	;CK FOR CARRIER LOSS
	CALL	STAT	;LOCAL CHAR KEYED?
	JZ	TERML	;..NO, CHECK LINE
	CALL	KEYIN	;GET CHAR
	CPI	ESCTCP	;TIME TO END?
	JZ	NDIS	;YES, NO DISCON
	CPI	DISCCH	;DISCONNECT REQUEST?
	JZ	DISCON	;YES, DO IT
	CPI	LSTCHR	;PRINT ON LIST DEVICE ?
	JNZ	NCHG	;NO CHANGE, CONTINUE
	LDA	LFLAG	;YES, FLIP FLAG
	CMA
	STA	LFLAG	; & SAVE IT
	XRA	A	;CLEAR ACCUM.
;
NCHG:
	IF	TIMESH
	ORI	80H	;FORCE BIT 7 TO HIGH
	ENDIF		;TIMESH
;
	OUT	MDATP	;SEND THE CHAR
;
;SEE IF CHAR FROM LINE
;
TERML	IN	MCTLP	;READ STATUS
	ANI	MRCVB	;ISOLATE BIT
	CPI	MRCVR	;READY?
	JNZ	TERM	;..NO, LOOP
	IN	MDATP	;READ DATA
	CALL	TYPE	;TYPE IT
;
	IF	LSTDEV
	CALL	LIST	;IF LIST DEVICE PRESENT (SPEED >300 BAUD)
	ENDIF
;
	JMP	TERM	;LOOP
;
;---->	DISCON: DISCONNECT THE PHONE
;
DISCON	XRA	A	;GET DISCON VALUE
	OUT	MCTLP	;RESET ORIG/ANSW
	OUT	MCTL2	;TURN OFF DTR, DO BREAK
	CALL	ILPRT	;PRINT:
	DB	CR,LF,'++ DISCONNECTED ++',CR,LF,0
	JMP	EXIT
;
;NO DISCONNECT, TYPE MSG AS REMINDER THAT PHONE'S
;OFF HOOK
;
NDIS	CALL	ILPRT
	DB	CR,LF,'++ DON''T FORGET - THE MODEM IS '
	DB	'NOT DISCONNECTED ++',CR,LF
	DB	'Use "DIAL #" to Disconnect',CR,LF,0
	JMP	EXIT
;
;*********************************************************
;
LOSS	IN	BAUDRP
	ANI	CTSBT	;MASK FOR CARRIER LOSS
	RZ		;STILL PRESENT
	LXI	D,CLMES	;TYPE CARRIER LOST MESSAGE
	CALL	PRTMSG
	JMP	HEXIT	;GO TO ABORT
;
HANGP:	XRA	A	;GET DISCONNECT VALUE
	OUT	MCTL2	;TURN OFF DTR, DO BREAK
	OUT	MCTLP	;GO ON HOOK
	RET
;
ABORT:	LXI	D,NAMES	;NO ANSWER MESSAGE
			; DO YOU WISH TO REDIAL?
;
ABORT2	CALL	HANGP
	MVI	B,25	;LOAD TIMER
	CALL	TIMER	; WITH LONG PAUSE
	CALL	PRTMSG	;PRINT THE MSG
	CALL	KEYIN	;GET REPLY
	CALL	TYPE
	CPI	'D'	;WAS A 'D' HIT?
	JZ	REDIAL	;YES
	JMP	EXIT	;NO,GO TO CP/M
;
SPECL	CPI	ESCTCP	;CTL-E JMP TO CPM
	JZ	EXIT
	CPI	DISCCH	;CTL-D DISCONNECT,TO CPM
	JZ	HEXIT
	CPI	RESTAR	;CTL-C ABORT,RESTAR
	JZ	RESTRT
	CPI	RBKCHA	;IF R
	JZ	RINGBK	;SET UP RINGBACK SEQUENCE
	CPI	LSTCHR	;CTL-P CONCURRENT LIST (DEVICE SPEED >300 BAUD)
	RNZ		;RETURN, NO SPECIAL CHARACTER IDENTIFIED
	LDA	LFLAG
	CMA		;UPDATE LIST FLAG
	STA	LFLAG
	RET
;
RINGBK:	MVI	A,'$'	;PUT INTO CURRENT # BUFFER
	LHLD	NBP	;GET BUFF POINTER
	MOV	M,A	;SAVE EOF CHAR.
	MVI	D,DTMSK	;LOAD IN TONE DETECT MASK
	MVI	C,RBLMT	;SET TIMER FOR RBLIMIT # OF SEC.
	CALL	RBTIME	;  ABORTS IF IT TAKES LONGER
	MVI	B,25	;WAIT 2.5 SEC
	CALL	TIMER	;
	IN	BAUDRP	;IS TONE STILL PRESENT ?
	ANA	D	;
	JNZ	RNGBK1	;
	JMP	BUSY	;YES, MUST BE BUSY
;
RNGBK1	CALL	HANGP	;HANGUP PHONE
	MVI	B,RBWAIT	;WAIT X SEC.
	CALL	TIMER	;
	JMP	REDIAL	;REDIAL NUMBER
;
RBTIME:	MVI	B,1	; 0.1SEC TIME OUT
	CALL	TIMER
	IN	BAUDRP	;GET STATUS
	ANA	D	;IS TONE PRESENT ?
	RZ		;YES
	DCR	C	;GET NEXT 0.1 SEC INTERVAL
	JNZ	RBTIME
	LXI	D,RBMES	;NO TONE IDENTIFIED IN TIME LIMIT
	CALL	PRTMSG	;  BUT WILL CONTINUE
	POP	D	;GET RID OF SUBROUTINE RETURN
	JMP	RNGBK1	;HANGUP, REDIAL, & LISTEN FOR CARRIER
;
REDIAL:	CALL	CRLF	;PRINT A CRLF
 	CALL	ORIGMD	;LOOK FOR DIAL TONE
	LXI	H,NUMBR	;GET START OF 'LAST' NUMBER BUFF.
;
RDIAL	MOV	A,M	;GET DIGIT
	CPI	'$'	;EOF CHAR. ?
	JZ	DTRON	;DONE DIALING
	ADI	'0'	;MAKE IT PRINTABLE
	CALL	TYPE
	MOV	A,M	;GET DIGIT AGAIN
	CALL	DIALR	;DIAL DIGIT
	INX	H	;NEXT ONE
	JMP	RDIAL
;
; SUBROUTINE- TIMER
;    reg B = # time periods to count
;***********************************************************
;
TIMER	MVI	A,TRATE	;RESET TO .1 SEC
;
TIMER2	OUT	BAUDRP
;
TIMES	IN	BAUDRP	;CK TO SEE IF TIMER BIT IS LOW
	ANI	PULSE
	JNZ	TIMES
;
TIMEE	IN	BAUDRP	;CK TO SEE IF BIT IS HIGH
	ANI	PULSE
	JZ	TIMEE
	DCR	B	;ONE PERIOD DONE
	JNZ	TIMES
	RET		;TOTAL TIME EXPIRED
;
;
;   DIALING ENDED:  CARRIER DETECT ROUTINES
;********************************************************************
;
; TIME OUT ROUTINE (CK OF BITS vs MASK IN  D )
;
WAT15:	MVI	C,150	;TIMER SET FOR 15 SEC. INTERVALS
;
T15	MVI	B,1	; .1 SEC TIMEOUT
	CALL	TIMER	;TIMER WAITS .1 SEC
	IN	BAUDRP	;TEST STATUS
	ANA	D	;MASK WITH TEST BIT IN D
	RZ		;RETURN IF OFF
	CALL	STAT
	JZ	TS15	;WAIT FOR INPUT
	CALL	KEYIN
	CALL	SPECL	;CK FOR ABORT
;
TS15	DCR	C	;GET NEXT .1 SEC INTERVAL
	JNZ	T15
	JMP	ABORT
;
;---->	INITAD: INIT'S CP/M CBIOS ADDRESSES
;
;THIS ROUTINE FILLS IN THE ADDRESSES OF VARIOUS
;JMP AND CALL INSTRUCTIONS, SO THAT CP/M BDOS
;IS BYPASSED WHILE ACCESSING THE CONSOLE.  THIS
;IS DONE TO ALLOW CHARACTERS SUCH AS CONTROL-C
;AND CONTROL-S TO BE KEYED WHILE IN TERMINAL
;MODE, WITHOUT CP/M INTERPRETING THEM.
;
INITAD	LHLD	1	;GET WARM BOOT ADDR
	LXI	D,3	;LENGTH OF A 'JMP'
	DAD	D	;TO CONSOLE STAT
	SHLD	VSTAT+1	;MODIFY CALL
	DAD	D	;TO CONSOLE IN
	SHLD	VKEYIN+1 ;MODIFY CALL
	DAD	D	;TO CONSOLE OUT
	SHLD	VTYPE+1	;MODIFY CALL
	IF	LSTDEV
	DAD	D	;TO LIST DEVICE
	SHLD	VLIST+1	;MODIFY	CALL
	ENDIF
	RET
;
CRLF	MVI	A,CR
	CALL	TYPE
	MVI	A,LF	;FALL INTO TYPE
;
;---->	TYPE: TYPE VIA DIRECT CBIOS ACCESS
;WE ASSUME CBIOS MAY DESTROY SOME REGISTERS,
;SO SAVE THEM ALL.
;
;THIS ROUTINE BYPASSES CP/M'S CTL-S, CTL-C
;TESTS.
;
TYPE	PUSH	PSW	;SAVE CHAR
	PUSH	B	;AND OTHER REGISTERS
	PUSH	D
	PUSH	H
	MOV	C,A	;FOR BIOS
VTYPE	CALL	$-$	;ADDR SET AT INIT
	POP	H	;RESTORE REGISTERS
	POP	D
	POP	B
	POP	PSW	;..AND CHAR
	RET		;FROM "TYPE"
;
;PRINT ON LIST DEVICE ROUTINE
	IF	LSTDEV	;IF LIST DEVICE IS PRESENT >300 BAUD
LIST	MOV	C,A	;SAVE CHAR.
	LDA	LFLAG	;GET LIST FLAG
	ORA	A
	RZ		;RETURN IF OFF
	PUSH	PSW	;SAVE CHAR.
	PUSH	B	;AND OTHER REGISTERS
	PUSH	D
	PUSH	H
VLIST	CALL	$-$	;ADDR SET AT INIT
	POP	H	;RESTORE REGISTERS
	POP	D
	POP	B
	POP	PSW	;..AND CHAR
	RET		;FROM	"LIST"
	ENDIF
;
;---->  STAT: KEYBOARD STATUS
;
;SAVE ALL REGISTERS, EXCEPT A, IN CASE
;CBIOS CLOBBERS THEM.
;
STAT	PUSH	B
	PUSH	D
	PUSH	H
VSTAT	CALL	$-$	;ADDR SET AT INIT
	POP	H
	POP	D
	POP	B
	ORA	A	;0 => NOT READY
	RET
;
;---->  KEYIN: KEYBOARD INPUT
;
;SAVE ALL REGISTERS, EXCEPT A, IN CASE
;CBIOS CLOBBERS THEM.
;
KEYIN	PUSH	B
	PUSH	D
	PUSH	H
VKEYIN	CALL	$-$	;ADDR SET AT INIT
	POP	H
	POP	D
	POP	B
	ANI	7FH	;STRIP PARITY IF THERE
	RET		;FROM KEYIN
;
;---->	ILPRT: INLINE PRINT OF MSG
;
;THE CALL TO ILPRT IS FOLLOWED BY A MESSAGE,
;BINARY 0 AS THE END.  BINARY 1 MAY BE USED TO
;PAUSE (MESSAGE 'PRESS RETURN TO CONTINUE')
;
ILPRT	XTHL		;SAVE HL, GET HL=MSG
;
ILPLP	MOV	A,M	;GET CHAR
	ORA	A	;END OF MSG?
	JZ	ILPRET	;..YES, RETURN
	CPI	1	;PAUSE?
	JZ	ILPAUS	;..YES
	CALL	TYPE	;TYPE THE MSG
;
ILPNEX	INX	H	;TO NEXT CHAR
	JMP	ILPLP	;LOOP
;
;PAUSE WHILE TYPING HELP SO INFO DOESN'T
;SCROLL OFF OF VIDEO SCREENS
ILPAUS	CALL	ILPRT	;PRINT:
	DB	CR,LF,'PRESS RETURN TO CONTINUE'
	DB	CR,LF,0
	CALL	KEYIN	;GET ANY CHAR
	CPI	'C'-40H	;REBOOT?
	JZ	EXIT	;YES.
	JMP	ILPNEX	;LOOP
;
ILPRET	XTHL		;RESTORE HL
	RET		;PAST MSG
;
;---->  PRTLST:  PRINTS THE PHONE LIST & GETS INPUT
;
PRTLST	PUSH	D	;STORE REGISTERS
	PUSH	H
	MVI	D,0	;STORE SKIP INCR IN D-E
	MVI	E,31
	LXI	H,NUMLST;1ST CHAR OF PHONE LIST
;
;	Move past phone number or skip * entry
;
PRTLP1	MOV	A,M	;GET CHAR FROM PHONE LIST
	INX	H	;BUMP H-L BEFORE CHECKING
	CPI	'@'	;IS IT EO LIST
	JZ	PLSTX	;YES, GO TO END
	CPI	'*'	;IS IT A BLANK
	JZ	PRTSKP	;YES, SKIP TO NEXT LINE
	CPI	'"'	;IS IT EO NUM
	JNZ	PRTLP1	;NO, GET ANOTHER CHAR
;
;	Print Rest of line
;
PRTLP2	MOV	A,M	;GET A CHAR (BUMPED ALREADY)
	CPI	'$'	;IS IT EO LINE
	JZ	PRTEOL	;YES, BYPASS LAST CHAR.
	CALL	TYPE	;PRINT IT OUT
	INX	H
	JMP	PRTLP2	;GET ANOTHER CHAR.
;
PRTEOL	INX	H	;GET READY FOR ANOTHER CHAR
	CALL	CRLF	;EO LINE
	JMP	PRTLP1	;NO, GET ANOTHER LINE
;
;	Handle End of List
;
PLSTX:	POP 	H	;RESTORE REGS
	POP	D
	CALL	ILPRT	;PRINT THIS MESSAGE
	DB	'Type the letter before name ',0
	CALL	KEYIN	;GET INPUT
	STA	OPTION	;STORE AS FROM FCB+1
	CALL	CRLF	;MAKE IT NEAT
	JMP	LETTER	;DIAL BASED ON KEYIN
;
;	Skip unused line
;
PRTSKP	DAD	D	;ADD NEXT LINE INCR
	JMP	PRTLP1	;GO FOR ANOTHER LINE
;
;---->	PRTMSG: PRINTS MSG POINTED TO BY (DE)
;
;A '$' IS THE ENDING DELIMITER FOR THE PRINT.
;NO REGISTERS SAVED.
;
PRTMSG	MVI	C,PRINT	;GET BDOS FNC
	JMP	BDOS	;PRINT MESSAGE, RETURN
;
HEXIT	CALL	HANGP	;DISCONNECT
;
EXIT	LHLD	STACK	;GET ORIGINAL STACK
	SPHL		;RESTORE IT
	RET		;--EXIT-- TO CP/M (WARM BOOT)
;
BDCHR	CALL	TYPE	;PRINT CHAR.
	CALL	HANGP	;DISCONNECT
	CALL	ILPRT	;PRINT EXIT MESSAGE
	DB	' :INVALID CHARACTER',CR,LF
	DB	'Press Return for Help, Ctrl-c if not.',cr,lf,1,0
;
EXAM	MVI	B,1	;WAIT
	CALL	TIMER
	CALL	ILPRT
 DB  cr,lf
 DB 'Commands:',cr,lf,cr,lf
 DB '   DIAL ',cr,lf
 DB '        if phone number is to be input from console',cr,lf,cr,lf
 DB '   DIAL ?',cr,lf
 DB '        for a phone listing from which you can choose',cr,lf,cr,lf
 DB '   DIAL 756-5553',cr,lf
 DB '        if the trailing number is to be dialed (spaces and',cr,lf
 DB '        dashes are ignored)',cr,lf,cr,lf
 DB '   DIAL C',cr,lf
 DB '        if one of 25 preset numbers is to be dialed (preset',cr,lf
 DB '        at time of assembly)',cr,lf,cr,lf
 DB '   An  R  which follows any number indicates that it is',cr,lf
 DB '    to be dialed as a ringback sequence.'
 DB '(One ring then dial back)',cr,lf
 DB '    (For preset numbers this must be entered before assembly)'
 DB cr,lf,cr,lf,0
	JMP	EXIT
;
MENU:
 DB '                      NOTE',cr,lf
 DB '                     ======',cr,lf
 DB '   ctrl- D  causes a disconnect and return to CP/M',cr,lf
 DB '   ctrl- E  causes a return to CP/M without a disconnect',cr,lf
 DB '   ctrl- C  aborts current dialing and restarts program',cr,lf
	IF	LSTDEV
 DB '   ctrl- P  turns list device on and off',cr,lf
	ENDIF
 DB cr,lf,cr,lf,'$'
;
;
NUMLST:
;  Phone Number list (capacity 25 numbers)
;Format    '############"acaaaaaaaaaaaaaa$'
;CAUTION:   ^----from here to here-------^
;	**MUST NOT EXCEED 30 CHARACTERS**
;	(the actual # of #'s or a's doesn't matter if <30)
;
;	where  # = a digit, space or dash
;	       " = separator between number and info
;	       a = ascii info
;	       c = a char corresponding to the second
;	           char of tag. It should follow the "
;		   by one space since it prints with
;		   the name
;	       $ = eof
;	       * = no number character
;
NA	DB	'304-555-1212" A:L.A. INFO    $'
NB	DB	'*                            $'
NC	DB	'*                            $'
ND	DB	'*                            $'
NE	DB	'*                            $'
NF	DB	'*                            $'
NG	DB	'4517840" G:GILBERTS, THE     $'
NH	DB	'*                            $'
NI	DB	'*                            $'
NJ	DB	'*                            $'
NK	DB	'*                            $'
NL	DB	'936-1212" L:WEATHER          $'
NM	DB	'*                            $'
NN	DB	'*                            $'
NO	DB	'*                            $'
NP	DB	'*                            $'
NQ	DB	'3135887054" Q:PETERSEN, K    $'
NR	DB	'*                            $'
NS	DB	'*                            $'
NT	DB	'*                            $'
NU	DB	'*                            $'
NV	DB	'844-2525" V:LOCAL TIME       $'
;	The following exceed a 24 line display
;	if all preceding entries are full
NW	DB	'*                            $'
NX	DB	'*                            $'
NY	DB	'*                            $'
NZ	DB	'*                            $'
;	The following is the list terminator
	DB	'@'
;
DMESS	DB	'Phone is off cradle  ',cr,lf,'$'
CMESS	DB	'DATA CARRIER Received',cr,lf,bell,'$'
BMESS	DB	bell,cr,lf,'BUSY Signal',bell,cr,lf,'$'
RBMES	DB	bell,lf,'No Ringing Tone Detected',cr,lf,'$'
NAMES	DB	'NO ANSWER',cr,lf
NAMES2	DB	'   If you wish to redial PRESS  D',cr,lf
	DB	'$'
CLMES	DB	cr,lf,'DATA CARRIER LOST',cr,lf,bell,'$'
NMESS	DB	'NO NUMBER STORED',cr,lf,'$'
PMESS	DB	'ENTER PHONE # (terminate with  RETURN )  ',cr,lf,'$'
;
;
NUMBR	DB	'$$$$$$$$$$$$$$$$'	;16 DIGIT BUFFER
;
PFLAG	DB	0	;PRINT FLAG
NFLAG	DB	0
LFLAG	DB	0	;LIST FLAG
MSTAT	DB	0	;MODEM STATUS
OPTION	DB	0
NBP	DS	2	;NUM BUFF POINTER
	DS	60	;STACK AREA
STACK	DS	2	;STACK POINTER
;
;  BDOS EQUATES
;
PRINT	EQU	9	;PRINT ROUTINE
BDOS	EQU	5
FCB	EQU	5CH	;SYSTEM FCB
DBUF	EQU	80H	;CP/M DEFAULT BUFFER
;
	END
