Proper /IRQ handling for multiple devices

For discussing the 65xx hardware itself or electronics projects.
User avatar
floobydust
Posts: 1394
Joined: 05 Mar 2013

Re: Proper /IRQ handling for multiple devices

Post by floobydust »

You can always add a 3-pin jumper for all IRQ outputs from the various devices (VIA, UART, etc.) and have the luxury of connecting to IRQ or NMI or just leave the jumper off. Same can be said for a 2-pin jumper, connect to IRQ or not.

Also, when you're considering software, note that the BRK vector is shared with the IRQ vector, so you might want to add some header code at that vector to determine which happened: an actual IRQ or the BRK instruction. I use a short piece of code in the ROM for that... and also for the exit routine via an RTI. The old Vic-20 used a similar routine, albeit had to move the index registers to the accumulator to push on the stack (and inverse when pulling from the stack), so that added more clock cycles and memory to the routines.

Code: Select all

IRQ_VECTOR                              ;This is the ROM start for the BRK/IRQ handler
                PHA                     ;Save A Reg (3)
                PHX                     ;Save X Reg (3)
                PHY                     ;Save Y Reg (3)
                TSX                     ;Get Stack pointer (2)
                LDA     $0100+4,X       ;Get Status Register (4)
                AND     #$10            ;Mask for BRK bit set (2)
                BNE     DO_BRK          ;If set, handle BRK (2/3)
                JMP     (IRQVEC0)       ;Jump to Soft vectored IRQ Handler (6)
DO_BRK          JMP     (BRKVEC0)       ;Jump to Soft vectored BRK Handler (6)
NMI_ROM         JMP     (NMIVEC0)       ;Jump to Soft vectored NMI handler (6)
;
;This is the standard return for the IRQ/BRK handler routines
;
IRQ_EXIT0       PLY                     ;Restore Y Reg (4)
                PLX                     ;Restore X Reg (4)
                PLA                     ;Restore A Reg (4)
                RTI                     ;Return from IRQ/BRK routine (6)
It's a small amount of overhead, but if you're running a 4MHz CPU clock, simply polling each IRQ capable device won't take very long. Note: the number in parenthesis is the number of clock cycles for each instruction. A branch instruction is 2 cycles if not taken and 3 cycles if taken. For the IRQ vector, the branch is not taken, which saves 1 clock cycle. I keep a vector table on page $03 ($0300) for entry and exit of IRQ, NMI and BRK vectors. I also defined 8 spare vectors so you can add hardware/software and insert pre- or post- the existing routines.
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Proper /IRQ handling for multiple devices

Post by drogon »

BigEd wrote:
Hmm, if you have a VIA and don't connect the IRQ up, you're certainly losing out on some future possibilities. It seems like it shouldn't cost much to add it. (I wouldn't always be in favour of adding things just because you can.)
And even if using the VIA but not needing interrupts you don't need to enable them in the VIA.

Also:
cbmeeks wrote:
I think I like the idea of having a "heartbeat" that occurs X times per second. That could then maybe read from RAM for the audio. Maybe handle the SD card, etc.
Thinking about this - Yes, my Ruby board "wastes" 0.2% cpu cycles on a pretty (for me) heartbeat LED, but again, I go back to what I consider to be the pinnacle of 6502 systems in the early 80's; the BBC Micro.... And in this case, the sound chip.

The sound chip is not anything special or clever. simple 3 channels of square wave plus a channel of noise. You could vary the pitch and amplitude and was often compared (usually badly) to the SID chip in the C64 which was much more capable, however... The clever part was the 100Hz software interrupt which was the central ticker in the Beeb - the sound system has a programmable pitch and amplitude envelope and channel synchronisation commands. The magic happened on the 100Hz interrupt with the OS updating the amplitude and pitch 100 times per second for each channel. So there is plenty of scope for substituting hardware for software when you need things to change regularly - like an old sound chip hung off a VIA port. (the BBC Micro had a "slow bus" which was essentially driven off a VIA and interfaced to several chips including the speech chip (and ROM), sound chip and the keyboard.

Studying the schematic of the BBC Micro might give you some ideas too. See e.g. here: http://www.8bs.com/boards/BBCBschematicJTribbeck.png

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Proper /IRQ handling for multiple devices

Post by BigDumbDinosaur »

BigEd wrote:
Hmm, if you have a VIA and don't connect the IRQ up, you're certainly losing out on some future possibilities. It seems like it shouldn't cost much to add it. (I wouldn't always be in favour of adding things just because you can.)

I agree with Ed. I'd connect the IRQ output...just don't program any interrupts in that VIA until such time you suddenly realize you could use them.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
cbmeeks
Posts: 1254
Joined: 17 Aug 2005
Location: Soddy-Daisy, TN USA
Contact:

Re: Proper /IRQ handling for multiple devices

Post by cbmeeks »

Hello everyone! It's been a while since I've been on this project.

So I have decided to ramp some stuff down. I've dropped three expansion slots so that I now just have one.
My total number of devices that generate interrupts is now FIVE.

In order of priority (most to least):
VDP
UART
VIA1
VIA2
Expansion Port

This brings up a problem. I'm looking at using a totem pole setup and having each device go into an AND gate. They don't make 5 input AND's. The closest for a single chip is 8 inputs. Which is the SN74HC08AN.

However, I'm not sure if using HC components is what I want to use. I still get confused on when it's safe to mix types.

Worse case, I can drop one of the VIA's. I was just keeping it on there so that I could use it as a timer.

The big components I'm using are the TMS9918 (NMOS), 6551 (probably use NMOS to avoid that bug) and the two VIA's. Plus whatever could be plugged into the expansion.

Do any of you see an issue running with that particular chip? (SN74HC08AN)

My max speed would be 2 Mhz. with maybe seeing if I could push to 3 or 4 MHz. But 2 Mhz is my target.

Thanks for any tips.
Cat; the other white meat.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Proper /IRQ handling for multiple devices

Post by GARTHWILSON »

For this application, 74HC will be fine, both speedwise and regarding input voltage levels too.  Totem-pole outputs will pull up plenty high for 74HC, and the open-drain with a pull-up also will come up to 5V.
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?
User avatar
Dr Jefyll
Posts: 3526
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: Proper /IRQ handling for multiple devices

Post by Dr Jefyll »

cbmeeks wrote:
The closest for a single chip is 8 inputs. Which is the SN74HC08AN.
Yes 74HC will be fine. And, 8 inputs, yes -- but that's in four separate gates of two inputs each. It doesn't mean you'd get 8 interrupt inputs.

In a case like this you'd be OK cascading the gates, which at best would allow as many as 5 interrupt inputs (as shown below). But it's possible to do better. For example, cascading an 'HC11 triple 3-input AND would allow up to 7 interrupt inputs.

-- Jeff
Attachments
cascaded gates.png
cascaded gates.png (958 Bytes) Viewed 1078 times
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
User avatar
cjs
Posts: 759
Joined: 01 Dec 2018
Location: Tokyo, Japan
Contact:

Re: Proper /IRQ handling for multiple devices

Post by cjs »

cbmeeks wrote:
Actually, I think I misspoke. My intention was to only have one true /NMI and the idea was to tie it to a keyboard. But the more I think about that, the more it doesn't really make sense. I was thinking you could press some keyboard sequence (much like the RESTORE key on C64) to interrupt just about anything and return to BASIC. I think it does make more sense to tie it to a "monitor" button. So pressing it would load a system monitor or something similar.
That is, in fact, exactly how the RESTORE key on the C64 works. That "key" is not part of the regular key matrix (and not scanned) but is a momentary switch with its own separate output that is debounced before being fed directly to the NMI line. (The NMI routine does something along the lines of reinitializing the I/O and then checking to see if the STOP key is also currently pressed, indicating it should restart BASIC at the input routine as well.)

I've attached below the diagrams from the C64 service manual showing the keyboard matrix side and block diagram (the vertical line at "RESTORE" is connected to ground above) and the circuit on the motherboard that debounces the switch (the /NMI line has a 3k3 pullup on it that's not on this fragment of the schematic). You might be able to get away with something simpler from Garth's reset circuits page, but at least some of the Commodore designers—Bil Herd for certain—were firm believers that a 555 or similar one-shot was absolutely necessary for reliable resets and NMIs. (If you're uncertain about your choice of circuit, you could use their technique of producing ten thousand machines and testing each one.)

Using NMI as a "soft reset" to recover from programming errors or similar seems to be a fairly common technique. As well as being used on Commodore machines and BDD's boards, it's also used in my (6800-based) National/Panasonic JR-200: the "BREAK" key on that keyboard is part of the regular keyboard matrix, but that matrix is scanned by a microcontroller that generates a separate NMI output when that key is pressed, rather than putting the key code into a register as it does with all the other keys. I seem to recall that the KIM also had NMI on a debounced switch.

The Apple II used RESET instead for this, freeing NMI for other purposes. To determine whether a reset was a cold or warm start it had a checksum for a vector in the zero page, using that if the checksum was ok or doing a complete machine initialization if it was not. The downside of this technique is that unlike an NMI you don't get the previous program counter and flags pushed on to the stack, which you might want if you're interrupting running code in order to debug it.
Attachments
c64-restore-kbmatrix.png
c64-restore-nmi-circuit.png
Curt J. Sampson - github.com/0cjs
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Proper /IRQ handling for multiple devices

Post by BigDumbDinosaur »

cbmeeks wrote:
My total number of devices that generate interrupts is now FIVE.

In order of priority (most to least):
VDP
UART
VIA1
VIA2
Expansion Port

This brings up a problem. I'm looking at using a totem pole setup and having each device go into an AND gate. They don't make 5 input AND's. The closest for a single chip is 8 inputs. Which is the SN74HC08AN.

The only devices that *may* need separate /IRQ lines would be the VIAs, assuming you use the 'S' versions. So you could get away with a triple-input AND, with the third input a wired-OR driven by the VDP, UART and expansion port. The pullup resistor on the wired-OR input should be the lowest value consistent with the current-sinking capability of the weakest device. That device likely would be the 6551, being NMOS.

cjs wrote:
Using NMI as a "soft reset" to recover from programming errors or similar seems to be a fairly common technique...it's also used in my (6800-based) National/Panasonic JR-200: the "BREAK" key on that keyboard is part of the regular keyboard matrix, but that matrix is scanned by a microcontroller that generates a separate NMI output when that key is pressed, rather than putting the key code into a register as it does with all the other keys.

When I built my first POC unit, I was using a WYSE 60 terminal as the console. The terminal has a [BREAK] key which when pressed, causes TxD to go to a continuous space condition for one datum period. The DUART can be programmed to generate an IRQ when a break is received. In the early versions of the firmware, I used that feature to interrupt program execution by calling the BRK entry point in the monitor.

Problem was if the "stuck" code had executed an SEI before getting stuck, striking [BREAK] was of no use, since the MPU couldn't respond to the resulting interrupt. After tripping over that behavior a few times I added the necessary circuitry to use NMI. The thin clients I now use for terminals don't seem to have the means to generate a break, so I disabled that feature in POC's firmware.
Last edited by BigDumbDinosaur on Sat Aug 07, 2021 7:44 am, edited 1 time in total.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
gfoot
Posts: 871
Joined: 09 Jul 2021

Re: Proper /IRQ handling for multiple devices

Post by gfoot »

cjs wrote:
The Apple II used RESET instead for this, freeing NMI for other purposes. To determine whether a reset was a cold or warm start it had a checksum for a vector in the zero page, using that if the checksum was ok or doing a complete machine initialization if it was not. The downside of this technique is that unlike an NMI you don't get the previous program counter and flags pushed on to the stack, which you might want if you're interrupting running code in order to debug it.
The BBC Micro also uses RESET (and a 555 timer) for this. It has a different way to detect a power-on reset though - one of its VIAs has its reset pin driven by an RC circuit, instead of the shared reset line used by everything else, so soft resets don't affect this VIA. It then reads the interrupt enable register as a kind of flag to detect a hard reset - I guess there's never normally a time when all interrupt sources are disabled.
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Proper /IRQ handling for multiple devices

Post by BigDumbDinosaur »

gfoot wrote:
The BBC Micro also uses RESET (and a 555 timer) for this. It has a different way to detect a power-on reset though - one of its VIAs has its reset pin driven by an RC circuit, instead of the shared reset line used by everything else, so soft resets don't affect this VIA. It then reads the interrupt enable register as a kind of flag to detect a hard reset - I guess there's never normally a time when all interrupt sources are disabled.

In the Commodore 128, the reset handler differentiates between a cold start (power-on) and a hard reset (pressing the reset button) by writing a short text string at the top of RAM1 after the full reset sequence has been executed, but before control is given to the BASIC interpreter. This scheme works because DRAM, at power-on, tends to initialize with $00 and $FF in all cells.

Associated with this "the machine is powered up" text string is a vector that may be modified to point to something other than the reset functions in ROM. The early part of the ROM reset code will check for the "powered-up" string and if present, take the vector. Unchanged, the vector points to the balance of the ROM reset routine. Edited, the vector could take the machine anywhere. It's amusing to watch what happens if the vector is pointed to the start of BASIC program text (normally seen by the 8502 as a BRK opcode). :D I once did this to a friend's C-128 when he wasn't looking and then told him to press reset. He almost panicked when he saw what happened. :twisted:

I once used this (poorly-documented) feature on a C-128 in a retail store to run an "unbreakable" program that would print a sales pitch on the monitor using slowly-moving PET graphics. The first thing the program would do once started was change the reset vector to point to the program itself. Pressing the reset button would merely initialize a few things, and then the program would restart. The machine had to be powered off long enough for capacitor charges to dissipate in order to "break" the program.

In my POC unit, I'm using SRAM, which when powered up, will have any of the 256 possible byte values in each memory cell. Potentially, a series of cells could have a recognizable pattern that a reset handler could mistake for a genuine "power-up" signature. I've not yet figured out a foolproof way of differentiating in software alone a power-on reset from one initiated by pressing the reset button.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
cbmeeks
Posts: 1254
Joined: 17 Aug 2005
Location: Soddy-Daisy, TN USA
Contact:

Re: Proper /IRQ handling for multiple devices

Post by cbmeeks »

BigDumbDinosaur wrote:
I once used this (poorly-documented) feature on a C-128 in a retail store to run an "unbreakable" program that would print a sales pitch on the monitor using slowly-moving PET graphics.
That's really clever! I wished I had known that back then. The best I did was:

Code: Select all

10 PRINT "FARTS";
20 GOTO 10
lol

Thanks everyone for the suggestions. I've convinced myself to use /NMI for a "hardware abort" or debug switch. But instead of using a 555, I thought I would use a DS1813 instead. Which are a little pricey but saves board space.
Attachments
Capture.JPG
Cat; the other white meat.
plasmo
Posts: 1273
Joined: 21 Dec 2018
Location: Albuquerque NM USA

Re: Proper /IRQ handling for multiple devices

Post by plasmo »

I see DS1813 being mentioned several times and looked it up. Far as I can tell, it is same as the 50-cent MCP130 that I use in about every board design except it is 5 times more expensive. So why DS1813?
Bill
User avatar
floobydust
Posts: 1394
Joined: 05 Mar 2013

Re: Proper /IRQ handling for multiple devices

Post by floobydust »

plasmo wrote:
I see DS1813 being mentioned several times and looked it up. Far as I can tell, it is same as the 50-cent MCP130 that I use in about every board design except it is 5 times more expensive. So why DS1813?
Bill
Well, for what it's worth, the DS1813 also provides for a manual reset switch. It's simply wired from the reset output to ground. When pressed and released, the DS1813 performs the hold time again, same as power on.

According to the MCP130 datasheet, this is not the case. Perhaps it also provides a reset timer when using a switch the same way, but I don't know.
plasmo
Posts: 1273
Joined: 21 Dec 2018
Location: Albuquerque NM USA

Re: Proper /IRQ handling for multiple devices

Post by plasmo »

Ah, that is a difference between mcp130 and ds1813. It is possible to add reset push botton to mcp130's reset (it is open drain with internal 5k pull up), but the reset is not stretched for the nominal 250ms, it is not debounced, in fact. To generate manual reset that stretches for the nominal 250ms, the reset button should connect to the VCC terminal of mcp130 and the VCC terminal should connect to 5V supply through a 1K or so current limiting resistor.
Bill
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Proper /IRQ handling for multiple devices

Post by BigDumbDinosaur »

plasmo wrote:
To generate manual reset that stretches for the nominal 250ms, the reset button should connect to the VCC terminal of mcp130 and the VCC terminal should connect to 5V supply through a 1K or so current limiting resistor.

In other words, two parts are required to do the work of one. :D
x86?  We ain't got no x86.  We don't NEED no stinking x86!
Post Reply