Attachment 'delay_ping_pong.asm'
Download 1 ; program: ping_pong-18b-pot.asm
2 ; UID = 000030 - unique id to eliminate conflicts between variables
3 ; 18b address space (3s delay time)
4 ; stereo data - left and right swap to create ping-pong effect
5 ; pot (MOD1) controlled delay time (3ms - 3s)
6
7 ; program overview
8 ;
9 ; data is read in from memory and written out the codec at the same time
10 ; new data is written to the memory from the codec. ADC0 (MOD1) is read
11 ; and averaged over 256 samples to reduce jitter. this value is subtracted
12 ; from the write address to create the desired read address. if the actual
13 ; read address doesnt match the desired read address, it is either
14 ; incremented or decremented by one sample each sample period until it
15 ; matches. this reduces noise during delay time transitions. the left
16 ; channel input is recorded to the right channel output buffer (and vice
17 ; versa), so the sound bounces back and forth between the two channels.
18
19 ; register usage - may be redefined in other sections
20 ;
21 ; r0 deisred delay time fractional byte
22 ; r1
23 ; r2 left lsb out
24 ; r3 left msb out
25 ; r4 right lsb out
26 ; r5 right msb out
27 ; r6 left lsb in
28 ; r7 left msb in
29 ; r8 right lsb in
30 ; r9 right msb in
31 ; r10 adc accumulator lsb
32 ; r11 adc accumulator msb
33 ; r12 actual delay lsb
34 ; r13 actual delay msb
35 ; r14 adc sample counter
36 ; r15 switch sample counter
37 ; r16 temporary swap register
38 ; r17 temporary swap register
39 ; r18 null register
40 ; r19 adc accumulator fractional byte
41 ; r20 temporary swap register
42 ; r21 actual delay fractional byte
43 ; r22 write address third byte
44 ; r23 read address third byte
45 ; r24 write address lsb
46 ; r25 write address msb
47 ; r26 desired delay lsb
48 ; r27 desired delay msb
49 ; r28 read address lsb
50 ; r29 read address msb
51 ; r30 jump location for interrupt lsb
52 ; r31 jump location for interrupt msb
53 ; t
54
55 ;program starts here first time
56 ldi r30,$25 ; set jump location to program start
57 clr r24 ; clear write register
58 clr r25
59 ldi r22,$00 ; setup write address high byte
60 clr r18 ; setup r18 as null register for carry addition and ddr setting
61 ldi r17,$ff ; setup r17 for ddr setting
62
63 clear_000030: ; clear delay buffer
64 ; eliminates static when first switching to the delay setting
65
66 adiw r25:r24,$01 ; increment write register
67 adc r22,r18 ; increment write third byte
68 cpi r22,$04 ; check if full memory space has been cleared
69 breq cleardone_000030 ; continue until end of buffer reached
70 out portd,r24 ; set address
71 sts porth,r25
72 out portg,r22 ; pull ce low,we low,and set high bits of address
73 out ddra,r17 ; set porta as output for data write
74 out ddrc,r17 ; set portc as output for data write
75 out porta,r18 ; set data
76 out portc,r18 ; r18 is cleared above
77 sbi portg,portg2 ; pull we high to write
78 out ddra,r18 ; set porta as input for data lines
79 out ddrc,r18 ; set portc as input for data lines
80 rjmp clear_000030 ; continue clearing
81
82 cleardone_000030: ; reset registers
83
84 clr r24 ; clear write register
85 clr r25
86 ldi r22,$00 ; setup write address high byte
87 clr r28 ; set read address to minimum delay
88 ldi r29,$ff
89 ldi r23,$07 ; setup read address high byte
90 clr r21 ; set actual delay time to minimum delay
91 ldi r16,$01
92 mov r12,r16
93 clr r13
94 clr r2 ; initialize data output registers
95 clr r3
96 clr r4
97 clr r5
98 reti ; finish with initialization and wait for next interrupt
99
100 ; program starts here every time but first
101 ; initiate data transfer to codec
102 sbi portb,portb0 ; toggle slave select pin
103 out spdr,r3 ; send out left channel msb
104 cbi portb,portb0
105
106 ;increment sram addresses
107 adiw r25:r24,$01 ; increment write address
108 adc r22,r18 ; increment write third byte
109 andi r22,$03 ; mask off unsed bits
110 adiw r29:r28,$01 ; increment read address
111 adc r23,r18 ; increment read third byte
112 andi r23,$03 ; mask off unsed bits
113 ori r23,$04 ; set we bit for reading
114
115 wait1_000030: ; check if byte has been sent
116
117 in r17,spsr
118 sbrs r17,spif
119 rjmp wait1_000030
120 in r7,spdr ; recieve in left channel msb
121 out spdr,r2 ; send out left channel lsb
122
123 ;get left channel data from sram
124 out portg,r23 ; pull ce low, we high, and set high bits of register
125 out portd,r28 ; set address
126 sts porth,r29
127 adiw r29:r28,$01 ; increment read address
128 adc r23,r18 ; placed here to use setup time efficiently
129 andi r23,$03 ; mask off unsed bits
130 ori r23,$04 ; set we bit for reading
131 in r2,pina ; get data
132 in r3,pinc ; get data
133
134 wait2_000030: ; check if byte has been sent
135
136 in r17,spsr
137 sbrs r17,spif
138 rjmp wait2_000030
139 in r6,spdr ; recieve in left channel lsb
140 out spdr,r5 ; send out right channel msb
141
142 ;write left channel data to sram
143 out portd,r24 ; set address
144 sts porth,r25
145 out portg,r22 ; pull ce low,we low,and set high bits of address
146 ldi r17,$ff
147 out ddra,r17 ; set porta as output for data write
148 out ddrc,r17 ; set portc as output for data write
149 out porta,r6 ; set data
150 out portc,r7
151 sbi portg,portg2 ; pull we high to write
152 out ddra,r18 ; set porta as input for data lines
153 out ddrc,r18 ; set portc as input for data lines
154
155 wait3_000030: ; check if byte has been sent
156
157 in r17,spsr
158 sbrs r17,spif
159 rjmp wait3_000030
160 in r9,spdr ; recieve in right channel msb
161 out spdr,r4 ; send out right channel lsb
162
163 ;get right channel data from sram
164 out portg,r23 ; pull ce low,we high,oe low, and set high bits of address
165 out portd,r28 ; set address
166 sts porth,r29
167 adiw r25:r24,$01 ; increment write address
168 adc r22,r18 ; placed here for efficient use of setup time
169 andi r22,$03 ; mask off unsed bits
170 in r4,pina ; get data
171 in r5,pinc ; get data
172
173 wait4_000030: ; check if byte has been sent
174
175 in r17,spsr
176 sbrs r17,spif
177 rjmp wait4_000030
178 in r8,spdr ; recieve in left channel lsb
179
180 ;write right channel data to sram
181 out portd,r24 ; set address
182 sts porth,r25
183 out portg,r22 ; pull ce low,we low,and set high bits of address
184 ldi r17,$ff
185 out ddra,r17 ; set porta as output for data write
186 out ddrc,r17 ; set portc as output for data write
187 out porta,r8 ; set data
188 out portc,r9
189 sbi portg,portg2 ; pull we high to write
190 out ddra,r18 ; set porta as input for data lines
191 out ddrc,r18 ; set portc as input for data lines
192
193 ; get delay settings
194 lds r17,adcsra ; get adc control register
195 sbrs r17,adif ; check if adc conversion is complete
196 rjmp shift_000030 ; skip adc sampling
197 lds r16,adcl ; get low byte adc value
198 lds r17,adch ; get high byte adc value
199 add r19,r16 ; accumulate adc samples
200 adc r10,r17
201 adc r11,r18 ; r18 is cleared above
202 ldi r17,$f7
203 sts adcsra,r17 ; clear interrupt flag
204 dec r14 ; countdown adc sample clock
205 brne shift_000030 ; get delay time if its been long enough
206 ldi r17,$01 ; check if adc value is less than $000100
207 cp r19,r18 ; r18 is cleared above
208 cpc r10,r17
209 cpc r11,r18
210 brsh deadband_000030 ; check if adc value changed enough to update delay
211 inc r10 ; set minimum delay to $000100 = 3ms
212 clr r19
213
214 deadband_000030: ; check for change in adc value
215
216 movw r17:r16,r11:r10 ; move adc sample to temporary register
217 mov r20,r19
218 sub r20,r0 ; find difference between adc sample and desired delay time
219 sbc r16,r26
220 sbc r17,r27
221 brsh check_000030 ; check for deadband if positive
222 com r20 ; invert if negative
223 com r16 ; using ones complement as it is faster, and only has 1 bit error
224 com r17
225
226 check_000030: ; check if difference is greater than deadband
227
228 cpi r16,$01 ; check if difference is less than 1 lsb
229 cpc r17,r18 ; r18 cleared above
230 brlo empty_000030 ; do nothing if less than 1 lsb
231 movw r27:r26,r11:r10 ; move adc sample to delay time if large enough change
232 andi r19,$fc ; make sure delay time is a multiple of 4
233 mov r0,r19
234
235 empty_000030: ; empty accumulation registers and finish off
236
237 clr r10 ; empty accumulation registers
238 clr r11
239 clr r19
240
241 shift_000030: ; check if delay time is correct
242
243 cp r0,r21 ; compare desired delay to actual delay
244 cpc r26,r12
245 cpc r27,r13
246 breq switchsample_000030 ; do nothing if the same
247 brlo indexdown_000030
248 ldi r17,$04 ; increment delay register
249 add r21,r17
250 adc r12,r18 ; r18 is cleared above
251 adc r13,r18
252 ldi r17,$03
253 and r13,r17 ; mask off unused bits
254 rjmp switchsample_000030
255
256 indexdown_000030:
257
258 subi r21,$02 ; decrement delay register
259 sbc r12,r18 ; r18 is cleared above
260 sbc r13,r18
261 ldi r17,$03
262 and r13,r17 ; mask off unused bits
263
264 switchsample_000030: ; check state of rotary switch
265
266 dec r15
267 brne done_000030
268 lds r16,pinj ; get switch data
269 andi r16,$78 ; mask off rotary switch
270 lsr r16 ; adjust switch position to program memory location
271 lsr r16
272 ldi r17,$02
273 add r16,r17 ; move to jump register
274 cp r16,r31 ; check if location has changed
275 breq done_000030 ; finish off if no change
276 clr r30 ; reset jump register to intial state
277 mov r31,r16
278
279 done_000030:
280
281 movw r29:r28,r25:r24 ; move write address to read destination register
282 mov r23,r22 ; move write third byte to read third byte
283 sub r28,r21 ; subtract delay time
284 sbc r29,r12
285 sbc r23,r13
286 andi r23,$03 ; mask off unsed bits
287 ori r23,$04 ; set we bit for reading
288 movw r17:r16,r3:r2 ; swap left and right channels
289 movw r3:r2,r5:r4
290 movw r5:r4,r17:r16
291 reti
292
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.