User Tools

Site Tools


base:launching_long_tasks_from_irq_handler

This is an old revision of the document!


Launching long tasks from inside a IRQ handler

When executing code within an IRQ handler you have to finish things before the next IRQ occurs. But sometimes tasks just take some more time, for that you can spin off those tasks from inside the handler, and allow then upcoming IRQs to happen. When the IRQ handler is finished it would fetch 3 bytes from stack and return to the code that was interrupted by the IRQ. Here we squeeze in our new task by adding another 3 bytes to the stack. Thus before continuing with the interrupted code our new task will be executed first.

irq
       ;save registers
       sta register_a
       stx register_x
       sty register_y

       ;... your desired irq handler code goes here
   
       ;now push 3 more bytes on stack
       lda #>task
       pha
       lda #<task
       pha
       ;flags, can even be used to signal stuff to task by setting carry/overflow/negative/...
       lda #$00
       pha
   
       ;rti will now finish this interrupt and continue with the new task instead of the code
       ;being executed before this IRQ occurred.
       rti
    
task
       ;...some code
    
       ;restore registers
       lda register_a
       ldx register_x
       ldy register_y
       ;now finally continue with code being executed before IRQ
       rti

Alternatively one can just clear the irq flag and let the next irq happen, but this only works if the next irq is a different irq with different handler. Imagine you have one interrupt happening at rasterline $32 and it will usually take until line $120 or shorter. Now you want to have your music play at line $ff constantly. To solve that conflict you can do:

irq1
        dec $d019
        sta reg_a
        stx reg_x
        sty reg_y
        
        ;set up next irq to play music
        lda #<irq2
        sta $fffe
        lda #>irq2
        sta $ffff
        
        lda #$ff
        sta $d012
        
        ;now allow irq2 happen on top of this task and return to this task when done
        cli
        
        ... effect that takes much cycles ...
        
        ldy reg_y
        ldx reg_x
        lda reg_a
        rti
        
irq2
        dec $d019
        ;use different locations to store registers
        sta reg_a_
        stx reg_x_
        sty reg_y_
        
        jsr $1003
        
        ;setup next irq1
        lda #$32
        sta $d012
        
        lda #<irq1
        sta $fffe
        lda #>irq1
        sta $ffff

        ldy reg_y_
        ldx reg_x_
        lda reg_a_
        rti
base/launching_long_tasks_from_irq_handler.1454440135.txt.gz · Last modified: 2016-02-02 20:08 by bitbreaker