Audioint4.asm
[Discussion of code elements, needed revision etc, can go here]
1 .include "m3250Pdef.inc" ; standard definitions include file
2
3 ; microdec v1.0 - /ss = pb0
4
5 ; fuse settings
6 ;
7 ; start up time set to 258CK + 65ms
8 ; set to 20MHz by external crystal
9 ; BOD set at 4.3V
10 ; RSTDISBL not set
11 ; OCDEN not set
12 ; JTAG enabled
13 ; SPI enabled
14 ; EESAVE not set
15 ; CKOUT not set
16 ; CKDIV8 not set
17 ; WDT not set
18
19 ; hardware connections
20 ;
21 ; portA0:7 = D0 - D7 for sram
22 ; portB0:4 = SPI to codec and ISP
23 ; portB5:6 = NC (XP3)
24 ; portB7 = OE for sram
25 ; portC0:7 = D8 - D15 for sram
26 ; portD0:7 = A0 - A7 for sram
27 ; portE0:1 = USART (CEREAL)
28 ; portE2:3 = NC (XP1)
29 ; portE4:5 = I2C to codec with external pullups (could be any pins as USI is pointless)
30 ; portE6:7 = NC (XP2)
31 ; portF0 = ADC0 for potentiometer input (MOD1)
32 ; portF1:3 = NC (ADC1:3)
33 ; portF4:7 = JTAG
34 ; portG0:1 = A16 - A17 for sram
35 ; portG2 = WE for sram
36 ; portG3 = CE for sram
37 ; portG4 = CLKin from codec to T0 for interrupt timing
38 ; portG5 = RESET to JTAG/ISP
39 ; portH0:7 = A8 - A15 for sram
40 ; portJ0:1 = rotary encoder (b0,b1) with external pullups
41 ; portJ2 = rotary encoder pushbutton
42 ; portJ3:6 = rotary switch (b0 - b3)
43 ; AREF = externally connected to AVcc = +5V
44 ; XTAL1:2 = 20MHz crystal
45 ; VCC = DVcc = +5V
46 ; AVCC = AVcc = +5V
47
48 ; program structure overview
49 ;
50 ; Data is transferred to the codec via SPI, using the codec's DSP mode.
51 ; The codec's master clock is divided by two within the codec, and then
52 ; sent to the microcontroller where it is divided by 128 with T0. This
53 ; causes an interrupt at 44.1kHz for data transfers to the codec. In
54 ; order to eliminate audio glitches, this transfer must happen at the
55 ; same time, every time. For this reason, all code is run within this
56 ; interrupt, and no other interrupts are used. This way there can never
57 ; be a delay in the transfer of data. The exact piece of code that is
58 ; run is determined by the rotary switch, which must be checked within
59 ; the interrupt periodically to determine which code should be currently
60 ; running. The program executes the correct code by jumping to the
61 ; program space defined by the rotary switch setting (ijmp command).
62 ; This jump location has to be loaded into r31:r30 before returning from
63 ; the interrupt, or the program may crash. Because of the timing
64 ; limitations, only 20MHz/44.1kHz = 453 clock cycles can occur per
65 ; interrupt, of which approximatley 60 are taken up with SPI communication
66 ; and interrupt handling. A buffered data method could be used if
67 ; the program does not perform the same operations each sample period,
68 ; but the current method is used because of its simplicity. If you want
69 ; to change a function, merely swap out the code at that .org location.
70
71 ; current programs and their memory locations
72 ;
73 ; code switch memory address/data bits/channels - function
74 ; ----- ----------- --------------------------------------------
75 ; $0200 = position 07 = 18b/16b/stereo - delay - pot controlled (3ms - 3s)
76 ; $0400 = position 06 = 16b/16b/stereo - delay - pot controlled (0s - .7s)
77 ; $0600 = position 05 = 16b/16b/mono - vco with vca
78 ; $0800 = position 04 = 16b/16b/stereo - upsweep - pot controlled
79 ; $0a00 = position 03 = 16b/16b/stereo - reverser
80 ; $0c00 = position 02 = 16b/16b/stereo - up/down sweep
81 ; $0e00 = position 01 = 16b/16b/stereo - delay - rotary encoder controlled
82 ; $1000 = position 00 = 16b/16b/mono - reverb
83 ; $1200 = position 15 = 16b/16b/mono - fullwave rectifier
84 ; $1400 = position 14 = 16b/16b/mono - gated reverser
85 ; $1600 = position 13 = 16b/16b/mono - envelope stripper as vca on rampwave
86 ; $1800 = position 12 = 16b/16b/mono - ring modulator
87 ; $1a00 = position 11 = 16b/16b/mono - sampler - pot controlled playback speed
88 ; $1c00 = position 10 = 16b/16b/mono - 16 voice chorus
89 ; $1e00 = position 09 = 16b/16b/mono - flanger
90 ; $2000 = position 08 = 16b/16b/mono - sampler - rotary encoder controlled playback speed
91
92 ; interrupt vectors
93 ;
94 .org 0 ; reset interrupt
95 rjmp start ; initialize microcontroller registers
96 .org OC0addr ; T0 compare interrupt - set to $80
97 ijmp ; send data to codec every 128 cycles of codec clock
98 .org OVF0addr ; T0 overflow interrupt
99 ijmp ; send data to codec every 128 cycles of codec clock
100
101 ; register usage - may be redefined in other sections
102 ; for conistency between programs, these registers(*) are normally used
103 ; as shown
104 ;
105 ; r0 multiply result lsb(*)
106 ; r1 multiply result msb(*)
107 ; r2 left data out lsb(*)
108 ; r3 left data out msb(*)
109 ; r4 right data out lsb(*)
110 ; r5 right data out msb(*)
111 ; r6 left data in lsb(*)
112 ; r7 left data in msb(*)
113 ; r8 right data in lsb(*)
114 ; r9 right data in msb(*)
115 ; r10
116 ; r11
117 ; r12
118 ; r13
119 ; r14
120 ; r15
121 ; r16 temporary swap register(*)
122 ; r17 temporary swap register(*)
123 ; r18 twi (i2c) counter register
124 ; r19
125 ; r20
126 ; r21
127 ; r22 write address third byte(*)
128 ; r23 read address third byte(*)
129 ; r24 write address lsb(*)
130 ; r25 write address msb(*)
131 ; r26
132 ; r27
133 ; r28 read address lsb(*)
134 ; r29 read address msb(*)
135 ; r30 jump location for interrupts lsb(*)
136 ; r31 jump location for interrupts msb(*)
137
138 start: ; configure microcontroller registers
139
140 ;set stack pointer to top of SRAM
141 ldi r16,low(RAMEND)
142 out SPH,r16
143 ldi r16,high(RAMEND)
144 out SPL,r16
145
146 ;setup sram io lines
147 ldi r16,$ff
148 out ddrd,r16 ; set portd as output for address lines
149 sts ddrh,r16 ; set porth as output for address lines
150 out porta,r16 ; turn on pullups on porta for data lines
151 out portc,r16 ; turn on pullups on portc for data lines
152 ldi r16,$00
153 out ddra,r16 ; set porta as input for data lines
154 out ddrc,r16 ; set portc as input for data lines
155 ldi r16,$0f
156 out ddrg,r16 ; set portg sram control pins to output
157 sbi ddrb,ddb7 ; set oe control pin to output
158 cbi portb,portb7 ; set oe to low - defined again in the spi setup
159
160 ;setup spi for codec data io
161 ldi r16,$87
162 out ddrb,r16 ; set ss,sck,mosi as output,and pb7 as output for oe on sram
163 ldi r16,$50 ; set spi to master,mode 0
164 out spcr,r16
165 ldi r16,$01 ; set spi to 2x (10MHz)
166 out spsr,r16
167
168 ;initialize ijmp address for reset vectors
169 ldi r30,$00
170 ldi r31,$02
171
172 ;setup adc
173 ldi r16,$01
174 sts didr0,r16 ; turn off input stage for pf0(adc0)
175 ldi r16,$00
176 sts admux,r16 ; set adc to sample adc0,external vcc ref,10b result
177 ldi r16,$e7
178 sts adcsra,r16 ; enable adc,start conversion,free running mode,interrupt disabled,ck/128(156khz@20mhz cpu)
179
180 ;initialize sram address buffers
181 ldi r25,$00 ; initialize sram write address registers
182 ldi r24,$00
183 ldi r29,$00 ; initialize sram read address registers
184 ldi r28,$80
185 ldi r23,$04 ; initialize high byte read address register (/we bit set)
186 ldi r22,$00 ; initialize high byte write address register (/we bit cleared)
187
188 ;setup switch lines
189 ldi r16,$7c
190 sts portj,r16 ; turn on pullups for rotary switch and pushbutton
191
192 ;codec initialization routines
193 ;check wm8731 datasheet for other settings
194 ;
195 ;setup codec - power and clock registers
196 ldi r17,$34 ; send address
197 rcall twisend
198 ldi r17,$0c ; power down command register
199 rcall clock_data
200 ldi r17,$02 ; adc on,line in on,adc on,osc on,power on,clock out,mic off
201 rcall clock_data
202
203 ;setup codec - digital interface
204 ldi r17,$34 ; send address
205 rcall twisend
206 ldi r17,$0e ; digital interface command register
207 rcall clock_data
208 ldi r17,$03 ; dsp mode,16bit,slave mode,bclk invert disabled,lrswap disabled,data on first edge
209 rcall clock_data
210
211 ;setup codec - left analog input
212 ldi r17,$34 ; send address
213 rcall twisend
214 ldi r17,$00 ; left analog interface command register
215 rcall clock_data
216 ldi r17,$17 ; mute off, +0db gain, lr load off
217 rcall clock_data
218
219 ;setup codec - right analog input
220 ldi r17,$34 ; send address
221 rcall twisend
222 ldi r17,$02 ; right analog interface command register
223 rcall clock_data
224 ldi r17,$17 ; mute off, +0db gain, lr load off
225 rcall clock_data
226
227 ;setup codec - left headphone output
228 ldi r17,$34 ; send address
229 rcall twisend
230 ldi r17,$04 ; left headphone otput command register
231 rcall clock_data
232 ldi r17,$79 ; zero-cross disable, +0db gain, lr load off
233 rcall clock_data
234
235 ;setup codec - right headphone output
236 ldi r17,$34 ; send address
237 rcall twisend
238 ldi r17,$06 ; right headphone output command register
239 rcall clock_data
240 ldi r17,$79 ; zero-cross disable, +0db gain, lr load off
241 rcall clock_data
242
243 ;setup codec - digital audio path
244 ldi r17,$34 ; send address
245 rcall twisend
246 ldi r17,$0a ; digital audio path command register
247 rcall clock_data
248 ldi r17,$00 ; highpass filter enabled,de-emphasis disabled,mute disabled,dc offset storage disabled
249 rcall clock_data
250
251 ;setup codec - analog audio path
252 ldi r17,$34 ; send address
253 rcall twisend
254 ldi r17,$08 ; analog audio path command register
255 rcall clock_data
256 ldi r17,$12 ; disable mic boost,mute mic,line in to adc,disable bypass,select dac,disable sidetone
257 rcall clock_data
258
259 ;setup codec - sampling control
260 ldi r17,$34 ; send address
261 rcall twisend
262 ldi r17,$10 ; sampling control command register
263 rcall clock_data
264 ldi r17,$a0 ; normal mode,256fs,clk/2 disable,clk/2 out enable
265 rcall clock_data
266
267 ;setup codec - activate codec
268 ldi r17,$34 ; send address
269 rcall twisend
270 ldi r17,$12 ; active command register
271 rcall clock_data
272 ldi r17,$01 ; active
273 rcall clock_data
274
275 ;setup timer0 for interrupt on dataclock
276 ldi r17,$07
277 out tccr0a,r17 ; set timer0 to external clock source, normal mode
278 ldi r17,$00
279 out tcnt0,r17 ; clear counter
280 ldi r17,$80
281 out ocr0a,r17 ; set counter top to 128
282 ldi r17,$03
283 sts timsk0,r17 ; set timer to interrupt on compare match and overflow
284
285 sei ; turn on interrupts
286
287 repeat: ; idle while outside of interrupt
288
289 nop
290 nop
291 nop
292 nop
293 nop
294 nop
295 rjmp repeat ; continue to idle
296
297 twisend: ; send data over twi (r17=data)
298 ; this is being bit banged as the USI peripheral essentially needs to be
299 ; bit banged anyways. the stop bit is not sent, as it doesn't seem to be
300 ; neccesary.
301 ;
302 ;setup timer0 for twi operation
303 ldi r16,$00
304 out tcnt0,r16 ; clear counter
305 ldi r16,$20
306 out ocr0a,r16 ; set counter top to 32 (167kHz data clock frequency)
307 ldi r16,$01
308 out tccr0a,r16 ; set timer0 to internal clock (cpu/1 = 20MHz), normal mode
309 ; make sure pullups are off
310 cbi porte,porte4 ; clock
311 cbi porte,porte5 ; data
312 cbi ddre,dde4 ; pull clock high
313 cbi ddre,dde5 ; pull data high
314
315 ;initiate start condition
316 ;
317 wait_start1: ; wait one clock cycle
318
319 sbis tifr0,ocf0a
320 rjmp wait_start1
321 ldi r16,$00
322 out tcnt0,r16 ; clear counter
323 sbi tifr0,ocf0a ; clear interrupt flag
324 sbi ddre,dde5 ; pull data low
325
326 wait_start2: ; wait one clock cycle
327
328 sbis tifr0,ocf0a
329 rjmp wait_start2
330 sbi ddre,dde4 ; pull clock low
331 ldi r16,$00
332 out tcnt0,r16 ; clear counter
333 sbi tifr0,ocf0a ; clear interrupt flag
334
335 wait_start3: ; wait one clock cycle
336
337 sbis tifr0,ocf0a
338 rjmp wait_start3
339 sbi tifr0,ocf0a ; clear interrupt flag
340
341 clock_data: ; clock out data
342
343 ldi r18,$08 ; setup data counter for 8 data bits
344 ldi r16,$00 ; reinitialize counter as data sends start from here
345 out tcnt0,r16 ; clear counter
346 ldi r16,$20
347 out ocr0a,r16 ; set counter top to 32 (167kHz data clock frequency)
348 ldi r16,$01
349 out tccr0a,r16 ; set timer0 to internal clock (cpu/1 = 20MHz), normal mode
350
351 clock_data1: ; continue clocking bits
352
353 lsl r17 ; move bit to be sent to carry register
354 brcs setbit_data ; check if bit is set
355 sbi ddre,dde5 ; clear data at output if not
356 rjmp wait_data1 ; continue with clocking
357
358 setbit_data: ; set data at output
359
360 cbi ddre,dde5 ; output data if bit is set
361
362 wait_data1: ; wait one clock cycle
363
364 sbis tifr0,ocf0a
365 rjmp wait_data1
366 cbi ddre,dde4 ; pull clock high
367 ldi r16,$00
368 out tcnt0,r16 ; clear counter
369 sbi tifr0,ocf0a ; clear interrupt flag
370
371 wait_data2: ; wait one clock cycle
372
373 sbis tifr0,ocf0a
374 rjmp wait_data2
375 sbi ddre,dde4 ; pull clock low
376 ldi r16,$00
377 out tcnt0,r16 ; clear counter
378 sbi tifr0,ocf0a ; clear interrupt flag
379
380 wait_data3: ; wait one clock cycle
381
382 sbis tifr0,ocf0a
383 rjmp wait_data3
384 ldi r16,$00
385 out tcnt0,r16 ; clear counter
386 sbi tifr0,ocf0a ; clear interrupt flag
387 dec r18 ; check if all bits have been clocked out
388 brne clock_data1 ; continue if not done
389 cbi ddre,dde5 ; release data line for ack
390
391 ;check for ack from codec
392 ;
393 wait_ack1: ; check for ack
394
395 sbic tifr0,ocf0a ; check if timer has expired
396 rjmp start ; reset micro if no ack within timeout (1.3us)
397 sbic pine,pine5 ; check for codec pulling the data line low
398 rjmp wait_ack1
399
400 wait_ack2: ; wait remainder of clock cycle
401
402 sbis tifr0,ocf0a
403 rjmp wait_ack2
404 cbi ddre,dde4 ; pull clock high
405 ldi r16,$00
406 out tcnt0,r16 ; clear counter
407 sbi tifr0,ocf0a ; clear interrupt flag
408
409 wait_ack3: ; wait one clock cycle
410
411 sbis tifr0,ocf0a
412 rjmp wait_ack3
413 sbi ddre,dde4 ; pull clock low
414 ldi r16,$00
415 out tcnt0,r16 ; clear counter
416 sbi tifr0,ocf0a ; clear interrupt flag
417
418 wait_ack4: ; wait one clock cycle
419
420 sbis tifr0,ocf0a
421 rjmp wait_ack4
422 ldi r16,$00
423 out tcnt0,r16 ; clear counter
424 sbi tifr0,ocf0a ; clear interrupt flag
425 ldi r16,$80
426 out ocr0a,r16 ; set counter top to 128 for ack timeout (6.4us time out)
427
428 wait_ack5: ; check for ack complete
429
430 sbic tifr0,ocf0a ; check if timer has expired
431 rjmp start ; reset micro if no ack within timeout (6.4us)
432 sbis pine,pine5 ; check for codec releasing the data line
433 rjmp wait_ack5
434 ldi r16,$00
435 out tccr0a,r16 ; turn counter0 off
436 ret
437
438 .org $0200 ; program space for position 7 on rotary encoder
439
440 ;.include "flanger-16b-variable.asm"
441 ;.include "delay-16b-midi.asm"
442 .include "pitch_shifter-16b-variable-fading.asm"
443 ;.include "delay-18b-pot.asm" ; place delay program here
444
445 .org $0400 ; program space for switch position 6
446
447 ;.include "delay-16b-pot.asm" ; place delay program here
448 .include "pitch_shifter-16b-variable-ducking.asm"
449
450 .org $0600 ; program space for switch position 5
451
452 ;.include "pitch_shifter-16b-rotary.asm"
453 .include "pll-16b.asm" ; place pll program here
454
455 .org $0800 ; program space for switch position 4
456
457 ;.include "pitch_shifter-16b-variable.asm"
458 .include "upsweep-16b-pot.asm" ; place upsweep program here
459
460 .org $0a00 ; program space for switch position 3
461
462 .include "downsweep-16b.asm" ; place downsweep program here
463
464 .org $0c00 ; program space for switch position 2
465
466 .include "up_downsweep-16b.asm" ; place up_downsweep program here
467
468 .org $0e00 ; program space for switch position 1
469
470 .include "delay-16b-rotary.asm" ; place delay program here
471
472 .org $1000 ; program space for switch position 0
473
474 .include "reverb-16b.asm" ; place reverb program here
475
476 .org $1200 ; program space for switch position 15
477
478 .include "pseudo_convolver-16b.asm"
479 ;.include "fullwave.asm" ; place fullwave rectifier program here
480
481 .org $1400 ; program space for switch position 14
482
483 .include "gated_reverser-16b.asm" ; place gated reverser program here
484
485 .org $1600 ; program space for switch position 13
486
487 .include "envelope_stripper.asm" ; place envelope stripper program here
488
489 .org $1800 ; program space for switch position 12
490
491 .include "ring_modulator.asm" ; place ring modulator program here
492
493 .org $1a00 ; program space for switch position 11
494
495 .include "sampler-pot.asm" ; place sampler program here
496
497 .org $1c00 ; program space for switch position 10
498
499 .include "chorus-16b.asm" ; place chorus program here
500
501 .org $1e00 ; program space for switch position 9
502
503 .include "flanger-16b.asm" ; place flanger program here
504
505 .org $2000 ; program space for switch position 8
506
507 .include "sampler-rotary.asm" ; place sampler program here
508
509 .org $2200 ; program space for sinewave table
510 ; 256 sample, 8b, half sine table, only positive values [$00 - $7f]
511 ; should update to 16b table, as this sounds pretty bad
512 .include "sinewave-8b-256s.asm"
513
514 .org $2400 ; program space for sinewave lookup table
515 ; 256 samples at 16b resolution, halfwave table, signed positive values
516 ; only [$0000 - $7fff].
517 .include "sinewave-16b-256s.asm"
518