; ***************************************************************
; *								*
; *            ZRT-80 Video Terminal Driver Program		*
; *                        Written By				*
; *                      William White				*
; *                      437 Ogden Lane				*
; *                New Braunfels, Texas 78130			*
; *								*
; ***************************************************************
;
; Copyright William White and Digital Research Computers, (c) 1983
;
	title	'Terminal Driver Software'
;
; Created 		March   7, 1983	
; Last modified 	August 18, 1983	; Version 1.01
;
; This source file is assembled using the Digital Research MAC
; 8080 macro assembler with the Z80 macro library for Z-80 instructions
;
; Special thanks to Mark Kaufman and Wally Kulecz for help with the project.
;
	maclib	z80
;
false	equ	0
true	equ	not false
;
; Options:  video monitor selection
normal	equ	true		; normal selection of screen formats
motorol	equ	false		; Motorola high resolution monitor
;
;
; system memory organiztion:
;
orgn	equ	00000h		; start of program
eprom2	equ	01000h		; start of second EPROM
ram	equ	04000h		; start of scratchpad ram
ramlen	equ	00400h		; length of ram
screen	equ	0c000h		; screen refresh memory
;
; system i/o ports
;
; ins8250
receive	equ	0		; see ins8250 data sheet for details
xmit	equ	0
lobaud	equ	0
inten	equ	1
hibaud	equ	1
intid	equ	2
linctl	equ	3
modctl	equ	4		; bit 3=chrgen, 2=led, 1=rts, 0=dtr
linstat	equ	5
modstat	equ	6		; bit 7=rlsd, 6=capslock, 5=dsr, 4=cts

; 6845S ports
crtaddr	equ	8		; set the address of the port wanted
crtdata	equ	9		; transfer data to/from port

; stat1 and stat2 define default values for options
; see definitions at dip1, dip2 respectively
; note that these ports are inverted i.e. a zero is on, a one is off
stat1	equ	18h		; dip switch 2
stat2	equ	20h		; dip switch 3

kbd	equ	10h		; keyboard input port

beep	equ	30h		; short duration
bell	equ	38h		; long duration

; ASCII equates
bel	equ	'G'-64
bs	equ	'H'-64
ht	equ	'I'-64
lf	equ	'J'-64
cr	equ	'M'-64
xon	equ	'Q'-64
xoff	equ	'S'-64
esc	equ	'['-64
space	equ	' '
del	equ	127

; misc equates

; cursor size definitions
cstart	equ	0		; start raster
cend	equ	7		; end raster - 1

; macro definitions

; mask will place hl in the rage c000 to ffff
mask	macro	
	mov	a,h
	ori	11000000b
	mov	h,a
	endm

; mask8 will place hl in the range c000 to dfff
mask8	macro
	mov	a,h
	ori	11000000b
	ani	11011111b
	mov	h,a
	endm

; maskh8: place hl in range e000 to ffff
maskh8	macro
	mov	a,h
	ori	11100000b
	mov	h,a
	endm

; subhle will subtract:  hl:=hl-e
; uses d
subhle	macro	
	ana	a
	mvi	d,0
	dsbc	d
	endm

; addhle will add:  hl:=hl+e
; uses d
addhle	macro
	mvi	d,0
	dad	d
	endm

; turnon:  turn a bit in memory on
turnon	macro	?A,?B
	lxi	h,?A
	setb	?B,m
	endm

; turnoff:  turn off a bit in memory
turnoff	macro	?A,?B
	lxi	h,?A
	res	?B,m
	endm

	page
;	*********************************
;	*				*
;	*	initialization		*
;	*				*
;	*********************************

	org	orgn		; start of rom 

reset	jmp	startup

; copyright notice

	db	'Copyright 1983 Wm. White '
	db	'Digital Research Comp'

	page
;	*********************************
;	*				*
;	*         interrupts            *
;	*				*
;	*********************************

; the maskable interrupt (38h) is the ins8250 uart.
; it will interrupt on either received data or status line change

	if	$>(orgn+38h)	; check for errors
		'overrun error at 38h.'
	endif
	org	orgn + 38h

rxvisr	push	psw

; find cause of interrupt
	in	intid
	ani	6
	cpi	4
	jrz	rxint		; receiver interrupt

; modem status line has changed:
;   copy dsr to rts output
	in	modstat
	bit	5,a
	jrnz	rtsnl
	call	rtslow
	jr	preti		; end routine

; ***************************************************************
; Non-maskable interrupt	 				*
	if	$>(orgn+66h)	; check for errors		*
		'Error at 66h.'	;				*
	endif			;				*
	org	orgn+66h	;				*
				;				*
keyvisr	push	psw		; save registers		*
	in	kbd		; get keyboard character	*
	sta	kbuff		; save in buffer		*
	mvi	a,0ffh		; set flag			*
	sta	kflag		; 				*
	pop	psw		; restore			*
	retn			; return & restore int status  	*
;								*
; ***************************************************************

; uart interrupt service routine continued:

; set rts high if x-on mode or computer is not waiting on terminal
rtsně	in	stat1
	cma
	bit	6,a		; check for x-on control
	jrz	rtsw
	call	rtshi
	jr	preti

rtsw	ldá	dip3
	bit	a,5
	cz	rtshi
	jr	preti

; receiver interrupt: get a character
rxint	in	stat2
	cma
	bit	5,a		; check for local

	in	receive		; get chr from uart
	res	a,7		; rid of parity, no check!
	cz	storx		; store the rx chr in the fifo

; pop & reti
preti	pop	psw
	ei
	reti


; keyboard lookup table
;   bit 7 is the alternate keyboard mode bit.
;   bit 7 set on second byte sends ESC first
;
; these tables may also be used to recode keyboard codes.

ktheath	db	'1','S'+80H	; function key  1
	db	'2','T'+80H	;		2
	db	'3','U'+80H	;		3
	db	'4','V'+80H	;		4
	db	'5','W'+80H	;		5
	db	'6','P'+80H	;		blue
	db	'7','Q'+80H	;		red
	db	'8','R'+80H	;		gray

klheath	equ	($-ktheath)/2

ktadm	db	0,0		; empty table
kladm	equ	($-ktadm)/2

ktbee	db	'1','p'+80h
	db	'2','q'+80h
	db	'3','r'+80h
	db	'4','s'+80h
	db	'5','t'+80h
	db	'6','u'+80h
	db	'7','v'+80h
	db	'8','w'+80h
	db	'9','x'+80h
	db	'0','y'+80h

klbee	equ	($-ktbee)/2

ktadds	db	0,0
kladds	equ	($-ktadds)/2

	page
;	*********************************
;	*				*
;	*	initialization		*
;	*				*
;	*********************************

; initialize all buffers, pointers, flags, and i/o

startup	lxi	sp,stack
	di
	im1

; clear buffer space in RAM
	lxi	h,rambuff
	mvi	b,buffsiz
strtclr	mvi	m,0
	inx	h
	djnz	strtclr

; initialize fifo's
	lxi	h,rxfifo
	shld	rxinp
	shld	rxout
	lxi	h,txfifo
	shld	txinp
	shld	txout

; setup the flags in dip1,2,3,4
	in	stat1
	cma
	sta	dip1

	in	stat2
	cma
	sta	dip2

	mvi	a,init3
	sta	dip3

	mvi	a,init4
	sta	dip4

; initialize CRTC
	call	crtcmod		; set the mode
	call	cursmod		; set the cursor
	call	statmod		; set the status line

; initialize UART
	call	setbaud		; set the baud rate from dip1
	mvi	a,9
	out	inten		; enable int for rx & modstat
	mvi	a,initmod
	sta	modcopy		; copy of data sent to modem port
	out	modctl		; set dtr high

	rst	7		; execute interrupt routine once
				;   this reads input port & sets outputs
; Check for EPROM istalled in second ROM socket.
	lda	eprom2		; first byte must be a JMP instruction
	cpi	0c3h
	cz	eprom2		; execute the program now if there.
;
	ei			; let the receiver interrupt 
	jmp	main		; execute main program


; set baud rate
;  take data from 4 bits of dip1 and setup 8250
setbaud	lda	dip1
	ani	15		; keep 4 bits
	rlc
	mov	e,a
	mvi	d,0
	lxi	h,baudtab	; baud rate divisor table
	dad	d

; program 8250
	mvi	a,083h
	out	linctl
	mov	a,m
	out	lobaud
	inx	h
	mov	a,m
	out	hibaud

; set 2 stop bits for 110 baud or lower
	ani	04h		; bit 2 is on for these
	ori	3		; 8 bits, no parity, normal mode
	out	linctl
	ret

; table of baud rate divisors
;  xtal = 2.4576 MHz
baudtab	dw	8		; 19,200
	dw	16		;   9600
	dw	21		;   7200
	dw	32		;   4800
	dw	43		;   3600
	dw	64		;   2400
	dw	77		;   2000
	dw	85		;   1800
	dw	128		;   1200
	dw	256		;    600
	dw	512		;    300
	dw	1024		;    150
	dw	1142		;    134.5
	dw	1396		;    110
	dw	2048		;     75
	dw	3072		;     50

; set rts high
rtshi	lda	modcopy
	ori	6
	jmp	rtso

; set rts low
rtslow	lda	modcopy
	ani	0f9h
rtso	sta	modcopy
	out	modctl
	ret

	page
;	*********************************
;	*				*
;	*	CRTC routines		*
;	*				*
;	*********************************


; procedure crtcmod
;   read mode from 3 bits of dip2 and setup the crtc accordingly
;   clear the screen and set crtc cursor position
crtcmod	lda	dip2
	ani	111b
; lookup in table (16 byte entries)
	lxi	h,crttabl
	rlc
	rlc
	rlc
	rlc
 	mov	e,a
	mvi	d,0
	dad	d
	mov	a,m		; get cpl
	sta	cpl
	inx	h
	mov	a,m		; get lps
	sta	lps
	inx	h
	mov	a,m		; get vsyn
	sta	vsyn
	inx	h
	mov	a,m		; get scrsiz
	sta	scrsiz
	inx	h
	mov	a,m
	sta	scrsiz+1
	inx	h
; load up crtc registers
	mvi	c,0		; register counter
	mvi	b,10		; init 10 registers
crt1	mov	a,c		; get register number
	out	crtaddr
	mov	a,m		; get data
	out	crtdata
	inx	h
	inr	c
	djnz	crt1

	call	escreen
	call	setcurs
	ret

; crttabl is a table of initalization values for the crt controller
;
; each 16 byte entry has:
; cpl,lps,vsyn,scrsiz,d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,0
; cpl is the number of characters / line
; lps is the number of lines / screen
; vsyn is the vertical sync position for status line display
; scrsiz the screen size in bytes
; where di is crtc port data
;
;   Note:  The board must have at least 1 memory chip for each
;	   2048 characters on the screen.
;
; Xtal=20.000 MHz
;
; registers are:
;    	0 horizontal total	5 vert total adj
;  	1 horizontal displayed	6 vertical displayed
;	2 horiz sync pos	7 vert sync pos
;	3 sync width		8 interlace & skew
;	4 vertical total	9 maximum raster
;
; Other formats can be programmed:  Refer to Hitachi data sheet on
; the HD6845S or the Motorola data sheet on the MC6845*1 to determine
; correct values for registers.  The dot clock can typically be run up 
; to about 25MHz without modification.  The dot clock frequency can be
; changed without affecting any other circuitry on the board.
;
crttabl
;		 0   1   2   3   4   5   6   7   8   9  x
; 80 lines x 24 characters, 15748Hz horizontal, 60 Hz vertical, 10 rasters/line
	db	80,24,25
	dw	1920
	db	7eh,50h,61h,68h,19h,03h,18h,18h,50h,09h,0

; 80 x 48, 15748, 60, 9
	db	80,48,52
	dw	3840
	db	7eh,50h,61h,68h,39h,03h,30h,34h,53h,07h,0

; 80 x 24 17544, 60, 11 
	db	80,24,25
	dw	1920
	db	71h,50h,5ah,68h,19h,06h,18h,18h,50h,0ah,0

; 80 x 48, 18691, 60, 11
	db	80,48,52
	dw	3840
	db	6ah,50h,55h,68h,37h,07h,30h,34h,53h,09h,0

; 96 x 24, 15748, 60, 10
	db	96,24,25
	dw	2304
	db	7eh,60h,67h,68h,19h,03h,18h,18h,50h,09h,0

; 80 x 24, 15748, 50, 11
	db	80,24,1ah
	dw	1920
	db	7eh,50h,61h,68h,1bh,07h,18h,1ah,50h,0ah,0

	if	normal		; these two can be replaced by specials
; 80 x 48, 15748, 50, 
	db	80,48,51
	dw	3840
	db	7eh,50h,61h,68h,38h,03h,30h,33h,53h,09h,0

; 96 x 24, 15748, 50, 11
	db	96,24,26
	dw	2304
	db	7eh,60h,67h,68h,1bh,07h,18h,19h,50h,0ah,0
	endif

	if	motorol
; SPECIAL MONITOR SETUP:
;
; crtc parameters for use with Motorola M4408-540 high resolution monitor:
;  This monitor is a vertical page format monitor that allows operation with
;  up to 66 lines of 96 characters with this terminal.  This is the exact 
;  capacity of an 8-1/2 x 11 inch page on an elite typewriter.  It is actually
;  possible to run better than 80 lines but 66 seems more practical.
;
;  This monitor has a nominal horizontal frequency of 30.5kHz and a vertical 
;  frequency of 60 Hz.  The video bandwidth is 50MHz.  
;
;  In order to use this board with the monitor, the dot clock is run at
;  32 Mhz, (and slightly modified), the dot clock counter is replaced with
;  a schottky chip (74S196).
;
; 96 x 33, 29000, 60, 15
	db	96,33,35
	dw	96*33
	db	111,96,97,104,35,9,33,34,81,12,0
; 96 x 66, 29000, 60, 15
	db	96,66,70
	dw	96*66
	db	111,96,97,104,72,6,66,70,83,11,0
	endif
;
;
; set display register
; turn on extra display line when status line is enabled
; change vertical sync position
; this helps center the display in the useable area of the monitor

statmod	mvi	a,6		; vertical displayed
	out	crtaddr
	lda	dip4
	bit	0,a		; check for status
	lda	lps
	jrz	nostat
	inr	a
nostat	out	crtdata
	rz			; no status
; if status line enabled, then change vertical sync position
	mvi	a,7
	out	crtaddr
	lda	vsyn
	out	crtdata
	ret

; set cursor mode
;   use cursor enable,block cursor, blink  bits in dip3, dip4
cursmod	lda	dip3		; see if cursor is enabled
	bit	4,a
	mvi	c,20h		; cursor disabled
	jrz	cursmen

; cursor is enabled:  check for blink/non-blink
	bit	1,a		; check for blink
	mvi	c,0		; no blink
	jrz	cursmen
	mvi	c,60h		; cursor blink

; find correct type of cursor
cursmen	lda	dip4
	bit	1,a
	mvi	b,cstart	; top line for block cursor
	jrnz	cursblk
; underscore cursor
	mvi	b,cend		; single line
cursblk	mvi	a,10
	out	crtaddr
	mov	a,b
	ora	c		; enable/disable
	out	crtdata
	mvi	a,11
	out	crtaddr
	mvi	a,cend		; bottom
	out	crtdata
	ret



; *********************************
; * 				  *
; * housekeeping routines for crt *
; *				  *
; *********************************

; setcurs
;    send the cursor position to the crt controller
setcurs	mvi	a,15
	out	crtaddr
	lda	cursor
	out	crtdata

	mvi	a,14
	out	crtaddr
	lda	cursor+1
	out	crtdata
	ret

; sethome
;     save new position of home and copy the status line.

; if status enabled, copy cpl bytes from home+scrsiz to newhome+scrsiz
sethome	mask			; put in proper range
	lda	dip4
	bit	0,a
	jrz	sethno		; no status

	push	h		; save new home
	lbcd	scrsiz
	dad	b
	mask8
	xchg			; de=newhome+scrsiz

	lhld	home
	dad	b		; hl=home+scrsiz
	mask8

	lbcd	cpl
	mvi	b,0

	ldir			; copy status line

	pop	h		; save new home
sethno	shld	home

;
	mvi	a,13
	out	crtaddr
	mov	a,l		; get low(home)
	out	crtdata

	mvi	a,12
	out	crtaddr
	mov	a,h		; get high(home)
	out	crtdata
	ret

	page
;	*********************************
;	*				*
;	*       Main Program Loop       *
;	*				*
;	*********************************

main	lxi	h,main		; any routine called will return here
	push	h

	call	fetchrx		; get a character

; process the character:
;    case
;	chr=del do nothing
;	chr<32  control character:  lookup routine & exec
;	chr>=32 printable character:  write to screen

	cpi	del
	rz			; do nothing

	cpi	32
	jrc	control		; control character

; it is a printing character
	call	write		; put it on the screen
	jmp	cinc		; increment cursor position

; control character:
;    take the character and look for a match in the control code table
;    for the protocol being used.
;    CR, LF, HT are handled as special cases
control	cpi	ht		; check for commonly used codes first
	jz	ctab		; this improves the speed of execution
	cpi	cr
	jz	hcr
	cpi	lf
	jz	hlf

	lxi	h,ctltab	; find correct table for emulation mode
	call	select		; select a control table, lookup routine
	pchl			; execute the routine

; esc character received:
;     take next character and lookup routine associated with it
;     according to the selected protocol.
escseq	call	fetchrx
	lxi	h,esctab
	call	select
	pchl

; ctltab is a table with 4 entries, one for each emulation mode

; terminals are:
;   0.  Heathkit H-19
;   1.  Lear Seigler ADM-3
;   2.  Beehive
;   3.  ADDS Regent 200

ctltab	dw	ctheath
	db	3		; width
	db	clheath		; length
;
	dw	ctadm
	db	3		; width
	db	cladm		; length
;
	dw	ctbee
	db	3		; width
	db	clbee		; length
;
	dw	ctadds
	db	3		; width
	db	cladds		; length
;
esctab	dw	etheath		; table
	db	3		; width
	db	elheath		; length
;
	dw	etadm		; table
	db	3		; width
	db	eladm		; length
;
	dw	etbee		; table
	db	3		; width
	db	elbee		; length
;
	dw	etadds		; table
	db	3		; width
	db	eladds		; length
;
; key code lookup table
keytab	dw	ktheath
	db	2,klheath

	dw	ktadm
	db	2,kladm

	dw	ktbee
	db	2,klbee

	dw	ktadds
	db	2,kladds

; control code table for heath terminal
; note that cr,lf,ht are already taken care of

ctheath	db	esc		; escape sequence
	dw	escseq
	db	bel		; ring bell
	dw	ring
	db	bs		; back-space
	dw	cleft
clheath	equ	($-ctheath) / 3


; escape codes for heath and adm terminal
etadm
etheath
	db	'='		; cursor addressing for adm3
	dw	caddr

; cursor functions
	db	'Y'		; cursor addressing for heath
	dw	caddr
	db	'H'		; home cursor
	dw	chome
	db	'C'		; cursor right, stop at right margin    
	d÷	crighô		                                        
	db	'D'             ; cursor left, stop at left margin      
	dw	cleft		                                        
	db	'B'             ; cursor down, don't scroll             
	dw	cdown		                                        
	db	'A'             ; cursor up, don't scroll               
	dw	cup		                                        
	db	'I'             ; reverse line feed                     
	dw	crlf		                                        
	db	'n'             ; cursor position report		
	dw	crep		
	db	'j'		; save cursor position
	dw	csav
	db	'k'		; restore cursor position
	dw	cresto
; edit and erase
	db	'E'		; erase screen
	dw	escreen
	db	'b'		; erase start to cursor, inclusive
	dw	ebegin
	db	'J'		; erase cursor to end, inclusive
	dw	eend
	db	'l'		; erase line
	dw	eline
	db	'o'		; erase left to cursor, inclusive
	dw	eleft
	db	'K'		; erase cursor to right, inclusive
	dw	eright
	db	'L'		; insert line
	dw	insline
	db	'M'		; delete line
	dw	delline
	db	'N'		; delete character 
	dw	delchr
; modes
	db	'@'		; enter insert character mode
	dw	inson	
	db	'O'		; exit insert character mode
	dw	insoff
	db	'p'		; enter inverse video mode
	dw	invon
	db	'q'		; exit inverse video mode
	dw	invoff
	db	'F'		; enter graphics mode
	dw	gron
	db	'G'		; exit graphics mode
	dw	groff

	db	'r'		; set baud rate
	dw	setbrg
	db	'x'		; set mode -- takes one chr
	dw	setmode
	db	'y'		; reset mode -- takes one chr
	dw	resmode
	db	'{'		; enable keyboard
	dw	keyoff
	db	'}'		; disable keyboard
	dw	keyon
	db	'v'		; enable wraparound mode
	dw	wrapon
	db	'w'		; disable wraparound mode
	dw	wrapoff
; misc
	db	'z'		; reset to power on state
	dw	reset
	db	esc		; same as first escape
	dw	escseq

; added features
	db	't'		; test routines
	dw	testmod
	db	's'		; set screen format
	dw	setcrtc	
	db	'f'		; alternate character set
	dw	alton	
	db	'g'		; standard character set
	dw	altoff

elheath	equ	($-etheath)/3 	; end of heath table
eladm	equ	($-etadm)/3	; end of adm3 table


; adm-3 assignments
ctadm	db	bs		; back-space
	dw	cleft
	db	bel		; right bell
	dw	ring
	db	'K'-64		; cursor up
	dw	cup
	db	'L'-64		; cursor right
	dw	cright
	db	'N'-64		; keyboard enable
	dw	keyoff
	db	'Q'-64		; keyboard disable
	dw	keyon
	db	'Z'-64		; erase screen
	dw	escreen
	db	'['-64		; escape code
	dw	escseq
	db	'^'-64
	dw	chome

cladm	equ	($-ctadm)/3

; Beehive terminal assignments:
;   only those codes that are implemented are included.
;   Many features on the Beehive terminals are not included.

ctbee	db	bel		; ring bell
	dw	ring
	db	bs		; back-space
	dw	cleft	
	db	esc		; escape code
	dw	escseq
clbee	equ	($-ctbee)/3

etbee	db	'7'		; set baud rate
	dw	setbrg
	db	'Q'		; insert mode on
	dw	inson	
	db	'@'		; insert mode off
	dw	insoff
	db	'A'		; cursor up
	dw	cup
	db	'B'		; cursor down
	dw	cdown
	db	'C'		; cursor right
	dw	cright
	db	'D'		; cursor left
	dw	cleft
	db	'E'		; erase screen
	dw	escreen
	db	'F'		; cursor addressing
	dw	caddr
	db	'G'		; read cursor posn
	dw	cread
	db	'H'		; cursor home
	dw	chome
	db	'J'		; erase to end
	dw	eend
	db	'K'		; erase right
	dw	eright
	db	'L'		; insert line
	dw	insline
	db	'M'		; delete line
	dw	delline
	db	'P'		; delete character
	dw	delchr
	db	'R'		; graphics on
	dw	gron
	db	'S'		; graphics off
	dw	groff
	db	'V'		; reset terminal
	dw	reset
	db	'Y'		; cursor addressing
	dw	caddr
	db	'Z'		; toggle cursor on/off
	dw	curstog
	db	'\'		; report cursor position
	dw	crep
	db	'b'		; keyboard enable
	dw	keyoff
	db	'c'		; keyboard disable
	dw	keyon
	db	'l'		; inverse video
	dw	invon
	db	'm'		; normal video
	dw	invoff

elbee	equ	($-etbee)/3

; ADDS Regent 200 terminal assignments

ctadds	db	bs		; back-space
	dw	cleft
	db	esc		; escape
	dw	escseq
	db	bel		; ring bell
	dw	ring
	db	'A'-64		; home cursor
	dw	chome
	db	'B'-64		; keyboard unlock
	dw	keyoff
	db	'F'-64		; cursor right
	dw	cright
	db	'L'-64		; erase screen
	dw	escreen
	db	'U'-64		; cursor left
	dw	cleft
	db	'Y'-64		; keyboard lock
	dw	keyon

cladds	equ	($-ctadds)/3

etadds	db	'E'		; delete character
	dw	delchr
	db	'F'		; insert character
	dw	hinschr
	db	'l'		; delete line
	dw	delline
	db	'M'		; insert line
	dw	insline
	db	'Y'		; cursor addressing
	dw	caddr
	db	'k'		; erase to end
	dw	eend
	db	'K'		; erase to right
	dw	eright
	db	'Z'		; next chr is graphic
	dw	graphic
	db	's'		; reset terminal
	dw	reset
	db	'A'		; set baud rate
	dw	setbaud
		
eladds	equ	($-ctadds)/3



	page
;	*********************************
;	*				*
;	*    General Purpose Routines   *
;	*				*
;	*********************************

; Search a table for an entry matching the accumulator

; HL is table start
; D  is table length
; E  is table width
; A  is character to match

; return:
; A  is character after match, or same character if no match
; HL is address of character after match
; c  is set if no match found

search	mov	c,a		; save chr
srch1	cmp	m		; check this entry
	jrz	srch3		; match
; no match:
	mov	b,e		; width
	mov	a,c		; get chr
srch2	inx	h		; advance e bytes
	djnz	srch2

	dcr	d		; length-1
	jrnz	srch1
	mov	a,c
	stc
	ret

; match:
srch3	inx	h
	mov	a,m
	ret

; Select a pair values for hl,de based on
; the emulation mode selected and table address in hl
; there exists a table at (hl) with 4 four byte entries
; lookup the address of the routine using search
; and return it in hl
select	push	psw
	in	stat2		; its in bits 3,4
	cma
	rrc
	ani	00001100b
	mov	e,a
	mvi	d,0
	dad	d
; hl now points to entry
	mov	e,m
	inx	h
	mov	d,m
	inx	h
	mov	c,m
	inx	h
	mov	b,m
	xchg
	mov	d,b
	mov	e,c
; h,l,d,e have been loaded.
	pop	psw

; search for the address
	call	search
	jc	noroutn		; no routine found:  do noop
	inx	h
	mov	h,m		; get h
	mov	l,a		; get l
	ret			; no carry

noroutn	lxi	h,noop
noop	ret

; read keyboard character and put in fifos
;
keybd
; 
;   there is a keyboard translation table for each terminal type.
;   any entry in the table with bit 7 set will send an ESC char first
;
; 	get a keyboard character
;	lookup translated value in table
;	if capslock then map a-z to A-Z
;	if bit 7 then send ESC
;	send character
;

; check for available character
	lxi	h,kflag
	bit	0,m		; check for flag
	rz

; check for keyboard lock
	lda	dip3
	bit	3,a
	rnz

; get a character
	mvi	m,0		; clear flag
	inx	h		; goto buff
	mov	b,m		; get chr

	mov	a,b		; get chr with 8 bits
	res	7,b		; clear bit 7 on character

; lookup new value based on character and terminal type
	push	b
	lxi	h,keytab
	call	select		; find new value for this terminal
	pop	b
	jrc	keycvt
	mov	b,a		; save new character
; if capslock and lower case alphabetic then convert case
keycvt	in	modstat
	bit	6,a		; check bit
	jrz	keyfini		; no capslock

;      then if chr >= 'a' and chr <= 'z'
	mov	a,b		; get chr
	cpi	'a'
	jrc	keyfini		; else do nothing
	cpi	'z'+1
	jrnc	keyfini
;		    then chr := chr - 32
	sui	32
	mov	b,a
keyfini

; ready to send the char:
; if printable and col=cpl-8 then ding bell
	mov	a,b		; look at chr
	cpi	' '
	jrc	noding
	cpi	7fh
	jrnc	noding

	lda	cpl
	sui	8
	lxi	h,column
	cmp	m
	cz	ding
noding

; if bit7 set then
	bit	7,b
;   send ESC
	mvi	a,esc
	cnz	send
; send chr and 7fh
	mov	a,b
	res	7,a
send
;   if local or local copy
	push	psw
	in	stat2
	cma
	ani	01100000b
	jrz	sendnlc
;      then storx
	pop	psw
	push	psw
	call	storx
;   if not local 
sendnlc	in	stat2
	cma
	ani	00100000b
	jrnz	sendl
;      then stotx
	pop	psw
	call	stotx
	ret
; ret
sendl	pop	psw
	ret


; character fifo buffer routines:

; storx:  save a received character
; 	take care of xon/xoff protocol
storx	push	psw
	push	h
; save character, advance pointer
	lhld	rxinp
	mov	m,a		; save character
	inr	l		; no carry to h
	shld	rxinp
; if not xoff sent
	lda	dip3
	bit	5,a
	jrnz	srx
;   then if full
	lda	rxout		; pos of last chr sent 
	sub	l
	neg			; out-inp is number of chrs in buffer
	cpi	256 * 3/4	; compare to 3/4 full
	jrnz	srx		; do nothing
;      then send xoff
	call	sndxoff
; 	    set xoffsent flag
	lxi	h,dip3
	setb	5,m
; return
srx	pop	h
	pop	psw
	ret

; fetchrx:  fetch a received character
;   any time the terinal is idle, this routine is executing
;   take care of xon/xoff protocol
;   check keyboard buffer for character
;   transmit a character if tbe and chr is avail

fetchrx	push	b
	push	d
	push	h

; transmit if possible
frxagn	call	keybd		; handle the keyboard
	call	transmt		; take care of transmissions

; check for received characters
; if char available
	lhld	rxout
	lda	rxinp
	cmp	l
	jrz	frxels		; nothing

; 	then get character
	mov	b,m		; get chr

;	     advance pointer
	inr	l
	shld	rxout

;	     if xoff-sent 
	lda	dip3
	bit	5,a
	jrz	frxret

;		then if buffer=1/4
	lda	rxinp
	sub	l
	cpi	256 * 1/4	; check for 1/4 buffer
	jrnz	frxret

;		    then send xon
	call	sndxon

;			 reset flag
	lxi	h,dip3
	res	5,m
	jr	frxret

;	else
frxels

;	     setcurs
	call	setcurs

; 	     goto fetchrx
	jr	frxagn

; return
frxret	mov	a,b
	pop	h
	pop	d
	pođ	b
	ret

; xon/xoff routines:
;    turn led on/off
;    if x protocol is enabled, then
;        stotx an xon/xoff
;    else
;	turn rts on/off
; ret

sndxoff	in	stat1
	cma
	bit	6,a
	jrz	sxhrd		; set rts low
; send x-off
	mvi	a,xoff
	call	stotx
	lda	modcopy
	jr	sxled

sxhrd	lda	modcopy
	res	1,a		; rts low
sxled	res	2,a		; led off
	sta	modcopy
	out	modctl
	ret

sndxon	in	stat1
	cma
	bit	6,a
	jrz	sxnrts

	mvi	a,xon
	call	stotx
	lda	modcopy
	jr	sxnled

sxnrts	lda	modcopy
	setb	1,a		; rts high
sxnled	setb	2,a		; led on
	sta	modcopy
	out	modctl
	ret

; stotx:  save a character to be transmitted
stotx	push	h
	lhld	txinp
	mov	m,a
	inr	l
	res	txfsiz,l	; keep in bounds
	shld	txinp
	pop	h
	ret

; fetchtx: fetch a character to be transmitted
; return carry if there is none
fetchtx	lhld	txout
	mov	a,m
	inr	l
	res	txfsiz,l	; keep in bounds
	shld	txout
	ret

; see if a chr is present to transmit
txchr	lhld	txout
	lda	txinp
	cmp	l
	ret			; z means none, nz means chr avail


; Transmit a character if buffer is empty and chr is available
transmt	call	txchr
	rz			; nothing
; see if transmitter is ready to accept a character
; 1.  must have clear to send
; 2.  uart buffer must be empty
	in	modstat
	bit	4,a		; check for cts
	rz

	in	linstat		; buffer full?
	bit	5,a
	rz
; all systems are GO . . .
	call	fetchtx		; get the chr to transmit

; process for parity
	res	7,a		; strip first
	mov	b,a		; save
; check parity options
;    5  4  option
;
;    0  0  low
;    0  1  high
;    1  1  odd
;    1  0  even
	in	stat1
	rlc
	rlc
	rlc
	jrc	xmpar		; add parity
; no parity:  put in bit 7 and xmit
	ani	80h
	ora	b
	jr	xmout
; add parity
xmpar	ani	80h
	mov	c,a
	mov	a,b
	ana	a
	jpe	par
	xri	80h		; make parity eveb
par	xra	c		; change if neccessary
xmout	out	xmit
	ret

	page
;	*********************************
;	*				*
;	*     Erasing and Editing       *
;	*				*
;	*********************************

; clear the status line
clrstat	lhld	home
	lded	scrsiz
	dad	d
	lda	cpl
	mov	b,a
clrs1	mvi	m,space
	inx	h
	djnz	clrs1
	ret

; check for status line:  return z if yes, nz if no
dumpst	lda	lps		; check for status line.
	lxi	h,line
	cmp	m		; is status line?
	ret

; erase de bytes from hl
; de >= 0
erase	mov	a,d
	ani	8191/256	; 8k max
	mov	d,a
	mask8

	lda	dip3		; check for inverse video
	ani	80h
	adi	space
	mov	b,a		; write this chr
; write b into de bytes at hl
	mov	a,d		; check for zero
	ora	e
	rz
	inr	d
eras1	mov	m,b		; erase one
	inx	h
	dcr	e
	jnz	eras1
	dcr	d
	jnz	eras1
	ret

; erase the screen
;   home := screen
;   screen := spaces
escreen	call	dumpst
	jz	eline		; just erase status line

	lxi	h,screen
	call	sethome
	call	chome		; home the cursor

; erase the screen now
	lhld	home		; from 
	lded	scrsiz		; length
	jmp	erase

; eline: erase line with cursor, leave cursor alone
; find start of line
; erase cpl bytes
eline	lhld	cursor
	lded	column
	subhle
	mask8			; keep everything in bounds
	lded	cpl
	mvi	d,0
	jmp	erase

; ebegin:  erase from home to cursor inclusive
; (cursor-home+1) bytes from home
ebegin	call	dumpst		; dump if status line
	rz
	lhld	cursor
	lded	home
	ana	a
	dsbc	d
	inx	h
	xchg
	lhld	home
	jmp	erase

; eend: erase from cursor to end of display inclusive
;  (scrsiz-cursor+home) bytes from cursor
eend	call	dumpst
	rz

	lhld	scrsiz
	lded	home
	dad	d
	lded	cursor
	ana	a
	dsbc	d
	xchg
	lhld	cursor
	jmp	erase

; eleft:  erase from left of line to cursor inclusive
;   col+1 bytes from (cursor-col)
eleft	lhld	cursor
	lded	column
	subhle
	mask8
	lded	column
	mvi	d,0
	inr	e
	jmp	erase

; eright:  erase from cursor to right end of line inclusive
;   (cpl-col) bytes from cursor
eright	lxi	h,column
	lda	cpl
	sub	m
	mov	e,a
	mvi	d,0
	lhld	cursor
	jmp	erase

; inschr:  insert a character
; move col...cpl-2  to  col+1...cpl-1
; ie from cursor to cursor+1 with (cpl-col-1) bytes
; do not change character at col.
; hl=cursor+cpl-column-2; de=cursor+cpl-column-1; bc=cpl-col-1
inschr	lxi	h,column
	lda	cpl
	sub	m
	dcr	a
	rz			; zero bytes
	mov	c,a
	mvi	b,0

	lhld	cursor
	lded	cpl
	addhle
	lded	column
	subhle
	dcx	h
	maskh8
	mov	d,h
	mov	e,l
	
	dcx	h
	maskh8

	lddr
	ret

; hinschr: insert a blank
hinschr	call	inschr
	mvi	a,space
	jmp	write

; insline:  insert line with cursor
;   ccr
;   move (scrsiz-cursor-cpl+home+1)  from home+scrsiz-1-cpl to home+scrsiz-1
insline	call	dumpst
	rz

	call	ccr

	lhld	scrsiz
	lded	home
	dad	d
	lded	cpl
	subhle
	lded	cursor
	ana	a
	dsbc	d
	inx	h
	mov	a,h
	ani	8191/256
	mov	b,a
	mov	c,l		; bc:=scrsiz+home-cursor-cpl+1
	ora	c		; check for zero
	jrz	insl0

	lhld	scrsiz
	lded	home
	dad	d
	dcx	h
	maskh8
	push	h

	lded	cpl
	subhle
	maskh8
	
	pop	d

	lddr

insl0	jmp	eline

; delline:  delete line with cursor, leave cursor at left, fill with spaces
; at bottom.
;  ccr
;   move (scrsiz-cursor-cpl+home+1)  from cursor+cpl to cursor
delline	call	dumpst
	rz

	call	ccr

	lhld	scrsiz
	lded	home
	dad	d
	lded	cpl
	subhle
	lded	cursor
	ana	a
	dsbc	d
	mov	a,h		; bc<8k
	ani	8191/256
	mov	b,a
	mov	c,l		; bc:=scrsiz+home-cursor-cpl

	ora	c
	jrz	dell0		; nothing to move

	lhld	cursor
	mask8
	push	h

	lded	cpl
	addhle
	mask8			; hl=cursor+cpl

	pop	d		; de=cursor

	ldir

; erase bottom line
; cpl from home + scrsiz-cpl 
dell0	lhld	home
	lded	scrsiz
	dad	d
	lded	cpl
	subhle
	mask8
	
	lded	cpl
	mvi	d,0
	jmp	erase

; delete character:
;  move cpl-column-1 from cursor+1 to cursor
delchr	lxi	h,column
	lda	cpl
	sub	m
	dcr	a
	mov	c,a
	mvi	b,0

	lhld	cursor
	mask8
	mov	d,h
	mov	e,l

	inx	h

; check for zero bytes
	mov	a,c
	ana	a
	jrz	delc0

	ldir

delc0	xchg
	mvi	a,space
	call	writehl
	ret
	
	page
;	*********************************
;	*				*
;	*      Cursor Functions         *
;	*				*
;	*********************************

write	lhld	cursor
writehl	push	h
; write a character to the screen:

; if graphics then map 60-7f to 00-1f
; if inverse video then set b7
; if insert mode then inschr
; store character
	lxi	h,dip3
	bit	2,m		; check for graphics bit
	jrz	wrnog
; graphics mode: if a>=60, subtract 60h
	cpi	60h
	jc	wrnog
	sui	60h
; check for inverse video
wrnog	bit	7,m
	jrz	wrnoi
	ori	80h		; turn on inverse video
wrnoi	bit	6,m		; check for insert mode
	jrz	wrnins
	push	psw
	call	inschr
	pop	psw
; put character on the screen
wrnins	pop	h
	mov	m,a
	ret


; cinc:  increment cursor position
; if col<>cpl-1
;    then col:=col+1 ; cursor := cursor + 1; exit
;    else if wraparound
;	then crlf ; exit
cinc	lxi	h,column
	lda	cpl
	dcr	a
	cmp	m
	jrz	cincels
; then advance column, cursor, exit
	inr	m
	lhld	cursor
	inx	h
	mask
	shld	cursor
	ret
; if wraparound, do ccrlf
cincels	lda	dip2
	bit	7,a		; check wrap-around
	rz			; do nothing
	jmp	ccrlf		; do crlf

; hlf: line feed with optional carriage return
hlf	call	clf
	lda	dip3
	bit	0,a
	rz

; ccr:  carriage return
; cursor := cursor-col
; col:=0
ccr	lhld	cursor
	lded	column
	subhle			; hl := hl - e
	mask
	shld	cursor
	xra	a
	sta	column
	ret

; hcr: carriage return with optional linefeed
hcr	call	ccr
	lda	dip1
	bit	7,a
	rz

; clf: line feed and scroll if at bottom of screen
; 
;  cursor := cursor + cpl
;  if line<>lps-1
; 	then line := line+1
;	else home := home + cpl
;	     sethome
;	     eline

clf	call	dumpst
	rz

	lhld	cursor		; advance cursor
	lded	cpl
	addhle
	mask
	shld	cursor
; check for bottom of screen
	lxi	h,line
	lda	lps
	cmp	m		; check for status line
	rz			; dont do nothing
	dcr	a
	cmp	m
	jrz	clfe		; else scroll

; just move down one line
	inr	m		; incr line
	ret
; else scroll
clfe	lhld	home
	lded	cpl
	addhle

	call	sethome
	jmp	eline		; erase line


; crlf: reverse line feed
;  cursor := cursor - cpl
;  if line<>0
;	then line := line - 1;
;	else home := home - cpl
;	     sethome
;	     eline
crlf	call	dumpst
	rz

	lhld	cursor
	lded	cpl
	subhle
	mask
	shld	cursor

	lxi	h,line
	xra	a
	cmp	m
	jrz	crlfels		; else scroll up
;
	dcr	m		; dcr line
	ret
; scroll up:
crlfels	lhld	home
	lded	cpl
	subhle
	call	sethome

	jmp	eline		; erase & return


; ccrlf
;   cr
;   lf
ccrlf	call	ccr
	jmp	clf

; cleft
; if col <> 0
;   then cdec
;
; cdec:
; if col <> 0 
;   then col := col - 1
;        cursor := cursor - 1;
cleft
cdec	lxi	h,column
	xra	a
	cmp	m
	rz
; dec col & cursor
	dcr	m
	
	lhld	cursor
	dcx	h
	mask
	shld	cursor
	ret	

; cright
; if col+1 <> cpl 
;	then cinc
cright	lxi	h,column
	lda	cpl
	dcr	a
	cmp	m
	rz
	jmp	cinc

; cup
; if line <> 0 
;	then rlf
cup	lda	line
	ana	a
	rz
	jmp	crlf

; cdown
; if line+1 <> lps
;	then clf
cdown	lxi	h,line
	lda	lps
	dcr	a
	cmp	m
	rz

	jmp	clf

; horizontal tab:
;   move cursor to a column that is a multiple of 8
ctab	lbcd	column		; find old location
	push	b
	call	cinc
	pop	b
	lda	column
	cmp	c
	rz			; quit if nothing happened
	ani	7
	jrnz	ctab
	ret

; cursor home
;   cursor:=home
;   line:=0
;   col:=0
; 
chome	lhld	home
	shld	cursor
	xra	a
	sta	line
	sta	column
	ret

; csav: save cursor position for later recall
csav	lda	column
	sta	stoc
	lda	line
	sta	stol
	ret

; cresto: restore cursor position
cresto	lbcd	stoc		; get c,l
	jmp	setxy

; caddr:  cursor addressing
;   fetch a line, column
caddr	call	fetchrx
	sui	space
	push	psw
	call	fetchrx
	sui	space
	mov	c,a
	pop	psw
	mov	b,a

; setxy:  set the cursor position given b=line, c=column
; cursor := home + cpl*line + column
; if line >= lps then line=statusline
setxy	lda	cpl
	cmp	c		; check column validity
	jrnc	setxok
	dcr	a
	mov	c,a

setxok
; check bounds of line specified
	lda	lps
	cmp	b
	jrnc	setyok
	mov	b,a		; make b=lps
setyok

	mov	a,c
	sta	column
	mov	a,b
	sta	line

; calculate new cursor position
	mvi	h,0
	mov	l,c		; hl:=column
	lded	home
	dad	d		; hl=column+home

	ana	a
	jrz	xyline0

	lded	cpl
	mvi	d,0
setxy1	dad	d
	djnz	setxy1

xyline0	mask
	shld	cursor
	ret

; report cursor address
crep	mvi	a,esc
	call	send

	mvi	a,'Y'
	call	send

	lda	line
	adi	space
	call	send
	
	lda	column
	adi	space
	call	send

	ret

; read cursor character
cread	lhld	cursor
	mov	a,m
	jmp	send

; graphic character display
graphic	call	fetchrx
	call	write
	jmp	cinc

	page
;	*********************************
;	*				*
;	*        Configuration          *
;	*				*
;	*********************************

; setcrtc:  set the crtc mode
setcrtc	call	fetchrx		; get mode:  A thru H
	sui	'A'
	rc
	ani	7
	mov	b,a
	lxi	h,dip2
	mov	a,m
	ani	11111000b
	ora	b
	mov	m,a

	call	statoff		; turn off the status line

	jmp	crtcmod		; setup crtc

; setup the baud rate generator
setbrg	call	fetchrx		; get a character
	sui	'@'		; make binary
	rc			; bad
	ani	15		; save only 4 bits
	mov	b,a
	lxi	h,dip1
	mov	a,m
	ani	0f0h		; rid of rate
	ora	b		; put in rate
	mov	m,a		; save new dip1
	call	setbaud		; make new rate
	ret

; set mode:  turn on or off certain flags
setmode	call	fetchrx
	lxi	h,modton	; mode table
	mvi	d,modtonl	; length
	jmp	goaway

; reset mode:
resmode	call	fetchrx
	lxi	h,modtoff	; off mode table
	mvi	d,modtofl
	jmp	goaway

; test routines:
;    1=print all characters on screen (including ctl & esc)
;    2=fill screen with test pattern
;    3=fill screen with character
;    4=modify crtc register

testmod	call	fetchrx
	lxi	h,testtab
	mvi	d,testlen
	jmp	goaway 

testtab	db	'1'		; display EVERY character received
	dw	tstprt		;   ( including control characters)
	db	'2'		; fill screen with test pattern
	dw	tstfill
	db	'3'		; fill screen with character
	dw	tstfilc		
	db	'4'		; send a value to a crtc port
	dw	tstcrtc

testlen	equ	($-testtab)/3

; lookup routine and execute
goaway	mvi	e,3
	call	search
	rc			; not found.
	inx	h
	mov	h,m
	mov	l,a
	pchl

; mode tables
modton	db	'0'		; blinking cursor  (default)
	dw	blnkon	
	db	'1'		; status line on 
	dw	staton
	db	'2'		; bell off
	dw	beloff
	db	'4'		; block mode cursor (default)
	dw	blkon
	db	'5'		; no cursor
	dw	cursoff
	db	'8'		; auto line-feed
	dw	alfon
	db	'9'		; auto carriage-return
	dw	acron
modtonl	equ	($-modton)/3

modtoff	db	'0'		; no blinking cursor
	dw	blnkoff
	db	'1'		; no status line (default)
	dw	statoff
	db	'2'		; bell works     (default)
	dw	belon
	db	'4'		; underscore cursor
	dw	blkoff
	db	'5'		; cursor enable  (default)
	dw	curson
	db	'8'		; auto lf off    (default)
	dw	alfoff
	db	'9'		; auto cr off    (default)
	dw	acroff
modtofl	equ	($-modtoff)/3

; modes on and off:

inson	turnon	dip3,6		; insert mode
	ret
insoff	turnoff	dip3,6
	ret
invon	turnon	dip3,7		; inverted video
	ret
invoff	turnoff	dip3,7
	ret
gron	turnon	dip3,2		; graphics
	ret
groff	turnoff	dip3,2
	ret
keyon	turnon	dip3,3		; keyboard lock on
	ret
keyoff	turnoff	dip3,3		; keyboard lock off
	ret
wrapon	turnon	dip2,7		; wraparound mode
	ret
wrapoff	turnoff	dip2,7
	ret
alfon	turnon	dip1,7		; auto line-feed
	ret
alfoff	turnoff	dip1,7
	ret
acron	turnon	dip3,0		; auto carriage-return
	ret
acroff	turnoff	dip3,0
	ret
belon	turnon	dip4,2		; bell enable
	ret
beloff	turnoff	dip4,2
	ret
alton	turnon	modcopy,3	; alternate chr font
	lda	modcopy
	out	modctl
	ret
altoff	turnoff	modcopy,3
	lda	modcopy
	out	modctl
	ret

blnkon	turnon	dip3,1		; blinking cursor
	jmp	cursmod
blnkoff	turnoff	dip3,1
	jmp	cursmod
blkon	turnon	dip4,1		; block mode cursor
	jmp	cursmod
blkoff	turnoff	dip4,1
	jmp	cursmod
curson	turnon	dip3,4		; cursor enable
	jmp	cursmod
cursoff	turnoff	dip3,4
	jmp	cursmod
curstog	lxi	h,dip3		; toggle cursor enable
	mvi	a,00010000b
	xra	m
	mov	m,a
	jmp	cursmod

staton	call	clrstat		; status line enable
	turnon	dip4,0
	jmp	statmod
statoff	turnoff	dip4,0
	jmp	statmod

; test routines:
;   print all characters
;   note:  the only way to exit this mode is to reset the terminal
tstprt	call	wrapon		; turn on wraparound
tstprt1	call	fetchrx
	call	write
	call	cinc
	jr	tstprt1

;  fill screen with garbage
tstfill	lxi	h,screen
	lxi	b,8192
tstf1	mov	m,l
	dcx	b
	inx	h
	mov	a,b
	ora	c
	jrnz	tstf1
	ret

;  fill screen with character
tstfilc	call	fetchrx
	mov	e,a
	lxi	h,screen
	lxi	b,8192
tstfc1	mov	m,e
	inx	h
	dcx	b
	mov	a,b
	ora	c
	jrnz	tstfc1
	ret

; tstcrtc:  send data to the crt controller
; ESC t 4 aa dd
; where aa is the port address in the crtc  (hex)
;	dd is the data to send the crtc     (hex)
; if aa=11H  then set lps
; if aa=12H  then set cpl
;
tstcrtc	call	hexbyte		; get a byte (address)
	push	psw
	call	hexbyte		; get a byte (data)
	mov	b,a		; save data
	pop	psw		; get addr

	cpi	17
	jrz	setlps
	jrnc	setcpl

	out	crtaddr
	mov	a,b
	out	crtdata
	ret

setcpl	mov	a,b
	sta	cpl
	jmp	setsiz

setlps	mov	a,b
	sta	lps

; set screen size:  scrsiz := cpl*lps
setsiz	lda	cpl
	mov	b,a
	lded	lps
	mvi	d,0
	lxi	h,0
multlp	dad	d
	djnz	multlp
	shld	scrsiz	
	ret

; hexbyte:  get a byte & return in a
hexbyte	call	hexnib
	rlc
	rlc
	rlc
	rlc
	ani	11110000b
	mov	c,a
	push	b
	call	hexnib
	pop	b
	ora	c
	ret

; hexnib:  get a nibble in hex
;   0000 = '0'
;   0001 = '1'
;   ...
;   1001 = '9'
;   1010 = ':'
;   1011 = ';'
;   1100 = '<'
;   1101 = '='
;   1110 = '>'
;   1111 = '?'
hexnib	call	fetchrx
	ani	0fh
	ret

	page
;	*********************************
;	*				*
;	*            Misc               *
;	*				*
;	*********************************

; ring bell
ring	lda	dip4
	bit	2,a
	rz			; bell disabled
	out	bell
	ret

; ding bell (short duration)
ding	lda	dip4
	bit	2,a
	rz			; bell off
	out	beep
	ret

	page
;	*********************************
;	*				*
;	*	  RAM buffers		*
;	*				*
;	*********************************

	org	ram

; buffers
rxfifo	ds	256		; 256 byte fifo for receive
txfifo	ds	16		; 16 byte fifo for transmit
txfsiz	equ	4		; 2**4 bytes
; pointers, etc

rambuff	equ	$		; start of flags and buffers, etc
rxinp	ds	2		; points to rxfifo store location
rxout	ds	2		; points to rxfifo fetch location
txinp	ds	2		; points to txfifo store location
txout	ds	2		; points to txfifo fetch location

cursor	ds	2		; absolute cursor position in memory
home	ds	2		; absolute position of first chr on screen
scrsiz	ds	2		; screen size
vsyn	ds	1		; vertical sync position for status line ena

cpl	ds	1		; number of columns per line
lps	ds	1		; number of lines per screen

column	ds	1		; current column
line	ds	1		; current line

stoc	ds	1		; saved column
stol	ds	1		; saved line

; dip1 and dip2 are ram copies of the dip switch positions at power up.

dip1	ds	1
;      bit init function

;	0123 	buad rate
;	45   	parity
;	6	x-ctl or hardware
;	7    	auto-lf

dip2	ds	1
;	012  	screen format
;	34   	emulation mode
;	5    	local
;	6    	local copy
;	7    	wrap around

; NOTE:  dip 3 and 4 are hypothetical only. (just used as software flags)

dip3	ds	1		; various flags
;	0   0	auto-cr
;	1   1   cursor blink
;	2   0	graphics
;	3   0	keyboard lock
;	4   1	cursor enabled
;	5   0	x-off sent
;	6   0	insert mode
;	7   0	inverse video
init3	equ	00010010b	; initial value for dip3

dip4	ds	1		; more flags
;	0   0	status line enabled
;	1   1   block cursor
;	2   1   bell enable
init4	equ	110b		; initial value for dip4

modcopy	ds	1		; data sent to uart output port
initmod	equ	0001b		; initial data sent to modem control port
;	0   1	dtr
;	1   0	rts
;	2   0 	led
;	3   0	chrgen (select font)

;keyboard buffer and flag:
kflag	ds	1		; zero ==> empty
kbuff	ds	1		; keyboard character
buffsiz	equ	$-rambuff

; stack space:
stksize	equ	ram+ramlen-$
	ds	stksize
stack	equ	$

	end
