;; This example shows one way to handle the interrupts by hitting the hardware
;; directly.
;;
;; There are 6 interrupts per screen, one of which is triggered 2 HSYNCs after the start
;; of the VSYNC signal. We can use this to syncronise our interrupts.
;;
;; We first need to synchronise with the VSYNC, we can then enable our interrupts.
;; We now know exactly the order the interrupts will come and we can have 1 function for
;; each.

org &4000

start:
di				;; disable interrupts
im 1			;; Z80 interrupt mode (z80 calls to &0038 for each interrupt)

;; wait vsync (loop passes if VSYNC signal is high = in vsync)
ld b,&f5
wait1:
in a,(c)
rra
jr nc,wait1
;; wait for end of vsync (loop passes when VSYNC signal is low = out of vsync)
wait2:
in a,(c)
rra
jr c,wait2
;; now wait again for start (because we know we found the end, if we wait for VSYNC to be active
;; we know it will be the start)
wait3:
in a,(c)
rra
jr nc,wait3

;; we are now synchronised with the start of the vsync
;;
;; next interrupt should trigger 2 HSYNCs later.
;; 
;; now setup interrupts.

ld a,&c3	;; Z80 JP instruction
ld hl,int1	;; first function to call
ld (&0038),a	;; write JP instruction
ld (&0039),hl	;; write address
;;
;;
;; Z80 interrupt mode 1 vector is initialised
;; enable ints now.
ei


;; delay
loop:
jp loop

;; order:
;; int1->int2
;; int2->int3
;; int3->int4
;; int4->int5
;; int5->int6
;; int6->int1 (loop back)

;;--------------------------------------------------------------------------------------------

;; this is synchronised to happen 2 HSYNCs after VSYNC
int1:
;; change mode immediately
ld bc,&7f00+%10001101
out (c),c

push hl
ld hl,int2				;; we handle int2 next
ld (&0039),hl			;; set new interrupt vector address
pop hl
ei
reti

;;--------------------------------------------------------------------------------------------


int2:
push hl
ld hl,int3				;; we handle int3 next
ld (&0039),hl			;; set new interrupt vector address
pop hl
ei
reti

;;--------------------------------------------------------------------------------------------


int3:
push hl
ld hl,int4				;; we handle int4 next
ld (&0039),hl			;; set new interrupt vector address
pop hl
ei
reti

;;--------------------------------------------------------------------------------------------


int4:
push hl
ld hl,int5				;; we handle int5 next
ld (&0039),hl			;; set new interrupt vector address
pop hl
ei
reti

;;--------------------------------------------------------------------------------------------

int5:
push bc

;; delay
defs 32
defs 64*3
;; and change mode
ld bc,&7f00+%10001100
out (c),c

push hl
ld hl,int6				;; we handle int6 next
ld (&0039),hl			;; set new interrupt vector address
pop hl
pop bc
ei
reti

;;--------------------------------------------------------------------------------------------

int6:
push hl
ld hl,int1				;; we loop back to int1 next
ld (&0039),hl			;; set new interrupt vector address
pop hl
ei
reti

;;--------------------------------------------------------------------------------------------

end