Jump to content
  • 0
Elektron72

Line IRQ Timing

Question

Does anyone know exactly when the VERA triggers line IRQs? Ideally, I hope it can trigger an IRQ as soon as it is done drawing the visible part of the previous line. This would give programmers the maximum amount of time for routines that alter the screen between lines.

Share this post


Link to post
Share on other sites

15 answers to this question

Recommended Posts

  • 0

That can be configured in the VERA by setting the lower 4 bits of the IEN register ($9F26).  If you set bit 2, then it will trigger at the end of a line.  Looking at the emulator code, it looks like it's right when you are hoping, when it is done drawing the visible area of the line.

Quote

float advance = ((out_mode & 2) ? NTSC_PIXEL_FREQ :  VGA_PIXEL_FREQ) / mhz;
scan_pos_x += advance;
if (scan_pos_x > SCAN_WIDTH) {
     ....
    if (ien & 2) { // LINE IRQ
        ....

 

Share this post


Link to post
Share on other sites
  • 0

SCAN_WIDTH includes the horizontal back porch of the previous line. This means that the IRQ (at least in the emulator) doesn't trigger until the beginning of the horizontal front porch of the line that the interrupt is set to trigger on. Triggering the interrupt on the line before as soon as scan_pos_x is greater than the sum of SCREEN_WIDTH and either VGA_FRONT_PORCH or NTSC_FRONT_PORCH (changes depending on the video mode) would provide much more time to interrupt routines. Although changing the emulator would be relatively simple, I want to make sure that this will (hopefully) reflect the actual hardware.

Share this post


Link to post
Share on other sites
  • 0

Be aware that VERA hardware will probably have very different timings. The emulator renders the current line into the buffer in one cycle (from the CPU's perspective), while real hardware will be rendering most of the time during the scanline. If I'm understanding things correctly, real VERA will actually be rendering the next scanline into 3 separate line buffers (sprites, layer 0, layer 1) while it composes and outputs the current scanline from its line buffers. Which means that VERA is actually using a sort of scanline double buffering internally. See this comment from VERA's designer, Frank van den Hoef.

I suppose VERA hardware could latch the contents of its registers (layer settings, sprite settings etc.), but it's not going to be latching the VRAM. Therefore, writes to VRAM might affect the rendering of the scanline on real hardware. And if VERA doesn't perform any latching of its registers, any changes of those registers may also affect the rendering of the current (actually, next) scanline.

So, it really remains to be seen how the real hardware handles the rendering and what are the exact timings, e.g. when does the rendering of the scanline start/end and which, if any, registers are being latched. At this time it is only safe to assume that any changes that might affect the rendering of the scanline can only be made during a small window, but since we don't know where and how long this window is, we're back to square one 😀

TL;DR the emulator is not at all accurate when it comes to line interrupts. Any effects you create and test with the emulator may or may not work on real hardware. YMMV.

Edited by Guybrush

Share this post


Link to post
Share on other sites
  • 0
45 minutes ago, Elektron72 said:

SCAN_WIDTH includes the horizontal back porch of the previous line. This means that the IRQ (at least in the emulator) doesn't trigger until the beginning of the horizontal front porch of the line that the interrupt is set to trigger on. Triggering the interrupt on the line before as soon as scan_pos_x is greater than the sum of SCREEN_WIDTH and either VGA_FRONT_PORCH or NTSC_FRONT_PORCH (changes depending on the video mode) would provide much more time to interrupt routines. Although changing the emulator would be relatively simple, I want to make sure that this will (hopefully) reflect the actual hardware.

Ah right.  SCAN_WIDTH is 800 and the SCREEN_WIDTH is 640.  Yeah, that's unfortunate, then.  But as @Guybrush says, the real hardware will be different anyway.  I wonder how hard it would be to more accurately emulate the real hardware?  Based on his description it seems doable, but it would be a big rewrite.

Share this post


Link to post
Share on other sites
  • 0

I decided to calculate how many cycles programmers will have depending on where the IRQ triggers:

  • Beginning of front porch of IRQ line
    This is where the emulator currently triggers line IRQs. However, its effects are not immediately obvious, since the emulator instantly renders everything at the end of the line.
    Doing some calculations (numbers are rounded), we can determine:
    8000000 Hz (processor speed) / 60 Hz (refresh rate) = 133333 cycles per frame
    133333 / 525 (number of lines per frame) = 254 cycles per line
    254 / 800 (number of pixels in a line) = 0.32 cycles per pixel
    16 (number of pixels in the VGA front porch) * 0.32 = 5 cycles
    5 cycles is enough time to run about two short instructions. There isn't enough time to do anything useful before the visible area of the screen begins. Additionally, the 65C02 must also finish its current instruction before handling an interrupt, which will likely take a few cycles. After finishing the instruction, the CPU will jump to ROM before going to a user routine. This routine spends the remaining cycles pushing the registers onto the stack, and jumping to the user routine. With this timing, there is no safe window where changes can be made.
  • Beginning of back porch 
    This would be the ideal time to trigger the line IRQ in order to give the maximum available time to IRQ handlers.
    800 (number of pixels in a line) - 16 (number of pixels in the VGA front porch) - 640 (number of pixels in a visible line) = 144 pixels in the VGA back porch
    144 * 0.32 = 46 cycles
    46 cycles is enough time to make multiple changes to the VERA's registers, allowing for a wide variety of visual effects without any on-screen distortion.

Overall, if the actual hardware triggers an interrupt at the beginning of the front porch rather than the back porch, it will greatly hamper the usefulness of line IRQs.

Share this post


Link to post
Share on other sites
  • 0
6 hours ago, Elektron72 said:

Beginning of back porch 
This would be the ideal time to trigger the line IRQ in order to give the maximum available time to IRQ handlers.

I think you have your nomenclature backward. The porches surround hsync, so the front porch is the blank time before the sync pulse. This actually puts the 16 pixel front porch at the end of the scan line and at the beginning of the blanking interval. If the interrupt is actually fired on the front porch, this gives us the longest period of time to work between frames. 

From a hardware standpoint, the simplest time to trigger an interrupt is on the rising edge of the horizontal sync. Since the hardware has to trigger the sync pulse anyway, the IRQ line can be tied to the sync pulse and trigger at the same time. Triggering at the end of hsync is also fairly easy, since that's just a matter of inverting the hsync output. 

Display Timings 

https://projectf.io/posts/video-timings-vga-720p-1080p/

So let's analyze the timing:

According to the this page, the porch timings are:

Pixel Clock: 25.175 MHz. 
Front porch: 16
Sync: 96
Back Porch: 48

I'm thinking the clock generator will be driven by the video clock, or 25.175/3 MHz. This gives us 8.4MHz. 

  • The total blank time between lines is 160 pixels, or 53 clock ticks. This is room for roughly 10-13 ML instructions.
  • The back porch is 16 clock ticks, or 3-4 instructions.
  • The front porch is 5 clock ticks, enough for two instructions in the absolute best case. 

So losing the front porch doesn't lose that much time, basically one instruction, but losing the hsync means not really having enough time to get anything done between raster lines. 
 

image.png

Edited by TomXP411
math error
  • Thanks 1

Share this post


Link to post
Share on other sites
  • 0
31 minutes ago, TomXP411 said:

Pixel Clock: 25.175 MHz. 
Front porch: 16
Sync: 96
Back Porch: 98

This gives us roughly 3 pixels per 6502 clock tick, which we can use for some rough back of the napkin calculations:

  • The total blank time between lines is 210 pixels, or 70 clock ticks.
  • The back porch alone is 32 clock ticks.
  • hsync + back porch is 64 ticks

I think that's 48 on the back porch, and a total of 160, not 210? Which is 53 clock ticks total: 16 for the back porch, and hsync+back porch is 48.  If we assume an average of 4 ticks/instruction, that's 4, 12, or 13 instructions.

Share this post


Link to post
Share on other sites
  • 0
4 hours ago, Ender said:

I think that's 48 on the back porch, and a total of 160, not 210? Which is 53 clock ticks total: 16 for the back porch, and hsync+back porch is 48.  If we assume an average of 4 ticks/instruction, that's 4, 12, or 13 instructions.

Yes, it was a typo. 

I believe the CPU clock will be based on the video clock (this a super common design, and why we see weird speeds like 3.54 MHz or 1.79 Mhz. The closest speed to 8MHz is actually 8.391Mhz, or the 25.175MHz pixel clock divided by 3.

 

 

Share this post


Link to post
Share on other sites
  • 0
13 hours ago, TomXP411 said:

I think you have your nomenclature backward. The porches surround hsync, so the front porch is the blank time before the sync pulse. This actually puts the 16 pixel front porch at the end of the scan line and at the beginning of the blanking interval. If the interrupt is actually fired on the front porch, this gives us the longest period of time to work between frames. 

Thanks for the correction; I had assumed it was the other way around. While the current version of the emulator does not account for horizontal timing, it does count the vertical front porch lines at the beginning of a frame, rather than at the end. I might open a pull request to fix this.

  • Like 1

Share this post


Link to post
Share on other sites
  • 0
15 hours ago, Elektron72 said:

Thanks for the correction; I had assumed it was the other way around. While the current version of the emulator does not account for horizontal timing, it does count the vertical front porch lines at the beginning of a frame, rather than at the end. I might open a pull request to fix this.

Yeah, I think this is one area where the emulator may not be correct - but we won't know for sure until the next revision, which will match the current hardware configuration, comes out. 

It might be worth trying to get more info on exactly when VERA triggers the line and frame interrupts... knowing the exact timing is going to be important for people doing raster effects. 

 

Share this post


Link to post
Share on other sites
  • 0

I experimented with the raster line IRQ the last few days, too. I got it working, but there is very few cycles left you can use. Updating a (256) color palette seems almost impossible. I'll try to use the auto-increment feature of VERA, to improve this, by storing the 2nd palette in VRAM, too.

And that's with the emulator- no idea if this will work on real hardware.

Share this post


Link to post
Share on other sites
  • 0
33 minutes ago, AndyMt said:

I experimented with the raster line IRQ the last few days, too. I got it working, but there is very few cycles left you can use. Updating a (256) color palette seems almost impossible. I'll try to use the auto-increment feature of VERA, to improve this, by storing the 2nd palette in VRAM, too.

And that's with the emulator- no idea if this will work on real hardware.

It's simply impossible to update the entire palette during one scanline, even if you use every available hardware trick. There's only 254 (266) CPU cycles per scanline, the exact number depends on whether the CPU runs on dedicated 8 MHz clock, or a VGA clock divided by 3 (25.175 / 3 = 8.3196666 MHz) .

Since a simple LDA/STA combination to read and write from/to VERA data registers takes 8 cycles, even if you completely unroll the loop, you can copy 254 / 8 / 2 (2 bytes per palette entry) ~= 15 palette entries. And I'm not even taking the KERNAL IRQ handler overhead into account.

Even if there was a DMA chip somewhere in the system, it couldn't update the palette in one scanline beacuse it would need 256*2*2 = 1024 cycles, which also means that even a DMA internal to VERA couldn't do it because a VGA 640x480 scanline is only 800 cycles long.

The only way to update the entire palette in one scanline would be to have a relocatable palette.

So, you can only change a few colors each scanline and must design your graphics accordingly.

Edited by Guybrush
  • Like 1

Share this post


Link to post
Share on other sites
  • 0
1 hour ago, Guybrush said:

So, you can only change a few colors each scanline and must design your graphics accordingly.

Yes, that's what I'm going for. And I'll have to change the entire palette over multiple scanlines. This makes the line IRQ not all too useful - I wonder how much you could do on the C64...

Share this post


Link to post
Share on other sites
  • 0
26 minutes ago, AndyMt said:

Yes, that's what I'm going for. And I'll have to change the entire palette over multiple scanlines. This makes the line IRQ not all too useful - I wonder how much you could do on the C64...

Well, for one, you could not change the palette at all 😀.

Of course, you could change the background color registers (1,3 or 4, depending on the display mode), the sprite multi-color registers (2) and sprite color registers (8), but you'd have to time your code very precisely. And then there are badlines 😀.

On a normal line with no sprites, you get 63 cycles for PAL, and 64 or 65 for NTSC. That's 23-25 cycles off-screen, even a bit more since you only have to perform your writes in the invisible part of the scanline. If you're changing global color registers that's just about enough time to update 3-4 of them if you use self-modifying code (to directly update color values in LDA #val instructions). On a line with sprites, you lose up to 16 cycles in the invisible part, but if you're changing sprite colors you are more flexible in your timing because you know when the sprite is being displayed and since the sprite color affects only one one sprite... you get the point.

Long story short, on the C64 you also need to design the screens carefully to make big changes to colors.

  • Like 1

Share this post


Link to post
Share on other sites
  • 0
9 minutes ago, Guybrush said:

And then there are badlines 😀.

I remember those. Happens every 8 pixels, right? That's the beauty of the VERA design and it's interface to the bus: it's pretty independent.

Share this post


Link to post
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.

Guest
Answer this question...

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


×
×
  • Create New...

Important Information

Please review our Terms of Use