welcome: please sign in

Revision 4 as of 2010-08-13 05:34:12

Clear message
location: MicrodecAsm

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 

MICrODEC

Microdec Software