;***********************************************************************
;* irq code start
;***********************************************************************
	
irq
	cli
	;dump
	
	;save all register
	
	epushsadrl
	epushsadrh
	push	r0
	push	r1
	push	r2
	push	r3
	push	r4
	push	r5
	push	r6
	push	r7
	
	;check type of irq
	
	dexti	>UcIrqMemory
	movei	r0,UcIrqMemory
	nop
	rqldi	r0,0
	nop
	nop
	ld	r0		;memory
	nop
	extri	r0,1		;timer 2
	gpci	r7,2		
	brts	irqTimer2	
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	;
	
	dexti	>UcIrqMemory
	movei	r0,UcIrqMemory
	nop
	rqldi	r0,0
	nop
	nop
	ld	r0		;memory
	nop
	extri	r0,2		;dac
	gpci	r7,2		
	brts	irqDAC	
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	;restore all used register and go back
	
	rqpop		
	rqpop	
	rqpop	
	pop	r7
	pop	r6
	pop	r5
	
	rqpop		
	rqpop	
	rqpop	
	pop	r4
	pop	r3
	pop	r2
	
	rqpop		
	rqpop
	rqpop
	pop	r1
        pop	r0
	epopsadrh
	
	rqpop
	nop
	nop
	epopsadrl	;delay slot
	
	rti
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	sei		;delay slot
	
;***********************************************************************
;* irq timer 2
;***********************************************************************
		
irqTimer2

	push	r0
	push	r7
	
	;mod tick
	
	dexti	>modTick
	movei	r0,modTick
	gpci	r7,2
	jmpi	r0,0
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	;clear irq 2 timer
	
	dexti	>UcIrqMemory
	movei	r0,UcIrqMemory
	nop
	rqldi	r0,0
	nop
	movei	r1,2		;timer 2
	ld	r2		;memory
	nop
	bic	r2,r2,r1
	nop
	st	r0,r2		;
	
	;back
	
	rqpop
	nop
	nop
	pop	r7
	
	rqpop
	jmpi	r7,0
	nop		;delay slot
	pop	r0	;delay slot
	nop		;delay slot
	nop		;delay slot
	
;***********************************************************************
;* irq audio
;***********************************************************************
	
irqDAC
	;irq begin
	
	push	r7
	
	;push leds on
	
	movei	r0,UcRSwichtWLedG
	movei	r1,$ff
	moveih	r0,>UcRSwichtWLedG
	moveih	r1,$ff
	nop
	st	r0,r1	
		
	
	;copy 96 values from channel 0	

	movei	r7,channel0
	dexti	>channelBufferdCopy
	movei	r1,channelBufferdCopy
	gpci	r5,2
	jmpi	r1,0
	movei	r0,95			;value count samples
	movei	r6,channel0Buffer	;out buffer
	moveih	r7,>channel0		;data struct
	moveih	r6,>channel0Buffer
	
	;copy 96 values from channel 1	

	movei	r7,channel1
	dexti	>channelBufferdCopy
	movei	r1,channelBufferdCopy
	gpci	r5,2
	jmpi	r1,0
	movei	r0,95			;value count samples
	movei	r6,channel1Buffer	;out buffer
	moveih	r7,>channel1		;data struct
	moveih	r6,>channel1Buffer
	
	;copy 96 values from channel 2	

	movei	r7,channel2
	dexti	>channelBufferdCopy
	movei	r1,channelBufferdCopy
	gpci	r5,2
	jmpi	r1,0
	movei	r0,95			;value count samples
	movei	r6,channel2Buffer	;out buffer
	moveih	r7,>channel2		;data struct
	moveih	r6,>channel2Buffer
	
	;copy 96 values from channel 3	

	movei	r7,channel3
	dexti	>channelBufferdCopy
	movei	r1,channelBufferdCopy
	gpci	r5,2
	jmpi	r1,0
	movei	r0,95			;value count samples
	movei	r6,channel3Buffer	;out buffer
	moveih	r7,>channel3		;data struct
	moveih	r6,>channel3Buffer
	
	;copy 96 values from channel 4	

	movei	r7,channel4
	dexti	>channelBufferdCopy
	movei	r1,channelBufferdCopy
	gpci	r5,2
	jmpi	r1,0
	movei	r0,95			;value count samples
	movei	r6,channel4Buffer	;out buffer
	moveih	r7,>channel4		;data struct
	moveih	r6,>channel4Buffer
	
	;copy 96 values from channel 5	

	movei	r7,channel5
	dexti	>channelBufferdCopy
	movei	r1,channelBufferdCopy
	gpci	r5,2
	jmpi	r1,0
	movei	r0,95			;value count samples
	movei	r6,channel5Buffer	;out buffer
	moveih	r7,>channel5		;data struct
	moveih	r6,>channel5Buffer
	
	;push dac data
	
	movei	r1,channel0Buffer
	movei	r2,channel1Buffer
	movei	r3,channel2Buffer
	movei	r4,channel3Buffer
	movei	r5,channel4Buffer
	movei	r6,channel5Buffer
	moveih	r1,>channel0Buffer
	moveih	r2,>channel1Buffer
	moveih	r3,>channel2Buffer
	moveih	r4,>channel3Buffer
	moveih	r5,>channel4Buffer
	moveih	r6,>channel5Buffer
	
	movei	r0,95			;95 values to DAC
	
fillDACBuffer

	push	r1
	push	r2
	push	r3
	push	r4

	rqldi	r1,0
	rqldi	r2,0
	rqldi	r3,0
	ld	r1
	ld	r2
	ld	r3
	add	r1,r1,r2
	nop
	add	r1,r1,r3
	
	rqldi	r4,0
	rqldi	r5,0
	rqldi	r6,0
	ld	r4
	ld	r2
	ld	r3
	add	r4,r4,r2
	movei	r2,UcAudioDACBase
	add	r4,r4,r3			
	moveih	r2,>UcAudioDACBase		
	movei	r3,0			;r3 = zero
		
	stinc	r2,r1	;dac left high = value
	movei	r7,$1
	stinc	r2,r3	;dac left low = 0
	moveih	r7,$1
	stinc	r2,r4	;dac right high = value
	nop
	stinc	r2,r3	;dac right low = 0
	nop
	st	r2,r7	;dac address/ctrl = $0101	;ctrl = enable audio
	
	rqpop	
	rqpop
	rqpop
	pop	r4
	pop	r3
	pop	r2
	
	rqpop
	addi	r6,1
	addi	r5,1
	pop	r1

	subi	r0,1
	brts	fillDACBuffer
	addi	r1,1		;delay slot						
	addi	r4,1		;delay slot
	addi	r3,1		;delay slot
	addi	r2,1		;delay slot
	
	;push leds off
	
	movei	r7,UcRSwichtWLedG
	movei	r6,$0
	moveih	r7,>UcRSwichtWLedG
	nop
	st	r7,r6	
	
	;clear stored audio irq
	
	dexti	>UcIrqMemory
	movei	r0,UcIrqMemory
	nop
	rqldi	r0,0
	nop
	movei	r1,4		;dac
	ld	r2		;memory
	nop
	bic	r2,r2,r1
	nop
	st	r0,r2		;
	
	;restore all used register and go back
	
	rqpop		
	nop
	nop	
	pop	r7
	nop
	
	jmpi	r7,0
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
;******************************
;*
;* initAudio
;*
;* return
;*
;* r0 = 0 (PASS)
;*

initAudio	

	push	r7
		
	movei	r6,audioDefault	
	movei	r5,2			;y cursor	
	moveih	r6,>audioDefault
	nop	
		
initAudioI2CWriteLoop
	
	rqldi	r6,0
	rqldi	r6,1
	nop
	ld	r2		;address
	ld	r3		;data
	
	cmpeqi	r2,$ff		;stop at sentinel ($ff)
	brts	initAudioI2CWriteFinish
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
			
	gpci	r7,2		;next 4 + X
	br	i2cWM8731WriteWord	;r2 = address;	r3 = data; return r0 = result
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	
	br	initAudioI2CWriteLoop
	addi	r6,2		;next lut address	delay slot
	addi	r5,1		;next y counter		delay slot
	nop			;delay slot
	nop			;delay slot

	movei	r0,0
	
initAudioI2CWriteFinish	
	
	rqpop
	nop
	nop
	pop	r7
	nop
	
	jmpi	r7,0
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	
;******************************
;*
;* i2cWM8731WriteWord
;*
;* r2 = address
;* r3 = data
;* 
;* return:
;*
;* r0 = result
;*

i2cWM8731WriteWord

	push	r4
	push	r1
	push	r6
	push	r7
	
	;start
	
	dexti	>i2cSendStart
	movei	r4,i2cSendStart
	gpci	r7,2	;next 4 + X
	jmpi	r4,0
	movei	r6,UcI2CSoftPortBCtrl		;delay slot
	nop					;delay slot
	moveih	r6,>UcI2CSoftPortBCtrl		;I2C ports b	;delay slot
	nop					;delay slot
		
	;write id
	
	dexti	>i2cSend8WACK
	movei	r4,i2cSend8WACK
	gpci	r7,2	;next 4 + X
	jmpi	r4,0
	movei	r1,$34		;WRITE			;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	
	cmpeqi	r0,0
	brtc	i2cSend8WACKFailsWr
	movei	r0,$ff		;delay slot
	nop			;delay slot
	moveih	r0,$01		;delay slot
	nop			;delay slot
	
	;write address
	
	add	r1,r2,r2	;adr*2
	extri	r3,8
	addtqi	r1,r1,0		;+ bit8 of data
	
	dexti	>i2cSend8WACK
	movei	r4,i2cSend8WACK
	gpci	r7,2	;next 4 + X
	jmpi	r4,0
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	
	cmpeqi	r0,0
	brtc	i2cSend8WACKFailsWr
	movei	r0,$ff		;delay slot
	nop			;delay slot
	moveih	r0,$02		;delay slot
	nop			;delay slot

	;write data low

	dexti	>i2cSend8WACK
	movei	r4,i2cSend8WACK
	gpci	r7,2	;next 4 + X
	jmpi	r4,0
	or	r1,r3,r3	;WRITE		;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
		
	cmpeqi	r0,0
	brtc	i2cSend8WACKFailsWr
	movei	r0,$ff		;delay slot
	nop			;delay slot
	moveih	r0,$04		;delay slot
	nop			;delay slot
	
	;finished without fail
	
	movei	r0,0		;all fine
	
	;stop
	
i2cSend8WACKFailsWr

	dexti	>i2cSendStop
	movei	r4,i2cSendStop
	gpci	r7,2	;next 4 + X
	jmpi	r4,0
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	
	dexti	>i2cWaitHalfPeriode
	movei	r4,i2cWaitHalfPeriode
	gpci	r7,2	;next 4 + X
	jmpi	r4,0
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
		
	dexti	>i2cWaitHalfPeriode
	movei	r4,i2cWaitHalfPeriode
	gpci	r7,2	;next 4 + X
	jmpi	r4,0
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	
	dexti	>i2cWaitHalfPeriode
	movei	r4,i2cWaitHalfPeriode
	gpci	r7,2	;next 4 + X
	jmpi	r4,0
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	
	dexti	>i2cWaitHalfPeriode
	movei	r4,i2cWaitHalfPeriode
	gpci	r7,2	;next 4 + X
	jmpi	r4,0
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot	
	
	
	rqpop
	rqpop
	rqpop
	pop	r7
	pop	r6
	pop	r1

	rqpop
	jmpi	r7,0
	nop			;delay slot
	pop	r4		;delay slot
	nop			;delay slot
	nop			;delay slot	
	
;******************************
;*
;* playSFX
;*
;* r5 = sfx data
;* r6 = channel
;*
	
playSFX

	push	r0
	push	r1
	push	r2
	push	r3
	push	r6
	push	r7
	
	;disable irq if enabled temporary

	getssr	r7,0	;get ucore status reg 0 (irq 0 = irq enabled)
	cli		;stop irqs
	push	r7
	
	;get sfx channel and switch
	
	;dexti	>sfxChannelSelector
	;movei	r0,sfxChannelSelector
	;nop
        ;
	;rqldi	r0,0
	;dexti	>sfxChannels
	;movei	r1,sfxChannels
	;ld	r2
	;movei	r3,sfxChannelSelectorMask
	;addi	r2,1
	;nop
	;and	r2,r2,r3
	;nop
	;st	r0,r2
	
	;set sample

	;rqld	r1,r2
	;nop
	;nop
	;ld	r6		;sfx channel
	
	gpci	r7,2
	br	setSfxSample	
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	nop			;delay slot
	
	;restore irq enable
	
	rqpop
	nop
	nop
	pop	r7
	nop
	setssr	r7,0	;write back
	
	;
	
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r6
	poparqp	r3
	pop	r2
	pop	r1
	pop	r0
	
	jmpi	r7,0
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	
;******************************
;*
;* setSfxSample
;* 	
;* r5 = sfx data
;* r6 = channel (struct)
;*
	
setSfxSample

	push	r0
	push	r1
	push	r2
	push	r3
	push	r4
	push	r7
	
	rqldi	r5,sfxSampleAddressHigh
	rqldi	r5,sfxSampleAddressLow
	nop
	ld	r1
	ld	r0
	
	dexti	>channelSetSampleAddress
	movei	r4,channelSetSampleAddress
	gpci	r7,2
	jmpi	r4,0
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	dexti	>channelSetRepeatStart
	movei	r4,channelSetRepeatStart
	gpci	r7,2
	jmpi	r4,0
	rqldi	r5,sfxSampleRepeatStart	;delay slot
	nop				;delay slot
	nop				;delay slot
	ld	r0			;delay slot
	
	dexti	>channelSetRepeatLength
	movei	r4,channelSetRepeatLength
	gpci	r7,2
	jmpi	r4,0
	rqldi	r5,sfxSampleRepeatLength;delay slot
	nop				;delay slot
	nop				;delay slot
	ld	r0			;delay slot
	
	dexti	>channelSetSampleLength
	movei	r4,channelSetSampleLength
	gpci	r7,2
	jmpi	r4,0
	rqldi	r5,sfxSampleLength	;delay slot
	nop				;delay slot
	nop				;delay slot
	ld	r0			;delay slot
	
	dexti	>channelSetSampleStart
	movei	r4,channelSetSampleStart
	gpci	r7,2
	jmpi	r4,0
	movei	r0,$0	;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	dexti	>channelSetVolume
	movei	r4,channelSetVolume
	gpci	r7,2
	jmpi	r4,0
	rqldi	r5,sfxSampleVolume	;delay slot
	nop				;delay slot
	nop				;delay slot
	ld	r0			;delay slot
	
	dexti	>channelSetPeriode
	movei	r4,channelSetPeriode
	gpci	r7,2
	jmpi	r4,0
	rqldi	r5,sfxSamplePeriode	;delay slot
	nop				;delay slot
	nop				;delay slot
	ld	r0			;delay slot
	
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r4
	poparqp	r3
	pop	r2
	pop	r1
	pop	r0
	
	jmpi	r7,0
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot	
		
;*********************************************************************
;* sfx setup
;*********************************************************************	

	.def	sfxSampleAddressHigh	0
	.def	sfxSampleAddressLow	1
	.def	sfxSampleRepeatStart	2
	.def	sfxSampleRepeatLength	3
	.def	sfxSampleLength		4
	.def	sfxSampleVolume		5
	.def	sfxSamplePeriode	6

sfxExplosionData	worduc	>>globalSfxExplosion
			worduc	globalSfxExplosion
			.data	0,2,$f8ee,$40,113
			
sfxShotData		worduc	>>globalSfxShot
			worduc	globalSfxShot
			.data	0,2,$6546,$40,269
	
;*********************************************************************
;* wm audio setup
;*********************************************************************	
	
audioDefault
	
	;
				;A =  8 7654 3210
	.data   $9,$0000	;9 =  0 0000 0000 	(inactivate interface)
	.data	$0,$0097	;0 =  0 1001 0111	;left line in mute
	.data	$1,$0097	;1 =  0 1001 0111	;right line in mute
	.data	$2,$0077	;2 =  0 0111 1001	;+6db left out
	.data	$3,$0077	;3 =  0 0111 1001	;0db right out
	.data	$4,$0012	;4 =  0 0001 0010	;0=0 mic boost off;
							;1=1 enable line input mute
							;2=1 line input to adc
							;3=0 disable bypass
							;4=1 DAC select
							;5=0 side tone disable
							;76=0 -6db sidetone						
	.data	$5,$0000	;5 =  0 0000 0000	;DAC soft Mute off, no Filer
	.data	$6,$0067	;6 =  0 0110 0111 	;DAC Power, Output Power, Device Power on
	.data	$7,$0009	;7 =  0 0000 1001 	;left justified, 24 bit
	.data	$8,$001e	;8 =  0 0001 1110	;0=0 normal mode
							;1=1 bosr (384/192)
							;5432=0111 96khz
							;78=00 no clk dividing	
	.data   $9,$0001	;9 =  0 0000 0001 	(activate interface)
	.data	$ff,$0000	;stop	
		
	