****************************************************************************
*(Amiga)	KEYBOARD.S	Keyboard interrupt handler
****************************************************************************

	INCLUDE	"c:\headers.s\amiga\hardware\intbits.i"
	INCLUDE	"c:\headers.s\amiga\hardware\custom.i"
	INCLUDE	"c:\headers.s\amiga\hardware\cia.i"

CUSTOM	EQU	$dff000	hardware addresses
CIAA	EQU	$bfe001

	OFFSET	0	buffer offsets
head	DS.W	1
tail	DS.W	1
size	DS.W	1
buffer	DS.B	1

	TEXT
	XDEF	_KeyServer
	XREF	_scancode_table

_KeyServer	movem.l	d0-d7/a0-a6,-(sp)
	lea	CUSTOM,a6
	move.w	intreqr(a6),d7
	and.w	intenar(a6),d7
*              -------------------------------------------------------------
test_ports	btst.l	#INTB_PORTS,d7
	beq	exit
*---------------------------------------------------------------------------
	lea	CIAA,a0
	move.b	ciaicr(a0),d6		interrupt control register
	move.b	ciacra(a0),d4		control register a
*              -------------------------------------------------------------
test_irq	btst.l	#CIAICRB_IR,d6
	beq	exit		test for interrupt request
*              -------------------------------------------------------------
test_sp	btst.l	#CIAICRB_SP,d6		test for SP interrupt
	beq.s	test_ta
	btst.l	#CIACRAB_SPMODE,d4	test for sp mode
	bne.s	test_ta		ignore if in output mode
	bra.s	get_keycode
*              -------------------------------------------------------------
test_ta	btst.l	#CIAICRB_TA,d6		test for TA interrupt
	bne.s	set_inputmode
*              -------------------------------------------------------------
	bra	exit
*---------------------------------------------------------------------------
set_inputmode	move.b	#%00000000,ciacra(a0)	set sp input mode
	move.b	#%00000001,ciaicr(a0)	disable TA interrupts
	move.b	#%10001000,ciaicr(a0)	enable SP interrupt
	bra	exit
*---------------------------------------------------------------------------
get_keycode	move.b	ciasdr(a0),d0			keycode
	ror.b	#1,d0			restore bit 7
	not.b	d0			now amiga keycode
*              -------------------------------------------------------------
	move.b	d0,d1			store copy of keycode
	bge.s	check_legal
	sub.b	#$80,d0			downstroke equivalent
*              -------------------------------------------------------------
check_legal	cmp.b	#$67,d0			legal value ?
	bhi.s	handshake			no -ignore
*              -------------------------------------------------------------
get_scancode	lea	_scancode_table,a1
	ext.w	d0
	move.b	(a1,d0.w),d0			get independant code
	bmi.s	handshake			unsupported key -ignore
	ext.w	d0
*              -------------------------------------------------------------
	lea	_key_status,a1			update key status
	tst.b	d1
	bpl.s	downstroke
upstroke	clr.b	0(a1,d0.w)
	bra.s	handshake
downstroke	move.b	#1,0(a1,d0.w)
*              -------------------------------------------------------------
store_scancode	lea	_i_key_buf,a1
	move.w	head(a1),d1			head
	move.w	tail(a1),d2			tail
	sub.w	d1,d2			tail-head
	bge.s	.positive
.negative	add.w	size(a1),d2
.positive	subq.w	#1,d2
	beq.s	handshake			buffer full
	move.b	d0,buffer(a1,d1.w)		put output byte
	addq.w	#1,d1			increment head
	cmp.w	size(a1),d1			wrap around ?
	blt.s	.savehead
	sub.w	size(a1),d1
.savehead	move.w	d1,head(a1)
*---------------------------------------------------------------------------
handshake	move.b	#%01001000,ciacra(a0)	spmode=out, ta=oneshot
	move.b	#%00001000,ciaicr(a0)	disable SP interrupts
	move.b	#%10000001,ciaicr(a0)	enable TA interrupts
	move.b	#0,ciatalo(a0)			setup timer A
	move.b	#4,ciatahi(a0)
*---------------------------------------------------------------------------
exit	move.w	#INTF_PORTS,intreq(a6)	reset request bit
	movem.l	(sp)+,d0-d7/a0-a6
	rte

_i_key_buf	DC.W	0,0,20
	DS.B	20

_key_status	DS.B	$62

	END
