Jump to content
IGNORED

How can POKEY IRQ Timers mess up NMI timing?


Sheddy

Recommended Posts

Well, the CIA on the C-64 holds NMI low indefinately, until it's status is cleared by the user program.

 

In Atari's case, you don't want that because DLI usage on a 1 per scanline basis is reasonably common. The other thing is that Antic's original design also needed to cater for System Reset which could occur anywhere.

I think it's already been established that it's (S-Reset's) NMI only occurs at a certain cycle on the scanline. It could be that Antic needs to do things that way - there's some breathing space between DList Instruction and PMG fetches and the screen/refresh DMA burst, which in many cases keeps it busy for most of the remainder of the scanline.

 

All that aside though, you'd think they would have tested for contention issues like we're having, and likely could have implemented the simple fix of extending /NMI by a couple of cycles.

Link to comment
Share on other sites

Well, the CIA on the C-64 holds NMI low indefinately, until it's status is cleared by the user program.

 

In Atari's case, you don't want that because DLI usage on a 1 per scanline basis is reasonably common. The other thing is that Antic's original design also needed to cater for System Reset which could occur anywhere.

I think it's already been established that it's (S-Reset's) NMI only occurs at a certain cycle on the scanline. It could be that Antic needs to do things that way - there's some breathing space between DList Instruction and PMG fetches and the screen/refresh DMA burst, which in many cases keeps it busy for most of the remainder of the scanline.

 

All that aside though, you'd think they would have tested for contention issues like we're having, and likely could have implemented the simple fix of extending /NMI by a couple of cycles.

 

The funny thing is that it doesn't really matter how long NMI is, as long as it's cleared before the next one. Inverting NMI makes Chris' sound code work great, so that way NMI is asserted for all but 2 cycles of each line. With one chip it could be extended by resetting a counter that counts for 8 or 16 cycles (74LS190 type with TC routed into /CE, and /NMI into /PL), but the inversion method works too.

 

Atari may have been trying to leave as much room as possible on the NMI line for other devices to use it since they can't be stacked like IRQ requests (edge vs level triggering).

Link to comment
Share on other sites

But, by inverting NMI, won't that delay them by 2 cycles?

 

Problem is - there's a fair bit of code that does near the limit of stuff before STA WSYNC and 2 cycles extra wait could be enough to cause it do the WSYNC too late and miss a scanline.

 

Yes, they'd be delayed 2 cycles but it's interesting that it worked.

Link to comment
Share on other sites

Sounds fair that it does work... all that's happening is the 1->0 transitions are 2 cycles late.

 

Unsolicited NMIs on the XL/XE are just assumed to be VBlanks, I guess if one was to sneak through on powerup it might upset things a little.

 

But, since they rely on the transition and not the level, I doubt you'd be getting any dubious behaviour other than that 2 cycle delay.

Link to comment
Share on other sites

Here's /NMI vs phase2 clock (ph2). The 6502 datasheet states that /NMI will be sampled during the ph2 interval (ph2 high). So, NMI properly falls and rises during the ph1 part of the clock.

 

The problem must be that the 6502 requires not only a falling edge (one high sample followed by one low sample of /NMI) but NMI must also remain low until the some part of the CPU's interrupt sequencer is ready (not tied up in the early stages of an IRQ). I bet other 6502-based computers have longer NMI assertions, or ones that must be cleared.

 

Perhaps, the C64 doesn't have the problem because the interrupt/NMI handling is at 1.023Mhz and in making a 1.79Mhz version the circuitry wasn't sped up to deal with it (or wasn't debugged at that speed).

Link to comment
Share on other sites

When I hit warm reset, I get the same color pattern so previous INIT settings didn't have any impact in that case (this is reset when I'm not hitting the NMI cycle with the IRQ). And this is an Atari 800 so it's not a chip reset.

 

When you hit Reset, it doesn't much matter if it's a chip or soft Reset.

 

The OS warmstart clears all the Hardware Registers, so any previous syncing of Timers is lost.

 

But... that only becomes apparent to someone using Timers if you've taken measures to change their alignment in the first place. Like I theorized before, you should get the same Timer alignment on a given machine every time because the warmstart clear-register routine hits WSYNC as well as putting Pokey into Init, so it causes a "default" alignment that should be the same on any machine using the same Operating System revision.

 

I thought you were talking about INIT state having a memory of previous setting so even with one WARM RESET-- you have initialized it twice with same cycle position.

Link to comment
Share on other sites

I don't think the clock speed on the 6502 would have bearing on NMI handling. But, the number of cycles NMI is held low might.

 

The C64's differing case seems to be that CIA NMIs at least are held low until cleared by the program. No idea what the Restore key NMI does, maybe it's a momentary thing too, like Atari ?

 

It's yet to be shown if in fact the C64 has the same issue when using CIA NMI vs IRQs, I guess I should try and test that out. At least it might help prove once and for all if the Atari's problem is Antic, or it's just a generic 6502 issue that can potentially crop up on any machine.

Link to comment
Share on other sites

I don't think the clock speed on the 6502 would have bearing on NMI handling. But, the number of cycles NMI is held low might.

 

The C64's differing case seems to be that CIA NMIs at least are held low until cleared by the program. No idea what the Restore key NMI does, maybe it's a momentary thing too, like Atari ?

 

It's yet to be shown if in fact the C64 has the same issue when using CIA NMI vs IRQs, I guess I should try and test that out. At least it might help prove once and for all if the Atari's problem is Antic, or it's just a generic 6502 issue that can potentially crop up on any machine.

 

Yeah, but even if NMIs are held down low for long time the fact that both occurred on same cycle and IRQ getting serviced first would flip priorities at least and if IRQ cleared the NMI request the NMI would never occur.

Link to comment
Share on other sites

I don't have source with me on this disk I'm traveling with, I'll post the source code when I get home but I am getting a case where 3 consecutive cycles where I set INIT produce the same color patterns meaning the phase didn't move at all. (This is on Atari 800).

 

I don't see why it would make any difference when doing this on 800 or 800xl.

What would be nice is if you could post a .xex or .atr of the test prog when you get home.

 

One difference on 800 vs 800XL is the CLD instruction is missing from NMI/IRQ handlers on 400/800 OSes.

 

[it's been raining here in Tolland, MA and signal quality sucks-- finally got to log-in tonight; blackberry phones seem to be working fine though.]

Link to comment
Share on other sites

One difference on 800 vs 800XL is the CLD instruction is missing from NMI/IRQ handlers on 400/800 OSes.

 

OK, but then we can emulate the same effect on 800xl as on 800xl we can redefine IRQ handler.

Anyway, if it is just a 2-cycle difference (due to the extra CLD), it won't change the idea.

Maybe some shift in the results.

Link to comment
Share on other sites

I'm going to test this circuit for stretching NMI. It only involves one chip and no extra parts.

 

 

EDIT: Results attached (stretched pulse on top). Works perfectly when playing sample.

post-3606-125105341138_thumb.jpg

post-3606-125105429836_thumb.png

Edited by Bryan
Link to comment
Share on other sites

I've just confirmed the behaviour using similar technique (enable SEROC IRQ at known times).

 

Burn 5 cycles after WSYNC then Store 8 to IRQEN. It blocks any DLI, except those types that are on single scanline modes.

 

To block single-scanline DLIs, strangely enough, you just need to burn 4 cycles after the DLI.

Might be just the way Antic does DLIs... if it's a single scanline mode line then it must start the NMI one cycle earlier.

 

I also tried the same technique but executing a 7-cycle 6502 Instruction... no problematic effects caused there at all.

 

Also tried varying the delay after WSYNC - no effect. It would seem that you need to store to IRQEN exactly on cycle 112 (or cycle 111 if dealing with single-line modes). But it could be that POKEY has some delay before triggering the IRQ once we've enabled it.

 

What mode/width are you using? WSYNC can be delayed by up to two cycles if playfield or refresh DMA extends to the end of a scanline. I've also suspected that you may encounter yet another cycle delay if the cycle immediately after STA WSYNC is contended, but unfortunately, I can't find my test app to confirm this.

 

Can we have some test code that shows best/worst case of WSYNC cycle delays? I have just been doing double WSYNCs when there is probability of DMA cycles to get exact positioning on the scanline.

Link to comment
Share on other sites

The Antic Timings text document would help there.

 

Delays of WSync extending it beyond the normal restart should only occur in widescreen width or standard + scrolling.

 

DMA Contention immmediately following a WSync store? I think it doesn't matter - the 6502 should still fetch the first byte of the following instruction.

Link to comment
Share on other sites

The Antic Timings text document would help there.

 

Delays of WSync extending it beyond the normal restart should only occur in widescreen width or standard + scrolling.

 

DMA Contention immmediately following a WSync store? I think it doesn't matter - the 6502 should still fetch the first byte of the following instruction.

 

I was in normal 40 column graphics 0 text mode and my timer starting position was going off by one cycle and sometimes correct until I started doing two consecutive WSYNCs. Now it always starts at a constant position.

Link to comment
Share on other sites

Well, when you have a badline, the number of cycles available drops considerably... also you have the DList Instruction at the very start of it.

There's also the consideration that if you store to WSync too late, it misses the boat and you end up a scanline later than you'd hoped for.

Link to comment
Share on other sites

One thing I previously tried was connecting Antic's /NMI to its reset interrupt input. I was thinking that perhaps I could trick it into doubling up the NMI pulse, but of course it didn't work since reset is only sampled at certain intervals.

 

Anyway, I don't think we can count on anyone implementing a hardware fix. The best solution is a fool-proof set of interrupt timing routines.

Link to comment
Share on other sites

Agreed... I can't see people doing a hardware fix for the sake of having maybe half a dozen games (that don't yet exist) work.

Plus there's always the possibility that it might break existing stuff that's out there.

 

I doubt it would break anything because as far as we know, the 6502 will always be oblivious to when the rising edge of /NMI happens and it would be very strange to rely on the /NMI dropping behavior for anything. Too bad Atari didn't catch this bug when they modified Antic with the extra refresh row for the XL machines.

Edited by Bryan
Link to comment
Share on other sites

Agreed... I can't see people doing a hardware fix for the sake of having maybe half a dozen games (that don't yet exist) work.

Plus there's always the possibility that it might break existing stuff that's out there.

 

I doubt it would break anything because as far as we know, the 6502 will always be oblivious to when the rising edge of /NMI happens and it would be very strange to rely on the /NMI dropping behavior for anything. Too bad Atari didn't catch this bug when they modified Antic with the extra refresh row for the XL machines.

 

Here's a fix that seems to work (swap 6502 with 65c02) with one jumper:

post-12094-125113560655_thumb.jpg

Link to comment
Share on other sites

Well, I was reading the old 1976 datasheet on the 6502 and discovered this tidbit on page 51:

 

The /NMI signal must be low for at least two clock cycles for the interrupt to be recognized, whereupon new program count vectors are fetched. (shouldn't that be program counter?)

 

So, Atari followed the minimum requirement of the official spec and MOS didn't know about the bug.

Link to comment
Share on other sites

Well, I was reading the old 1976 datasheet on the 6502 and discovered this tidbit on page 51:

 

The /NMI signal must be low for at least two clock cycles for the interrupt to be recognized, whereupon new program count vectors are fetched. (shouldn't that be program counter?)

 

So, Atari followed the minimum requirement of the official spec and MOS didn't know about the bug.

 

Unknowingly they seem to have fixed it in some variations of the 6502.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...