AudioInt4Asm

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 

MICrODEC

Microdec Software

AudioInt4Asm (last edited 2010-06-17 01:31:45 by DanielMcAnulty)