welcome: please sign in
location: Diff for "Chorus"
Differences between revisions 1 and 2
Revision 1 as of 2010-08-13 19:06:48
Size: 18
Editor: guest
Comment:
Revision 2 as of 2010-08-13 19:09:19
Size: 13256
Editor: guest
Comment:
Deletions are marked like this. Additions are marked like this.
Line 2: Line 2:

[[attachment:chorus_sine.asm|chorus_sine.asm]]

----

{{{#!highlight nasm
; program: chorus-16b-sine.asm
; UID = 000042 - unique id to eliminate conflicts between variables
; 16b address space
; mono data in on left channel, identical stereo out
; pot (MOD1) controls lfo frequency
; rotary encoder (MOD2) controls lfo depth

; program overview
;
; data is read in from the codec and stored to sram. this data is then read
; back out at a time varying delay. the average delay time is a fixed number
; set at the beginning of the code, and is varied with a sinusoidal lfo. the
; lfo is generated via interpolating a 16b 512s half sinewave lookup table.
; a 32b number is used to index into this lookup table, to allow for very
; slow lfo rates. this lfo is then multiplied by a 16b amplitude signal,
; and the data is fetched from the sram, at that location. the adc is
; oversampled 256 times and deadbanded before updating the lfo rate. the
; rotary encoder is used to increment the amplitude of the lfo. there are
; two voices, each swept with the same lfo signal, but in opposite
; directions. the average delay for each is independent.

; constants
;
.equ delay1_000042 = $0321 ; chorus average delay time for voice 1
; (1/44.1 ms per unit), min value $0100
.equ delay2_000042 = $0444 ; chorus average delay time for voice 2
; (1/44.1 ms per unit), min value $0100

; register usage - may be redefined in other sections
;
; r0 multiply result lsb
; r1 multiply result msb
; r2 accumulation lsb
; r3 accumulation mlb
; r4 right/left lsb out/accumulation mhb
; r5 right/left msb out/accumulation msb
; r6 left lsb in
; r7 left msb in
; r8 adc accumulator fractional byte
; r9 adc accumulator lsb
; r10 adc accumulator msb
; r11 rotary encoder counter
; r12 lfo rate lsb
; r13 lfo rate msb
; r14 null register
; r15 switch sample counter
; r16 temporary swap register
; r17 temporary swap register
; r18 sine wave buffer/multiply msb
; r19 sine wave buffer/multiply msb
; r20 multiply swap register
; r21 multiply swap register
; r22 sinetable lookup address lsb
; r23 sinetable lookup address mlb
; r24 write address lsb
; r25 write address msb
; r26 sinetable lookup address mhb
; r27 sinetable lookup address msb
; r28 temporary swap register
; r29 lfo depth
; r30 jump location for interrupt lsb
; r31 jump location for interrupt msb
; t rotary encoder edge detect indicator

; program starts here first time
; intialize registers
ldi r30,$04 ; increment z pointer to new jump location
clr r14 ; clear null register
ldi r29,$0e ; initialize lfo depth
reti ; finish with initialization and wait for next interrupt

; program starts here every time but first
; 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

wait1_000042: ; check if byte has been sent

in r17,spsr
sbrs r17,spif
rjmp wait1_000042
in r7,spdr ; recieve in left channel msb
out spdr,r4 ; send out left channel lsb

wait2_000042: ; check if byte has been sent

in r17,spsr
sbrs r17,spif
rjmp wait2_000042
in r6,spdr ; recieve in left channel lsb
out spdr,r5 ; send out right channel msb

;write left channel datat to sram
out portd,r24 ; set address
sts porth,r25
out portg,r14 ; 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
sbi portg,portg2 ; pull we high to write
out ddra,r14 ; set porta as input for data lines
out ddrc,r14 ; set portc as input for data lines

wait3_000042: ; check if byte has been sent

in r17,spsr
sbrs r17,spif
rjmp wait3_000042
in r17,spdr ; recieve in right channel msb
out spdr,r4 ; send out right channel lsb

wait4_000042: ; check if byte has been sent

in r17,spsr
sbrs r17,spif
rjmp wait4_000042
in r17,spdr ; recieve in right channel lsb

; vco generation
movw r17:r16,r31:r30 ; store z register
;get sample 1
add r22,r12 ; increment sinetable address
adc r23,r13
adc r26,r14 ; r14 is cleared above
adc r27,r14
movw r31:r30,r27:r26 ; move to z register for data fetch
lsl r30 ; adjust pointer for 16b fetch
rol r31
andi r31,$03 ; limit value to 10b (512 samples x 2 bytes)
ori r31,$48 ; set to memory address location where table is stored
lpm r18,z+ ; get sine value lsb, increment z register
lpm r19,z ; get sine value msb
sbrc r27,$01 ; flip sign for half of the values
rjmp interpolate_000042
neg r18
adc r19,r14 ; r14 is cleared above
neg r19

interpolate_000042: ; multiply sample 1 by distance

movw r21:r20,r23:r22 ; get distance from sample 1
com r20 ; invert distance
com r21
mulsu r19,r21 ; (signed)Ah * (unsigned)Bh - multiply high bytes
movw r5:r4,r1:r0 ; store high bytes result for later
mul r18,r20 ; (unsigned)Al * (unsigned)Bl ; multiply low bytes
movw r3:r2,r1:r0 ; store low byets for later
mulsu r19,r20 ; (signed)Ah * (unsigned)Bl - multiply middle bytes
sbc r5,r14 ; r14 is cleared above - subtract sign bit
add r3,r0 ; accumulate result
adc r4,r1
adc r5,r14 ; r14 is cleared above
mul r21,r18 ; (unsigned)Bh * (unsigned)Al - multiply middle bytes
add r3,r0 ; accumulate result
adc r4,r1
adc r5,r14 ; r14 is cleared above

;get sample 2
adiw r27:r26,$01 ; set to next sample
movw r31:r30,r27:r26 ; move to z register for data fetch
lsl r30 ; adjust pointer for 16b fetch
rol r31
andi r31,$03 ; limit value to 10b (512 samples x 2 bytes)
ori r31,$48 ; set to memory address location where table is stored
lpm r18,z+ ; get sine value lsb, increment z register
lpm r19,z ; get sine value msb
sbrc r27,$01 ; flip sign for half of the values
rjmp interpolate1_000042
neg r18
adc r19,r14 ; r14 is cleared above
neg r19

interpolate1_000042: ; multiply sample 2 by distance

sbiw r27:r26,$01 ; reset address
movw r31:r30,r17:r16 ; restore z register
mulsu r19,r23 ; (signed)Ah * (unsigned)Bh - multiply high bytes
add r4,r0 ; accumulate result
adc r5,r1
mul r18,r22 ; (unsigned)Al * (unsigned)Bl ; multiply low bytes
add r2,r0 ; accumulate result
adc r3,r1
adc r4,r14 ; r14 is cleared above
adc r5,r14
mulsu r19,r22 ; (signed)Ah * (unsigned)Bl - multiply middle bytes
sbc r5,r14 ; r14 is cleared above - subtract sign bit
add r3,r0 ; accumulate result
adc r4,r1
adc r5,r14 ; r14 is cleared above
mul r23,r18 ; (unsigned)Bh * (unsigned)Al - multiply middle bytes
add r3,r0 ; accumulate result
adc r4,r1
adc r5,r14 ; r14 is cleared above

;set lfo depth
movw r19:r18,r5:r4 ; move lfo signal to multiply register
mov r21,r29 ; move lfo depth to multiply register
mulsu r19,r21 ; (signed)ah * (unsigned)b
movw r5:r4,r1:r0
mul r21,r18 ; (unsigned)b * (unsigned)al
add r4,r1
adc r5,r14 ; r14 is cleared above

;create first voice
;add lfo to delay
mov r2,r4 ; make a backup copy of lfo value for second voice
mov r28,r5
movw r17:r16,r25:r24 ; move current location to read address
subi r16,low(delay1_000042) ; remove delay time
sbci r17,high(delay1_000042)
clr r21 ; prepare to add in lfo time
tst r5 ; check if lfo time is negative
brpl lfoadd_000042 ; add in lfo time if positive
ser r21 ; subtract lfo time if negative

lfoadd_000042: ; add in lfo time

add r16,r5 ; add in lfo time
adc r17,r21

;get left channel sample 1 from sram
out portd,r16 ; set address
sts porth,r17
nop ; wait setup period of two cycles
nop
in r18,pina ; get data
in r19,pinc ; get data

;multiply sample 1 by distance
mov r20,r4 ; get distance from sample 1
com r20 ; invert distance for sample weighting
mulsu r19,r20 ; (signed)ah * b
movw r5:r4,r1:r0
mul r18,r20 ; al * b
add r4,r1
adc r5,r14 ; r14 is cleared above
mov r3,r0

;get left channel sample 2 from sram
subi r16,$ff ; set to next sample
sbci r17,$ff ; done this way because there is no addi or adci
out portd,r16 ; set address
sts porth,r17
nop ; wait setup period of two cycles
nop
in r18,pina ; get data
in r19,pinc ; get data

;multiply sample 2 by distance
com r20 ; reset sample 2 distance
mulsu r19,r20 ; (signed)ah * b
add r4,r0 ; accumulate result
adc r5,r1
mul r18,r20 ; al * b
add r3,r0 ; accumulate result
adc r4,r1
adc r5,r14 ; r14 is cleared above
movw r7:r6,r5:r4 ; store voice 1

;create second voice
;add lfo to delay
mov r4,r2 ; restore lfo value for second voice
mov r5,r28
com r4 ; invert lfo for second voice
com r5
movw r17:r16,r25:r24 ; move current location to read address
subi r16,low(delay2_000042) ; remove delay time
sbci r17,high(delay2_000042)
clr r21 ; prepare to add in lfo time
tst r5 ; check if lfo time is negative
brpl lfoadd1_000042 ; add in lfo time if positive
ser r21 ; subtract lfo time if negative

lfoadd1_000042: ; add in lfo time

add r16,r5 ; add in lfo time
adc r17,r21

;get left channel sample 1 from sram
out portd,r16 ; set address
sts porth,r17
nop ; wait setup period of two cycles
nop
in r18,pina ; get data
in r19,pinc ; get data

;multiply sample 1 by distance
mov r20,r4 ; get distance from sample 1
com r20 ; invert distance for sample weighting
mulsu r19,r20 ; (signed)ah * b
movw r5:r4,r1:r0
mul r18,r20 ; al * b
add r4,r1
adc r5,r14 ; r14 is cleared above
mov r3,r0

;get left channel sample 2 from sram
subi r16,$ff ; set to next sample
sbci r17,$ff ; done this way because there is no addi or adci
out portd,r16 ; set address
sts porth,r17
nop ; wait setup period of two cycles
nop
in r18,pina ; get data
in r19,pinc ; get data

;multiply sample 2 by distance
com r20 ; reset sample 2 distance
mulsu r19,r20 ; (signed)ah * b
add r4,r0 ; accumulate result
adc r5,r1
mul r18,r20 ; al * b
add r3,r0 ; accumulate result
adc r4,r1
adc r5,r14 ; r14 is cleared above

;divide both voices by 2 and add them
asr r7 ; divide voice 1 by 2
ror r6
asr r5 ; divide voice 2 by 2
ror r4
add r4,r6 ; add the two voices
adc r5,r7

;check rotary encoder and adjust lfo depth
; although rotary encoder is externally debounced, it is done here again.
; pin1 is sampled on a transition from high to low on pin0. if pin1 is
; high, a left turn occured, if pin1 is low, a right turn occured.
dec r11 ; check if time to sample rotary encoder
brne adcsample_000042 ; continue if not
ldi r17,$40 ; adjust sample frequency to catch all rising edges (1.5ms)
mov r11,r17
lds r17,pinj ; get switch data
sbrs r17,$00 ; check if pin0 is low
rjmp edge_000042 ; check if pin0 was low on previous sample
clt ; clear state register if back high
rjmp adcsample_000042 ; finish off

edge_000042: ; check for falling edge

brts adcsample_000042 ; do nothing if edge was already detected
set ; set t register to indicate edge detected
sbrs r17,$01 ; check if pin1 is high
rjmp increment_000042 ; increment desired delay if right rotation
subi r29,$01 ; decrement lfo depth register
brcc adcsample_000042 ; check if underflow occured
clr r29 ; set lfo depth to min
rjmp adcsample_000042 ; finish off

increment_000042: ; increment desired delay register

ldi r16,$01 ; increment lfo depth register
add r29,r16
brcc adcsample_000042 ; check if overflow occured
ser r29 ; set lfo depth to max

adcsample_000042: ; sample adc for lfo rate

lds r17,adcsra ; get adc control register
sbrs r17,adif ; check if adc conversion is complete
rjmp done_000042 ; skip adc sampling
lds r16,adcl ; get low byte adc value
lds r17,adch ; get high byte adc value
add r8,r16 ; accumulate adc samples
adc r9,r17
adc r10,r14 ; r14 is cleared above
ldi r17,$f7
sts adcsra,r17 ; clear interrupt flag
dec r15 ; countdown adc sample clock
brne done_000042 ; get delay time if its been long enough

deadband_000042: ; set the low value of the delay

lsr r10 ; divide adc value by 16
ror r9
ror r8
lsr r10
ror r9
ror r8
lsr r9 ; r10 is now empty
ror r8
lsr r9
ror r8
movw r17:r16,r9:r8 ; move adc sample to temporary register
ldi r21,$80 ; add in offset of min lfo rate ($0080)
add r16,r21
adc r17,r14 ; r14 is cleared above
sub r16,r12 ; find difference between adc sample and current lfo rate
sbc r17,r13
brsh check_000042 ; check for deadband if positive
neg r16 ; invert if negative
adc r17,r14 ; r14 is cleared above
neg r17

check_000042: ; check if difference is greater than deadband

cpi r16,$10 ; check if difference is less than 1 adc lsb
cpc r17,r14 ; r14 cleared above
brlo empty_000042 ; do nothing if less than 1 adc lsb
movw r13:r12,r9:r8 ; move adc sample to lfo rate register
add r12,r21 ; add in offset of min lfo rate ($0080)
adc r13,r14 ; r14 is cleared above

empty_000042: ; empty accumulation registers and finish off

clr r8 ; empty accumulation registers
clr r9
clr r10

switchsample_000042: ; check rotary switch

lds r16,pinj ; get switch data
andi r16,$78 ; mask off rotary switch
lsr r16 ; adjust switch position to program memory location
lsr r16
ldi r17,$02
add r16,r17
cpse r16,r31 ; check if location has changed
clr r30 ; reset jump register to intial state
mov r31,r16

done_000042:

reti ; return to waiting
}}}

Chorus

chorus_sine.asm


   1 ; program: chorus-16b-sine.asm
   2 ; UID = 000042 - unique id to eliminate conflicts between variables
   3 ; 16b address space
   4 ; mono data in on left channel, identical stereo out
   5 ; pot (MOD1) controls lfo frequency
   6 ; rotary encoder (MOD2) controls lfo depth
   7 
   8 ; program overview
   9 ;
  10 ; data is read in from the codec and stored to sram.  this data is then read
  11 ; back out at a time varying delay.  the average delay time is a fixed number
  12 ; set at the beginning of the code, and is varied with a sinusoidal lfo.  the
  13 ; lfo is generated via interpolating a 16b 512s half sinewave lookup table.
  14 ; a 32b number is used to index into this lookup table, to allow for very
  15 ; slow lfo rates.  this lfo is then multiplied by a 16b amplitude signal,
  16 ; and the data is fetched from the sram, at that location.  the adc is
  17 ; oversampled 256 times and deadbanded before updating the lfo rate.  the
  18 ; rotary encoder is used to increment the amplitude of the lfo.  there are
  19 ; two voices, each swept with the same lfo signal, but in opposite
  20 ; directions. the average delay for each is independent.
  21 
  22 ; constants
  23 ;
  24 .equ delay1_000042 = $0321 ; chorus average delay time for voice 1
  25 ; (1/44.1 ms per unit), min value $0100
  26 .equ delay2_000042 = $0444 ; chorus average delay time for voice 2
  27 ; (1/44.1 ms per unit), min value $0100
  28 
  29 ; register usage - may be redefined in other sections
  30 ;
  31 ; r0  multiply result lsb
  32 ; r1  multiply result msb
  33 ; r2  accumulation lsb
  34 ; r3  accumulation mlb
  35 ; r4  right/left lsb out/accumulation mhb
  36 ; r5  right/left msb out/accumulation msb
  37 ; r6  left lsb in
  38 ; r7  left msb in
  39 ; r8  adc accumulator fractional byte
  40 ; r9  adc accumulator lsb
  41 ; r10 adc accumulator msb
  42 ; r11 rotary encoder counter
  43 ; r12 lfo rate lsb
  44 ; r13 lfo rate msb
  45 ; r14 null register
  46 ; r15 switch sample counter
  47 ; r16 temporary swap register
  48 ; r17 temporary swap register
  49 ; r18 sine wave buffer/multiply msb
  50 ; r19 sine wave buffer/multiply msb
  51 ; r20 multiply swap register
  52 ; r21 multiply swap register
  53 ; r22 sinetable lookup address lsb
  54 ; r23 sinetable lookup address mlb
  55 ; r24 write address lsb
  56 ; r25 write address msb
  57 ; r26 sinetable lookup address mhb
  58 ; r27 sinetable lookup address msb
  59 ; r28 temporary swap register
  60 ; r29 lfo depth
  61 ; r30 jump location for interrupt lsb
  62 ; r31 jump location for interrupt msb
  63 ; t   rotary encoder edge detect indicator
  64 
  65 ; program starts here first time
  66 ; intialize registers
  67 ldi r30,$04 ; increment z pointer to new jump location
  68 clr r14 ; clear null register
  69 ldi r29,$0e ; initialize lfo depth
  70 reti ; finish with initialization and wait for next interrupt
  71 
  72 ; program starts here every time but first
  73 ; initiate data transfer to codec
  74 sbi portb,portb0 ; toggle slave select pin
  75 out spdr,r5 ; send out left channel msb
  76 cbi portb,portb0
  77 
  78 adiw r25:r24,$01 ; increment write address
  79 
  80 wait1_000042: ; check if byte has been sent
  81 
  82 in r17,spsr
  83 sbrs r17,spif
  84 rjmp wait1_000042
  85 in r7,spdr ; recieve in left channel msb
  86 out spdr,r4 ; send out left channel lsb
  87 
  88 wait2_000042: ; check if byte has been sent
  89 
  90 in r17,spsr
  91 sbrs r17,spif
  92 rjmp wait2_000042
  93 in r6,spdr ; recieve in left channel lsb
  94 out spdr,r5 ; send out right channel msb
  95 
  96 ;write left channel datat to sram
  97 out portd,r24 ; set address
  98 sts porth,r25
  99 out portg,r14 ; pull ce low,we low,and set high bits of address
 100 ldi r17,$ff
 101 out ddra,r17 ; set porta as output for data write
 102 out ddrc,r17 ; set portc as output for data write
 103 out porta,r6 ; set data
 104 out portc,r7
 105 sbi portg,portg2 ; pull we high to write
 106 out ddra,r14 ; set porta as input for data lines
 107 out ddrc,r14 ; set portc as input for data lines
 108 
 109 wait3_000042: ; check if byte has been sent
 110 
 111 in r17,spsr
 112 sbrs r17,spif
 113 rjmp wait3_000042
 114 in r17,spdr ; recieve in right channel msb
 115 out spdr,r4 ; send out right channel lsb
 116 
 117 wait4_000042: ; check if byte has been sent
 118 
 119 in r17,spsr
 120 sbrs r17,spif
 121 rjmp wait4_000042
 122 in r17,spdr ; recieve in right channel lsb
 123 
 124 ; vco generation
 125 movw r17:r16,r31:r30 ; store z register
 126 ;get sample 1
 127 add r22,r12 ; increment sinetable address
 128 adc r23,r13
 129 adc r26,r14 ; r14 is cleared above
 130 adc r27,r14
 131 movw r31:r30,r27:r26 ; move to z register for data fetch
 132 lsl r30 ; adjust pointer for 16b fetch
 133 rol r31
 134 andi r31,$03 ; limit value to 10b (512 samples x 2 bytes)
 135 ori r31,$48 ; set to memory address location where table is stored
 136 lpm r18,z+ ; get sine value lsb, increment z register
 137 lpm r19,z ; get sine value msb
 138 sbrc r27,$01 ; flip sign for half of the values
 139 rjmp interpolate_000042
 140 neg r18
 141 adc r19,r14 ; r14 is cleared above
 142 neg r19
 143 
 144 interpolate_000042: ; multiply sample 1 by distance
 145 
 146 movw r21:r20,r23:r22 ; get distance from sample 1
 147 com r20 ; invert distance
 148 com r21
 149 mulsu r19,r21 ; (signed)Ah * (unsigned)Bh - multiply high bytes
 150 movw r5:r4,r1:r0 ; store high bytes result for later
 151 mul     r18,r20 ; (unsigned)Al * (unsigned)Bl ; multiply low bytes
 152 movw r3:r2,r1:r0 ; store low byets for later
 153 mulsu r19,r20 ; (signed)Ah * (unsigned)Bl - multiply middle bytes
 154 sbc     r5,r14 ; r14 is cleared above - subtract sign bit
 155 add     r3,r0 ; accumulate result
 156 adc     r4,r1
 157 adc     r5,r14 ; r14 is cleared above
 158 mul r21,r18 ; (unsigned)Bh * (unsigned)Al - multiply middle bytes
 159 add     r3,r0 ; accumulate result
 160 adc     r4,r1
 161 adc     r5,r14 ; r14 is cleared above
 162 
 163 ;get sample 2
 164 adiw r27:r26,$01 ; set to next sample
 165 movw r31:r30,r27:r26 ; move to z register for data fetch
 166 lsl r30 ; adjust pointer for 16b fetch
 167 rol r31
 168 andi r31,$03 ; limit value to 10b (512 samples x 2 bytes)
 169 ori r31,$48 ; set to memory address location where table is stored
 170 lpm r18,z+ ; get sine value lsb, increment z register
 171 lpm r19,z ; get sine value msb
 172 sbrc r27,$01 ; flip sign for half of the values
 173 rjmp interpolate1_000042
 174 neg r18
 175 adc r19,r14 ; r14 is cleared above
 176 neg r19
 177 
 178 interpolate1_000042: ; multiply sample 2 by distance
 179 
 180 sbiw r27:r26,$01 ; reset address
 181 movw r31:r30,r17:r16 ; restore z register
 182 mulsu r19,r23 ; (signed)Ah * (unsigned)Bh - multiply high bytes
 183 add r4,r0 ; accumulate result
 184 adc r5,r1
 185 mul     r18,r22 ; (unsigned)Al * (unsigned)Bl ; multiply low bytes
 186 add r2,r0 ; accumulate result
 187 adc r3,r1
 188 adc r4,r14 ; r14 is cleared above
 189 adc r5,r14
 190 mulsu r19,r22 ; (signed)Ah * (unsigned)Bl - multiply middle bytes
 191 sbc     r5,r14 ; r14 is cleared above - subtract sign bit
 192 add     r3,r0 ; accumulate result
 193 adc     r4,r1
 194 adc     r5,r14 ; r14 is cleared above
 195 mul r23,r18 ; (unsigned)Bh * (unsigned)Al - multiply middle bytes
 196 add     r3,r0 ; accumulate result
 197 adc     r4,r1
 198 adc     r5,r14 ; r14 is cleared above
 199 
 200 ;set lfo depth
 201 movw r19:r18,r5:r4 ; move lfo signal to multiply register
 202 mov r21,r29 ; move lfo depth to multiply register
 203 mulsu r19,r21 ; (signed)ah * (unsigned)b
 204 movw r5:r4,r1:r0
 205 mul r21,r18 ; (unsigned)b * (unsigned)al
 206 add     r4,r1
 207 adc     r5,r14 ; r14 is cleared above
 208 
 209 ;create first voice
 210 ;add lfo to delay
 211 mov r2,r4 ; make a backup copy of lfo value for second voice
 212 mov r28,r5
 213 movw r17:r16,r25:r24 ; move current location to read address
 214 subi r16,low(delay1_000042) ; remove delay time
 215 sbci r17,high(delay1_000042)
 216 clr r21 ; prepare to add in lfo time
 217 tst r5 ; check if lfo time is negative
 218 brpl lfoadd_000042 ; add in lfo time if positive
 219 ser r21 ; subtract lfo time if negative
 220 
 221 lfoadd_000042: ; add in lfo time
 222 
 223 add r16,r5 ; add in lfo time
 224 adc r17,r21
 225 
 226 ;get left channel sample 1 from sram
 227 out portd,r16 ; set address
 228 sts porth,r17
 229 nop ; wait setup period of two cycles
 230 nop
 231 in r18,pina ; get data
 232 in r19,pinc ; get data
 233 
 234 ;multiply sample 1 by distance
 235 mov r20,r4 ; get distance from sample 1
 236 com r20 ; invert distance for sample weighting
 237 mulsu r19,r20 ; (signed)ah * b
 238 movw r5:r4,r1:r0
 239 mul r18,r20 ; al * b
 240 add r4,r1
 241 adc r5,r14 ; r14 is cleared above
 242 mov r3,r0
 243 
 244 ;get left channel sample 2 from sram
 245 subi r16,$ff ; set to next sample
 246 sbci r17,$ff ; done this way because there is no addi or adci
 247 out portd,r16 ; set address
 248 sts porth,r17
 249 nop ; wait setup period of two cycles
 250 nop
 251 in r18,pina ; get data
 252 in r19,pinc ; get data
 253 
 254 ;multiply sample 2 by distance
 255 com r20 ; reset sample 2 distance
 256 mulsu r19,r20 ; (signed)ah * b
 257 add r4,r0 ; accumulate result
 258 adc r5,r1
 259 mul r18,r20 ; al * b
 260 add r3,r0 ; accumulate result
 261 adc r4,r1
 262 adc r5,r14 ; r14 is cleared above
 263 movw r7:r6,r5:r4 ; store voice 1
 264 
 265 ;create second voice
 266 ;add lfo to delay
 267 mov r4,r2 ; restore lfo value for second voice
 268 mov r5,r28
 269 com r4 ; invert lfo for second voice
 270 com r5
 271 movw r17:r16,r25:r24 ; move current location to read address
 272 subi r16,low(delay2_000042) ; remove delay time
 273 sbci r17,high(delay2_000042)
 274 clr r21 ; prepare to add in lfo time
 275 tst r5 ; check if lfo time is negative
 276 brpl lfoadd1_000042 ; add in lfo time if positive
 277 ser r21 ; subtract lfo time if negative
 278 
 279 lfoadd1_000042: ; add in lfo time
 280 
 281 add r16,r5 ; add in lfo time
 282 adc r17,r21
 283 
 284 ;get left channel sample 1 from sram
 285 out portd,r16 ; set address
 286 sts porth,r17
 287 nop ; wait setup period of two cycles
 288 nop
 289 in r18,pina ; get data
 290 in r19,pinc ; get data
 291 
 292 ;multiply sample 1 by distance
 293 mov r20,r4 ; get distance from sample 1
 294 com r20 ; invert distance for sample weighting
 295 mulsu r19,r20 ; (signed)ah * b
 296 movw r5:r4,r1:r0
 297 mul r18,r20 ; al * b
 298 add r4,r1
 299 adc r5,r14 ; r14 is cleared above
 300 mov r3,r0
 301 
 302 ;get left channel sample 2 from sram
 303 subi r16,$ff ; set to next sample
 304 sbci r17,$ff ; done this way because there is no addi or adci
 305 out portd,r16 ; set address
 306 sts porth,r17
 307 nop ; wait setup period of two cycles
 308 nop
 309 in r18,pina ; get data
 310 in r19,pinc ; get data
 311 
 312 ;multiply sample 2 by distance
 313 com r20 ; reset sample 2 distance
 314 mulsu r19,r20 ; (signed)ah * b
 315 add r4,r0 ; accumulate result
 316 adc r5,r1
 317 mul r18,r20 ; al * b
 318 add r3,r0 ; accumulate result
 319 adc r4,r1
 320 adc r5,r14 ; r14 is cleared above
 321 
 322 ;divide both voices by 2 and add them
 323 asr r7 ; divide voice 1 by 2
 324 ror r6
 325 asr r5 ; divide voice 2 by 2
 326 ror r4
 327 add r4,r6 ; add the two voices
 328 adc r5,r7
 329 
 330 ;check rotary encoder and adjust lfo depth
 331 ; although rotary encoder is externally debounced, it is done here again.
 332 ; pin1 is sampled on a transition from high to low on pin0.  if pin1 is
 333 ; high, a left turn occured, if pin1 is low, a right turn occured.
 334 dec r11 ; check if time to sample rotary encoder
 335 brne adcsample_000042 ; continue if not
 336 ldi r17,$40 ; adjust sample frequency to catch all rising edges (1.5ms)
 337 mov r11,r17
 338 lds r17,pinj ; get switch data
 339 sbrs r17,$00 ; check if pin0 is low
 340 rjmp edge_000042 ; check if pin0 was low on previous sample
 341 clt ;  clear state register if back high
 342 rjmp adcsample_000042 ; finish off
 343 
 344 edge_000042: ; check for falling edge
 345 
 346 brts adcsample_000042 ; do nothing if edge was already detected
 347 set ; set t register to indicate edge detected
 348 sbrs r17,$01 ; check if pin1 is high
 349 rjmp increment_000042 ; increment desired delay if right rotation
 350 subi r29,$01 ; decrement lfo depth register
 351 brcc adcsample_000042 ; check if underflow occured
 352 clr r29 ; set lfo depth to min
 353 rjmp adcsample_000042 ; finish off
 354 
 355 increment_000042: ; increment desired delay register
 356 
 357 ldi r16,$01 ; increment lfo depth register 
 358 add r29,r16
 359 brcc adcsample_000042 ; check if overflow occured
 360 ser r29 ; set lfo depth to max
 361 
 362 adcsample_000042: ; sample adc for lfo rate
 363 
 364 lds r17,adcsra ; get adc control register
 365 sbrs r17,adif ; check if adc conversion is complete
 366 rjmp done_000042 ; skip adc sampling
 367 lds r16,adcl ; get low byte adc value
 368 lds r17,adch ; get high byte adc value
 369 add r8,r16 ; accumulate adc samples
 370 adc r9,r17
 371 adc r10,r14 ; r14 is cleared above
 372 ldi r17,$f7
 373 sts adcsra,r17 ; clear interrupt flag
 374 dec r15 ; countdown adc sample clock
 375 brne done_000042 ; get delay time if its been long enough
 376 
 377 deadband_000042: ; set the low value of the delay
 378 
 379 lsr r10 ; divide adc value by 16
 380 ror r9
 381 ror r8
 382 lsr r10
 383 ror r9
 384 ror r8
 385 lsr r9 ; r10 is now empty
 386 ror r8
 387 lsr r9
 388 ror r8
 389 movw r17:r16,r9:r8 ; move adc sample to temporary register
 390 ldi r21,$80 ; add in offset of min lfo rate ($0080)
 391 add r16,r21
 392 adc r17,r14 ; r14 is cleared above
 393 sub r16,r12 ; find difference between adc sample and current lfo rate
 394 sbc r17,r13
 395 brsh check_000042 ; check for deadband if positive
 396 neg r16 ; invert if negative
 397 adc r17,r14 ; r14 is cleared above
 398 neg r17
 399 
 400 check_000042: ; check if difference is greater than deadband
 401 
 402 cpi r16,$10 ; check if difference is less than 1 adc lsb
 403 cpc r17,r14 ; r14 cleared above
 404 brlo empty_000042 ; do nothing if less than 1 adc lsb
 405 movw r13:r12,r9:r8 ; move adc sample to lfo rate register
 406 add r12,r21 ; add in offset of min lfo rate ($0080)
 407 adc r13,r14 ; r14 is cleared above
 408 
 409 empty_000042: ; empty accumulation registers and finish off
 410 
 411 clr r8 ; empty accumulation registers
 412 clr r9
 413 clr r10
 414 
 415 switchsample_000042: ; check rotary switch
 416 
 417 lds r16,pinj ; get switch data
 418 andi r16,$78 ; mask off rotary switch
 419 lsr r16 ; adjust switch position to program memory location
 420 lsr r16
 421 ldi r17,$02
 422 add r16,r17
 423 cpse r16,r31 ; check if location has changed
 424 clr r30 ; reset jump register to intial state
 425 mov r31,r16
 426 
 427 done_000042:
 428 
 429 reti ; return to waiting
 430 

Chorus (last edited 2010-08-21 02:09:04 by guest)