; program: reverb-16b.asm
; UID = 000009 - unique id to eliminate conflicts between variables
; 16b address space (.7s delay time)
; mono data

; program overview
;
; data is written to the memory as it arrives from the codec.  data is
; read in from the memory and muliplied by a fixed constant.  this is
; done for 10 delay times with different constants, and the result is
; accumulated and played out.  data is taken in on the left channel, and
; played out on both left and right.

; reverb constants
; tap gains should sum to approximately 1 to keep the data normalized
; program assumes signed gain constants
.equ tap1 = $3f45 ; tap1 gain constant
.equ tap2 = $cab8 ; tap2 gain constant
.equ tap3 = $2fe3 ; tap3 gain constant
.equ tap4 = $d056 ; tap4 gain constant
.equ tap5 = $1345 ; tap5 gain constant
.equ tap6 = $ea48 ; tap6 gain constant
.equ tap7 = $1be3 ; tap7 gain constant
.equ tap8 = $e056 ; tap8 gain constant
.equ tap9 = $0c45 ; tap9 gain constant
.equ tap10 = $0a48 ; tap10 gain constant

; delay times are in samples (value/44.1kHz = delay time in ms)
.equ tap_delay1 = $0146 ; tap1 delay time
.equ tap_delay2 = $0205 ; tap2 delay time
.equ tap_delay3 = $032f ; tap3 delay time
.equ tap_delay4 = $04fe ; tap4 delay time
.equ tap_delay5 = $0526 ; tap5 delay time
.equ tap_delay6 = $06cc ; tap6 delay time
.equ tap_delay7 = $0a23 ; tap7 delay time
.equ tap_delay8 = $1deb ; tap8 delay time
.equ tap_delay9 = $2f0b ; tap9 delay time
.equ tap_delay10 = $395c ; tap10 delay time

; register usage - may be redefined in other sections
;
; r0  multiply result lsb
; r1  multiply result msb
; r2  accumulate lsb
; r3  accumulate mlb
; r4  right/left lsb out/accumulate mhb
; r5  right/left msb out/accumulate msb
; r6  left lsb in
; r7  left msb in
; r8  right lsb in
; r9  right msb in
; r10 
; r11 
; r12 
; r13 
; r14 
; r15 switch sample counter
; r16 temporary swap register
; r17 temporary swap register
; r18 tap multiply constant lsb
; r19 tap multiply constant msb
; r20 audio data multiply lsb
; r21 audio data multiply msb
; r22 write address third byte/null register
; r23 read address third byte
; r24 write address lsb
; r25 write address msb
; r26 
; r27 
; r28 read address lsb
; r29 read address msb
; r30 jump location for interrupt lsb
; r31 jump location for interrupt msb

; program starts here
; initiate data transfer to codec
sbi portb,portb0 ; toggle slave select pin
out spdr,r5 ; send out left channel msb
cbi portb,portb0
adiw r25:r24,$01 ; increment write address
ldi r23,$04 ; set up high byte read register
ldi r22,$00 ; set up high byte write register

wait1_000009: ; check if byte has been sent

in r17,spsr
sbrs r17,spif
rjmp wait1_000009
in r7,spdr ; recieve in left channel msb
out spdr,r4 ; send out left channel lsb
out portg,r23 ; pull ce low, we high, and set high bits of register
;get delayed data
movw r29:r28,r25:r24 ; move write register to read register
subi r28,low(tap_delay1) ; remove delay time
sbci r29,high(tap_delay1)
out portd,r28 ; set address
sts porth,r29
nop ; wait input latch time of 2 clock cycles
nop ; wait input latch time of 2 clock cycles
in r20,pina ; get data
in r21,pinc ; get data

wait2_000009: ; check if byte has been sent

in r17,spsr
sbrs r17,spif
rjmp wait2_000009
in r6,spdr ; recieve in left channel lsb
out spdr,r5 ; send out right channel msb
;write left channel data to sram
out portd,r24 ; set address
sts porth,r25
out portg,r22 ; pull ce low,we low,and set high bits of address
ldi r17,$ff
out ddra,r17 ; set porta as output for data write
out ddrc,r17 ; set portc as output for data write
out porta,r6 ; set data
out portc,r7
ldi r17,$00 ; prepare for setting ports a,c as input
sbi portg,portg2 ; pull we high to write
out ddra,r17 ; set porta as input for data lines
out ddrc,r17 ; set portc as input for data lines

wait3_000009: ; check if byte has been sent

in r17,spsr
sbrs r17,spif
rjmp wait3_000009
in r9,spdr ; recieve in right channel msb
out spdr,r4 ; send out right channel lsb
;setup delay constant
ldi r18,low(tap1)
ldi r19,high(tap1)
;clear accumulation registers
clr r5
clr r4
clr r3
clr r2

wait4_000009: ; check if byte has been sent

in r17,spsr
sbrs r17,spif
rjmp wait4_000009
in r8,spdr ; recieve in left channel lsb

;multiply and accumulate - r5:r4:r3:r2
muls r19,r21 ; (signed)ah * (signed)bh
add	r4,r0
adc	r5,r1
mul	r18,r20 ; al * bl
add	r2,r0
adc	r3,r1
adc	r4,r22 ; r22 cleared earlier
adc	r5,r22
mulsu r19,r20 ; (signed)ah * bl
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22
mulsu r21,r18 ; (signed)bh * al
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22

;get delayed data
movw r29:r28,r25:r24 ; move write register to read register
subi r28,low(tap_delay2) ; remove delay time
sbci r29,high(tap_delay2)
out portd,r28 ; set address
sts porth,r29
nop ; wait input latch time of 2 clock cycles
nop ; wait input latch time of 2 clock cycles
in r20,pina ; get data
in r21,pinc ; get data

;setup delay constant
ldi r18,low(tap2)
ldi r19,high(tap2)

;multiply and accumulate - r5:r4:r3:r2
muls r19,r21 ; (signed)ah * (signed)bh
add	r4,r0
adc	r5,r1
mul	r18,r20 ; al * bl
add	r2,r0
adc	r3,r1
adc	r4,r22
adc	r5,r22
mulsu r19,r20 ; (signed)ah * bl
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22
mulsu r21,r18 ; (signed)bh * al
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22

;get delayed data
movw r29:r28,r25:r24 ; move write register to read register
subi r28,low(tap_delay3) ; remove delay time
sbci r29,high(tap_delay3)
out portd,r28 ; set address
sts porth,r29
nop ; wait input latch time of 2 clock cycles
nop ; wait input latch time of 2 clock cycles
in r20,pina ; get data
in r21,pinc ; get data

;setup delay constant
ldi r18,low(tap3)
ldi r19,high(tap3)

;multiply and accumulate - r5:r4:r3:r2
muls r19,r21 ; (signed)ah * (signed)bh
add	r4,r0
adc	r5,r1
mul	r18,r20 ; al * bl
add	r2,r0
adc	r3,r1
adc	r4,r22
adc	r5,r22
mulsu r19,r20 ; (signed)ah * bl
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22
mulsu r21,r18 ; (signed)bh * al
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22

;get delayed data
movw r29:r28,r25:r24 ; move write register to read register
subi r28,low(tap_delay4) ; remove delay time
sbci r29,high(tap_delay4)
out portd,r28 ; set address
sts porth,r29
nop ; wait input latch time of 2 clock cycles
nop ; wait input latch time of 2 clock cycles
in r20,pina ; get data
in r21,pinc ; get data

;setup delay constant
ldi r18,low(tap4)
ldi r19,high(tap4)

;multiply and accumulate - r5:r4:r3:r2
muls r19,r21 ; (signed)ah * (signed)bh
add	r4,r0
adc	r5,r1
mul	r18,r20 ; al * bl
add	r2,r0
adc	r3,r1
adc	r4,r22
adc	r5,r22
mulsu r19,r20 ; (signed)ah * bl
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22
mulsu r21,r18 ; (signed)bh * al
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22

;get delayed data
movw r29:r28,r25:r24 ; move write register to read register
subi r28,low(tap_delay5) ; remove delay time
sbci r29,high(tap_delay5)
out portd,r28 ; set address
sts porth,r29
nop ; wait input latch time of 2 clock cycles
nop ; wait input latch time of 2 clock cycles
in r20,pina ; get data
in r21,pinc ; get data

;setup delay constant
ldi r18,low(tap5)
ldi r19,high(tap5)

;multiply and accumulate - r5:r4:r3:r2
muls r19,r21 ; (signed)ah * (signed)bh
add	r4,r0
adc	r5,r1
mul	r18,r20 ; al * bl
add	r2,r0
adc	r3,r1
adc	r4,r22
adc	r5,r22
mulsu r19,r20 ; (signed)ah * bl
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22
mulsu r21,r18 ; (signed)bh * al
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22

;get delayed data
movw r29:r28,r25:r24 ; move write register to read register
subi r28,low(tap_delay6) ; remove delay time
sbci r29,high(tap_delay6)
out portd,r28 ; set address
sts porth,r29
nop ; wait input latch time of 2 clock cycles
nop ; wait input latch time of 2 clock cycles
in r20,pina ; get data
in r21,pinc ; get data

;setup delay constant
ldi r18,low(tap6)
ldi r19,high(tap6)

;multiply and accumulate - r5:r4:r3:r2
muls r19,r21 ; (signed)ah * (signed)bh
add	r4,r0
adc	r5,r1
mul	r18,r20 ; al * bl
add	r2,r0
adc	r3,r1
adc	r4,r22
adc	r5,r22
mulsu r19,r20 ; (signed)ah * bl
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22
mulsu r21,r18 ; (signed)bh * al
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22

;get delayed data
movw r29:r28,r25:r24 ; move write register to read register
subi r28,low(tap_delay7) ; remove delay time
sbci r29,high(tap_delay7)
out portd,r28 ; set address
sts porth,r29
nop ; wait input latch time of 2 clock cycles
nop ; wait input latch time of 2 clock cycles
in r20,pina ; get data
in r21,pinc ; get data

;setup delay constant
ldi r18,low(tap7)
ldi r19,high(tap7)

;multiply and accumulate - r5:r4:r3:r2
muls r19,r21 ; (signed)ah * (signed)bh
add	r4,r0
adc	r5,r1
mul	r18,r20 ; al * bl
add	r2,r0
adc	r3,r1
adc	r4,r22
adc	r5,r22
mulsu r19,r20 ; (signed)ah * bl
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22
mulsu r21,r18 ; (signed)bh * al
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22

;get delayed data
movw r29:r28,r25:r24 ; move write register to read register
subi r28,low(tap_delay8) ; remove delay time
sbci r29,high(tap_delay8)
out portd,r28 ; set address
sts porth,r29
nop ; wait input latch time of 2 clock cycles
nop ; wait input latch time of 2 clock cycles
in r20,pina ; get data
in r21,pinc ; get data

;setup delay constant
ldi r18,low(tap8)
ldi r19,high(tap8)

;multiply and accumulate - r5:r4:r3:r2
muls r19,r21 ; (signed)ah * (signed)bh
add	r4,r0
adc	r5,r1
mul	r18,r20 ; al * bl
add	r2,r0
adc	r3,r1
adc	r4,r22
adc	r5,r22
mulsu r19,r20 ; (signed)ah * bl
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22
mulsu r21,r18 ; (signed)bh * al
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22

;get delayed data
movw r29:r28,r25:r24 ; move write register to read register
subi r28,low(tap_delay9) ; remove delay time
sbci r29,high(tap_delay9)
out portd,r28 ; set address
sts porth,r29
nop ; wait input latch time of 2 clock cycles
nop ; wait input latch time of 2 clock cycles
in r20,pina ; get data
in r21,pinc ; get data

;setup delay constant
ldi r18,low(tap9)
ldi r19,high(tap9)

;multiply and accumulate - r5:r4:r3:r2
muls r19,r21 ; (signed)ah * (signed)bh
add	r4,r0
adc	r5,r1
mul	r18,r20 ; al * bl
add	r2,r0
adc	r3,r1
adc	r4,r22
adc	r5,r22
mulsu r19,r20 ; (signed)ah * bl
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22
mulsu r21,r18 ; (signed)bh * al
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22

;get delayed data
movw r29:r28,r25:r24 ; move write register to read register
subi r28,low(tap_delay10) ; remove delay time
sbci r29,high(tap_delay10)
out portd,r28 ; set address
sts porth,r29
nop ; wait input latch time of 2 clock cycles
nop ; wait input latch time of 2 clock cycles
in r20,pina ; get data
in r21,pinc ; get data

;setup delay constant
ldi r18,low(tap10)
ldi r19,high(tap10)

;multiply and accumulate - r5:r4:r3:r2
muls r19,r21 ; (signed)ah * (signed)bh
add	r4,r0
adc	r5,r1
mul	r18,r20 ; al * bl
add	r2,r0
adc	r3,r1
adc	r4,r22
adc	r5,r22
mulsu r19,r20 ; (signed)ah * bl
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22
mulsu r21,r18 ; (signed)bh * al
sbc	r5,r22
add	r3,r0
adc	r4,r1
adc	r5,r22

dec r15
brne done_000009
lds r31,pinj ; get switch data
andi r31,$78 ; mask off rotary switch
ldi r17,$02
lsr r31
lsr r31
add r31,r17 ; adjust switch position to program memory location

done_000009:

reti

