;****************************************************************
;  EECS 452 Digital Signal Processing Design Laboratory         *
;  				                      *
;  File : flange.asm                                            *
;  Author : Kevin Ziemer & Kurt Metzger                         *
;                                                               *
;  This file adds flange to an audio signal, controlling the    *
;  frequency, mix, and variance of the flange with knobs        *
;****************************************************************
 
         page    132,60
         opt      mex
         
         ; Allocate the Y memory between top of on-chip memory
         ; and the bottom of the off chip memory so that it
         ; won't accidentally be used.
                  SECTION    X_FILL 
GAP_BOT  EQU    $800        
         org    x:GAP_BOT
x_fill   ds     $10000-GAP_BOT
         ENDSEC

         SECTION    Y_FILL 
GAP_BOT  EQU    $800        
         org    y:GAP_BOT
y_fill   ds     $10000-GAP_BOT
         ENDSEC


         ; The RTFFT section contains the main code

         SECTION    RTFFT

         nolist
         include  'ioequ.asm'       ; define I/0 equates
         include  'intequ.asm'      ; define interrupt equates
         include  'v_init.asm'      ; read interrupt vector initialization
         include  'ada_equ.asm'     ; read CODEC support definitions
         list

;****************************************************************************
; the following EQUates will define the operatonal parameters
;   of the codec.  Please refer to the ADA_EQU.ASM source file
;   for a description of the parameters selections available.  The
;   variables defined by the EQUates are sent to the  codec via 
;   the transmit buffer, TX_BUFF.
;
;   Since the parameters are defined in ADA_EQU.ASM, these lines must
;   follow the include statement.
;****************************************************************************

TONE_OUTPUT     EQU     HEADPHONE_EN+LINEOUT_EN+(0*LEFT_ATTN)+(0*RIGHT_ATTN)   
TONE_INPUT      EQU     MIC_IN_SELECT+(15*MONITOR_ATTN)




; Declare relative storage prior to defining absolute storage

        org    x:               ; first assign x memory

stack    ds    40       ; allocate the stack

IR_FLAGS        ds      1       ; interrupt flags
IRA             EQU     0       ; SW 2 pressed
IRD             EQU     1       ; SW 3 pressed
B_SIZE         EQU     512     ; Define the size of the FFT here!!!!

LASTTIME        ds      1	; these are for knob support
ENCOUNT1        ds      1
ENCOUNT2        ds      1
ENCOUNT3        ds      1
ENCOUNT4        ds      1


;---------------------Memory allocation--------------------------

        		org   x:B_SIZE                  
LSIZE   		EQU   B_SIZE+128     ; need extra room for smaller transforms
l_inp   		dsm   LSIZE           ; left channel input sample buffer
l_out   		dsm   LSIZE           ; left channel output value buffer
NVAL			ds	1
FLANGE_SIZE 	equ	2001
DELAY_VARY		equ	50
OFFSET		equ	1000		; offset for normal audio values
N_INC			equ   1000




			org	x:$10000
buff_ptr		equ	*
aud_buff 	  	dsm	FLANGE_SIZE		; = 2001 buffer for sampling
I_N_TABLE		equ	16
			nolist
			include 'Inverse_Desired_Size.asm'
			list

			org 	y:$100
SINTAB		equ 	*		; sine table starts here
SINSIZE		equ	256		; sine table is this big
			nolist
			include 'Sine256.asm'
			list
		



;----------------------------------------------------------------
;   Interrupt vectors

        org P:0

        jmp     START                   ; reset comes here

        org p:I_IRQA                    ; IRQA .. EVM SW2 pressed

        jsr     EVM_SW2                 ; call sw2 interrupt handler

        org p:I_IRQD                    ; IRQD .. EVM SW3 pressed

        jsr     EVM_SW3                 ; call sw3 interrupt handler
	  
	  org p:I_TIM2C				; knob support

        jsr     >TIMER2C   
                                                                
;---------------------Program start address----------------------

        org     p:$100

START
        ori     #3,mr                   ; disable interrupts
        movep   #$040004,x:M_PCTL       ; PLL = 5 x 16.9344Mhz = 84.672MHz

                                        ; set up ext memory wait state counts
        movep   #012422,x:M_BCR         ; load bus control register
                                        ; 00002 area 0 wait state for SRAM
                                        ; 00001 area 1 wait states
                                        ; 001   area 2 wait states
                                        ; 001   area 3 wait states
                                        ; 00001 default wait states
                                        ; 000   state, lock, request
                                        
                                        ; set use of external SRAM
SRAM    equ     $010000                 ; starting address of 32 KW SRAM
        movep   #$010931,x:M_AAR0       ; load address atribute register 0
                                        ; 01   static ram access
                                        ; 0    polarity
                                        ; 0    program space enable
                                        ; 1    x address space enable
                                        ; 1    y address space enable
                                        ; 0    address multiplexing
                                        ; 0    packing enable
                                        ; 1001 Number of address bit to compare
                                        ; 0000 0001 0000  addr to compare
                                        ; described in EVM manual pps 4-7, 4-8
        movep   #$000A05,X:M_IPRC       ; IRQA/IRQD/SSI level 1 interrupts. edge sensitive
        bset    #M_MS,omr

        movec   #0,SP                   ; clear stack pointer
        move    #0,SC                   ; clear stack counter
        movep   #$0,x:M_TCSR0           ; turn LED off

        move    #stack,r6               ; initialize stack pointer
        move    #-1,m6                  ; linear addressing for stack

        movep   #>$1,x:M_HPCR           ; enable GPIO B input to CPU
        movep   #>$1,x:M_HDDR

; --- INIT THE CODEC ---

        jsr     ada_init                ; jump subroutine to initialize the codec
        
        move    #l_inp,x0               ; address of left channel input buffer
        move    #LSIZE,x1               ; size of the buffer
        jsr     get_l_init              ; initialize left input support
        move    #l_out,x0               ; address of left channel output buffer
        move    #LSIZE,x1               ; size of the buffer
        jsr     put_l_init              ; initialize left output support
        
        move    #TONE_OUTPUT,y1         ; headphones, line out, mute spkr, no attn.
        move    y1,x:DA_DATA+2
        move    #TONE_INPUT,y1          ; no input gain, monitor mute
        move    y1,x:DA_DATA+3

;----------------------Main program loop--------------------------
;============================================================================
; Initialize Knobs
;============================================================================

        move    #0,x0
        move    x0,x:ENCOUNT1           ; initialize counters
        move    x0,x:ENCOUNT2
	move	#>15,x1
        move    x1,x:ENCOUNT3
        move    x1,x:ENCOUNT4		
        
        movep   x:M_HDR,x0              ; read switch states
        move    x0,x:LASTTIME           ; initialize LASTTIME       
        movep   #200000,x:M_TCPR2       ; set clock tic rate
        movep   #0,x:M_TLR2             ; start counting from 0
        movep   #$205,x:M_TCSR2
	  
	  movep	x:M_IPRP,a1			
	  move	#>$100,x0
	  or		x0,a
	  movep	a,x:M_IPRP			; Sets the appropriate Inturrupts
 

        andi    #$FC,mr                 ; enable interrupts

;============================================================================

start



	move	#aud_buff,r1		; r1 will be used for audio input
	move 	#FLANGE_SIZE-1,m1		; allow for modular addressing

	move	r1,r2				; R2 will be used for normal audio output
	move	#>OFFSET,n2			; offset for audio out
	move	m1,m2				; allow for modular addressing

	move 	r1,r3				; R3 will be used for addressing flange out
	move	m1,m3				; allow for modular addressing
	
	move	#5,r5				; R5 will be CTR
	
	move	#SINTAB,r0			; R0 will be i
	move	#SINSIZE-1,m0		; allow for modular addressing


loop
	jsr	get_l_val
	move	a,x:(r1)+			; store first audio value
	
;-----------------------------------------------------------------------
	move 	x:ENCOUNT2,x1

	brclr   #0,x1,fbitclear      
      movep   #>$002800,x:M_TCSR0     ; turn LED on
      jmp     fnotclear
fbitclear
        movep   #>$000800,x:M_TCSR0     ; turn LED on
fnotclear

	move	#I_N_TABLE,r7
	move	x1,n7
	move	x:(r7+n7),y1		; y1 = 1/N

	move	#>N_INC,y0
	mpy	y0,x1,a
	asl	#24,a,a
	add	#>N_INC,a
	move	a,r7				; R7 = N
;------------------------------------------------------------------------
	move	y:(r0)+,y0			; y0 contains first sine value (A)
	move	y:(r0)-,x0			; x0 contains second sine value (B)

	move	r5,x1				; x1 = CTR
	mpy	x1,y1,a			; a0 = (CTR/N) [also offset by 1 due to multiply]
	asl	#23,a,a			; a1 = (CTR/N)
	move	a,y1				; y1 = (CTR/N)	
	move	x0,a				; a1 = B
	sub	y0,a				; a1 = (B-A)
check
	move	a,x0				; x0 = (B-A)

	mpy	x0,y1,a			; a1 = (CTR/N)*(B-A)
	add	y0,a				; a1 = A + (CTR/N)*(B-A)
	move	a,x0				; x0 = A + (CTR/N)*(B-A)
;	move	x:(r7)+,x0		; support for 6000 value sine table
;============================================================================
knob_support
	move	x:ENCOUNT1,x1
	mpy	#>DELAY_VARY,x1,a
	asl	#23,a,a
	move	a,y0
	brclr   #0,x1,bitclear      
 ;     movep   #>$002800,x:M_TCSR0     ; turn LED on
      jmp     notclear
bitclear
 ;       movep   #>$000800,x:M_TCSR0     ; turn LED on
notclear
;============================================================================

	mpy	y0,x0,a			; a1 = (interpolated) sine value * how far back and forth flange values are read
	add	#>OFFSET,a			; a1 = base delay + flange delay
	move	a,n3				; n3 now contains proper flange offset.
	
	move	r5,a				; a1 = CTR
	add	#>256,a			; a1 = CTR + 256
	move	a,x1				; x1 = CTR + 256
	move	x1,r5				; r5 (CTR) = CTR + 256
	move	r7,y0
	sub	y0,a				; a1 = CTR - N
	sub	#>1,a				; a1 = CTR - N - 1
	move	a,x1				; x1 = CTR - N - 1
	BRSET	#23,x1,N_greater		; Branch if N >= CTR to greater

;************************************************************************************	
; The following only runs when CTR >= N
;************************************************************************************	
	move	r5,a				; a1 = CTR
	sub	y0,a		; a1 = CTR - N
	move	a,r5				; r5 (CTR) = CTR - N
	move	#>1,n0			; These two lines incriment I
	move	(r0)+n0		; 
;************************************************************************************

N_greater
	move	x:(r2+n2),x0		; x0 = normal audio
	move	(r2)+				; incriments r2
	move	x:(r3+n3),y0		; y0 = flange audio
	move	(r3)+				; incriments r3

	move	x:ENCOUNT3,y1		; ENCOUNT3 will be for normal audio
	move	#$7f347,x1			; x1 ~ 1/16
	mpy	y1,x1,a			; a0 = desired gain fraction
	and	#0,a				
	asl	#23,a,a				; a1 = desired gain fraction
	move	a,y1				; y1 = desired gain fraction
	mpy	y1,x0,a 
	move	a,x0				; x0 = normal audio w/ gain	

	move	x:ENCOUNT4,x1		; ENCOUNT4 will be for flange audio
	move	#$7f347,y1
	mpy	y1,x1,a
	and	#0,a
	asl	#23,a,a
	move	a,x1
	mpy	y0,x1,a			; add flange
	
	add	x0,a
	


	move	a,x0				; put audio out onto x0 for output
      jsr   put_l_val			; output audio
	jmp	loop				; do it all over
	





















;============================================================================
;============================================================================
; Knob Support
;============================================================================
TIMER2C                                 ; timer 2 compare interrupt support
        move    x0,x:(r6)+
        move    x1,x:(r6)+
        move    a0,x:(r6)+
        move    a1,x:(r6)+
        move    a2,x:(r6)+
	  move    m0,x:(r6)+
	  move    n0,x:(r6)+
        move    r0,x:(r6)+

        movep   x:M_HDR,x0              ; get switches this time
        move    x:LASTTIME,a            ; get switches last time
        eor     x0,a1                   ; look for changes
        and     #>$5500,a               ; retain A bits only
        tst     a                       ; 0 = no changes
        jeq     testend
        move    a,x1                    ; save changes
        brclr   #8,a1,set_limits_1           ; branch if sw1 not change
        move    x:ENCOUNT1,r0
		  move	#$FFFF,m0
        move    x0,a1                   ; get switch states
        lsl     a                       ; shift A into B position
        eor     x0,a1                   ; checking direction
        brset   #9,a1,sw1up
        move    (r0)-
        move    r0,x:ENCOUNT1
        jmp     set_limits_1
sw1up   move    (r0)+
        move    r0,x:ENCOUNT1    

;-------------------------------------------------------------------
; This following section successfully sets the limits of the nobs to be
; 0 <= knob <= 15
set_limits_1
	move	x:ENCOUNT1,r0
	brclr	#23,r0,pos_cot_1
	move	#0,r0
	move	r0,x:ENCOUNT1
	jmp	within_lim1
pos_cot_1
	brclr	#4,r0,within_lim1
	move	#>15,r0
	move	r0,x:ENCOUNT1
within_lim1
;-------------------------------------------------------------------
   
testsw2
        move    x1,a                    ; get changes back
        brclr   #10,a1,testsw3
        move    x:ENCOUNT2,r0
	  move	#$FFFF,m0
        move    x0,a1                   ; get switch states
        lsl     a                       ; shift A into B position
        eor     x0,a1                   ; checking direction
        brset   #11,a1,sw2up
        move    (r0)-
        move    r0,x:ENCOUNT2
        jmp     set_limits_2
sw2up   move    (r0)+
        move    r0,x:ENCOUNT2

;-------------------------------------------------------------------
; This following section successfully sets the limits of the nobs to be
; 0 <= knob <= 15
set_limits_2
	move	x:ENCOUNT2,r0
	brclr	#23,r0,pos_cot_2
	move	#0,r0
	move	r0,x:ENCOUNT2
	jmp	within_lim2
pos_cot_2
	brclr	#4,r0,within_lim2
	move	#>15,r0
	move	r0,x:ENCOUNT2
within_lim2
;-------------------------------------------------------------------

testsw3
        move    x1,a                    ; get changes back
        brclr   #12,a1,testsw4
        move    x:ENCOUNT3,r0
	  move	#$FFFF,m0
        move    x0,a1                   ; get switch states
        lsl     a                       ; shift A into B position
        eor     x0,a1                   ; checking direction
        brset   #13,a1,sw3up
        move    (r0)-
        move    r0,x:ENCOUNT3
        jmp     set_limits_3
sw3up   move    (r0)+
        move    r0,x:ENCOUNT3

;-------------------------------------------------------------------
; This following section successfully sets the limits of the nobs to be
; 0 <= knob <= 15
set_limits_3
	move	x:ENCOUNT3,r0
	brclr	#23,r0,pos_cot_3
	move	#0,r0
	move	r0,x:ENCOUNT3
	jmp	within_lim3
pos_cot_3
	brclr	#4,r0,within_lim3
	move	#>15,r0
	move	r0,x:ENCOUNT3
within_lim3
;-------------------------------------------------------------------


testsw4
        move    x1,a                    ; get changes back
        brclr   #14,a1,testend
        move    x:ENCOUNT4,r0
	  move	#$FFFF,m0
        move    x0,a1                   ; get switch states
        lsl     a                       ; shift A into B position
        eor     x0,a1                   ; checking direction
        brset   #15,a1,sw4up
        move    (r0)-
        move    r0,x:ENCOUNT4
        jmp     set_limits_4
sw4up   move    (r0)+
        move    r0,x:ENCOUNT4  

;-------------------------------------------------------------------
; This following section successfully sets the limits of the nobs to be
; 0 <= knob <= 15
set_limits_4
	move	x:ENCOUNT4,r0
	brclr	#23,r0,pos_cot_4
	move	#0,r0
	move	r0,x:ENCOUNT4
	jmp	within_lim4
pos_cot_4
	brclr	#4,r0,within_lim4
	move	#>15,r0
	move	r0,x:ENCOUNT4
within_lim4
;-------------------------------------------------------------------
     
testend
        move    x0,x:LASTTIME
	  move    x:-(r6),r0
	  move    x:-(r6),n0
	  move    x:-(r6),m0
        move    x:-(r6),a2
        move    x:-(r6),a1
        move    x:-(r6),a0
        move    x:-(r6),x1
        move    x:-(r6),x0
        rti

; EVM switches 2 and 3 interrupt support

EVM_SW2                                 ; switch 2 pressed interrupt support
        bset    #IRA,x:>IR_FLAGS
        rti

EVM_SW3
        bset    #IRD,x:>IR_FLAGS        ; switch 3 pressed interrupt support
        rti


        ENDSEC
	
