home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
rcpm
/
nbye10.lbr
/
NBYEMDM.IQC
/
NBYEMDM.INC
Wrap
Text File
|
1985-05-15
|
24KB
|
902 lines
;******************************************************************************
;
; NBHAYES.INC Gary Case
; 19 August 1984 585 Big Sky Court
; Colorado Springs, CO
; 80919
; (303) 599-0744
;
;
; Hayes Smartmodem (or compatible) Insert for NBYE.MAC
;
; *** Must be renamed as NBYEMDM.INC before assembling NBYE.
;
;
;******************************************************************************
;
;
; This insert requires an additional insert with the actual port I/O routines
; that talk to the Smartmodem. The required routines are:
;
; MDMISTAT -- Return zero status if no input character available,
; non-zero status otherwise. NOTE: This routine must
; also define the value of 'MISCYL' as follows:
;
; MISCYL EQU nn ;Nbr of machine cycles executed by
; ;this routine when no char ready
;
;
; MDMOSTAT -- Return zero status if port is not ready for output,
; non-zero status otherwise.
;
; MDMINP -- Do an input from the modem port, waiting for the next
; available character if necessary. Return the character
; in Acc. If any USART errors were detected, clear the
; errors and substitute a Null for the errored character.
;
; MDMOUT -- Send the character from Acc to the modem port.
; (Wait until ready if necessary)
;
; MDM110 -- Initialize the modem port to 110 baud.
; Not required if OK110 is FALSE.
; NOTE: DTR must be on after initialization if DTRCTRL
; is TRUE.
;
; MDM300 -- Initialize the modem port to 300 baud.
; NOTE: DTR must be on after initialization if DTRCTRL
; is TRUE.
;
; MDM1200 -- Initialize the modem port to 1200 baud.
; Not required if SM1200 is FALSE.
; NOTE: DTR must be on after initialization if DTRCTRL
; is TRUE.
;
; MDMDTRON -- Turn modem port DTR on.
; Only required if DTRCTRL is TRUE.
;
; MDMDTROFF -- Turn modem port DTR off.
; Only required if DTRCTRL is TRUE.
;
; MDMDSR -- Return Zero Flag = state of DSR from modem port.
; (NZ ==> high, Z ==> low)
; Only required if DCDDSR is TRUE.
;
;
; *** NOTE: The above routines must SAVE ALL REGISTERS except Acc.
;
;
; The following files provide the above inserts for the
; Compupro Interfacer 3 (or 4) and North Star Horizon
; right serial port, respectively:
;
; NBCPRO.INC
; NBNSRS.INC
;
; The desired insert must be renamed NBYEIO.INC
;
;
;******************************************************************************
;
; Customization Options (see notes that follow)
;
DTRCTRL EQU TRUE ;CAN WE CONTROL THE SMARTMODEM DTR INPUT?
;
DCDDSR EQU TRUE ;SMARTMODEM DCD WIRED TO COMPUTER'S DSR INPUT?
;
SM1200 EQU TRUE ;1200 BAUD SMARTMODEM?
;
OK110 EQU FALSE ;WANT TO SUPPORT 110 BAUD?
;
;
;******************************************************************************
;
;
; Configuration Notes: This insert allows several different configurations
; for the Smartmodem. The recommended configuration is
; to set DTRCTRL and DCDDSR both TRUE, and wire the
; connector as shown below. However, any combination
; can be selected. Note that if both DTRCTRL and DCDDSR
; are FALSE, a simple 3-wire connection can be used to
; connect the modem. Several functions take longer to
; perform in this mode, however, and loss of carrier
; will only be detected while I/O is through NBYE; i.e.
; it will not be detected during an XMODEM transfer
; (although as long as NBYE is set to automatically
; logout after a reasonable period of inactivity this
; should not be a significant problem).
;
;
;
; Recommended Computer to Smartmodem Cable Connections:
;
; Pin Number if Pin Number if Smartmodem When to Make the
; Computer is DTE Computer is DCE Pin Number Connection
;
; 1 1 1 Always **
; 2 3 2 Always
; 3 2 3 Always
; 5 4 5 Always ***
; 6 20 6 When DCDDSR is FALSE **
; 6 20 8 When DCDDSR is TRUE
; 7 7 7 Always
; 8 8 8 When DCDDSR is FALSE ***
; 20 6 20 When DTRCTRL is TRUE
;
;
; ** ==> Not a required connection
; *** ==> Only required if this line is not
; pulled high by your computer when
; no connection is made.
;
;
; Smartmodem Switch Settings:
;
; Switch Number Position When to Set This Way
;
; 1 UP When DTRCTRL is TRUE
; 1 DOWN When DTRCTRL is FALSE
; 2 UP Always
; 3 DOWN Always
; 4 UP Always
; 5 DOWN Always
; 6 UP When DCDDSR is TRUE
; 6 DOWN When DCDDSR is FALSE
; 7 UP For single line installations
; 7 DOWN For multiple line installations
; 8 DOWN Always
;
;
;******************************************************************************
;
;
IFT DTRCTRL EQ FALSE OR DCDDSR EQ FALSE
ESCCHR EQU 28 ;SMARTMODEM ESCAPE CHARACTER
NEWCR EQU '.' ;SMARTMODEM 'CARRIAGE RETURN' CHARACTER
NEWLF EQU '.' ;SMARTMODEM 'LINE FEED' CHARACTER
ELSE
NEWCR EQU CR
NEWLF EQU LF
ESCCHR EQU 128
ENDIF ;DTRCTRL EQ FALSE OR DCDDSR EQ FALSE
;
;
MISTAT EQU MDMISTAT ;Returns modem input status.
;
; Z ==> No Character Ready
; NZ ==> Character is Ready
;
;
;
;
MOSTAT EQU MDMOSTAT ;Returns modem output status.
;
; Z ==> Not Ready for Output
; NZ ==> Ready for Output
;
;
;
;
IFT DCDDSR
MINP EQU MDMINP ;Get Next Input Character from Modem Port
;
; ??? ==> Acc ==> Input Character
;
ELSE
MINP: CALL MDMINP ;GET CHARACTER FROM MODEM
PUSH PSW ;SAVE IT
PUSH D ;SAVE OTHER REGISTERS
PUSH H
LHLD SMCCHK ;POINT TO NEXT CHARACTER IN DISCONNECT STRING
LXI D,SMNOCR
XCHG
DAD D
CMP M ;THIS CHARACTER PART OF THE STRING?
XCHG ;(CURRENT INDEX TO HL JUST IN CASE)
JZ MABEDC ;...YES, MIGHT BE DISCONNECT STRING
RSTIDX: LXI H,-1 ;...NO, RESET POINTER TO START OF STRING
MABEDC: INX H ;UPDATE COMPARISON INDEX
SHLD SMCCHK
LXI D,SMNOCR ;END OF STRING?
DAD D
MOV A,M
ORA A
JNZ NOTDSC ;...NO, DON'T HAVE POTENTIAL DISCONNECT
CALL CARSTS ;...YES, GET TRUE CARRIER STATUS
JMP RSTIDX ;RESET INDEX TO START OF DISCONNECT STRING
;
NOTDSC: POP H ;RESTORE REGISTERS AND THE NEW CHAR AND EXIT
POP D
POP PSW
RET
ENDIF ;DCDDSR
;
;
;
MOUT EQU MDMOUT ;Send a Character to the Modem Port
;
; Character to Send ==> Acc ==> Unchanged
;
;
;
;
MINIT: ;Routine to initialize the Smartmodem.
;
;Exit Status: None
;
;
IFT DTRCTRL EQ FALSE OR DCDDSR EQ FALSE
MFIRST EQU $+1
MVI A,1 ;IS THIS THE FIRST TIME WE'VE BEEN CALLED?
DCR A
JNZ MBOKAY ;...NO, WE KNOW THE MODEM PORT BAUD RATE
STA MFIRST ;...YES, SET FLAG SO WE DON'T DO THIS AGAIN AND
IFT SM1200 ; SET APPROPRIATE MODEM PORT BAUD RATE
CALL MDM1200
ELSE
CALL MDM300
ENDIF ;SM1200
PUSH H ;SEND SMARTMODEM INIT SEQUENCE TO FORCE PROPER
LXI H,SMCMD2 ;ESCAPE CODE RECOGNITION
CALL SMSW2
POP H
MBOKAY EQU $
MVI A,0FFH ;SET 'HAVE CARRIER' FLAG VALUE
STA CARFLG
ENDIF ;DTRCTRL EQ FALSE OR DCDDSR EQ FALSE
PUSH H ;SAVE REGISTERS
LXI H,SMCMD2 ;SET DESIRED INITIALIZATION SETUP STRING
JMP MSET1 ;REST SAME AS EXIT ROUTINE
;
;
;
MEXIT: ;Routine to return the Smartmodem to a default state.
;Called when NBYE is terminated by the system operator.
;
;Exit Status: None
;
;
PUSH H ;SAVE REGISTERS
LXI H,SMCMD4 ;SET DESIRED EXIT SETUP STRING
MSET1: PUSH H ;SAVE SETUP STRING POINTER
MSET2 EQU $
IFT DTRCTRL
CALL MDMDTROFF ;TURN OFF DTR TO ENSURE NO CARRIER
MVI A,3 ;WAIT A BIT
CALL ICDELAY
CALL MDMDTRON ;TURN DTR BACK ON
ELSE
CALL SMESC ;GET CONTROL OF THE SMARTMODEM
ENDIF ;DTRCTRL
CALL MDM300 ;ALWAYS DO SETUP AT 300 BAUD
LXI H,SMCMD0 ;SEND RESET STRING TO SMARTMODEM
CALL SMSW2
JNZ MSET2 ;KEEP TRYING IF ANY PROBLEM
MVI A,5 ;WAIT FOR EXTRA INTER-COMMAND DELAY FOR RESET
CALL ICDELAY
LXI H,SMCMD1 ;SEND DESIRED SWITCH POSITIONS
CALL SMSW2
JNZ MSET2 ;KEEP TRYING IF ANY PROBLEM
POP H ;FOLLOW WITH DESIRED SETUP PARAMETERS
CALL SMSW2
JNZ MSET1 ;AND TRY AGAIN IF ANY PROBLEM
POP H ;RESTORE REGISTERS AND EXIT
RET
;
;
;
MRING: ;Routine to return current ring status. Uses the 'RING' result
;code from the Smartmodem to determine ringing.
;
;Exit Status: Z and NC ==> Not Ringing
; NZ and NC ==> Ringing
;
;
CALL SMCHK ;KEEP CHECKING MODEM STATUS
SMRPLY EQU $+1
MVI A,0FFH ;GET RING STATUS
PUSH PSW ;SAVE IT
MVI A,0FFH ;RESET REPLY FLAG REGARDLESS
STA SMRPLY
POP PSW ;RESTORE RING STATUS
CPI 3 ;SET FLAGS BASED ON WHETHER WE HAD A RING
JZ MR1
XRA A ;...NOT RINGING
RET
;
MR1: ORA A ;...RINGING
RET
;
;
;
MANSWER: ;Routine to answer the telephone. Tells Smartmodem to answer
;the telephone, then waits for the Smartmodem response code.
;If the response is 'CONNECT' or 'CONNECT 1200' then a
;connected status is returned. If the response is anything
;else, or if no response is received within 60 seconds, then
;no carrier status is returned. If a connection is
;established, the modem polling at 'SMCHK' (invoked through
;DELAY and KDELAY) is disabled.
;
;Exit Status: Z ==> No Carrier
; NZ ==> Connected with a carrier
;
;
PUSH B ;SAVE REGISTERS
PUSH H
LXI H,SMCMD3
CALL SMSW60 ;SEND ANSWER COMMAND AND WAIT FOR RESPONSE
CPI 0FFH ;CHECK FOR RESPONSE
JZ MAEXIT ;RETURN WITH ZERO STATUS IF NONE
CPI 4 ;HAVE A CONNECTION?
JZ MANSWD ;...YES, AT 110 OR 300 BAUD
ORA A
JZ MANSWD ;...YES, AT 1200 BAUD
XRA A ;...NO, RETURN ZERO STATUS
JMP MAEXIT
;
MANSWD EQU $
IFT SM1200
STA MBRATE ;STORE BAUD RATE FLAG FOR THE CONNECTION
ENDIF ;SM1200
MVI A,RET ;DISABLE 'SMCHK' POLLING
STA SMCRTN
ORA A ;FORCE NON-ZERO STATUS TO SHOW THE CONNECTION
MAEXIT: POP H ;RESTORE REGISTERS AND EXIT
POP B
RET
;
;
;
MBAUD: ;Routine to determine the appropriate baud rate.
;
; ??? ==> Acc ==> Baud Rate Indicator (if known)
; 0 ==> 110
; 1 ==> 300
; 5 ==> 1200
;
;Exit Status: C ==> Couldn't Determine Baud Rate
; NC ==> Baud Rate Indicator is Set
;
;
IFT SM1200
MBRATE EQU $+1
MVI A,0 ;WAS THE CONNECTION AT 1200 BAUD?
ORA A
JNZ LOBAUD ;...NO, HAS TO BE 110 OR 300
CALL MDM1200 ;...YES, SET CORRECT BAUD RATE AND EXIT
MVI A,5 ; WITH BAUD RATE INDICATOR AND NO CARRY
ORA A
RET
LOBAUD EQU $
ENDIF ;SM1200
;
IFF OK110 ;IF 110 BAUD NOT ALLOWED, THEN MUST BE 300
MVI A,1 ;...SO SET INDICATOR AND EXIT WITH NO CARRY
RET
ELSE ;ELSE NEED TO TRY BOTH 110 AND 300 BAUD
CALL MDM300 ;TRY 300 BAUD
CALL MCHRCK ;WAIT FOR A CHARACTER (OR LOSS OF CARRIER)
RC ;EXIT IF CARRIER LOST
MVI A,1 ;...JUST IN CASE
RZ ;DONE IF WE FOUND THE RIGHT SPEED
CALL MDM110 ;ELSE NOW TRY 110
CALL MCHRCK
RC ;EXIT IF CARRIER LOST
MVI A,0 ;...JUST IN CASE
RZ ;DONE IF WE FOUND THE RIGHT SPEED
STC ;ELSE RETURN WITH UNKNOWN STATUS
RET
ENDIF ;OK110
;
;
;
MCARRIER: ;Routine to check current carrier status.
;
;Exit Status: Z ==> No Carrier
; NZ ==> Carrier
;
;
IFT DCDDSR
JMP MDMDSR ;DCD TIED TO DSR -- JUST RETURN DSR STATUS
ELSE
CARFLG EQU $+1
MVI A,0FFH ;GET CARRIER FLAG
ORA A ;SET APPROPRIATE STATUS AND EXIT
RET
ENDIF ;DCDDSR
;
;
;
DELAY: ;Routine to delay .1 second. Polls the modem as part of the
;delay loop, and buffers any incoming data (if enabled).
;
;Exit Status: None
;
;
USEC EQU (41+SMCCYL+MHZ/2)/MHZ ;MICROSECONDS PER DELAY LOOP
LOOPS EQU 4*((25000+USEC/2)/USEC) ;LOOPS NEEDED TO KILL .1 SECOND
;
PUSH B ;SAVE REGISTERS
LXI B,LOOPS ;SET NBR OF DELAY LOOPS FOR .1 SECOND
DLAY1: CALL SMCHK ;CHECK FOR SMARTMODEM INPUT AND BUFFER IF SO
DCX B ;DO ENOUGH TIMES TO TAKE APPROX .1 SECOND
MOV A,B
ORA C
JNZ DLAY1
POP B ;RESTORE REGISTERS AND EXIT
RET
;
;
;
KDELAY: ;Routine to delay 1 millisecond. Polls the modem as part of
;the delay loop, and buffers any incoming data (if enabled).
;
;Exit Status: None
;
;
KLOOPS EQU (1000+USEC/2)/USEC
;
PUSH B
LXI B,KLOOPS
JMP DLAY1
;
;
;
SMCHK: ;Routine to check the Smartmodem for pending characters and
;buffer any which may be available. Used prior to establishing
;a connection to receive the 'RING', 'CONNECT', 'OK', and
;'CONNECT 1200' reply codes from the Smartmodem.
;
;Exit Status: None
;
;
SMCCYL EQU 28+MISCYL ;CYCLES USED WHEN NO CHAR READY
;
CALL MDMISTAT ;ANY CHARACTERS READY FROM MODEM?
SMCRTN: RZ ;...NO, NOTHING TO DO
CALL MDMINP ;...YES, GET THE CHARACTER
PUSH D ;SAVE REGISTERS
PUSH H
BFROFS EQU $+1
LXI D,0 ;COMPUTE POSITION IN BUFFER FOR THIS CHARACTER
LXI H,SMBUFR
DAD D
MOV M,A ;AND STORE THE CHARACTER
SUI LF ;UPDATE OFFSET CIRCULARLY UNLESS A LINE FEED
JZ NXTOFS ;IN WHICH CASE USE THE START OF THE BUFFER
IFT NEWLF NE LF
ADI LF-NEWLF
JZ NXTOFS
ENDIF ;NEWLF NE LF
MOV A,E
INR A
ANI 00001111B
NXTOFS: STA BFROFS
MOV A,M ;WAS CHARACTER A LINE FEED?
IFT NEWLF NE LF
CPI NEWLF
JZ C4SMR
ENDIF ;NEWLF NE LF
CPI LF
JNZ SMCXIT ;...NO, WE'RE DONE
C4SMR: LXI H,SMBUFR ;...YES, CHECK FOR SMARTMODEM RESPONSE CODE
LXI D,SMCODES
CALL SEARCH
JNZ SMCXIT ;DONE IF NOT A SMARTMODEM RESPONSE CODE
STA SMRPLY ;ELSE FIRST FLAG THE RESPONSE WE JUST RECEIVED
SMCXIT: POP H ;RESTORE REGISTERS AND EXIT
POP D
RET
;
;
;
IFF DCDDSR
;
CARSTS: ;Routine to get the true carrier status from the Smartmodem
;and store at 'CARFLG'.
;
; Store 0 at CARFLG if no carrier, 0FFH otherwise.
;
;Exit Status: None
;
;
CALL SMESC ;GET CONTROL OF THE MODEM
PUSH B ;SAVE REGISTERS
PUSH D
PUSH H
LXI H,SMCMD5 ;ASK FOR CURRENT VALUE OF STATUS REGISTER 15
CALL SMSEND
MVI A,RET ;DISABLE 'SMCHK' POLLING
STA SMCRTN
LXI B,2000 ;WAIT 2 SECONDS FOR RESPONSE
MVI D,0 ;SET INITIAL REGISTER VALUE
MVI E,3 ;NUMBER OF EXPECTED DIGITS
CSTS1: CALL MISTAT ;WAIT FOR A CHARACTER
JZ CSTS2
CALL MINP ;GET THE CHARACTER
SUI '0' ;DIGIT?
CPI 9+1
JNC CSTS2 ;...NO
MOV H,A ;...YES, UPDATE REGISTER VALUE
MOV A,D
ADD A
MOV D,A
ADD A
ADD A
ADD D
ADD H
MOV D,A
DCR E ;DONE WITH THE REGISTER VALUE?
JZ CSTS3 ;...YES
CSTS2: CALL KDELAY ;...NO, WAIT FOR NEXT CHARACTER
DCX B
MOV A,B
ORA C
JNZ CSTS1
POP H ;NO RESPONSE, SO START OVER
POP D
POP B
JMP CARSTS
;
CSTS3: MVI B,150 ;WAIT FOR .15 SECOND WITH NO INPUT
CSTS4: CALL KDELAY ;OR THE TERMINATING LINE FEED
CALL MISTAT
JZ CSTS5
CALL MINP
CPI LF
JZ CSTS6
IFT NEWLF NE LF
CPI NEWLF
JZ CSTS6
ENDIF ;NEWLF NE LF
MVI B,150+1
CSTS5: DCR B
JNZ CSTS4
CSTS6: MOV A,D ;GET REGISTER VALUE
ANI 01000000B ;ISOLATE CARRIER STATUS
JZ CSEXIT ;DONE IF NO CARRIER
LXI H,SMCMD6 ;ELSE FIRST GO BACK ON LINE
CALL SMSW2
MVI A,RET ;DISABLE 'SMCHK' POLLING
STA SMCRTN
MVI A,0FFH ;AND SET 'HAVE CARRIER' FLAG VALUE
CSEXIT: STA CARFLG ;STORE APPROPRIATE CARRIER FLAG AND EXIT
POP H
POP D
POP B
RET
ENDIF ;DCDDSR
;
;
;
IFT DTRCTRL EQ FALSE OR DCDDSR EQ FALSE
;
SMESC: ;Routine to force the Smartmodem into command mode with the
;Smartmodem escape sequence. Waits for the 'OK' response from
;the Smartmodem, and keeps trying if not received.
;
;Exit Status: None
;
;
MVI A,4 ;DELAY .6 SECOND (.4 + .2 ADDED BY 'SMSEND')
CALL ICDELAY
PUSH H ;SAVE REGISTERS
LXI H,ESCSEQ ;SEND THE ESCAPE CHARACTER SEQUENCE AND WAIT
CALL SMSW2 ;FOR 'OK' STATUS
POP H ;RESTORE REGISTERS IN ANTICIPATION
RZ ;AND EXIT IF WE'VE SUCCESSFULLY 'ESCAPED'
PUSH H ;ELSE TRY AN 'AT' IN CASE WE WEREN'T ON LINE
LXI H,SMCMD4
CALL SMSW2
POP H
RZ
JMP SMESC ;KEEP TRYING UNTIL WE SUCCEED
;
ENDIF ;DTRCTRL EQ FALSE OR DCDDSR EQ FALSE
;
;
;
SEARCH: ;Routine to search a table for a specified string.
;If found returns zero status and a zero-based index number
;for the matched string. If not found returns non-zero status.
;
; ??? => Acc => Index number of matched entry if
; match found; else 0FFH
;
; Ptr to table to => DE => ???
; search
;
; Ptr to 1st char => HL => Pointer to char after last matched
; of string char if matched; else unchanged
;
;
;Exit Status: Z ==> Match found
; NZ ==> No match in specified table
;
;Table Structure: Consecutive strings with high-order bit
; of last char in each string set. Zero
; byte as first (and only) byte of a
; string terminates the table.
;
; e.g. DB 'STRING','1'+080H
; DB 'STRING','2'+080H
; DB 0 ;END OF THE TABLE
;
;
PUSH B ;SAVE REGISTERS
PUSH H ;WITH STRING POINTER ON TOP
MVI B,0 ;INIT TABLE INDEX
CHKCHR: LDAX D ;GET CHAR FROM TABLE
ANI 01111111B ;DON'T INCLUDE END FLAG IN COMPARE
CMP M ;MATCH THE STRING?
JNZ NOMTCH ;...NO
LDAX D ;...YES, CHECK FOR END OF THE TABLE ENTRY
ANI 10000000B ; AND IF SO WE'VE FOUND A MATCH
INX D ;(BUMP POINTERS REGARDLESS)
INX H
JNZ MATCH
JMP CHKCHR ;ELSE KEEP CHECKING THE CURRENT STRING
;
MATCH: XRA A ;FOUND A MATCH -- SET ZERO FLAG
MOV A,B ;AND RETURN WITH INDEX IN ACC
POP B ;POP STRING POINTER OFF STACK
POP B ;AND RESTORE ONLY THE BC PAIR
RET
;
NOMTCH: LDAX D ;FIND END OF THE CURRENT TABLE ENTRY
ANI 10000000B ;(AND BEGINNING OF THE NEXT)
INX D
JZ NOMTCH
POP H ;RESTORE POINTER TO STRING TO CHECK
PUSH H ;BUT KEEP ON STACK
INR B ;BUMP TABLE INDEX NUMBER
LDAX D ;SEE IF WE'VE EXHAUSTED THE TABLE
ORA A
JNZ CHKCHR ;AND KEEP CHECKING IF NOT
DCR A ;ELSE FORCE NON-ZERO STATUS
POP H ;RESTORE REGISTERS AND EXIT
POP B
RET
;
;
;
MCHRCK: ;Routine to wait for a character from the modem or a loss of
;carrier. Carrier must be lost for 2 seconds before it will
;report lost carrier (so call waiting doesn't kill us). If
;a character is input, the status relative to the set of
;characters CR, LF, and Ctrl-C is returned. The routine will
;not wait longer than 5 seconds.
;
;Exit Status: C ==> Carrier Lost
; Z and NC ==> Got one of the valid characters
; NZ and NC ==> No valid character received in 5 seconds
;
;
PUSH B
MVI B,50 ;MAX TIME TO WAIT FOR A CHARACTER
MCC1: CALL MDMISTAT ;ANYTHING READY?
JNZ MCC4 ;...YES, GET IT AND EXIT
MVI C,20 ;(JUST IN CASE CARRIER'S LOST, SET TIMEOUT)
MCC2: CALL MCARRIER ;...NO, CHECK FOR CARRIER
JNZ MCC3 ; AND CONTINUE IF OKAY
CALL DELAY ;ELSE WAIT FOR CARRIER TO COME BACK
DCR C
JNZ MCC2
STC ;AND ABORT IF IT DOESN'T
POP B
RET
;
MCC3: CALL DELAY
DCR B
JNZ MCC1
POP B
IFF DCDDSR
CALL CARSTS ;TIMED OUT -- GET TRUE CARRIER STATUS
ENDIF ;DCDDSR
NZNC: MVI A,0FFH ;FORCE NON-ZERO STATUS AND NO CARRY
ORA A
RET
;
MCC4: CALL MDMINP ;GET THE WAITING CHARACTER
POP B ;RESTORE REGISTERS BEFORE PENDING EXIT
CPI CR ;SEE IF IT'S ONE OF THE EXPECTED ONES
RZ ;AND EXIT IF SO
CPI LF
RZ
CPI 'C'-040H
RZ
JMP NZNC ;ELSE EXIT WITH NZ AND NC
;
;
;
SMSW60: ;Same as SMSW2, but maximum wait time is 60 seconds.
;
;
PUSH B ;SAVE REGISTERS
PUSH H
LXI B,600 ;WAIT MAX OF 60 SECONDS FOR REPLY
JMP SMSALT ;REST IDENTICAL TO 'SMSOK2'
;
;
;
SMSW2: ;Routine to send a command to the Smartmodem and wait for the
;response. The maximum wait time is 2 seconds.
;
; ??? ==> Acc ==> Smartmodem Reply Code (See SMCODES)
; or 0FFH if no reply in 2 seconds
;
; Ptr to String ==> HL ==> Unchanged
; (0 terminated)
;
;Exit Status: Z ==> Reply was 'OK'
; NZ ==> Reply was other than 'OK'
;
;
PUSH B ;SAVE REGISTERS
PUSH H
LXI B,20 ;WAIT MAX OF 2 SECONDS FOR REPLY
SMSALT: MVI A,RZ ;ENABLE 'SMCHK' POLLING
STA SMCRTN
CALL SMSEND
W4RPLY: CALL DELAY
LDA SMRPLY ;GET REPLY FLAG
PUSH PSW ;SAVE IT JUST IN CASE
CPI 0FFH ;HAVE REPLY?
JNZ HAVRPY ;...YES
POP PSW ;...NO, BALANCE STACK AND KEEP WAITING
DCX B
MOV A,B
ORA C
JNZ W4RPLY
MVI A,0FFH ;NO REPLY IN MAX TIME -- RETURN 0FFH
PUSH PSW ;(RESULT EXPECTED ON STACK)
HAVRPY: MVI A,0FFH ;RESET REPLY FLAG
STA SMRPLY
POP PSW ;RESTORE REPLY RESULT
CPI 5 ;SET STATUS BASED ON 'OK'
POP H ;RESTORE REGISTERS AND EXIT
POP B
RET
;
;
;
SMSEND: ;Routine to send a null-terminated string to the Smartmodem.
;
; Ptr to String ==> HL ==> Ptr to String Terminator
; (0 terminated)
;
;Exit Status: None
;
;
MVI A,2 ;ALWAYS WAIT .2 SECONDS BEFORE SENDING COMMAND
CALL ICDELAY ;(TO PROVIDE INTER-COMMAND DELAY)
SMS1: MOV A,M ;GET NEXT CHARACTER OF STRING
ORA A ;END OF STRING?
RZ ;...YES, EXIT
CALL MDMOUT ;...NO, SEND TO SMARTMODEM
INX H ; AND CONTINUE WITH NEXT CHARACTER
JMP SMS1
;
;
;
ICDELAY: ;Routine to wait a specified number of .1 second intervals.
;Used to provide Smartmodem inter-command delays.
;
; Nbr of Milliseconds to delay ==> Acc ==> ???
;
;
PUSH B ;SAVE REGISTERS
MOV B,A ;SET LOOP COUNTER
ICDLAY: CALL DELAY ;DELAY A TENTH OF A SECOND
DCR B ;DONE?
JNZ ICDLAY ;...NO, CONTINUE
POP B ;...YES, RESTORE REGISTERS AND EXIT
RET
;
;
;
;******************************************************************************
;
; Data Constants
;
;
EC100 EQU ESCCHR/100
EC10 EQU (ESCCHR-100*EC100)/10
EC1 EQU ESCCHR-100*EC100-10*EC10
;
NCR100 EQU NEWCR/100
NCR10 EQU (NEWCR-100*NCR100)/10
NCR1 EQU NEWCR-100*NCR100-10*NCR10
;
NLF100 EQU NEWLF/100
NLF10 EQU (NEWLF-100*NLF100)/10
NLF1 EQU NEWLF-100*NLF100-10*NLF10
;
SMCMD0: DB 'AT Z'
IFT NEWCR NE CR
DB NEWCR
ENDIF ;NEWCR NE CR
DB CR,0
;
SMCMD1: DB 'AT E0 M0 Q0 V1'
IFT SM1200
DB ' X1'
ENDIF ;SM1200
IFT NEWCR NE CR
DB NEWCR
ENDIF ;NEWCR NE CR
DB CR,0
;
SMCMD2: DB 'AT'
DB 'S0=0'
DB 'S2=',EC100+'0',EC10+'0',EC1+'0'
DB 'S3=',NCR100+'0',NCR10+'0',NCR1+'0'
DB 'S4=',NLF100+'0',NLF10+'0',NLF1+'0'
DB 'S10=20'
DB 'S12=20'
IFT NEWCR NE CR
DB NEWCR
ENDIF ;NEWCR NE CR
DB CR,0
;
SMCMD3: DB 'AT A'
IFT NEWCR NE CR
DB NEWCR
ENDIF ;NEWCR NE CR
DB CR,0
;
SMCMD4: DB 'AT'
IFT NEWCR NE CR
DB NEWCR
ENDIF ;NEWCR NE CR
DB CR,0
;
SMCMD5: DB 'ATS15?'
IFT NEWCR NE CR
DB NEWCR
ENDIF ;NEWCR NE CR
DB CR,0
;
SMCMD6: DB 'ATO'
IFT NEWCR NE CR
DB NEWCR
ENDIF ;NEWCR NE CR
DB CR,0
;
SMBUFR: DS 16
;
ESCSEQ: DB ESCCHR,ESCCHR,ESCCHR,0
;
SMCCHK: DW 0 ;OFFSET IN 'SMNOCR' STRING FOR NEXT INPUT CHAR
;
SMNOCR: DB NEWCR,NEWLF ;STRING TO LOOK FOR FROM SMARTMODEM
DB 'NO CARRIER' ;IN CASE CARRIER LOST
DB NEWCR,NEWLF,0
;
;
HIBIT EQU 10000000B
;
SMCODES: ;Table of Smartmodem Result Codes. Order is reversed from that
;listed in the Hayes book so 'CONNECT 1200' precedes 'CONNECT'.
;Otherwise either result code would match 'CONNECT'. Result
;code indexes returned by 'SEARCH' are consequently as follows:
;
; 0 ==> CONNECT 1200
; 1 ==> ERROR
; 2 ==> NO CARRIER
; 3 ==> RING
; 4 ==> CONNECT
; 5 ==> OK
;
DB 'CONNECT 120','0'+HIBIT
DB 'ERRO','R'+HIBIT
DB 'NO CARRIE','R'+HIBIT
DB 'RIN','G'+HIBIT
DB 'CONNEC','T'+HIBIT
DB 'O','K'+HIBIT
;
;
; *** End of Smartmodem Insert ***
;
;******************************************************************************