TITLE 'MEX Cermetek Infomate 212a overlay V1.1' ; ; (DELETE ABOVE TITLE LINE IF ASSEMBLING WITH ASM) ; ; Cermetek overlay for MEX: revision 1.1 ; Written 08/22/84 by Paul Traina with grateful thanks to Ronald G. Fowler ; Last revision: 08/24/84 (PST) ; ; This modules adapts MEX for the Cermetek Infomate 212a Intelligent Modem. ; The main function of this module is to provide dialing capability; the ; disconnect vector is ancillary. ; ;---------------------------------------------------------------- ; ; 08/24/84 Updated for MEX version 1.1 -- Paul Traina ; ; 08/22/84 This is based upon original work by RGF. I can take ; no credit for the intelligence needed to make this module, ; but if there is some blame for it malfunctioning, I'll take ; that, because I was the one who performed the cut-job. ; -- Paul Traina ; ;---------------------------------------------------------------- ; ; This overlay will work with any modem overlay that terminates ; prior to 0900H ; ; System Constants ; DIALV EQU 0162H ; Location of DIAL vector in overlay DISCV EQU 0165H ; Location of DISCONNECT vector in overlay DIALOC EQU 0900H ; Dialing code goes here MEX EQU 0D00H ; "CALL MEX" ; ; Following are function codes for the MEX service call processor ; INMDM EQU 255 ; Return char form MDM in A, CY=no chr in 100ms TIMER EQU 254 ; Wait B*100ms 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 char from modem (after RCVRDY) ILP EQU 240 ; Inline print routine ; CR EQU 13 ; Ascii carriage-return LF EQU 10 ; Ascii line-feed APPOS EQU 027H ; Ascii appostrophe ; ORG DIALV ; Overlay the dialing vector JMP DIAL ; ; 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 (in fact, that's the ; scheme employed here for the Smartmodem). ; ; After the 254-start-dial sequence, MEX will call the overlay with ; digits, one-at-a-time. MEX will make no assumptions about the dig- ; its, 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). ; ; 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 ; 5 - No ring detected (only for modems that can detect this condition) ; 6 - No dial tone (only for modems that can detect this condition) ; ; ; ; 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 ; DIAL: 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 ; MOV M,A ; Put char 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,0 ; Terminate buffer CALL IMLRN ; Learn new baud rate LXI H,IMDIAL ; Point to dialing string CALL IMSEND ; Send it LXI H,IMEND ; Point to terminal part of string CALL IMSEND MVI C,INMDM CALL MEX ; Catch any output from the modem ; ; The following loop waits for a result from the modem (up to ; 60 seconds: You may change this value in the following line) ; RESULT: MVI C,60 ; <<== MAXIMUM TIME TO WAIT FOR RESULT IMWLP: 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 IMTEST ; Jump if modem had a char PUSH B ; No, test for ^C from console MVI C,CHEKCC CALL MEX POP B JNZ IMNEXT ; If not, jump CALL DISCV ; Disconnect for 1 second if possible LXI H,IMABRT ; Send abort string CALL IMSEND WTABRT: MVI C,INMDM ; Wait for any garbage CALL MEX JNC WTABRT MVI A,3 ; Return abort code RET IMNEXT: DCR C ; No JNZ IMWLP ; Continue ; ; One minute with no modem response ; IMTIMO: MVI A,4 ; Return with modem error RET ; ; Modem gave us a result, check it ; IMTEST: ANI 127 ; Ignore any parity CALL IMANAL ; Test the result JC RESULT ; Go try again if unknown response MOV A,B ; A=result PUSH PSW ; Save it IMTLP: MVI C,INMDM ; Eat any additional chars from modem CALL MEX JNC IMTLP ; Until 100ms of quiet time POP PSW ; Return the code RET ; IMANAL: MVI B,0 ; Prep connect code B=0 CPI 'A' ; Answer? RZ MVI B,1 ; Prep busy code B=1 CPI 'B' ; Busy? RZ MVI B,2 ; Prep no connect message B=2 CPI 'N' ; No answer? RZ MVI B,4 ; Prep error B=4 CPI 'W' ; Wrong baud rate? RZ MVI B,6 ; Prep no dial tone B=6 CPI 'X' ; No phone connected? RZ ; CPI 'V' ; Voice (which mex does not support) JNZ WTCR ; Error PUSH D ; Message PUSH H MVI C,ILP CALL MEX DB 'VOICE ',0 POP H POP D ; ; Unknown response, return carry to caller, do not flush unknown response ; WTCR: STC ; Set flag if so RET ; ; Utility routine, learn baud rate ; IMLRN: LXI H,IMLERN IMLRN1: MVI C,SNDRDY ; Wait for modem ready CALL MEX JNZ IMLRN1 PUSH H ; Wait 200ms MVI B,2 MVI C,TIMER CALL MEX POP H 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 ; Nope, send the character CALL MEX JMP IMLRN1 ; ; Utility routine: send string to modem ; IMSEND: MVI C,SNDRDY ; Wait for modem ready CALL MEX JNZ IMSEND 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 ; Nope, send the character CALL MEX JMP IMSEND ; ; DATA AREA ; IMDIAL: DB CR,'N'-40H,'N ~',CR,CR,CR ; Init to new attn character DB '~U 1',CR,CR,CR ; Unlisten DB '~D ',APPOS ; ~D 'num'^M DIALBF: DS 52 ; 2* 24 char max,+cr+null+slop DIALPT: DS 2 ; Dial position pointer IMEND: DB APPOS,CR,0 ; End part of dial string IMABRT: DB '~',CR,'~',CR,CR,0 ; Abort string IMLERN: DB ' XY',CR,0 ; Learn baud rate ; END