title 'MEX 2400-Smartmodem Overlay V1.0' ; ; MXM-2400.ASM: Smartmodem 2400 overlay for MEX: revision 1.0. ; ; This is a modem overlay for the MEX communication program. It ; supports 2400 baud auto-stepdown, and works with the Hayes 2400 ; and US Robotics Courier. Probably others as well. ; ; This overlay is based on revisions to MXM-SM15 made by George ; Sipe (who developed the fallback technique, and the checksum ; concept for modem response) and Paul Traina (who added Courier ; 2400 support). ; ; This overlay takes advantage of the capability of many 2400-baud ; (and perhaps some 1200 baud) modems to "fall back" when a call is ; made to a modem at a rate less than the highest rate supported by ; the calling modem. The MEXBD equate (below) determines the highest ; baudrate supported by the modem (6 for 2400, 5 for 1200), and makes ; all calls at that baudrate. If the remote modem answers at a lower ; rate, this overlay will switch to the lower rate. (You can turn ; this feature on or off with the SSET AUTO ON and SSET AUTO OFF com- ; mands, respectively. ; ; ; If you set the USR equate, MEX will automatically use the Courier's ; adaptive dialing feature, and will always enable the modem's busy ; detector (which increases the frequency of "hits" when using re- ; peated dialing to a busy number). The USR equate also enables VOICE ; answer detection (if you've ever repeatedly used MEX to dial a wrong ; number, then discovered your error and felt bad for the poor guy on ; the other end, you should use this option) Also, you can set SHOWRNG ; TRUE and this overlay will print "RING" each time the distant end rings. ; ; If you use the USR2400 equate, you may want to customize the modem ; setup string at the label SMDIAL. ; ;------------------------------------------------------------ ; ; Update history (please use MXM-2401, MXM-2402, etc when revising). ; Note to updaters: please do NOT use mixed upper-case opcodes ; and operands with lower case comments. Someone (I don't know ; who, nor, for the love 'a Mike, WHY) loves to go through ; source code and intermix case on EACH line!; (rgf) ; ; 24.01.1988: Angepasst an deutsche Verhaeltnisse -B. Bollinger ; ; 07/29/85: MXM-2400 (rev 1.0) released. (incorporated work done by ; George Sipe and Paul Traina) --Ron Fowler ; ;------------------------------------------------------------ ; ; This module adapts MEX for the DC Hayes Smartmodem (as well ; as many others -- including US Robotics -- that use a similar ; command language). The main function of this module is to pro- ; vide dialing capability; the disconnect vector is ancillary. ; You may use this module as a model to develop dialing routines ; for non-standard modems (e.g., the Racal-Vadic). The only ; pertinent entry point is the DIAL routine; you'll find entry ; specs for that below. ; ; The only conditional you might want to change in this module is ; the DISC equate below -- if left on, MEX will use the ; Smartmodem's disconnect code. If you prefer to provide your own ; in your overlay's DISCV vector (e.g., by dropping DTR), then set ; DISC to FALSE and re-assemble. (If you don't understand this, ; then play it safe, and leave the equate set as it is). NOTE: ; Note that MexPlus supports both "hardware" (DTR) AND "software" ; (Smartmodem) disconnection: always set DISC to TRUE for MexPlus. ; false equ 0 true equ not false ; usr24 equ false ;set to true if using a robotics 2400 modem adapt equ false ;set TRUE for adaptive dialing (Courier only) showrng equ true ;set true to type RING every time remote rings maxbd equ 5 ;maximum baudrate: 1=300, 3=600, 5=1200, 6=2400 wordres equ true ;true = interpret word ("verbose") result codes numres equ false ;true = interpret numeric result codes disc equ false ;<<== change to false if you disc. with DTR ;always set true for MEXPLUS ; ; NOTE: This overlay converted for MEXPLUS compatiblility ; and 8086 translation 2/20/85 by Al Jewer. ; yes equ 0ffh ;this is for 8086 translator - do not change no equ 0 i8080 equ yes ;define processor type i8086 equ no tpulsv equ 0105h ;tone/pulse flag in modem overlay ndiscv equ 015fh ;new (MexPlus) smart modem disconnect here dialv equ 0162h ;location of dial vector in overlay discv equ 0165h ;location of hardware disconnect vector dialoc equ 0b00h ;dialing code goes here mexloc equ 0d00h ;"CALL MEX" here smtabl equ 0d55h ;Smartmodem init, de-init and sset vectors ; ; Standard control code equates ; lf equ 'J'-'@' ;Linefeed cr equ 'M'-'@' ;Carriage return ; ; MEX service processor stuff ... MEX supports an overlay service ; processor, located at 0D00h (and maintained at this address from ; version to version). If your overlay needs to call bdos for any ; reason, it should call MEX instead; function calls below about ; 240 are simply passed on to the bdos (console and list i/o calls ; are specially handled to allow modem port queueing, which is why ; you should call MEX instead of bdos). MEX uses function calls ; above about 244 for special overlay services (described below). ; ; Some sophisticated overlays may need to do file i/o; if so, use ; the parsfn MEX call with a pointer to the fcb in de to parse out ; the name. This fcb should support a spare byte immediately pre- ; ceeding the actual fcb (to contain user # information). If you've ; used mex-10 for input instead of bdos-10 (or you're parsing part ; of a set command line that's already been input), then MEX will ; take care of du specs, and set up the fcb accordingly. There- ; after all file i/o calls done through the MEX service processor ; will handle drive and user with no further effort necessary on ; the part of the programmer. ; inmdm equ 255 ;get char from port to a, cy=no more in 100 ms 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 char from modem (after rcvrdy) lookup equ 247 ;table search: see cmdtbl comments for info parsfn equ 246 ;parse filename from input stream bdpars equ 245 ;parse baud-rate from input stream sblank equ 244 ;scan input stream to next non-blank evala equ 243 ;evaluate numeric from input stream lkahed equ 242 ;get nxt char w/o removing from input gnc equ 241 ;get char from input, cy=1 if none ilp equ 240 ;inline print decout equ 239 ;decimal output prbaud equ 238 ;print baud rate prntbl equ 237 ;print table prid equ 236 ;print [mex] id onoff equ 235 ;parse on/off fm input strm a=0 or 1 (c=err) ;doesn't seem to be in mex 1.12? conout equ 2 ;simulated bdos function 2: console char out print equ 9 ;simulated bdos function 9: print string inbuf equ 10 ;input buffer, same structure as bdos 10 kstat equ 11 ;keyboard status kbdin equ 01 ;keyboard input ; ; ***** Code starts here ***** ; ; ; NOTE: This file contains control characters used by our ; 8080-8086 translator, XLAT. These are in the form ; of "\" characters inserted as the first character ; of the comment field. Please do not change or ; delete these, so that future versions of this ; overlay will directly convert to 8086 operation. ; Thanks - Al Jewer. ; ; For MEXPLUS, the first byte of the overlay MUST contain a "jump" ; opcode. The is a 0C3H for 8080 and an 0E9H for 8086. MEXPLUS ; checks this byte before it loads the overlay, to make sure you ; don't load the wrong type of overlay. This byte will not affect ; pre-MEXPLUS versions. ; ; Also, MEXPLUS contains a new vector at 15FH which is the smart- ; modem disconnect vector (now separate from the hardware vector at ; 165H). The hardware vector typically toggles the DTR line to ; cause a hangup, while the smart-modem vector sends the hangup ; string to the modem. MEXPLUS will ignore the vector at 165H in ; this overlay. ; org 100h ;base of tpa ; if i8080 db 0c3h ;define 8080 overlay endif ;I8080 ; if i8086 db 0e9h ;8086 flag endif ;I8086 ; org tpulsv db 'P' ;touchtone flag ; if disc ;if providing disconnect code org ndiscv ;Smartmodem disconnect vector (MexPlus) jmp discon endif if not disc ;if not providing disconnect code org ndiscv ;fix sm25..sm24 had no org here ret ;for MEXPLUS, in case somebody screws up.... endif ;disc ; org dialv ;overlay the dialing vector jmp dial ; if disc ;if providing disconnect code org discv ;overlay the vector (mex 1.1x) jmp discon endif ;disc ; org 016eh newbdv: ds 3 ;location of baud rate set vector ; org dialoc ; ; The following is a "signature" word that identifies this overlay (for ; multiple-modem selection based on processor number in a TurboDOS sys- ; tem). If you use this overlay to develop a non-autobaud overlay for ; a different modem, either move this block to the end of the program, ; or contact NightOwl Software (414-563-4013) for assignment of a dif- ; ferent signature ID). ; dw 3746 ;signature of MXM-2400. abdflg: db 0 ;auto baud rate on/off flag mbaud: db maxbd ;maximum baudrate ; if usr24 smdial: db 'ATX5V1M3D' tpmark: db ' ',0 ;Courier dial string (adaptive/extended) endif ; if not usr24 sminit: db 'ATX1V1 S7=20',cr,0 ;ev. nach eigenen Anforderungen erweitern smdial: db 'ATD' tpmark: db 'P',0 ;Smartmodem dial string endif ; ;------------------------------------------------------------ ; ; 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 ; 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). ; ; 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) ; 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 ; ; dial: cpi 255 ;end dial? jz endial ;\jump if so cpi 254 ;start dial? jnz smchr ;go send to modem if not lda abdflg ;get autobaud rate flag ora a ;set psw lda mbaud ;get maximum baud rate cnz newbdv ;set it if autobaud rate flag <> 0 ; if not adapt ;if no adaptive dialing lda tpulsv ;get overlay's touch-tone flag sta tpmark ;put into string endif ; if not usr24 lxi h,sminit ;Zeiger auf Init-String in HL call smstr ;Init-String senden call flush ;'OK' einlesen endif lxi h,smdial ;point to dialing string jmp smstr ;send it ; ; Here on an end-dial sequence ; endial: mvi a,cr ;send end-of-line to the modem call smchr call flush ;flush any pending modem output ; ; 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 Smartmodem has an internal 30 second timeout for a ; carrier on the other end. You can change by playing with the S7 ; variable (i.e. send the smartmodem "AT S7=20" to lower the 30 ; second wait to 20 seconds). ; mvi e,45 ;<<== maximum time to wait for result smwlt: mvi d,0 ;clear response checksum smwlp: lxi b,1*256+tmdinp ;b=1 second, C=tmdinp func code call mex jnc smlog ;\jump if modem had a char mvi c,kstat ;check for keypress call mex ora a jz smnext ;\jump if no keypress mvi c,kbdin call mex cpi 'C'-40h ;is ^C? jnz nocc ;\jump if not mvi a,3 ;prep return code jmp abcom ;\finish in common code nocc: cpi ' ' ;space bar? jnz smnext ;\ignore all others mvi a,1 ;prep return code abcom: push psw ;\save return code lxi b,cr*256+sndchr ;b=cr, c=sndchr func code call mex pop psw ;\return abort code ret smnext: dcr e ;no jnz smwlp ;\continue ; ; 45 seconds with no modem response (or no connection) ; mvi a,2 ;return timeout code ret ; ; modem gave us a result, check for end and save it ; smlog: ani 7fh ;ignore any parity cpi ' ' ;see if end of message jc smrslt ;\jump when control character add d ;add to checksum mov d,a ;save response checksum jmp smwlp ;\continue ; ; result code completely presented ; smrslt: mov a,d ;get result checksum ora a ;see if accumulated yet jz smwlp ;\continue if no result yet call flush ;flush any pending modem output lxi h,rctab-2 ;get pointer to result table smrlp: inx h ;\advance to next entry inx h ;\ mov a,m ;get table entry inx h ;\bump to response cpi 0ffh ;check for end of table jnz smok ;\jump if not mvi a,4 ;else return error reported by modem ret smok: cmp d ;check for match with checksum jnz smrlp ;\loop if no match lda abdflg ;got a match. Get autobaud rate flag ora a ;set z on flag jz noauto ;\jump if not auto-baud mode mov a,m ;get newbdv-code cpi 0FFH ;null? cnz newbdv ;set it if not noauto: inx h ;\bump over newbdv-code mov a,m ;get MEX response code ; if not usr24 ;don't try to interpret extended codes ret endif if usr24 ;Courier supports ring and voice detect cpi 8 jz ring ;\say phone is ringing cpi 7 ;say we found a human rnz ;\r3\otherwise it's a normal mex code voice: call ilprt ;whoops, we have ourselves a human. db 'VOICE ',0 mvi a,2 ;return with no answer additional error r3: ret endif ; if usr24 and showrng ring: call ilprt ;just print nice ring message, db 'RING ',0 ;it's not an error jmp smwlt ;go to main loop endif ; if usr24 and not showrng ring: jmp smwlt ;\just clear the checksum and continue endif ; ; The following table is used to interpret the calculated result code ; checksum which is reported by the modem (and excludes all control ; characters). For numeric responses, the checksum is the same as ; the numeric response (in most cases). For word responses, the ; checksum is as listed in the table. The table format consists of ; triplets: result-checksum, newbdv-code, MEX-response. Note that ; with this scheme, "CONNECT 0600" and "CONNECT 2400" appear the ; same, further "RING" and "0" ("OK") appear the same. These ; should not normally cause any difficulties however. ; rctab: if wordres db 09ah,0ffh,4 ;"OK" - error reported by modem db 00ah,1,0 ;"CONNECT" - carrier detected db 030h,0ffh,4 ;"RING" - error reported by modem db 0c5h,0ffh,2 ;"NO CARRIER" - no answer db 08ah,0ffh,4 ;"ERROR" - error reported by modem db 0edh,5,0 ;"CONNECT 1200" - carrier detected db 00dh,0ffh,6 ;"NO DIALTONE" - error reported by modem db 043h,0ffh,1 ;"BUSY" - far end busy db 08dh,0ffh,2 ;"NO ANSWER" - no answer db 0f0h,6,0 ;"CONNECT 2400" - carrier detected endif ;wordres ; if wordres and usr24 db 076h,0ffh,7 ;"VOICE" - mex doesn't support...we do db 00eh,0ffh,8 ;"RINGING" - mex doesn't support..we do endif ; if numres db '1', 1,0 ;"CONNECT" - carrier detected db '2',255,4 ;"RING" - error reported by modem db '3',255,2 ;"NO CARRIER" - no answer db '4',255,4 ;"ERROR" - error reported by modem db '5', 5,0 ;"CONNECT 1200" - carrier detected db '6',255,6 ;"NO DIALTONE" - error reported by modem db '7',255,1 ;"BUSY" - far end busy db '8',255,2 ;"NO ANSWER" - no answer db '9', 3,0 ;"CONNECT 0600" - carrier detected db '1'+'0', 6,0 ;"CONNECT 2400" - carrier detected endif ; if numres and usr24 db '1'+'1',255,7 ;"RINGING" - remote modem ringing db '1'+'2',255,8 ;"VOICE" - say there is a voice endif ;numres ; db 0ffh ;end of table ; ; Following routine disconnects the modem using Smartmodem ; codes. All registers are available for this function. ; Nothing returned to caller. ; if disc discon: mvi b,20 mvi c,timer ;wait 2 seconds call mex lxi h,smatn ;send '+++' call smstr mvi b,20 ;wait 2 more seconds mvi c,timer call mex lxi h,smdisc ;send 'ath' call smstr mvi b,1 ;wait 1 second mvi c,timer jmp mex ; smatn: db '+++',0 ;Smartmodem attention string smdisc: db 'ATH',cr,0 ;Smartmodem hang-up string ; endif ;disc ; ; Smartmodem utility routine: send string to modem ; smstr: mov a,m ;fetch next character inx h ;\ ora a ;end? rz ;\r1\done if so call smchr ;otherwise send the character jmp smstr ;\ ; ; Smartmodem utility routine: send character to modem ; smchr: push psw ;save character smrdy: mvi c,sndrdy ;wait for modem ready call mex jnz smrdy ;\ pop psw ;restore character mov b,a ;position for sending mvi c,sndchr ;send the character jmp mex ; ; Smartmodem utility routine: flush pending modem output ; flush: mvi c,inmdm ;catch any output from the modem call mex jnc flush ;\loop until no more characters r1: ret ; ; This routine performs the MEX inline print function. ; ilprt: mvi c,ilp jmp mex ; ;---------------------------------------------------------------- ; ; Next is the SSET command processor. ; sset: mvi c,sblank ;Any arguments? call mex jc telall ;\tell current status if not lxi d,cmdtbl ;point command table mvi c,lookup ;see if command found call mex jc seterr ;\complain if not pchl ;else go to service routine seterr: call ilprt ;print error message db 'SSET error - use SSET AUTO {on|off}',cr,lf,0 ret ; ; This is the SSET command table. ; cmdtbl: db 'AUT','O'+80h ;Autobaud mode on/off dw setbd db 0 ;Table terminator ; ; Set message on/off processor. ; telall: setbd: lxi h,abdblk ;load pointer ; ; Boolean SSET common code. ; boole: mov e,m ;fetch address of boolean inx h ;\ mov d,m inx h ;\HL addresses text push d ;save it push h ;save that pointer mvi c,sblank ;any arguments? call mex jc tell ;\jump if not mvi c,onoff ;parse on/off from input stream call mex pop d ;recall msg pointer pop h ;boolean's adrs jc seterr ;\complain if not on or off push h ;resave push d mov m,a ;update boolean tell: pop d ;none, query only mvi c,print ;print message call mex pop h ;boolean location mov a,m ora a ;is it off? jz izoff ;\jump if so call ilprt ;else print 'on' db 'N',cr,lf,0 ret izoff: call ilprt ;print 'off' db 'FF',cr,lf,0 ret ; abdblk: dw abdflg db 'Auto baud detect O$' ; ; justrt: ret ; ; The following statement insures that we don't exceed our boundary. ; It's IFed around 8080 (with ";|") because the brain-damaged 8086 ; (Microsoft) assembler forces a type on all variables; since '$' is ; an address and 0CFFH is a constant, MASM will refuse to assemble the ; statement. Someone at Microsoft should be strung up by his fingernails ; and baked in the late afternoon sun for forcing such ridiculous con- ; straints on ASSEMBLY language programmers!; (I imagine there's some ; way around this stupidty, but I have neither the time nor the in- ; clination to go digging through the MASM documentation to find it). ; if i8080 and ($ > 0cffh) ;| : error - overlay area exceeded ;| endif ;| ; org mexloc ;"CALL MEX" mex: ; org smtabl ;table of smart modem vectors here dw justrt ;Smartmodem init dw sset ;SSET command dw justrt ;Smartmodem exit ; ; end