welcome:
location: Diff for "ReverbMono"
Differences between revisions 4 and 5
 ← Revision 4 as of 2010-08-13 08:22:13 → Size: 13221 Editor: guest Comment: ← Revision 5 as of 2010-08-13 08:22:30 → Size: 13221 Editor: guest Comment: Deletions are marked like this. Additions are marked like this. Line 3: Line 3: This function performs a simple reverb. This means it takes a series of delayed signals, and adds them together at varying amplitudes and polarities. It is in mono, and takes in data on the left channel. It presents the output on both the left and right channels. Niether MOD1 nor MOD2 do anything for this function. This function performs a simple reverb. This means it takes a series of delayed signals, and adds them together at varying amplitudes and polarities. It is in mono, and takes in data on the left channel. It presents the output on both the left and right channels. Neither MOD1 nor MOD2 do anything for this function.

#### Mono Reverb

This function performs a simple reverb. This means it takes a series of delayed signals, and adds them together at varying amplitudes and polarities. It is in mono, and takes in data on the left channel. It presents the output on both the left and right channels. Neither MOD1 nor MOD2 do anything for this function.

Because the 16b signed multiplies take up so much time, you can only get so many in before the next sample arrives. In this case, we can do 10 multiplies (with careful rewriting, this could probably go up to 12 or so). Each of these multiplies also requires a fetch of delayed data (often referred to as a Tap). Both the Tap time and the Tap weighting (multiply value) are defined as constants at the beginning of the code. The sum of these taps should be limited to keep the buffers from overflowing. You can hear the effect of overflowing buffers if you overdrive the input to the reverb.

These multiplies actually implement a multiply-accumulate function (MAC). This means they both multiply the delayed sample and add it to the total sum, at the same time. It takes less time and registers to do it this way. If the Tap weightings were limited to 8b, you could probably get twice as many Taps (but limited resolution in the reverb sounds you could create). The complexity of the reverb sound increases with the number of Taps, but using feedback can also increase complexity, especially if prime Tap spacings are used (this way Taps wont overlap after coming in through the feedback).

```   1 ; program: reverb-16b.asm
2 ; UID = 000009 - unique id to eliminate conflicts between variables
3 ; 16b address space (.7s delay time)
4 ; mono data
5
6 ; program overview
7 ;
8 ; data is written to the memory as it arrives from the codec.  data is
9 ; read in from the memory and muliplied by a fixed constant.  this is
10 ; done for 10 delay times with different constants, and the result is
11 ; accumulated and played out.  data is taken in on the left channel, and
12 ; played out on both left and right.
13
14 ; reverb constants
15 ; tap gains should sum to approximately 1 to keep the data normalized
16 ; program assumes signed gain constants
17 .equ tap1 = \$3f45 ; tap1 gain constant
18 .equ tap2 = \$cab8 ; tap2 gain constant
19 .equ tap3 = \$2fe3 ; tap3 gain constant
20 .equ tap4 = \$d056 ; tap4 gain constant
21 .equ tap5 = \$1345 ; tap5 gain constant
22 .equ tap6 = \$ea48 ; tap6 gain constant
23 .equ tap7 = \$1be3 ; tap7 gain constant
24 .equ tap8 = \$e056 ; tap8 gain constant
25 .equ tap9 = \$0c45 ; tap9 gain constant
26 .equ tap10 = \$0a48 ; tap10 gain constant
27
28 ; delay times are in samples (value/44.1kHz = delay time in ms)
29 .equ tap_delay1 = \$0146 ; tap1 delay time
30 .equ tap_delay2 = \$0205 ; tap2 delay time
31 .equ tap_delay3 = \$032f ; tap3 delay time
32 .equ tap_delay4 = \$04fe ; tap4 delay time
33 .equ tap_delay5 = \$0526 ; tap5 delay time
34 .equ tap_delay6 = \$06cc ; tap6 delay time
35 .equ tap_delay7 = \$0a23 ; tap7 delay time
36 .equ tap_delay8 = \$1deb ; tap8 delay time
37 .equ tap_delay9 = \$2f0b ; tap9 delay time
38 .equ tap_delay10 = \$395c ; tap10 delay time
39
40 ; register usage - may be redefined in other sections
41 ;
42 ; r0  multiply result lsb
43 ; r1  multiply result msb
44 ; r2  accumulate lsb
45 ; r3  accumulate mlb
46 ; r4  right/left lsb out/accumulate mhb
47 ; r5  right/left msb out/accumulate msb
48 ; r6  left lsb in
49 ; r7  left msb in
50 ; r8  right lsb in
51 ; r9  right msb in
52 ; r10
53 ; r11
54 ; r12
55 ; r13
56 ; r14
57 ; r15 switch sample counter
58 ; r16 temporary swap register
59 ; r17 temporary swap register
60 ; r18 tap multiply constant lsb
61 ; r19 tap multiply constant msb
62 ; r20 audio data multiply lsb
63 ; r21 audio data multiply msb
64 ; r22 write address third byte/null register
66 ; r24 write address lsb
67 ; r25 write address msb
68 ; r26
69 ; r27
72 ; r30 jump location for interrupt lsb
73 ; r31 jump location for interrupt msb
74
75 ; program starts here
76 ; initiate data transfer to codec
77 sbi portb,portb0 ; toggle slave select pin
78 out spdr,r5 ; send out left channel msb
79 cbi portb,portb0
81 ldi r23,\$04 ; set up high byte read register
82 ldi r22,\$00 ; set up high byte write register
83
84 wait1_000009: ; check if byte has been sent
85
86 in r17,spsr
87 sbrs r17,spif
88 rjmp wait1_000009
89 in r7,spdr ; recieve in left channel msb
90 out spdr,r4 ; send out left channel lsb
91 out portg,r23 ; pull ce low, we high, and set high bits of register
92 ;get delayed data
93 movw r29:r28,r25:r24 ; move write register to read register
94 subi r28,low(tap_delay1) ; remove delay time
95 sbci r29,high(tap_delay1)
96 out portd,r28 ; set address
97 sts porth,r29
98 nop ; wait input latch time of 2 clock cycles
99 nop ; wait input latch time of 2 clock cycles
100 in r20,pina ; get data
101 in r21,pinc ; get data
102
103 wait2_000009: ; check if byte has been sent
104
105 in r17,spsr
106 sbrs r17,spif
107 rjmp wait2_000009
108 in r6,spdr ; recieve in left channel lsb
109 out spdr,r5 ; send out right channel msb
110 ;write left channel data to sram
111 out portd,r24 ; set address
112 sts porth,r25
113 out portg,r22 ; pull ce low,we low,and set high bits of address
114 ldi r17,\$ff
115 out ddra,r17 ; set porta as output for data write
116 out ddrc,r17 ; set portc as output for data write
117 out porta,r6 ; set data
118 out portc,r7
119 ldi r17,\$00 ; prepare for setting ports a,c as input
120 sbi portg,portg2 ; pull we high to write
121 out ddra,r17 ; set porta as input for data lines
122 out ddrc,r17 ; set portc as input for data lines
123
124 wait3_000009: ; check if byte has been sent
125
126 in r17,spsr
127 sbrs r17,spif
128 rjmp wait3_000009
129 in r9,spdr ; recieve in right channel msb
130 out spdr,r4 ; send out right channel lsb
131 ;setup delay constant
132 ldi r18,low(tap1)
133 ldi r19,high(tap1)
134 ;clear accumulation registers
135 clr r5
136 clr r4
137 clr r3
138 clr r2
139
140 wait4_000009: ; check if byte has been sent
141
142 in r17,spsr
143 sbrs r17,spif
144 rjmp wait4_000009
145 in r8,spdr ; recieve in left channel lsb
146
147 ;multiply and accumulate - r5:r4:r3:r2
148 muls r19,r21 ; (signed)ah * (signed)bh
151 mul     r18,r20 ; al * bl
154 adc     r4,r22 ; r22 cleared earlier
156 mulsu r19,r20 ; (signed)ah * bl
157 sbc     r5,r22
161 mulsu r21,r18 ; (signed)bh * al
162 sbc     r5,r22
166
167 ;get delayed data
168 movw r29:r28,r25:r24 ; move write register to read register
169 subi r28,low(tap_delay2) ; remove delay time
170 sbci r29,high(tap_delay2)
171 out portd,r28 ; set address
172 sts porth,r29
173 nop ; wait input latch time of 2 clock cycles
174 nop ; wait input latch time of 2 clock cycles
175 in r20,pina ; get data
176 in r21,pinc ; get data
177
178 ;setup delay constant
179 ldi r18,low(tap2)
180 ldi r19,high(tap2)
181
182 ;multiply and accumulate - r5:r4:r3:r2
183 muls r19,r21 ; (signed)ah * (signed)bh
186 mul     r18,r20 ; al * bl
191 mulsu r19,r20 ; (signed)ah * bl
192 sbc     r5,r22
196 mulsu r21,r18 ; (signed)bh * al
197 sbc     r5,r22
201
202 ;get delayed data
203 movw r29:r28,r25:r24 ; move write register to read register
204 subi r28,low(tap_delay3) ; remove delay time
205 sbci r29,high(tap_delay3)
206 out portd,r28 ; set address
207 sts porth,r29
208 nop ; wait input latch time of 2 clock cycles
209 nop ; wait input latch time of 2 clock cycles
210 in r20,pina ; get data
211 in r21,pinc ; get data
212
213 ;setup delay constant
214 ldi r18,low(tap3)
215 ldi r19,high(tap3)
216
217 ;multiply and accumulate - r5:r4:r3:r2
218 muls r19,r21 ; (signed)ah * (signed)bh
221 mul     r18,r20 ; al * bl
226 mulsu r19,r20 ; (signed)ah * bl
227 sbc     r5,r22
231 mulsu r21,r18 ; (signed)bh * al
232 sbc     r5,r22
236
237 ;get delayed data
238 movw r29:r28,r25:r24 ; move write register to read register
239 subi r28,low(tap_delay4) ; remove delay time
240 sbci r29,high(tap_delay4)
241 out portd,r28 ; set address
242 sts porth,r29
243 nop ; wait input latch time of 2 clock cycles
244 nop ; wait input latch time of 2 clock cycles
245 in r20,pina ; get data
246 in r21,pinc ; get data
247
248 ;setup delay constant
249 ldi r18,low(tap4)
250 ldi r19,high(tap4)
251
252 ;multiply and accumulate - r5:r4:r3:r2
253 muls r19,r21 ; (signed)ah * (signed)bh
256 mul     r18,r20 ; al * bl
261 mulsu r19,r20 ; (signed)ah * bl
262 sbc     r5,r22
266 mulsu r21,r18 ; (signed)bh * al
267 sbc     r5,r22
271
272 ;get delayed data
273 movw r29:r28,r25:r24 ; move write register to read register
274 subi r28,low(tap_delay5) ; remove delay time
275 sbci r29,high(tap_delay5)
276 out portd,r28 ; set address
277 sts porth,r29
278 nop ; wait input latch time of 2 clock cycles
279 nop ; wait input latch time of 2 clock cycles
280 in r20,pina ; get data
281 in r21,pinc ; get data
282
283 ;setup delay constant
284 ldi r18,low(tap5)
285 ldi r19,high(tap5)
286
287 ;multiply and accumulate - r5:r4:r3:r2
288 muls r19,r21 ; (signed)ah * (signed)bh
291 mul     r18,r20 ; al * bl
296 mulsu r19,r20 ; (signed)ah * bl
297 sbc     r5,r22
301 mulsu r21,r18 ; (signed)bh * al
302 sbc     r5,r22
306
307 ;get delayed data
308 movw r29:r28,r25:r24 ; move write register to read register
309 subi r28,low(tap_delay6) ; remove delay time
310 sbci r29,high(tap_delay6)
311 out portd,r28 ; set address
312 sts porth,r29
313 nop ; wait input latch time of 2 clock cycles
314 nop ; wait input latch time of 2 clock cycles
315 in r20,pina ; get data
316 in r21,pinc ; get data
317
318 ;setup delay constant
319 ldi r18,low(tap6)
320 ldi r19,high(tap6)
321
322 ;multiply and accumulate - r5:r4:r3:r2
323 muls r19,r21 ; (signed)ah * (signed)bh
326 mul     r18,r20 ; al * bl
331 mulsu r19,r20 ; (signed)ah * bl
332 sbc     r5,r22
336 mulsu r21,r18 ; (signed)bh * al
337 sbc     r5,r22
341
342 ;get delayed data
343 movw r29:r28,r25:r24 ; move write register to read register
344 subi r28,low(tap_delay7) ; remove delay time
345 sbci r29,high(tap_delay7)
346 out portd,r28 ; set address
347 sts porth,r29
348 nop ; wait input latch time of 2 clock cycles
349 nop ; wait input latch time of 2 clock cycles
350 in r20,pina ; get data
351 in r21,pinc ; get data
352
353 ;setup delay constant
354 ldi r18,low(tap7)
355 ldi r19,high(tap7)
356
357 ;multiply and accumulate - r5:r4:r3:r2
358 muls r19,r21 ; (signed)ah * (signed)bh
361 mul     r18,r20 ; al * bl
366 mulsu r19,r20 ; (signed)ah * bl
367 sbc     r5,r22
371 mulsu r21,r18 ; (signed)bh * al
372 sbc     r5,r22
376
377 ;get delayed data
378 movw r29:r28,r25:r24 ; move write register to read register
379 subi r28,low(tap_delay8) ; remove delay time
380 sbci r29,high(tap_delay8)
381 out portd,r28 ; set address
382 sts porth,r29
383 nop ; wait input latch time of 2 clock cycles
384 nop ; wait input latch time of 2 clock cycles
385 in r20,pina ; get data
386 in r21,pinc ; get data
387
388 ;setup delay constant
389 ldi r18,low(tap8)
390 ldi r19,high(tap8)
391
392 ;multiply and accumulate - r5:r4:r3:r2
393 muls r19,r21 ; (signed)ah * (signed)bh
396 mul     r18,r20 ; al * bl
401 mulsu r19,r20 ; (signed)ah * bl
402 sbc     r5,r22
406 mulsu r21,r18 ; (signed)bh * al
407 sbc     r5,r22
411
412 ;get delayed data
413 movw r29:r28,r25:r24 ; move write register to read register
414 subi r28,low(tap_delay9) ; remove delay time
415 sbci r29,high(tap_delay9)
416 out portd,r28 ; set address
417 sts porth,r29
418 nop ; wait input latch time of 2 clock cycles
419 nop ; wait input latch time of 2 clock cycles
420 in r20,pina ; get data
421 in r21,pinc ; get data
422
423 ;setup delay constant
424 ldi r18,low(tap9)
425 ldi r19,high(tap9)
426
427 ;multiply and accumulate - r5:r4:r3:r2
428 muls r19,r21 ; (signed)ah * (signed)bh
431 mul     r18,r20 ; al * bl
436 mulsu r19,r20 ; (signed)ah * bl
437 sbc     r5,r22
441 mulsu r21,r18 ; (signed)bh * al
442 sbc     r5,r22
446
447 ;get delayed data
448 movw r29:r28,r25:r24 ; move write register to read register
449 subi r28,low(tap_delay10) ; remove delay time
450 sbci r29,high(tap_delay10)
451 out portd,r28 ; set address
452 sts porth,r29
453 nop ; wait input latch time of 2 clock cycles
454 nop ; wait input latch time of 2 clock cycles
455 in r20,pina ; get data
456 in r21,pinc ; get data
457
458 ;setup delay constant
459 ldi r18,low(tap10)
460 ldi r19,high(tap10)
461
462 ;multiply and accumulate - r5:r4:r3:r2
463 muls r19,r21 ; (signed)ah * (signed)bh
466 mul     r18,r20 ; al * bl
471 mulsu r19,r20 ; (signed)ah * bl
472 sbc     r5,r22
476 mulsu r21,r18 ; (signed)bh * al
477 sbc     r5,r22
481
482 dec r15
483 brne done_000009
484 lds r31,pinj ; get switch data
485 andi r31,\$78 ; mask off rotary switch
486 ldi r17,\$02
487 lsr r31
488 lsr r31