;*******************************************************************************
; C H A M E L E O N   DSP Assembler file                                       *
;*******************************************************************************
;Aleix Riera
;http://www.fjarre.com/~aleix
;aleix@fjarre.com
;*******************************************************************************
;South pole v0.99 Basic Modular Structure:
;
;-->IN===LPF0==3MIXER0===SAT===4MIXER==============3MIXER====OUT---->
;        |  |     "          "  |		    " "
;        BPF0====="          "  |		    " "
;        |  |     "          "  |		    " "
;        HPF0====="          =====4MIXERD===STDELAY=" "
;        |  |                   |		      "
;        |  |                	|		      "
;        |  |                	|		      "
;     KF0C  KF0R 	       K0P		      "
;       |    |          	|		      "
;       |    |    	        |		      "
;     LFO0C LFO0R             LFO0P		     IN
;
; NOTE: Lines 3 and 4 have the Saturator BEFORE the filter bank
;
;###############################################################################

 	nolist
	page	255,0
	opt	MU,S,CC,CEX,MEX,MD
	list

	nolist
	include	"SDK\include\dsp\dsp_equ.asm"
	include	"dma\cdma.asm"
	include	"dma\dma.asm"
	;include "SDK\include\dsp\dma.asm"
	list

;constants
	;THE NEXT ARE INVOLVED IN COLDFIRE TOO
MIN_CUTOFF		equ	$080000	;to avoid negative and near 0 values
BUFFER_SIZE		equ	16
DSP_DATA_LEN		equ	79
LFO_WAVETABLE_SIZE	equ	$0000FF	;(-1)
	;(MAKE SURE TO MAKE THE CHANGES IN BOTH SIDES)
	
ZERO			equ	$000000
ONE			equ	$7FFFFF
MAX_CUTOFF		equ	$7FFFFF	;to make de complementary NOTCH_BANDWIDTH
MIN_RES			equ	$000000
MIN_PAN			equ	$000000
VOLUME_INC		equ	$008000	;GlobalVolume interpolation
CUTOFF_INC		equ	$00C000	;Filters cut off interpolation
HALFSAT_WAVETABLE_SIZE	equ	$000080 ;half (if odd=> subtract -1 and make half)
DELAY_BUFFER_SIZE	equ	$080000
NOTCH_BANDWIDTH		equ	$100000	;LPF cutoff offset
COMP_NOTCH_BANDWIDTH	equ	MAX_CUTOFF-NOTCH_BANDWIDTH

MODULE_PARAM_SIZE	equ	32
NUM_MODULE_PARAM	equ	27	;To be initialized
NUM_Y_BUFFERS		equ	0	;To be initialized
NUM_L_BUFFERS		equ	33	;To be initialized

	org	Xl:ZERO	; internal X memory
	org	Yl:ZERO	; internal Y memory

	org	Pl:$000100	; internal P memory
	org	Ph:$400000	; external P memory

	org	Xh:$440000	; external X memory (with an arbitrary offset of $40000
				; to avoid overlapping with the external P memory)

	define	R_X	'R0'	;module parameters transfer
	define	N_X	'N0'	;indexing (used in filter module)
	
	define	R_HostDataIn	'R4'
	define	M_HostDataIn	'M4'
		;DO NOT CHANGE (main program & modules would have to be changed)
	
	org	Xh:

	;DMA buffers
BufferDAC:
	BufferDAC1:	ds	2*BUFFER_SIZE
	BufferDAC2:	ds	2*BUFFER_SIZE
BufferADC:
	BufferADC1:	ds	2*BUFFER_SIZE
	BufferADC2:	ds	2*BUFFER_SIZE
	;;;;
	DelayBufferL:	ds	DELAY_BUFFER_SIZE
	DelayBufferR:	ds	DELAY_BUFFER_SIZE
	SatWave:
				include	'wtables/longpul.asm'

	org	L:ZERO
	IN_STEREO_CHUNK:	ds	BUFFER_SIZE
	OutStereoFilter0:	ds	BUFFER_SIZE
	OutStereoFilter1:	ds	BUFFER_SIZE
	OutStereoFilter2:	ds	BUFFER_SIZE
	OutStereoFilter3:	ds	BUFFER_SIZE
	OutStereoFilter0_NR1:	ds	BUFFER_SIZE
	OutStereoFilter1_NR1:	ds	BUFFER_SIZE
	OutStereoFilter2_NR1:	ds	BUFFER_SIZE
	OutStereoFilter3_NR1:	ds	BUFFER_SIZE
	OutStereoFilter0_NR2:	ds	BUFFER_SIZE
	OutStereoFilter1_NR2:	ds	BUFFER_SIZE
	OutStereoFilter2_NR2:	ds	BUFFER_SIZE
	OutStereoFilter3_NR2:	ds	BUFFER_SIZE
	OutStereoHFilter0:	ds	BUFFER_SIZE
	OutStereoHFilter1:	ds	BUFFER_SIZE
	OutStereoHFilter2:	ds	BUFFER_SIZE
	OutStereoHFilter3:	ds	BUFFER_SIZE
	OutStereoBFilter0:	ds	BUFFER_SIZE
	OutStereoBFilter1:	ds	BUFFER_SIZE
	OutStereoBFilter2:	ds	BUFFER_SIZE
	OutStereoBFilter3:	ds	BUFFER_SIZE
	OutStereo3Mixer0:	ds	BUFFER_SIZE
	OutStereo3Mixer1:	ds	BUFFER_SIZE
	OutStereo3Mixer2:	ds	BUFFER_SIZE
	OutStereo3Mixer3:	ds	BUFFER_SIZE
	OutStereoSat0:		ds	BUFFER_SIZE
	OutStereoSat1:		ds	BUFFER_SIZE
	OutStereoSat2:		ds	BUFFER_SIZE
	OutStereoSat3:		ds	BUFFER_SIZE
	OutStereo4Mixer:	ds	BUFFER_SIZE
	OutStereo4MixerD:	ds	BUFFER_SIZE
	OutStereoDelay:		ds	BUFFER_SIZE
	OutStereo3GlobalMixer:	ds	BUFFER_SIZE
	;IN_STEREO_CHUNK before all (initialization)

End_L_Memory:
		
	org	Xl:End_L_Memory
	;Wavetables
	LFOWave:
				include 'wtables/cosine.asm'
	;Stacks:

	ModuleParamX:		ds	MODULE_PARAM_SIZE
		;For modules which do not have state variables
	ModuleParamX_Filt0:	ds	MODULE_PARAM_SIZE
	ModuleParamX_Filt1:	ds	MODULE_PARAM_SIZE
	ModuleParamX_Filt2:	ds	MODULE_PARAM_SIZE
	ModuleParamX_Filt3:	ds	MODULE_PARAM_SIZE
	ModuleParamX_Filt0_NR1:	ds	MODULE_PARAM_SIZE
	ModuleParamX_Filt1_NR1:	ds	MODULE_PARAM_SIZE
	ModuleParamX_Filt2_NR1:	ds	MODULE_PARAM_SIZE
	ModuleParamX_Filt3_NR1:	ds	MODULE_PARAM_SIZE
	ModuleParamX_Filt0_NR2:	ds	MODULE_PARAM_SIZE
	ModuleParamX_Filt1_NR2:	ds	MODULE_PARAM_SIZE
	ModuleParamX_Filt2_NR2:	ds	MODULE_PARAM_SIZE
	ModuleParamX_Filt3_NR2:	ds	MODULE_PARAM_SIZE
	ModuleParamX_LFO0Cut:	ds	MODULE_PARAM_SIZE
	ModuleParamX_LFO0Res:	ds	MODULE_PARAM_SIZE
	ModuleParamX_LFO0Pan:	ds	MODULE_PARAM_SIZE
	ModuleParamX_LFO1Cut:	ds	MODULE_PARAM_SIZE
	ModuleParamX_LFO1Res:	ds	MODULE_PARAM_SIZE
	ModuleParamX_LFO1Pan:	ds	MODULE_PARAM_SIZE
	ModuleParamX_LFO2Cut:	ds	MODULE_PARAM_SIZE
	ModuleParamX_LFO2Res:	ds	MODULE_PARAM_SIZE
	ModuleParamX_LFO2Pan:	ds	MODULE_PARAM_SIZE
	ModuleParamX_LFO3Cut:	ds	MODULE_PARAM_SIZE
	ModuleParamX_LFO3Res:	ds	MODULE_PARAM_SIZE
	ModuleParamX_LFO3Pan:	ds	MODULE_PARAM_SIZE
	ModuleParamX_DelayL:	ds	MODULE_PARAM_SIZE
	ModuleParamX_DelayR:	ds	MODULE_PARAM_SIZE
		;Delay0L BEFORE of Delay0R (initialization)
		;WARNING: Number of stacks must be updated in constant
		;'NUM_MODULE_PARAM'

	;X WARNING: Make sure that the range $800 is not overrided
	
	org	Yl:End_L_Memory

	HostDataInput:	dsm	DSP_DATA_LEN

	OutK0Cut:	ds	1
	OutK0Res:	ds	1
	OutK0Pan:	ds	1
	OutK1Cut:	ds	1
	OutK1Res:	ds	1
	OutK1Pan:	ds	1
	OutK2Cut:	ds	1
	OutK2Res:	ds	1
	OutK2Pan:	ds	1
	OutK3Cut:	ds	1
	OutK3Res:	ds	1
	OutK3Pan:	ds	1
	OutLFO0Cut:	ds	1
	OutLFO0Res:	ds	1
	OutLFO0Pan:	ds	1
	OutLFO1Cut:	ds	1
	OutLFO1Res:	ds	1
	OutLFO1Pan:	ds	1
	OutLFO2Cut:	ds	1
	OutLFO2Res:	ds	1
	OutLFO2Pan:	ds	1
	OutLFO3Cut:	ds	1
	OutLFO3Res:	ds	1
	OutLFO3Pan:	ds	1

	GlobalVolume:		ds	1
	GlobalVolume_actual:	ds	1
	
	;Global Delay
		DelayTimeL:	ds	1
		DelayTimeR:	ds	1
		DelayFeedback:	ds	1
	;Saturation
		Sat0:		ds	1
		Sat1:		ds	1
		Sat2:		ds	1
		Sat3:		ds	1
	;Global Mix
		MixThru:	ds	1
		MixLines:	ds	1
		MixDelay:	ds	1
	;Line0:
		Volume0:	ds	1
		K0Cut:		ds	1
		K0Res:		ds	1
		K0Pan:		ds	1
		LFO0CutAmp:	ds	1
		LFO0ResAmp:	ds	1
		LFO0PanAmp:	ds	1
		LFO0iCutFreq:	ds	1
		LFO0iResFreq:	ds	1
		LFO0iPanFreq:	ds	1
		LFO0fCutFreq:	ds	1
		LFO0fResFreq:	ds	1
		LFO0fPanFreq:	ds	1
		Send0:		ds	1
		LPFLevel0:	ds	1
		BPFLevel0:	ds	1
		HPFLevel0:	ds	1
		;Cutoff interpolation
		K0Cut_actual:	ds	1
	;Line1:
		Volume1:	ds	1
		K1Cut:		ds	1
		K1Res:		ds	1
		K1Pan:		ds	1
		LFO1CutAmp:	ds	1
		LFO1ResAmp:	ds	1
		LFO1PanAmp:	ds	1
		LFO1iCutFreq:	ds	1
		LFO1iResFreq:	ds	1
		LFO1iPanFreq:	ds	1
		LFO1fCutFreq:	ds	1
		LFO1fResFreq:	ds	1
		LFO1fPanFreq:	ds	1
		Send1:		ds	1
		LPFLevel1:	ds	1
		BPFLevel1:	ds	1
		HPFLevel1:	ds	1
		K1Cut_actual:	ds	1
	;Line2:
		Volume2:	ds	1
		K2Cut:		ds	1
		K2Res:		ds	1
		K2Pan:		ds	1
		LFO2CutAmp:	ds	1
		LFO2ResAmp:	ds	1
		LFO2PanAmp:	ds	1
		LFO2iCutFreq:	ds	1
		LFO2iResFreq:	ds	1
		LFO2iPanFreq:	ds	1
		LFO2fCutFreq:	ds	1
		LFO2fResFreq:	ds	1
		LFO2fPanFreq:	ds	1
		Send2:		ds	1
		LPFLevel2:	ds	1
		BPFLevel2:	ds	1
		HPFLevel2:	ds	1
		K2Cut_actual:	ds	1
	;Line3:
		Volume3:	ds	1
		K3Cut:		ds	1
		K3Res:		ds	1
		K3Pan:		ds	1
		LFO3CutAmp:	ds	1
		LFO3ResAmp:	ds	1
		LFO3PanAmp:	ds	1
		LFO3iCutFreq:	ds	1
		LFO3iResFreq:	ds	1
		LFO3iPanFreq:	ds	1
		LFO3fCutFreq:	ds	1
		LFO3fResFreq:	ds	1
		LFO3fPanFreq:	ds	1
		Send3:		ds	1
		LPFLevel3:	ds	1
		BPFLevel3:	ds	1
		HPFLevel3:	ds	1
		K3Cut_actual:	ds	1
		
	;addr containing wich buffer is the active one
	ActiveBufferDAC:	ds	1	; Filled on Start
	ActiveBufferADC:	ds	1	; Filled on Start
	
	;Y WARNING: Make sure that the range $800 is not overrided

	;Get Connections Table
	include 'ctable.asm'

	;Get Control Table
	include 'ctrltab.asm'

	;Interrupt on Host Data Received
	org	P:VecHostRxDataFull
	MOVEP	X:<<HRX,Y:(R_HostDataIn)+
	NOP
		
	org	Pl:
	;Modules
	include	'modules/in.asm'
	include	'modules/out.asm'
	include 'modules/osc_.asm'	;1 sample/DMA
	include	'modules/4mixer2.asm'
	include	'modules/4mixerd.asm'
	include 'modules/3mixer.asm'
	include 'modules/sub.asm'
	include	'modules/addk_.asm'	;1 sample/DMA
	include	'modules/addklim.asm'
	include	'modules/filter2.asm'
	include	'modules/delayl.asm'
	include	'modules/delayr.asm'
	include	'modules/sati.asm'
	;;;
Start:
	CLR	A
	CLR	B
	
	; Init Pointers to the Host Receive Buffer
	MOVE	#DSP_DATA_LEN-1,M_HostDataIn
	MOVE	#>HostDataInput,R_HostDataIn

	;Init DELAY
	;DelayPointer (L+R)
	MOVE	#>ModuleParamX_DelayL,R1
	MOVE	#(MODULE_PARAM_SIZE*2),R5
	REP	R5
		MOVE	A,X:(R1)+
	;DelayBuffer (L+R)
	MOVE	#>DelayBufferL,R1
	MOVE	#(2*DELAY_BUFFER_SIZE),R5
	REP	R5
		MOVE	A,X:(R1)+
	
	;Clear intermediate buffers
	;L
	MOVE	#>IN_STEREO_CHUNK,R1
	MOVE	#>IN_STEREO_CHUNK,R6
	MOVE	#(NUM_L_BUFFERS*BUFFER_SIZE),R5
	REP	R5
		MOVE	A,X:(R1)+	A,Y:(R6)+
		
	;Clear Stack buffers (module state variables)
	MOVE	#>ModuleParamX,R_X
	MOVE	#(MODULE_PARAM_SIZE*NUM_MODULE_PARAM),R5
	REP	R5
		MOVE	A,X:(R_X)+
		
	;Init interpolation variables
	MOVE	A,Y:GlobalVolume_actual
	MOVE	A,Y:K0Cut_actual
	MOVE	A,Y:K1Cut_actual
	MOVE	A,Y:K2Cut_actual
	MOVE	A,Y:K3Cut_actual
	
	;Init LFO phases (12 LFOs)!!!
	MOVE	#>ModuleParamX_LFO0Res,R1
	MOVE	#>ModuleParamX_LFO0Pan,R2
	MOVE	#$0000F0,X0
	MOVE	#$0000D0,X1
	MOVE	X0,X:(R1+6)
	MOVE	X1,X:(R2+6)
	MOVE	#>ModuleParamX_LFO1Cut,R1
	MOVE	#>ModuleParamX_LFO1Res,R2
	MOVE	#>ModuleParamX_LFO1Pan,R3
	MOVE	#$0000B0,X0
	MOVE	#$000090,X1
	MOVE	#$000070,Y0
	MOVE	X0,X:(R1+6)
	MOVE	X1,X:(R2+6)
	MOVE	Y0,X:(R3+6)
	MOVE	#>ModuleParamX_LFO2Cut,R1
	MOVE	#>ModuleParamX_LFO2Res,R2
	MOVE	#>ModuleParamX_LFO2Pan,R3
	MOVE	#$000050,X0
	MOVE	#$000030,X1
	MOVE	#$000010,Y0
	MOVE	X0,X:(R1+6)
	MOVE	X1,X:(R2+6)
	MOVE	Y0,X:(R3+6)
	MOVE	#>ModuleParamX_LFO3Cut,R1
	MOVE	#>ModuleParamX_LFO3Res,R2
	MOVE	#>ModuleParamX_LFO3Pan,R3
	MOVE	#$000040,X0
	MOVE	#$000080,X1
	MOVE	#$0000C0,Y0
	MOVE	X0,X:(R1+6)
	MOVE	X1,X:(R2+6)
	MOVE	Y0,X:(R3+6)

	; Enable HOST Receive and Command interrupts
	BSET	#HCR_HRIE,X:<<HCR	; Enable Host Receive Interrupts

	;ENABLE INTERRUPTS
	ANDI	#<$FC,MR

	;Wait for START flag (flag0) from COLDFIRE
	DO FOREVER,_init
		BRSET	#HSR_HF0,X:<<HSR,_init
_init:
	BSR	ConfigureAudioDMA
	
MainLoop:
	include	'getvar.asm'

;/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-

	;MODULE: IN
	MOVE	#>ModuleParamX,R_X
	MOVE	Y:ActiveBufferADC,X0
	MOVE	#>IN_STEREO_CHUNK,X1
	MOVE	X0,X:(R_X)
	MOVE	X1,X:(R_X+1)
	BSR	module_in
	;END MODULE
	
		include	'line0.asm'
		include	'line1.asm'
		include	'line2.asm'
		include	'line3.asm'

		include	'mixing.asm'

		include 'delaying.asm'

		include	'mix.asm'
		
	;MODULE: OUT
		;Making interpolation
		;actual+=(global-actual)*inc
		MOVE	Y:GlobalVolume_actual,X0
		MOVE	Y:Ctrl_MasterVolume,A
		SUB	X0,A
		TFR	X0,B	A,Y1	#VOLUME_INC,X0
		MACR	X0,Y1,B
	MOVE	#>ModuleParamX,R_X
	MOVE	#>OUT_STEREO_CHUNK,X0
	MOVE	Y:ActiveBufferDAC,X1
	MOVE	X0,X:(R_X)
	MOVE	X1,X:(R_X+1)
	MOVE	B,X:(R_X+2)
	MOVE			B,Y:GlobalVolume_actual
	BSR	module_out
	;END MODULE

;/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-/*-
	BSR	ChangeActiveBuffer
	BRA	MainLoop

	end	Start