; ticker.s
; Sits on TickerV and fills Replay sound buffers when necessary.
; To work in 32-bit mode this code will have to be rewritten, removing
; the ^ from the LDMFD instructions, changing "MOVS pc, lr" to "MOV pc, lr",
; and changing the code to switch to and from SVC mode.

; SWI code
XOS_AddCallBack			EQU 0x20054

; Structure offsets
O_codec				EQU 0
O_mute				EQU 4
O_sfr				EQU 8
O_pw				EQU 12
O_semaphore			EQU 16
O_ticker_registered		EQU 17
O_tick_callback_registered	EQU 18
O_finished_callback_registered	EQU 19
O_fill_needed			EQU 20
O_finished			EQU 21

O_bufferA			EQU 16
O_bufferB			EQU 20

O_needs_fill			EQU 4

fill_result_Finished		EQU 4

	AREA |Replay$$Code|, CODE, READONLY

	IMPORT cmhg_tick_callback
	IMPORT cmhg_finished_callback

	EXPORT ticker_handler

 DCB	"ticker_handler", 0
 ALIGN

ticker_handler
	STMFD	sp!, {r0-r3, r8, r9, r12, lr}
	LDRB	r1, [r12, #O_semaphore]
	; Mustn't do anything if semaphore already set
	TEQ	r1, #0
	LDMNEFD	sp!, {r0-r3, r8, r9, r12, pc}^
	MOV	r1, #1
	STRB	r1, [r12, #O_semaphore]
	; Read whether sample buffers need filling
	LDR	r1, [r12, #O_codec]
	LDR	r2, [r1, #O_bufferB]
	LDR	r1, [r1, #O_bufferA]
	LDR	r1, [r1, #O_needs_fill]
	LDR	r2, [r2, #O_needs_fill]
	; If finished, check whether both buffers are empty
	LDR	r0, [r12, #O_sfr]
	TEQ	r0, #fill_result_Finished
	BNE	check_if_fill_needed
	TEQ	r1, #0
	TEQNE	r2, #0
	MOVEQ	r1, #0
	STREQB	r1, [r12, #O_semaphore]
	LDMEQFD	sp!, {r0-r3, r8, r9, r12, pc}^
	LDR	r0, =cmhg_finished_callback
	MOV	r2, #O_finished_callback_registered
	B	set_callback
check_if_fill_needed
	ORRS	r1, r1, r2
	STREQB	r1, [r12, #O_semaphore]
	LDMEQFD	sp!, {r0-r3, r8, r9, r12, pc}^
	LDR	r0, =cmhg_tick_callback
	MOV	r2, #O_tick_callback_registered
set_callback
	LDR	r1, [r12, #O_pw]

	[ EVERY = 1
	; Preserve current mode and enter SVC mode to preserve R14_SVC
	; Only needs to be done for TickerV, not for OS_CallEvery
	MOV	r9, pc
	ORR	r8, r9, #3
	TEQP	r8, #0
	MOV	r0, r0
	STMFD	sp!, {lr}
	]

	; Call the SWI
	SWI	XOS_AddCallBack
	MOVVC	r1, #1
	STRVCB	r1, [r12, r2]

	[ EVERY = 1
	; Restore R14_SVC and re-enter previous mode
	LDMFD	sp!, {lr}
	TEQP	r9, #0
	MOV	r0, r0
	]

	LDMFD	sp!, {r0-r3, r8, r9, r12, pc}^


local_tick_callback
	STMFD	sp!, {r0}
	MOV	r0, #0
	STRB	r0, [r12, #O_tick_callback_registered]
	MOV	r0, #1
	STRB	r0, [r12, #O_fill_needed]
	LDMFD	sp!, {r0}
	MOV	pc, lr

local_finished_callback
	STMFD	sp!, {r0}
	MOV	r0, #0
	STRB	r0, [r12, #O_finished_callback_registered]
	MOV	r0, #1
	STRB	r0, [r12, #O_finished]
	LDMFD	sp!, {r0}
	MOV	pc, lr


	END
