;********************************************************
;*							*
;*	INTERRUPT SERVICE ROUTINES FOR KEYBOARD		*
;*	INPUT AND REAL-TIME CLOCK FUNCTIONS		*
;*							*
;********************************************************
;
;
;
;
KBDST:	LD	A,(FIFCNT)	;GET INPUT FIFO BYTECOUNT
	OR	A		;TEST IF EQUAL ZERO
	RET	Z		;EXIT WITH A=0 IF QUEUE IS EMPTY
	LD	A,255
	RET			;ELSE SET A=255 TO INDICATE DATA READY
;
;
;
KBDIN:	CALL	KBDST
	JR	Z,KBDIN		;LOOP UNTIL KEYBOARD INPUT READY
	PUSH	HL
	CALL	REMOVE		;GET CHARACTER FROM INPUT QUEUE
	POP	HL
	RET
;
;
;
;
;
STASH:	LD	C,A		;PUT CHARACTER IN C
	LD	A,(FIFSIZ)
	AND	00111111B
	LD	B,A		;PUT MAX FIFO SIZE IN B
	LD	HL,FIFCNT	;BUMP FIFO CHARACTER COUNT
	LD	A,(HL)
	INC	A
	CP	B
	RET	NC		;EXIT NOW IF FIFO IS FULL
	LD	(HL),A		; ELSE INCREMENT FIFO COUNT
	LD	HL,FIFIN	;POINT HL TO FIFO INPUT OFFSET
	CALL	INDEX
	LD	(HL),C		;STORE CHARACTER IN FIFO @ HL
	RET
;
;
;
;
REMOVE:	LD	HL,FIFCNT
	DEC	(HL)
	LD	HL,FIFOUT	;POINT HL TO FIFO OUTPUT OFFSET
INDEX:	LD	A,(HL)
	INC	A
	AND	00111111B	;INCREMENT FIFO POINTER
	LD	(HL),A		; MODULO 64 AND REPLACE
	LD	HL,FIFOŠ	ADD	A,L		;INDEX INTO FIFO BY OFFSET IN A
	LD	L,A
	LD	A,H
	ADC	A,0		;CARRY ADD OUT TO 16 BITS
	LD	H,A
	LD	A,(HL)
	RET
;
;
;
;
;
;
;	-- INTERRUPT SERVICE ROUTINE FOR PARALLEL KEYBOARD --
;
KEYSRV:	LD	(IRQSAV),SP	;SAVE USER STACK POINTER AND
	LD	SP,IRQSTK	; SWITCH TO LOCAL STACK
	PUSH	HL
	PUSH	DE
	PUSH	BC
	PUSH	AF		;SAVE MACHINE STATE
	IN	A,(KBD)		;READ KEYBOARD INPUT PORT
        BIT     7,A             
        JR      Z,KEYSRV1       ;USE TABEL IF BIT 7 IS SET
        LD      BC,KEYTABL      ;TABLE LENGTH
        LD      HL,KEYTAB       ;CONVERSION TABEL
        CPIR
        LD      A,(HL)
KEYSRV1:LD	HL,(KBDVEC)
	CALL	DISPATCH
	POP	AF
	POP	BC
	POP	DE
	POP	HL
	LD	SP,(IRQSAV)
RETI:	EI			;RE-ENABLE INTERRUPTS AND RETURN
	RETI
;
;
;
;	-- INTERRUPT SERVICE ROUTINE FOR ONE MILLISECOND TIMER --
;
MILLISEC:
	LD	(IRQSAV),SP	;SAVE USER STACK POINTER AND
	LD	SP,IRQSTK	; SWITCH TO LOCAL STACK
	PUSH	HL
	PUSH	DE
	PUSH	BC
	PUSH	AF
	LD	HL,(STPVEC)
	CALL	DISPATCH	;CALL MILLISECOND INTERRUPT ROUTINE
	POP	AF
	POP	BC
	POP	DE
	POP	HLŠ	LD	SP,(IRQSAV)
	EI
	RETI
;
;
;
DISPATCH:
	JP	(HL)
;
;
;
;	-- INTERRUPT SERVICE ROUTINE FOR CLOCK TICK INTERRUPT --
;
TIMER:
	LD	(IRQSAV),SP	;SAVE USER STACK POINTER AND
	LD	SP,IRQSTK	; SWITCH TO LOCAL STACK
	PUSH	HL
	PUSH	DE
	PUSH	BC
	PUSH	AF
	LD	HL,(TICKS)
	INC	HL		;BUMP FREE RUNNING CLOCK TICK COUNTER
	LD	(TICKS),HL
	LD	HL,(TIKVEC)
	CALL	DISPATCH	;DO EXTRA CLOCK TICK ACTIVITY
	LD	HL,TIKCNT
	DEC	(HL)		;DECREMENT CLOCK TICK PRE-SCALER
	JR	NZ,TIMER2	;JUMP IF CURRENT SECOND NOT PASSED

	LD	A,(NTICKS)	;ELSE RELOAD TICK COUNT AND DO
	LD	(HL),A		; VARIOUS ONCE-A-SECOND THINGS
	CALL	CLOCK		;UPDATE TIME-OF-DAY CLOCK
	CALL	DISKTEST	;DO BACKGROUND DISK ACTIVITY MONITOR

TIMER2:	POP	AF
	POP	BC
	POP	DE
	POP	HL
	LD	SP,(IRQSAV)
	EI			;RE-ENABLE INTERRUPTS AND RETURN
	RETI
;
;
;	-- INTERRUPT SERVICE ROUTINE FOR CRTC VSYNC INTERRUPT --
;
VSYNC:	LD	(IRQSAV),SP	;SAVE USER STACK POINTER AND
	LD	SP,IRQSTK	; SWITCH TO LOCAL STACK
	PUSH	HL
	PUSH	DE
	PUSH	BC
	PUSH	AF
	LD	A,(DSCOPY)
	PUSH	AF		;SAVE D/S CONTROL BYTE ON STACK
	LD	A,DYSTAT+OFF
	OUT	(PORT0),A	;SWITCH-ON STATIC MEMORY BANKŠ;
; This part is almost a dead out copy of the original.  I used
; de for my start reference to save a couple of bytes.  (vsync2
; gets it if we take the jump).
;
newcrsph:
	ld	a,(scroll)
	or	a
	ld	de,(start)	; both paths need this, so be efficient
	jr	z,vsync2	; if no scroll requested this time
;
	ld	a,12
	out	(crtadd),a	; select high start register
	ld	a,d		; new high start
	out	(crtdat),a
	ld	a,13
	out	(crtadd),a	; select low start register
	ld	a,e
	out	(crtdat),a
	ld	hl,(newlin)
	add	hl,de		; (start)+(newlin)
	res	3,h		; modulo 2048
	ld	bc,80
	push	de		; have to pass (start) to vsync2 this
				;  path too.
	call	CLRLINE
	pop	de		; recover (start)
;
; This part is new.  You can have this mod without re-burning
; a PROM, and thus have your cake and eat it too.  ZAPCSR is
; no longer needed, so you can take it out if you re-assemble.
;
; vsync2 receives de = (start)
;
vsync2:	
	ld	hl,(cursor)
	ld	a,15		; low order cursor position
	out	(crtadd),a
	ld	a,l
	out	(crtdat),a
	sub	e		; if cursor position is less than
	ld	a,14		;  start, we will bump cursor mod 2048
	out	(crtadd),a
	ld	a,h		; high order cursor position
	sbc	a,d
	ld	a,h		; tentative high order byte
	jr	nc,cursok	; if start <=curs
;
	set	3,a		; else bump cursor modulo 2048
;
cursok:
	out	(crtdat),a	; high order


	LD	A,00000011BŠ	OUT	(CTCA3),A	;TURN OFF VSYNC INTERRUPT
	XOR	A
	LD	(SCROLL),A	;RESET SCROLL-REQUEST FLAG
	LD	(MOVECS),A	;RESET CURSOR-MOVE-REQUEST FLAG

	POP	AF		;POP MEMORY CONTROL BYTE OFF STACK
	OUT	(PORT0),A	;SWITCH BACK TO PRE-INTERRUPT CONFIG
	POP	AF
	POP	BC
	POP	DE
	POP	HL
	LD	SP,(IRQSAV)
	EI			;RE-ENABLE INTERRUPTS AND RETURN
	RETI
;
;
;
;	POLLED MODE I/O ROUTINES FOR SIO CHANEL B
;
SIOST:	IN	A,(SIOCPB)	;GET SIO STATUS REGISTER
	AND	00000001B
	RET	Z		;ACC=0 IF NO DATA AVAILABLE
	LD	A,255
	RET
;
;
SIOIN:	CALL	SIOST		;TEST CONSOLE STATUS
	JR	Z,SIOIN		;LOOP UNTIL DATA IS
	IN	A,(SIODPB)	; READY AT SIO DATA PORT
	AND	01111111B
	RET
;
;
;
;	-- RX INTERRUPT SERVICE ROUTINE FOR SIO CONSOLE --
;

SIOINT:
	LD	(IRQSAV),SP
	LD	SP,IRQSTK
	PUSH	HL
	PUSH	DE
	PUSH	BC
	PUSH	AF
	LD	HL,SIOADR+1
	LD	C,(HL)		;LOAD C WITH SIO DATA PORT#
	IN	A,(C)
	AND	01111111B
	LD	HL,(RDAVEC)
	CALL	DISPATCH	;GO PROCESS SIO INPUT CHARACTER
	POP	AF
	POP	BC
	POP	DE
	POP	HL
	LD	SP,(IRQSAV)Š	EI
	RETI
;
;
;	-- RX ERROR INTERRUPT SERVICE ROUTINE FOR SIO CONSOLE --
;
SIOERR:
	LD	(IRQSAV),SP
	LD	SP,IRQSTK
	PUSH	AF
	PUSH	BC
	LD	A,(SIOADR)
	LD	C,A		;LOAD C WITH SIO CONTROL PORT#
	LD	A,00110000B
	OUT	(C),A		;RESET SIO EXTERNAL STATUS/INTERRUPTS
	LD	A,(SIOADR+1)
	LD	C,A		;NOW LOAD C WITH DATA PORT#
	IN	A,(C)		;INPUT AND DISCARD BAD CHARACTER
	POP	BC
	POP	AF
	EI
	RETI
;
;
;
;
;
SIOOUT:
	PUSH	BC
	PUSH	AF
	LD	A,(SIOADR)
	LD	C,A		;LOAD C WITH SIO STATUS PORT#
SIOUT1:	IN	A,(C)
	AND	00000100B	;TEST TBE STATUS BIT
	JR	Z,SIOUT1
	LD	A,(SIOADR+1)
	LD	C,A		;LOAD C WITH SIO DATA PORT# NOW
	POP	AF
	OUT	(C),A		;OUTPUT DATA TO SIO
	POP	BC
	RET
;
;
;
;
;
;
CLOCK:	LD	DE,TOD		;POINT DE TO START OF TIME-OF-DAY
	LD	HL,TODTAB	;POINT HL TO HH:MM:SS TABLE
	LD	B,4
CLOCK2:	LD	A,(DE)
	ADD	A,1		;INCREMENT TIME WITH ADD INSTRUCTION
	DAA			; SO DECIMAL ADJUST WILL WORK RIGHT
	CP	(HL)		;COMPARE IF HH/MM/SS ROLLED OVER
	JR	C,CLOCK3Š	XOR	A		;RESET TO ZERO IF ROLL OVER
CLOCK3:	LD	(DE),A		;STORE UPDATED TIME DATA
	RET	C		;EXIT IF NO MORE NEEDS TO BE DONE
	INC	HL
	INC	DE		;ELSE POINT TO NEXT DATA & CONSTANT
	DJNZ	CLOCK2
CLOCK4:	RET

TODTAB:	DEFB	60H		;60 SECONDS/MINUTE
	DEFB	60H		;60 MINUTES/HOUR
	DEFB	24H		;24 HOURS/DAY
	DEFB	99H		;OVERFLOW TO DAYS
;
;
KEYTAB: DB      0C3H,0D         ;OLD VALUE - NEW VALUE
        DB      3FH
KEYTABL EQU     $-KEYTAB-1      ;CALCULATE LENGHT OF TABLE
;
