.TITLE	KERMIT-65 Mountain Hardware CPS card
.SBTTL	6502 version - Alan Thomson

;	Version 1.0
;	Supports only the serial part of the card
;	Does not use interrupts

;	Based on the KERMIT Protocol.

;	$Header: appcps.m65,v 1.5 90/10/15 14:19:59 medin Locked $
.SBTTL	Define start address for assembly

       .=$1003			; Start assembly at hex 1003

.SBTTL	Revision History

;
; Edit #	Description
; ------	-----------
;

;$Log:	appcps.m65,v $
Revision 1.5  90/10/15  14:19:59  medin
new org for 3.87 of $7f00
version 1.4

;Revision 1.4  88/12/22  09:25:02  medin
;use the time constant for the wait routine

;Revision 1.3  88/01/15  08:42:03  medin
;New origin for 3.81

;Revision 1.2  87/06/29  11:02:31  medin
; Change wait rtn to use apple rom rtn, change org for 3.78

;Revision 1.1  87/06/29  09:26:27  medin
;Initial revision

;
;
;	Vector for com cards starts here 
;		location $1003 for data
;		location $1020 for routine jumps
;		location $1040 for main routines
;
sscdbd:	.blkb	1  ;contains baud index(ala super serial card) used by init
			;		6 - 300 baud
			;		7 - 600 
			;		etc
	.blkb	1	
crdnam:	.word	herld	; null terminated string of who we are
kersli:	.blkb	1	; com slot $n0
kerins:	.blkb	1	; force initialization flag-when 0
endker:	.blkb	2	; address of end of main kermit
flowfg:	.blkb	1	; flow flag for xon/xoff controll b7=1 yes
tl0end	.word	endcom	;[1.2] end of this routine
timect	.blkb	1	;[1.3] 1 ms delay via rom wait rtn
	.=$1020		; future expansion
tlinit:	jmp	tl2int		; initialize com card
tl0cmd:	jmp	tl2cmd		; command for ACIA in A
			;
			; 0 - hang up 
			; $0b - set baud
			; $0c - set break on the line
			; $91 - xon
			; $93 - xoff
			;
			; routine will return false(0) if unable
tl0cp:	jmp	tl2cp		; check for input ch ready-0 false
tl0gpc:	jmp	tl2gpc		; get input ch
tl0ppc:	jmp	tl2ppc		; put output character
tl0exi:	jmp	tl2exi		; reset card and restore initialized
	.=$1040		; futures
;[1.1]wait:	.blkb	3	; wait routine-a reg contains milliseconds
wait:	.blkb	3	;[1.1] wait routine-use apple rom rtn 220=125ms,206=108ms,25=2ms
prstr:	.blkb	3	; print string x=lsb,y=msb x&y->null terminated string
rdkey:	.blkb	3	; read keyboard
prcrlf:	.blkb	3	; print cr and lf
telcnc:	.blkb	3	; check for keyboard character
telspa:	.blkb	3	; set character parity

;[1.1]	.=$6c00	; place to start com card assembly
	.=$7f00	;[1.4][1.2] place to start com card assembly
start	=	.		;need a label at begining
data	=	$C0FA		;data port
mode	=	$C0FA		;mode reg
status	=	$C0FB		;status port
command	=	$C0FB		;command port
control	=	$C0FE		;control port
initbd	=	$35	; Baud init (300 baud)
framing	=	$4E	; Framing init (8bit, no par. , 1 stop, 16x)
rcvst	=	$C2	; status bit for input ready
xmitst	=	$C1	; status for output ready
xmitcmd	=	$27	; transmit command
pinptr:	.byte		; input buffer pointer
inptr:	.byte		; input buffer pointer for get
poutpt	.byte		; output buffer pointer
outptr	.byte		;   "       "     "    for put
kwrk01	.byte		;[1.3]
scrlo	=	$0	; sets control bit low
scrhi	=	$80	; sets control bit high
irqsva	=	$45	;place dos saves a reg
hctrlq	=	$91	;^Q with high bit on
hctrls	=	$93	;^S "
ctrlq	=	$11	; ^Q
ctrls	=	$13	; ^S
dirq	=	$3fe	; interupt address
herld	nasc	<MOUNTAIN HARDWARE CPS V1.4> 1	;tell who we are
bad	nasc	<*****ERROR***** COM ROUTINES ASSEMBLED TOO LOW IN MEMORY> 1

;
;	CPS serial interface support
;
chkwst	lda	#xmitcmd	;Wait for vacant transmit reg.
	jsr	setcmd		;set transmit command
chk1	lda	status		;get status reg
	and	#xmitst		;mask unwanted bits
	cmp	#xmitst		;is transmit reg clear?
	bne	chk1		;no it isn't, go back
	rts			;yes it is 


setcmd	pha			;save acc
	lda	#scrhi		;set bit
v1	sta	control		;set control for command access
	pla			;recover acc
v2	sta	command		;write command
	lda	#scrlo		;unset bit
v3	sta	control		;reset control reg
	rts


tl2int:
	lda	#start^
	cmp	endker+1	;are we loaded above main
	beq	dontno		;cant tell yet
	bcc	trble		;yes we are in trouble
	bcs	setnm		;ok 
dontno	lda	#start\		;well lets check 16 bits
	cmp	endker
	beq	setnm		;whee just exactly right
	bcs	setnm		;ok
trble	ldx	#bad\		;got to tell someone
	ldy	#bad^
	jsr	prstr		;print the message
	jsr	prcrlf		;and terminate it properly
setnm:
	lda	kerins
	bne	tl2prr	; already initialized
	lda	#0	; clear pointers etc
	sta	pinptr	; buffer starts at 0
	sta	inptr	; buffer starts at 0
	sta	poutpt	;    "
	sta	outptr	;    "
	lda	kersli	;now for the slot $n0
	lsr	a	;rotate acc 4bits
	lsr	a
	lsr	a
	lsr	a
	and	#$0f	;isolate bottom bits
	ora	#$c0	;create address
	jsr	setslot	;and store in relevant locs
	lda	#scrhi	;set bit
v4	sta	control	;set control for mode access
	lda	#framing
v5	sta	mode	;write framing
	lda	sscdbd	;get baud code
	cmp	#$0a	;is it 9 or less?
	bmi	baudx	;yes it is
	sec		;no it isnt
	bcs	baudy	;always taken
baudx	clc
baudy	lda	#initbd	;get baud initialisation
	and	#$f0	;drop baud
	ora	sscdbd	;add new baud
	sbc	#$0	;reduce by 1 if baud code <=9
v6	sta	mode	;set baud rate
	lda	#scrlo	;unset bit
v7	sta	control	;reset control
	lda	#xmitcmd	;set for transmit
	jsr	setcmd	;and set
	lda	#$01
	sta	kerins	;set init done reg
tl2prr	rts		;return

tl2cp:	lda 	status		; Try for a character
	and	#rcvst		; mask out bits
	cmp	#rcvst		; is receive reg full?
	bne	tl2cp7		; no we dont have a ch
v8	lda	data		; yes get ch
	ldy	pinptr		; where to put it in buf
	sta	inbuf,y		; save it
	inc	pinptr		; ready for next ch
	bit	flowfg		; how about flow control
	bpl	tl2cp7		; no
	lda	inbuf,y		; get input ch
	and	#$7f		; drop parity etc
;	bvc	tl2cp4		; yes,how about ^S received?, no
	cmp	#ctrlq		; is this continue(start up outputing)
	bne	tl2cp4		; no, check for ^S
	lda	flowfg		; tattle about the continue
	and	#$bf		; 
	sta	flowfg		; 
	dec	pinptr		; forget about this character
tl2cp2	ldy	outptr		; see if any to output
	cpy	poutpt		; well?
	beq	tl2cp7		; no more we have put all
tl2cp3	jsr	chkwst		; check status for output
	lda	outbuf,y	; output ch
v9	sta	data		; bye
	inc	outptr		; ready for next
	jmp	tl2cp2		; 
tl2cp4	cmp	#ctrls		; is this stop?
	bne	tl2cp7		; no
	lda	#$40		; yes, tattle
	ora	flowfg		; 
	sta	flowfg		; now everyone knows
	dec	pinptr		; forget about the ^S character
tl2cp7:
	lda	pinptr
	cmp	inptr
	rts			;return with false(0) or true(non 0)

tl2gpc:	ldx	inptr		; get where it is in buf
	lda	inbuf,x		; get the ch
	inc	inptr		; ready for next get
tl2rtc:	rts			;	and return

tl2ppc:	pha			; Hold the byte to send
tl2pp1:	lda	#xmitcmd	; load command
	jsr	setcmd		; send it
v10	lda	status		; Get the status byte
	and	#xmitst		; Isolate the bits we want
	cmp	#xmitst		;is it empty
	bne	tl2pp2		; Transmit register is NOT empty, try again
	bit	flowfg		; flow control?
	bpl	tl2pp0		; no
	bvc	tl2pp0		; should we stop outputing?,no
	ldy	poutpt		; yes, save this ch in buffer
	pla			; 
	sta	outbuf,y	; 
	inc	poutpt		; tell how many
	rts			; thats all
tl2pp0				; 
	pla			; Fetch the data byte off the stack
v11	sta	data		; Stuff it at the proper loc to send it
	rts			;	and return
tl2pp2:	jsr	tl2cp		; see if there is an input ch
	jmp	tl2pp1		;and try again

tl2exi:
	lda	#0		;tell we did this
	sta	kerins		;just in case init gets called
exit9:	rts
tl2cmd:			;find out what command
	beq	tl2rts	;its drop line and we cant
	cmp	#$0c
	beq	break	;its a break command
	cmp	#$0b
	beq	baud   	;its a set baud command
	cmp	#hctrlq
	beq	tl2sac	;its a xon command
	cmp	#hctrls
	beq	tl2sac	;its a xoff command
tl2fls:	lda	#0	;unknown command
tl2rts:	rts		;que passo ? return false(0)
tl2sac:	ldx	flowfg	;do we have flow control
	bpl	tl2fls	;no return false
	and	#$7f	;drop high bit and send the ch
	jsr	telspa	;set parity
	jsr	tl2ppc	;output the ch
	lda	#1	;set true return
	rts
baud:	lda	#scrhi	;set bit
v12	sta	control	;set control for mode access
	lda	#framing
v13	sta	mode	;write framing
	lda	sscdbd	;get baud code
	cmp	#$0a	;is it 9 or less?
	bmi	baudx1	;yes it is
	sec		;no it isnt
	bcs	baudy1	;always taken
baudx1	clc
baudy1	lda	#initbd	;get baud initialisation
	and	#$f0	;drop baud
	ora	sscdbd	;add new baud
	sbc	#$0	;reduce by 1 if baud code <=9
v14	sta	mode	;set baud rate
	lda	#scrlo	;unset bit
v15	sta	control	;reset control
	lda	#xmitcmd
	jsr	setcmd	;set for transmit
	lda	#xmitst
	rts		;return true(non 0)
break:
	lda	#scrhi		; set bit
v16	sta	control		; select command reg
v17	lda	command		; get current command
	pha			;
	lda	#$08		;
v18	sta	command		; start the break
;[1.1]	lda	#233		; for 233 millseconds
;[1.1]	jsr	wait		; the y reg is not clobered
;[1.3]	lda	#220		;[1.1] 125ms
	lda	#233		;[1.3] 233 ms
	sta	kwrk01		;[1.3] 1 ms at a time
break3	lda	timect		;[1.3]
	jsr	wait		;[1.1]
	dec	kwrk01		;[1.3]
	bne	break3		;[1.3]
;	lda	#206		;[1.1] 108ms
;	jsr	wait		;[1.1] for a grand total of 233ms
	pla			; restore command
v19	sta	command		; rewrite
	lda	#scrlo		; unset bit
v20	sta	control		; do it
	lda	#1		;return true
	rts
;
setslot	sta	tl2cp+2		;Stores correct ioslot in the various
	sta	chk1+2		;io instructions
	sta	v1+2
	sta	v2+2
	sta	v3+2
	sta	v4+2
	sta	v5+2
	sta	v6+2
	sta	v7+2
	sta	v8+2
	sta	v9+2
	sta	v10+2
	sta	v11+2
	sta	v12+2
	sta	v13+2
	sta	v14+2
	sta	v15+2
	sta	v16+2
	sta	v17+2
	sta	v18+2
	sta	v19+2
	sta	v20+2
	rts

inbuf	.blkb	256		;input buffer
outbuf	.blkb	256		;output  "
endcom			;[1.2]
