Attachment 'updown_sweep.asm'
Download 1 ; program: up_downsweep-18b-pot.asm
2 ; UID = 000035 - unique id to eliminate conflicts between variables
3 ; 18b address space (3s sample time)
4 ; stereo data
5 ; pot (MOD1) controlled buffer size (3ms - 1.5s)
6
7 ; program overview
8 ;
9 ; data is read in from memory and written out to the codec at the same time
10 ; new data is written to the memory from the codec. the write address
11 ; increments until it reaches the top of the buffer and then starts at
12 ; zero. the read address increases at twice the rate until it reaches the
13 ; write address, and then decreases until it reaches the write address.
14 ; it continues this back and forth sample playback. ADC0 (MOD1) is read
15 ; and averaged over 256 samples to reduce jitter. this value is subtracted
16 ; from the write address to create the desired read address. if the actual
17 ; read address doesnt match the desired read address, it is either
18 ; incremented or decremented by one sample each sample period until it
19 ; matches. this reduces noise during delay time transitions.
20
21 ; register usage - may be redefined in other sections
22 ;
23 ; r0 desired buffer size fractional byte
24 ; r1
25 ; r2 left lsb out
26 ; r3 left msb out
27 ; r4 right lsb out
28 ; r5 right msb out
29 ; r6 left lsb in
30 ; r7 left msb in
31 ; r8 right lsb in
32 ; r9 right msb in
33 ; r10 adc accumulation lsb
34 ; r11 adc accumulation msb
35 ; r12 read address offset lsb
36 ; r13 read address offset msb
37 ; r14 adc/switch sample counter
38 ; r15
39 ; r16 temporary swap register
40 ; r17 temporary swap register
41 ; r18 null register
42 ; r19 adc accumulation fractional byte
43 ; r20 temporary swap regiser
44 ; r21 read address offset high byte
45 ; r22 write address high byte
46 ; r23 read address high byte
47 ; r24 write address lsb
48 ; r25 write address msb
49 ; r26 desired buffer size lsb
50 ; r27 desired buffer size msb
51 ; r28 read address lsb
52 ; r29 read address msb
53 ; r30 jump location for interrupt lsb
54 ; r31 jump location for interrupt msb
55 ; t forward/reverse indicator
56
57 ; program starts here first time
58 ; initialze z pointer for correct jump
59 ; this assumes a less than 256 word jump
60 ldi r30,$29 ; set jump location to program start
61 clr r24 ; clear write register
62 clr r25
63 ldi r22,$00 ; setup write address high byte
64 clr r18 ; setup r18 as null register for carry addition and ddr setting
65 ldi r17,$ff ; setup r17 for ddr setting
66
67 clear_000035: ; clear delay buffer
68 ; eliminates static when first switching to the delay setting
69
70 adiw r25:r24,$01 ; increment write register
71 adc r22,r18 ; increment write third byte
72 cpi r22,$04 ; check if full memory space has been cleared
73 breq cleardone_000035 ; continue until end of buffer reached
74 out portd,r24 ; set address
75 sts porth,r25
76 out portg,r22 ; pull ce low,we low,and set high bits of address
77 out ddra,r17 ; set porta as output for data write
78 out ddrc,r17 ; set portc as output for data write
79 out porta,r18 ; set data
80 out portc,r18 ; r18 is cleared above
81 sbi portg,portg2 ; pull we high to write
82 out ddra,r18 ; set porta as input for data lines
83 out ddrc,r18 ; set portc as input for data lines
84 rjmp clear_000035 ; continue clearing
85
86 cleardone_000035: ; reset registers
87
88 ldi r24,$00 ; initialize write register
89 ldi r25,$00
90 ldi r22,$00 ; setup write address high byte
91 ldi r28,$00 ; set read address to minimum delay
92 ldi r29,$fe
93 ldi r23,$07 ; setup read address high byte
94 clr r0 ; set buffer size to minimum
95 ldi r26,$01
96 clr r27
97 clr r12 ; set read address offset to minimum buffer size
98 ldi r16,$01
99 mov r13,r16
100 clr r21
101 clr r2 ; initialize data output registers
102 clr r3
103 clr r4
104 clr r5
105 clt ; clear t register to start with forward play
106 reti ; finish with initialization and wait for next interrupt
107
108 ; program starts here all but first time
109 ; this is the point the z-pointer is incremented to
110 ; initiate data transfer to codec
111 sbi portb,portb0 ; toggle slave select pin
112 out spdr,r3 ; send out left channel msb
113 cbi portb,portb0
114
115 wait1_000035: ; check if byte has been sent
116
117 in r17,spsr
118 sbrs r17,spif
119 rjmp wait1_000035
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 for efficient use of setup time
129 andi r23,$03 ; mask off unsed bits
130 ori r23,$04 ; set we/ bit in high byte register
131 in r2,pina ; get data
132 in r3,pinc ; get data
133
134 wait2_000035: ; check if byte has been sent
135
136 in r17,spsr
137 sbrs r17,spif
138 rjmp wait2_000035
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_000035: ; check if byte has been sent
156
157 in r17,spsr
158 sbrs r17,spif
159 rjmp wait3_000035
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, and set high bits of register
165 out portd,r28 ; set address
166 sts porth,r29
167 adiw r25:r24,$01 ; increment write address
168 adc r22,r18 ; placed here to use setup time efficiently
169 andi r22,$03 ; mask off unsed bits
170 in r4,pina ; get data
171 in r5,pinc ; get data
172
173 wait4_000035: ; check if byte has been sent
174
175 in r17,spsr
176 sbrs r17,spif
177 rjmp wait4_000035
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 ;increment write address to next sample position
194 adiw r25:r24,$01 ; increment write address
195 adc r22,r18 ; increment write third byte
196 andi r22,$03 ; mask off unsed bits
197 movw r29:r28,r25:r24 ; move write address to read address
198 mov r23,r22
199
200 ;calculate read offset
201 brtc increment_000035 ; move read address forward if in foward mode
202 ldi r16,$04 ; else move read address backwards by 2
203 add r12,r16 ; this requires incrementing the read offset by 4
204 adc r13,r18 ; r18 is cleared above
205 adc r21,r18
206 cp r12,r0 ; check if at bottom of buffer
207 cpc r13,r26
208 cpc r21,r27
209 brlo readadd_000035 ; load read address if not at bottom of buffer
210 clt ; else clear t register to indicate forward motion after next sample
211 ; decrement offset by 2 - this halts playback for one sample
212 ; to reduce spikes at transitions
213
214 increment_000035: ; move read address forward by 4
215 ; moving read address forward requires reducing the read offset by 2
216 ldi r16,$02 ; subtract 2 from read offset
217 sub r12,r16
218 sbc r13,r18 ; r18 is cleared above
219 sbc r21,r18
220 brne readadd_000035 ; load read address if not at top of buffer
221 ldi r16,$04 ; set to playback last played sample
222 mov r12,r16 ; reduces spikes at transitions
223 set ; else set t register to start reversing on next sample
224
225 readadd_000035: ; add in read offset
226
227 sub r28,r12 ; subtract offset from read address
228 sbc r29,r13
229 sbc r23,r21
230 andi r23,$03 ; mask off unused bits
231 ori r23,$04 ; set we/ bit for reading
232
233 adcsample_000035: ; get buffer size from adc
234
235 lds r17,adcsra ; get adc control register
236 sbrs r17,adif ; check if adc conversion is complete
237 rjmp done_000035 ; skip adc sampling if not
238 lds r16,adcl ; get low byte adc value
239 lds r17,adch ; get high byte adc value
240 add r19,r16 ; accumulate adc samples
241 adc r10,r17
242 adc r11,r18 ; r18 is cleared above
243 ldi r17,$f7
244 sts adcsra,r17 ; clear interrupt flag
245 dec r14 ; countdown adc sample clock
246 brne done_000035 ; dont get buffer size till its been long enough
247 lsr r11 ; divide adc sample by 2
248 ror r10 ; as the max buffer size is only $020000
249 ror r19 ; as the buffer is read backwards half of the time
250 ldi r17,$01 ; check if adc value is less than $000100
251 cp r10,r17
252 cpc r11,r18 ; r18 cleared above
253 brsh deadband_000035 ; check if adc value changed enough to update delay
254 mov r10,r17 ; set minimum delay to $000100 = 3ms
255 clr r19
256
257 deadband_000035: ; check for change in adc value
258
259 movw r17:r16,r11:r10 ; move adc sample to temporary register
260 mov r20,r19
261 sub r20,r0 ; find difference between adc sample and desired buffer size
262 sbc r16,r26
263 sbc r17,r27
264 brsh check_000035 ; check for deadband if positive
265 com r20 ; invert if negative
266 com r16 ; using ones complement as it is faster, and only has 1 bit error
267 com r17
268
269 check_000035: ; check if difference is greater than deadband
270
271 cpi r20,$80 ; check if difference is less than 1 lsb
272 cpc r16,r18 ; r18 cleared above
273 cpc r17,r18
274 brlo empty_000035 ; do nothing if less than 1 lsb
275 movw r27:r26,r11:r10 ; move adc sample to delay time if large enough change
276 andi r19,$fc ; make sure buffer size is a multiple of 4
277 mov r0,r19
278
279 empty_000035: ; empty accumulation registers and finish off
280
281 clr r10 ; empty accumulation registers
282 clr r11
283 clr r19
284
285 switchsample_000035: ; check if at same function
286
287 lds r16,pinj ; get switch data
288 andi r16,$78 ; mask off rotary switch
289 lsr r16 ; adjust switch position to program memory location
290 lsr r16
291 ldi r17,$02
292 add r16,r17 ; move to jump register
293 cpse r16,r31 ; check if location has changed
294 clr r30 ; reset jump register to intial state
295 mov r31,r16
296
297 done_000035:
298
299 reti ; return to waiting
300
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.