.SBTTL	65816 version - Ted Medin & Mark Johnson

;	Version 1.0

;	Based on the KERMIT Protocol.

;	$Header: appgs.m65,v 1.5 89/01/30 11:39:24 medin Locked $
.SBTTL	Define start address for assembly

       .=$1003			; Start assembly at hex 1003

debug	=	1		;[1.4] debug flag - when 0 will not add debug code

.SBTTL	Revision History

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

; $Log:	appgs.m65,v $
;Revision 1.5  89/01/30  11:39:24  medin
; Version 1.4 add drop dtr and correct some debug problems.

;Revision 1.4  88/01/15  08:43:21  medin
;New origin for 3.81



; DONT FORGET TO UPDATE THE VERSION

;
;
;	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.3] end of this routine
timect	.blkb	1	;[1.4] 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.2]wait:	.blkb	3	; wait routine-a reg contains milliseconds
wait:	.blkb	3	; wait routine-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

	.=$7b00	; place to start com card assembly
start	=	.		;need a label at begining
true	=	1		; true is non zero
false	=	0		; but not false
irqsva	=	$45	;place dos saves a reg
hctrlq	=	$91	;^Q with high bit on
hctrls	=	$93	;^S "
cr	=	$d	;^M carrage rtn
ctrlq	=	$11	;[59] ^Q
ctrls	=	$13	;[59] ^S
dirq	=	$3fe	; interupt address
sscstp	=	$5f8	; +slot,bit 7 on turns off commands to ssc
comnd	=	1	; command to start with
prntax	=	$f941	; print hex bytes in a & x
prbyte	=	$fdda	; print hex byte in a
herld	nasc	<//GS SERIAL PORT V1.5> 1	;[1.1]tell who we are
bad	nasc	<*****ERROR***** COM ROUTINES ASSEMBLED TOO LOW IN MEMORY> 1
statms	nasc	<<- STATUS ERROR ON COM CALL FROM - > 1
temp	.byte		;[1.1] index to init array
binita	.byte	comnd,'F,' ,'D		;[1.1] disable keyboard
	.byte	comnd,'0,'D		;[1.1] 8 data bits 1 stop bit
	.byte	comnd,'0,'P		;[1.1] no parity
	.byte	comnd,'B,'E		;[1.1] enable buffering
	.byte	comnd,'C,'D		;[1.1] disable line feed after cr
;[1.5]	.byte	comnd,'X,'D		;[1.1] disable xon/xoff
	.byte	comnd,'L,'D		;[1.1] disable auto line feed
	.byte	comnd,'E,'D		;[1.1] disable echo to screen
	.byte	comnd,'M,'D		;[1.1] disable mask line feed
	.byte	comnd,'A,'D		;[1.1] disable basic tabs
	.byte	comnd,'Z,0		;[1.1] the last in the list
bbrka	.byte	comnd,'T		;[1.1] go to terminal mode
	.byte	comnd,'S		;[1.1] now for the break
	.byte	comnd,'Q		;[1.1] now exit terminal mode
	.byte	comnd,'Z,0		;[1.1] last of the list
saveac	.byte		; next input ch
gmb	.byte	3	; # parameters
gmbc	.byte	0	; command 0=read 1=write $14=flush-in $15=flush-out
gmbr	.word		; result
gmbd	.byte		; 7-0 bit image
	.byte		; 15-8
gmbz	.byte		; 23-16
	.byte		; 31-24

;
;	Apple //gs  serial interface support
;

prerst	cpx	#0		; first see if there is an error
	beq	prersa		; no
;[1.4]	jsr	prbyte		;
preree				;[1.4]
	jsr	prntax		;[1.4]
	ldx	#statms\	; tell what we got
	ldy	#statms^
	jsr	prstr	
	pla			; get low byte of call address
	tax
	pla			; and the high byte
	tay
	pha
	txa
	pha			; now it back correct
	tya			; put the high byte in a
	jsr	prntax		; and print them
	jmp	prcrlf		; on a line by itself, & let prcrlf do the rts
prersa	rts
alowcm
	sei			; lock out interupts
	lda	#3		; 3 for param count
	sta	gmb
	lda	#0
	sta	gmbc		; make the command get
	jsr	dmb		; send the request
	lda	gmbz		; get the command ignore byte
	and	#$7f		; make the bit 0
	sta	gmbz		; and set it in the list
	lda	gmbd		; now turn off dtr/dsr
;[1.4]	and	#$fb
	ora	#4		;[1.4] turn on dtr/dsr handshake
	and	#$df		;[1.5] turn off xon/xoff handshake
	bit	flowfg		;[1.5] see if we should xon/xoff
	bpl	alow3		;[1.5] no
	ora	#$20		;[1.5] tell firmware abt xon/xoff
	and	#$fb		;[1.5] turn off dtr
alow3				;[1.5]
	sta	gmbd
	lda	#1		; make the command set
	sta	gmbc
	jsr	dmb
	cli			; now allow interupts
	rts
;[1.1]flush
;[1.1]	sei			; lock out interupts
;[1.1]	lda	#2		; 2 for param count
;[1.1]	sta	gmb
;[1.1]	lda	#$14		; flush input queue
;[1.1]	sta	gmbc
;[1.1]	jsr	dmb		; do it
;[1.1]	lda	#$15		; flush output queue
;[1.1]	sta	gmbc
;[1.1]	jsr	dmb	
;[1.1]	cli			; now allow interupts
;[1.1]	rts			; thats all folks
dmb	
	.byte	$8b		; should be PHB (push bank on stack)
	ply			; and put it in y
	ldx	#gmb^		; middle of the 3 bytes of address
	lda	#gmb\		; and low
cnsta5	jsr	$c000		; call the extended interface
	.ifne	debug	;[1.4] conditional assembly
; till apple fixes the bug	bcc	dmbr		;[1.4] was it good, yes
	lda	gmbr+1		;[1.4] see if we have an error
	ora	gmbr		;[1.4]
	beq	dmbr		;[1.4] nope
	lda	gmbr+1		;[1.4] should be something here
	ldx	gmbr		;[1.4] ***** debug hope this is the right byte
	jmp	preree		;[1.4] tattle and let it do the rts
	.endc		;[1.4]
dmbr	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	prersa		; already initialized
	lda	kersli		; first generate the $cn
	lsr	a		;
	lsr	a		;
	lsr	a		;
	lsr	a		;
	ora	#$c0		; finally $cn
	sta	cnstat+2	; this sets up the high byte to $cn
	sta	cnsta1+2	;
	sta	cnsta2+2	;
	sta	cnsta3+2	;
	sta	cnsta4+2	;
	sta	tl2cp1+2	;
	sta	tl2gc1+2	;
	sta	tl2pc1+2	;
	sta	tl2pc2+2	;
	sta	cnsta5+2
	sta	cnsta0+2
cnsta0	lda	$c012		; the extended offset
	sta	cnsta5+1	; now the jsr should all be correct
	jsr	alowcm		; allow commands
cnstat	lda	$c00d		; get the init offset from $cn0d
	sta	cnsta1+1	; now set the low byte address
	ldy	kersli		; y=$n0
	ldx	cnsta1+2	; x=$cn
cnsta1	jsr	$c000		; init
	jsr	prerst		; check for errors
cnsta2	lda	$c00e		; get the read offset
	sta	tl2gc1+1	; and set up the get ch call
cnsta3	lda	$c00f		; get the write offset
	sta	tl2pc1+1	; and set up the put ch call
cnsta4	lda	$c010		; get the status offset
	sta	tl2cp1+1	; and set up the read status call
	sta	tl2pc2+1	; and set up the write status call
;[1.1]	lda	#comnd
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'F		;  no keyboard
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#' 
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'D
;[1.1]	jsr	finis
	lda	#comnd		; start of the command string
	jsr	tl2ppf		; send it
	lda	sscdbd		; first the baud
	cmp	#9		; hex and dec 
	bcc	tl2inz
	pha			; going to need this
	lda	#'1		; power of 10 sigh
	jsr	tl2ppf
	pla
	sec			; now take away the 10
	sbc	#10
tl2inz	clc			; make it ascii
	adc	#$30		; that should do it
	jsr	tl2ppf
	lda	#'B		; that says baud
;[1.1]	jsr	finis
	jsr	tl2ppf		;[1.1] dont send cr
;[1.1]	lda	#comnd
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'0		; 8 data bits 1 stop bit
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'D
;[1.1]	jsr	finis
;[1.1]	lda	#comnd
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'0		; how about no parity
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'P
;[1.1]	jsr	finis
;[1.1]	lda	#comnd
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'B		; enable buffering
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'E
;[1.1]	jsr	finis
;[1.1]	lda	#comnd
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'C		; disable line formating
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'D
;[1.1]	jsr	finis
;[1.1]	lda	#comnd
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'X		; disable xon xoff
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'D
;[1.1]	jsr	finis
;[1.1]	lda	#comnd
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'L		; disable auto line feed
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'D
;[1.1]	jsr	finis
;[1.1]	lda	#comnd
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'E		; disable echo to screen
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'D
;[1.1]	jsr	finis
;[1.1]	lda	#comnd
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'M		; disable mask line feed
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'D
;[1.1]	jsr	finis
;[1.1]	lda	#comnd
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'A		; disable basic tabs
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'D
;[1.1]	jsr	finis
;[1.1]	jsr	flush		; now that baud is set flush previous
;[1.1]	lda	#comnd
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'Z		; no more commands, accept all chs
;[1.1]	jsr	finis
	stz	temp		;[1.1] starting index
tl2iny	ldx	temp		;[1.1]
	lda	binita,x	;[1.1] get initialization ch
	beq	tl2inx		;[1.1] are we thru? yes
	jsr	tl2ppf		;[1.1] no send the ch
	inc	temp		;[1.1] ready for next
	jmp	tl2iny		;[1.1]
tl2inx				;[1.1] thats all
	lda	#true
	rts			; say its ok
;[1.1]finis	jsr	tl2ppf		; send a out
;[1.1]	lda	#cr		; and terminate the command
;[1.1]	jmp	tl2ppf		; let tl2ppc do the rtn also

tl2cp:	ldx	tl2cp1+2	; x needs $cn
	ldy	kersli		; y needs $n0
	lda	#1		; input ready?
tl2cp1	jsr	$c000		; status call
	bcs	tl2cp5		; *********** debug
	jsr	prerst		; *********** debug
tl2cp2	lda	#false		; ready for no
	rts
tl2cp5	ldx	tl2gc1+2	; x needs $cn
	ldy	kersli		; y needs $n0
tl2gc1	jsr	$c000		; get a ch, tl2cp said we had one
	jsr	prerst		; check for error, let prerst do the rts
	sta	saveac		; save the a for tl2gpc
	ldy	flowfg	;[57] are we flow controll
	bpl	tl2cp6	;[57] no dont worry about stopping output
	and	#$7f	;[59] ignore parity
	cmp	#ctrlq	;[59] do we have a continue
	bne	tl2in2	;[59] no
	lda	#$bf	;[59] yes, now turn on flow
	and	flowfg	;[59]
	sta 	flowfg	;[59]
	jmp	tl2cp2	;[59] and carry on
tl2in2	cmp	#ctrls	;[59] do we have a stop?
	bne	tl2cp6	;[59]
	lda	#$40	;[59] yes tell all
	ora	flowfg	;[59] would you believe the remote
	sta	flowfg	;[59] has asked us to stop!
	jmp	tl2cp2	; return false
tl2cp6	lda	#true		; hooray we have one ready
tl2cp3	rts			;return with false(0) or true(non 0)

tl2gpc:	lda	saveac		
	rts			
tl2ppc:	pha			; Hold the byte to send
tl2pc0	bit	flowfg		; is output on hold?
	bvc	tl2pcl		; no
	jsr	tl2cp		; yes wait for ^q
	jmp	tl2pc0		; throw away everything else
tl2pcl	ldx	tl2pc2+2	; x needs $cn
	ldy	kersli		; y needs $n0
	lda	#0		; ask about outputing a ch
tl2pc2	jsr	$c000		; status call
	bcs	tl2pc7		; *********** debug
	jsr	prerst		; *********** debug
	jmp	tl2pcl		; ready?,no try again
tl2pc7	pla			; get the ch back
tl2ppf	ldx	tl2pc1+2	; $cn again
	ldy	kersli		; $n0 again
tl2pc1	jsr	$c000		; put the ch
	jmp	prerst		; let prerst do the rts

tl2exi:
	lda	#0	;tell we did this
	sta	kerins		;just in case init gets called
	lda	#true		; say its ok
exit9:	rts

tl2drp				;[1.4]
	sei			;[1.4] lock out interupts
	lda	#3		;[1.4] 3 for param count
	sta	gmb		;[1.4]
	lda	#$a		;[1.4] get dtr stuff
	sta	gmbc		;[1.4] make the command get
	jsr	dmb		;[1.4] send the request
	lda	gmbd		;[1.4] now turn off dtr/dsr
	ora	#$80		;[1.4]
	sta	gmbd		;[1.4]
	lda	#$b		;[1.4] set dtr
	sta	gmbc		;[1.4]
	jsr	dmb		;[1.4]
	cli			;[1.4] now allow interupts
	lda	#true		;[1.4] hope hope
	rts			;[1.4]
tl2cmd:			;find out what command
;[1.4]	beq	tl2rts	;its drop line and we cant
	beq	tl2drp	;[1.4] its drop line and we shall see
	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	#false	;unknown command
tl2rts:	rts		;que passo ? return false(0)
tl2sac:
	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	#0	; force an initialization
	sta	kerins	; that will reset baud
	lda	#true		;
	rts		;return 
break:
	jsr	alowcm		; allow commands again
;[1.1]	lda	#comnd		; start of command string
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'T		; terminal mode
;[1.1]	jsr	finis
;[1.1]	lda	#comnd		; start of command string
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'S		; break
;[1.1]	jsr	finis
;[1.1]	lda	#comnd		; start of command string
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'Q		; exit terminal mode
;[1.1]	jsr	finis
;[1.1]	lda	#comnd		; start of command string
;[1.1]	jsr	tl2ppf
;[1.1]	lda	#'Z		; now shut off looking
;[1.1]	jsr	finis
	stz	temp		;[1.1]
break2	ldx	temp		;[1.1] index into break array
	lda	bbrka,x		;[1.1] next ch
	beq	break5		;[1.1] are we thru? yes
	jsr	tl2ppf		;[1.1] no send the ch to rom
	inc	temp		;[1.1] ready for next
	jmp	break2		;[1.1]
break5				;[1.1] thats all	
	lda	#true		; and tell we did it ok
	rts
endcom			;[1.3]
