; Title 'MEX Overlay for ON! computer Version SM 2.0' ; REV EQU 20 ; Overlay revision level ; ; ; MEX Overlay for ON! Computers, external smartmodems, ; either Anchor or Hayes-compatible. ; ; A full-featured SET command processor is implemented. ; The following table outlines the SET command options: ; ; ; SET Command ; ; ANCHOR Sets modem to respond to ; Anchor modem commands; although ; Anchor modems are considered Hayes ; compatible, there ARE a few ; differences which require special ; processing considerations. ; ; DELAY Number of seconds to wait before ; aborting a call in progress ; ; BAUD Set modem to Baud rate specified. ; Baud rates supported are 300, ; 1200, 2400, 4800, 9600, and 19200 ; ; ORIG Set modem to Originate mode ; ANSWER Set modem to Auto-answer mode ; TONE Set modem to Tone dialing ; PULSE Set modem to Pulse dialing ; MONITOR Turn Hayes monitor ON ; QUIET Turn Hayes monitor OFF ; PARITY Set Parity to Odd, Even, or Off ; STOPBITS Set number of Stop Bits to 1, 1.5, 2 ; LENGTH Set word length to 5, 6, 7, 8 ; ; MANUAL ORIG ANSWER Place modem in active state and ; generate Answer or Originate ; carrier tone ; ; ; This overlay includes the smartmodem dialing routine from ; MXO-SM13.ASM by Ron Fowler which has been slightly modified ; to allow programmable delay for answer. (Note that this is ; different from the "ATS7=nn".). ; ; This overlay is intended to be fully compatible with the ; MEX structure and should be readily upward compatible with ; the predicted MEX 2.0. ; ; Calling conventions for the various overlay entry points ; are detailed more fully in the PMMI overlay (MXO-PMxx.ASM, ; where xx=revision number). ; ; History: ; November 24, 1987 MXO-ON2.Z80 (release version) ; ; Fixed buglet in PBAUD - Bruce Morgen ; ; October 8, 1987 MXO-ON2.Z80 (not released) ; ; SET ANSWER now sets the NDELAY variable to 12 via the ; SET DELAY code and waits for a connect indication from ; the modem before proceeding. A control-C abort results ; in a DISCON call, the restoration of the original SET ; DELAY condition, and a SET ORIGINATE sequence. ; ; Bruce Morgen ; ; July 20, 1987 ; Adapted for ON! computer as MXO-ON1.Z80 - Bruce Morgen ; ; 12/20/84 4.0 Fixed bugs in send break and initialization routines. ; -- Kim Levitt ; ; 11/25/84 3.0 Added SILENT option to quiet that damn beep-beep- ; beep while dialing out. Speaker will come on at ; end of dialing. ; -- Kim Levitt ; ; 9/19/84 2.0 Fixed bug in DISCON routine that left DTR/RTS off, ; added "soft" abort (any key except ^C) to abort a ; CALL in progress, but not repeats or next CALL cmds. ; -- Kim Levitt ; ; 9/9/84 1.0 The universal Kaypro overlay distributed previously ; combined support for both the internal modem on the 4'84 ; and external smartmodems. This overlay supports external ; smartmodems only, and thus provides more flexibility for ; expansion and adaptability to new MEX releases. The only ; additional feature of this overlay is support for ; entering Terminal mode via generation of manual Originate ; or Answer carrier tones. Clarity of documentation for ; the SET command has also been improved. ; Terry Carroll ; ; ; Credits: ; ; M7KP-1 overlay structure by Irv Hoff ; Smartmodem dialing routine by Ron Fowler ; Parity, Length and Stopbits routines by Norm Saunders ; MXO-KP overlay structure by John Smith ; Art work by Terry Carroll ; Bug fix/feature added by Kim Levitt ; Based on an idea by an inspired hacker ; Music by John Williams ; Directed by Stanley Kubrick ; ;------------------------------------------------------------ ; ; Miscellaneous equates ; NO EQU 0 YES EQU 0FFH ; TPA EQU 100H ; CR EQU 13 LF EQU 10 TAB EQU 9 ; ; Silent dial option: ; SILENT EQU YES ; If yes, speaker is silenced during dial ; ; (NOTE: This may not work on all "smart" modems, it works on the ; Hayes.. Set it to NO if it doesn't dial out ok...) ; ; ON! port definitions ; EXPORT EQU 92H ; Base external port EXTCT1 EQU EXPORT+1 ; External modem status port EXTDAT EQU EXPORT ; External modem data port ; ; ON! bit definitions ; MDRCVB EQU 01H ; Modem receive bit (dav) MDRCVR EQU 01H ; Modem receive ready MDSNDB EQU 04H ; Modem send bit MDSNDR EQU 04H ; Modem send ready bit ; ; ON! baud rates. Low order byte is baud rate generator divisor, ; High order byte is the Dart divisor (WR4, 1 stop bit). ; BD300 EQU 0C400H ; /64, /32 BD1200 EQU 04400H ; /16, /32 BD2400 EQU 08410H ; /32, /8 BD4800 EQU 04410H ; /16, /8 BD9600 EQU 0C420H ; /64, /1 BD19200 EQU 08420H ; /32, /1 ; ; MEX Service Processor ; MEX EQU 0D00H ; Address of the service processor 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 ; 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 ; DCONIO EQU 6 ; BDOS direct console io function # DCONIN EQU 0FFH ; BDOS dconio flag for input BDOS EQU 5 ; BDOS function caller ; ; ORG TPA ; We begin ; DS 3 ; MEX has a jmp start here ; DS 2 ; Not used by MEX TPULSE: DB 'T' ; T=touch, P=pulse (used by this overlay) CLOCK: DB 46 ; Clock speed x .1, up to 25.5 mhz. MSPEED: DB 5 ; Sets display time for sending a file ; 0=110 1=300 2=450 3=600 4=710 ; 5=1200 6=2400 7=4800 8=9600 9=19200 BYTDLY: DB 5 ; Default time to send character in ; Terminal mode file transfer (0-9) ; 0=0 delay, 1=10 ms, 5=50 ms, 9=90 ms CRDLY: DB 5 ; End-of-line delay after crlf in terminal ; Mode file transfer for slow bbs systems ; 0=0 delay, 1=100 ms, 5=500 ms, 9=900 ms COLUMS: DB 5 ; Number of directory columns SETFL: DB YES ; Yes=user-defined set command SCRTST: DB YES ; Yes=if home cursor and clear screen ; Routine at CLRSCRN DB 0 ; Was once acknak, now spare BAKFLG: DB YES ; Yes=make .BAK file CRCDFL: DB YES ; Yes=default to CRC checking ; No=default to checksum checking TOGCRC: DB YES ; Yes=allow toggling of checksum to CRC CVTBS: DB NO ; Yes=convert backspace to rub TOGLBK: DB YES ; Yes=allow toggling of bksp to rub ADDLF: DB NO ; No=no lf after cr to send file in ; Terminal mode (added by remote echo) TOGLF: DB YES ; Yes=allow toggling of lf after cr TRNLOG: DB NO ; Yes=allow transmission of logon ; Write logon sequence at location logon SAVCCP: DB YES ; Yes=do not overwrite ccp LOCNXT: DB NO ; Yes=local cmd if extchr precedes ; No=not local cmd if extchr precedes TOGLOC: DB YES ; Yes=allow toggling of locnxtchr LSTTST: DB YES ; Yes=allow toggling of printer on/off ; In terminal mode. set to no if using ; The printer port for the modem XOFTST: DB NO ; Yes=allow testing of XOFF from remote ; While sending a file in terminal mode XONWT: DB NO ; Yes=wait for xon after sending cr while ; Transmitting a file in terminal mode TOGXOF: DB YES ; Yes=allow toggling of XOFF testing IGNCTL: DB NO ; Yes=do not send control characters ; Above ctl-m to CRT in terminal mode ; No=send any incoming ctl-char to CRT EXTRA1: DB 0 ; For future expansion EXTRA2: DB 0 ; For future expansion BRKCHR: DB '@'-40H ; ^@ = send a 300 ms. break tone NOCONN: DB 'N'-40H ; ^N = disconnect from phone line LOGCHR: DB 'L'-40H ; ^L = send logon LSTCHR: DB 'P'-40H ; ^P = toggle printer UNSVCH: DB 'R'-40H ; ^R = close input text buffer TRNCHR: DB 'T'-40H ; ^T = transmit file to remote SAVCHR: DB 'Y'-40H ; ^Y = open input text buffer EXTCHR: DB '^'-40H ; ^^ = send next character ; DS 2 ; Not used ; ; Low-level modem I/O routines. ; INCTL1: LD A,10H ; In modem control port OUT (EXTCT1),A IN A,(EXTCT1) RET INCEND: DS 10-[INCEND-INCTL1] ; OTDATA: OUT (EXTDAT),A ; Out modem data port RET OTDEND: DS 10-[OTDEND-OTDATA] ; INPORT: IN A,(EXTDAT) ; In modem data port RET INPEND: DS 10-[INPEND-INPORT] ; ; Bit-test routines. ; MASKR: AND MDRCVB RET ; Bit to test for receive ready TESTR: CP MDRCVR RET ; Value of receive bit when ready MASKS: AND MDSNDB RET ; Bit to test for send ready TESTS: CP MDSNDR RET ; Value of send bit when ready ; DS 12 ; LOGON: DS 2 ; Needed for MDM compat, not ref'd by MEX DIALV: JP DIAL DISCV: JP DISCON GOODBV: JP GOODBYE ; Called before exit to CP/M INMODV: JP NITMOD ; Initialization. called at cold-start NEWBDV: JP PBAUD ; Set baud rate NOPARV: RET NOP NOP ; Set modem for no-parity PARITV: RET NOP NOP ; Set modem parity SETUPV: JP SETCMD ; Set cmd: jump to a ret if you don't write SET SPMENV: RET NOP NOP ; Not used with MEX VERSNV: JP SYSVER ; Overlay's voice in the sign-on message BREAKV: JP SBREAK ; Send a break ; ; MDM calls supported in MEX 1.0 but not recommended for use. ; ILPRTV: DS 3 ; Replace with MEX function 9 INBUFV: DS 3 ; Replace with MEX function 10 ILCMPV: DS 3 ; Replace with table lookup funct. 247 INMDMV: DS 3 ; Replace with MEX function 255 NXSCRV: DS 3 ; Not supported by MEX (returns w/no action) TIMERV: DS 3 ; Replace with MEX function 254 ; CLREOS: LD DE,EOSMSG LD C,PRINT CALL MEX RET ; CLS: LD DE,CLSMSG LD C,PRINT CALL MEX RET ;------------------------------------------------------------ ; ; end of fixed area ; ;------------------------------------------------------------ ; ; Print out the overlay version ; SYSVER: CALL MILP DB 'ON! Overlay Version SM ' DB REV/10+'0' DB '.' DB REV MOD 10+'0' DB CR,LF,LF DB 0 RET ; ; Break, disconnect and goodbye routines ; SBREAK: LD A,5 OUT (EXTCT1),A LD A,(REG5) OR 9AH ; Send a break OUT (EXTCT1),A LD B,3 ; Delay 300 ms. CALL MTIME LD A,5 OUT (EXTCT1),A LD A,(REG5) OUT (EXTCT1),A ; Stop break RET ; ; Disconnect Routine ; DISCON: LD A,(MODMTYP) OR A JR Z,DISCONH ; ; Disconnect Anchor Modem. ; Anchor does not respond to DTR so the only way to disconnect is through ; standard Smartmodem disconnect commands ; DISCONA:LD B,20 CALL MTIME ; Wait 2 seconds LD HL,SMATN ; Send '+++' CALL SMSEND LD B,40 ; Wait 4 more seconds (Anchor is slow) CALL MTIME LD HL,SMDISC ; Send 'ATH' CALL SMSEND LD B,10 ; Wait 1 second CALL MTIME RET ; ; Disconnect Hayes, etc. ; DISCONH:LD A,5 OUT (EXTCT1),A ; Send to the status port LD A,68H ; Turn off DTR/RTS OUT (EXTCT1),A LD B,10 ; Delay 1 sec. CALL MTIME LD A,5 OUT (EXTCT1),A LD A,0EAH ; Turn 'em back on again OUT (EXTCT1),A GOODBYE:RET ; ; GOODBYE routines are called by MEX prior to exit to CP/M ; (re-use DISCONH's RET to save space) ;GOODBYE:RET ; NOTE: EXIT TO CP/M with no change to ; connect status or settings (parity, etc) ; ; Initialize RS-232 port, Smartmodem, and default modes. ; NITMOD: CALL NITSIO ; Don't assume initialized dart chip! CALL INCTL1 ; See if modem is connected, i.e., returning AND 08H ; To active modem from CPM RET NZ ; Skip if connected LD A,(MSPEED) ; Get default baud rate CALL PBAUD ; Set it LD A,(MONFLG) ; Get monitor default OR A LD A,'0' ; Speaker off JR Z,NITMOD4 INC A ; Speaker on (A='1') NITMOD4:LD (SMINIT+3),A ; Put it in sminit string LD A,(ANSFLG) ; Get mode default OR A LD A,'0' ; Originate JR Z,NITMOD5 INC A ; Answer (A='1') NITMOD5:LD (SMINIT+8),A ; Put it in sminit string LD HL,SMINIT SINIT: CALL SMSEND ; Send the init string SMTLP1: LD C,INMDM ; Wait for modem response CALL MEX JR NC,SMTLP1 ; Eat everything until silence for RET ; 100 msec ; ; Initialize the Zilog DART chip ; NITSIO: XOR A ; Select reg. 0 OUT (EXTCT1),A LD A,(REG0) ; Command byte OUT (EXTCT1),A LD A,04H ; Select reg. 4 OUT (EXTCT1),A LD A,(REG4) ; Receive/transmit control byte OUT (EXTCT1),A LD A,03H ; Select reg. 3 OUT (EXTCT1),A LD A,(REG3) ; Receiver logic byte OUT (EXTCT1),A LD A,05H ; Select reg. 5 OUT (EXTCT1),A LD A,(REG5) ; Transmitter logic byte OUT (EXTCT1),A RET ; ; Set command processor ; SETCMD: LD C,SBLANK ; Any arguments? CALL MEX JP C,SETSHO ; If not, display default(s) LD DE,CMDTBL LD C,LOOKUP CALL MEX ; Parse the argument PUSH HL ; Save any parsed arguments on stack RET NC ; If we have one, return to it POP HL ; Oops, input not found in table SETERR: LD DE,SETEMS LD C,PRINT CALL MEX JP CRLF ; Jp = call!ret ; RET SETEMS: DB CR,LF,'SET command error',CR,LF,'$' ; ; Argument table ; CMDTBL: DB '?'+80H ; Help DW SETHELP DB 'ORI','G'+80H ; Originate mode DW ORIG DB 'ANSWE','R'+80H ; Answer mode DW ANS DB 'TON','E'+80H ; Tone dialing DW STTONE DB 'PULS','E'+80H ; Pulse dialing DW STPULSE DB 'MONITO','R'+80H ; Monitor on DW MONIT DB 'QUIE','T'+80H ; Monitor off DW QUIET DB 'BAU','D'+80H ; Set baud DW STBAUD DB 'DELA','Y'+80H ; Set delay DW DELAY DB 'PARIT','Y'+80H ; Set parity DW STPRTY DB 'STOPBIT','S'+80H ; Set stopbits DW STSTOP DB 'LENGT','H'+80H ; Set length DW STBITS DB 'ANCHO','R'+80H ; Set to Anchor modem DW SETANCH DB 'MANUA','L'+80H ; Set to manual mode DW MANUAL DB 0 ; Table terminator ; ; ; "SET (no args): PRINT CURRENT STATISTICS ; SETSHO: CALL MILP DB CR,LF DB 'SET values:',CR,LF,0 CALL CRLF CALL MDMSHOW CALL CRLF CALL MDSHOW CALL CRLF CALL TPSHOW CALL CRLF CALL BDSHOW CALL CRLF CALL DLSHOW CALL CRLF CALL MONSHO CALL CRLF CALL CRLF CALL SHPRTY CALL CRLF CALL SHSTOP CALL CRLF CALL SHBITS CALL CRLF JP CRLF ; JP = CALL!RET ; ; "SET ?" processor ; SETHELP:CALL MILP DB CR,LF,'SET ANCHOR - Set modem to respond to Anchor commands' DB CR,LF,'SET ORIG - Set modem to Originate mode' DB CR,LF,' (Disable auto-answer mode)' DB CR,LF,'SET ANSWER - Set modem to auto-answer mode' DB CR,LF,'SET TONE - Set modem for Touchtone dialing' DB CR,LF,'SET PULSE - Set modem for Pulse dialing' DB CR,LF,'SET DELAY - seconds to wait for answer' DB CR,LF,'SET PARITY - OFF, EVEN or ODD' DB CR,LF,'SET STOPBITS - 1, 1.5 or 2' DB CR,LF,'SET LENGTH - 5, 6, 7 or 8' DB CR,LF,'SET QUIET - Turn Modem monitor OFF' DB CR,LF,'SET MONITOR - Turn Modem monitor ON' DB CR,LF,'SET BAUD - 300, 1200, 2400, 4800, 9600, 19200' DB CR,LF,'SET MANUAL - ORIG or ANSWER' DB CR,LF,' Manually generate Answer or Originate ' DB 'carrier tone' DB CR,LF,LF,0 RET ; ; SET ANCHOR processor ; SETANCH:LD A,0FFH LD (MODMTYP),A LD A,041H LD (DIALAB),A XOR A LD (MONFLG),A MDMSHOW:LD A,(MODMTYP) OR A JR Z,MDMSHOH CALL MILP DB 'Anchor Modem',0 RET MDMSHOH:CALL MILP DB 'Hayes-compatible Smartmodem',0 RET ; ; Set manual processor ; Note: manual mode does not change the auto-answer status of the modem ; MANUAL: LD C,SBLANK ; Check for orig answer CALL MEX ; JP C,SETERR ; If none, print error LD DE,MANTBL ; Check for proper syntax LD C,LOOKUP CALL MEX PUSH HL ; Match found, go do it! RET NC ; POP HL ; No match: fix stack and JP SETERR ; Print error ; MANORIG:LD B,30 ; Force 3 second delay on originate end CALL MTIME LD HL,SMATD ; Send out 'ATD' CALL SINIT CALL MILP DB CR,LF,'Manual originate mode,',CR,LF DB 'Awaiting answer tone.' DB CR,LF,LF,0 JR GOMAN MANANS: LD HL,SMATA ; Send out 'ATD' CALL SINIT CALL MILP DB CR,LF,'Manual answer mode, carrier tone sent',CR,LF,LF,0 JR GOMAN ; SMATD: DB 'ATD',CR,0 SMATA: DB 'ATA',CR,0 ; GOMAN: LD B,20 CALL MTIME CALL MILP DB 'Enter Terminal Mode at the next command prompt',CR,LF DB 'to check status of the connection',CR,LF,LF DB 'To return to voice mode,',CR,LF DB 'disconnect from terminal mode ,',CR,LF DB 'or from the command line ',CR,LF,LF,0 RET ; ; Manual originate / answer command table ; MANTBL: DB 'ORI','G'+80H ; Manual originate mode DW MANORIG DB 'ANSWE','R'+80H ; Manual answer mode DW MANANS DB 0 ; ; "SET BAUD" processor ; STBAUD: LD C,BDPARS ; Function code: parse a baudrate CALL MEX ; Let MEX look up code JP C,SETERR ; Jump if invalid code CALL PBAUD ; No, try to set it JP C,SETERR ; If not one of ours, bomb out BDSHOW: LD A,(MSPEED) ; Get current baud rate LD C,PRBAUD ; Let MEX print it JP MEX ; RET ; ; This routine sets baud rate passed as MSPEED code in A. ; Returns CY=1 if baud rate not supported. ; ; ; PBAUD: PUSH HL PUSH DE PUSH BC OR A JR Z,NO$BAUD ; No speed selected CP 10 JR NC,NO$BAUD ; Out of range LD B,A ; ; Speed value in range, set it up ; LD DE,BD300 DEC A JR Z,SETBAUD ; Set 300 bps DEC A JR Z,NO$BAUD ; Skip 450 bps DEC A JR Z,NO$BAUD ; Skip 600 bps DEC A JR Z,NO$BAUD ; Skip 710 bps LD DE,BD1200 DEC A JR Z,SETBAUD ; Set 1200 bps LD DE,BD2400 DEC A JR Z,SETBAUD ; Set 2400 bps LD DE,BD4800 DEC A JR Z,SETBAUD ; Set 4800 bps LD DE,BD9600 DEC A JR Z,SETBAUD ; Set 9600 bps LD DE,BD19200 DEC A JR Z,SETBAUD ; Set 19200 bps NO$BAUD: SCF JR ERR$RET ; ; Set up the baud rate requested ; SETBAUD: CALL SELBNK ; A=0 returns system port data AND 0CFH ; Mask rate generator xx00xxxxb OR E ; Selected rate PUSH BC LD C,A ; Return it in c CALL SELBNK ; A<=>0 sets new rate POP BC LD A,4 OUT (EXTCT1),A ; Select wr4 LD A,D ; Get dart divisor, 1 stop bit OUT (EXTCT1),A LD A,3 OUT (EXTCT1),A ; Wr3 LD A,0C1H ; 8 bits, rx enable OUT (EXTCT1),A LD A,5 OUT (EXTCT1),A ; Wr5 LD A,0EAH ; Dtr, 8 bits, tx enable, rts OUT (EXTCT1),A LD A,B LD (MSPEED),A OR A ; Clear carry ; ERR$RET: POP BC POP DE POP HL RET ; ; SELBNK routine in the ON bios gets/sets the baud rate clock ; This routine also affects the bank port and the terminal speed. ; Please don't play around with it. ; SELBNK: LD HL,(1) ; Bios jump table LD L,33H ; Offset to selbnk jump JP (HL) ; Do it, return to caller ; ; SET MODEM STATUS TO ENABLE OR DISABLE AUTO-ANSWER ; ; SMO: DB 'ATS0=0',CR,0 SMA: DB 'ATS0=1',CR,0 ADELAY: DS 1 ; ANS: LD A,(ANSFLG) ; Already in auto-answer? OR A JR NZ,NOTORI ; Then no set delay stuff CPL ; A=FFh LD (ANSFLG),A ; Set ans flag LD A,(NDELAY) ; Save originate mode's delay LD (ADELAY),A LD A,12 ; 12 seconds seems about right CALL IDELAY ; Set delay 12 NOTORI: LD HL,SMA ; Send out ATS0=1 CALL SINIT CALL MDSHOW ; Display mode ANSLOO: CALL RESULT ; Poll modem OR A ; Connect? RET Z ; Then just return to MEX CP 3 ; Control-C abort? JR NZ,ANSLOO ; If not, loop CALL DISCON ; Otherwise, hang up ; fall through ORIG: LD A,(ANSFLG) ; Already in originate mode? OR A JR Z,NOTANS ; Then no set delay stuff LD A,(ADELAY) CALL IDELAY XOR A LD (ANSFLG),A ; Set orig flag NOTANS: LD HL,SMO ; Send out ATS0=0 CALL SINIT CALL CRLF ; fall through MDSHOW: LD A,(ANSFLG) OR A JR Z,MDORIG CALL MILP DB CR,LF,'Auto-answer mode, ^C aborts',CR,LF,0 RET MDORIG: CALL MILP DB 'Originate mode, auto-answer off',CR,LF,0 RET ; ; ; Monitor control processor ; QUIET: XOR A LD (MONFLG),A LD HL,SMQT CALL SINIT JR MONSHO ; MONIT: LD A,0FFH LD (MONFLG),A LD HL,SMMON CALL SINIT ; MONSHO: CALL MILP DB 'Monitor Speaker O',0 LD A,(MONFLG) OR A JR Z,MONOFF CALL MILP DB 'N',0 RET ; MONOFF: CALL MILP DB 'FF',0 RET ; SMQT: DB 'ATM0',CR,0 SMMON: DB 'ATM1',CR,0 ; ; Set dial processor ; STTONE: LD B,'T' JR SDIAL1 ; STPULSE:LD B,'P' ; SDIAL1: LD A,(TPULSE) CP B JR Z,TPSHOW LD A,B LD (TPULSE),A CP 'P' LD A,01010000B ; Pulse dial JR Z,SDIAL2 LD A,01000000B ; Tone dial ; SDIAL2: LD (DIALWD),A ; TPSHOW: LD A,(DIALWD) AND 00010000B JR Z,TPTONE CALL MILP DB 'Pulse Dialing',0 RET TPTONE: CALL MILP DB 'Touchtone Dialing',0 RET ; ; Set delay processor ; DELAY: LD C,EVALA CALL MEX LD A,H OR A JP NZ,SETERR LD A,L IDELAY: LD (NDELAY),A DLSHOW: CALL MILP DB 'Answer Delay is ',0 LD A,(NDELAY) LD L,A LD H,0 LD C,DECOUT CALL MEX CALL MILP DB ' seconds',0 RET ; ; SET PARITY command: reset transmit/receive parity ; ; Parity is controlled by bits 0 and 1 of ; the byte sent to the SIO write-register ; 4 as follows: ; ; Parity Bit 1 Bit 0 ; Off - 0 ; Odd 0 1 ; Even 1 1 ; STPRTY: LD C,SBLANK ; Check for parity code CALL MEX ; JP C,SETERR ; If none, print error LD DE,PARTBL ; Check for proper syntax LD C,LOOKUP CALL MEX PUSH HL ; Match found, go do it! RET NC ; POP HL ; No match: fix stack and JP SETERR ; Print error ; PROFF: LD A,(REG4) ; Get register 4 byte AND 0FEH ; Reset bit 0 JR PARTB1 ; PREVEN: LD A,(REG4) ; OR 003H ; Set bits 0 & 1 JR PARTB1 ; PRODD: LD A,(REG4) ; OR 001H ; Set bit 0 AND 0FDH ; Reset bit 1 PARTB1: LD (REG4),A ; CALL NITSIO ; Re-initialize the usart ; FALL THRU ; To SHPRTY ; CALL SHPRTY ; Print the result ; RET ; SHPRTY: CALL MILP ; Display parity DB 'Parity: ',TAB,' ',0 LD A,(REG4) ; AND 001H ; Test bit 0 OR A ; If bit0=0 then parity off JR NZ,SHPRT1 ; CALL MILP ; DB 'Off',0 ; RET SHPRT1: LD A,(REG4) ; AND 002H ; Test bit 1 OR A ; If bit1=0 then parity odd JR NZ,SHPRT2 ; CALL MILP ; DB 'Odd',0 ; RET ; SHPRT2: CALL MILP ; DB 'Even',0 ; RET ; ; SET PARITY command table ; PARTBL: DB 'OF','F'+80H ; "set parity off" DW PROFF DB 'EVE','N'+80H ; "set parity even" DW PREVEN DB 'OD','D'+80H ; "set parity odd" DW PRODD DB 0 ; <<== end of parity table ; ; SET STOPBITS command: reset number of stop bits ; ; The number of stop bits is controlled by bits ; 2 and 3 of the byte sent to the SIO write- ; register 4, as follows: ; ; Stop bits Bit 3 Bit 2 ; 1 0 1 ; 1.5 1 0 ; 2 1 1 ; ; STSTOP: LD C,SBLANK ; Check for stop bits CALL MEX ; JP C,SETERR ; If none, print error LD DE,STPTBL ; Check for proper syntax LD C,LOOKUP CALL MEX ; PUSH HL ; Match found, go do it! RET NC ; POP HL ; No match: fix stack and JP SETERR ; Print error ; STOP01: LD A,(REG4) ; Get register 4 byte AND 0F7H ; Reset bit 3 OR 004H ; Set bit 2 JR STSTP1 ; STOP02: LD A,(REG4) ; OR 00CH ; Set bits 2 and 3 JR STSTP1 ; STOP15: LD A,(REG4) ; OR 008H ; Set bit 3 AND 0FBH ; Reset bit 2 STSTP1: LD (REG4),A ; CALL NITSIO ; ; FALL THRU ; To SHSTOP ; CALL SHSTOP ; Print the result ; RET ; SHSTOP: CALL MILP ; Display stop-bits DB 'Stop bits:',TAB,' ',0 LD A,(REG4) ; AND 004H ; Test bit 2 OR A ; If bit2=0 then 1.5 JR NZ,SHSTP1 ; CALL MILP ; DB '1.5',0 ; RET SHSTP1: LD A,(REG4) ; AND 008H ; Test bit 3 OR A ; If bit3=0 then 1 JR NZ,SHSTP2 ; CALL MILP ; DB '1',0 ; RET SHSTP2: CALL MILP ; DB '2',0 ; RET ; ; SET STOPBITS command table ; STPTBL: DB '1'+80H ; "set stop 1" DW STOP01 DB '2'+80H ; "set stop 2" DW STOP02 DB '1.','5'+80H ; "set stop 1.5" DW STOP15 DB 0 ; <<== end of stop-bits table ; ; SET LENGTH command: set bits per character ; ; The number of bits per character is controlled for ; the receiver circuit by bits 6 and 7 of the byte ; sent to the SIO write-register 3 and for the trans- ; mitter circuit by bits 5 and 6 of the byte sent to ; the SIO write-register 5. The assumption has been ; made here that both transmission and reception will ; be carried on at the same number of bits per charac- ; ter. The bit configurations are shown for register ; 3 only, but are the same for register 5: ; ; BPC Bit 7 Bit 6 ; 5 0 0 ; 6 1 0 ; 7 0 1 ; 8 1 1 ; STBITS: LD C,SBLANK ; Check for bits/char CALL MEX ; JP C,SETERR ; If none, print error LD DE,BITTBL ; Check for proper syntax LD C,LOOKUP CALL MEX PUSH HL ; Match found, go do it! RET NC ; POP HL ; No match: fix stack and JP SETERR ; Print error ; BIT5: LD A,(REG3) ; AND 0BFH ; Reset bit 6 AND 07FH ; Reset bit 7 LD (REG3),A ; LD A,(REG5) ; AND 0DFH ; Reset bit 5 AND 0BFH ; Reset bit 6 JR STBTS1 ; BIT6: LD A,(REG3) ; AND 0BFH ; Reset bit 6 OR 080H ; Set bit 7 LD (REG3),A ; LD A,(REG5) ; AND 0DFH ; Reset bit 5 OR 040H ; Set bit 6 JR STBTS1 ; BIT7: LD A,(REG3) ; OR 040H ; Set bit 6 AND 07FH ; Reset bit 7 LD (REG3),A ; LD A,(REG5) ; OR 020H ; Set bit 5 AND 0BFH ; Reset bit 6 JR STBTS1 ; BIT8: LD A,(REG3) ; OR 040H ; Set bit 6 OR 080H ; Set bit 7 LD (REG3),A ; LD A,(REG5) ; OR 020H ; Set bit 5 OR 040H ; Set bit 6 STBTS1: LD (REG5),A ; CALL NITSIO ; ; FALL THRU ; To SHBITS SHBITS: CALL MILP ; Display bits/char DB 'Bits/char:',TAB,' ',0 LD A,(REG5) ; AND 040H ; Test bit 6 OR A ; If bit6=0 then 6 bpc JR NZ,SHBTS2 ; LD A,(REG5) ; AND 020H ; Test bit 5 OR A ; If bit5=0 then 5 bpc JR NZ,SHBTS1 ; CALL MILP ; DB '5',0 ; RET ; SHBTS1: CALL MILP ; DB '7',0 ; RET ; SHBTS2: LD A,(REG5) ; AND 020H ; Test bit 5 OR A ; If bit5=0 then 6 bpc JR NZ,SHBTS3 ; CALL MILP ; DB '6',0 ; RET ; SHBTS3: CALL MILP ; DB '8',0 ; RET ; ; SET LENGTH command table ; BITTBL: DB '5'+80H ; "set bits 5" DW BIT5 DB '6'+80H ; "set bits 6" DW BIT6 DB '7'+80H ; "set bits 7" DW BIT7 DB '8'+80H ; "set bits 8" DW BIT8 DB 0 ; <<== end of bpc table ; ; Smartmodem dialing routine from Ron Fowler's MXO-SM10.ASM ; DIAL: LD HL,(DIALPT) ; Fetch pointer CP 254 ; Start dial? JR Z,STDIAL ; Jump if so CP 255 ; End dial? JR Z,ENDIAL ; Jump if so ; ; Not start or end sequence, must be a digit to be sent to the modem ; LD (HL),A ; Put char in buffer INC HL ; Advance pointer LD (DIALPT),HL ; Stuff pntr RET ; All done ; ; Here on a start-dial sequence ; STDIAL: LD HL,DIALBF ; Set up buffer pointer LD (DIALPT),HL RET ; ; Here on an end-dial sequence ; ENDIAL: ; IF SILENT LD A,(MONFLG) ; Check monitor speaker flag OR A ; To see if on or off JR Z,LEAVOFF ; If off, leave it off LD (HL),'M' ; If we silenced speaker to dial, INC HL ; Turn it on again LD (HL),'1' INC HL LEAVOFF: ENDIF ; LD (HL),CR ; Stuff end-of-line into buffer INC HL ; Followed by terminator LD (HL),0 LD A,(TPULSE) ; Get overlay's touch-tone flag ; IF SILENT LD (SMDIAL+5),A ENDIF ; IF NOT SILENT LD (SMDIAL+3),A ; Put into string ENDIF ; LD HL,SMDIAL ; Point to dialing string CALL SMSEND ; Send it ; WAITSM: LD C,INMDM CALL MEX ; Catch any output from the modem JR NC,WAITSM ; Loop until no more characters ; ; THE FOLLOWING LOOP WAITS FOR A RESULT FROM THE MODEM. ; RESULT: LD A,(NDELAY) ; Get delay count LD C,A SMWLP: PUSH BC LD B,1 ; Check for a char, up to 1 sec wait LD C,TMDINP ; Do timed input CALL MEX POP BC JR NC,SMTEST ; Jump if modem had a char PUSH BC ; No, test for control-c from console LD C,DCONIO LD E,DCONIN ; Use BDOS direct console input function CALL BDOS POP BC CP 'C'-40H ; ^C? JR NZ,SMNEXT ; If not, jump LD A,(DIALAB) ; Quit dialing LD B,A LD C,SNDCHR CALL MEX CALL INCTL1 ; See if modem is connected, i.e., returning AND 08H ; To active modem from CPM CALL Z,SMDMOFF ; No carrier, so shut down modem LD A,3 ; Return abort code RET SMNEXT: OR A ; Any other key JR NZ,SMTIMO ; Yes, treat like timeout DEC C ; No JR NZ,SMWLP ; Continue ; ; NO MODEM RESPONSE WITHIN THE TIME SPECIFIED IN SET DELAY COMMAND ; SMTIMO: LD A,(DIALAB) LD B,A LD C,SNDCHR CALL MEX CALL INCTL1 ; See if modem is connected, i.e., returning AND 08H ; To active modem from CPM CALL Z,SMDMOFF ; Shut down modem if we're not on pc pursuit LD A,2 ; Return timeout code RET ; ; MODEM GAVE US A RESULT, CHECK IT ; SMTEST: AND 7FH ; Ignore any parity CALL SMANAL ; Test the result JR C,RESULT ; Go try again if unknown response LD A,B ; A=result PUSH AF ; Save it SMTLP: LD C,INMDM ; Eat any additional chars from smartmodem CALL MEX JR NC,SMTLP ; Until 100ms of quiet time POP AF ; Return the code RET ; ; Analyze character returned from External Modem ; SMANAL: PUSH AF LD A,(MODMTYP) OR A JR Z,SMANALH ; ; Analyze Modem response codes for Anchor modems. ; Anchor echoes the digits as they are being dialed. The returned digits ; are interpreted as call return codes, shutting down the modem too early. ; SMANALA:POP AF LD B,0 ; Prep connect code CP 'C' ; "connect"? RET Z INC B ; Prep busy code B=1 CP 'B' RET Z INC B ; Prep no connect msg B=2 CP 'N' ; N=no connect RET Z LD B,4 ; Prep modem error CP 'E' ; E=error RET Z JR WTLF ; ; Analyze Modem response codes for Hayes, etc. ; SMANALH:POP AF LD B,0 ; Prep connect code CP 'C' ; "connect"? RET Z CP '1' ; Numeric version of "CONNECT" RET Z CP '5' ; Numeric version of "CONNECT 1200" RET Z INC B ; Prep busy code B=1 CP 'B' JR NZ,NOBUSY ; Not busy, check for no answer PUSH BC ; Otherwise, save return code LD B,5 ; Wait 1/2 second CALL MTIME LD A,(DIALAB) ; Abort possible firmware re-dial LD B,A LD C,SNDCHR CALL MEX POP BC ; Get back return code XOR A ; Clear carry, return RET NOBUSY: INC B ; Prep no connect msg B=2 CP 'N' ; N=no connect RET Z CP '3' ; Numeric version of "NO CONNECT" RET Z LD B,4 ; Prep modem error CP 'E' ; E=error RET Z CP '4' ; Numeric version of "ERROR" RET Z ; ; UNKNOWN RESPONSE, RETURN CARRY TO CALLER. BUT FIRST, ; FLUSH THE UNKNOWN RESPONSE LINE FROM THE MODEM. ; WTLF: CP LF ; Linefeed? SCF RET Z ; End if so LD C,INMDM ; No. get next char CALL MEX JR NC,WTLF ; Unless busy, loop RET ; ; Send string to the External Modem ; SMSEND: LD C,SNDRDY ; Wait for modem ready CALL MEX JR NZ,SMSEND LD A,(HL) ; Fetch next character INC HL OR A ; End? RET Z ; Done if so LD B,A ; No, position for sending LD C,SNDCHR ; Nope, send the character CALL MEX JR SMSEND ; ; Shut down (disconnect) External Modem ; SMDMOFF:LD B,20 ; Two second wait to settle down CALL MTIME LD A,(MODMTYP) ; Test modem type OR A CALL Z,DISCON ; If Hayes type, do DTR disconnect RET ; If Anchor, just return ; ; General utility routines ; CRLF: CALL MILP ; Print carriage return, line feed DB CR,LF,0 RET ; MILP: LD C,ILP ; In-line print JP MEX ; MTIME: LD C,TIMER ; MEX timer JP MEX ; ; ;========================================================================== ; Data Area ;========================================================================== ; ; Default UART parameters (Initalized for External RS-232) ; REG0: DB 00011000B ; Reset channel A REG3: DB 11000001B ; Enable receive at 8 bits/char REG4: DB 01000100B ; No parity, 1 stop bit, clock x16 REG5: DB 11101010B ; Enable transmit at 8 bits/char ; ; Miscellaneous Default Data ; SMDIAL: DB 'AT' ; IF SILENT DB 'M0' ; Turn off speaker during dialing ENDIF ; DB 'DT' ; Smartmodem dial prefix ; DIALBF: DS 52 ; 2* 24 char max, + cr + null + slop DIALPT: DS 2 ; Dial position pointer DIALWD: DB 01000000B ; Pulse/tone dial word DIGIT: DB 0 ; Save dialed digit MSPDSV: DB 0 ; Save external modem mspeed MONFLG: DB 0FFH ; 0: monitor off - 0ffh: monitor on ANSFLG: DB 0 ; 0: originate - 0ffh: answer NDELAY: DB 30 ; No. seconds for answer MODMTYP:DB 0 ; 0=Hayes, etc., - 0ffh=Anchor modem DIALAB: DB CR ; Character to use to abort dial sequence ; SMATN: DB '+++',0 ; Smartmodem online 'attention' SMDISC: DB 'ATH',CR,0 ; Smartmodem disconnect (used by Anchor) SMINIT: DB 'ATM1 S0=0 S7=60 Q0 X1',CR,0 ; Modem init string ; EOSMSG: DB 1BH,'Y$' ; Clear to end-of-screen CLSMSG: DB 1BH,'+$' ; Clear whole screen END