diff --git a/compiler/res/prog8lib/cx16/syslib.p8 b/compiler/res/prog8lib/cx16/syslib.p8 index 977583858..8933aeaeb 100644 --- a/compiler/res/prog8lib/cx16/syslib.p8 +++ b/compiler/res/prog8lib/cx16/syslib.p8 @@ -854,7 +854,7 @@ asmsub restore_vera_context() clobbers(A) { ; Commander X16 IRQ dispatcher routines -inline asmsub disable_vera_irqs() clobbers(A) { +inline asmsub disable_irqs() clobbers(A) { ; Disable all Vera IRQ sources. Note that it does NOT set the CPU IRQ disabled status bit! %asm {{ lda #%00001111 @@ -863,9 +863,9 @@ inline asmsub disable_vera_irqs() clobbers(A) { } asmsub enable_irq_handlers(bool disable_all_irq_sources @Pc) clobbers(A,Y) { - ; Install the "master IRQ handler" that will dispatch IRQs. + ; Install the "master IRQ handler" that will dispatch IRQs ; to the registered handler for each type. (Only Vera IRQs supported for now). - ; The handlers don't need to clear its ISR bit, but have to return 0 or 1 in A: + ; The handlers don't need to clear its ISR bit, but have to return 0 or 1 in A, ; where 1 means: continue with the system IRQ handler, 0 means: don't call that. %asm {{ php @@ -1007,10 +1007,10 @@ asmsub set_aflow_irq_handler(uword address @AY) clobbers(A) { } -asmsub disable_irq_handlers() { +inline asmsub disable_irq_handlers() { ; back to the system default IRQ handler. %asm {{ - jmp sys.restore_irq + jsr sys.restore_irq }} } @@ -1189,15 +1189,15 @@ asmsub set_rasterline(uword line @AY) { php sei sta cx16.VERA_IRQLINE_L - lda cx16.VERA_IEN - and #%01111111 - sta cx16.VERA_IEN tya lsr a - ror a - and #%10000000 - ora cx16.VERA_IEN - sta cx16.VERA_IEN + bcs + + lda #%10000000 + trb cx16.VERA_IEN + plp + rts ++ lda #%10000000 + tsb cx16.VERA_IEN plp rts }} diff --git a/docs/source/targetsystem.rst b/docs/source/targetsystem.rst index 54a2acfa9..3ce1fccb9 100644 --- a/docs/source/targetsystem.rst +++ b/docs/source/targetsystem.rst @@ -138,7 +138,7 @@ IRQ Handling Normally, the system's default IRQ handling is not interfered with. You can however install your own IRQ handler (for clean separation, it is advised to define it inside its own block). -There are a few library routines available to make setting up C64 60hz IRQs and Raster IRQs a lot easier (no assembly code required). +There are a few library routines available to make setting up 60hz/vsync IRQs and raster/line IRQs a lot easier (no assembly code required). These routines are:: @@ -146,7 +146,7 @@ These routines are:: sys.set_rasterirq(uword handler_address, uword rasterline) sys.restore_irq() ; set everything back to the systems default irq handler -The IRQ handler routine must return a boolean value (0 or 1) in the A register. +The IRQ handler routine must return a boolean value (0 or 1) in the A register: 0 means do *not* run the system IRQ handler routine afterwards, 1 means run the system IRQ handler routine afterwards. @@ -158,9 +158,10 @@ when using this handler. These two helper routines are not particularly suited to handle multiple IRQ sources on the Commander X16. It's possible but it requires correct fiddling with IRQ enable bits, acknowledging the IRQs, and properly calling -or not calling the system IRQ handler routine. +or not calling the system IRQ handler routine. See the section below for perhaps a better and easier solution that +is tailored to this system. -The Commander X16 syslib provides two additional routines that should be used *in your IRQ handler routine* if it uses the Vera registers. +The Commander X16 syslib provides some additional routines that should be used *in your IRQ handler routine* if it uses the Vera registers. They take care of saving and restoring the Vera state of the interrupted main program, otherwise the IRQ handler's manipulation will corrupt any Vera operations that were going on in the main program. The routines are:: @@ -184,3 +185,42 @@ will corrupt any Vera operations that were going on in the main program. The rou of corrupting variables and floating point calculations that are being executed in the interrupted main program. These memory locations should be backed up and restored at the end of the handler, further increasing its execution time... + + +Commander X16 specific IRQ handling +=================================== + +Instead of using the routines in `sys` as mentioned above (that are more or less portable +across the C64,C128 and cx16), you can also use the special routines made for the Commander X16, +in `cx16`. The idea is to let Prog8 do the irq dispatching and housekeeping for you, and that +your program only has to register the specific handlers for the specific IRQ sources that you want to handle. + +Look at the examples/cx16/multi-irq-new.p8 example to see how these routines can be used. +Here they are, all available in `cx16`: + +``disable_irqs ()`` + Disables all Vera IRQ sources. Note that the CPU irq disable flag is not changed by this routine. + you can manipulate that via ``sys.set_irqd()`` and ``sys.clear_irqd()`` as usual. + +``enable_irq_handlers (bool disable_all_irq_sources)`` + Install the "master IRQ handler" that will dispatch IRQs to the registered handler for each type. + Only Vera IRQs supported for now. + The handlers don't need to clear its ISR bit, but have to return 0 or 1 in A, + where 1 means: continue with the system IRQ handler, 0 means: don't call that. + +``set_vsync_irq_handler (uword address)`` + Sets the verical sync interrupt handler routine. Also enables VSYNC interrupts. + +``set_line_irq_handler (uword rasterline, uword address)`` + Sets the rasterline interrupt handler routine to trigger on the specified raster line. + Also enables LINE interrupts. + You can use ``sys.set_rasterline()`` later to adjust the rasterline on which to trigger. + +``set_sprcol_irq_handler (uword address)`` + Sets the sprite collision interrupt handler routine. Also enables SPRCOL interrupts. + +``set_aflow_irq_handler (uword address)`` + Sets the audio buffer underrun interrupt handler routine. Also enables AFLOW interrupts. + +``disable_irq_handlers ()`` + Hand control back to the system default IRQ handler. diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 185bb3e11..7b17f3298 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -2,9 +2,6 @@ TODO ==== -- optimize sys.set_rasterline on X16 -- document new x16 irq handling stuff in docs - - use TRB/TSB instructions more on the x16 such as when ack vera irq bits cx16.VERA_ISR |= 4 xx |= %0001000, xx &= %1110111 diff --git a/examples/test.p8 b/examples/test.p8 index 17d53f20f..cbfd4e1d2 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -3,14 +3,19 @@ %import syslib %zeropage basicsafe +; Example that shows a way to handle multiple IRQ sources on the X16. +; This uses the "OLD" way using the interrupt handler routines in sys. +; (see multi-irq-new example to do it the "new" way) +; Currently only Vera interrupts are supported. VIA irqs are an exercise for the reader. + main { sub start() { sys.set_rasterline(150) - sys.set_irq(&irq.master_handler) - cx16.VERA_IEN |= 2 ; also enable line irq + sys.set_irq(&irq.master_handler) ; ..will just enable vsync.. + cx16.VERA_IEN |= 2 ; .. so also enable line irq here. - txt.print("\n\n\nisr installed\n") - txt.print("red = vsync\n") + txt.print("\n\n\nx16 irq handlers installed (old style)\n") + txt.print("red = vsync irq\n") txt.print("green = first line irq\n") txt.print("blue = second line irq\n") } @@ -18,7 +23,7 @@ main { irq { sub master_handler() -> bool { - ubyte irqsrc = cx16.VERA_ISR + ubyte irqsrc = cx16.VERA_ISR & cx16.VERA_IEN ; only consider sources that are enabled ror(irqsrc) if_cs { vsync_irq()