ralphb Posted October 18, 2015 Share Posted October 18, 2015 I've been playing around with user ISRs, and I'm somewhat puzzled by the result of this program: . main: lwpi ws li r0, handler mov r0, @>83c4 ; set user ISR limi 2 jmp $ position: data 0 handler: mov r11, r10 mov @position, r0 li r1, '# ' bl @vsbw ; standard implementation inc r0 andi r0, >1ff mov r0, @position b *r10 . This does not fill 2/3 of the screen, but simply displays two chars. Even more bizarely, the second char only appears after a couple of seconds. Now I realize that you probably wouldn't want to write to the VDP in the handler itself. In fact, I wouldn't enable interrupts in the first place but use vsync polling in my game instead. But can someone explain to me what is happening here? Is access to the VDP triggering another interrupt?! And what is causing the delay? (This is all in MESS, BTW.) Quote Link to comment Share on other sites More sharing options...
+mizapf Posted October 18, 2015 Share Posted October 18, 2015 This is your own VSBW? The standard one is a context-switched routine, requiring BLWP. Also, to make sure you could add a LIMI 0 as the first line of "handler". Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted October 18, 2015 Share Posted October 18, 2015 ... But can someone explain to me what is happening here? Is access to the VDP triggering another interrupt?! And what is causing the delay? (This is all in MESS, BTW.) I'm surprised it does anything at all. VSBW needs to be called by BLWP. ...lee Quote Link to comment Share on other sites More sharing options...
Asmusr Posted October 18, 2015 Share Posted October 18, 2015 This works fine for me: def main VDPRD EQU >8800 * VDP read data VDPSTA EQU >8802 * VDP status VDPWD EQU >8C00 * VDP write data VDPWA EQU >8C02 * VDP set read/write address ws EQU >8300 AORG >A000 main: lwpi ws li r0, handler mov r0, @>83c4 ; set user ISR limi 2 jmp $ position: data 0 handler: mov r11, r10 mov @position, r0 li r1, '# ' bl @vsbw ; standard implementation inc r0 andi r0, >1ff mov r0, @position b *r10 *************************************************************************** * * VDP Single Byte Write * * R0 Write address in VDP RAM * R1 MSB of R1 sent to VDP RAM * * R0 is modified, but can be restored with: ANDI R0,>3FFF * VSBW SWPB R0 MOVB R0,@VDPWA * Send low byte of VDP RAM write address SWPB R0 ORI R0,>4000 * Set read/write bits 14 and 15 to write (01) MOVB R0,@VDPWA * Send high byte of VDP RAM write address MOVB R1,@VDPWD * Write byte to VDP RAM B *R11 *// VSBW end main It takes 512/60=8.5 seconds to draw the screen. 1 Quote Link to comment Share on other sites More sharing options...
ralphb Posted October 18, 2015 Author Share Posted October 18, 2015 This works fine for me Ah, I think I've figured it out. Sorry for not posting the entire code and for the misleading comment about VSBW; by "standard implementation" I meant "what everybody else is doing." Here's the missing part of my code: ws: equ >8300 ws_r0lb: equ ws + 1 vsbw: movb @ws_r0lb, @vdpwa ori r0, >4000 movb r0, @vdpwa movb r1, @vdpwd rt Since the SWPB version is working fine I conclude that the user ISR is using a different WS than the one I set upfront! I'll check what the console ISR is using with the debugger ... But would it be safe to alter the WS and not restore it prior to returning from the user ISR (which, of course, would have to be a B @whatever instead of RT)? Quote Link to comment Share on other sites More sharing options...
ralphb Posted October 18, 2015 Author Share Posted October 18, 2015 Also, to make sure you could add a LIMI 0 as the first line of "handler". Would it matter if I'm fast enough? In fact, I would prefer to be preemted if I'm tardy ... Quote Link to comment Share on other sites More sharing options...
+mizapf Posted October 18, 2015 Share Posted October 18, 2015 We do not have a stack management for subroutines, accordingly, the least desirable event is being interrupted while handling an interrupt. I'm not sure, however, if the interrupts are not already masked when entering the ISR, anyway. I'm currently not at my desk, so I cannot check "TI Intern" right now, but maybe you can look it up. Check locations >0900. Quote Link to comment Share on other sites More sharing options...
+mizapf Posted October 18, 2015 Share Posted October 18, 2015 The workspace is definitely not >8300. It's either INTWS (83C0) or GPLWS (83E0), but I just don't have my "TI Intern" at hand right now. Quote Link to comment Share on other sites More sharing options...
+mizapf Posted October 18, 2015 Share Posted October 18, 2015 (edited) Since the SWPB version is working fine I conclude that the user ISR is using a different WS than the one I set upfront! I'll check what the console ISR is using with the debugger ... But would it be safe to alter the WS and not restore it prior to returning from the user ISR (which, of course, would have to be a B @whatever instead of RT)? That is the point. Your user ISR is called with a fixed WS (either 83C0 or 83E0, need to check). If you want to change the WS you have to use LWPI in your handler. In that case you must restore the WS pointer prior to returning. Accordingly, the reaction of your program is quite clear. Your INC R0 does not affect 8301 which you use as the low byte of the address. The high byte is correctly fetched from R0, and this one increases every 256 iterations, so you get those 3 positions on the screen. [Edit: OK, back at the desk, browsing TI Intern. See page 34, address 0AB6 - this is the branch and link to the user ISR. Shortly before, the workspace pointer is set to GPLWS. At address 0900, LIMI 0 is executed, as expected, so you don't need a LIMI 0 in your code.] Edited October 18, 2015 by mizapf 1 Quote Link to comment Share on other sites More sharing options...
ralphb Posted October 19, 2015 Author Share Posted October 19, 2015 Accordingly, the reaction of your program is quite clear. Your INC R0 does not affect 8301 which you use as the low byte of the address. The high byte is correctly fetched from R0, and this one increases every 256 iterations, so you get those 3 positions on the screen. [Edit: OK, back at the desk, browsing TI Intern. See page 34, address 0AB6 - this is the branch and link to the user ISR. Shortly before, the workspace pointer is set to GPLWS. At address 0900, LIMI 0 is executed, as expected, so you don't need a LIMI 0 in your code.] Yes, I figured as much ... It's kind of satisfying to see how seemingly erratic code suddenly makes perfect sense! And thanks for the Intern pointer, I'll take a look. We do not have a stack management for subroutines, accordingly, the least desirable event is being interrupted while handling an interrupt. Well, on a modern system I would agree, but for the TI I could imagine using the interrupt as some kind of "time boxing" for certain use cases -- I guess that the important stuff has already been done by the console ISR, so never mind how far the user ISR will get ... I don't see how this would trip up the caller, assuming that the user ISR will not change the workspace. This would be different if the ISR was called by BLWP instead of a BL. (But then, I'll really check TI Intern on this one before making any further bold assumptions.) Quote Link to comment Share on other sites More sharing options...
Tursi Posted October 19, 2015 Share Posted October 19, 2015 If you are running an interrupt hook and you turn interrupts back on, when you're interrupted again you don't get to resume - you'll be called again from the beginning of your hook. You might be able to maintain some form of stage inside your own code for picking up again. But it won't hurt anything - except that the main program will never get a chance to run. Running your main program, of course, when the interrupt finishes you get your original workspace back and pick up where you left off -- assuming nothing that happened during the interrupt corrupted your data. Quote Link to comment Share on other sites More sharing options...
Willsy Posted October 19, 2015 Share Posted October 19, 2015 (edited) You get a surprising amount of work done on the VDP interrupt. My machine code version of manic miner (un-finished) runs entirely off of the VDP interrupt. The main thread is just a JMP $ instruction! I do it by splitting up the work across multiple frames. Frame 0 - updates sprite positions, frame 1, animate floors, frame 2, animate oxygen level bar etc. The nature of that game means 60 fps are simply not required! Edited October 19, 2015 by Willsy 2 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted November 4, 2015 Share Posted November 4, 2015 As far as I can remember, the TMS 9900 CPU itself will change the interrupt level mask to allow only interrupts with at least one level higher priority than the currently executing automatically. Quote Link to comment 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.