; ; MODULE: T3TI24-2 (Telephone Interface) for Hayes-compatible 2400 bps ; modems ; Author: David McCord/Richard Conn ; Version: 2.2 ; Date: 25 Feb 88 ; Version 2.2: Tested with EMEX 2400 modem from NAOG, P.O. Box ; 2781, Warminister, PA 1897, 215/443-9031. Code ; cleaned-up a little. fg. ; Version 2.1: This Version has been modified by Ron Bush, Hanahan, SC for ; U.S. Roboutics Courier 2400 Modem. The Courier Modem will not ; Auto-Baud below 1200 bps. There fore you have to check baud ; rate selected on ZCPR3 Message buffer before going to auto- ; baud mode, Page 4-1 Term III Manual. Also added M3 to ; Telephone Interface Initialization. Speaker On after last ; digit dialed, Off at Connect. ; Previous Versions: Richard Conn wrote T3TI-SM v1.2, which this is based on. ; v1.2 (2 Jan 86) ; ; Comments: This TI supports 300/1200/2400 bps Hayes-compatible modems. A key ; compatibility point is that the modem return the terse result code ; "10" on CONNECT 2400. Modems that should work with this TI include ; the Hayes 2400, USR Courier 2400, and Racal-Vadic 2400V. Developed ; and tested on a Courier 2400. Baud rate is automatically set upon ; connection in answer or originate modes. The answer routines have ; been rewritten from the original to NOT use modem auto-answer ; functions, as this can lead to the modem answering the phone when ; it shouldn't. ; History: v2 fixes a few minor bugs. Now console- abort during ; dialing will always work, in v1 it didn't. T3ANSWER ; sometimes ended up with the serial port at 2400 bps and ; the modem at 300 or 1200 in v1, and this has been fixed also. ; Also set the speaker off during answer routines as a nice touch. ; Set COURIER equate below; if using COURIER place your Z3BASE file ; on default drive. Rename file to TI.Z80; assemble to ; Hex and load to BIN file type, ready to be used with install ; "T3INS INSTALL.T3I" command, using ZAS and MLOAD: ; ; ZAS TI H;MLOAD TI.BIN=TI ; ORG 700H ; BASE ADDRESS (700H - 9FFH) ; ; ACCESS TO FILER$SERVER WITHIN T3ANSWER, T3DIAL, T3HANGUP, T3INIT ; FILER$SERVER EQU 11AH ; ADDRESS OF ADDRESS FS$GETSPEED EQU 0 ; GET PROCESSOR SPEED FS$WAIT1S EQU 1 ; WAIT 1 SEC FS$WAITP1S EQU 2 ; WAIT 0.1 SEC FS$WAIT1MS EQU 3 ; WAIT 0.001 SEC FS$CST EQU 4 ; CONSOLE STATUS (Z=RDA) FS$CIN EQU 5 ; CONSOLE INPUT FS$COUT EQU 6 ; CONSOLE OUTPUT (CHAR IN C) ; ; ACCESS TO MODEM OVERLAY ROUTINES ; M1$INIT EQU 600H ; INITIALIZE MODEM M1$ISTAT EQU M1$INIT+3 ; INPUT STATUS M1$OSTAT EQU M1$ISTAT+3 ; OUTPUT STATUS M1$IN EQU M1$OSTAT+3 ; INPUT BYTE M1$OUT EQU M1$IN+3 ; OUTPUT BYTE M1$BREAK EQU M1$OUT+3 ; SEND BREAK M1$CST EQU M1$BREAK+3 ; CARRIER STATUS DETECT M1$SPTAB EQU M1$CST+3 ; SPEED BYTE ; ; ASCII CONSTANTS ; CR EQU 0DH CTRLC EQU 'C'-'@' ; COURIER EQU 000H ; IF YES, USE 0FFH FOR COURIER 2400 IF COURIER .XLIST .IN Z3BASE .LIST ENDIF ; ; Telephone System Interface Routines ; TI$INIT: JP STI$INIT ; INITIALIZATION TI$ANS: JP STI$ANS ; SET ANSWER MODE TI$HANG: JP STI$HANG ; HANG UP PHONE TI$RST: JP STI$RST ; RING STATUS DETECT TI$DSTRT: JP STI$DSTRT ; START DIALING TI$DSTOP: JP STI$DSTOP ; STOP DIALING TI$DIGIT: JP STI$DIGIT ; DIAL DIGIT TI$PREPANS: JP STI$PREPANS ; PREPARE FOR ANSWERING PHONE TI$GETBAUD: JP STI$GETBAUD ; RETURN CURRENT BAUD RATE VALUE ; ; FILER$SERVER INTERFACE FOR TELEPHONE INTERFACE OVERLAY ; FILER$SERVER CODE IS IN A ; TI$FS: PUSH HL ; SAVE HL LD HL,TI$FSRET ; SET RETURN ADDRESS PUSH HL ; ... ON STACK LD HL,(FILER$SERVER) ; GET ADDRESS OF FILER$SERVER JP (HL) ; "CALL" ROUTINE TI$FSRET: POP HL ; RESTORE HL RET ; ; SEND 'ATx' COMMAND TO MODEM ; CMD$SEND: PUSH AF ; SAVE CMD LD A,FS$WAIT1S ; CODE TO WAIT 1 SECOND CALL TI$FS ; FILER$SERVER LD A,'A' ; SEND 'AT' CALL CMD$SEND1 LD A,'T' CALL CMD$SEND1 POP AF ; GET CMD ; ; SEND FURTHER COMMAND CHARS TO MODEM ; CMD$SEND1: PUSH AF ; SAVE CHAR CALL M1$OUT ; SEND CHAR IN A PUSH BC IF COURIER LD B,30 ; do this 30 times... ELSE LD B,10 ; do this 10 times... ENDIF CMD$SEND2: LD A,FS$WAIT1MS CALL TI$FS ; wait a millisecond DJNZ CMD$SEND2 ; if courier 2400 wait 30ms POP BC ; when we get here, we waited 10ms for echo CALL FLUSH ; flush the echo POP AF RET ; ; END MODEM COMMAND SEQUENCE ; CMD$END: PUSH AF ; SAVE A LD A,0DH ; SEND AND WAIT FOR CALL CMD$SEND1 ; SEND CHAR WITH ECHO POP AF ; RESTORE A RET ; ; WAIT FOR RESPONSE FROM MODEM COMMAND ; RETURN DIGIT UNLESS ERROR: ; A=0FFH if TIMEOUT ; A=0FEH if USER ABORT ; SSRESPONSE: PUSH HL LD HL,500 ; super short delay for response (.5 sec) JR RESPE SRESPONSE: PUSH HL LD HL,2000 ; SHORT DELAY FOR RESPONSE (2 secs) JR RESPE RESPONSE: PUSH HL ; SAVE HL LD HL,30000 ; LARGE DELAY FOR RESPONSE (30 secs) RESPE: LD (RESP$DELAY),HL RESP1: LD HL,(RESP$DELAY) ; DELAY FOR RESPONSE RESP2: CALL M1$ISTAT ; INPUT CHAR FROM MODEM? JR NZ,RESPM LD A,FS$CST ; CONSOLE STATUS CALL TI$FS ; USER ABORT? JR Z,RESP3 LD A,FS$WAIT1MS CALL TI$FS ; wait 0.001 sec DEC HL ; COUNT DOWN LD A,H ; DONE? OR L JR NZ,RESP2 POP HL OR 0FFH ; TIMEOUT CODE RET RESP$DELAY: DS 2 ; RESPONSE DELAY ; ; PROCESS USER CHAR ; RESP3: LD A,FS$CIN ; GET USER INPUT CALL TI$FS ; USE FILER$SERVER AND 7FH ; MASK CP CTRLC ; ABORT? JR NZ,RESP2 POP HL ; RESTORE HL LD A,0FEH ; USER ABORT OR A RET ; ; PROCESS MODEM CHAR ; RESPM: CALL M1$IN ; GET CHAR AND 7FH ; MASK JR Z,RESP1 ; FLUSH NULL POP HL ; RESTORE HL RET ; ; ATTRACT ATTENTION OF MODEM ; ATTENTION: CALL M1$CST ; DO NOTHING IF NO CARRIER RET Z CALL FLUSH ; FLUSH ANY CHAR LD A,0 ; SEND AT LEAST ONE CHAR FIRST CALL M1$OUT LD A,FS$WAIT1S ; WAIT 1 SEC CALL TI$FS ; USE FILER$SERVER LD A,'+' ; ATTRACT MODEM'S ATTENTION CALL M1$OUT CALL M1$OUT CALL M1$OUT CALL SRESPONSE ; WAIT FOR RESPONSE OR TIMEOUT RET ; ; FLUSH ANY GARBAGE CHARS FROM COMMAND LINE ; FLUSH: CALL M1$ISTAT ; ANY CHARS? RET Z ; RETURN IF NONE CALL M1$IN ; GET CHAR RET ; ; Telephone Interface Initialization ; Function: Initialize the Modem/UART Interface ; Input Parameters: None ; Output Parameters: None ; STI$INIT: PUSH AF ; SAVE A CALL ATTENTION ; GET MODEM'S ATTENTION LD A,'Z' ; RESET MODEM CALL CMD$SEND ; SEND COMMAND CALL CMD$END ; SEND CALL OK ; GET OK/USER ABORT CP 0FEH ; USER ABORT? JR Z,STI$INI1 LD A,'V' ; SET NON-VERBOSE MODE CALL CMD$SEND ; SEND COMMAND LD A,'0' ; V0 COMMAND CALL CMD$SEND1 LD A,'X' ; SET EXTENDED COMMAND SET CALL CMD$SEND1 ; SEND COMMAND LD A,'4' ; Enable result codes 0 thru 10 CALL CMD$SEND1 IF COURIER LD A,'M' ; Speaker On after last digit, Off at Connect CALL CMD$SEND1 LD A,'3' CALL CMD$SEND1 ENDIF LD A,'S' ; disable auto-answer if turned on somehow CALL CMD$SEND1 LD A,'0' CALL CMD$SEND1 LD A,'=' CALL CMD$SEND1 LD A,'0' CALL CMD$SEND1 CALL CMD$END ; SEND CALL OK1 ; GET OK/USER ABORT STI$INI1: CALL FLUSH ; FLUSH RESPONSES POP AF ; RESTORE A RET ; ; GET RESPONSE CODE OF 'OK' OR '0' ; OK: CALL SRESPONSE ; GET FIRST CHAR CP 0FEH ; USER ABORT? RET Z CP '0' ; DIGIT '0'? JR Z,OK1A CP 'O' ; LETTER 'O'? JR NZ,OK CALL SRESPONSE ; GET 'K' CP 0FEH ; USER ABORT? RET Z CALL SRESPONSE ; GET CP 0FEH ; USER ABORT? RET Z CALL SRESPONSE ; GET RET ; ; GET RESPONSE CODE OF '0' ; OK1: CALL SRESPONSE ; GET FIRST CHAR CP 0FEH ; USER ABORT? RET Z CP '0' ; OK? JR NZ,OK1 OK1A: CALL SRESPONSE ; GET RET ; ; Prepare Modem to Answer Phone ; Function: To condition modem for answering phone ; Input Parameters: None ; Output Parameters: None ; STI$PREPANS: PUSH AF LD A,3 ; set serial port to 2400 SPEED IF COURIER LD (Z3MSG+3AH),A ; SET BAUD RATE ZMSG BYTE ENDIF LD (STI$BRATE),A ; SET FLAG CALL M1$INIT LD A,'M' ; shut off speaker when recieving calls and CALL CMD$SEND ; also set modem to 2400 as a side effect LD A,'0' CALL CMD$SEND1 CALL CMD$END POP AF RET ; ; Set Modem to Answer ; Function: Set Modem to Answer Mode ; Input Parameters: None ; Output Parameters: A=0 IF NOT SUCCESSFUL, A=0FFH IF SUCCESSFUL ; STI$ANS: XOR A ; SET NO BAUD RATE IF COURIER LD (Z3MSG+3AH),A ; SET BAUD RATE ZMSG BYTE ENDIF LD (STI$BRATE),A ; SET FLAG LD A,'A' ; prepare to send ATA command CALL CMD$SEND ; send it CALL CMD$END STI$ANS1: CALL RESPONSE CP CR ; ? JR Z,STI$ANS1 CP '1' ; is it "1" or "10" (300 or 2400)? JR Z,STI$ANS324 ; If Z, process further CP '5' ; CONNECT 1200? JR Z,STI$ANS12 XOR A ; make A 0 (we didn't get a connect) RET STI$ANS324: CALL SSRESPONSE ; we should have at least a CR or a 0 pending CP CR ; is it CR? JR Z,STI$ANS3 ; must be 300 if Z STI$ANS24: LD A,3 ; select 2400 bps JR STI$ANSSET STI$ANS3: LD A,1 ; SELECT 300 BAUD JR STI$ANSSET STI$ANS12: LD A,2 ; SELECT 1200 BAUD STI$ANSSET: IF COURIER LD (Z3MSG+3AH),A ; SET BAUD RATE ZMSG BYTE ENDIF LD (STI$BRATE),A ; SET BAUD RATE CALL M1$INIT ; INIT USART BAUD RATE LD A,FS$WAITP1S ; wait 0.1 sec CALL TI$FS CALL FLUSH ; gobble possible pending CR OR A,0FFH ; RETURN CONNECT CODE RET ; ; Hang up telephone ; Function: Place the telephone on hook ; Input Parameters: None ; Output Parameters: None ; STI$HANG: PUSH AF CALL M1$CST ; DO NOT HANG UP IF NO CARRIER JR Z,STI$HANG1 CALL STI$HANG3 ; HANG UP PHONE CP 0FEH ; USER ABORT? JR Z,STI$HANG1 CALL M1$CST ; STILL CARRIER? JR Z,STI$HANG1 CALL STI$HANG3 ; TRY A SECOND TIME TO HANG UP STI$HANG1: CALL CMD$END ; send a CR to be safe POP AF RET STI$HANG3: CALL ATTENTION ; GET MODEM'S ATTENTION LD A,'H' ; HANG UP PHONE CALL CMD$SEND CALL CMD$END ; END OF COMMAND CALL SRESPONSE ; FLUSH RESPONSE DIGIT CP 0FEH ; USER ABORT RET Z CALL SRESPONSE ; FLUSH RESPONSE RET ; ; YES and NO Return Codes ; STI$YES: OR 0FFH ; SET FLAGS RET STI$NO: XOR A ; NO ANSWER RET ; ; Ring Status Detect ; Function: Determines if phone is ringing or not. ; Input Parameters: None ; Output Parameters: A=0FFH no ring, A=0 ring, A=0FEH user abort ; STI$RST: CALL SSRESPONSE ; GET RETURN CODE CP 0DH ; cr? JR Z,STI$RST CP '2' ; RING? JR Z,STI$RST3 CP 0FEH ; USER ABORT? JR Z,STI$RST2 STI$RST1: LD A,0FFH ; RETURN NO RING STI$RST2: OR A ; SET FLAGS RET STI$RST3: CALL SSRESPONSE ; get trailing CR CP 0FEH ; user abort? JR Z,STI$RST2 XOR A RET ; ; Start Dialing ; Function: Initiate the dialing process ; Input Parameters: None ; Output Parameters: A=0 if no dial tone, A=0FFH if dial tone ; STI$DSTRT: CALL FLUSH ; FLUSH CHAR IF PRESENT IF COURIER LD A,(Z3MSG+3AH) ; CHECK BAUD RATE CP 2 ; IF LESS THAN 1200 JR C,STI$DSTR1 ; NO AUTO BAUD ENDIF LD A,3 ; SELECT 2400 BPS STI$DSTR1: IF COURIER LD (Z3MSG+3AH),A ; SET BAUD RATE ZMSG BYTE ENDIF LD (STI$BRATE),A ; SET FLAG CALL M1$INIT LD A,'D' ; START DIALING CALL CMD$SEND ; SEND COMMAND LD A,'T' ; TOUCH TONE DIALING CALL CMD$SEND1 JP STI$YES ; fake dial tone OK, even though we aren't ; off-hook yet ; ; Stop Dialing ; Function: Terminate the dialing process with answer or user abort, ; and set baud rate based on result code if answer. ; Input Parameters: None ; Output Parameters: A=0 and Z if answer, NZ and error code if no ans ; Error Code: 0FFH=Timeout, 0FEH=User Abort ; Other=TI Return Code ; STI$DSTOP: LD A,CR CALL CMD$SEND1 ; send CR STI$DS1: LD A,FS$CST ; CHECK CONSOLE STATUS CALL TI$FS ; USE FILER$SERVER JR Z,STI$DS2 ; NO CONNECTION IF USER ABORT STI$DSLOOP: CALL RESPONSE ; ANSWER? CP 0FFH ; TIMEOUT? JR Z,STI$DS1 CP 0FEH ; USER ABORT JR Z,STI$DS2E CP '2' ; RING? JR Z,STI$DSLOOP CP CR ; JR Z,STI$DSLOOP CP '9'+1 ; CHECK RANGE JR NC,STI$DS1 CP '0' ; CHECK RANGE JR C,STI$DS1 CP '1' ; is it a "1" or "10"? JR Z,STI$DS324 ; process more if so CP '5' ; CONNECTED AT 1200 BAUD? RET NZ LD A,2 ; SELECT 1200 BAUD STI$DSB: IF COURIER LD (Z3MSG+3AH),A ; SET BAUD RATE ZMSG BYTE ENDIF LD (STI$BRATE),A ; SET FLAG CALL M1$INIT ; SET BAUD RATE XOR A ; RETURN CONNECT CODE RET STI$DS2: LD A,FS$CIN ; GET CHAR CALL TI$FS ; USE FILER$SERVER AND 7FH CP CTRLC ; ABORT? JR NZ,STI$DS1 STI$DS2E: LD A,0FEH ; SET USER ABORT OR A RET STI$DS324: CALL SSRESPONSE ; there is at least a CR or 0 pending CP CR ; was it cr, not 0? JR Z,STI$DS3 ; if yes, go set 300 baud STI$DS24: LD A,3 ; select 2400 bps JR STI$DSB STI$DS3: LD A,1 ; SELECT 300 BAUD JR STI$DSB ; ; Dial Digit ; Function: Dial an individual digit ; Input Parameters: A=ASCII for digit to dial ; Output Parameters: None ; STI$DIGIT: PUSH AF CP ' ' ; DON'T SEND SPACES JR Z,STI$DIGIT1 CP '-' ; don't send dashes JR Z,STI$DIGIT1 CP '(' ; don't send parenthesis JR Z,STI$DIGIT1 CP ')' ; other kind JR Z,STI$DIGIT1 CALL CMD$SEND1 ; SEND DIGIT WITH ECHO STI$DIGIT1: POP AF RET ; ; Get Baud ; Function: Return current baud rate value (from answer or dial) ; Input Parameters: None ; Output Parameters: A = Baud Rate and Z flag set ; A = 0 means undefined ; A = 1 means 300 baud ; A = 2 means 1200 bps ; A = 3 means 2400 bps ; STI$GETBAUD: LD A,(STI$BRATE) ; SET FLAG OR A ; SET FLAGS RET ; ; BAUD RATE FLAG ; A = 0 IF NONE ; A = 1 IF 300 BAUD ; A = 2 IF 1200 bps ; A = 3 IF 2400 bps ; STI$BRATE: DB 0 ; FLAG BUFFER ; ; END of Telephone Interface Routines ; DB 'End of TI-2400' END  IF 2400 bps ; STI$BRATE: DB 0 ; FLAG BUFFER ; ; END of Telephone Interface Routines