;****************************************************************************** ; ; 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 *** ; ;******************************************************************************