TITLE 'MEXPLUS overlay for SwitchCom Canadiana 212A modem V 1.3' ; (DELETE ABOVE TITLE LINE IF ASSEMBLING WITH ASM) ; SwitchCom Canadiana 212A overlay for MEXPLUS: revision 1.3 86/12/01 ; This module adapts MEX or MEXPLUS for the SwitchCom Canadiana 212A ; modem. Made by: SwitchCom Manufacturing Inc ; 100-10 Amber St., Markham, Ontario, Canada ; L3R 3A2 Tel: 416-475-0296 ; This overlay will work with any port overlay that terminates ; prior to 0B00H and will work with either MEX or MEXPLUS. ; 86/12/26 V1.3 - moved modem initialization code to front of ; dial code and added flag to make sure that ; modem is only initialized once ; - Ian Cottrell ; 86/06/01 V1.2 - added 'space bar return busy' code (thanks ; to Al Jewer). This code allows the user to ; push the space bar if he knows that the ; called number is busy. If he is dialing ; a series of numbers, MEX will advance to the ; next one. ; - Ian Cottrell ; 86/01/18 V1.1 - filter all but numerals from dial routine, ; tightened code, made compatible with MEXPLUS ; - Ian Cottrell ; 85/03/06 V1.0 - Written - based on MXO-SM11.ASM ; - Ian Cottrell ; Sysop ; Info Centre BBS ; Ottawa, Ont ; Canada ; 613-952-2289 FALSE EQU 0 TRUE EQU NOT FALSE DISC EQU TRUE ; <<== change to FALSE if you disc. with DTR ; always true for MEX 1.2 or greater ; System constants NDISCV EQU 015FH ; New smart modem disconnect here DIALV EQU 0162H ; Location of dial vector in port overlay DISCV EQU 0165H ; Location of disconnect vector in port overlay DIALOC EQU 0B00H ; Dialing code goes here MEX EQU 0D00H ; "CALL MEX" SMTABL: EQU 0D55H ; Smart modem init, SSET, de-init ; The following are function codes for the MEX Service Processor INMDM EQU 255 ; Return char from mdm in A, CY=no char in 100ms TIMER EQU 254 ; Delay 100ms * reg 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 character from the modem (after RCVRDY) ILP EQU 240 ; Inline print KSTAT EQU 11 ; Keyboard status KBDIN EQU 01 ; Keyboard input CR EQU 13 LF EQU 10 CTRLQ EQU 'Q'-40H ORG 100H DB 0C3H ; We're an 8080/Z-80 overlay ORG DIALV ; Overlay the dialing vector JMP DIAL IF DISC ; If providing disconnect code, ORG NDISCV ; overlay the vector JMP DISCON ENDIF ; DISC ; 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. Thus, ; the overlay may use these values to "block" the number, holding it ; in a buffer until it is completely assembled (that's the scheme ; employed here ). ; After the 254-start-dial sequence, MEX will call the overlay with ; digits, one-at-a-time. MEX will make no assumptions about the digits, ; and will send each to the DIAL routine un-inspected (some modems, ; like the Smartmodem, allow special non-numeric characters in the ; phone number, and MEX may make no assumptions about these. ; The Canadiana does not allow non-numberic characters, so they are ; filtered out by the overlay). ; 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 ; ; 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 ; First, check to see if modem has been initialized. If not, ; initialize Canadiana by setting for numeric responses and ; turning off the echo. DIAL: PUSH PSW ; Save number LDA INITFL ; Get initialization flag ORA A ; Test JNZ DIAL1 ; If done, skip init code LXI H,ECHO ; Else,point to message to set echo CALL SCSEND ; Send it to modem ELOOP: MVI C,INMDM ; Wait for response from modem CALL MEX JNC ELOOP ; Get it all LXI H,VERBOSE ; Point to message to set verbose CALL SCSEND ; Send it to modem VLOOP: MVI C,INMDM ; Wait for response CALL MEX JNC VLOOP MVI A,0FFH ; Set initialization flag STA INITFL DIAL1: POP PSW ; Restore number 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 CPI '0' ; Only allow numbers RC ; If not a number, just ignore it CPI '9'+1 RNC MOV M,A ; Must be a number, so put it in buffer INX H ; Advance pointer SHLD DIALPT ; Stuff pointer RET ; All done ; Here on a start-dial sequence STDIAL: LXI H,DIALBF ; Set up buffer pointer SHLD DIALPT RET ; Here on an end-dial sequence ENDIAL: MVI M,CR ; Stuff end-of-line into buffer INX H ; followed by terminator MVI M,0 LXI H,SCDIAL ; Point to dialing string CALL SCSEND ; Send it WAITSC: MVI C,INMDM CALL MEX ; Catch any output from the modem JNC WAITSC ; Loop until no more characters ; The following loop waits for a result from the modem (up to ; 60 seconds; you may change this value in the following line). ; Note that the Canadiana has an internal 30 second timeout while ; waiting for a carrier on the other end. RESULT: MVI C,60 ; <<== Maximum time to wait for result (in secs) SCWLP: 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 SCTEST ; If modem had a character, jump PUSH B ; Else, test for character from console MVI C,KSTAT ; Check for keypress CALL MEX ORA A POP B JZ SCNEXT ; Jump if no keypress PUSH B ; Else, get character from keyboard MVI C,KBDIN CALL MEX POP B CPI 'C'-40H ; CTL-C? JNZ SPTST ; If not, go test for space MVI A,3 ; Else, get abort code SCOFF: PUSH PSW ; Save it MVI B,CR ; Shut down the modem MVI C,SNDCHR CALL MEX POP PSW ; Restore return code RET SPTST: CPI ' ' ; Space? JNZ SCNEXT ; If not, round the loop again MVI A,1 ; Else, get busy code JP SCOFF ; Now go shut down modem SCNEXT: DCR C ; Decrement counter JNZ SCWLP ; Continue if not done ; One minute with no modem response (or no connection) SCTIMO: MVI A,2 ; Timed out, so return timeout code RET ; Modem gave us a result, check it SCTEST: ANI 7FH ; Ignore any parity CALL SCANAL ; Test the result JC RESULT ; Go try again if unknown response MOV A,B ; A=result PUSH PSW ; Save it SCTLP: MVI C,INMDM ; Eat any additional chars from Candaiana CALL MEX JNC SCTLP ; Until 100ms of quiet time POP PSW ; Return the code RET SCANAL: MVI B,0 ; Prep connect code CPI '2' ; 2=connect RZ INR B ; Prep busy cond; B=1 INR B ; Prep no connect msg; B=2 CPI '3' ; 3=no connect (from Canadiana) RZ ; Unknown response, return carry to caller. But first, ; flush the unknown response line from the modem. WTLF: CPI 1 ; 'Dialing'? STC RZ ; End if so MVI C,INMDM ; No - get next char CALL MEX JNC WTLF ; Unless busy, loop RET ; Following routine disconnects the modem using Canadiana ; codes. All registers are available for this function. ; Nothing is returned to caller. IF DISC DISCON: MVI B,20 MVI C,TIMER ; Wait 2 seconds CALL MEX LXI H,SCATN ; Send 3 Ctrl-Q's CALL SCSEND PUSH B MVI B,5 DISCLP: MVI C,TMDINP ; Wait for response from modem CALL MEX JNC DISCLP ; Wait til all done POP B LXI H,ECHRES ; Reset echo CALL SCSEND ECHLP: MVI C,INMDM ; Wait for next response CALL MEX JNC ECHLP LXI H,VERRES ; Reset verbose CALL SCSEND XRA A ; Clear the init flag in case STA INITFL ; we want to dial again RET SCATN: DB CTRLQ,CTRLQ,CTRLQ,CR,LF,0 ; Disconnect ECHRES: DB 'E=1',CR,LF,0 ; Turn echo back on VERRES: DB 'V=2',CR,LF,0 ; Turn verbose back on ENDIF ;Canadiana Utility routing: send string to modem SCSEND: MVI C,SNDRDY ; Wait for modem ready CALL MEX JNZ SCSEND MOV A,M ; Fetch next character INX H ORA A ; End? RZ ; Done if so MOV B,A ; No, position for sending MVI C,SNDCHR ; Send the character CALL MEX JMP SCSEND ; Data area SCDIAL: DB 'D' DIALBF: DS 52 ; 2 * 24 char max, + CR + NULL + slop DIALPT: DS 2 ; Dial position pointer VERBOSE:DB 'V=1',CR,LF,0 ; Set for numeric responses from modem ECHO: DB 'E=0',CR,LF,0 ; Turn echo off INITFL: DB 0 ; Storage for init flag ; must be 0 to start NOTIMP: MVI C,ILP CALL MEX DB CR,LF,'Not Implemented',CR,LF,0 JUSTRT: RET ORG SMTABL ; Table of smart modem vectors here DS 2 DW NOTIMP ; SSET command (not implemented) DW JUSTRT ; Smart modem exit (do nothing) END