; ; MODULE: T3T-24-1 (Telephone Interface) for Hayes-compatible 2400bps modems ; Author: David McCord/Richard Conn ; Version: 1.0 ; Date: 23 May 86 ; Previous Versions: Richard Conn wrote T3TI-SM v1.2, which this is based on. ; Comments: This TI supports 300/1200/2400bps 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. ; 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'-'@' ; ; 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 SMARTMODEM ; 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 SMARTMODEM ; CMD$SEND1: PUSH AF ; SAVE CHAR CALL M1$OUT ; SEND CHAR IN A push bc ld b,10 ; do this 10 times... cmd$send2: ld a,fs$wait1ms call ti$fs ; wait a millisecond djnz cmd$send2 pop bc ; when we get here, we waited 10ms for echo CALL FLUSH ; flush the echo POP AF RET ; ; END SMARTMODEM 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 SMARTMODEM 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 SMARTMODEM ; 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 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 ; SELECT 2400 BAUD LD (STI$BRATE),A ; SET FLAG CALL M1$INIT 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 LD (STI$BRATE),A 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: LD (STI$BRATE),A ; SET BAUD RATE CALL M1$INIT ; INIT USART BAUD RATE 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: POP AF ; DO NOTHING SINCE WE ARE ALREADY OFFLINE RET STI$HANG3: CALL ATTENTION ; GET SMARTMODEM'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 LD A,3 ; SELECT 2400 BAUD LD (STI$BRATE),A ; SET BAUD RATE 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 ; end dial string call cmd$send1 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: LD (STI$BRATE),A ; SET BAUD RATE 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 baud ; STI$GETBAUD: LD A,(STI$BRATE) ; GET VALUE OR A ; SET FLAGS RET ; ; BAUD RATE FLAG ; A = 0 IF NONE ; A = 1 IF 300 BAUD ; A = 2 IF 1200 BAUD ; STI$BRATE: DB 0 ; FLAG BUFFER ; ; END of Telephone Interface Routines ; DB 'End of TI-2400' END