new X16 irq handler routines and examples

This commit is contained in:
Irmen de Jong 2023-11-22 20:03:21 +01:00
parent 935450a45f
commit 16851746d6
5 changed files with 204 additions and 7 deletions

View File

@ -850,8 +850,149 @@ asmsub restore_vera_context() clobbers(A) {
rts rts
}} }}
} }
; Commander X16 IRQ dispatcher routines
asmsub enable_irq_handlers() clobbers(A,Y) {
; 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.
%asm {{
php
sei
lda #<_irq_dispatcher
ldy #>_irq_dispatcher
sta cx16.CINV
sty cx16.CINV+1
plp
rts
_irq_dispatcher
jsr sys.save_prog8_internals
cld
lda cx16.VERA_ISR
lsr a
bcc +
_mod_vsync_jump
jsr _default_vsync_handler ; modified
cmp #0
bne _dispatch_end
lda #1
sta cx16.VERA_ISR
bra _return_irq
+ lsr a
bcc +
_mod_line_jump
jsr _default_line_handler ; modified
ldy #2
sty cx16.VERA_ISR
bra _dispatch_end
+ lsr a
bcc +
_mod_sprcol_jump
jsr _default_sprcol_handler ; modified
ldy #4
sty cx16.VERA_ISR
bra _dispatch_end
+ lsr a
bcc +
_mod_aflow_jump
jsr _default_aflow_handler ; modified
; note: AFLOW can only be cleared by filling the audio FIFO for at least 1/4. Not via the ISR bit.
bra _dispatch_end
+ lda #0
_dispatch_end
cmp #0
beq _return_irq
jsr sys.restore_prog8_internals
jmp (sys.restore_irq._orig_irqvec) ; continue with normal kernal irq routine
_return_irq
jsr sys.restore_prog8_internals
ply
plx
pla
rti
_default_vsync_handler
lda #1
rts
_default_line_handler
lda #0
rts
_default_sprcol_handler
lda #0
rts
_default_aflow_handler
lda #0
rts
}}
} }
asmsub set_vsync_irq_handler(uword address @AY) clobbers(A) {
; Sets the VSYNC irq handler to use with enable_irq_handlers(). Also enables VSYNC irqs.
; NOTE: unless a proper irq handler is already running, you should enclose this call in set_irqd() / clear_irqd() to avoid system crashes.
%asm {{
sta enable_irq_handlers._mod_vsync_jump+1
sty enable_irq_handlers._mod_vsync_jump+2
lda #1
tsb cx16.VERA_IEN
rts
}}
}
asmsub set_line_irq_handler(uword rasterline @R0, uword address @AY) clobbers(A,Y) {
; Sets the LINE irq handler to use with enable_irq_handlers(), for the given rasterline. Also enables LINE irqs.
; You can use sys.set_rasterline() later to adjust the rasterline on which to trigger.
; NOTE: unless a proper irq handler is already running, you should enclose this call in set_irqd() / clear_irqd() to avoid system crashes.
%asm {{
sta enable_irq_handlers._mod_line_jump+1
sty enable_irq_handlers._mod_line_jump+2
lda cx16.r0
ldy cx16.r0+1
jsr sys.set_rasterline
lda #2
tsb cx16.VERA_IEN
rts
}}
}
asmsub set_sprcol_irq_handler(uword address @AY) clobbers(A) {
; Sets the SPRCOL irq handler to use with enable_irq_handlers(). Also enables SPRCOL irqs.
; NOTE: unless a proper irq handler is already running, you should enclose this call in set_irqd() / clear_irqd() to avoid system crashes.
%asm {{
sta enable_irq_handlers._mod_sprcol_jump+1
sty enable_irq_handlers._mod_sprcol_jump+2
lda #4
tsb cx16.VERA_IEN
rts
}}
}
asmsub set_aflow_irq_handler(uword address @AY) clobbers(A) {
; Sets the AFLOW irq handler to use with enable_irq_handlers(). Also enables AFLOW irqs.
; NOTE: unless a proper irq handler is already running, you should enclose this call in set_irqd() / clear_irqd() to avoid system crashes.
%asm {{
sta enable_irq_handlers._mod_aflow_jump+1
sty enable_irq_handlers._mod_aflow_jump+2
lda #8
tsb cx16.VERA_IEN
rts
}}
}
asmsub disable_irq_handlers() {
; back to the system default IRQ handler.
%asm {{
jmp sys.restore_irq
}}
}
}
sys { sys {
; ------- lowlevel system routines -------- ; ------- lowlevel system routines --------
@ -962,9 +1103,7 @@ _modified
plx plx
pla pla
rti rti
}}
_use_kernal .byte 0
}}
} }
asmsub restore_irq() clobbers(A) { asmsub restore_irq() clobbers(A) {

View File

@ -117,7 +117,8 @@ class TestCompilerOnExamplesCx16: FunSpec({
"kefrenbars", "kefrenbars",
"keyboardhandler", "keyboardhandler",
"mandelbrot", "mandelbrot",
"multi-irq", "multi-irq-old",
"multi-irq-new",
"plasma", "plasma",
"rasterbars", "rasterbars",
"snow", "snow",

View File

@ -2,6 +2,10 @@
TODO TODO
==== ====
- move x16 irq examples over to new style handler
- 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 - use TRB/TSB instructions more on the x16 such as when ack vera irq bits cx16.VERA_ISR |= 4
xx |= %0001000, xx &= %1110111 xx |= %0001000, xx &= %1110111

View File

@ -0,0 +1,51 @@
%import palette
%import textio
%import syslib
%zeropage basicsafe
; Example that shows a way to handle multiple IRQ sources on the X16.
; This uses the "NEW" way using the X16 specific interrupt handler routines in cx16.
; Currently only Vera interrupts are supported. VIA irqs are an exercise for the reader.
main {
sub start() {
cx16.enable_irq_handlers()
cx16.set_line_irq_handler(150, &irq.line_irq)
cx16.set_vsync_irq_handler(&irq.vsync_irq)
txt.print("\n\n\nx16 irq handlers installed (new style)\n")
txt.print("red = vsync irq\n")
txt.print("green = first line irq\n")
txt.print("blue = second line irq\n")
}
}
irq {
sub vsync_irq() -> bool {
cx16.save_vera_context()
palette.set_color(0, $f00)
repeat 1000 {
cx16.r0++
}
palette.set_color(0, $000)
cx16.restore_vera_context()
return true
}
sub line_irq() -> bool {
cx16.save_vera_context()
if cx16.VERA_SCANLINE_L==150 {
palette.set_color(0, $0f0)
sys.set_rasterline(200) ; prepare next line irq
} else {
palette.set_color(0, $00f)
sys.set_rasterline(150) ; back to first line irq
}
repeat 500 {
cx16.r0++
}
palette.set_color(0, $000)
cx16.restore_vera_context()
return false
}
}

View File

@ -4,7 +4,9 @@
%zeropage basicsafe %zeropage basicsafe
; Example that shows a way to handle multiple IRQ sources on the X16. ; Example that shows a way to handle multiple IRQ sources on the X16.
; Currently only Vera interrupts are supported. ; 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 { main {
sub start() { sub start() {
@ -12,8 +14,8 @@ main {
sys.set_irq(&irq.master_handler) ; ..will just enable vsync.. sys.set_irq(&irq.master_handler) ; ..will just enable vsync..
cx16.VERA_IEN |= 2 ; .. so also enable line irq here. cx16.VERA_IEN |= 2 ; .. so also enable line irq here.
txt.print("\n\n\nisr installed\n") txt.print("\n\n\nx16 irq handlers installed (old style)\n")
txt.print("red = vsync\n") txt.print("red = vsync irq\n")
txt.print("green = first line irq\n") txt.print("green = first line irq\n")
txt.print("blue = second line irq\n") txt.print("blue = second line irq\n")
} }