Proper VDP Vblank interrupt handling when there are others source of interrupt active

Pagina 1/2
| 2

Door PingPong

Prophet (3339)

afbeelding van PingPong

11-06-2019, 01:20

I wondering what happens if an int from another source of VDP VBLANK appears and while the bios int routine is running a VDP interrupts kick in. Sequence:
1) Device A request an int: H.KEYI execute but at this pojnt no VDP int is requested.
2) H.TIMI execute but in the exact time the BIOS check if int is coming by VDP by reading S#0 the VDP request an interrupt.
3) because reading S#0 reset the int bit this will be read as inactive so no further processing occours.

Am i wrong or In this way the VDP int is lost?

The only way i can avoid this is checking other sources of interrupts on step (1) and preventing H.TIMI to execute if there are other devices.
Is there another way?

Aangemeld of registreer om reacties te plaatsen

Van RetroTechie

Paragon (1563)

afbeelding van RetroTechie

11-06-2019, 02:49

If properly implemented, device generating an interrupt should hold Z80 /INT line active until it is 'serviced'. So if it generates an interrupt, and this gets recognised as a VDP interrupt because the VDP generates one too in the meanwhile, then your "Device A" would not get serviced. And thus /INT would still be held active, leading to another call to 0038h immediately (at which point it would be recognised as coming from other than VDP).

This what H.KEYI is for! So that a handler for "Device A" can service that device before bios does the VDP status check. This hook is called first, minimizing interrupt handler length to help with devices that generate interrupts at a high rate (say 100+ / second). Well it does save & restore the whole Z80 register set (including alternate) on each call to 0038h, which is not an optimal design choice imho. Sad

So in the above case, that handler would recognise interrupt from "Device A", do its thing and cause Device A to release the /INT line. After which bios check for VDP interrupt is done.

Van PingPong

Prophet (3339)

afbeelding van PingPong

11-06-2019, 09:07

I think i'm been not clear in my previous post. The problem is the possibility to miss a VDP interrupt because of previous int handling of another device. Follow the timing sequence:
1) Device A request interrupt (INT goes low)
2) CPU execute H.KEYI and see that is Device A requesting service.
3) Now, when service routine (2) is executed then the H.TIMI is executed, but just when the z80 does in a,(99h) the VDP issue its own request. But Because we are reading the register S#0 the bit would be read as inactive! (bit clear-on-read). No H.TIMI action take place because it think there is no vdp int.

To me the only way to avoid this is, when H.KEY is executing (and interrupt is for another device) to return without let step (3) to execute.
In this way, if later the VDP issue interrupt the CPU can read S#0 and be able to detect VDP int.

is there any other way?

Van RetroTechie

Paragon (1563)

afbeelding van RetroTechie

11-06-2019, 18:07

I don't see any problem here...

H.KEYI gets called first, handler for Device A does its thing, clears Device A's interrupt signal & returns. Next, one of 2 things can happen:
a) There was no VDP interrupt pending, VDP S#0 that's subsequently read reflects this, and interrupt routine exits. Or
b) At the time Z80 reads VDP S#0, there was a VDP interrupt pending. The read value for S#0 reflects that, H.TIMI will be called, maybe keyboard read etc, and interrupt routine exits.

Either way, no VDP interrupt is missed because of Device A handler's actions. And H.TIMI only gets called if it was a VDP interrupt so 50 or 60 times/second (H.KEYI otoh, on every interrupt even non-VDP). And note that handler for Device A does NOT clear VDP /INT signal (or read its S#0).

Van PingPong

Prophet (3339)

afbeelding van PingPong

11-06-2019, 20:08

Quote:

b) At the time Z80 reads VDP S#0, there was a VDP interrupt pending. The read value for S#0 reflects that, H.TIMI will be called, maybe keyboard read etc, and interrupt routine exits.

Not at the time there was ...... that's the difference. if it was as you said there is no problem.
But there is a bug on VDP that if you read continously s#0 you can miss the flag value .
this happens when the s#0 is read and vdp is about to set it.

I'm referring to this, from https://www.msx.org/wiki/VDP_Status_Registers

Quote:

Status Register 0
This status register is common to all MSX generations and can be read with the MSX-BASIC instruction VDP(), using the value 8.

It may be read at any time but asynchronous reads will cause the F flag to be reset and therefore missed. Consequently, the status register should be read only when the VDP interrupt is pending (flag value 1)

Van RetroTechie

Paragon (1563)

afbeelding van RetroTechie

11-06-2019, 22:57

"Citation needed". This would be a VDP hardware bug, and I'm unable to find any references in documentation or online. Just a single line from the Wiki on this site? Not enough imho. Therefore, it would be appreciated if someone has a better reference. Or better yet: example code to demonstrate this issue (if it exists at all). Only on TMS9918, or also applies to V9938 or V9958?

Also: this sounds more like a theoretical issue, veeerrryy perhaps shown when polling the VDP S#0 continuously. That's very different from a situation where eg. this "Device A" produces say, 100 extra interrupts / second. With VDP set to 60 Hz, that's still (on average) in the order of 22k+ Z80 clock cycles between each interrupt. But even worst case: what 'damage' could a missed VDP interrupt do?

So even if this issue does in fact exist (I'm doubtful), would this have any practical significance for real-world applications? If not: just use the hooks as intended, and don't worry about it.

Van hit9918

Prophet (2858)

afbeelding van hit9918

11-06-2019, 23:29

so, the issue is what happens together with lost events of VDP status register reads.
does the 9938 too have the status register bug? the wiki lists it like a general thing of all VDPs.

the interrupt of another device could create the timing situation! that IN 0x99 is done in the same cycle as the VDP interrupt and the event is lost.

Van hit9918

Prophet (2858)

afbeelding van hit9918

11-06-2019, 23:35

on a real MSX1 this bug hit me in surprising patterns. I dont remember the details but I think sometimes the same code worked or didnt work. when the program was launched in a different phase.
but maybe it is just polling loops who get hit in a surprising way.

Van PingPong

Prophet (3339)

afbeelding van PingPong

12-06-2019, 08:45

Quote:

the interrupt of another device could create the timing situation! that IN 0x99 is done in the same cycle as the VDP interrupt and the event is lost.

Exactly! is what i said.
However it is not clear what get missed with the polling approach.
a) Do we loose the INTerrupt ? (because we are reading s#0 in a loop)
b) Do we loose the 7th status bit of register 0 ? (That is more problematic because we cannot detect VBLANK)

I think it is more likely the (a).

Something told that V99x8 does not have this behaviour, but giving the plethora of TMS VDP clones would be interesting to know what VDPs exibit this bug.

Would be a good idea to create a test program that can help to detect (a) or (b). Any idea on how could be done this detection?

Van hit9918

Prophet (2858)

afbeelding van hit9918

12-06-2019, 09:26

the polling loops fall thru with lost events.
so the status register bit gets lost.
whether in such case the z80 still calls the interrupt handler I dont know.

Van PingPong

Prophet (3339)

afbeelding van PingPong

12-06-2019, 12:35

maybe there is a way to create a sw that detects this problem in order to know if this happen on TMS, clones, V99x8 or so ?

Pagina 1/2
| 2