Jump to content
IGNORED

POKEY serial and IRQ timing details


HiassofT

Recommended Posts

I was working on my highspeed SIO code again and tried to analyze some timing details, but the docs out there were a little bit unclear and sometime contracting each other. So I decided to do my own tests. It would be great if some of you could repeat these tests and check the results, plus my code.

 

Doing the test is quite easy, the only additional hardware device required is a wire to connect the SIO command line with SIO data input. First of all, here's the link to the test code (including source), plus a the logicanalzer sample of checking IRQST at cycle 143 (irqst-143.vcd, you can use gtkwave to view this file):

http://www.horus.com/~hias/tmp/pokeytest-1.0.zip

 

The test-setup is quite simple: I use cycle-exact code to control the SIO command line (driven by PIA), which acts as a signal-source for Pokey. This is used to transmit a byte (usually $81) at pokey divisor 0 - 126kBit/sec, or 14 cycles per bit. I setup the code so that the startbit begins in cycle 70 (so this is "cycle 0" of the transmission) of a scanline and the stopbit ends in cycle 95 (included, that is cycle 139 of the transmission) of the next scanline. Therefore the Antic refresh-cycles don't disturb the beginning and end of transmission where I wanted to do my tests.

 

Whenever I now mention cycles, I now mean transmission cycles (not scanline-cycles). Counting from 0 to 139 is easier than from 70 to 114+95 :-) BTW: internally in my test-program I calculate with scanline-cycles, but the output of the program is in cycles based on the start of the transmission.

 

BTW: for my tests I used a 600XL and a 800XL with all the SIO-caps removed, tests with a 130XE and a 800XL where the caps were still in place resulted in a shift by one cycle (eg. cycle 143 on the 600XL and 144 on the 130XE).

 

So, let's have a look at cycle -1 and 0:

post-9299-128275263851_thumb.png

In cycle -1 $34 is written to PBCTL (see PIA_CS going low). 250ns after the beginning of cycle 0 SERIN at the pokey goes low. Since pokey samples SERIN at the end of each cycle, this is our cycle 0.

 

Then I wanted to reproduce my old tests, where I found out that pokey samples SERIN on the 12th of 14 cycles (i.e. cycle 11).

 

The first test sets SERIN high beginning at cycle 121..125 (these are the last 5 cycles of bit 7). Again, serin goes high at ~250ns within these cycles, pokey samples at the end of the cycle. If SERIN is set early enough, a correct $81 is received, if it's set to late, a $01 is received.

 

This test ran fine, setting SERIN at cycle 121..123 resulted in a correct "$81", setting it at 124 and 125 resulted in "$01".

 

I then redid this test with the stopbit at cycles 135..139, the difference here is that the received byte will always be $01, but now SKSTAT reports a framing error if it samples a "0" bit. Like with the bit 7 test, the first 3 cycles resulted in SKSTAT=$FF (everything fine), whereas setting SERIN high in the last 2 cycles was too late and resulted in a framing error (SKSTAT=$7F).

 

So: Stopbit sampling is identical to normal bit sampling and occurrs at the end of cycle 11 (counting from 0 to 13) of each bit. The stopbit is sampled at the end of cycle 137.

 

Now to the next checks: I wanted to find out how long it takes until the reception is reported in IRQST (bit5=low). I setup my code so that it transmits a $81 byte and then checks IRQST in cycles 141..145. In cycles 141 and 142 IRQST bit 5 was still high (i.e. nothing received), but in cycle 143 the check was fine. So it takes 5 cycles (138-142) until pokey signals the reception of a byte. Here's the logic-analyzer sample of cycles 143:

post-9299-128275432339_thumb.png

POKEY_CS goes low and reports the received byte with D5=0.

 

The interesting thing about this screenshot is that the IRQ pin goes low at the end of cycle 143 (i.e. although Pokey is able to report reception during cycle 143 the IRQ pin "fires" at the beginning of cycle 144).

 

The IRQ-pin stuff was interesting, so I had a look at how long it takes to shutdown the IRQ afterwards (write $00 to IRQEN):

post-9299-128275457234_thumb.png

At the left is the cycle writing to IRQEN, 460ns after the end of this write cycle IRQ goes high. So IRQ is still active in the cycle after the write.

 

And I did another test, I wanted to find out how long before the signalling of the reception IRQEN has to be setup. Again I set up the code to transmit a $81 byte, then wrote $20 to IRQEN at cycles 141..145 (and later checked IRQST). At cycles 141&142 this worked fine (IRQST bit 5 was low), at cycles 143..145 it failed.

 

So: enabling the interrupt just has to be finished before the IRQ occurs, there's no additional delay needed. If IRQEN was set at cycle 142, the interrupt occuring in cycle 143 was successfully reported.

 

Finally, here's a screenshot of the output on my 800XL:

post-9299-128275515119_thumb.png

In each test, the fist line is the cycle number (in hex), the following lines contain the values of IRQST, SKSTAT and SERIN corresponding to these cycles.

 

While all these results seem to be quite clear, I still have a question that I couldn't answer myself:

 

The Altirra Hardware Reference Manual mentions a 3 cycle delay from IRQST to the IRQ being executed. In my tests I only saw a 1 cycle delay, and my 6502 docs don't mention any delay for the IRQ pin (only a 2 cycle delay for NMI). Does the IRQ input also have this 2-cycle delay like NMI?

 

so long,

 

Hias

Link to comment
Share on other sites

Note that the Altirra hardware manual is talking about observable behavior -- it doesn't describe the behavior of the IRQ line, which is never user or program visible.

 

I can only speak from the software side of things, but from what I can tell, the IRQ does need to be held for a minimum time before the 6502 will acknowledge it. The way I arrived at 3 cycles was to use a POKEY timer at 1.79MHz with a small delay and then measure the difference between when IRQST flips and when the IRQ routine executes. In my test, IRQST shows an interrupt 14 cycles after the write to STIMER, and using two patterns of NOPs skewed by one cycle I see the IRQ handler firing at 16 and 17 cycles later, respectively. I don't think using a longer instruction matters, although I can't find a test like that in my test directory right now. I've attached my tests in case you're interested.

 

The timing for disabling IRQEN is indeed nasty, because the IRQ can actually fire in that one cycle window after you've tried disabling all IRQs. I figured this out when I was trying to get Cup of Tea to authentically crash as it occasionally does on a real Atari.

 

By the way, I recently discovered that Altirra has an off-by-one cycle error in IRQ acknowledge timing, which I'm planning on fixing in 1.8 (post 1.7). I discovered it when I couldn't get IRQ timing fully correct between timers firing and the CPU enabling a hot serial output complete interrupt through IRQEN.

stimer-tests.zip

Link to comment
Share on other sites

too much beer for me to understand... ;)

Here's the short version - timing details of an asynchronous transmission at POKEY divisor 0:

 

During Cycle 0 DataIn goes low and Pokey detects the start-bit at the end of cycle 0.

At the end of cycle 11 Pokey samples the start-bit.

At the end of cycle 25 Pokey samples bit 0.

...

At the end of cycle 123 Pokey samples bit 7.

At the end of cycle 137 Pokey samples the stop-bit.

Cycle 139 is the last cycle of the transmission.

Pokey isn't able to detect a new start-bit in cycle 140, so a 1-cycle delay is required and the next start-bit may begin in cycle 141.

By the end of cycle 142 IRQEN has to be setup, otherwise Pokey will not generate a "serial input ready" interrupt.

In cycle 143 Pokey signals the receipt of a byte in IRQST, at the end of this cycle Pokey pulls the IRQ line.

 

That's all :-)

 

so long,

 

Hias

Link to comment
Share on other sites

Note that the Altirra hardware manual is talking about observable behavior -- it doesn't describe the behavior of the IRQ line, which is never user or program visible.

I know, but it's still a real wonderful resource, also for hardware guys like me :-). Thanks a lot for putting this all together!

 

I can only speak from the software side of things, but from what I can tell, the IRQ does need to be held for a minimum time before the 6502 will acknowledge it. The way I arrived at 3 cycles was to use a POKEY timer at 1.79MHz with a small delay and then measure the difference between when IRQST flips and when the IRQ routine executes. In my test, IRQST shows an interrupt 14 cycles after the write to STIMER, and using two patterns of NOPs skewed by one cycle I see the IRQ handler firing at 16 and 17 cycles later, respectively. I don't think using a longer instruction matters, although I can't find a test like that in my test directory right now. I've attached my tests in case you're interested.

OK, nice idea! I guess you setup and IRQ handler and check the return-address on the stack, so you know where the interrupt occured.

 

I'll try to setup a similar testcase, plus hook up my logic analyzer to see what's going on. Then we should be able to solve this mystery.

 

As as side note: As always the (6502) datasheets and specs miss the intersting stuff. At least the WDC 65C02 datasheet has some information (which might not be applicable to the 6502, of course) and says that IRQ and NMI are sampled during PHI2=high. But this datasheet doesn't write anything about a 2-cycle (NMI) delay - the Mostek HW manual is the only document I know of containing this information.

 

The timing for disabling IRQEN is indeed nasty, because the IRQ can actually fire in that one cycle window after you've tried disabling all IRQs. I figured this out when I was trying to get Cup of Tea to authentically crash as it occasionally does on a real Atari.

POKEY IRQ signalling is indeed quite strange. I had expeced a delay of approx. 1/3 of a cycle, but it seems to be ~ 3/4 cycle. This explains some of the nasty behaviour :-)

 

so long,

 

Hias

Link to comment
Share on other sites

Here are the logic analyzer screenshots of the IRQ handling. I sampled PHI2, IRQ and A15. With A15 it's easy to identify where the 7-cycle IRQ sequence starts, my code is in low memory $1xxx, so A15=low, the last 2 cycles of the IRQ sequence fetch the IRQ address from $FFFx - so A15 is high. I've marked the start and end of the IRQ sequence with markers A and B, respectively.

 

I did 2 test, one with the NOPs starting at cycle 89 - so all even cycles were occupied by the CPU executing "NOP", and another one with NOPs starting at cycle 90 - so all odd cycles were occupied.

 

post-9299-128282874678_thumb.png

 

post-9299-128282875876_thumb.png

 

We can clearly see the additional 2-cycle delay, most certainly the same as with NMI handling. At the end of cycle 143 IRQ goes low, then the CPU continues with normal operations in cycles 144 and 145 and then starts the IRQ sequence in cycle 146. In the first test the CPU was busy executing the NOP at cycle 146, so the sequence started one cycle later, at cycle 147.

 

So the total delay between signalling the interrupt in IRQST and start of the IRQ sequence is (at least, if some instructions are executed or DMA occurs) 3 cycles.

 

so long,

 

Hias

Link to comment
Share on other sites

Forget about the CPU/IRQ timing, I just discovered an interesting thing:

 

Depending on the Pokey (and maybe CPU) the delay between signalling in IRQST and start of the 7-cycle IRQ sequence may be 2 or 3 cycles. On my PAL 800XL I usually get 2 cycles, the same on my NTSC 800XL, and my PAL 600XL I get 2 cycles if Pokey is cold (i.e. by cooling it down with freezing spray) and 3 cycles when the Pokey has normal temperature.

 

I checked with my logic analyzer, if Pokey is cold, IRQ goes low 40ns before then end of the cycle, if it's warmer it goes low 30ns before (in previous tests I also observed that IRQ was going low at the very end, i.e. 0ns delay between IRQ and PHI2).

 

Here's the sample of the 2 cycle delay:

post-9299-128292152588_thumb.png

 

And here the sample of the 3 cycle delay:

post-9299-128292155702_thumb.png

 

I've also uploaded a new test-program: http://www.horus.com/~hias/tmp/pokeytest-1.1.zip

It contains the new irqtest.atr / irqtest.src code, plus the logic analyzer samples (irq-0x91.vcd and irq-0x93.vcd).

 

The irqtest uses sequences of 2/3/4/5/6 cycle opcodes, started at various cycles (start-cycle number in first line) and the cycle where the IRQ sequence started (second line).

 

On my PAL 800XL it looks like this:

post-9299-128292177052_thumb.jpg

 

On my NTSC 800XL it looks like this:

post-9299-128292187543_thumb.jpg

 

An on my PAL 600XL, when the Pokey is warm, it looks like this:

post-9299-128292188828_thumb.jpg

 

I also observed that on my PAL 800XL, when repeating the test serveral times, sometimes I also get $92 instead of $91 as minimal value.

 

so long,

 

Hias

  • Like 1
Link to comment
Share on other sites

What about stability of your SIO COMMAND line?

 

Have you measured with a scope the waveform slope when it does 0->1 transitions?

 

I found in the past that PORTA output was inconsistent with a visible slope on those transitions, whereas it was virtually instantaneous for 1->0 transitions.

Link to comment
Share on other sites

Forget about the CPU/IRQ timing, I just discovered an interesting thing:

 

Depending on the Pokey (and maybe CPU) the delay between signalling in IRQST and start of the 7-cycle IRQ sequence may be 2 or 3 cycles. On my PAL 800XL I usually get 2 cycles, the same on my NTSC 800XL, and my PAL 600XL I get 2 cycles if Pokey is cold (i.e. by cooling it down with freezing spray) and 3 cycles when the Pokey has normal temperature.

 

I checked with my logic analyzer, if Pokey is cold, IRQ goes low 40ns before then end of the cycle, if it's warmer it goes low 30ns before (in previous tests I also observed that IRQ was going low at the very end, i.e. 0ns delay between IRQ and PHI2).

...

SIO has more complexity than using a simple timer IRQ trigger. In a timer triggerred IRQ, there's no 2*(Audf+7) just Audf+7 so it seems to be more consistent as I get consistent results across all A8s. I guess you need to better define cold. If you boot up the machine then how long before you call it "hot" or not cold?

Link to comment
Share on other sites

What about stability of your SIO COMMAND line?

 

Have you measured with a scope the waveform slope when it does 0->1 transitions?

Sorry, I don't have a scope :-(

 

But according to the samples of my logic analyzer command should be pretty stable. Have a look at irq-0x91.vcd and irq-0x93.vcd: SERIN (measured directly at pokey) goes low at +250ns after I accessed the PIA (at 74.5 us), in both cases. 81.2 us later IRQ goes low (at 155.7 us).

 

All the interesting things happen later, after the IRQ line goes low: in irq-0x91.vcd IRQ goes low at 155.67 us and 600ns (1 cycle) later the 7-cycle IRQ sequence starts (the last 2 cycles of the IRQ sequence, accessing the ROM vectors, start at 159.09 us).

 

My current theory is as follows:

 

- Pokey delays the IRQ line from it's internal registers by some 1/2 - 2/3 cycle.

 

- The CPU needs two falling edges of PHI2 (155.71 and 156.27 us) before it accepts the IRQ and starts the 7-cycle IRQ sequence.

 

- In addition to that, the IRQ input seems to have a setup-time of some 20-40ns (at least with my CPU).

 

I'll try to do some more tests tomorrow and hook up my logic analyzer to my 800XLs, then I'll report back.

 

so long,

 

Hias

Link to comment
Share on other sites

SIO has more complexity than using a simple timer IRQ trigger. In a timer triggerred IRQ, there's no 2*(Audf+7) just Audf+7 so it seems to be more consistent as I get consistent results across all A8s.

SIO stuff is covered by the first test (pokeytest.atr), which is giving consistent results so far. The only variation I could observe was in the case when the SIO caps were in place and thus the signal was skewed (due to less steeper slopes).

 

I guess you need to better define cold. If you boot up the machine then how long before you call it "hot" or not cold?

Current room temperature is some 25° Celsius at the moment, my 600XL reports this minimum $92 immediately after power-up (within 1 minute after switching it on). I have to cool Pokey down (to maybe 10-15° Celsius) to get $91 like my PAL and NTSC 800XLs do.

 

so long,

 

Hias

Link to comment
Share on other sites

I don't think the CPU plays any part in /IRQ assertion.

Not in IRQ assertion but in IRQ execution. The 6502 datasheets I have don't specifically mention when the IRQ input is sampled, but it looks like it's at the falling edge of PHI2. The datasheets only mention a t_DSU (read data setup time) value of 50nS (for 2MHz CPUs), the Rockwell datasheet also contains the SO setup times, which is 50nS, too.

 

Since Pokey asserts IRQ in this very critical period (50ns to 0ns before end of PHI2), we can expect this 1-cycle jitter. If IRQ comes just a little bit too late the setup time is not met and the CPU "sees" IRQ being low 1 cycle later (of course assuming that the CPU really samples IRQ at the falling edge of PHI2).

 

It's kinda like the half cycle delay when you change a colour register... data writes are sampled in the second half of the cycle aren't they?

Usually everything is done at the falling edge of PHI2: On reads the CPU samples the databus at this time, on writes the custom chips etc. sample the databus also at this time. pokey.pdf mentions a data setup time of 130ns, gtia.pdf 50ns. On writes the databus is valid some 20-100ns after the rising edge of PHI2, that would be some 160-240ns before the falling edge of PHI2.

 

I guess the half-cycle delay comes from internal processing in GTIA.

 

BTW: I'd also like to do this IRQ-test using Pokey timers, it would be interesting if IRQ is asserted at the same time. Since I'm not really a pokey (and pokey-timer) expert, could you (or some other pokey expert) provide some code which syncs pokey to some fixed cycle and then activates a pokey timer some 10-150 cycles later? I already had a look at phaeron's code, but need some more hints on how to sync pokey.

 

so long & thanks,

 

Hias

Link to comment
Share on other sites

Not in IRQ assertion but in IRQ execution. The 6502 datasheets I have don't specifically mention when the IRQ input is sampled, but it looks like it's at the falling edge of PHI2. The datasheets only mention a t_DSU (read data setup time) value of 50nS (for 2MHz CPUs), the Rockwell datasheet also contains the SO setup times, which is 50nS, too.

 

The Synertek SY6500 datasheet says the following:

 

Inputs /IRQ and /NMI are hardware interrupts lines that are
sampled during ϕ2 (phase 2) and will begin the appropriate
interrupt routine on the ϕ1 (phase 1) following the comple-
tion of the current instruction.

 

The R6500 Hardware Manual is not specific enough.

Link to comment
Share on other sites

I don't think the CPU plays any part in /IRQ assertion.

Not in IRQ assertion but in IRQ execution. The 6502 datasheets I have don't specifically mention when the IRQ input is sampled, but it looks like it's at the falling edge of PHI2. The datasheets only mention a t_DSU (read data setup time) value of 50nS (for 2MHz CPUs), the Rockwell datasheet also contains the SO setup times, which is 50nS, too.

 

Since Pokey asserts IRQ in this very critical period (50ns to 0ns before end of PHI2), we can expect this 1-cycle jitter. If IRQ comes just a little bit too late the setup time is not met and the CPU "sees" IRQ being low 1 cycle later (of course assuming that the CPU really samples IRQ at the falling edge of PHI2).

 

I don't know the schematics but logic tells me if a combinational circuit does the samething every time, it should give the same results. No jitter should be present unless initial conditions were changed. Now if the results the next time depend on previous conditions, you changed the initial conditions for the next time.

Link to comment
Share on other sites

The Synertek SY6500 datasheet says the following:

 

Inputs /IRQ and /NMI are hardware interrupts lines that are
sampled during ϕ2 (phase 2) and will begin the appropriate
interrupt routine on the ϕ1 (phase 1) following the comple-
tion of the current instruction.

 

The R6500 Hardware Manual is not specific enough.

Thanks for the info, I must have skipped this when reading the datasheets. The WDC 65C02S manual contains a similar description, but unfortunately this isn't precise enough, and also wrong (at least for the 6502C used in the Ataris, can't say anything about the original 6502 chips).

 

"during" phase 2 seems to mean at the falling edge of phase 2 (plus IRQ has to be low some time before to meet the unmentioned setup time). And: this description doesn't mention the 2-cycle (i.e. 2 falling edges of PHI2) delay we are experiencing. I'll post more details later.

 

Anyways, thanks for mentioning this!

 

so long,

 

Hias

Link to comment
Share on other sites

Since Pokey asserts IRQ in this very critical period (50ns to 0ns before end of PHI2), we can expect this 1-cycle jitter. If IRQ comes just a little bit too late the setup time is not met and the CPU "sees" IRQ being low 1 cycle later (of course assuming that the CPU really samples IRQ at the falling edge of PHI2).

 

I don't know the schematics but logic tells me if a combinational circuit does the samething every time, it should give the same results.

Sorry, my fault. Jitter was the wrong word, I should have used "variation" or something like that. When testing a single system, the values are constant and don't "jump back and forth" as jitter suggests. But when comparing different systems, the results are (slightly) different.

 

so long,

 

Hias

Link to comment
Share on other sites

Here's another update:

 

It was a cold any rainy day, ideally suited for sitting at the soldering iron, finally building a PBI adapter for my logic analyzer, and doing some more tests :-)

 

I dug out various 800XLs and discovered that one of it (a stock PAL 800XL) also showed the "delay" (minimum cycle $92) as my 600XL. All other PAL 800XLs and my NTSC 800XL (also stock) had a minimum cycle of $91.

 

Before doing the test I removed the SIO caps, and discovered that my main 800XL still had the cap on the command line. Not a big deal, but I removed it.

 

First I measured the time between IRQ going low and PHI2 going low. With my PAL 800XL that showed the $92 cycle IRQ and PHI2 went low at the same time (in one test, see below, the IRQ went low 10ns before PHI2). On my main 800XL IRQ went low 70ns before PHI2, on my NTSC 800XL it was 60ns before PHI2.

 

This time I decided to run the 3-cycle instruction test (a "LDX $E0", resulting in opcode $A6, followed by $E0, followed by a read to $E0) so we could see a little bit more on the logic analyzer screenshots. NOPs are boring :-) I ran 3 tests (skewed by 1 cycle each, starting at cycle $84, $85, $86 - like in irqtest.atr) with my NTSC 800XL ($91 minimum) and my other PAL 800XL ($92 minimum):

 

First the screenshots of the NTSC 800XL samples:

post-9299-128303615298_thumb.png

post-9299-128303616388_thumb.png

post-9299-128303617703_thumb.png

And now the PAL 800XL samples:

post-9299-128303622667_thumb.png

post-9299-128303624714_thumb.png

post-9299-128303625999_thumb.png

 

I marked the start of the 7-cycle IRQ sequence with marker "A" and the end with marker "B". I also set the base marker to the falling edge of IRQ and the cursor to the falling edge of PHI2. With the NTSC 800XL the difference is a constant 60ns, with the PAL 800XL it's 0 (except for the last test, where it's 10ns).

 

In the first tests ($84) you can see that the CPU is executing the last cycle of the instruction (reading $E0) when IRQ goes low in cycle $8F. In cycle $90 it begins the next instruction (fetching the LDX/$A6 from address $2308), which ends in cycle $92. In cycle $93 the 7-cycle IRQ sequence starts with the first 2 "internal operation" cycles where the CPU issues (dummy) reads to the current program counter. Then the hi PC, low PC and P register are pushed onto the stack and finally the low and high byte of the IRQ vector are loaded. After that the IRQ code at $C02C is executed.

 

The third tests is similar: The CPU started the instruction in cycle $8F (where IRQ goes low), ends this instruction in cycle $91 and begins with the IRQ sequence in cycle $92.

 

Please note that these results are identical for the PAL and NTSC 800XL.

 

Now the second test is different:

 

In cycle $8F the CPU fetches the second byte of the instruction and executes the "read $E0" in cycle $90. The NTSC 800XL already "saw" the second falling edge of PHI2 while IRQ was low, so it starts the IRQ sequence in cycle $91. But not the PAL 800XL, it only "saw" a single falling edge while IRQ was low (at the end of cycle $90), so it starts with a new instruction. So the IRQ sequence is started 3 cycles later, in cycle $94.

 

BTW: all this has nothing to do with PAL vs. NTSC, I also could have compared 2 PAL 800XLs or a PAL 800XL and a PAL 600XL, but thought it'd be easier to distinguish if I'm writing PAL and NTSC.

 

So let's come to some (preliminary) conclusion:

 

So far I only tested with the Pokey serial input ready IRQ, currently I can't say if they are also applicable to other Pokey IRQs (timer etc.). Although I think this is highly probable, we can't be sure until I do some more tests.

 

When writing cycle-exact programs, the next-but-one cycle after the SERIN IRQ is signalled in IRQST should be considered "unsafe". If IRQ goes low a little bit too late the CPU executes another instruction, resulting in a 2-7 cycle penalty. In other words: if IRQST is signalled in cycle X, and IRQ goes low at the end of cycle X, cycle X is unsafe. To get stable results with cycle-exact code it's best to place instructions so that the CPU is executing (but NOT starting) an instruction during this "unsafe" cycle.

 

All other cycles can be considered "safe".

 

so long,

 

Hias

  • Like 1
Link to comment
Share on other sites

And now some really, really strange Pokey weirdness:

 

If the first received byte is exactly 141 cycles long, sampling and IRQ reporting of the second byte occurs 7 cycles earlier.

 

And what's even more weird: if the first byte was 141 cycles long, the second byte may be only 134 cycles long (the stop-bit shortened by 7 cycles) and still the third byte is received fine (sampling and IRQ reporting has identical timing as the second byte - 7 cycles earlier than the usual timing as checked with pokeytest.atr).

 

As soon as a byte is longer than 141 (or 134) cycles Pokey seems to fall back to standard timing.

 

I prepared another testcase (pokeytest2.atr) for testing 2 and 3 byte transmissions with varying byte lengths. You can get it from here: http://www.horus.com/~hias/tmp/pokeytest-1.2.zip

 

Here's a screenshot of what it looks like on my PAL Atari 800XL:

post-9299-128329917114_thumb.jpg

 

Since I needed more space for displaying the interesting results I compacted the output a little bit: The first 2 lines contain the cycle number where a check/test occurred (to be read top-down), and then each line starts with the length of byte 1 (or byte 2, in the second test), followed by the samples (0 or 1, described below).

 

The first test ("byte 1 len vs. irqst byte 2) transmits a $FF byte with "len" cycles (left column), then another $FF byte and then checks bit 5 of IRQST at cycles $84..$93 of the second byte. "0" means the byte has been received, "1" means no byte here. This test determines when the 2nd byte is "received" (relative to the start of the second byte).

 

The first line (byte 1 len = $8C/140) is just for completeness, if the startbit of byte 2 comes before cycle 141 pokey doesn't recognize it and thus it will miss the byte (or sync to the next hi->lo transition of SERIN, which doesn't happen here).

 

The second line shows the interesting case of the $8D/141 cycle first byte: The reception of the second byte is reported at cycle $88/136 after the startbit.

 

The third line shows the standard case, as we already know it: reception is signalled at cycle $8F/143.

 

I also tested various other byte 1 lengths (up to 157 cycles), but the results were identical to the third line, so I skipped them from this test.

 

 

The second test ("byte 2 len vs. irqst byte 3") does a similar check: at first it transmits a $F0 byte with 141 cycles, then another $F0 byte with $85/133..$87/135 cycles, then a $FF byte and then samples IRQST at cycles $84..$93 of byte 3. Again, this check should tell us when the 3rd byte is "received".

 

The first line is again a dummy check: $85 cycles is too short (as $8C cycles in the usual case), so Pokey won't see the 3rd byte at all.

 

The second line ($86/134 cycles) is interesting, again: the byte is received at cycle $88, like the second byte in the previous test (but note that in this test the second byte was only 134 cycles long). So Pokey seems to have "locked in" to the $86/134 rhythm (again, note that the last IRQ was reported at cycle $88 of the second byte, so the difference between IRQ 2 and IRQ 3 is also $86 cycle - just like the byte length).

 

The third line with a $87/135 cycles byte shows Pokey falling back to standard timing again. Reception is reported after $8F cycles, as usual. I also did some more tests with longer bytes, but the result was identical ($8F), so I skipped them in this test, again.

 

 

The third test ("byte 2 bit 7 sampling") checks the sampling of the second byte. At first a $FF byte with $8D/141..$8F/143 cycles is transmitted, then serin is kept low until cycle $70..$7D and bit 7 of the received byte is output on screen. Similar to the earlier pokeytest.atr, this should result in "1" (i.e. a $80 byte received) if everythhing was fine, or in a "0" (i.e. a $00 byte received) if bit 7 was set high too late.

 

The first line shows the results for our well-known $8D/141 cycles byte before our testing byte: SERIN is sampled at cycle $74 (7 cycles before the usual cycle $7B). There's the same 7-cycle shift as in the IRQ-reporting case.

 

The next two lines ($8E/142 and $8F/143 cycles byte 1) show the standard case: sampling at $7B. Again, I did some more tests, but with identical results.

 

I captured the second test with my logic analyzer, so here are some screenshots:

 

This is cycle 0 (marker "A"), the first start bit. The cycle starts at (absolute) time 80780 ns, for the descriptions of the screenshots I'll use relative times (like +563ns), since they are easier to convert into Atari cycles. So this cylce "0" has relative time +0 (how surprising :-):

post-9299-128330155067_thumb.png

 

Cycle 141 (+79510 ns, marker "B"): the second startbit,

Cycle 143 (+80630 ns, marker "C"): IRQ goes low, first byte received:

post-9299-128330205979_thumb.png

 

Cycle 197 (+111080 ns): "LDY SERIN" (=$F0) and "LDY SKSTAT" (=$ED), so everything's fine, then set SERIN high for bit 4:

post-9299-128330221334_thumb.png

 

Cycle 275 (+155060 ns, marker "D"): Third startbit. Difference to second startbit (cycle 141) is 134 cycles.

Cycle 277 (+156190 ns, marker "E"): IRQ of second byte arrives. Diff to last IRQ (cycle 143) is 134 cycles. Diff to start of byte (cycle 141) is 136 cycles:

post-9299-128330224136_thumb.png

 

Cycle 301 (+169730 ns): "LDY SERIN" (=$F0) and "LDY SKSTAT" (=$FD), everything's fine again:

post-9299-128330266227_thumb.png

 

Cycle 411 (+231750 ns, marker "F"): "LDA IRQST executed" (=$D7), IRQ goes low. Diff to last IRQ (cycle 277) is 134 cycles, diff to start of byte (cycle 275) is 136 cycles:

post-9299-128330276995_thumb.png

 

Cycle 416 (+234570 ns): "LDA SERIN" (=$FF) and "LDA SKSTAT" (=$FF), so still everything fine :-)

post-9299-12833029666_thumb.png

 

BTW: I don't have an explanation yet why Pokey is shortening the timing when it receives a 141 cycles byte. Maybe resetting the counters is skipped or something like this. But this is just a wild guess, I really don't know what's going on inside Pokey.

 

Going to bed now, have hacked way too much on my Atari the last days. First I ran into this Pokey weirdness, and while I was investigating it and trying to solve my cycle-counting problem with my highspeed SIO code I ran into this CPU weirdness. Finally solved it all now, but I guess I was really close to going completely insane :-)

 

so long,

 

Hias

Link to comment
Share on other sites

Insofar as the timing weirdness... maybe try putting Pokey into INIT state, then re-enable it on some different cycle offsets before you do your testing.

 

Maybe it's the case that on certain cycle boundaries it gets busy doing other stuff and ignores the serial subsystem or something.

Link to comment
Share on other sites

Insofar as the timing weirdness... maybe try putting Pokey into INIT state, then re-enable it on some different cycle offsets before you do your testing.

 

Maybe it's the case that on certain cycle boundaries it gets busy doing other stuff and ignores the serial subsystem or something.

I'm not sure if I understood you right. The results I'm getting are consistent, the first byte at divisor 0 always has to be at least 141 cycles long, otherwise pokey doesn't recognize the startbit of the second byte. But, yes, I could try initing the Pokey, maybe it will accept a first byte with less than 141 cycles in some case (if this is what you meant).

 

Otherwise, this timing weirdness is not really a bug, as serial transmission runs fine, but more a "feature" one has to take care of when implementing SIO stuff. One has to be prepared that the time between two received bytes is less than 141 cycles. Before this finding, I assumed that I had (at least) 141 cycles time for each byte.

 

But my tests showed that this assumption couldn't be correct and finally I observed in the logic analyzer samples of my "real world" SIO transmission that the time between two IRQs was alternating in a 134, 148, 142, 134, 148, 142, ... cycle. I had expected it to be almost constant at 141, maybe jittering between 141 and 142 as I used a transmission speed of 125494 bit/sec on the sending side (that is 141.3 PAL Atari cycles per byte). I most certainly hadn't expected it to be way lower than 141.

 

So, the bottom line is: be prepared that you have to manage to receive a byte, clear the IRQ and re-enable the IRQ within 134 cycles. Otherwise you run into troubles :-)

 

so long,

 

Hias

Link to comment
Share on other sites

 

BTW: I'd also like to do this IRQ-test using Pokey timers, it would be interesting if IRQ is asserted at the same time. Since I'm not really a pokey (and pokey-timer) expert, could you (or some other pokey expert) provide some code which syncs pokey to some fixed cycle and then activates a pokey timer some 10-150 cycles later? I already had a look at phaeron's code, but need some more hints on how to sync pokey.

 

so long & thanks,

 

Hias

 

Enclosed is POKEY timer code (src and boot disk image) I wrote a few years ago using cycle-exact code that triggers IRQ at exact cycle on a scanline on Atari 400/800/XL/XE. Only tested on NTSC machines, but expect same results on PAL.

 

It uses an 8-bit timer but with POKEY Init so it's like a 16-bit timer to trigger off at exact point on screen. I used to play with this to replace DLIs with Timer IRQs that didn't require WSYNC and ran into disabling of NMI System Reset.

ATIRQ.ZIP

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