Up one Vic 20 network - software by Lee Davison Up to top

Interrupts

Without setting about the Vic with a screwdriver there is no way to change the lowest level handling of the Vic interrupts, so some of this code is to deal with the way interrupts are handled by the kernal.

Before the interrupts can be used the three vectors for IRQ, NMI and BRK handling need to be set up. This is done during the initialisation by this loop.


	LDX	#$05			; set 6 vector bytes	
int_loop
	LDA	i_table,X		; get byte from vector table		
	STA	IRQ_vec_l,X		; save to vector	
	DEX				; decrement count
	BPL	int_loop		; loop if more to do

These are the vector words that are copied to the vectors.


; *********************************************************************		
; default values for the interrupt vectors

i_table
	.word	iIRQ			; IRQ routine address
	.word	iBRK			; BRK routine address
	.word	iNMI			; NMI routine address

; *********************************************************************

The NMI routine disables IRQ interrupts and saves any registers used, it could also clear the D flag if needed at this point. The next thing done is to reset the NMI latch, this ensures that longer than the minimum period needed elapses before the NMI line can become active again. After this it reads the status from the network card, the only source of NMI interrupts as set up, and copies any set bits into the interrupt flag byte. Lastly the registers are restored and the routine exits.


; *********************************************************************		
; NMI interrupt routine - the NIC /should/ trigger this

iNMI
	SEI				; disable interrupts
	PHA				; save A

	LDA	NMI_res			; reset NMI latch
	LDA	com_reg_l		; read status byte
	AND	#$FE			; mask wanted bits
	ORA	IB			; OR with interrupt flag byte
	STA	IB			; save new interrupt flag byte

	PLA				; restore A
	RTI

; *********************************************************************

This, commented out, code is what goes on in the kernal ROM when either an IRQ or a BRK opcode generate an interrupt. It's included as a reminder of what goes on before code execution gets to our code.


;; *********************************************************************	
;; IRQ interrupt routine - this part is in the kernal ROM and is here
;; only to show what happens before we get to our code.
;;
;;IRQ
;;	PHA				; save A
;;	TXA				; copy X
;;	PHA				; save X
;;	TYA				; copy Y
;;	PHA				; save Y
;;	TSX				; copy stack pointer
;;	LDA	stack+4,X		; get stacked status register	
;;	AND	#$10			; mask BRK flag
;;	BEQ	do_IRQ			; branch if not BRK
;;
;;	JMP	(BRK_vec_l)		; else do BRK vector (iBRK)
;;
;;do_IRQ					
;;	JMP	(IRQ_vec_l)		; do IRQ vector (iIRQ)
;;
;; *********************************************************************

The only IRQ interrupt we expect is the timer implemented with VIA 2's timer 1. If it was timer 1 then a call is made to the countdown routine after which the routine exits. If timer 1 was not the source, or a BRK was the cause of the interrupt, then the routine just exits.


; *********************************************************************		
; IRQ interrupt routine

iIRQ
	LDA	VIA_2+IFR		; check VIA 2 interrupt flags
	BPL	IRQexit			; exit if wasn't VIA 2

	AND	#$40			; mask timer 1 time-out flagged
	BEQ	IRQexit			; exit if not timer 1 time-out

	STA	VIA_2+IFR		; clear timer 1 time-out flag
	JSR	LAB_12000		; do timeout countdowns

; *********************************************************************
; BRK interrupt routine - does nothing at the moment

iBRK
IRQexit
	PLA				; pull byte
	TAY				; restore Y
	PLA				; pull byte
	TAX				; restore X
	PLA				; restore A
	RTI

; *********************************************************************

This is the system timer code and it implements three independant, re-triggerable, single shot count down timers. At present only the TCP timer and one other is used.


; *********************************************************************		
; does the timeout counting down, called on TIMER 1 timeout (1mS)
; decrement the TCP timeout counter if <> 0

LAB_12000
	LDA	tcp_toc			; test TCP timeout count
	BEQ	LAB_12005		; skip decrement if zero

	DEC	tcp_toc			; else decrement it
LAB_12005
	LDA	cdtb_l			; get countdown timer b low byte
	BEQ	LAB_12010		; skip decrement if zero

	DEC	cdtb_l			; else decrement it
LAB_12010
	LDA	cdtf_l			; get countdown timer f low byte
	BEQ	LAB_12015		; skip decrement if zero

	DEC	cdtf_l			; else decrement it
LAB_12015
	RTS

; *********************************************************************


Last page update: 29th February, 2004. e-mail me e-mail