home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
MEX
/
MXO-PX8.ASM
< prev
next >
Wrap
Assembly Source File
|
2000-06-30
|
32KB
|
1,232 lines
Title 'MEX overlay for Epson PX-8 version 1.0'
;
;
; (delete above title line if not assembling with MAC)
;
;
REV EQU 10 ;overlay revision level
;
; MEX overlay for Epson PX-8 with MFU, Direct Connect modem, or
; external modem. Support is provided for an external dialing overlay
; such as MXO-SM. For details see MXO-PX8.DOC.
;
; Written 3/10/85 by David B. Kozinn
;
; Copyright (C) 1985 by David B. Kozinn
;
; This program (in source or object code form) may be copied and distributed
; for non-commercial purposes. Sale of this program is forbidden without
; written consent of the author.
;
; The author can be contacted on CompuServe [76703,565] via Easyplex, or
; (preferably) in CP-MIG (PCS-47) or EpsOnline (PCS-19).
;
; PLEASE READ THE FOLLOWING IF YOU INTEND TO MODIFY THIS OVERLAY:
; ---------------------------------------------------------------
; Much of the commentary has been removed in order to save space. For
; complete documentation of how an overlay is structured, see the original
; overlay, MXO-PM.ASM, written by Ron Fowler. Please be sure to read the
; comments in that overlay if you intend to change this one.
;
; Version Date Changes
; ------- ------- -------
; 1.0 850310 First general release version
;------------------------------------------------------------
;
; Misc equates
;
NO EQU 0
YES EQU (NOT NO) AND 0FFH
TPA EQU 100H
CR EQU 13
LF EQU 10
TAB EQU 9
BELL EQU 7
ESC EQU 01BH
CUROFF EQU 032H
CURON EQU 033H
XON EQU 011H
XOFF EQU 013H
;
; PX-8 port definitions
;
MCTLR2 EQU 002H ;Misc control signals (output)
CCR EQU 00DH ;8251 command port
DCRREG EQU 084H ;Modem tone dialer control port (output)
OCR EQU 085H ;Modem control register (output)
STR EQU 086H ;Modem status register (input)
OMR EQU 087H ;Modem port setup (output)
;
; PX-8 Special locations (see code for use)
;
WBLOC EQU 0EC03H ;BIOS call Warm Boot location
DRSDAT EQU 0F00FH ;Default RS-232 data
CTLR1 EQU 0F0B0H ;CTLR1 register value
CTLR2 EQU 0F0B2H ;CTLR2 register value
RSMODE EQU 0F6D0H ;8251 Mode byte location
RSCMD EQU 0F6D1H ;8251 Command byte location
RSOPN EQU 0F2C8H ;RS-232 open flag (00=Open)
SLVFLG EQU 0F358H ;Slave cpu (6301) flag
INTBUF EQU 0FB90H ;Internal rs232 buffer
INTBUFL EQU 0160H ;Internal buffer length
;
; bit definitions
;
MDMINIT EQU 089H ;8251 initialization string
BRKBIT EQU 008H ;8251 bit to turn break on
MDRCVB EQU 001H ;modem receive bits
MDRCVR EQU 001H ;modem recieve ready
MDSNDB EQU 002H ;modem send bits
MDSNDR EQU 002H ;modem recieve ready
USEINT EQU 020H ;set to 0, send this to CTLR2 to use int.
DCD EQU 008H ;Use with RSIOX CTLIN
;
; bit definitions for OCR
;
OHC EQU 001H ;off hook
HSC EQU 002H ;handset control
MON EQU 004H ;enable speaker
TXC EQU 008H ;transmit carrier
ANS EQU 010H ;Answer mode
TEST EQU 020H ;Test function
PWR EQU 040H ;Modem Power
CCT EQU 080H ;connect to phone lne
;
; bit definitions for STR
;
BDS EQU 001H ;Bell Detect Signal. 0 if ringing
CTSMSK EQU 004H ;Clear to send. (carrier det) =0 if clear
MII EQU 080H ;Modem Installation Indicator 0=installed
;
;
; Special BIOS call locations
;
CONIN EQU WBLOC+006H ;Direct console input
CONOUT EQU WBLOC+009H ;Direct console output
RSOPEN EQU WBLOC+039H ;Open RS-232 port
RSCLOSE EQU WBLOC+03CH ;Close RS-232 port
RSINST EQU WBLOC+03FH ;Check for input
RSOUTST EQU WBLOC+042H ;Check for output
RSIN EQU WBLOC+045H ;Get a character
RSOUT EQU WBLOC+048H ;Send a character
RSIOX EQU WBLOC+051H ;Special RS-232 calls
SLAVE EQU WBLOC+072H ;Use slave CPU
;
; Equates for use with RSIOX
;
OPNIOX EQU 010H ;Open using RSIOX
CLSIOX EQU 020H ;Close using RSIOX
INSTS EQU 030H ;Check for data in recieve buffer
CTLIN EQU 070H ;Check carrier & DSR
;
; Mex locations
;
QUEUE EQU 00D51H ;Queued I/O variable
MODE EQU 00D54H ;Terminal mode byte (01 = in terminal mode)
SMART EQU 00B00H ;Entry point for smart modem overlay
;
; Other equates
;
WTCTS EQU 150 ;How long to wait for carrier. 150=30 seconds
;
; MEX service processor stuff
;
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
;
;
PRINT EQU 9 ;simulated BDOS function 9: print string
INBUF EQU 10 ;input buffer, same structure as BDOS 10
;
ORG SMART ;Put code in in case he calls smartmodem
CPI 255 ;without installing the overlay first
RNZ ;Only do it once, at the end
CALL ILPRT
DB '** You have not installed a dialing overlay **'
DB BELL,CR,LF,0
XRA A ;Set zero flag
MVI A,3 ;Tell him dialing has been aborted
RET
ORG QUEUE ;Set to Queued I/O flag location
DB 0 ;Don't allow queued I/O (it interferes
;with the stuff we're doing)
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 NO ;yes=Smartmodem / \ referenced by MEX
TPULSE: DB 'T' ;T=touch, P=pulse (not referenced by MEX)
CLOCK: DB 20 ;clock speed x .1, up to 25.5 mhz.
MSPEED: DB 1 ;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 0 ;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 0 ;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 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 YES ;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
;
; The next two are for PMMI, we don't use them, but they have to hang
; around anyway.
;
DB 250
DB 0
;
; Low-level modem I/O routines
;
INCTL1: JMP MODSTAT ;in modem control port
DB 0,0,0,0,0,0,0 ;spares
;
OTDATA: JMP MODOUT ;out modem data port
DB 0,0,0,0,0,0,0 ;spares
;
INPORT: JMP MODIN ;in modem data port
DB 0,0,0,0,0,0,0 ;spares
;
; 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 table
;
LOGON: DS 2 ;needed for MDM compat, not ref'd by MEX
DIALV: JMP PDIAL ;dial digit in A (see info at PDIAL)
DISCV: JMP PDISC ;disconnect the modem
GOODBV: DS 3 ;called before exit to CP/M
INMODV: JMP NITMOD ;initialization. Called at cold-start
NEWBDV: JMP PBAUD ;set baud rate
NOPARV: DS 3 ;set modem for no-parity
PARITV: DS 3 ;set modem parity
SETUPV: JMP SETCMD ;SET cmd: jump to a RET if you don't write SET
SPMENV: DS 3 ;not used with MEX
VERSNV: JMP SYSVER ;Overlay's voice in the sign-on message
BREAKV: JMP PBREAK ;send a break
;
; Entry points here are for compatibility with MDM7. They will be gone
; in MEX 2.0, so avoid using them.
;
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
;
;
; Clear/screen and clear/end-of-screen. Each routine must use the
; full 9 bytes alloted (may be padded with nulls).
;
CLREOS: LXI D,EOSMSG
MVI C,PRINT
CALL MEX
RET
;
;
CLS: LXI D,CLSMSG ;null unless patched
MVI C,PRINT
CALL MEX
RET
;
;------------------------------------------------------------
;
; *** END OF FIXED FORMAT AREA ***
;
;------------------------------------------------------------
;
; Modem initialization. First make sure that the dialing overlay
; address is correct (some overlays ORG the dial vector and stick a
; JMP B00 there.) We have to make sure that we get control first.
; Also, store away the current value in the DISCV address, because it
; might be the address of the dialing overlay disconnect vector. We'll
; use this to disconnect along with the regular disconnect code if an
; external modem is being used. Then, set up the default communications
; parameters. Then, if the port is already open, just return, else set
; up to use the built-in modem.
;
NITMOD: LXI H,PDIAL ;Get address of our dialing routine
SHLD DIALV+1 ;Store it as the address to jump to
LHLD DISCV+1 ;Get address of disconnect vector
SHLD SMDISCV+1 ;Save it in case it's needed
LXI B,PDISC ;Get our disconnect routine address
XRA A ;Clear carry flag
DB 0EDH,042H ;SBC HL,BC If zero, then the same
JZ NIT0 ;Don't do anything special
DCR A ;Get 0FFH to store
STA GOTDISC ;Indicate that we've got external disc
LXI H,PDISC ;Get the address of our disconnect routine
SHLD DISCV+1 ;Store it in the proper place
NIT0: LXI H,DRSDAT ;Get default rs232 data
LXI D,BAUDRATE
LXI B,4
DB 0EDH,0B0H ;LDIR
LDA BAUDRATE ;Find out what baud we're set to
LXI H,BAUDTBL
MVI B,0
NIT1: CMP M ;Do we match this table entry?
JZ NIT2 ;Yes
INX H
INR B
JMP NIT1
NIT2: MOV A,B ;Store the table entry locally
STA MDMSPD
CALL SMSPEED ;Set modem speed for time for xfer
LDA RSOPN ;See if the port is already open
ORA A
RZ ;Don't do anything if so
CALL RSOPEN ;Turn the port on
CALL PWRON ;Try to turn the modem on
IN STR ;Read status register
ANI MII ;Is modem installed?
JNZ OPENIT ;No, open the RS-232 port normally
CALL STPORT ;Set up to use the direct connect
LDA OCRVAL ;Turn off modem power to conserve
ANI (NOT PWR) AND 0FFH
STA OCRVAL
OUT OCR
MVI A,0FFH ;Indicate we're using the internal modem
STA MDMTYPE
RET
OPENIT: CALL RSCLOSE ;Close the port to clean things up
CALL RSOPEN ;Open it up for the regular port
RET
;
; send-break routine
;
PBREAK: LDA RSCMD ;Get the current command for the 8251
ORI BRKBIT ;turn break on
OUT CCR ;Send it to the 8251
MVI B,3 ;Wait 300 ms.
MVI C,TIMER
CALL MEX
LDA RSCMD ;Restore the 8251 to normal
OUT CCR
RET
;
; disconnect the modem
;
PDISC: LDA MDMTYPE ;See if we're using an external modem
ORA A ;This will be zero if so
JNZ PDISC0 ;If not, don't worry about it
LDA GOTDISC ;See if we had an external routine
ORA A ;This will be non-zero if so
JNZ SMDISCV ;Call it if it's there
PDISC0: CALL RSCLOSE
LDA OCRVAL ;get current modem control values
ANI 0FFH-(CCT+TXC+OHC) ;On-hook, carrier off,disconnect
OUT OCR ;send it
ANI (NOT PWR) AND 0FFH ;now turn power off too
OUT OCR
STA OCRVAL ;Save this as current mod. ctl. value
CALL RESPORT ;Reset to use internal
CALL SPKROFF ;Turn the speaker off
CALL RSOPEN
RET
;
; External dialing routine disconnect code is called through here.
;
SMDISCV:JMP PDISC ;<-----This may be modified
;
;
;------------------------------------------------------------
;
; DIALING ROUTINES
;
;
; The DIGITS table is a translation for digit to register value for
; all of the possible legal digits. Not many people will likely have
; use for A-D, since they are kind of hard to dial on a normal phone,
; but since the modem supports them, I've included them here. If you do
; want to use A-D, be sure to specify them as UPPER CASE or they'll be
; treated as they were one of the non-special characters. The modem
; also understands that a comma (,) means to wait for n seconds before
; continuing (for compatability with various intelligent modems.) Any other
; values (such as -, (, or ) ) are ignored. (Values have been OR'd with
; the tone-on bit already.)
;
DIGITS: DB 1DH,10H,11H,12H ; 0, 1, 2, 3
DB 14H,15H,16H,18H ; 4, 5, 6, 7
DB 19H,1AH ; 8, 9
SPLAT: DB 1CH ; *
CRUNCH: DB 1EH ; #
CHARS: DB 13H,17H,1BH,1FH ;A, B, C, D
;
PDIAL: MOV B,A ;Save the digit
LDA MDMTYPE ;See if we're using an external modem
ORA A
MOV A,B ;Restore the digit
JZ SMART ;If so, jump to the Hayes routines
CPI 254 ;start-dial?
JZ STDIAL
CPI 255 ;end-dial
JZ ENDIAL
CPI ',' ;smartmodem pause command
JNZ CKDIG ;if not pause, continue
LDA COMDLY ;delay n seconds
MOV B,A
ADD A ; x 2
ADD A ; x 4
ADD A ; x 8
ADD B ; x 9
ADD B ; x 10
MOV B,A
MVI C,TIMER
CALL MEX
RET
;
CKDIG: CPI '9'+1 ;digits are 0-9
JNC CKALFA ;too big...check if it's A-D
SUI '0'
JC CKSPEC ;too small....check if it's * or #
LXI H,DIGITS ;get start of digits table
JMP DIALIT
;
CKALFA: CPI 'D'+1 ;legal alpha are A-D
RNC ;too big, ignore it
SUI 'A'
RC ;too small
LXI H,CHARS ;get start of character table
JMP DIALIT
;
CKSPEC: LXI H,SPLAT ;Check for specials
CPI ('*'-'0') AND 0FFH ;..is it *?
JZ DIALIT1 ;Yup, go dial
INX H ;point to CRUNCH
CPI ('#'-'0') AND 0FFH ;..is it #?
RNZ ;No, forget it
JMP DIALIT1 ;Yup, go dial
;
; First get the value to send to the tone control register. At DIALIT,
; HL contains the proper table, and A contains the offset into that table.
;
DIALIT: MVI B,0
MOV C,A ;Get offset into BC
DAD B ;Get real byte location into HL
;
DIALIT1:MOV A,M ;Get value to dial into A
OUT DCRREG ;Start sending the tone
MVI B,1 ;Send it for 100ms (which is kinda long
MVI C,TIMER ;but it's easier than coding my own timing
CALL MEX ;routine.)
XRA A
OUT DCRREG ;Turn tone off
MVI B,1 ;Wait for 100ms for the inter-digit delay
MVI C,TIMER
CALL MEX
RET
;
; Start-dial sequence: Go thru normal init sequence, assuming that
; the guy is not trying to dial while connected. (This should
; disconnect him anyway.
;
STDIAL: CALL PDISC ;Disconnect
LDA OCRVAL ;Turn on monitor soon
ORI MON
STA OCRVAL
CALL RESPORT ;I don't know why, but I gotta do this
CALL PWRON ;Init modem and ports
CALL SPKRON ;turn power to speaker on
LDA OCRVAL ;Get current value for OCR
ANI (NOT ANS) AND 0FFH ;Set originate mode
STA OCRVAL
OUT OCR
OFFHK: LDA OCRVAL ;Have to reload 'cause we're called directly
ORI CCT ;Connect to phone
OUT OCR
ORI OHC ;go off hook
OUT OCR
STA OCRVAL
MVI B,20 ;Wait 2 seconds for dial tone
MVI C,TIMER
CALL MEX
RET ;dialing init done
;
; End-dial sequence: Watch to see if CTS goes on within 30 seconds. If
; so, turn on carrier, turn speaker off, and connect to the line.
;
ENDIAL: LDA OCRVAL ;Turn on carrier
ORI TXC
OUT OCR
STA OCRVAL
CALL STPORT
MVI E,WTCTS ;# of ms * 5 to wait
LP1: MVI B,2 ;200 ms.
MVI C,TIMER
CALL MEX
IN STR ;Check modem status register
ANI CTSMSK ;See if we've got carrier yet
JZ GOTCAR ;If it's zero, then we've got carrier
MVI C,CHEKCC ;Not yet, see if he hit ctl-c
CALL MEX
MVI A,3 ;Get ready to return code
JZ NOCAR ;Yup, return
DCR E ;Nope, count down
JNZ LP1 ;Keep going if more time
MVI A,2 ;Set code in A to 2 (no answer)
NOCAR: PUSH PSW ;Save the return code
CALL PDISC ;Hang up
POP PSW ;Get the return code back
RET
;
; GOTCAR - Come here to go on-line, we've got a carrier from remote
;
GOTCAR: CALL SPKROFF ;Turn the speaker off
XRA A ;Report that we got carrier
RET
;
; <end of PX-8 dialing routines>
;------------------------------------------------------------
;
PBAUD: RET ;use SET COMM for this
;
; Sign-on message
;
SYSVER: LXI D,SOMESG
MVI C,PRINT
CALL MEX
RET
;
SOMESG: DB 'Epson PX-8 overlay V'
DB REV/10+'0'
DB '.'
DB REV MOD 10+'0'
DB '$'
;
; input from the status port. Since the PX-8 has 2 status ports, and
; we can't tell why we're being call (for input or output), we have to
; kludge here. We'll call both in & out status, and fake a 1 byte status
; word. See the MOD??? bytes for the values. Also, we check here to see
; if carrier has been lost (only if we were using the modem.) If so, then
; we'll disconnect from the phone line, reset the port, and tell the user.
;
; NOTE: It was observed that there was really no need for output status,
; so these routines always return "ready to output". However, the
; basic code structure to support both input and output status has
; been left in should it ever be necessary.
;
; Automatic X-ON/X-OFF flow control is also done from this point.
;
MODSTAT:
PUSH B ;push all registers (except A)
PUSH D
PUSH H
LDA CTLR2 ;See if we're using an MFU
ANI USEINT
JNZ MDSTAT1 ;If not, forget about it
IN STR ;Else check modem status register
ANI CTSMSK
JZ MDSTAT1 ;Everything Ok if it's there
CALL PDISC ;Otherwise hang up
CALL ILPRT ;and say something about it
DB CR,LF,'** Carrier Lost **',BELL,CR,LF,0
MDSTAT1:LDA MODE ;Get terminal mode
CPI 1 ;01 means in terminal mode
JNZ MDSTAT4 ;If not, then don't worry about it
MDSTAT2:MVI B,INSTS ;Check for characters in input buffer
LXI H,WIPEOUT ;Here's where to put the returned info
CALL RSIOX
JNZ MDSTAT2 ;Wait until we get good status
XRA A ;Clear carry
LXI H,264 ;3/4 full buffer
DB 0EDH,042H ;SBC HL,BC
JNC MDSTAT3 ;Continue if < 264 chars in buffer
LDA PENDXOFF ;is there an XOFF outstanding already?
ORA A ;It'll be 0 if not
JNZ MDSTAT4 ;If so, then just go ahead
MVI C,XOFF ;Send out an XOFF
CALL RSOUT
XRA A
DCR A
STA PENDXOFF ;Indicate a pending XOFF
JMP MDSTAT4 ;Continue
MDSTAT3:MVI B,INSTS ;Check input again, this time we're
LXI H,WIPEOUT ;seeing if it's time to send an XON
CALL RSIOX
JNZ MDSTAT3
XRA A
LXI H,50
DB 0EDH,042H ;SBC HL,BC
JC MDSTAT4 ;Don't send XON until < 50 chars in buffer
LDA PENDXOFF ;Ok, we've got < 50, did we send an XOFF?
ORA A
JZ MDSTAT4 ;No, so don't do anything
MVI C,XON
CALL RSOUT ;Send the XON
XRA A
STA PENDXOFF
MDSTAT4:CALL RSINST ;Now get status
ANI MDRCVB ;Mask off what we don't care about
ORI MDSNDB ;Always say that output is ready
POPEM:
POP H
POP D
POP B
RET
;
; Get a character
;
MODIN:
PUSH B
PUSH D
PUSH H
MVI B,INSTS
LXI H,STATBLK
CALL RSIOX ;Make sure there is really data so we
ORA A ;don't ever hang waiting
JZ MODIN1
CALL RSIN
MODIN1: POP H
POP D
POP B
RET
;
; Send a character
;
MODOUT:
PUSH B
PUSH D
PUSH H
MOV C,A
CALL RSOUT
POP H
POP D
POP B
RET
;
; type char in A on console
;
TYPE: PUSH H ;save 'em
PUSH D
PUSH B
MOV C,A ;align output character
CALL CONOUT
POP B
POP D
POP H
RET
;
; SETPORT - set up to use internal modem
;
STPORT: LDA CTLR2 ;Get current port info
ANI (NOT USEINT) AND 0FFH ;Use internal modem
SPORT: STA CTLR2
OUT MCTLR2
RET
;
; RESPORT - set up to use external modem
;
RESPORT:LDA CTLR2 ;Get current port info
ORI USEINT ;Use external modem
JMP SPORT ;Store & send to modem
;
; PWRON - Turn power on to the modem (& some other initialization stuff)
;
PWRON: MVI A,MDMINIT ;Initialize the 7508
OUT OMR
LDA OCRVAL ;Get current parameters
ORI PWR ;Turn the power on
OUT OCR
STA OCRVAL ;Save the parameters
MVI B,1 ;Wait a while to let things settle
MVI C,TIMER
CALL MEX
RET
;
; SPKRON - Turn the speaker on
;
SPKRON: MVI A,0FFH
STA SLVFLG
LXI D,SLVPRAM1
CALL SLAVE
RET
;
; SPKROFF - Turn speaker off
;
SPKROFF:LDA OCRVAL ;Get current params
ANI (NOT MON) AND 0FFH ;We're not monitoring anymore
OUT OCR
STA OCRVAL
MVI A,0FFH
STA SLVFLG
LXI D,SLVPRAM2
CALL SLAVE
RET
;
; Print in-line message ... blows away C register
;
ILPRT: MVI C,ILP ;get function code
JMP MEX ;go do it
;
; PLACECUR - Place cursor at row/col specified by BC.
;
PLACECUR:
PUSH PSW
MOV A,B
ADI 01FH ;Add in offset
STA ROW
MOV A,C
ADI 01FH ;Add in offset
STA COL
CALL ILPRT
DB ESC,'='
ROW: DS 1
COL DS 1
DB 0
POP PSW
RET
;
; Keyin - get a character into A
;
KEYIN: PUSH B
PUSH D
PUSH H
CALL CONIN ;Direct console input
POP H
POP D
POP B
RET
;
; UCASE - Convert character in A to uppercase
;
UCASE: CPI 'a'
RC ;Return if not lower case
CPI 'z'+1
RNC ;Return if > lower case z
ANI 05FH ;Else change to upper case
RET
;
; SMSPEED - Set time to transfer speed
;
SMSPEED:LDA MDMSPD ;Get locally stored speed value
MOV C,A ;Put in lower half of BC
MVI B,0 ;Zap upper half of BC
LXI H,XSPDTBL ;Get address of xfer speed table
DAD B ;Get address of time for xfer byte
MOV A,M ;Get the value
STA MSPEED ;Store it
RET
;
; Data area
;
;
; XSPDTBL - transfer speed table. The number in parenthesis is the value
; given to MEX. This differs from the actual baud rate in some
; cases due to the baud rates available on the PX-8.
;
XSPDTBL:DB 0 ;Unused
DB 0 ;110 Baud (110)
DB 0 ;150 Baud (110)
DB 1 ;300 Baud (300)
DB 3 ;800 Baud (600)
DB 5 ;1200 Baud (1200)
DB 6 ;2400 Baud (2400)
DB 7 ;4800 Baud (4800)
DB 8 ;9600 Baud (9600)
DB 9 ;19200 Baud (19200)
EOSMSG: DB ESC,'Y','$' ;clear to end-of-screen
CLSMSG: DB ESC,'*','$' ;clear whole screen
OCRVAL: DB 0 ;OCR register value
MDMTYPE:DB 0 ;modem type, 0FFH=external, 0=internal
GOTDISC:DB 0 ;got external disconnect routine, FF=Yes
MDMSPD: DS 1 ;current port speed
COMDLY: DB 2 ;#secs to wait for , in dial string
PENDXOFF:
DB 0 ;0FFH if XOFF pending, 0 otherwise
STATBLK:DS 9 ;Returned info from RSIOX INSTS call
;
; The following group of data items are for using the slave CPU.
; DO NOT ADD OR REMOVE ANYTHING IN THIS AREA!!!
;---------------Start of slave CPU data------------------
SLVPRAM1:
DW ONSNDCMD
DW ONSNDLEN
DW ONRETVAL
DW ONRETLEN
ONSNDCMD:
DB 072H,080H
ONSNDLEN:
DB 2
ONRETVAL:
DB 1
ONRETLEN:
DB 1
SLVPRAM2:
DW OFFSDCMD
DW OFFSDLEN
DW OFFRTVAL
DW OFFRTLEN
OFFSDCMD:
DB 072H,0
OFFSDLEN:
DB 2
OFFRTVAL:
DB 1
OFFRTLEN:
DB 1
;
;-----------------End of Slave CPU data----------------------
;
;
;------------------------------------------------------------
;
;
; Control is passed here after MEX parses a SET command.
;
SETCMD: 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: LXI D,SETEMS ;print error
MVI C,PRINT
CALL MEX
RET
;
SETEMS: DB CR,LF,'SET command error',CR,LF,'$'
;
;
CMDTBL: DB '?'+80H ;"set ?"
DW STHELP
DB 'OFFHOO','K'+80H ;"set offhook"
DW SETOFF
DB 'COM','M'+80H ;"set comm"
DW SETCOMM
DB 'DELA','Y'+80H ;"set delay"
DW SETDLY
;
DB 0 ;<<=== table terminator
;
; SET <no-args>: print current statistics
;
SETSHO: 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
RZ ;exit if so
PUSH H ;save table pointer
XCHG ;adrs to HL
CALL GOHL ;do it
MVI C,CHEKCC ;check for console abort
CALL MEX
POP H ;it's done
JNZ SETSLP ;continue if no abort
RET
;
GOHL: PCHL
;
; table of SHOW subroutines
;
SHOTBL: DW SHHOOK
; DW SHSTAT
DW SHDLY
DW 0 ;<<== table terminator
;
; SET ? processor
;
STHELP: LXI D,HLPMSG
MVI C,PRINT
CALL MEX
RET
;
; The help message
;
HLPMSG: DB CR,LF,'SET command, PX-8 version:',CR,LF,LF
DB CR,LF,'SET COMM set/display comm parameters'
DB CR,LF,'SET DELAY n set delay for comma in dial string'
DB CR,LF,' to n seconds'
DB CR,LF,'SET OFFHOOK go offhook'
DB CR,LF,'$'
;
; Show carrier status
;
CARRSH: CALL CARRCK ;check for it
LXI D,NOMESG ;tell about carrier
MVI C,PRINT
CZ MEX ;print the "NO" if no carrier
LXI D,CARMSG ;print "carrier present"
MVI C,PRINT
CALL MEX
RET
;
NOMESG: DB 'no $'
CARMSG: DB 'carrier present',CR,LF,'$'
;
; check the PX-8 for carrier-present (Z=no)
;
CARRCK: MVI B,CTLIN ;get status byte
CALL RSIOX
ANI DCD ;Check for carrier detect
RET
;
; Set OFFHOOK processor
;
SETOFF: CALL PDISC ;Disconnect if anything was there
CALL PWRON ;Fire up the modem
CALL OFFHK
SHHOOK: CALL ILPRT
DB 'Modem is ',0
LDA OCRVAL
ANI OHC
JZ SHONHK
CALL ILPRT
DB 'off-hook',CR,LF,0
RET
SHONHK: CALL ILPRT
DB 'on-hook',CR,LF,0
RET
;
; Set delay for comma
;
SETDLY: MVI C,EVALA ;Get the number
CALL MEX
MOV A,H ;Validate
ORA A
JNZ SETERR
MOV A,L
STA COMDLY ;Store new rate
;
; Show dialing delay
;
SHDLY: CALL ILPRT
DB 'Delay time for dialing:',0
LDA COMDLY
MOV L,A
MVI H,0
MVI C,DECOUT
CALL MEX
CALL ILPRT
DB ' seconds',CR,LF,0
RET
;
; 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
;
; SET COMM routines - With thanks to Mike Hoffman and Christopher Rhodes
; of Epson. These are from EPPXMDM3.MAC
;
SETCOMM:CALL CLS ;Clear the screen
LXI D,MENU
MVI C,PRINT
CALL MEX ;Display the setup menu
; DISPLAY CURRENT VALUES ON SETUP SCREEN
CALL DBAUD
CALL DDBITS
CALL DPARITY
CALL DSTP
CALL DMODEM
; GET USERS RESPONSE AND SET PARAMITERS
SETUP0: CALL KEYIN
CALL UCASE
CPI ESC
JZ SETUP
CPI '9'+1 ;GREATER THAN BAUD SELECTION
JNC SDBITS ;CHECK FOR DATA BITS
CPI '1' ;LESS THAN 1?
JC SETUP0 ;GET ANOTHER RESPONSE
ANI 0FH
MOV E,A
MVI A,10
SUB E
STA MDMSPD
MOV C,A
MVI B,0
LXI H,BAUDTBL
DAD B
MOV A,M
STA BAUDRATE
CALL DBAUD
JMP SETUP0
SDBITS: CPI 'B'+1 ;GREATER THAN DATA BITS
JNC SPARITY ;CHECK FOR PARITY
CPI 'A' ;LESS THAN 'A'
JC SETUP0 ;GET ANOTHER RESPONSE
SUI 3FH ;MAKE 2 OR 3
STA DBITS
CALL DDBITS
JMP SETUP0
SPARITY:CPI 'E'+1 ;GREATER THAN PARITY
JNC SSTOP ;CHECK FOR STOP BITS
SUI 'C'
SPAR1: STA PARBITS
CALL DPARITY
JMP SETUP0
SSTOP: CPI 'G'+1 ;GREATER THAN STOP BITS
JNC SMOD ;CHECK FOR MODEM
SUI 'F'-1
CPI 1
JZ SSTOP1
ADI 2
SSTOP1: STA STP
CALL DSTP
JMP SETUP0
SMOD: CPI 'I'+1 ;GREATER THAN BAUD
JNC SETUP0 ;BAD SELECTION GET ANOTHER RESPONSE
SUI 'H'
JZ SMOD1
CALL PWRON ;Try to turn the modem on
IN STR ;Read status register
ANI MII ;Is modem installed?
JNZ SMOD2
MVI A,0FFH
SMOD1: STA MDMTYPE
CALL DMODEM
JMP SETUP0
SMOD2: MVI A,BELL
CALL TYPE
SMOD3: LXI B,0201H
CALL PLACECUR
CALL ILPRT
DB TAB,'*** NO MODEM ***',0
XRA A
STA MDMTYPE
CALL DMODEM
JMP SETUP0
;
; Display baud rate
;
DBAUD: LXI B,30DH
CALL PLACECUR
LXI H,BAUDSPD
MVI D,0
LDA MDMSPD ;get baud rate code
CPI 0FFH
RZ ;unknown baud rate
MOV E,A ;x1
ADD A ;x2
ADD A ;x4
ADD E ;x5
ADD E
MOV E,A
DAD D ;point to correct rate
XCHG
MVI C,PRINT
CALL MEX
CALL ILPRT
DB ' bps ',CR,LF,0
RET
;
; Display data bits
;
DDBITS: LXI B,50DH
CALL PLACECUR
LDA DBITS
CPI 2
MVI A,'7'
JZ DDBITS1
MVI A,'8'
DDBITS1:CALL TYPE
RET
;
; Display parity
;
DPARITY:LXI B,60DH
CALL PLACECUR
LDA PARBITS
ORA A
JNZ DPAR1
CALL ILPRT
DB 'none',0
RET
DPAR1: CPI 1
JNZ DPAR2
CALL ILPRT
DB 'odd ',0
RET
DPAR2: CALL ILPRT
DB 'even',0
RET
;
; Display stop bits
;
DSTP: LXI B,70DH
CALL PLACECUR
LDA STP
CPI 1
MVI A,'1'
JZ DSTP1
MVI A,'2'
DSTP1: CALL TYPE
RET
;
; Display modem type
;
DMODEM: LXI B,80DH
CALL PLACECUR
LDA MDMTYPE
ORA A
JNZ DMODEM1
CALL ILPRT
DB 'external',0
RET
DMODEM1:CALL ILPRT
DB 'internal',0
RET
SETUP: CALL STPORT ;Set up for internal mode just in case
CALL SMSPEED ;Set time to xfer speed
LDA MDMTYPE ;See what kind of modem we're using
INR A ;If FF, then it's internal
JZ SETUP1 ;yep, it's internal
CALL RESPORT ;Using external, do setup
SETUP1: LXI H,PARAMS
LXI D,WIPEOUT
LXI B,9
DB 0EDH,0B0H ;LDIR
MVI B,CLSIOX
CALL RSIOX ; close port first
MVI B,OPNIOX
LXI H,WIPEOUT
CALL RSIOX ; open with new parameters
CALL CLS
CALL ILPRT
DB ESC,CURON
DB CR,LF,LF,LF
DB TAB,'Communication initialization completed.',CR,LF,0
RET
BAUDSPD: DB '50 $110 $150 $300 $600 $'
DB '1200 $2400 $4800 $9600 $19200$'
BAUDTBL:
DB 0FFH ; 50 baud not supported
DB 2 ; 110 baud
DB 4 ; 150 baud
DB 6 ; 300 baud
DB 8 ; 600 baud
DB 0AH ; 1200 baud
DB 0CH ; 2400 baud
DB 0DH ; 4800 baud
DB 0EH ; 9600 baud
DB 0FH ; 19.2 baud
MENU: DB ESC,CUROFF
DB ' Select alphanumeric or ESC to return.',CR,LF,LF
DB 'bit rate : 1=19200 2=9600 3=4800 4=2400'
DB ' 5=1200',CR,LF
DB ' 6=600 7=300 8=150 9=110',CR,LF
DB 'data bits : A=7 B=8',CR,LF
DB 'parity : C=none D=odd E=even',CR,LF
DB 'stop bits : F=1 G=2',CR,LF
DB 'modem type: H=external I=internal$'
PARAMS:
DW INTBUF
DW INTBUFL
BAUDRATE:
DS 1
DBITS:
DS 1
PARBITS:
DS 1
STP:
DS 1
SPECIAL:
DB 0FFH ;Not XON/XOFF, not SI/SO, DTR on, RTS on
WIPEOUT:DS 9 ; this area gets overwritten by BIOS call
COPYRITE:
DB 'Copyright (C) 1985 by David B. Kozinn'
;
;------------------------------------------------------------
;
; End of PX-8 MEX modem overlay
;
;------------------------------------------------------------
;
END