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