
	.def	channelRepeatStart		0
	.def	channelRepeatLength		1
	.def	channelIncrement		2
	.def	channelVolume			3	
	.def	channelLength			4
	.def	channelCurrentPositionLow	5
	.def	channelCurrentPositionHigh	6
	.def	channelSampleAdrLow		7
	.def	channelSampleAdrHigh		8
	.def	channelDummy			9
	
	;following values are only for store mod values (dont reservate size if not needed)
	
	.def	channelStCmd			10	;0
	.def	channelStNote			11	;1
	.def	channelStPeriode		12	;2
	.def	channelStVolume			13	;3
	.def	channelStSampleNumber		14	;4
	.def	channelStStart			15	;5
	.def	channelStRealLength		16	;6
	.def	channelStLength			17	;7
	.def	channelStFineTune		18	;8
	.def	channelStRepeatStart		19	;10
	.def	channelStRepeatLength		20	;11
	.def	channelStVibratoCmd		21	;12
	.def	channelStVibratoPos		22	;13
	.def	channelStLoopPos		23	;14
	.def	channelStLoopCount		24	;15
	.def	channelStTremoloCmd		25	;16
	.def	channelStTremoloPos		26	;17
	.def	channelStWantPeriode		27	;18
	.def	channelStToneportdirec		28	;19
	.def	channelStToneportspeed		29	;20
	
	.def	channelStructSize		32
	
; channel init !!!	
	
;******************************
;*
;* channelSetSampleAddress
;*
;* r0 = sample low
;* r1 = sample high
;* r6 = channel struct
;*

channelSetSampleAddress
	
	jmpi	r7,0
	ssto	channelSampleAdrLow	;delay slot
	stwo	r6,r0			;delay slot
	ssto	channelSampleAdrHigh	;delay slot
	stwo	r6,r1			;delay slot
	
;******************************
;*
;* channelSetRepeatStart
;*
;* r0 = value
;* r6 = channel struct
;*

channelSetRepeatStart

	jmpi	r7,0
	ssto	channelRepeatStart	;delay slot
	stwo	r6,r0			;delay slot
	nop				;delay slot
	nop				;delay slot

;******************************
;*
;* channelSetRepeatLength
;*
;* r0 = value
;* r6 = channel struct
;*

channelSetRepeatLength

	push	r1
	push	r2
	push	r3

	movei	r1,$ff
	rqldi	r6,channelRepeatStart
	moveih	r1,$ff
	movei	r3,0
	ld	r2		;get rep start

	cmploi	r0,3		;length <3 is no repeat 
	movets	r0,r1,r0	;no repeat -> rep length = $ffff else rep length
	movets	r2,r3,r2	;             rep start  = $0    else rep start
	
	ssto	channelRepeatStart
	st	r6,r2			;store repeat start
	
	rqpop
	rqpop
	rqpop
	pop	r3
	pop	r2
	pop	r1
	
	jmpi	r7,0
	ssto	channelRepeatLength	;store repeat length	delay slot
	stwo	r6,r0			;			delay slot
	nop				;			delay slot
	nop				;			delay slot
	
;******************************
;*
;* channelSetVolume
;*
;* r0 = value
;* r6 = channel struct
;*

channelSetVolume

	jmpi	r7,0
	ssto	channelVolume		;delay slot
	stwo	r6,r0			;delay slot
	nop				;delay slot
	nop				;delay slot

;******************************
;*
;* channelSetSampleLength
;*
;* r0 = value
;* r6 = channel struct
;*

channelSetSampleLength

	jmpi	r7,0
	ssto	channelLength		;delay slot
	stwo	r6,r0			;delay slot
	nop				;delay slot
	nop				;delay slot
	
;******************************
;*
;* channelSetSampleStart
;*
;* r0 = value (in bytes)
;* r6 = channel struct
;*

channelSetSampleStart

	;dump
	;add	r0,r0,r0	; *2
	ssto	channelCurrentPositionHigh	
	stwo	r6,r0	
	jmpi	r7,0
	movei	r0,0				;delay slot
	nop					;delay slot
	ssto	channelCurrentPositionLow	;delay slot	
	stwo	r6,r0				;delay slot

;******************************
;*
;* channelSetPeriode
;*
;* r0 = value
;* r6 = channel struct
;*
;* note: this function is not irq save
;* 

channelSetPeriode

	push	r2
	push	r3
		
	;store irq_enable
	
	cmpeqi	r0,0		;periode 0? if true set increment to 0
	brts	skipDiv0
	nop			;delay slot
	movei	r2,$7c		;delay slot
	movei	r3,$37		;delay slot
	moveih	r2,$6b		;r3:r2 = 3631996 	;delay slot
	
	udivinit	21	;22 bit division (-1)
	udivsdd		r2
	udivsddh	r3	;
	
	movei	r2,4	;(4+1)*4 = 20
	udivsdv		r0	;r3:r2 / periode
	
pToILoop	
	subi	r2,1
	brts	pToILoop
	udivstep	;delay slot	
	udivstep        ;delay slot
	udivstep        ;delay slot
	udivstep        ;delay slot
	
	udivstep        ;21
	udivstep        ;22
		
	udivgq	r0      ;get result

skipDiv0	
	
	rqpop
	rqpop
	jmpi	r7,0	
	pop	r3			;delay slot
	pop	r2      		;delay slot
	ssto	channelIncrement	;delay slot	
	stwo	r6,r0			;store new increment value delay slot	
	
;******************************
;*
;* channelBufferdCopy
;*
;* r0 = counter
;* r5 = return address !!
;* r6 = channel out buffer
;* r7 = channel struct
;*
	
channelBufferdCopy	

	push	r1
	push	r2
	push	r3
	push	r4
	push	r5
	
	rqldi	r7,channelCurrentPositionHigh
	rqldi	r7,channelRepeatStart
	rqldi	r7,channelRepeatLength
	ld	r1		;pos high
	ld	r2		;repeat start
	ld	r3		;repeat length
	
	rqldi	r7,channelSampleAdrLow
	rqldi	r7,channelSampleAdrHigh
	add	r3,r3,r2	;rep start + rep length
	ld	r4		;sample adr low
	ld	r5		;sample adr high
	nop

	esadr	r5,r4		;sample addr
	
smpLoop	
	
	rqldi	r7,channelLength
	cmplo	r1,r3		;pos high < (rep start + rep length)
	movets	r1,r1,r2	;pos high = pos high TS else rep start , dont remove fractal part
	ld	r4		;channel length
	nop
	cmplo	r1,r4		;pos high < channel length
	brtc	smpFinish
	movei	r4,0				;delay slot	value = 0
	rqldi	r7,channelCurrentPositionLow	;delay slot
	rqldi	r7,channelIncrement		;delay slot
	nop					;delay slot
	
	ld	r5		;pos low
	ld	r4		;increment
	nop			;?
	
	erqldb	r1		;take some cycles to get data
	
	add	r5,r5,r4	;pos + incremnt 
	addtqi	r1,r1,0	
	rqldi	r7,channelVolume
	add	r5,r5,r4	;pos + increment
	addtqi	r1,r1,0
	ld	r4		;volume
	
	ssto	channelCurrentPositionLow
	stwo	r7,r5		;store low back
		
	extri	r5,0		;is even address?	
	eld	r5		;value
	nop
	swptc	r5,r5		;swap bytes
	
smpFinish
	
	subi	r0,1
	extb	r5,r5		;signed extend from byte to word
	brts	smpLoop
	muls	r5,r5,r4	;value * volume			delay slot
        nop     		;				delay slot
	stinc	r6,r5    	;*channelbuffer++ = value	delay slot
	nop			;				delay slot
	
	ssto	channelCurrentPositionHigh
	stwo	r7,r1		;store high back
	
	rqpop	
	rqpop	
	rqpop
	pop	r5
	pop	r4
	pop	r3
	
	rqpop
	rqpop
	jmpi	r5,0		;return via r5!
	pop	r2		;				delay slot
	pop	r1		;				delay slot
	nop			;				delay slot
	nop			;				delay slot