<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">	TITLE	'Interrupt-driven MEX overlay for SSM IO5  v1.0'

; MXO-I510.ASM -- SSM IO5 overlay for MEX	 86/11/22

VERSION	equ	10		;version number

; NOTE 1: This overlay is designed for use with either MEXPLUS or MEX.
;	Edit this file for your preferences, then follow the 'TO USE'
;	example shown below.
;
; NOTE 2: The SSM IO-5 board supports two Intel 8251s plus 3 parallel ports.
;	Extensive configuration options are supported by the many jumpers on
;	this board, but only a few of them relate to software.  These are
;	supported by the SET command, as follows:
;		SET BASE	sets base port number of board
;		SET PORT	selects which serial port (A or B)
;		SET DATA	select position of data port (0 or 1); the
;				status port will be at the other address
;		SET RST		selects restart vector to use
;	Other SET commands supported:
;		SET DIAL	select pulse/touch dialing


; TO USE: First edit this file filling in answers for your own equipment,
;	then assemble with ASM.COM or equivalent assembler.  Finally,
;	depending on the version of Mex, create an executable module:
;
;	For MEX (v1.1x), use MLOAD (v2.3 or later) to overlay the base
;	.COM file:
;		A&gt;MLOAD MEX.COM=MEX114.COM,[MXO-SMxx,]MXO-I5xx
;			where MXO-SMxx is an optional modem overlay.
;
;	For MEXPLUS (v1.2 or greater), use MLOAD to create an overlay
;	file (.OVR), boot MEXPLUS, and use its builtin LOAD command to
;	install the overlay:
;		A&gt;MLOAD MXO-MMxx.OVR=MXO-I5xx.HEX
;		A&gt;MEXPLUS
;		[MEX] A0&gt;&gt;LOAD MXO-I5XX.OVR
;
; =   =   =   =   =   =   =   =   =   =   =   =   =   =   =   =   =   =
;
; 86.11.22 - v1.0: created first version, based on	- Roger Burrows
;		   MXO-S511.ASM
;
; =   =   =   =   =   =   =   =   =   =   =   =   =   =   =   =   =   =

YES	equ	0FFH
NO	equ	0

BELL	equ	07H		;bell
TAB	equ	09H		;tab
LF	equ	0AH		;linefeed
CR	equ	0DH		;carriage return
ESC	equ	1BH		;escape

; Change the following information to match your equipment

DEFBASE	equ	090H		;Default base address for IO5 board
DEFPORT	equ	'B'		;Default serial port (A or B)
DEFDATA	equ	0		;Default data port (0=even, 1=odd)
DEFRST	equ	7		;Default restart code (1 thru 7)

; End of information to change

DEFSTAT	equ	1-DEFDATA	;Default status port

DATA	equ	DEFBASE+(DEFPORT-'A')*2+DEFDATA	;8251 data port

STATUS	equ	DEFBASE+(DEFPORT-'A')*2+DEFSTAT	;8251 status port
TXRDY	equ	01H		;  Transmitter Empty
MDSNDB	equ	TXRDY		;    Bit to test for Send
MDSNDR	equ	TXRDY		;    &amp; value when ready
RXRDY	equ	02H		;  Receiver Ready
MDRCVB	equ	RXRDY		;    Bit to test for Receive
MDRCVR	equ	RXRDY		;    &amp; value when ready

COMMAND	equ	STATUS		;8251 command port
TXEN	equ	01H		;  Transmit Enable
DTR	equ	02H		;  Data Terminal Ready
RXEN	equ	04H		;  Receive Enable
SBRK	equ	08H		;  Send Break
ER	equ	10H		;  Error Reset
RTS	equ	20H		;  Request To Send
IR	equ	40H		;  Internal Reset
STDCMD	equ	TXEN+DTR+RXEN+RTS ;standard command combination
STDMODE	equ	4EH		;Standard Mode Value (see 8251 spec):
				;  bits: 8 data, 1 stop, no parity
				;  baud rate factor = 16x

; 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


	org	100h		;we begin

	ds	3		;for the "JMP START" instruction
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 (referenced by MXO-SMxx)
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	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		;used for PMMI (not referenced by MEX)

INSTAT:			;in modem status port
	jmp	STATIN		;(can't fit code into 10 bytes)

; Default values for BASE, PORT, DATA, RST (here to save space)

	db	'DFT'		;eyecatcher
BASEVAL:db	DEFBASE
PORTVAL:db	DEFPORT
DATAVAL:db	DEFDATA
RSTVAL:	db	DEFRST


OTDATA:	di		;out modem data port
DA1:	out	DATA
	mvi	a,STDCMD	;have to turn TXEN back on
	call	OUTCMD		; to transmit data 
	ei
	ret

INDATA:			;in modem data port
	jmp	DATAIN		;(can't fit code into 10 bytes)

; Buffer pointers &amp; overrun counter (here to save space)

	db	'BU'		;eyecatcher
INTPTR:	dw	BUFFER		;next spot where interrupt routine stores data
MEXPTR:	dw	BUFFER		;next spot where mex gets data from
OVERUN:	db	0		;number of buffer overruns


MASKR:	ani	MDRCVB		;bit to test for receive ready
	ret
TESTR:	cpi	MDRCVR		;value of receive bit when ready
	ret
MASKS:	ani	MDSNDB		;bit to test for send ready
	ret
TESTS:	cpi	MDSNDR		;value of send bit when ready
	ret

DCDTST:	jmp	DCDVEC		;data carrier detect (MEXPLUS)
RNGDET:	jmp	RNGVEC		;ring detect (MEXPLUS)
	db	0,0,0,0,0	;reserved
SMDISC:	ds	3		;smartmodem disconnect (MEXPLUS)

DIALV:	ds	3		;dial digit in A
DISCV:	jmp	PDISC		;disconnect modem (with DTR)
GOODBV:	jmp	GOODBY		;call just before exit to CP/M
INMODV:	jmp	INITMD		;called on entry from CP/M
NEWBDV:	jmp	DUMMY		;set new baud rate
NOPARV:	jmp	DUMMY		;set modem for no parity
PARITV:	jmp	DUMMY		;set modem for parity
SETUPV:	jmp	SETCMD		;process SET cmd
	ds	3		;reserved, not used by MEX
VERSNV:	jmp	SYSVER		;sign-on message from overlay
BREAKV:	jmp	PBREAK		;send a break

; Do not change the following six lines
; (jump vectors, not supported in MEX 2.0)

	ds	3		;replace with MEX function 9
	ds	3		;replace with MEX function 10
	ds	3		;replace with MEX function 247
	ds	3		;replace with MEX function 255
	ds	3		;not supported by MEX
	ds	3		;replace with MEX function 254

; Routines to clear screen &amp; clear to end of screen.  If using
; these routines, set SCRTST to YES at 010AH (above).

CLREOS:	mvi	c,PRINT
	lxi	d,TCLEOS
	call	MEX
	ret

CLS:	mvi	c,PRINT
	lxi	d,TCLSCR
	call	MEX
	ret

; End of fixed area ... from here to 1FFH is reserved (MEXPLUS)

	org	200H

;..........	start of free-format user routines	..........

; Return data carrier detect status (MEXPLUS)

DCDVEC:				;not supported - no DCD on 8251s
				;(drops through into RNGVEC)

; Return ring indicator status (MEXPLUS)

RNGVEC:	mvi	a,254		;not supported - no RI on 8251s
DUMMY:	ret

; Get input status by combining hardware &amp; buffer status

STATIN:	push	h		;save regs
ST1:	in	STATUS
	ani	255-MDRCVR	;turn off real input status
	mov	h,a		;and save across s/rtn call
	call	COMPTR		;compare pointers
	mov	a,h		;restore status
	pop	h		; &amp; regs
	rz			;equal, return any o/p status
	ori	MDRCVR		;else set i/p waiting
	ret

; Get input data (from buffer)

DATAIN:
	call	COMPTR		;buffer empty ?
	mvi	a,BELL		;yes - return with a bell (mex shouldn't
	rz			;	be calling us anyway)
	push	h		;save regs
	push	d
	lhld	MEXPTR		;get data ptr
	mov	d,m		;get the byte
	call	INCPTR		;up the pointer
	shld	MEXPTR		; &amp; save
	mov	a,d		;put byte where mex wants it
	pop	d		;restore regs
	pop	h
	ret

;*************** keep the next few routines together ***************

; Send break to remote

PBREAK:	call	FLUSH		;flush buffer first
	mvi	a,STDCMD+SBRK	;set break
	jmp	ODO		;go output, delay, then output

; Disconnect modem

PDISC:	call	FLUSH		;flush buffer first
	mvi	a,STDCMD-DTR	;turn off DTR

; Output A to command port, Delay 300 millisecs, then Output normal command

ODO:	call	OUTCMD
	mvi	b,3		;delay 300 milliseconds
	mvi	c,TIMER
	call	MEX

; Output command to resume normal status

NORMST:	mvi	a,STDCMD	;resuming normal service ...

; Output to command port

OUTCMD:				;output to command port
CO1:	out	COMMAND

; Dummy routine

	ret

;*************** end of 'drop-through' routines ***************

; Enter from CP/M

INITMD:	call	FIXRST		;set up restart vector
	call	FIXIO		;fix up port references
	ret

; Exit to CP/M

GOODBY:	di			;disable interrupts
	xra	a		;turn off everything (DTR, RTS etc)
	jmp	OUTCMD		;which returns

; Issue signon message

SYSVER:	mvi	c,ILP
	call	MEX
	db	'Version ',VERSION/10+'0','.',VERSION MOD 10+'0'
	db	' for SSM IO5 board at base address ',0
	lda	BASEVAL		;print base port number
	call	PRTHEX
	call	CRLF
	mvi	c,ILP
	call	MEX
	db	'Serial port ',0
	mvi	c,CONOUT
	lda	PORTVAL		;print serial port (A or B)
	mov	e,a
	call	MEX
	mvi	c,ILP		;show data port as even or odd
	call	MEX
	db	', data port is ',0
	lda	DATAVAL
	lxi	d,EVEN		;print even/odd
	ora	a		;is it even ?
	jz	SYSVR1		;yes
	lxi	d,ODD		;else odd
SYSVR1:	mvi	c,PRINT
	call	MEX
	mvi	c,ILP
	call	MEX
	db	', restart code ',0
	lhld	RSTVAL		;print restart code
	mvi	h,0
	mvi	c,DECOUT
	call	MEX
	mvi	c,ILP
	call	MEX
	db	', ',0
	lda	TPULSE
	lxi	d,PLSMSG	;print pulse/touch
	cpi	'P'		;is it pulse ?
	jz	SYSVR2		;yes
	lxi	d,TCHMSG	;else touch
SYSVR2:	mvi	c,PRINT
	call	MEX
	mvi	c,ILP
	call	MEX
	db	' dialing',0
	ret

; Handle SET command

SETCMD:	mvi	c,SBLANK	;any arguments?
	call	MEX
	jc	STSHOW		;if not, go print out values
	mvi	c,LOOKUP
	lxi	d,CMDTBL	;parse command
	call	MEX
	jc	SETERR		;can't find it
	pchl			;else go there
SETERR:	mvi	c,PRINT
	lxi	d,SETEMS	;print error
	jmp	MEX		;which returns

SETEMS:	db	'SET command error',CR,LF,CR,LF,'$'

CMDTBL:	db	'?'+80h		; "set ?"
	dw	STHELP
	db	'BAS','E'+80h	; "set base"
	dw	STBASE
	db	'DAT','A'+80h	; "set data"
	dw	STDATA
	db	'DIA','L'+80h	; "set dial"
	dw	STDIAL
	db	'RS','T'+80h	; "set rst"
	dw	STRST
	db	'POR','T'+80h	; "set port"
	dw	STPORT
	db	0

; SET &lt;no-args&gt;: print current statistics

STSHOW:	lxi	h,SHOTBL	;get table of SHOW subroutines
STSHLP:	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	STSHLP		;continue if no abort

; Enter here to do cr+lf

CRLF:	mvi	c,PRINT
	lxi	d,CRLFMS
	jmp	MEX		;which returns

GOHL:	pchl

; table of SHOW subroutines

SHOTBL:	dw	SHOWBA
	dw	SHOWPO
	dw	SHOWDT
	dw	SHOWRS
	dw	SHOWDL
	dw	0

; SET ?  processor

STHELP:	mvi	c,PRINT
	lxi	d,HLPMSG
	jmp	MEX		;which returns

; The help message

HLPMSG:	db	CR,LF,'SET command options:'
	db	CR,LF,'  SET BASE &lt;hex #&gt;    ... set new base port (00,10 ... F0)'
	db	CR,LF,'  SET DATA &lt;0|1&gt;      ... set data port address (0=even,1=odd)'
	db	CR,LF,'  SET DIAL &lt;P|T&gt;      ... set Pulse or Touch dialing'
	db	CR,LF,'  SET PORT &lt;A|B&gt;      ... set serial port id'
	db	CR,LF,'  SET RST  &lt;dec #&gt;    ... set restart code (1 thru 7)'
	db	CR,LF
CRLFMS:	db	CR,LF,'$'

; SET BASE command processor

STBASE:	mvi	c,SBLANK	;skip blanks
	call	MEX
	jc	SETERR		;nothing else
	lxi	h,0		;use HL to build port #
STBAS1:	push	h		;save across MEX
	mvi	c,GNC		;get char from input, cy=1 if none
	call	MEX
	pop	h		;restore
	jc	STBAS2
	call	HEXCON		;convert to hex nybble in A
	jc	SETERR		;not hex
	dad	h		;shift L left by 4 bits
	dad	h
	dad	h
	dad	h
	ora	l		;or with new nybble
	mov	l,a		;back to L
	mov	a,h		;anything in H yet ?
	ora	a
	jnz	SETERR		;yes - too big
	jmp	STBAS1		;else go round again
STBAS2:	mov	a,l		;reg L contains base port #
	ani	0fh		;check boundary alignment
	jnz	SETERR		;no good
	mov	a,l		;ok - save for display
	sta	BASEVAL
	call	FIXIO		;fix up in/out with BASEVAL,PORTVAL,DATAVAL
SHOWBA:	mvi	c,ILP
	call	MEX
	db	'Base address set to ',0
	lda	BASEVAL
	call	PRTHEX
	jmp	CRLF		;which returns

; SET DATA processor

STDATA:	mvi	c,SBLANK	;skip blanks
	call	MEX
	jc	SETERR		;nothing else
	mvi	c,EVALA		;get numeric from input
	call	MEX
	mov	a,h
	ora	a		;&gt; 256 ?
	jnz	SETERR		;yes, error
	mov	a,l
	cpi	2		;check it
	jnc	SETERR		;invalid
	sta	DATAVAL		;store it
	call	FIXIO		;fix up in/out with BASEVAL,PORTVAL,DATAVAL
SHOWDT:	mvi	c,ILP
	call	MEX
	db	'Data port set to ',0
	lda	DATAVAL		;get data setting
	lxi	d,EVEN		;assume even
	ora	a		;is it ?
	jz	SHOWT2		;yes
	lxi	d,ODD		;else odd
SHOWT2:	mvi	c,PRINT
	call	MEX
	jmp	CRLF		;which returns

; SET DIAL processor

STDIAL:	mvi	c,SBLANK	;skip blanks
	call	MEX
	jc	SETERR		;nothing else
	lxi	d,DIALTB	;parse cmd
	mvi	c,LOOKUP
	call	MEX
	jc	SETERR
	mov	a,l		;get upper case character
	sta	TPULSE		;store it for MXO-SMxx
SHOWDL:	mvi	c,ILP		;display status
	call	MEX
	db	'Dialing type set to ',0
	lda	TPULSE		;get pulse/touch setting
	lxi	d,PLSMSG	;assume pulse
	cpi	'P'		;is it ?
	jz	SHOWD2		;yes
	lxi	d,TCHMSG	;else touch
SHOWD2:	mvi	c,PRINT
	call	MEX
	jmp	CRLF		;which returns

; Dial table - saves us worrying about upper/lower case

DIALTB:	db	'P'+80H		;pulse dial
	db	'P',0
	db	'T'+80H		;touch dial
	db	'T',0
	db	0

; SET PORT processor

STPORT:	mvi	c,SBLANK	;skip blanks
	call	MEX
	jc	SETERR		;nothing else
	lxi	d,PORTTB	;parse cmd
	mvi	c,LOOKUP
	call	MEX
	jc	SETERR
	mov	a,l		;get upper case character
	sta	PORTVAL		;a-ok, save it
	call	FIXIO		;fix up in/out with BASEVAL,PORTVAL,DATAVAL
SHOWPO:	mvi	c,ILP		;display status
	call	MEX
	db	'Port set to ',0
	mvi	c,CONOUT
	lda	PORTVAL
	mov	e,a
	call	MEX		;display it
	jmp	CRLF		;which returns

; SET RST processor

STRST:	mvi	c,SBLANK	;skip blanks
	call	MEX
	jc	SETERR		;nothing else
	mvi	c,EVALA		;get numeric from input
	call	MEX
	mov	a,h
	ora	a		;&gt; 256 ?
	jnz	SETERR		;yes, error
	mov	a,l
	ora	a		;zero isn't allowed
	jz	SETERR
	cpi	8		;max of 7
	jnc	SETERR		;invalid
	sta	RSTVAL		;store it
	call	FIXRST		;fix up RST vector
SHOWRS:	mvi	c,ILP
	call	MEX
	db	'Restart code set to ',0
	lhld	RSTVAL		;get value in hl
	mvi	h,0
	mvi	c,DECOUT
	call	MEX
	jmp	CRLF		;which returns

; Port table - saves us worrying about upper/lower case

PORTTB:	db	'A'+80H
	db	'A',0
	db	'B'+80H
	db	'B',0
	db	0

;..........	subroutines used by the above routines	..........

; Convert ascii char in A to hex nybble

HEXCON:	cpi	'0'		;&lt; '0' ?
	rc			;error - return with carry set
	cpi	'9'+1		;&lt;= '9' ?
	jc	HEXNUM		;yes - must be 0-9
	cpi	'A'		;&lt; 'A' ?
	rc			;error
	cpi	'F'+1		;&lt;= 'F' ?
	jc	HEXALF		;yes - convert to hex nybble
	cpi	'a'		;&lt; 'a' ?
	rc			;error
	cpi	'f'+1		;&lt;= 'f' ?
	jnc	HEXERR		;no - error
	sui	'a'-'A'		;convert lower case a-f to upper
HEXALF:	stc
	adi	9		;convert upper case A-F to 3ah-3fh
HEXNUM:	ani	0fh		;clear high-order nybble
	ret
HEXERR:	stc
	ret

; Print contents of A as hex, followed by 'h'

PRTHEX:	push	psw		;save A
	rrc			;right justify one hex digit
	rrc
	rrc
	rrc
	call	PRTNYB		;print first hex digit
	pop	psw
	call	PRTNYB		;print second hex digit
	mvi	c,CONOUT
	mvi	e,'h'
	jmp	MEX		;print trailing 'h' &amp; return

; Print hex nybble

PRTNYB:	ani	0fh		;print one hex digit
	adi	90h		;trust me, this works
	daa
	aci	40h
	daa			;now ascii
	mvi	c,CONOUT	;print it
	mov	e,a
	jmp	MEX		;which returns

; Update in &amp; out instructions with new BASEVAL, PORTVAL, DATAVAL

FIXIO:	lda	PORTVAL		;get port id
	sui	'A'		; make it 0 or 1
	add	a		;  then 0 or 2 (offset to 1st reg for A or B)
	mov	b,a		;   in reg b
	lda	BASEVAL		;get base address
	ora	b
	mov	b,a		;b = address of even port
	lda	DATAVAL		;get data port offset
	ora	b		;a = address of data port
	sta	DA1+1
	sta	DA2+1
	xri	01h		;now a = address of status/command port
	sta	ST1+1
	sta	ST2+1
	sta	CO1+1
			;now go reinitialise ports
	mvi	b,3		;send 3 nulls
	xra	a		; to force to command state
FIXIO2:	call	OUTCMD
	dcr	b
	jnz	FIXIO2
	mvi	a,IR		;reset to mode level
	call	OUTCMD
	mvi	a,STDMODE 	;set standard mode
	call	OUTCMD
	mvi	a,STDCMD+ER	;clear errors
	call	OUTCMD
	jmp	NORMST		;which returns

; Initialise restart vector &amp; interrupts

FIXRST:	di			;safety first
	lxi	d,INTRPT	;de-&gt;interrupt routine
	lhld	RSTVAL		;hl = restart code
	mvi	h,0
	dad	h
	dad	h
	dad	h		;* 8 = address of restart vector
	mvi	a,JMP		;set up vector
	mov	m,a
	inx	h		;hl-&gt;a(interrupt routine)
	xchg			;hl-&gt;interrupt rtn, de-&gt;a(interrupt rtn)
	mov	a,l
	stax	d		;store address
	inx	d
	mov	a,h
	stax	d
	ei			;ok, interrupt away
	ret

; Compare buffer pointers
;	return with	z flag set =&gt; pointers equal

COMPTR:	push	h		;save regs
	push	d
	lhld	INTPTR
	xchg			;de-&gt;next place for input data
	lhld	MEXPTR		;hl-&gt;next char for mex
	mov	a,h
	cmp	d		;high-order bytes the same ?
	jnz	COMPTX		;no - definitely not equal
	mov	a,l		;yes - it all depends on the low-order
	cmp	e
COMPTX:	pop	d		;restore regs
	pop	h
	ret			;with z/nz set

; Increment buffer pointer
;	enter with	pointer in hl
;	return with	hl pointing to next byte of buffer (wrapped if nec)

INCPTR:	inx	h		;increment
	mov	a,h
	cpi	HIGH BUFEND	;reached end of buffer ?
	rnz			;no, return
	mov	a,l		;maybe
	cpi	LOW BUFEND	;really end ?
	rnz			;no, return
	lxi	h,BUFFER	;yes - time to wrap instead
	ret

; Flush buffer

FLUSH:	lhld	INTPTR		;set MEXPTR equal to INTPTR
	shld	MEXPTR
	ret

; Miscellaneous messages

EVEN:	db	'even address','$'
ODD:	db	'odd address','$'
PLSMSG:	db	'pulse','$'
TCHMSG:	db	'touch','$'

; Terminal-dependent control sequences

TCLEOS:	db	17H,'$'		;clear to end-of-screen
TCLSCR:	db	18H,'$'		;clear screen

;..........	interrupt-related items	..........

; Interrupt handler

INTRPT:	push	psw		;minimum status save to start with
ST2:	in	STATUS		;get status
	ani	RXRDY		;receive data ?
	jnz	INTRCV		;yes,  go get it
	mvi	a,STDCMD-TXEN	;else we got a useless TXRDY interrupt
	call	OUTCMD		; so turn off TXEN
	jmp	INTXIT		;  &amp; exit
INTRCV:	push	h		;save more status
DA2:	in	DATA
	lhld	INTPTR		;where we want to store data
	mov	m,a		;store it
	call	INCPTR		;up to next
	shld	INTPTR
	call	COMPTR		;caught up to MEXPTR ?
	jnz	INTOK		;no
	lxi	h,OVERUN	;oops - overrun
	inr	m
INTOK:	pop	h		;restore status
INTXIT:	pop	psw
	ei			;enable interrupts again
	ret

; Circular buffer for interrupt routine

BUFFER	equ	$		;at 1200 baud, 100h bytes fills in 2 secs
BUFEND	equ	0b00h		;don't club Smartmodem overlay
BUFSIZ	equ	BUFEND-BUFFER	;for interest

;.....
;
; Note:	This overlay must terminate prior to 0B00H (with Smartmodem overlay)
;					     0D00H (without Smartmodem overlay)
;.....

	END
���������������������������������������������������������</pre></body></html>