News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu

Messing with interrupt timing for fun and profit

Started by djaybee, 10:44, 30 March 24

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

djaybee

TL;DR: I'm trying to modify the timing of interrupts and am not sure about MRER bit 4.

Background: I am trying to modify the timing of interrupts, in order to have an interrupt on or right before a specific line (in my case, line 88 as counted from VSYNC, which by chance might be very convenient).

I understand the following, which I'm able to rely on in my emulator:
-2 lines after VSYNC, or also whenever the line counter reaches 52, the interrupt request is set if the counter is 32 or greater, and the counter is reset to 0.
-When an interrupt is acknowledged (EI instruction at the end of the interrupt routine), the counter's bit 5 is cleared, and the interrupt request is cleared.

I am less clear about bit 4 in the Gate Array's MRER register (Mode and ROM Enable Register).

Soft 968 appendix XI section E documents it as "Clear raster 52 divider." with the explanation "writing a 1 to bit 4 clears the top bit of the divide by 52 counter used for generating periodic interrupts."

Arnold V specs section 2.7 "Interrupt Service" mentions "For compatibility with earlier models, the raster interrupt is reset either by a CPU interrupt acknowledge cycle, or by writing a 1 to bit D4 of the mode and ROM enable register."

The first one might imply that the whole counter is cleared, but the two put together might imply that bit 4 of MRER behaves like an interrupt acknowledge.

However, on the emulator I'm using (the one in 8bitworkshop, sorry), I'm seeing that bit 4 of MRER clears both the counter and the interrupt request, which matches what I've read in some community documents (it's hard to tell which one is the original).

I can test the former by setting bit 4 of MRER within about 20 lines after an interrupt, it does reset the counter and the next interrupt occurs 52 lines later. Any value between 1 and 31 lines will do. I can test the latter by disabling interrupts for about 72 lines (52+20) after an interrupt, and setting bit 4 of MRER before enabling interrupts: no interrupt gets immediately triggered, the interrupt request got cleared.

By luck, I can write my code in a way that doesn't rely on bit 4 of MRER, but that's slightly more complex, so it's not critical for me, but my sense of curiosity makes me wonder what the behavior of bit 4 of MRER would be on real hardware.

I can probably provide source code on request.

McArti0

But are you writing code specifically for CPCplus? There you have PRI.
CPC 6128, Whole 6128 and Only 6128, with .....
NewPAL v3 for use all 128kB RAM by CRTC as VRAM
TYPICAL :) TV Funai 22FL532/10 with VGA-RGB-in.

djaybee

Specifically for the original series (I had a 464 and a 6128 when I was a kid, never owned a Plus, so there's that nostalgia effect). Otherwise, PRI would indeed do exactly what I need.

andycadley

Quote from: djaybee on 10:44, 30 March 24-When an interrupt is acknowledged (EI instruction at the end of the interrupt routine), the counter's bit 5 is cleared, and the interrupt request is cleared.


Can't help with the other bits, but interrupt acknowledge is not when the EI happens. An interrupt acknowledge signal is generated when the CPU detects an interrupt has occured and begins processing the interrupt handler.

djaybee


Good catch, thanks, and my emulator behavior matches your description (a short interrupt that starts 32+ lines late because of disabled interrupts does change the timing of subsequent interrupts, but an interrupt that starts on time but lasts 32+ lines doesn't change the timing of subsequent interrupts).

That doesn't change much in my case since my prodution interrupt code is EI/RET at $38/$39, all I care about is HALTing for it.

McArti0

#5
Maybe you want precise geometry with the CRTC R5?
R5=6, R4=37
CPC 6128, Whole 6128 and Only 6128, with .....
NewPAL v3 for use all 128kB RAM by CRTC as VRAM
TYPICAL :) TV Funai 22FL532/10 with VGA-RGB-in.

djaybee

#6
Quote from: McArti0 on 19:52, 30 March 24Maybe you want precise geometry with the CRTC R5?
I've looked into playing with the CRTC settings a little bit. R5 only gives me a few lines of alignement, not quite enough. I've even considered running at 60Hz instead of 50, but I end up losing more than I gain.

Here's my current timing (R6 = 20, R7 = 28, everything else as default), with undisturbed interrupts. This works, but it forces me to count 33 more lines than necessary. I can disable interrupts during my 160 lines of display and still land on my feet.
; 0 start vsync
; 2 interrupt 1
; 8 start top border (R3H)
; 54 interrupt 2
; 88 start display ((R4+1-R7)*8 )
; 106 interrupt request
; 158 interrupt request
; 210 interrupt request
; 248 start bottom border ((R4+1-R7+R6)*8 )
; 262 interrupt 6
; 312=0 start vsync ((R4+1)*8 )


The next approach is to force the interrupt on line 54 to get delayed by 32 lines. This seems to work, but it doesn't as it causes the next frame to skip its interrupt on line 2, and I need that interrupt to get requested so that I get can delay it and cause the next ones to get delayed as well.

; 0 start vsync
; 2 interrupt request 1
; 8 start top border (R3H)
; ~44 (35-53) interrupt acknowledge 1
; 86 interrupt 2
; 88 start display ((R4+1-R7)*8 )
; 138 interrupt request 3
; 190 interrupt request 4
; 242 interrupt request 5
; 248 start bottom border ((R4+1-R7+R6)*8 )
; 249 interrupt acknowledge 3-5
; 294 interrupt 6
; 312=0 start vsync ((R4+1)*8 )
; 2 vsync interrupt request suppressed, counter == 20

I can work around that by shifting the interrupts a second time. This works, but it requires me to count another 27 to 45 lines after my display, when I'd prefer not to have to worry about timings, especially since I already need to count 35 to 53 lines at the beginning.
; 0 start vsync
; 2 interrupt request 1
; 8 start top border (R3H)
; ~44 (35-53) interrupt acknowledge 1
; 86 interrupt 2
; 88 start display ((R4+1-R7)*8 )
; 138 interrupt request 3
; 190 interrupt request 4
; 242 interrupt request 5
; 248 start bottom border ((R4+1-R7+R6)*8 )
; ~284 (275-293) interrupt acknowledge 3-5, counter -= 32
; 312=0 start vsync
; 2 interrupt line 2 allowed, counter == 40

That's why I'd prefer to use MRER bit 4, but not knowing exactly what it does makes the work a bit difficult.

djaybee

I've made it work in spite of the uncertainty around MRER bit 4!

Here's my sequence:
0 wait for vsync, DI.
2 GA issues interrupt request
35-53 EI, interrupt acknowledge, counter > 32, counter-= 32.
before 86: HALT
86 GA issues interrupt request, acknowledge immediately, DI
88 CRTC first line
138 GA issues interrupt request
190 GA issues interrupt request
224 use MRER bit 4. It either resets the counter to 0 or drops it to 2.
247 CRTC last line
248 EI, interrupt acknowledge if MRER didn't clear interrupt request
274 or 276: GA issues interrupt request, acknowledge immediately
312: next frame
312+2: GA issues interrupt request because counter is 38 or 40.

Because MRER is in the GA, I can abuse any code that changes some palette and make that code use $9D as if it were a color value, such that I don't need that write to be very special, I merely need to plan my code such that line 224 (display line 136) can work with one less palette change than the other lines.

Now, I would prefer to be sure about what MRER bit 4 does, but I use it at a time when the following 2 properties are true, such that its exact semantics don't matter to me:
-the counter is slightly more than 32, such that reseting it or clearing its bit 5 is almost the same.
-the remaining interrupts for the frame don't matter, neither in whether they fire at all nor in their precise timing.

This will allow me to run timed raster code for barely more than the duration of my display, leaving me tons of CPU time to do the rest of the work, with minimal timing constraints.

McArti0

I try make "shorter" 52lines.

org #b941

jp #8000

org #8000

push bc
push af

ld bc,#b8bf
ld a,(bc)
cp 5
jp nz, endint
ld bc,#bc03
out (c),c
ld bc,#bd01
out (c),c  ;R3=1

ld bc,#bc00
out (c),c
ld bc,#bd00+15 ;R0=15
out (c),c

ld bc,#bc02
out (c),c
ld bc,#bd05 ;R2=5
out (c),c

ld b,161
.loop
nop
djnz loop

ld bc,#bc02
out (c),c
ld bc,#bd03 ;R0=3
out (c),c

ld c,#2E ;R0=46
out (c),c

ld bc,#bc00
out (c),c
ld bc,#bd00+3 ;R0=3
out (c),c
ld c,63 ;R0=63
out (c),c

ld bc,#bc03
out (c),c
ld bc,#bd0E
out (c),c  ;R3=14

.endint
pop af
pop bc

EX AF,AF'
JP C,#B978
JP #B945
CPC 6128, Whole 6128 and Only 6128, with .....
NewPAL v3 for use all 128kB RAM by CRTC as VRAM
TYPICAL :) TV Funai 22FL532/10 with VGA-RGB-in.

Powered by SMFPacks Menu Editor Mod