; TITLE 'MEX DATEC 212 OVERLAY V1.0'
;
; Datec 212 overlay for MEX: revision 1.0
; Modified from MXO-SM10.ASM by Ted H. Emigh 25 May 1984 (emigh@ecsvax)
;
; Last revision: 25 May 1984, THE
;
; This modules adapts MEX for the Datec 212. The main function
; of this module is to provide dialing capability; the disconnect
; vector is ancillary.
;
; The only conditional you might want to change in this
; module is the DISC equate below -- if left on, MEX will
; use the Datec 212's disconnect code. If you prefer to
; provide your own in your overlay's DISCV vector (e.g.,
; by dropping DTR), then set DISC to FALSE and re-assemble.
; (If you don't understand this, then play it safe, and
; leave the equate set as it is).
;
; This overlay will work with any modem overlay that terminates
; prior to 0B00H
;
FALSE EQU 0
TRUE EQU NOT FALSE
;
;
DISC EQU TRUE ;<<== CHANGE TO FALSE IF YOU DISC. WITH DTR
ECHOSW EQU TRUE ;<<== TRUE IF COMMANDS TO MODEM ARE ECHOED
; BY THE MODEM
VERBOS EQU TRUE ;<<== TRUE IF MODEM MESSAGES ARE ECHOED ON
; THE CONSOLE
LFSW EQU TRUE ;<<== TRUE IF CR/LF AFTER DATEC MESSAGES
;
; SYSTEM CONSTANTS
;
TPULSE EQU 0105H ;TONE/PULSE FLAG IN MODEM OVERLAY
DIALV EQU 0162H ;LOCATION OF DIAL VECTOR IN OVERLAY
DISCV EQU 0165H ;LOCATION OF DISCONNECT VECTOR IN OVERLAY
DIALOC EQU 0B00H ;DIALING CODE GOES HERE
MEX EQU 0D00H ;"CALL MEX"
;
; FOLLOWING ARE FUNCTION CODES FOR THE MEX SERVICE CALL PROCESSOR
;
INMDM EQU 255 ;RETURN CHAR FROM MDM IN A, CY=NO CHR IN 100MS
TIMER EQU 254 ;DELAY 100 MS*REGISTER 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 CHARACTER TO THE MODEM (AFTER SNDRDY)
RCVCHR EQU 248 ;RECV A CHAR FROM MODEM (AFTER RCVRDY)
CONOUT EQU 2 ;SIMULATED BDOS FUNCTION 2: CONSOLE OUTPUT
;
CR EQU 13
LF EQU 10
;
;
;
ORG TPULSE
DB 'T' ;T=touch, P=pulse
;
ORG DIALV ;OVERLAY THE DIALING VECTOR
JMP DIAL
;
IF DISC ;IF PROVIDING DISCONNECT CODE
ORG DISCV ;OVERLAY THE VECTOR
JMP DISCON
ENDIF
;
; This is the DIAL routine called by MEX to dial a digit. The digit
; to be dialed is passed in the A register. Note that two special
; codes must be intercepted as non-digits: 254 (start dial sequence)
; and 255 (end-dial sequence). Mex will always call DIAL with 254
; in the accumulator prior to dialing a number. Mex will also call
; dial with 255 in A as an indication that dialing is complete.
;
; After the 254-start-dial sequence, MEX will call the overlay with
; digits, one-at-a-time. MEX will make no assumptions about the dig-
; its, and will send each to the DIAL routine un-inspected (some modems,
; like the Datec 212, allow special non-numeric characters in the
; phone number, and MEX may make no assumptions about these).
;
; After receiving the end-dial sequence (255) the overlay must take
; whatever end-of-dial actions are necessary *including* waiting for
; carrier at the distant end. The overlay should monitor the keyboard
; during this wait (using the MEX keystat service call), and return
; an exit code to MEX in the A register, as follows:
;
; 0 - Carrier detected, connection established
; 1 - Far end busy (only for modems that can detect this condition)
; 2 - No answer (or timed out waiting for modem response)
; 3 - Keyboard abort (^C only: all others should be ignored)
; 4 - Error reported by modem
;
; <No other codes should be returned after an end-dial sequence>
;
; The overlay should not loop forever in the carrier-wait routine, but
; instead use either the overlay timer vector, or the INMDMV (timed 100
; ms character wait) service call routine.
;
; The DIAL routine is free to use any of the registers, but must return
; the above code after an end-dial sequence
;
ORG DIALOC
;
DIAL: LHLD DIALPT ;FETCH POINTER
CPI 254 ;START DIAL?
JZ STDIAL ;JUMP IF SO
CPI 255 ;END DIAL?
JZ ENDIAL ;JUMP IF SO
;
; Not start or end sequence, must be a digit to be sent to the modem
;
MOV M,A ;PUT CHAR IN BUFFER
INX H ;ADVANCE POINTER
SHLD DIALPT ;STUFF PNTR
RET ;ALL DONE
;
; Here on a start-dial sequence
;
STDIAL: LXI H,DIALBF+1 ;SET UP BUFFER POINTER
SHLD DIALPT
RET
;
; Here on an end-dial sequence
;
ENDIAL: XRA A ;RESET DISCONNECT FLAG
STA DSCFLG
MVI M,CR ;STUFF END-OF-LINE INTO BUFFER
INX H ;FOLLOWED BY TERMINATOR
MVI M,0
LDA TPULSE ;GET OVERLAY'S TOUCH-TONE FLAG
STA DIALBF ;PUT INTO STRING
LXI H,ATTN ;GET MODEM'S ATTENTION
CALL MSEND
MVI A,3 ;WAIT 3 SECONDS FOR RESPONSE
STA TIME
CALL RESPON
CPI 6 ;SEE IF MODEM IS READY
MVI A,4 ;SET FOR MODEM ERROR
RNZ
LXI H,DIALBF ;POINT TO DIALING STRING
CALL MSEND ;SEND IT
CALL RESPON ;WAIT 3 SECONDS FOR RESPONSE
CPI 7 ;SEE IF MESSAGE "NUMBER STORED"
MVI A,4 ;SET FOR MODEM ERROR
RNZ
LXI H,DIALCM ;FINALLY, DIAL THE NUMBER
CALL MSEND ;SEND IT
CALL RESPON ;WAIT 3 SECONDS FOR A RESPONSE
CPI 5 ;SEE IF MODEM IS DIALING
MVI A,4 ;SET FOR MODEM ERROR
RNZ
MVI A,60 ;WAIT 60 SECONDS FOR RESPONSE
STA TIME
CALL RESPON
CPI 5 ;ADJUST RESPONSE TO 0-4
RC
MVI A,4 ;RESPONSE ABOVE 4 ARE ERRORS
RET
;
; THE FOLLOWING LOOP WAITS FOR A RESPONSE FROM THE MODEM (UP TO
; 60 SECONDS: YOU MAY CHANGE THIS VALUE IN THE FOLLOWING LINE)
;
RESPON: XRA A ;ZERO THE MESSAGE FLAG
STA MSGFLG
LDA TIME ;GET MAXIMUM TIME TO WAIT FOR RESPONSE
MOV C,A
MWLP: PUSH B
MVI B,1 ;CHECK FOR A CHAR, UP TO 1 SEC WAIT
MVI C,TMDINP ;DO TIMED INPUT
CALL MEX
POP B
JNC MTEST ;JUMP IF MODEM HAD A CHAR
PUSH B ;NO, TEST FOR CONTROL-C FROM CONSOLE
MVI C,CHEKCC
CALL MEX
POP B
JNZ MNEXT ;IF NOT, JUMP
LDA DSCFLG ;SEE IF ^C ALREADY HIT
ORA A
JNZ MWLP ;ALREADY HIT, IGNORE THIS ONE
DCR A ;SET DSCFLG
STA DSCFLG
LXI H,DISCD ;MAKE THIS ROUTINE EXIT THROUGH DISCD
PUSH H
JMP MWLP ;WAIT FOR ANOTHER MODEM CHARACTER
MNEXT: DCR C ;NO
JNZ MWLP ;CONTINUE
;
; ONE MINUTE WITH NO MODEM RESPONSE (OR NO CONNECTION)
;
MTIMO: MVI A,2 ;RETURN TIMEOUT CODE
RET
;
; DATA USED DURING WAIT FOR RESPONSE FROM MODEM
;
TIME: DB 0 ;TIME (IN SECONDS) TO WAIT
;
; MODEM GAVE US A RESPONSE, CHECK IT
;
MTEST:
;
IF VERBOS
CALL CDISP ;DISPLAY THE CHARACTER
ENDIF
;
ANI 7FH ;IGNORE ANY PARITY
CALL MANAL ;TEST THE RESPONSE
JC MWLP ;GO TRY AGAIN IF UNKNOWN RESPONSE
MOV A,B ;A=RESPONSE
PUSH PSW ;SAVE IT
MTLP: MVI C,INMDM ;EAT ANY ADDITIONAL CHARS FROM DATEC
CALL MEX
;
IF VERBOS
CNC CDISP ;DISPLAY THE CHARACTER (DOES NOT EFFECT CARRY)
ENDIF
;
JNC MTLP ;UNTIL 100MS OF QUIET TIME
POP PSW ;RETURN THE CODE
RET
;
MANAL: MOV B,A ;SAVE CHARACTER
LDA MSGFLG ;SEE IF CONTINUATION OF MESSAGE
ORA A
JNZ CMSG ;CONTINUATIN OF MESSAGE
MOV A,B ;RESTORE CHARACTER
CPI 'O' ;"ON LINE" OR "OFF LINE"?
JZ OMSG
CPI 'N' ;"NO CARRIER", "NUMBER STORED", OR
;"NO NUMBER STORED"
JZ NMSG
;
; RETURN CODE 0
;
MVI B,0 ;PREP CONNECT CODE
CPI '1' ;NUMERIC VERSION OF "ON LINE"
RZ
;
; RETURN CODE 2
;
MVI B,2
CPI '3' ;NUMERIC VERSION OF "NO CARRIER"
RZ
;
; RETURN CODE 4
;
MVI B,4 ;PREP MODEM ERROR
CPI 'E' ;"ERROR"?
RZ
CPI '4' ;NUMERIC VERSION OF "ERROR"
RZ
;
; RETURN CODE 5
;
INR B
CPI 'D' ;"DIALING'?
RZ
CPI '5' ;NUMERIC VERSION OF "DIALING"
RZ
CPI '6' ;NUMERIC VERSION OF "DIALING 1ST NUMBER"
RZ
CPI '7' ;NUMERIC VERSION OF "DIALING 2ND NUMBER"
RZ
;
; RETURN CODE 6
;
INR B
CPI 'R' ;USED FOR THIS ROUTINE FOR
RZ ;"READY"?
CPI '0' ;NUMERIC VERSION OF "READY"
RZ
;
; RETURN CODE 7
;
INR B
CPI '8' ;NUMERIC VERSION OF "NUMBER STORED"
RZ
;
; RETURN CODE 8
;
INR B
CPI '9' ;NUMERIC VERSION OF "OFF LINE"
RZ
;
; RETURN CODE 9
;
INR B
CPI 'A' ;NUMERIC VERSION OF "NO NUMBER STORED"
RZ
;
; FINISHED WITH RECOGNIZABLE CODES
;
CPI CR ;IGNORE CARRIAGE RETURNS
STC
RZ
;
; UNKNOWN RESPONSE, RETURN CARRY TO CALLER. BUT FIRST,
; FLUSH THE UNKNOWN RESPONSE LINE FROM THE MODEM.
;
WTLF: CPI LF ;LINEFEED?
STC
RZ ;END IF SO
WTLF1: MVI C,INMDM ;NO. GET NEXT CHAR
CALL MEX
;
IF VERBOS
CNC CDISP ;DISPLAY THE CHARACTER (DOES NOT EFFECT PSW)
ENDIF
;
JNC WTLF ;UNLESS BUSY, LOOP
RET
;
; CONTINUATION OF MESSAGE -- NOT ABLE TO DISTINGUISH
; WITH THE FIRST LETTER. USE THE FOURTH LETTER FOR "N"
; MESSAGES AND THE SECOND LETTER WITH "O" MESSAGES
;
CMSG: RAL ;SEE IF "O" OR "N" MESSAGE
JNC CNMSG ;"N" MESSAGE
;
; RETURN CODE 0
;
STA MSGFLG ;RESET MESSAGE FLAG
MOV A,B ;GET CHARACTER
MVI B,0
CPI 'N' ;"ON LINE"
RZ
;
; RETURN CODE 8
;
MVI B,8
CPI 'F' ;"OFF LINE"
RZ
JMP WTLF ;UNKNOWN RESPONSE
;
; CHECK FOURTH LETTER FOR "N" MESSAGES
;
CNMSG: RAR
INR A ;A = LETTER #
CPI 4
JC GETNXT ;IGNORE THIS LETTER, GET ANOTHER
MOV A,B
;
; RETURN CODE 2
;
MVI B,2
CPI 'C' ;"NO CARRIER"
RZ
;
; RETURN CODE 7
;
MVI B,7
CPI 'B' ;"NUMBER STORED"
RZ
;
; RETURN CODE 9
;
MVI B,9
CPI 'N' ;"NO NUMBER STORED"
RZ
JMP WTLF ;UNRECOGNIZED RESPONSE
;
; GET THE NEXT CHARACTER IN THE MESSAGE
;
GETNXT: STA MSGFLG ;UPDATE MESSAGE FLAG
RET ;CARRY FLAG IS SET
;
; INITIALIZE THE "O" MESSAGE SEARCH
;
OMSG: MVI A,80H ;SET THE MESSAGE FLAG FOR "O" MESSAGE
STA MSGFLG
STC ;GET ANOTHER CHARACTER
RET
;
; INITIALIZE THE "N" MESSAGE SEARCH
;
NMSG: MVI A,1 ;SET THE MESSAGE FLAG FOR "N" MESSAGE
STA MSGFLG
STC ;GET ANOTHER CHARACTER
RET
;
; MESSAGE FLAG
; SIGNALS WHETHER OR NOT A RESOLUTION OF AN "O" OR "N" MESSAGE
; IS IN PROGRESS
MSGFLG: DS 1
;
; SEND A TO THE CONSOLE FOR VERBOS OPTION
;
IF VERBOS
CDISP: PUSH PSW
PUSH H
PUSH D
PUSH B
ANI 7FH ;STRIP HIGH BIT
MOV E,A
MVI C,CONOUT
CALL MEX ;SEND TO THE CONSOLE
POP B
POP D
POP H
POP PSW
RET
ENDIF
;
; FOLLOWING ROUTINE DISCONNECTS THE MODEM USING DATEC
; CODES. ALL REGISTERS ARE AVAILABLE FOR THIS FUNCTION
; NOTHING RETURNED TO CALLER
;
DISCD: CALL DISCV ;DISCONNECT THE MODEM
;GO TO DISCV IN CASE DISC=FALSE
MVI A,3 ;^C CODE FOR DIAL ROUTINE
RET
;
DSCFLG: DB 0 ;DISCONNECT FLAG
;
IF DISC
;
DISCON: LXI H,MATN ;SEND '^D^D^D'
CALL MSEND
MVI A,60 ;MAXIMUM OF 60 SECONDS TO WAIT
STA TIME ;__FOR MODEM TO DISCONNECT
CALL RESPON
RET
;
MATN: DB 'D'-40H,'D'-40H,'D'-40H,0
;
ENDIF
;
; DATEC UTILITY ROUTINE: SEND STRING TO MODEM
;
MSEND: MOV A,M ;FETCH NEXT CHARACTER
INX H
ORA A ;END?
RZ ;DONE
PUSH H
PUSH PSW ;SAVE CHARACTER
MSEND1: MVI C,SNDRDY ;WAIT FOR MODEM READY
CALL MEX
JNZ MSEND1
POP B ;GET CHARACTER
MVI C,SNDCHR ;SEND THE CHARACTER
CALL MEX
;
IF ECHOSW
MVI C,INMDM ;DELAY TIL ECHO, OR 100MS
CALL MEX
ENDIF
;
POP H
JMP MSEND
;
; DATA AREA
;
ATTN: DB 'AT',0 ;GET THE MODEM'S ATTENTION
DIALCM: DB 'A/',0 ;DIAL THE NUMBER
DIALPT: DS 2 ;DIAL POSITION POINTER
DIALBF: DS 50 ;NUMBER BUFFER (48 CHAR MAX+CR+NULL+SLOP)
;
END