Tursi Posted June 9, 2012 Share Posted June 9, 2012 I haven't really put this to the test, but while playing with the F18A's horizontal interrupt, I dug in to see whether faster interrupt response was possible on the 4A than using the user interrupt link.. and I think it is, slightly. I figured I'd just post something for discussion and consideration. So this is the normal code path, using the user interrupt hook and setting the flags to disable all console functions: 0900 0300 LIMI >0000 Disable interrupt 16 0902 0000 0904 02E0 LWPI >83E0 Load GPLWS! 10 0906 83E0 0908 04CC CLR 12 Clear CRU 10 090A 23A0 COC @>0032,14 Cassette interrupt? 14+8 090C 0032 090E 1602 JNE >0914 No, jump 8 0914 1F02 TB >0002 12 0916 1619 JNE >094A Jump, if VDP interrupt 10 094A 1D02 SBO >0002 Clear VDP interrupt 12 094C D060 MOVB @>83C2,1 Fetch interrupt flag byte 14+8 094E 83C2 0950 0A11 SLA 1,1 No interrupt permitted 12+2 0952 1702 JNC >0958 8 0954 0460 B @>0A84 Then jump 8+8 0956 0A84 0A84 D82F MOVB @>FC00(15),@>837B VDP status in copy RAM 14+8+4+8 0A86 FC00 0A88 837B 0A8A 02E0 LWPI >83C0 INTWS 10 0A8C 83C0 0A8E 05CB INCT 11 Screen timeout counter 10 0A90 160B JNE >0AA8 Not 0 10 0AA8 02E0 LWPI >83E0 GPLWS 10 0AAA 83E0 0AAC B80E AB 14,@>8379 VDP interrupt timer 14+8 0AAE 8379 0AB0 C320 MOV @>83C4,12 User defined interrupt 14+8 0AB2 83C4 0AB4 1301 JEQ >0AB8 None, then jump 8 0AB6 069C BL *12 Otherwise execute 12+4 Using this path, the console executes 21 instructions (30 words) and takes about 294 cycles to get to your code. In addition: -VDP interrupt is cleared for you -Peripheral and other interrupts are also handled -Screen blanking may occur unless the counter variable is changed Registers used if it's a VDP interrupt: >8379: VDP system flags >837B: VDP Status copy >83C0: R1, R2, R11 >83E0: R1, R12, R14, R15 The alternative is to use the little hack discovered by Jeff Brown to get other interrupts running. Basically, you configure the system to expect cassette timer interrupts then take over. It takes a little setup (see below), but this is the code path taken in that case: 0900 0300 LIMI >0000 Disable interrupt 16 0902 0000 0904 02E0 LWPI >83E0 Load GPLWS! 10 0906 83E0 0908 04CC CLR 12 Clear CRU 10 090A 23A0 COC @>0032,14 Cassette interrupt? 14+8 090C 0032 090E 1602 JNE >0914 Yes, don't jump 8 0910 0460 B @>1404 8+8 0912 1404 1404 1E00 SBZ >0000 Control 9901 set 12 1406 1D03 SBO >0003 Timer interrupt reset 12 1408 C041 MOV 1,1 R1 Negative? 14 140A 1107 JLT >141A 10 141A 02E0 LWPI >83C0 10 141C 83C0 141E C3A0 MOV @>83EC,14 R6 GPLWS becomes new R14 14+8 1420 83EC 1422 10FA JMP >1418 10 1418 0380 RTWP End 14 This time, only 14 instructions (20 words) are executed, and it's about 178 cycles to get control (versus 294). However, there are some important differences: -VDP registers are NOT read on this path, we get them -To clear VDP interrupts, we need at least two more instructions: -- read status register 0A84 D82F MOVB @>FC00(15),@>837B VDP status in copy RAM -- clear 9901 interrupt 094A 1D02 SBO >0002 Clear VDP interrupt -16 is still faster than 21. (24 words versus 30 - including the tests and clears, it's 242 cycles) -The above also does not account for peripheral interrupts -Also, 9901 timer mode can not be used because every interrupt will disable it -And, of course, the true return address is lost, so you have to know where to jump back to -Finally, the interrupt function is called with the host program's workspace! To set up requires some messing with the scratchpad -- but this disables all the rest of the scratchpad usage: LWPI >83E0 GPLWS SETO R14 Everything's a cassette interrupt! SETO R1 Make R1 negative LI R6,INTERR Load R6 with the address you want interrupts to call (It would also be a very good idea to disable peripheral interrupts in the 9901 if you do not plan on servicing them, otherwise a spurious card interrupt will lock up your program.) So, reserved values: >83DA old workspace pointer >83DC overwritten with address of interrupt routine >83DE old STatus register >83E2 'R1' flag byte >83EC Interrupt function pointer (you fill this in, MUST BE VALID) >83F8 GPLWS CRU pointer (overwritten) >83FC scratch register Maybe 20% faster overall, and frees 2 bytes of scratchpad (or so). Worth it? Hard to say. Maybe in some cases. Probably not most of the time. But, it was interesting to dig through the paths. Quote Link to comment https://forums.atariage.com/topic/199048-faster-interrupts/ Share on other sites More sharing options...
+retroclouds Posted June 10, 2012 Share Posted June 10, 2012 (edited) Been thinking about the load interrupt. Suppose you'd have a little device plugged in the sideport with a programmable timer that triggers the load interrupt. You would not have the hassle having to go through the console ISR. Dunno if you can trigger multiple load interrupts without resetting the console. Would have been cool if the CF7+ / nanopeb would have had such feature. Another thing that comes too mind; with the available space constraints in the console ROM, would be possible to replace the ISR, perhaps removing the cassette functionality in favour of a faster ISR? Ofcourse the nice thing about your documented setup is that no hardware mods are required. Edited June 10, 2012 by retroclouds Quote Link to comment https://forums.atariage.com/topic/199048-faster-interrupts/#findComment-2539069 Share on other sites More sharing options...
matthew180 Posted June 11, 2012 Share Posted June 11, 2012 The alternative to using the ISR is to just poll. You can check the status of the VDP interrupt once per program loop and call your pseudo ISR if it is set. Also, using the timer in the F18A you could set up some other interval by checking the counter value once per loop. I realize polling is not as convenient as the interrupt mechanism, but it is probably more efficient in the 99/4A unless you are using a lot of the services that the console ISR processes. Quote Link to comment https://forums.atariage.com/topic/199048-faster-interrupts/#findComment-2539383 Share on other sites More sharing options...
Tursi Posted June 11, 2012 Author Share Posted June 11, 2012 Yeah, the load interrupt is much faster, since it will jump directly to your vector, but neither hte VDP nor the 9901 can trigger it without hardware mods. As for replacing the console ROMs.. well, yeah, you could do whatever you like there. Most of the cassette DSR is actually in the GROM though, you don't get as much space as you might think (but the main purpose of such a replacement is probably to take advantage of the code that the cassette DSR forces anyway.) Polling works more or less as well if you're limiting interrupts to one place in your code with LIMI 2/LIMI 0 anyway, yeah. Takes a little more code though, but it probably comes out to a wash overall. Quote Link to comment https://forums.atariage.com/topic/199048-faster-interrupts/#findComment-2539518 Share on other sites More sharing options...
+retroclouds Posted June 11, 2012 Share Posted June 11, 2012 (edited) Polling worked fine for the stuff I did sofar. But was toying with the idea of creating a little scheduler for doing preemptive multitasking. The thing with the ISR is that it expects scratchpad memory to be setup as required. In my spectra2 library I use scratchpad memory in a different way. And it seems quite an overhead swapping values back and forth or if this would even be possible when running without the 32K. I think I read somewhere that there was a hack for UCSD Pascal on the TI-99/4A for implementing a preemptive multitasking scheduler. I dunno how this was done and if it involved some extra piece of hardware. Edited June 11, 2012 by retroclouds Quote Link to comment https://forums.atariage.com/topic/199048-faster-interrupts/#findComment-2539529 Share on other sites More sharing options...
matthew180 Posted June 11, 2012 Share Posted June 11, 2012 Polling worked fine for the stuff I did sofar. But was toying with the idea of creating a little scheduler for doing preemptive multitasking. Have you seen Thierry's page on his multitasking implementation? http://nouspikel.group.shef.ac.uk/ti99/tasks.htm Quote Link to comment https://forums.atariage.com/topic/199048-faster-interrupts/#findComment-2539746 Share on other sites More sharing options...
Willsy Posted June 12, 2012 Share Posted June 12, 2012 How are the ROMs organised in the console? Is it two 8 bit 8K ROMs? I'd be interested in fitting an alternative ROM that simply jumps over the interrupt code in the console (the part that determines where the interrupt came from, does the sprites, sound etc). It would be interesting to see if it increased interrupt performance by a lot... Quite a few carts would cease to work I imagine, but a simple switch on the chip selects would allow one to select the original ROM or the modified ROM. Quote Link to comment https://forums.atariage.com/topic/199048-faster-interrupts/#findComment-2540121 Share on other sites More sharing options...
+Lee Stewart Posted June 12, 2012 Share Posted June 12, 2012 (edited) How are the ROMs organised in the console? Is it two 8 bit 8K ROMs? I'd be interested in fitting an alternative ROM that simply jumps over the interrupt code in the console (the part that determines where the interrupt came from, does the sprites, sound etc). It would be interesting to see if it increased interrupt performance by a lot... Quite a few carts would cease to work I imagine, but a simple switch on the chip selects would allow one to select the original ROM or the modified ROM. See Thierry's site here---more specifically, here. ...lee Edited June 12, 2012 by Lee Stewart Quote Link to comment https://forums.atariage.com/topic/199048-faster-interrupts/#findComment-2540141 Share on other sites More sharing options...
+retroclouds Posted June 13, 2012 Share Posted June 13, 2012 Thanks for pointing me to Thierry's site. He really has some interesting stuff on there Quote Link to comment https://forums.atariage.com/topic/199048-faster-interrupts/#findComment-2540769 Share on other sites More sharing options...
apersson850 Posted June 19, 2012 Share Posted June 19, 2012 Have you seen Thierry's page on his multitasking implementation?Interesting. That's very similar to what I tried to accomplish within the UCSD p-system context. The UCSD Pascal implementation on the TI already supports cooperative multitasking, so some things were already there, but no pre-emptive support. My attempt worked, but it turned out that the system doesn't protect dynamic memory allocations from being interrupted, and without the source code for unit HEAPOPS, it was in reality impossible to fix. Quote Link to comment https://forums.atariage.com/topic/199048-faster-interrupts/#findComment-2544000 Share on other sites More sharing options...
Recommended Posts
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.