6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Oct 06, 2024 3:25 am

All times are UTC




Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Thu Apr 08, 2004 2:16 pm 
Offline

Joined: Wed Dec 18, 2002 3:20 am
Posts: 113
Hi All,

I'm wondering what everyone else does to handle interrupts. Right now since there is only one IRQ line (not including the NMI line), I'm or'ing together several potential things that could request an interrupt which then requires me to query each interrupt connected device to see which one did it to execute their specific interrupt handler.

I was wondering if there was a better way to handle this in software/hardware as I waste a decent amount of time dealing with the interrupt, and of course the issues of dealing with multiple interrupts at the same time.


ps - if I could I would cross post this in hardware, but I don't think there is a way to cross post...
-T

_________________
-Tony
KG4WFX


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Apr 08, 2004 4:04 pm 
Offline

Joined: Fri Aug 30, 2002 2:05 pm
Posts: 347
Location: UK
You could do this..

Connect all the interrupts to a 1 of n priority encoder and connect the <>0 output of the encoder to the IRQ line. Make a port so you can read the coded output of the priority encoder.

Now when there's an interrupt you just read the port and use that as an index to the routine for that interrupt.

There is a 74 series chip that does most of this in one package. I'll have to look it up though.

Lee.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Apr 08, 2004 6:49 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8521
Location: Southern California
Mike is getting my interrupts primer ready to put up on the website.  It's basically a little book of 30 or 40 pages including pictures, diagrams, and code examples.  It should be up soon.  Edit: It's up.

I'll put a little bit down here addressing the issue where you have no hardware prioritizing or interrupt source detection—IOW, where software alone must determine who pulled the IRQ line down and why.

The 65xx I/O ICs use bit 7 of their status registers to tell if they requested an interrupt, so all you have to do is BIT addr, BMI/BPL—two instructions for each.

After you've determined which IC caused the interrupt, you'd AND its interrupt enable register with its interrupt flag register and check each bit, possibly as quickly as shift, BMI/BPL, shift, BMI/BPL...  I think this is one of the books, except that the writer of that one forgot the ANDing of the interrupt enable register.  The result is that you could have the situation where a particular status appears to be the source of the interrupt when actually you didn't want that status to pull the interrupt line down.

What I've seen in so many examples though is a waste of time checking for interrupts that aren't even enabled.  There's no point in checking an IC that is not enabled to produce interrupts, or, once you've determined which IC interrupted, to check various things in that IC that are not allowed to interrupt at the time anyway.  If you're only using one interrupt source in that IC and you know it was that IC, there's no point in looking further.  You know which one it was.  If only one IC is allowed to be producing interrupts, there's no point in checking the others.  It's a waste of time.  You typically won't have gobs of interrupts enabled at once; and yet the examples in books sometimes have you checking all 20 or 30 interrupt sources when probably only two or three are enabled at any one time.

Another point to consider is either the priority or the frequency of the interrupts.  If you have three sources enabled and you know one will be interrupting 100 times as often as the next and 1000 times as often as the last, you'll probably want to poll the most frequent one first to save time.  Alternately, if another interrupt that seldom hits is nevertheless very high in priority and needs immediate attention, you might choose to check that one first if the others can wait.

In any case, the job of figuring out where the interrupt came from does not have to take anywhere near as long as many examples in books might lead us to believe.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Apr 09, 2004 1:52 am 
Offline

Joined: Wed Dec 18, 2002 3:20 am
Posts: 113
Garth: Interesting, I'll be looking forward to the article you will have on interrupts. I never really had to think of so many before in the past, so this is kind of new to me.

Lee: If you happen to find out what that IC is, please let me know, I'll probably start searching thru my nte book tonight, hopefully I'll come across it....

_________________
-Tony
KG4WFX


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Apr 09, 2004 12:55 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 9:02 pm
Posts: 1738
Location: Sacramento, CA
Tancor wrote:
Lee: If you happen to find out what that IC is, please let me know, I'll probably start searching thru my nte book tonight, hopefully I'll come across it....


Hi Tancor,

I believe the IC Lee is referring to is the 74LS148 Priority Encoder.

It takes 8 (active low) inputs and provides a 3 bit output. There is another output (GS) that is active low anytime there is an active input, which can connect to IRQ or NMI. It can also be cascaded to provide 16 inputs.

You can find the datasheet at the Fairchild Semiconductor website:
http://www.fairchildsemi.com/

Hope this helps!

Daryl


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Apr 09, 2004 7:45 pm 
Offline

Joined: Fri Aug 30, 2002 2:05 pm
Posts: 347
Location: UK
Yup, 74LS148 or 74LS248 (I think). So when you get an interrupt you do ..

Code:
IRQ_code:
   PHA         ; save A
   TXA         ; copy X
   PHA         ; save X
   LDA   int_port   ; get priority
   AND   #$07      ; mask it
   TAX         ; copy to index
   LDA   tab_l,X   ; get address low byte
   STA   vec_l      ; save to vector
   LDA   tab_h,X   ; get address high byte
   STA   vec_h      ; save to vector
   JMP   (vec_l)   ; do code

; table of interrupt routine address low bytes

tab_l:
   .byte   <interrupt_0
   .byte   <interrupt_1
   .
   .
   .byte   <interrupt_7

; table of interrupt routine address high bytes

tab_h:
   .byte   >interrupt_0
   .byte   >interrupt_1
   .
   .
   .byte   >interrupt_7


This easily handles up to 8 interrupts. When one interrupt is done if there are any lower priority interrupts still pending IRQ will be held low and the interrupt routine will be called again to handle that one. This continues until no interrupting sources remain.

I'm sure an arcade board used something similar to handle sprite-sprite, sprite-character, sprite-background, timer and input interrupts.

Lee.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Apr 09, 2004 10:18 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8521
Location: Southern California
If you just wire the chip one bit over and use a 65c02, you could shorten that to:
Code:
IRQ_code:
    PHA
    PHX
    LDA   int_port
    AND   #$E
    TAX
    JMP   (table,X)


table:
   .word   interrupt_0
   .word   interrupt_1
   .
   .
   .word   interrupt_7


Eliminating the AND# may also be possible if you work the circuit to deliver 0's in the other bits when you read that address. Then it could become:
Code:
IRQ_code:
    PHX
    LDX   int_port
    JMP   (table,X)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Apr 13, 2004 1:53 am 
Offline
User avatar

Joined: Thu Mar 11, 2004 7:42 am
Posts: 362
leeeeee wrote:
Yup, 74LS148 or 74LS248 (I think).


The '248 is NOT a priority encoder! The '248 (and '247) are BCD-to-7-segment decoder/drivers!
The '148 is a 8-line to 3-line priority encoder.
The '147 is a 10-line to 4-line priority encoder.

Anyway, here are a couple of other ideas you could try. I haven't tried these myself, so you may want to experiment before going hog wild with the soldering iron. The following signal names are used below:

An = bit n of the (65C02) address bus
ADn = bit n of the ROM address input
Yn = bit n of the '148 output

Say, for example, you have a 4k x 8-bit ROM mapped to $F000-$FFFF, where A11-A0 is connected to AD11-AD0. The idea is to use a 32k x 8-bit ROM, connecting AD11-AD0 to A11-A0, and AD14-AD12 to Y2-Y0. Now you have eight 4k chunks of ROM. Make all eight chunks identical EXCEPT for the locations that map to $FFFE and $FFFF, and now you have eight vectors for eight different interrupt sources and you don't need to determine the interrupt source in software at all. Of course, you'll only be able to access one interrupt vector at time with, say, a LDA $FFFE, but how often do you need to read interrupt vectors with LDA? The main downside to this approach is that you may need a large ROM.

Idea number two is to create a signal that I'll call FFFEB which is low when you are accessing address FFFE or FFFF and high otherwise. Basically, FFFEB is:

FFFEB = NOT (A1 AND A2 AND A3 AND ... AND A13 AND A14 AND A15)

or if you have a newfangled 65C02 with the VPB signal:

FFFEB = VPB OR (NOT (A1 AND A2))

then use the FFFEB signal to modify the ROM address you read from, as follows:

AD1 = A1 AND (FFFEB OR Y0)
AD2 = A2 AND (FFFEB OR Y1)
AD3 = A3 AND (FFFEB OR Y2)
AD4 = A4 AND FFFEB

Connect all other ADn lines to An. Then the vector for interrupt source N is at $FFE0 + N * 2. The 10 bytes at $FFF0-$FFF9 will be unused, but maybe you can find something to put there.

If the above is confusing, feel free to post or e-mail me.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Apr 13, 2004 7:28 am 
Offline

Joined: Fri Aug 30, 2002 2:05 pm
Posts: 347
Location: UK
Ok so perhaps not '248, there is another 8 to 3 line encoder but I forget it's part #

Nice ideas on hardware vectoring but what happens if a higher priority interrupt arrives between fetching the first byte of the vector and fetching the second byte?

Lee.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Apr 13, 2004 9:29 am 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
leeeeee wrote:
Nice ideas on hardware vectoring but what happens if a higher priority interrupt arrives between fetching the first byte of the vector and fetching the second byte?

How about latching the priority encoder with the processor SYNC signal so that it can't change mid-instruction?

_________________
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Apr 13, 2004 10:49 pm 
Offline
User avatar

Joined: Thu Mar 11, 2004 7:42 am
Posts: 362
leeeeee wrote:
Ok so perhaps not '248, there is another 8 to 3 line encoder but I forget it's part #


The '348 is an 8 to 3 line priority encoder with tri-state outputs. There is also a '748 and '848 (from Motorola) which are equivalents of the '148 and '348, respectively, and are were designed to minimize glitches on the GS output pin.

leeeeee wrote:
Nice ideas on hardware vectoring but what happens if a higher priority interrupt arrives between fetching the first byte of the vector and fetching the second byte?


If the interrupt handlers are short, start all of them on the same page and all of the high bytes will be the same. If the interrupts handlers are long, you could start all of them on page boundaries and all of the low bytes will be the same. In fact, with all of the low bytes the same, you could use FFFFB (low when accessing $FFFF ONLY, high otherwise) instead of FFFEB in the second idea above and move everything down one bit and map the high bytes to $FFF0-$FFF7 and save a few bytes. In the case where all of the high bytes are the same, change FFFEB so that it is low when accessing $FFFE ONLY, and high otherwise. Move everything down one bit, but for AD0 use:

AD0 = A0 OR ((NOT NewFFFEB) AND Y0)

Then the low bytes will be mapped to $FFF0-$FFF8. If the interrupts are asynchronous and could, for example, change in the middle of the cycle that the low byte is fetched (in the case where all of the high bytes are the same), then the latch (or a flip-flop) that someone else suggested is probably a good idea. In this case you could probably use the processor clock rather than SYNC, since you'll only need a stable value for one clock cycle.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Apr 13, 2004 10:57 pm 
Offline

Joined: Fri Aug 30, 2002 2:05 pm
Posts: 347
Location: UK
Found it, 74LS348 - 8 input priority encoder with tri state outputs.

Easier to interface as you wouldn't need external data bus buffers.

Lee.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Apr 19, 2004 6:54 am 
Offline

Joined: Fri Jun 27, 2003 8:12 am
Posts: 618
Location: Meadowbrook
for my own SBC, I only have 2 types of interrupt chips coming in, so its easier with my little idea. I use a 6522 and the IRQ pin also can go out, so the interrupts are either from that 6522 or from otside. From the6522, i the irq routine, I merely copy the status flag over to a memory location and call it the interrupt location. The bit will tell exactly what caused the interrupt from the 6522, and if thevalue is 0, then the interrupt is from outside. I figure if I have multiple outside IRQ sources, if I use 6522s, I can always check the flag registers which takes some time, or go the priority route and define accordingly....

_________________
"My biggest dream in life? Building black plywood Habitrails"


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Jun 09, 2004 7:34 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8521
Location: Southern California
The 6502 interrupts primer is up.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Jun 11, 2004 7:43 am 
Offline

Joined: Fri Jun 27, 2003 8:12 am
Posts: 618
Location: Meadowbrook
Lee, in terms of 6502 usage, I have yet to see an arcade board use multiple interrupt inputs, there wopuld usually only be a single one. On some laster 68000 games, there might be some priority encoding, the only ones I DID actually see in circuit for prioritzing interrupts would be Sky Shark and Twin Cobra.

The Bally pinball MPU is kind of bananas for interrupots, though. It uses 2 6821s, a 6800 cpu and 2 seperate interrupt inputs, a 120 hz zero crossing fromthe AC in the cabinet, and a 555 time for the display interrupts, something like 300 hz.

_________________
"My biggest dream in life? Building black plywood Habitrails"


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 16 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: