Title 'MEX overlay for the U.S. Robotics 212A version 1.0'
;
; 06/17/85 by Gary MacKay Converted MXM-US13.ASM to MXM-USR2.ASM
; for use with the U.S. Robotics 212A. Also cleaned up
; the fancy video rtns to work better on my TVI925 term.
; 08/30/84 added parity routines
; 08/29/84 added fancy video conditionals
; 08/27/84 by Don Wilke
;
REV EQU 10 ; Overlay revision level
;
; Misc equates
;
NO EQU 0
YES EQU 0FFH
BELL EQU 07H ; Bell
TAB EQU 09H ; Tab
LF EQU 0AH ; Line feed
CR EQU 0DH ; Carriage return
ESC EQU 1BH ; Escape
TPA EQU 100H ; Transient prog area
MEX EQU 0D00H ; Address of the service processor
ATTRIB EQU YES ; Yes if fancy video supported
;
; USR port equates
;
PORT EQU 060H ; Base I/O address for my 8251 DART card
MODCT1 EQU 064H ; 8251 control port
MODDAT EQU 063H ; 8251 data port
MDDCDB EQU 10000000B ; Carrier detect bit
MDDCDA EQU 10000000B ; Value when active
MDRCVB EQU 00000010B ; Bit to test for receive
MDRCVR EQU 00000010B ; Value when ready
MDSNDB EQU 00000001B ; Bit to test for send
MDSNDR EQU 00000001B ; Value when ready
MMODEA EQU 01001110B ; 8 bits, clock/16, 1 stop bit
MMODEB EQU 11001111B ; 8 bits, clock/64, 2 stop bits
MMCMDA EQU 00110111B ; RTS hi, error reset, DTR hi, enable TX/RX
MMCMDB EQU 00010111B ; Error reset, DTR hi, enable TX/RX
MRESET EQU 01000000B ; 8251 reset
;
; Following are function codes for the MEX service call 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
ORG TPA ; We begin
;
DS 3 ; MEX has a JMP START here
;
; The following variables are located at the beginning of the program
; to facilitate modification without the need of re-assembly. They will
; be moved in MEX 2.0.
;
PMODEM: DB NO ; Yes=PMMI modem \ / These 2 locations are not
SMODEM: DB YES ; Yes=Smartmodem / \ referenced by MEX
TPULSE: DB 'T' ; T=touch,P=pulse (not referenced by MEX)
CLOCK: DB 40 ; 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 NO ; 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 YES ; 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 YES ; 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
;
; Equates used only by PMMI routines grouped together here.
;
PRATE: DB 250 ; 125=20pps dialing, 250=10pps
DB 0 ; Not used
;
; Low-level modem I/O routines: this will be replaced with
; a jump table in MEX 2.0 (you can insert jumps here to longer
; routines if you'd like ... I'd recommend NOT putting part of
; a routine in this area,then jumping to the rest of the routine
; in the non-fixed area; that will complicate the 2.0 conversion)
;
INCTL1: IN MODCT1 ; In modem control port
RET
DB 0,0,0,0,0,0,0 ; Spares if needed for non-PMMI
;
OTDATA: OUT MODDAT ; Out modem data port
RET
DB 0,0,0,0,0,0,0 ; Spares if needed for non=PMMI
;
INPORT: IN MODDAT ; In modem data port
RET
DB 0,0,0,0,0,0,0 ; Spares if needed for non-PMMI
;
; Bit-test routines. These will be merged with the above
; routines in MEX 2.0 to provide a more reasonable format
;
MASKR: ANI MDRCVB ! RET ; Bit to test for receive ready
TESTR: CPI MDRCVR ! RET ; Value of receive bit when ready
MASKS: ANI MDSNDB ! RET ; Bit to test for send ready
TESTS: CPI MDSNDR ! RET ; Value of send bit when ready
;
;
; Unused area: was once used for special PMMI functions,
; Now used only to retain compatibility with MDM overlays.
; You may use this area for any miscellaneous storage you'd
; like but the length of the area *must* be 12 bytes.
;
DS 12
;
; Special modem function jump table: if your overlay cannot handle
; some of these, change the jump to "DS 3", so the code present in
; MEX will be retained. Thus, if your modem can't dial, change the
; JMP PDIAL at DIALV to DS 3, and MEX will print a "not-implemented"
; diagnostic for any commands that require dialing.
;
; DIALV dials the digit in A. See the comments at PDIAL for specs.
;
; DISCV disconnects the modem
;
; GOODBV is called just before MEX exits to CP/M. If your overlay
; requires some exit cleanup, do it here.
;
; INMODV is called when MEX starts up; use INMODV to initialize the modem.
;
; NEWBDV is used for phone-number baud rates and is called with a baud-rate
; code in the A register, value as follows:
;
; A=0: 110 baud A=1: 300 baud A=2: 450 baud
; A=3: 600 baud A=4: 710 baud A=5: 1200 baud
; A=6: 2400 baud A=7: 4800 baud A=8: 19200 baud
;
; If your overlay supports the passed baud rate,it should store the
; value passed in A at MSPEED (107H), and set the requested rate. If
; the value passed is not supported, you should simply return (with-
; out modifying MSPEED) -or- optionally request a baud-rate from the
; user interactively.
;
; NOPARV is called at the end of each file transfer; your overlay may simply
; return here, or you may want to restore parity if you set no-parity
; in the following vector (this is the case with the PMMI overlay).
;
; PARITV is called at the start of each file transfer; your overlay may simply
; return here, or you may want to enable parity detection (this is the
; case with the PMMI overlay).
;
; SETUPV is the user-defined command ... to use this routine to build your own
; MEX command, set the variable SETFL (117H) non-zero,and add your SET
; code. You can use the routine presented in the PMMI overlay as a
; guide for parsing, table lookup, etc.
;
; SPMENU is provided only for MDM compatibility, and is not used by MEX 1.0
; for any purpose (it will be gone in MEX 2).
;
; VERSNV is called immediately after MEX prints its sign-on message at cold
; startup -- use this to identify your overlay in the sign-on message
; (include overlay version number in the line).
;
; BREAKV is provided for sending a BREAK (<ESC>-B in terminal mode). If your
; modem doesn't support BREAK, or you don't care to code a BREAK rou-
; tine, you may simply execute a RET instruction.
;
LOGON: DS 2 ; Needed for MDM compat, not ref'd by MEX
DIALV: DS 3 ; Dial digit in A
DISCV: DS 3 ; Disconnect the modem
GOODBV: JMP GOODBYE ; Called before exit to CP/M
INMODV: JMP NITMOD ; Initialization. Called at cold-start
NEWBDV: JMP PBAUD ; Set baud rate
NOPARV: RET ! NOP ! NOP ; Set modem for no-parity
PARITV: RET ! NOP ! NOP ; Set modem parity
SETUPV: JMP SETCMD ; SET cmd
SPMENV: RET ! NOP ! NOP ; Not used with MEX
VERSNV: JMP SYSVER ; Overlay's voice in the sign-on message
BREAKV: JMP PBREAK ; Send a break
;
; The following jump vector provides the overlay with access to special
; routines in the main program (retained and supported in the main pro-
; gram for MDM overlay compatibility). These should not be modified by
; the overlay.
;
; Note that for MEX 2.0 compatibility, you should not try to use these
; routines, since this table will go away with MEX 2.0 (use the MEX
; service call processor instead).
;
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
;
; Routine to clear to end of screen. If using CLREOS and CLRSCRN, set
; SCRNTEST to YES at 010AH (above). Each routine must use the
; full 9 bytes alloted (may be padded with nulls).
;
; These routines (and other screen routines that MEX 2.0 will sup-
; port) will be accessed through a jump table in 2.0, and will be
; located in an area that won't tie the screen functions to the
; modem overlay (as the MDM format does).
;
CLREOS: LXI D,EOSMSG ; Point to clear to EOS msg
MVI C,PRINT ; MEX print string funct #
CALL MEX ; Let MEX do it
RET
;
CLS: LXI D,CLSMSG ; Point to clear screen msg
MVI C,PRINT ; MEX print string funct #
CALL MEX ; Let MEX do it
RET
;
; The following routine sends a break "character" to the remote computer
; for 300 ms. The "MSPEED" value is needed to decide whether the modem
; is at 300, 600, or 1200 baud. The routine must know this because U.S.R.
; sets up the RTS bit of the command register as a baud rate selection bit,
; and this routine must be careful not to change it, or the user will end up
; at a different baud rate after the break "character" is sent. Note that
; the "MVI A,01FH" does not change any flags.
;
PBREAK: LDA MSPEED ; Get speed byte
CPI 3 ; Are we at 600 baud?
MVI A,01FH ; Set up for 600 (no flag changes)
JZ PBRK2 ; And if we are, go do that
MVI A,03FH ; Otherwise,set up for 300/1200
PBRK2: OUT MODCT1 ; Send break
PUSH PSW ; Save value
MVI B,3 ; 300 ms delay value
MVI C,TIMER ; MEX service function #254
CALL MEX ; Wait that long
POP PSW ; Restore command byte
ANI 0F7H ; Turn off break bit
OUT MODCT1 ; Send command byte to UART
RET
;
; The U.S.R. 212A does not have a "quick-disconnect" feature like
; the Hayes does (by lowering DTR). Therefore, "GOODBYE" is not
; implemented. Yet control-N still works to hang up (see note
; above in introduction)
;
GOODBYE:
LXI D,DISC1 ; Point to disconnect message
CALL PMSG ; Send it
MVI B,15 ; Wait 1.5 sec
MVI C,TIMER ; MEX service function #254
CALL MEX ; Wait for USR212A to wake up
LXI D,DISC2 ; Point to rest of disconnect message
CALL PMSG ; Send it too
MVI B,15 ; Wait 1.5 sec
MVI C,TIMER ; MEX service function #254
CALL MEX ; Wait for USR212A to wake up
LXI H,INITBL ; Point to beginning of 8251 chip init table
LXI B,4 ; Only want first 4 commands this time
GBOUT: MOV A,M ; Get character
INX H ; Bump up pointer
OUT MODCT1 ; Send command to port
DCX B ; Counter -1
MOV A,C ; Move C into accum.
ORA B ; Test for zero
JNZ GBOUT ; Nope, keep sending
RET
;
DISC1: DB '+++','$' ; To get modems attention
DISC2: DB 'ATH',CR,'$' ; To hang up modem
;
; * * * * * * * * *
;
; You can use this area for any special initialization or setup you may
; wish to include. Each must stop with a RET. This initialization
; sets up 1200 baud, 8 data bits, 1 stop bit, no parity.
;
NITMOD: DB 3EH ; "MVI,A" OP-CODE
BDCODE: DB 33H ; Default to 1200 baud
OUT PORT ; Send to 8251 buad rate port
LXI H,INITBL ; Point to beginning of 8251 chip init table
LXI B,INITBLL ; Point to length of table
UOUT: MOV A,M ; Get character
INX H ; Bump up pointer
OUT MODCT1 ; Send command to port
DCX B ; Counter -1
MOV A,C ; Move C into accum.
ORA B ; Test for zero
JNZ UOUT ; Nope, keep sending
LXI H,INISTR ; Yep, point to modem init string
LXI B,MDMTBLL ; Get length of table
MDM: MOV A,M ; Get character
INX H ; Bump up pointer
PUSH PSW ; Save command
MDM1: IN MODCT1 ; Get modem status
ANI 085H ; Ready?
CPI 085H ;
JNZ MDM1 ; Nope, wait
POP PSW ; Recall command
OUT MODDAT ; Send command
DCX B ; Decrement counter
MOV A,C ; Move C to accum.
ORA B ; Test for zero
JNZ MDM ; Nope, keep sending
RET ; Yep, return to caller
;
INITBL: DB 0,0,0 ; Three nulls to reset modem
DB 40H ; 8251 UART reset command
MODEBT: DB 4EH ; 8 bits, 1 stop bit, clock/16, no parity
CMDBT: DB 37H ; RTS hi, Error reset, DTR hi, Enable TX/RX
INITBLL EQU $-INITBL ; Length of table
;
;
; Command string sent to modem after I/O initialization
;
INISTR: DB 'AT' ; Get modem's attention
DB 'X1' ; Send extended result codes
SPBYTE: DB 'M1' ; Speaker on 'til connect
WABYTE: DB 'S7=30' ; Wait for 30 seconds for carrier
DB CR,'$' ; End of command string
MDMTBLL EQU $-INISTR ; LENGTH OF STRING TO SEND
;
;....
;
PBAUD: CPI 8 ; 8=9600 baud
JZ OK9600 ; Set to 9600 baud
CPI 7 ; 7=4800
JZ OK4800 ; Set to 4800 baud
CPI 6 ; 6=2400
JZ OK2400 ; Set to 2400 baud
CPI 5 ; 5=1200 baud
JZ OK1200 ; Set to 1200 baud
CPI 1 ; 1=300 baud
JZ OK300 ; Set to 300 baud
; Else set up for 110 baud * sigh!
OK110: CALL WAIT90 ; Set even longer wait for carrier
MVI A,MMODEA ; Get default mode byte
STA MODEBT ; Reinit for 8 bits, 1 stp bit, no parity
MVI B,00H ; Initializer for 110 baud
MVI A,0 ; 110 baud
JMP LOADBD ; Go load it
;
OK300: CALL WAIT60 ; Set longer wait for carrier
MVI A,MMODEA ; Get default mode byte
STA MODEBT ; Reinit for 8 bits, 1 stp bit, no parity
MVI B,22H ; Initializer for 300 baud
MVI A,1 ; 300 baud value
JMP LOADBD ; Go load it
;
OK1200: CALL WAIT30 ; Set short wait for carrier
MVI A,MMODEA ; Get default mode byte
STA MODEBT ; Reinit for 8 bits, 1 stp bit, no parity
MVI B,33H ; Initializer for 1200 baud
MVI A,5 ; 1200 baud value
JMP LOADBD ; Go load it
;
OK2400: CALL WAIT10 ; Set short wait for carrier
MVI A,MMODEA ; Get default mode byte
STA MODEBT ; Reinit for 8 bits, 1 stp bit, no parity
MVI B,55H ; Initializer for 2400 baud
MVI A,6 ; 2400 baud value
JMP LOADBD ; Go load it
;
OK4800: CALL WAIT10 ; Set short wait for carrier
MVI A,MMODEA ; Get default mode byte
STA MODEBT ; Reinit for 8 bits, 1 stp bit, no parity
MVI B,66H ; Initializer for 4800 baud
MVI A,7 ; 4800 baud value
JMP LOADBD ; Go load it
;
OK9600: CALL WAIT10 ; Set short wait for carrier
MVI A,MMODEA ; Get default mode byte
STA MODEBT ; Reinit for 8 bits, 1 stp bit, no parity
MVI B,77H ; Initializer for 9600 baud
MVI A,8 ; 9600 baud value
;
LOADBD: STA MSPEED ; Change baud rate code value
MOV A,B ; Get mode byte value
STA BDCODE ; Change mode byte
CALL NITMOD ; (Re)initialize the modem
LDA SETFLG ; Get setflg
CPI 0FFH ; Is it a 'SET'
JNZ PBPSA ; No, print bps in dial prompt
RET ; Yes, just return
PBPSA:
IF ATTRIB
LXI D,INDVID ; Set video attribute
CALL PMSG ; Issue attribute to term
ENDIF ;ATTRIB
JMP PBPS ; Print bps rate
;.....
;
;WAIT FOR CARRIER 30/60 SECONDS
;
WAIT10: MVI A,'1' ; SET UP FOR REAL SHORT WAIT
JMP SWAIT ; JUMP AROUND
WAIT30: MVI A,'3' ; SET UP FOR SHORT WAIT
JMP SWAIT ; JUMP AROUND
WAIT60: MVI A,'6' ; SET UP FOR LONG WAIT
JMP SWAIT ; JUMP AROUND
WAIT90: MVI A,'9' ; SET UP FOR LONG LONG WAIT
SWAIT: STA WABYTE+3 ; STORE THE WAIT MSB VALUE
MVI A,'0' ; FAKE LSBYTE
STA WABYTE+4 ; STORE THE WAIT LSB VALUE
RET ;
;....
;
; Sign-on message
;
SYSVER: IF ATTRIB ; IF ATTRIB
LXI D,INVID ; Set video attribute
CALL PMSG ; Issue attribute to term
ENDIF ; ENDIF ATTRIB
;
LXI D,SOMESG ; Point to signon message
CALL PMSG ; Print message on term
;
CARRSH: IF ATTRIB ; IF ATTRIB
LXI D,NORVID ; Reset video attribute
CALL PMSG ; Issue attribute to term
ENDIF ; ENDIF ATTRIB
;
CALL CRLF ; Print crlf
;
LXI D,NOMESG ; Tell about carrier
CALL CARRCK ; Check for it
CZ PMSG ; Print the "No" if no carrier
LXI D,CARMSG ; Print "carrier present"
CALL PMSG ; Print message on term
;
IF ATTRIB ; IF ATTRIB
LXI D,NORVID ; Reset video attribute
ENDIF ; ENDIF ATTRIB
;
IF NOT ATTRIB ; IF NOT ATRIB
RET ; Return
ENDIF ; ENDIF NOT ATTRIB
;
PMSG: MVI C,PRINT ; Get print funct #
CALL MEX ; Let MEX do it
RET
;
SOMESG: DB ' U. S. Robotics 212A '
DB ' Autodial Version '
DB REV/10+'0','.'
DB REV MOD 10+'0',' ','$'
;
NOMESG: DB 'No$'
CARMSG: DB ' carrier present '
DB CR,LF,'$'
;
; Strings to clear-to-end-of-screen, and clear-screen
;
EOSMSG: DB ESC,79H,'$' ; ANSI clear EOS
CLSMSG: DB ESC,'+$' ; ANSI clear screen
;
; Strings for setting video attributes
;
UNVID: DB ESC,'G8$' ; ANSI underscore
INDVID: DB ESC,'G4$' ; ANSI inverse
INVID: DB ESC,'G4$' ; ANSI bold, inverse
BLVID: DB ESC,'G6$' ; ANSI bold, inverse, blinking
NORVID: DB ESC,'G0$' ; ANSI return to normal video
;
; Check the USR for carrier-present (Z=no)
;
CARRCK: IN MODCT1 ; Get status byte
ANI MDDCDB
RET
;
; Newline on console
;
CRLF: MVI A,CR
CALL TYPE
MVI A,LF ; Fall into TYPE
;
; Type char in A on console
;
TYPE: PUSH H ; Save 'em
PUSH D
PUSH B
MOV E,A ; Align output character
MVI C,CONOUT ; Print via MEX
CALL MEX
POP B
POP D
POP H
RET
;
; The remainder of this overlay implements a very versatile
; SET command -- if you prefer not to write a SET for your
; modem, you may delete the code from here to the END statement.
;
; Control is passed here after MEX parses a SET command.
;
SETCMD: PUSH PSW ; Save modem speed code
MVI A,0FFH ; Get all ones
STA SETFLG ; Set setflg
POP PSW ; Get modem spd back
MVI C,SBLANK ; Any arguments?
CALL MEX
JC SETSHO ; If not, go print out values
LXI D,CMDTBL ; Parse command
CALL TSRCH ; From table
PUSH H ; Any address on stack
RNC ; If we have one, execute it
POP H ; Nope, fix stack
;
SETERR: CALL CRLF ; Print crlf
LXI D,SPCS2 ; Point to spaces
CALL PMSG ; Print them
;
IF ATTRIB ; IF ATTRIB
LXI D,BLVID ; Set video attribute
CALL PMSG ; Issue attribute to term
ENDIF ; ENDIF ATTRIB
;
LXI D,SETEMS ; Point to error msg
CALL PMSG ; Print message on term
;
IF ATTRIB ; IF ATTRIB
LXI D,NORVID ; Reset video attribute
CALL PMSG ; Issue attribute to term
ENDIF ; ENDIF ATTRIB
;
CALL CRLF ; Print crlf
;
CALL STHELP ; Print help on error
;
MVI A,0 ; Clear acc
STA SETFLG ; Reset setflg
RET
;
SETEMS: DB BELL,' SET COMMAND ERROR $'
;
; SET command table ... note that tables are constructed of command-
; name (terminated by high bit=1) followed by word-data-value returned
; in HL by MEX service processor LOOKUP. Table must be terminated by
; a binary zero.
;
; Note that LOOKUP attempts to find the next item in the input stream
; in the table passed to it in HL ... if found, the table data item is
; returned in HL; if not found, LOOKUP returns carry set.
;
CMDTBL: DB '?'+80H ; "set ?"
DW STHELP
DB 'BAU','D'+80H ; "set baud"
DW STBAUD
DB 'PARIT','Y'+80H ; "set parity"
DW STPAR
DB 'SPK','R'+80H ; "set spkr"
DW STSPKR
DB 'WAI','T'+80H ; "set wait"
DW STWAIT
DB 'DIA','L'+80H ; "set dial"
DW STDIAL
DB 0 ; <<=== table terminator
;
; SET <no-args>: print current statistics
;
SETSHO: CALL CRLF ; Print crlf
CALL CARRSH ; Show carrier present/not present
LXI H,SHOTBL ; Get table of SHOW subroutines
SETSLP: MOV E,M ; Get table address
INX H
MOV D,M
INX H
MOV A,D ; End of table?
ORA E
JZ SETEXT ; Exit if so
PUSH H ; Save table pointer
XCHG ; Adrs to HL
CALL GOHL ; Do it
CALL CRLF ; Print newline
MVI C,CHEKCC ; Check for console abort
CALL MEX
POP H ; It's done
JNZ SETSLP ; Continue if no abort
CALL CRLF ; Abort and send crlf
RET
;
GOHL: PCHL
;
SETEXT: CALL CRLF ; Print crlf
RET ; Return to caller
;
; table of SHOW subroutines
;
SHOTBL: DW BDSHOW
DW PASHOW
DW SPSHOW
DW WASHOW
DW DISHOW
DW 0 ; <<== table terminator
;
; SET ? processor
;
STHELP:
CALL CRLF ; Print message on term
CALL CRLF ; Print message on term
;
LXI D,SPCS1 ; Point to spaces
CALL PMSG ; Print them
;
IF ATTRIB ; IF ATTRIB
LXI D,UNVID ; Set video attribute
CALL PMSG ; Issue attribute to term
ENDIF ; ENDIF ATTRIB
;
LXI D,HLPHDR ; Point to HELP header
CALL PMSG ; Print message on term
;
IF ATTRIB ; IF ATTRIB
LXI D,NORVID ; Reset video attribute
CALL PMSG ; Issue attribute to term
ENDIF ; ENDIF ATTRIB
;
CALL CRLF ; Print message on term
CALL CRLF ; Print message on term
;
LXI D,HLPMSG ; Point to HELP msg
CALL PMSG ; Print message on term
;
CALL CRLF ; Print message on term
;
LXI D,SPCS1 ; Point to spaces
CALL PMSG ; Print them
;
IF ATTRIB ; IF ATTRIB
LXI D,INDVID ; Set video attribute
CALL PMSG ; Issue attribute to term
ENDIF ; ENDIF ATTRIB
;
LXI D,HLPNOT ; Point to HELP note
CALL PMSG ; Print message on term
;
IF ATTRIB ; IF ATTRIB
LXI D,NORVID ; Reset video attribute
CALL PMSG ; Issue attribute to term
ENDIF ; ENDIF ATTRIB
;
CALL CRLF ; Print CR,LF on term
CALL CRLF ; Print another CR,LF on term
RET ; Return to caller
;
; The help message
;
HLPHDR: DB 'THE FOLLOWING ARE VALID SET COMMANDS:$'
;
HLPMSG: DB ' SET BAUD <110> or <300> or <1200>',CR,LF
DB ' <2400> or <4800) or <9600>',CR,LF
DB ' SET PARITY <NONE> or <ODD> or <EVEN>',CR,LF
DB ' SET SPKR <OFF> or <ON> or <DEBUG>',CR,LF
DB ' SET WAIT <10> or <30> or <60> or <90>',CR,LF
DB ' SET DIAL <TOUCH> or <PULSE>',CR,LF,'$'
;
HLPNOT: DB 'NOTE: SET BAUD defaults to NO parity.$'
;
SPCS1: DB ' $'
SPCS2: DB ' $'
;
SETFLG: DB 0 ; SET command flag
;
;....
;
; SET BAUD processor
;
STBAUD: MVI C,BDPARS ; Function code
CALL MEX ; Let MEX look up code
JC SETERR ; Invalid code
CALL PBAUD ; No, try to set it
JC SETERR ; Not-supported code
JMP SETSHO ; review parameters
;
BDSHOW: LDA SETFLG ; Get setflg
CPI 0FFH ; Is it a 'SET' operation?
JNZ PBPS ; No, must be dial - just display bps
CALL ILPRT ; Yes, display the 'Baud' prompt
DB 'Baud rate: ',0
PBPS: LDA MSPEED ; Load modem speed code
MVI C,PRBAUD ; Use MEX function #
CALL MEX ; To print bps
LXI D,NORVID ; Reset video attribute
CALL PMSG ; Issue attribute to term
MVI E,' ' ; Followed by space
MVI C,CONOUT ; Use MEX function #
CALL MEX ; Let MEX do it
MVI A,0 ; Clear acc
STA SETFLG ; Reset setflg
RET
;
;....
;
; SET PARITY PROCESSOR
;
STPAR: LXI D,PARTBL ; Point to parity table
CALL TSRCH ; Lookup next input item in table
JC SETERR ; If NOT found, error
PUSH PSW ; A=byte from table
LDA MODEBT ; Get old mode byte
ANI 0C3H ; Strip off parity bits, word length
MOV B,A ; Old modebt into B
POP PSW ; Get table entry back
ANI 3CH ; Mask parity bits, word length
ADD B ; Adjust new parity values
STA MODEBT ; Store the new mode byte
CALL NITMOD ; (Re)initialize the modem
JMP SETSHO ; Review parameters
;
PASHOW: CALL ILPRT ; Show parity mode
DB 'Parity: ',0
LDA MODEBT ; Get mode byte
ANI 30H ; Mask off parity bits
CPI 10H ; Bit 4 hi?
JZ ODDPAR ; Yes, ODD parity
CPI 30H ; Bits 4,5 hi?
JZ EVPAR ; Yes, EVEN parity
; Else NO parity
NOPAR: CALL ILPRT ; In-line print
DB 'NONE',0 ; Message
RET ; Return
EVPAR: CALL ILPRT ; In-line print
DB 'EVEN',0 ; Message
RET ; Return
ODDPAR: CALL ILPRT ; In-line print
DB 'ODD',0 ; Message
RET ; Return
;
PARTBL: DB 'NON','E'+80H ; Set parity NONE
DB 0CH,0 ; 8 Bit word length
DB 'EVE','N'+80H ; Set parity EVEN
DB 38H,0 ; Bits 5,4,3 hi (7 bit word length)
DB 'OD','D'+80H ; Set parity ODD
DB 18H,0 ; Bits 4,3 hi (7 bit word length)
DB 0 ; <<==== TABLE TERMINATOR
;....
;
; SET SPKR processor
;
STSPKR: LXI D,SPKTBL ; lookup next input item in table
CALL TSRCH
JC SETERR ; if not found, error
STA SPBYTE+1 ; store the spkr command
CALL NITMOD ; (re)initialize modem
JMP SETSHO ; review parameters
;
SPSHOW: CALL ILPRT ; show spkr mode
DB 'Speaker: ',0
LDA SPBYTE+1 ; get spkr byte
CPI '1'
JZ SPONPT ; spkr on part-time
CPI '2'
JZ SPON ; spkr on continuously
;
SPOFF: CALL ILPRT
DB 'OFF',0
RET
;
SPONPT: CALL ILPRT
DB 'ON until connect',0
RET
;
SPON: CALL ILPRT
DB 'ON always',0
RET
;
SPKTBL: DB 'OF','F'+80H ; set spkr off
DB '0',0
DB 'O','N'+80H ; set spkr on 'til connect
DB '1',0
DB 'DEBU','G'+80H ; set spkr on continuously
DB '2',0
DB 0 ; <<=== table terminator
;
; SET WAIT PROCESSOR
;
STWAIT: LXI D,WAITBL ; LOOKUP NEXT INPUT ITEM IN TABLE
CALL TSRCH ;
JC SETERR ; IF NOT FOUND, ERROR
STA WABYTE+3 ; STORE THE WAIT MSB VALUE
MVI A,'0' ; FAKE LSB BYTE
STA WABYTE+4 ; STORE THE WAIT LSB VALUE
CALL NITMOD ; (RE) INITIALIZE MODEM
JMP SETSHO ; REVIEW PARAMETERS
;
WASHOW: CALL ILPRT
DB 'Wait: ',0
LDA WABYTE+3
CALL TYPE ; SHOW MSB OF VALUE
LDA WABYTE+4 ;
CALL TYPE ; SHOW LSB OF VALUE
CALL ILPRT
DB ' seconds for carrier',0
RET ;
;
WAITBL: DB '1','0'+80H ; "SET WAIT 10"
DB '1',0
DB '3','0'+80H ; "SET WAIT 30"
DB '3',0
DB '6','0'+80H ; "SET WAIT 60"
DB '6',0
DB '9','0'+80H ; "SET WAIT 90"
DB '9',0
DB 0
;
;.....
;
; SET DIAL PROCESSOR
;
STDIAL: LXI D,DIATBL ; LOOKUP NEXT INPUT ITEM IN TABLE
CALL TSRCH
JC SETERR ; IF NOT FOUND, ERROR
STA TPULSE ; STORE THE DIAL COMMAND
CALL NITMOD ; (RE) INITIALIZE MODEM
JMP SETSHO ; REVIEW PARAMETERS
;
DISHOW: CALL ILPRT ; SHOW DIAL MODE
DB 'Dial: ',0
LDA TPULSE ; GET DIAL BYTE
CPI 'T' ;
JZ TTONE ; TOUCH TONE
;
PDIAL: CALL ILPRT ; PRINT
DB 'Pulse',0 ; PULSE DIAL MESSAGE
RET ; AND RETURN
;
TTONE: CALL ILPRT ; PRINT
DB 'Touch Tone',0 ; TONE DIAL MESSAGE
RET ; AND RETURN
;
; DIAL ARGUMENT TABLE
;
DIATBL: DB 'TOUC','H'+80H ; TOUCH TONE
DB 'T',0
DB 'PULS','E'+80H ; PULSE DIAL
DB 'P',0
DB 0
;
;.....
;
; Compare next input-stream item in table @DE; CY=1
; if not found, else HL=matched data item
;
TSRCH: MVI C,LOOKUP ; Get function code
JMP MEX ; Pass to MEX processor
;
;....
; Print in-line message ... blows away C register
;
ILPRT: MVI C,ILP ; Get function code
JMP MEX ; Go do it
;
;....
;
; NOTE: Must terminate prior to 0B00H
;
END