Jump to content
IGNORED

How can POKEY IRQ Timers mess up NMI timing?


Sheddy

Recommended Posts

I've got a bit lost in this thread with all the Pokey talk and timers, but I thought I'd mention this that I was just reading..

http://members.lycos.co.uk/leeedavison/6502/vic20/isa/index.html

 

It's not of direct relevance really, but it is interesting in that he states that the 6502 in the Vic he was using was missing NMIs, and goes on to explain why..

Though the 6502 NMI interrupt is described as edge triggered it is actually sampled on each Ø2 trailing edge and needs to be seen to be idle on one cycle and active on the next to trigger. The idle time of the interrupt from the card was too short for this to occur reliably so eventually a change would be missed.

 

Just seemed relevant and I didn't realise this was the case, and hadn't seen this mentioned in here.. I'll go away now :)

It is a good read though, hooking up ISA cards to Vic-20s ;)

Link to comment
Share on other sites

I've got a bit lost in this thread with all the Pokey talk and timers, but I thought I'd mention this that I was just reading..

http://members.lycos.co.uk/leeedavison/6502/vic20/isa/index.html

 

It's not of direct relevance really, but it is interesting in that he states that the 6502 in the Vic he was using was missing NMIs, and goes on to explain why..

Though the 6502 NMI interrupt is described as edge triggered it is actually sampled on each Ø2 trailing edge and needs to be seen to be idle on one cycle and active on the next to trigger. The idle time of the interrupt from the card was too short for this to occur reliably so eventually a change would be missed.

 

Just seemed relevant and I didn't realise this was the case, and hadn't seen this mentioned in here.. I'll go away now :)

It is a good read though, hooking up ISA cards to Vic-20s ;)

Nice find - I am enjoying this thread immensely, even though the coding that is used to find this stuff is over my head.

 

Stephen Anderson

Link to comment
Share on other sites

The "edge-triggering" must mean that the 6502 compares the previous cycle's latched copy of /NMI with the current state of the /NMI pin and looks for them to be different if so, then the /NMI signal can be let through just like /IRQ.

 

My guess is still that Antic's presentation of /NMI to the 6502 happens at a part of the cycle where the previous state of /NMI can be lost if a new /IRQ is found. It's got to be something unique to the way Antic does things because other 6502-based machines don't seem to have this problem (although, I suppose it could be Pokey with the odd timing). Obviously the 65C02 has more robust interrupt sampling.

 

My next step is going to be to put the /IRQ and /NMI signals on the monitor and watch the interactions (as soon as I have time).

Link to comment
Share on other sites

The "edge-triggering" must mean that the 6502 compares the previous cycle's latched copy of /NMI with the current state of the /NMI pin and looks for them to be different if so, then the /NMI signal can be let through just like /IRQ.

 

Found this on the 6502 forums where coincidently that exact problem was being discussed..

Last post in the thread..

http://forum.6502.org/viewtopic.php?t=225

 

I couldn't find a straight, definitive answer from my books on the cycle-by-cycle response to the NMI input, so I tried it on a Rockwell 65c02.

 

I found that whether the NMI line is doing a short negative pulse or a positive one, as long as the processor can see a high state at one phase-2 falling edge and a low state at the very next phase-2 falling edge, regardless of where those edges are in the progress of an instruction, the NMI is registered and the sequence will begin when the instruction is finished. IOW, it's not just the last ph2 falling edge of an instruction that looks at the NMI input (as I previously thought), but rather every ph2 falling edge.

 

The NMI-high time in Lee's case would not have to be even a whole cycle long (let alone a whole instruction long) if it went up shortly before a ph2 falling edge and was pulled back down right after the same edge. So if it were timed just perfectly on a processor whose NMI set-up and hold times were 10ns, it is conceivable that an NMI pulse hardly longer than 20ns would indeed be recognized. If the exact timing is not known however, the pulse needs to be over one cycle in length to be guaranteed any recognition.

 

Of course if you're using a passive pull-up resistor on the NMI\ line, the greater concern will be whether the line had time to float (charge) up to a logic-high state before being pulled back down.

 

It would be too tedious to test this single-clock NMI pulse matter on all clocks of all instructions and all manufacturers, but I expect I'd get the same result.

Link to comment
Share on other sites

I tried all sorts of delays between STA zero and 3 to SKCTL and still 15Khz interrupt is quantized to certain positions. For example, if I burn 39 cycles after WSYNC with instructions then whether I burn 39,40, or 41, I get the same exact color pattern. Similarly, burning 42,43,or 44 cycles produces the same pattern. Now take into account the refresh cycle that's lurking there, it's at least /4 quantization factor.

 

How about the following code?:

lda  #0
ldx  #3
sta  skctl
sta  stimer
sta  wsync
stx  skctl
sta  stimer

 

I might be wrong but, as far as I remember, in some case one needs to trigger STIMER 2 times to be sure the (15khz or other) divisor is reset with 100% certainty.

 

The resetting of STIMER (53769) does work w/o any delays but trying to set the phase for the 15Khz timer using resetting of SKCTL was problematic as not all phase shift cycles (0..113) seem to work.

Link to comment
Share on other sites

POKEY was specifically developed for the computer range the way I see it. Otherwise, why have 8 Pots, and why have keyboard support at all, especially given that the keyscan can't handle multiple presses.

 

Atari was still using discreet logic sound for some arcade games even after the computers came out... Asteroids Deluxe used discrete + Pokey but plain old Asteroids didn't.

 

Re - sync of 16 Khz Timers, I got them to move... the only reason they appear locked to Antic is like I said before - the warmstart OS routine is the cause of that.

 

You can't move them with STIMER and with SKCTL they don't seem to work for all cycles. Perhaps, I will test SKCTL resetting of 15Khz timer with some more machines.

Link to comment
Share on other sites

There's some cycles you just can't reach anyway thanks to Refresh.

 

I am curious about a couple of things... like does having a voice in 1.79 Mhz or 16 bit mode while going into INIT state have any bearing on the accuracy we can sync to.

 

1.79Mhz mode with 8-bit or 16-bit divisor did not affect the cycle where NMI got disabled and I was using timer interrupts so it did not have any effect on timer accuracy.

Link to comment
Share on other sites

What I mean is I'd like to know if the settings that exist when you go into INIT have any bearing on the alignment once you come out... given that once you come out of Init, you'll likely use different AUDCTL settings.

 

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.

Link to comment
Share on other sites

The resetting of STIMER (53769) does work w/o any delays but trying to set the phase for the 15Khz timer using resetting of SKCTL was problematic as not all phase shift cycles (0..113) seem to work.

 

I also did a small test, but, isn't this caused by the memory refresh cycles?

Can you post some source?

 

I'm rather sure the timer itself can be synced to any desired position, at least when the INIT procedure doesn't coincide with a memory refresh or DMA cycle.

Link to comment
Share on other sites

The resetting of STIMER (53769) does work w/o any delays but trying to set the phase for the 15Khz timer using resetting of SKCTL was problematic as not all phase shift cycles (0..113) seem to work.

 

I also did a small test, but, isn't this caused by the memory refresh cycles?

Can you post some source?

 

I'm rather sure the timer itself can be synced to any desired position, at least when the INIT procedure doesn't coincide with a memory refresh or DMA cycle.

 

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).

 

Interestingly, when looking at this disk I have with me, I found this source code for stabilized VBIs. You have to write your code in such a way that it's aligned on certain cycle boundaries and then you don't need to waste time with WSYNC:

 

;*** ATVBI.ASM: Makes VBI perfectly stable on Atari 800XL by Krishna Software Inc.

;*** This also shows how to inhibit VBI by causing IRQ to occur on same cycle as VBI...

TIMERFREQLSB = 53760

TIMERFREQMSB = 53762

WSYNC = 54282

VCOUNT = 54283

 

DOSVEC = 10

CASINI = 2

WARMSTART = 58484

VMIRQ = 534 ;hardware irq ptr

VBI = 546 ;Vertical Blanking Intr (NMI)

 

ORG = 600h

;DW 0FFFFh

;DW StartAdr

;DW LastOffset-1

DB 0,3 ;# of sectors to load 1..255

DW ORG

DW StartAdr

Rts

StartAdr: Lda #MyReset,L

Sta CASINI

Lda #MyReset,H

Sta CASINI+1

Lda #0

Sta 580

Lda #2

Sta 9

Jmp WARMSTART

MyReset: Lda #2

Sta 9

Lda #MyReset,L

Sta CASINI

Lda #MyReset,H

Sta CASINI+1

Lda #128

Sta 40000

Lda #160

Sta 40080

Lda #65

Sta 40160

Sei

Lda #0 ;no VBIs nor DLIs for maximum performance

Sta 54286

Sta 54287

Sta 53774 ;disable all IRQs

Sta 54272 ;turn off screen

Lda #56

Sta 54018 ;set direction ctrl for 54016

Lda #255 ;set all pins for output

Sta 54016

Lda #60

Sta 54018 ;set data register at 54016

Lda #254 ;output zero on bit 0 (Pin 1)

Sta 54016

Lda #TimerTwoIRQ,L ;general IRQ routine but we use only for timer #2

Sta VMIRQ

Lda #TimerTwoIRQ,H

Sta VMIRQ+1

Lda #MyVBI,L

Sta VBI

Lda #MyVBI,H

Sta VBI+1

;Lda #80 ;40 for join channels 3,4; +80 for channels 1+2 @1.79Mhz

Lda #1+40 ;0 for 63Khz timers using 8-bit divisors (1 for 15.7Khz)

;+16 for 16-bit divisor on ch.1+2

Sta 53768

Lda #165 ;lsb 172-7 for 60Hz (86-7 for 120Hz) [5,1 for 262 scanlines @15.7Khz]

Sta 53764 ;timer #2 freq = 1789790/[A+7] or 15980/[A+1]

Lda #116 ;msb for rate divisor A (58 for 120Hz, 116 for 60Hz)

Sta 53766

Lda #0 ;disable IRQs for now

Sta 53774 ;enable/disable IRQs

Lda #12

FindEOS: Cmp VCOUNT

Bne FindEOS

Lda #1 ;was 123

FindVBITrigger: Cmp VCOUNT

Bne FindVBITrigger

Sta WSYNC

Nop

Nop

Sta WSYNC

Lda #64

Sta 54286 ;enable VBI

;Jmp Do3Cycle ;inhibits VBI at cycle 7,8,9 after WSYNC/STIMER (on XL)

Do3Cycle: ;Nop

;Nop

;CLI

;Sta 53769 ;start timer counter

;CLI

;Lda #34

;Sta 54272

IdleLoop: ;put your code here

Lda 0

Lda 1

Lda 2

Lda 3

;Lda 4

Nop

;Jmp NextLbl

NextLbl: Jmp IdleLoop

 

;*** There's a 2 cycle difference between old OS like on Atari 800 and 800XL OS. There's no CLD instruction

;*** on older OSes before vectoring through [534].

TimerTwoIRQ: Pha

;Lda VCOUNT

ChgColor: Lda #15

Sta 53274 ;change register (like color for example)

Lda #0

Sta 53774

Lda #4

Sta 53774

Inc ChgColor+1

;Lda #96

;Sta 53274 ;change register (like color for example)

Pla

Rti

 

MyVBI: ;following is experiment with vbi cycle exactness (OS uses 31 cycles before our routine

;gets control. Our exit procedure is 22 cycles and vectoring uses some. This

;VBI is 14+4*(256*9-1) cycles = 9226 + 2358 refresh cycles + 60 cycle overhead.

;29868-11644 = 18224 cycles left for background (align to 67*17*16).

Lda #255

Sta 54016 ;output "1" in pin 1 on Left Joystick for VBI started

Ldx #0

NxtX: Stx 53274

Dex

Bne NxtX

NxtX2: Stx 53274

Dex

Bne NxtX2

NxtX3: Stx 53274

Dex

Bne NxtX3

NxtX4: Stx 53274

Dex

Bne NxtX4

Lda #254 ;output "0" on pin 1 for end of VBI (for now one scanline time)

Sta 54016

 

 

Pla ;reverse stack from OS VBI entry (4 cycles)

Tay ;$A8 ;2 cycles

Pla ;$68 ;4 cycles

Tax ;$AA ;2 cycles

Pla ;4 cycles

Rti ;6 cycles

 

;LastOffset: DW 2e0h,2e1h,ORG

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.

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.

Link to comment
Share on other sites

OK, for what it's worth I've got the 'scope hooked up to the NMI line on Antic.

 

It seems that Antic only pulls NMI low for a very short time. I'm getting a kinda jittery graph, but it only looks in the order of 1 microsecond, so possibly only 1 or 2 cycles.

Link to comment
Share on other sites

OK, for what it's worth I've got the 'scope hooked up to the NMI line on Antic.

 

It seems that Antic only pulls NMI low for a very short time. I'm getting a kinda jittery graph, but it only looks in the order of 1 microsecond, so possibly only 1 or 2 cycles.

 

Have you tried to lengthen the signal with a capacitor? Maybe the problem vanishes then...

(Not only the Falcon030s need a 'clock-patch'... ;) )

Link to comment
Share on other sites

Didn't think of that. I only tested the pure tone and fairly briefly at that.

It was a bit of work doing it all - the machine has bad RF so I had to solder up a plug to get composite to an RCA jack then use my capture card to provide a monitor.

 

I've put the machine all back together, so end of that session.

 

I've sampled the triangle in the past, albeit through the monitor port, with both soundcard input and oscilloscope. The pics are posted somewhere, I think you might have been involved in the same thread/s.

Link to comment
Share on other sites

The biggest difference I notice between looking the audio output and Pokey's audio pin is that the audio is high-pass filtered on its way to the buffer/mixer circuit (which combines SIO audio and the keyclick). That's what distorts the square waves Pokey produces. If you look at the sawtooth, you'll probably notice a lot of high-frequency fuzz on it.

Link to comment
Share on other sites

I don't see much point really.

 

It's not the kind of "fix" like putting the Chroma line back in... you'd end up with a machine that behaved like nobody elses.

 

Hmm - it seems so, that the existing software library doesn't have a problem with this issue since it doesn't use this feature.

If it is a kind of malfunction, the system req. for the software relying on correct IRQ handling could allot the existance of a HW-patch.

Additionally such a fix could prove the 'NMI is to short'-theory first...

Edited by Irgendwer
Link to comment
Share on other sites

I just looked on the scope and sure enough, NMI is held for 2 cycles only (about 1116ns). This means there is no correlation between the NMIST bits and the state of the NMI pin. Once I find my other scope probe, I can determine what the phase relationship to the clock is.

 

EDIT: Well, the problem is easy to fix. If you invert /NMI on the way into the CPU, all NMI's work 100%, but that will shift the response to it by 2 cycles (you have to wait for a rising edge to get a falling edge). The better way is probably to extend it a wee bit.

 

EDIT2: Hmm.. the pages of the Antic datasheet that deal with NMI's are missing. I'm experimenting extending /NMI.

Edited by Bryan
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.

post-3606-12509781001_thumb.jpg

Edited by Bryan
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...