← Revision 1 as of 2010-08-13 19:17:00
Size: 134
Comment:
|
← Revision 2 as of 2010-08-13 23:59:07 →
Size: 12535
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 3: | Line 3: |
This function implements a reverser, so all input sounds are played backwards. It takes mono data in on the left channel, and presents mono data out on both the left and right channels. The pot (MOD1) controls the buffer size. A reverser is created by playing all the samples in reverse order. Unfortunately, you end up hitting the beginning of your buffer at some point, and need to start over again. There are a number of ways of dealing with this buffer transition, in this case we use the crossfading technique. |
|
Line 8: | Line 12: |
; program: reverser-16b-pot-crossfade.asm ; UID = 000044 - unique id to eliminate conflicts between variables ; 16b address space (1.5s sample time) ; mono data in on left channel, mono data out on left and right ; pot (MOD1) controlled buffer size ; program overview ; ; data is read in from memory and written out the codec at the same time ; new data is written to the memory from the codec. left channel data ; is read in, and presented on both right and left out. the write address ; increments until it reaches the top of the buffer and then starts at ; zero. the read address does the same thing, but in reverse. the adc ; value sets the buffer size, and is determined by the pot (MOD1) value, ; which is multiplied up to a 16b value. the buffer size is adjusted at a ; rate of 2 lsb per sample period, until it matches to what the pot says ; it should be. the samples are played normally, until within a fixed ; distance of the buffer boundary. at this point, the samples are ; crossfaded with the first samples on the other side of the boundary. this ; reduces the appearance of clicks at buffer transistions, without giving ; the reverb effect of the fading method, and with a little less tremolo ; than the ducking method. ; constant definitions ; .equ stepsize_000044 = $0080 ; 65536/(stepsize * 44.1) = crossfade time (ms) .equ buffer_min_000044 = (4 * ($10000 / stepsize_000044)) ; minimum sample buffer size to accomodate crossfade time ; register usage - may be redefined in other sections ; ; r0 multiply result lsb ; r1 multiply result msb ; r2 multiply accumulate lsb ; r3 multiply accumulate mlb ; r4 left/right lsb out / sample 1 lsb / multiply accumulate mhb ; r5 left/right msb out / smaple 2 msb / multiply accumulate msb ; r6 left lsb in / sample 2 lsb ; r7 left msb in / sample 2 msb ; r8 ; r9 adc msb accumulator ; r10 adc fractional byte accumulator ; r11 adc lsb accumulator ; r12 desired buffer size lsb ; r13 desired buffer size msb ; r14 null register ; r15 switch/adc counter ; r16 temporary swap register ; r17 temporary swap register ; r18 crossfade address temporary lsb ; r19 crossfade address temporary msb ; r20 crossfade distance lsb ; r21 crossfade distance msb ; r22 multiplicand lsb ; r23 multiplicand msb ; r24 write address lsb ; r25 write address msb ; r26 buffer size lsb ; r27 buffer size msb ; r28 read address lsb ; r29 read address msb ; r30 jump location for interrupt lsb ; r31 jump location for interrupt msb ; t crossfading indicator ; program starts here first time ; initialze z pointer for correct jump ; this assumes a less than 256 word jump ldi r30,$20 ; set jump location to program start clr r24 ; clear write register clr r25 ldi r22,$00 ; setup write address high byte clr r18 ; setup r18 as null register for carry addition and ddr setting ldi r17,$ff ; setup r17 for ddr setting clear_000044: ; clear delay buffer ; eliminates static when first switching to the delay setting adiw r25:r24,$01 ; increment write register adc r22,r18 ; increment write third byte cpi r22,$01 ; check if 16b memory space has been cleared breq cleardone_000044 ; continue until end of buffer reached out portd,r24 ; set address sts porth,r25 out portg,r22 ; pull ce low,we low,and set high bits of address out ddra,r17 ; set porta as output for data write out ddrc,r17 ; set portc as output for data write out porta,r18 ; set data out portc,r18 ; r18 is cleared above sbi portg,portg2 ; pull we high to write out ddra,r18 ; set porta as input for data lines out ddrc,r18 ; set portc as input for data lines rjmp clear_000044 ; continue clearing cleardone_000044: ; reset registers ldi r24,$00 ; initialize write register ldi r25,$00 clr r14 ; setup null register ldi r28,$00 ; set read address to minimum delay ldi r29,$fd clr r4 ; initialize data output registers clr r5 ldi r26,$00 ; initialize buffer size ldi r27,$06 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 ;increment write address adiw r25:r24,$01 ; increment write address cp r24,r26 ; check if at buffer boundary cpc r25,r27 brlo wait1_000044 ; continue if not clr r24 ; set write address to bottom clr r25 wait1_000044: ; check if byte has been sent in r17,spsr sbrs r17,spif rjmp wait1_000044 in r7,spdr ; recieve in left channel msb out spdr,r4 ; send out left channel lsb ;decrement read address sbiw r29:r28,$01 ; decrement read address brsh wait2_000044 ; check if at bottom of buffer movw r29:r28,r27:r26 ; set counter to top sbiw r29:r28,$01 ; decrement read address wait2_000044: ; check if byte has been sent in r17,spsr sbrs r17,spif rjmp wait2_000044 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,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_000044: ; check if byte has been sent in r17,spsr sbrs r17,spif rjmp wait3_000044 in r17,spdr ; recieve in right channel msb out spdr,r4 ; send out right channel lsb ;get left/right channel data from sram out portd,r28 ; set address sts porth,r29 nop ; wait input latch time of 2 clock cycles nop in r4,pina ; get data in r5,pinc ; get data wait4_000044: ; check if byte has been sent in r17,spsr sbrs r17,spif rjmp wait4_000044 in r17,spdr ; recieve in left channel lsb ;get crossfade distance movw r17:r16,r29:r28 ; move read address to temporary register sub r16,r24 ; find distance to loop boundary sbc r17,r25 brcc attenuate_000044 ; check if within crossfade distance if positive add r16,r26 ; flip result around boundary if negative adc r17,r27 attenuate_000044: ; multiply signal by distance to boundary brts crossfade1_000044 ; skip if already crossfading ldi r18,low(2 * ($10000 / stepsize_000044)) ; get crossfade distance ldi r19,high(2 * ($10000 / stepsize_000044)) cp r16,r18 ; check if less than crossfade distance cpc r17,r19 brsh check_000044 ; do nothing if not set ; set t register to indicate crossfade and downcounting clr r20 ; set crossfade counter to top clr r21 subi r20,low(stepsize_000044) ; decrement for first sample sbci r21,high(stepsize_000044) crossfade1_000044: ; crossfade the signal ;setup sample 2 read address movw r19:r18,r29:r28 ; move read address to temporary register subi r18,low(2 * ($10000 / stepsize_000044)) ; get sample from other side of boundary sbci r19,high(2 * ($10000 / stepsize_000044)) brcc crossfade2_000044 ; continue if no buffer underflow add r18,r26 ; wrap read address around buffer adc r19,r27 crossfade2_000044: ; continue crossfading signal ;get sample 2 from sram out portd,r18 ; set address sts porth,r19 nop ; wait input latch time of 2 clock cycles nop in r6,pina ; get data in r7,pinc ; get data ;multiply sample 1 movw r17:r16,r5:r4 ; move data to signed multiply register mulsu r17,r21 ; (signed)Ah * (unsigned)Bh - multiply high bytes movw r5:r4,r1:r0 ; store high bytes result for later mul r16,r20 ; (unsigned)Al * (unsigned)Bl ; multiply low bytes movw r3:r2,r1:r0 ; store low byets for later mulsu r17,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,r16 ; (unsigned)Bh * (unsigned)Al - multiply middle bytes add r3,r0 ; accumulate result adc r4,r1 adc r5,r14 ; r14 is cleared above ;multiply and accumulate sample 2 movw r17:r16,r7:r6 ; move data to signed multiply register movw r23:r22,r21:r20 ; move distance counter to temporary register com r22 ; invert distance for sample 2 com r23 mulsu r17,r23 ; (signed)Ah * (unsigned)Bh - multiply high bytes add r4,r0 ; accumulate result adc r5,r1 mul r16,r22 ; (unsigned)Al * (unsigned)Bl ; multiply low bytes add r2,r0 ; accumulate result adc r3,r1 adc r4,r14 adc r5,r14 mulsu r17,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,r16 ; (unsigned)Bh * (unsigned)Al - multiply middle bytes add r3,r0 ; accumulate result adc r4,r1 adc r5,r14 ; r14 is cleared above ;check if done crossfading subi r20,low(stepsize_000044) ; decrement crossfade sbci r21,high(stepsize_000044) brcc check1_000044 ; check if crossfade time is negative movw r29:r28,r19:r18 ; move crossfade address to current address clt ; clear the t register to indicate done rjmp check_000044 ; finish off check1_000044: ; continue checking crossfade time brne check_000044 ; check if crossfade time is zero movw r29:r28,r19:r18 ; move crossfade address to current address clt ; clear the t register to indicate done check_000044: ; check if buffer size is correct cp r26,r12 ; compare current delay to desired delay cpc r27,r13 brlo upcount2_000044 ; increment if smaller than breq adcsample_000044 ; do nothing if they are same size sbiw r27:r26,$02 ; decrement buffer size rjmp adcsample_000044 ; finish off upcount2_000044: ; increment buffer size register adiw r27:r26,$02 ; increment buffer size adcsample_000044: ; get loop setting lds r17,adcsra ; get adc control register sbrs r17,adif ; check if adc conversion is complete rjmp done_000044 ; skip adc sampling lds r16,adcl ; get low byte adc value lds r17,adch ; get high byte adc value add r10,r16 adc r11,r17 ; accumulate adc samples adc r9,r14 ; accumulate adc samples - r14 is cleared above ldi r17,$f7 sts adcsra,r17 ; clear interrupt flag dec r15 ; countdown adc sample clock brne done_000044 ; move adc value to loop setting after 256 samples lsr r9 ; divide accumulated value by 4 to get 16b value ror r11 ror r10 lsr r9 ror r11 ror r10 ldi r16,low(buffer_min_000044) ; load minimum buffer size ldi r17,high(buffer_min_000044) cp r10,r16 ; check if less than minimum cpc r11,r17 brsh compare_000044 ; compare to previous value if above min movw r11:r10,r17:r16 ; set buffer size to minimum compare_000044: ; compare to previous value movw r17:r16,r13:r12 ; make a copy of current loop time for comparison sub r16,r10 ; find difference between current loop time and last loop time sbc r17,r11 brcc deadband_000044 ; see if difference is large enough to indicate a change neg r16 ; invert difference if negative adc r17,r14 ; r14 is cleared above neg r17 deadband_000044: ; see if pot has moved or if its just noise cpi r16,$40 ; see if difference is greater than 1 lsb cpc r17,r14 ; r14 is cleared above brlo nochange_000044 ; dont update loop time if difference is not large enough ldi r16,$fe ; make sure buffer size is even and r10,r16 movw r13:r12,r11:r10 ; move adc value to loop time register nochange_000044: ; clear accumulation registers clr r10 ; empty accumulation registers clr r11 clr r9 ;check rotary switch state 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_000044: reti ; return to waiting |
Reverser with Crossfade
This function implements a reverser, so all input sounds are played backwards. It takes mono data in on the left channel, and presents mono data out on both the left and right channels. The pot (MOD1) controls the buffer size.
A reverser is created by playing all the samples in reverse order. Unfortunately, you end up hitting the beginning of your buffer at some point, and need to start over again. There are a number of ways of dealing with this buffer transition, in this case we use the crossfading technique.
1 ; program: reverser-16b-pot-crossfade.asm
2 ; UID = 000044 - unique id to eliminate conflicts between variables
3 ; 16b address space (1.5s sample time)
4 ; mono data in on left channel, mono data out on left and right
5 ; pot (MOD1) controlled buffer size
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. left channel data
11 ; is read in, and presented on both right and left out. the write address
12 ; increments until it reaches the top of the buffer and then starts at
13 ; zero. the read address does the same thing, but in reverse. the adc
14 ; value sets the buffer size, and is determined by the pot (MOD1) value,
15 ; which is multiplied up to a 16b value. the buffer size is adjusted at a
16 ; rate of 2 lsb per sample period, until it matches to what the pot says
17 ; it should be. the samples are played normally, until within a fixed
18 ; distance of the buffer boundary. at this point, the samples are
19 ; crossfaded with the first samples on the other side of the boundary. this
20 ; reduces the appearance of clicks at buffer transistions, without giving
21 ; the reverb effect of the fading method, and with a little less tremolo
22 ; than the ducking method.
23
24 ; constant definitions
25 ;
26 .equ stepsize_000044 = $0080 ; 65536/(stepsize * 44.1) = crossfade time (ms)
27 .equ buffer_min_000044 = (4 * ($10000 / stepsize_000044))
28 ; minimum sample buffer size to accomodate crossfade time
29
30 ; register usage - may be redefined in other sections
31 ;
32 ; r0 multiply result lsb
33 ; r1 multiply result msb
34 ; r2 multiply accumulate lsb
35 ; r3 multiply accumulate mlb
36 ; r4 left/right lsb out / sample 1 lsb / multiply accumulate mhb
37 ; r5 left/right msb out / smaple 2 msb / multiply accumulate msb
38 ; r6 left lsb in / sample 2 lsb
39 ; r7 left msb in / sample 2 msb
40 ; r8
41 ; r9 adc msb accumulator
42 ; r10 adc fractional byte accumulator
43 ; r11 adc lsb accumulator
44 ; r12 desired buffer size lsb
45 ; r13 desired buffer size msb
46 ; r14 null register
47 ; r15 switch/adc counter
48 ; r16 temporary swap register
49 ; r17 temporary swap register
50 ; r18 crossfade address temporary lsb
51 ; r19 crossfade address temporary msb
52 ; r20 crossfade distance lsb
53 ; r21 crossfade distance msb
54 ; r22 multiplicand lsb
55 ; r23 multiplicand msb
56 ; r24 write address lsb
57 ; r25 write address msb
58 ; r26 buffer size lsb
59 ; r27 buffer size msb
60 ; r28 read address lsb
61 ; r29 read address msb
62 ; r30 jump location for interrupt lsb
63 ; r31 jump location for interrupt msb
64 ; t crossfading indicator
65
66 ; program starts here first time
67 ; initialze z pointer for correct jump
68 ; this assumes a less than 256 word jump
69 ldi r30,$20 ; set jump location to program start
70 clr r24 ; clear write register
71 clr r25
72 ldi r22,$00 ; setup write address high byte
73 clr r18 ; setup r18 as null register for carry addition and ddr setting
74 ldi r17,$ff ; setup r17 for ddr setting
75
76 clear_000044: ; clear delay buffer
77 ; eliminates static when first switching to the delay setting
78
79 adiw r25:r24,$01 ; increment write register
80 adc r22,r18 ; increment write third byte
81 cpi r22,$01 ; check if 16b memory space has been cleared
82 breq cleardone_000044 ; continue until end of buffer reached
83 out portd,r24 ; set address
84 sts porth,r25
85 out portg,r22 ; pull ce low,we low,and set high bits of address
86 out ddra,r17 ; set porta as output for data write
87 out ddrc,r17 ; set portc as output for data write
88 out porta,r18 ; set data
89 out portc,r18 ; r18 is cleared above
90 sbi portg,portg2 ; pull we high to write
91 out ddra,r18 ; set porta as input for data lines
92 out ddrc,r18 ; set portc as input for data lines
93 rjmp clear_000044 ; continue clearing
94
95 cleardone_000044: ; reset registers
96
97 ldi r24,$00 ; initialize write register
98 ldi r25,$00
99 clr r14 ; setup null register
100 ldi r28,$00 ; set read address to minimum delay
101 ldi r29,$fd
102 clr r4 ; initialize data output registers
103 clr r5
104 ldi r26,$00 ; initialize buffer size
105 ldi r27,$06
106 reti ; finish with initialization and wait for next interrupt
107
108 ; program starts here every time but first
109 ; initiate data transfer to codec
110 sbi portb,portb0 ; toggle slave select pin
111 out spdr,r5 ; send out left channel msb
112 cbi portb,portb0
113
114 ;increment write address
115 adiw r25:r24,$01 ; increment write address
116 cp r24,r26 ; check if at buffer boundary
117 cpc r25,r27
118 brlo wait1_000044 ; continue if not
119 clr r24 ; set write address to bottom
120 clr r25
121
122 wait1_000044: ; check if byte has been sent
123
124 in r17,spsr
125 sbrs r17,spif
126 rjmp wait1_000044
127 in r7,spdr ; recieve in left channel msb
128 out spdr,r4 ; send out left channel lsb
129
130 ;decrement read address
131 sbiw r29:r28,$01 ; decrement read address
132 brsh wait2_000044 ; check if at bottom of buffer
133 movw r29:r28,r27:r26 ; set counter to top
134 sbiw r29:r28,$01 ; decrement read address
135
136 wait2_000044: ; check if byte has been sent
137
138 in r17,spsr
139 sbrs r17,spif
140 rjmp wait2_000044
141 in r6,spdr ; recieve in left channel lsb
142 out spdr,r5 ; send out right channel msb
143
144 ;write left channel data to sram
145 out portd,r24 ; set address
146 sts porth,r25
147 out portg,r14 ; pull ce low,we low,and set high bits of address
148 ldi r17,$ff
149 out ddra,r17 ; set porta as output for data write
150 out ddrc,r17 ; set portc as output for data write
151 out porta,r6 ; set data
152 out portc,r7
153 sbi portg,portg2 ; pull we high to write
154 out ddra,r14 ; set porta as input for data lines
155 out ddrc,r14 ; set portc as input for data lines
156
157 wait3_000044: ; check if byte has been sent
158
159 in r17,spsr
160 sbrs r17,spif
161 rjmp wait3_000044
162 in r17,spdr ; recieve in right channel msb
163 out spdr,r4 ; send out right channel lsb
164
165 ;get left/right channel data from sram
166 out portd,r28 ; set address
167 sts porth,r29
168 nop ; wait input latch time of 2 clock cycles
169 nop
170 in r4,pina ; get data
171 in r5,pinc ; get data
172
173 wait4_000044: ; check if byte has been sent
174
175 in r17,spsr
176 sbrs r17,spif
177 rjmp wait4_000044
178 in r17,spdr ; recieve in left channel lsb
179
180 ;get crossfade distance
181 movw r17:r16,r29:r28 ; move read address to temporary register
182 sub r16,r24 ; find distance to loop boundary
183 sbc r17,r25
184 brcc attenuate_000044 ; check if within crossfade distance if positive
185 add r16,r26 ; flip result around boundary if negative
186 adc r17,r27
187
188 attenuate_000044: ; multiply signal by distance to boundary
189
190 brts crossfade1_000044 ; skip if already crossfading
191 ldi r18,low(2 * ($10000 / stepsize_000044)) ; get crossfade distance
192 ldi r19,high(2 * ($10000 / stepsize_000044))
193 cp r16,r18 ; check if less than crossfade distance
194 cpc r17,r19
195 brsh check_000044 ; do nothing if not
196 set ; set t register to indicate crossfade and downcounting
197 clr r20 ; set crossfade counter to top
198 clr r21
199 subi r20,low(stepsize_000044) ; decrement for first sample
200 sbci r21,high(stepsize_000044)
201
202 crossfade1_000044: ; crossfade the signal
203
204 ;setup sample 2 read address
205 movw r19:r18,r29:r28 ; move read address to temporary register
206 subi r18,low(2 * ($10000 / stepsize_000044)) ; get sample from other side of boundary
207 sbci r19,high(2 * ($10000 / stepsize_000044))
208 brcc crossfade2_000044 ; continue if no buffer underflow
209 add r18,r26 ; wrap read address around buffer
210 adc r19,r27
211
212 crossfade2_000044: ; continue crossfading signal
213
214 ;get sample 2 from sram
215 out portd,r18 ; set address
216 sts porth,r19
217 nop ; wait input latch time of 2 clock cycles
218 nop
219 in r6,pina ; get data
220 in r7,pinc ; get data
221
222 ;multiply sample 1
223 movw r17:r16,r5:r4 ; move data to signed multiply register
224 mulsu r17,r21 ; (signed)Ah * (unsigned)Bh - multiply high bytes
225 movw r5:r4,r1:r0 ; store high bytes result for later
226 mul r16,r20 ; (unsigned)Al * (unsigned)Bl ; multiply low bytes
227 movw r3:r2,r1:r0 ; store low byets for later
228 mulsu r17,r20 ; (signed)Ah * (unsigned)Bl - multiply middle bytes
229 sbc r5,r14 ; r14 is cleared above - subtract sign bit
230 add r3,r0 ; accumulate result
231 adc r4,r1
232 adc r5,r14 ; r14 is cleared above
233 mul r21,r16 ; (unsigned)Bh * (unsigned)Al - multiply middle bytes
234 add r3,r0 ; accumulate result
235 adc r4,r1
236 adc r5,r14 ; r14 is cleared above
237
238 ;multiply and accumulate sample 2
239 movw r17:r16,r7:r6 ; move data to signed multiply register
240 movw r23:r22,r21:r20 ; move distance counter to temporary register
241 com r22 ; invert distance for sample 2
242 com r23
243 mulsu r17,r23 ; (signed)Ah * (unsigned)Bh - multiply high bytes
244 add r4,r0 ; accumulate result
245 adc r5,r1
246 mul r16,r22 ; (unsigned)Al * (unsigned)Bl ; multiply low bytes
247 add r2,r0 ; accumulate result
248 adc r3,r1
249 adc r4,r14
250 adc r5,r14
251 mulsu r17,r22 ; (signed)Ah * (unsigned)Bl - multiply middle bytes
252 sbc r5,r14 ; r14 is cleared above - subtract sign bit
253 add r3,r0 ; accumulate result
254 adc r4,r1
255 adc r5,r14 ; r14 is cleared above
256 mul r23,r16 ; (unsigned)Bh * (unsigned)Al - multiply middle bytes
257 add r3,r0 ; accumulate result
258 adc r4,r1
259 adc r5,r14 ; r14 is cleared above
260
261 ;check if done crossfading
262 subi r20,low(stepsize_000044) ; decrement crossfade
263 sbci r21,high(stepsize_000044)
264 brcc check1_000044 ; check if crossfade time is negative
265 movw r29:r28,r19:r18 ; move crossfade address to current address
266 clt ; clear the t register to indicate done
267 rjmp check_000044 ; finish off
268
269 check1_000044: ; continue checking crossfade time
270
271 brne check_000044 ; check if crossfade time is zero
272 movw r29:r28,r19:r18 ; move crossfade address to current address
273 clt ; clear the t register to indicate done
274
275 check_000044: ; check if buffer size is correct
276
277 cp r26,r12 ; compare current delay to desired delay
278 cpc r27,r13
279 brlo upcount2_000044 ; increment if smaller than
280 breq adcsample_000044 ; do nothing if they are same size
281 sbiw r27:r26,$02 ; decrement buffer size
282 rjmp adcsample_000044 ; finish off
283
284 upcount2_000044: ; increment buffer size register
285
286 adiw r27:r26,$02 ; increment buffer size
287
288 adcsample_000044: ; get loop setting
289
290 lds r17,adcsra ; get adc control register
291 sbrs r17,adif ; check if adc conversion is complete
292 rjmp done_000044 ; skip adc sampling
293 lds r16,adcl ; get low byte adc value
294 lds r17,adch ; get high byte adc value
295 add r10,r16
296 adc r11,r17 ; accumulate adc samples
297 adc r9,r14 ; accumulate adc samples - r14 is cleared above
298 ldi r17,$f7
299 sts adcsra,r17 ; clear interrupt flag
300 dec r15 ; countdown adc sample clock
301 brne done_000044 ; move adc value to loop setting after 256 samples
302 lsr r9 ; divide accumulated value by 4 to get 16b value
303 ror r11
304 ror r10
305 lsr r9
306 ror r11
307 ror r10
308 ldi r16,low(buffer_min_000044) ; load minimum buffer size
309 ldi r17,high(buffer_min_000044)
310 cp r10,r16 ; check if less than minimum
311 cpc r11,r17
312 brsh compare_000044 ; compare to previous value if above min
313 movw r11:r10,r17:r16 ; set buffer size to minimum
314
315 compare_000044: ; compare to previous value
316
317 movw r17:r16,r13:r12 ; make a copy of current loop time for comparison
318 sub r16,r10 ; find difference between current loop time and last loop time
319 sbc r17,r11
320 brcc deadband_000044 ; see if difference is large enough to indicate a change
321 neg r16 ; invert difference if negative
322 adc r17,r14 ; r14 is cleared above
323 neg r17
324
325 deadband_000044: ; see if pot has moved or if its just noise
326
327 cpi r16,$40 ; see if difference is greater than 1 lsb
328 cpc r17,r14 ; r14 is cleared above
329 brlo nochange_000044 ; dont update loop time if difference is not large enough
330 ldi r16,$fe ; make sure buffer size is even
331 and r10,r16
332 movw r13:r12,r11:r10 ; move adc value to loop time register
333
334 nochange_000044: ; clear accumulation registers
335
336 clr r10 ; empty accumulation registers
337 clr r11
338 clr r9
339
340 ;check rotary switch state
341 lds r16,pinj ; get switch data
342 andi r16,$78 ; mask off rotary switch
343 lsr r16 ; adjust switch position to program memory location
344 lsr r16
345 ldi r17,$02
346 add r16,r17
347 cpse r16,r31 ; check if location has changed
348 clr r30 ; reset jump register to intial state
349 mov r31,r16
350
351 done_000044:
352
353 reti ; return to waiting
354