English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 16 March 2019, 19:31   #1
mcgeezer
Registered User

 
Join Date: Oct 2017
Location: Sunderland, England
Posts: 2,349
Damn Interrupts

As part of Rygar I'm wanting to delve into an area that I know very little about.

I think I understand how the interrupts work but I just can't get them to fire.

Taking the level 3 Vertical Blanking Interrupt as an example my understanding is that I should be able to write an interrupt service routine attached to VBR+$6c, within that routine I need to check if the VERTB is set within INTREQ and if it is then do whatever required... i need to ignore the other interrupts that are generated at this level which are COPER (Copper) and BLIT (Finished).

Within my service routine i then need to acknowledge and unset the interrupt bit (i think).

The code below is partially borrowed from elsewhere... but for the life of me I cannot get the service routine to fire and increment the Timer.

Does anyone know what I'm missing here???

Code:
bsr	InstallLevel3Int
	move.w	#$c020,INTENA(a5)
Code:
InstallLevel3Int: 
	move.l	a5,-(a7)
;--- get the vbr which is most probably somewhere in fast-ram 
	lea	getvbr(pc),a5 
	move.l	$4.w,a6
	jsr	-30(a6)			; returns vbr in d0 
	lea	vbroffset(pc),a0 
	move.l	d0,(a0)			; store vbr 

;--- you could store some old values here 
;... 

;--- register our own level 3 interrupt (vertical blanc and blitter) 
	lea 	Level3Int(pc),a1 
	move.l	a1,$6c(a0)
	move.l	(a7)+,a5
	rts 

;--- get the vector base register 
getvbr:	movec	vbr,d0 
	;dc.l	$4e7a0801	; this is the opcode for the above command 
	rte 

vbroffset:	dc.l	0 


	cnop	0,4

;--- this is the actual interrupt code 
; it could interrupt (!) your main-programm at anytime so better 
; save the register states. this is what the push macro does (it uses movem.l). 
Level3Int: 
	movem.l	d0-d7/a0-a4,-(a7)
	move.w	INTREQR(a5),d0	; intreq-read 
	btst	#5,d0		; Vertical Blank? 
	bne	.vertb 
	bra	.quitL3 

.vertb 
	lea	Timer(pc),a0 
	addq.l	#1,(a0)	; increase Timer by 1
 
	lea	VerticalBlank(pc),a0
	move.w	#-1,(a0)

	move.w	#$4020,INTREQ(a5)   ;0100000000100000	; Clear vertical blank interupt.
	move.w	#$4020,INTREQ(a5)
	bra.w	.quitL3 

.quitL3: 
	movem.l	(a7)+,d0-d7/a0-a4
	nop 
	rte 

;--- this Timer is updated once a frame. 
; there are 50 FPS on a PAL Amiga, so this variable has a resolution 
; of 1/50 s 
; or 20/1000 s 
; or 20 ms 
Timer:	dc.l	1
VerticalBlank:	dc.w	0

Any help is really really really appreciated!!!

Geezer
mcgeezer is offline  
Old 16 March 2019, 20:05   #2
Asman
68k

Asman's Avatar
 
Join Date: Sep 2005
Location: Somewhere
Posts: 776
@mcgeezer What do you have in A0 when you set VERTB ? You should have VBR address here. Are you sure that you have VBR in A0 ? I ask because I see that VBR is in D0. Please add at least following line to your code
Code:
move.l	d0,(a0)			; store vbr 
move.l	d0,a0			; vbr --> a0
Or you can use move.l vbroffset(pc),a0 before you set up VERTB. its up to you.

Cheers
Asman is offline  
Old 16 March 2019, 20:08   #3
mcgeezer
Registered User

 
Join Date: Oct 2017
Location: Sunderland, England
Posts: 2,349
Quote:
Originally Posted by Asman View Post
@mcgeezer What do you have in A0 when you set VERTB ? You should have VBR address here. Are you sure that you have VBR in A0 ? I ask because I see that VBR is in D0. Please add at least following line to your code
Code:
move.l	d0,(a0)			; store vbr 
move.l	d0,a0			; vbr --> a0
Or you can use move.l vbroffset(pc),a0 before you set up VERTB. its up to you.

Cheers
Thanks Asman.... thanks for spotting, that was totally my fault!

Working great now!

Geezer
mcgeezer is offline  
Old 16 March 2019, 20:12   #4
Asman
68k

Asman's Avatar
 
Join Date: Sep 2005
Location: Somewhere
Posts: 776
@mcgeezer Great. But You can check also Level3Int. It works but I am not sure if is correct.
Asman is offline  
Old 16 March 2019, 20:21   #5
mcgeezer
Registered User

 
Join Date: Oct 2017
Location: Sunderland, England
Posts: 2,349
Quote:
Originally Posted by Asman View Post
@mcgeezer Great. But You can check also Level3Int. It works but I am not sure if is correct.
Yes it's working fine, I've moved some routines into the Level3Int service routine. If you're following the development of the game I want to do this so that I can load the next round of the game while the player is in the sanctuary scene and the bonus is counting up, it will save time but also the colour cycling will continue while the next round loads from disk.

Geezer

Edit...

Here is now my Interrupt Service Routine on Level 3. Part of this is to ensure that the 2nd button code works on all Amiga 1200's/CD32.

In the Vertical Blank routine I'm writing to POTGO, then in my copper routine at line 64 I'm causing the button state to be read. This is the first time I've done stuff like this and it seems I'm getting the hang of it finally.

Code:
Level3Int: 
	movem.l	d0-d7/a0-a4,-(a7)
	move.w	INTREQR(a5),d0			; intreq-read 
	btst	#5,d0				; Vertical Blank? 
	bne.s	.vertb 
	btst	#4,d0				; Copper
	bne.s	.copper 
	bra.s	.quitL3 

.vertb:
	lea	VerticalBlank(pc),a0
	move.w	#-1,(a0)
	move.w	#$ff00,POTGO(a5)		; Reset POTGO
	bsr	UPDATE_TIMER
	bsr	CYCLE_COLOURS
	moveq	#8,d0
	bsr	UPDATE_ROUND_GUIDE
	move.w	#$4020,INTREQ(a5)   		;0100000000100000	; Clear vertical blank interupt.
	move.w	#$4020,INTREQ(a5)
	bra.w	.quitL3 

.copper:
	bsr	BTN_DETECT
	move.w	#$4010,INTREQ(a5)   		;0100000000100000	; Clear copper interupt.
	move.w	#$4010,INTREQ(a5)
	bra.w	.quitL3 
	nop

.quitL3: 
	movem.l	(a7)+,d0-d7/a0-a4
	nop 
	rte

Last edited by mcgeezer; 16 March 2019 at 20:36.
mcgeezer is offline  
Old 16 March 2019, 20:43   #6
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 53
Posts: 1,327
Quote:
Originally Posted by mcgeezer View Post
Yes it's working fine, I've moved some routines into the Level3Int service routine. If you're following the development of the game I want to do this so that I can load the next round of the game while the player is in the sanctuary scene and the bonus is counting up, it will save time but also the colour cycling will continue while the next round loads from disk.

Geezer

Edit...

Here is now my Interrupt Service Routine on Level 3. Part of this is to ensure that the 2nd button code works on all Amiga 1200's/CD32.

In the Vertical Blank routine I'm writing to POTGO, then in my copper routine at line 64 I'm causing the button state to be read. This is the first time I've done stuff like this and it seems I'm getting the hang of it finally.

Code:
Level3Int: 
	movem.l	d0-d7/a0-a4,-(a7)
	move.w	INTREQR(a5),d0			; intreq-read 
	btst	#5,d0				; Vertical Blank? 
	bne.s	.vertb 
	btst	#4,d0				; Copper
	bne.s	.copper 
	bra.s	.quitL3 

.vertb:
	lea	VerticalBlank(pc),a0
	move.w	#-1,(a0)
	move.w	#$ff00,POTGO(a5)		; Reset POTGO
	bsr	UPDATE_TIMER
	bsr	CYCLE_COLOURS
	moveq	#8,d0
	bsr	UPDATE_ROUND_GUIDE
	move.w	#$4020,INTREQ(a5)   		;0100000000100000	; Clear vertical blank interupt.
	move.w	#$4020,INTREQ(a5)
	bra.w	.quitL3 

.copper:
	bsr	BTN_DETECT
	move.w	#$4010,INTREQ(a5)   		;0100000000100000	; Clear copper interupt.
	move.w	#$4010,INTREQ(a5)
	bra.w	.quitL3 
	nop

.quitL3: 
	movem.l	(a7)+,d0-d7/a0-a4
	nop 
	rte
One thing, you dont change A5 in your code? Its always $dff000?
This code dont looks good for me:
Level3Int:
movem.l d0-d7/a0-a4,-(a7)
move.w INTREQR(a5),d0 ; intreq-read
Don_Adan is offline  
Old 16 March 2019, 20:44   #7
mcgeezer
Registered User

 
Join Date: Oct 2017
Location: Sunderland, England
Posts: 2,349
Quote:
Originally Posted by Don_Adan View Post
One thing, you dont change A5 in your code? Its always $dff000?
This code dont looks good for me:
Level3Int:
movem.l d0-d7/a0-a4,-(a7)
move.w INTREQR(a5),d0 ; intreq-read

Nope, a5 and a6 are never changed... ever.
mcgeezer is offline  
Old 17 March 2019, 00:12   #8
ross
Defendit numerus

ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 51
Posts: 3,283
I'm a bit tipsy but I try

If you disable system IRQ you don't need to split IRQ3 in VBI and Copper parts.
And a simple init for POTGO suffice.

You can do:
Code:
        bsr	InstallLevel3Int
	move.w	#$ff00,POTGO(a5)		; Reset POTGO
	move.w	#$c020,INTENA(a5)
So when an IRQ3 trigger you're sure is by VBI.

(In Copper IRQ fork you test only joy/buttons state?)
[Anyway.. if you want to activate Copper IRQ you need to write
#$c030,INTENA(a5)
]

Another thing: do you stop IRQs during the loading phase?
Because if not, then a5/a6 need to be saved.

To clean the IRQ only clear the interested bit (so
move.w #$20,INTREQ(a5)
suffice) and
nop
is unnecessary.

Optimized routine:
Code:
Level3Int: 
	movem.l	d0-d7/a0-a6,-(a7)
        lea     $dff000,a5  ;a6?

	lea	VerticalBlank(pc),a0
	st      (a0)    ; do you check for EQ?
	bsr	BTN_DETECT
	bsr	UPDATE_TIMER
	bsr	CYCLE_COLOURS
	moveq	#8,d0
	bsr	UPDATE_ROUND_GUIDE

	moveq   #$20,d0
        move.w	d0,INTREQ(a5)
	move.w	d0,INTREQ(a5)
	movem.l	(a7)+,d0-d7/a0-a6
	rte

Last edited by ross; 17 March 2019 at 00:39. Reason: added lea custom,a5
ross is offline  
Old 17 March 2019, 12:49   #9
mcgeezer
Registered User

 
Join Date: Oct 2017
Location: Sunderland, England
Posts: 2,349
Thanks Ross, I have fixed up the saved registers.

My understanding was that if I wanted to support CD32 pads I would need to write #$ff00 to POTGO at the vertical blank and then read the button inputs from POTGOR at least 4 scan lines later.

I have probably mis-understood due to the various postings about this. It will all come out in play testing anyways.


Graeme
mcgeezer is offline  
Old 17 March 2019, 15:28   #10
ross
Defendit numerus

ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 51
Posts: 3,283
It depends.
CD32 pad have two working mode: "CD32 mode" and "normal mode".
If you want basic CD32 pad support (only the red/blue buttons as 1st and 2nd joy buttons) aka "normal mode" this init should suffice.

/Tech mode on
Pin 5 (MMB) = 1 = output, I/O data = 0 (gnd) -> pad to "CD32 mode", shift register enabled*.
Pin 5 = 0 = input or data = 1 (5v) -> "normal mode", red and blue buttons -> 2 buttons joystick.
This is what I've understood from the mess laying around
But I've never owned a joypad...
*you need a proper routine to read all the buttons state

All the delay / capacitors stuff is for when you use POT in analog mode (bit 0 = 1)
/off

jotd has a ready auto-recognition routine that uses different code depending on what is connected.
And a full "CD32 mode" support.

Toni to confirm/correct me and/or give you more details
ross is offline  
Old 24 March 2019, 16:50   #11
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 46
Posts: 24,786
Quote:
Originally Posted by mcgeezer View Post
Nope, a5 and a6 are never changed... ever.
Don't do it. Sooner or later you make some optimized routine that temporarily uses all address registers which in worst case works just fine until (much) later something else changes timing just enough to break it randomly without any clue..

Quote:
Originally Posted by ross View Post
It depends.
CD32 pad have two working mode: "CD32 mode" and "normal mode".
If you want basic CD32 pad support (only the red/blue buttons as 1st and 2nd joy buttons) aka "normal mode" this init should suffice.

/Tech mode on
Pin 5 (MMB) = 1 = output, I/O data = 0 (gnd) -> pad to "CD32 mode", shift register enabled*.
Pin 5 = 0 = input or data = 1 (5v) -> "normal mode", red and blue buttons -> 2 buttons joystick.
This is what I've understood from the mess laying around
But I've never owned a joypad...
*you need a proper routine to read all the buttons state

All the delay / capacitors stuff is for when you use POT in analog mode (bit 0 = 1)
/off

jotd has a ready auto-recognition routine that uses different code depending on what is connected.
And a full "CD32 mode" support.

Toni to confirm/correct me and/or give you more details
It looks correct enough

Capacitors are always connected but they only cause max few tens of microsecond delays when reading buttons using POTGOR bits. No problems as long as you don't do something weird like toggling POTGO data out/in bits and then immediately attempt to read button state

Pot line caps is also the reason why CD32 pad routines have delays (usually by reading CIA register which always takes at least 1 E-clock cycle = ~710KHz)

btw, it is much simpler to read POTGOR first, then set it to $ff00. This way you guarantee there is always more than enough time before next read. This is how KS ROM does it too. (But remember to ignore results of first read..)
Toni Wilen is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
A cautionary tale: trying to be 'too smart' with interrupts roondar Coders. Asm / Hardware 28 28 November 2018 17:54
How does Paula handle pending interrupts? bloodline Coders. Asm / Hardware 6 21 January 2018 15:45
CIA interrupts... bloodline Coders. System 6 18 January 2018 10:33
Interrupts and Multitasking: Examples? tygre Coders. General 13 22 December 2015 04:56
Advice on interrupts and jumps alexh Coders. General 11 20 May 2008 09:42

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 22:54.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, vBulletin Solutions Inc.
Page generated in 0.08982 seconds with 13 queries