;; This example shows the normal position of the cpc's 300Hz interrupt.
;; (i.e. the interrupt hasn't been delay)
;;
;; We use a fast ticker so we can show the most accurate position.
;;
;;
;; In Winape:
;; Reset cpc
;; Open assembler
;; New file
;; Copy and paste this code into the window
;; Assemble
;; In CPC window type:
;; CALL &8000



;; firmware functions we use in this example
.kl_new_fast_ticker equ &bce0
.mc_wait_flyback    equ &bd19
.kl_del_fast_ticker equ &bce6
.km_test_key 		equ &bb1e
.mc_set_inks		equ &bd25
.scr_set_mode		equ &bc0e
.txt_output			equ &bb5a
.txt_set_cursor	equ &bb75

org &8000

.start
ld a,1
call scr_set_mode

;; prevent firmware setting colours
;; and stop flicker at the top of screen which is caused by this
ld a,&c9
ld (mc_set_inks),a

ld hl,message
call print_msg

call set_vsync_pos

;; synchronise our ticker interrupt with the vsync       
call mc_wait_flyback
halt
halt
call mc_wait_flyback


ld a,6
ld (ticker_counter),a
ld hl,colours
ld (current_colour_pointer),hl

;; install interrupt
ld hl,ticker_event_block
ld b,%11000001				;; near address, express asynchronous event
ld c,&80					;; rom select 
ld de,ticker_function
call kl_new_fast_ticker


mainloop:
call mc_wait_flyback
call check_keys
jr c,quit_to_basic
halt
halt
jp mainloop

;; check if a key has been pressed and perform action if it has
check_keys:
ld a,0					;; cursor up
call km_test_key
jp nz,move_up
ld a,2					;; cursor down
call km_test_key
jp nz,move_down
ld a,47					;; space left
call km_test_key
ret z
scf
ret

print_msg:
ld a,(hl)
inc hl
or a
ret z
call txt_output
jr print_msg



move_up:
ld a,(vsync_pos)
inc a
ld (vsync_pos),a

call set_vsync_pos

or a
ret

move_down
ld a,(vsync_pos)
dec a
ld (vsync_pos),a

call set_vsync_pos

or a
ret

.set_vsync_pos
ld h,1
ld l,12
call txt_set_cursor
ld a,'&'
call txt_output
ld a,(vsync_pos)
call print_hex
ld bc,&bc07
out (c),c
ld a,(vsync_pos)
inc b
out (c),a
ret

.vsync_pos defb 30


.quit_to_basic
ld hl,ticker_event_block
call kl_del_fast_ticker
ret


;; this is initialised by
;; the firmware; holds runtime state of ticker interrupt
.ticker_event_block
defs 10

;; this is the function called each 1/300th of a second
.ticker_function
push af
push hl
;;push bc
;; The 1/300th of a second interrupt effectively splits
;; the screen into 6 sections of equal height. Each section
;; spans the entire width of the screen.
;;
;; We want to ensure that the effect is stationary so we reset
;; every 6 calls of this function. We need to ensure we are synced with vsync in
;; order that this works correctly.
ld a,(ticker_counter)
dec a
ld (ticker_counter),a
or a
jr nz,ticker_function2
ld a,6
ld (ticker_counter),a
ld hl,colours
ld (current_colour_pointer),hl

.ticker_function2

;; get pointer to current mode
ld hl,(current_colour_pointer)
;; get the mode

;; Select border
ld bc,&7f10			;; 
out (c),c			;; 
;; Set colour for border
ld a,(hl)			;; read colour from table
out (c),a			;; set colour

;; update pointer
inc hl
;; store pointer
ld (current_colour_pointer),hl

;; ensure express asynchronous event is retriggered correctly
;; see SOFT968
ld hl,ticker_event_block+2
ld (hl),#00
;;pop bc
pop hl
pop af
ret
 

print_hex:
push af
rrca
rrca
rrca
call print_hex_digit
pop af
.print_hex_digit
and &f
cp 10
jr nc,print_hex_digit2
add a,'0'
jp txt_output
print_hex_digit2:
add a,'A'-10
jp txt_output
    
message:
defb "The height of each colour bar show the",10,13
defb "time between each interrupt.",10,13,10,13
defb "The point where each colour changes is ",10,13
defb "the position of the interrupt.",10,13,10,13
defb "Use up/down cursor key to change the ",10,13
defb "position of the vertical sync."
defb 10,13,10,13
defb "Vsync Position (CRTC Register 7):",10,13,0
  

.ticker_counter defb 0

.current_colour_pointer defw colours

;; colours for each split

.colours
defb &43		;; pastel yellow
defb &40		;; white
defb &54		;; black
defb &4b		;; bright white
defb &45		;; purple
defb &51		;; yellow