welcome: please sign in

Upload page content

You can upload content for the page named below. If you change the page name, you can also upload content for another page. If the page name is empty, we derive the page name from the file name.

File to load page content from
Page name
Comment
What is the opposite of 'day'?

Revision 3 as of 2010-08-13 07:42:46

location: Delay700msStereo

700ms Stereo Delay

delay_700ms_stereo.asm


; program: delay-16b-pot.asm
; UID = 000003 - unique id to eliminate conflicts between variables
; 16b address space (.7s delay time)
; stereo data
; pot (MOD1) controlled delay time (3ms - 700ms)

; 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.  ADC0 (MOD1) is read
; and averaged over 256 samples to reduce jitter.  this value is subtracted
; from the write address to create the desired read address.  if the actual
; read address doesnt match the desired read address, it is either
; incremented or decremented by one sample each sample period until it
; matches.  this reduces noise during delay time transitions.

; register usage - may be redefined in other sections
;
; r0  
; r1  
; r2  left lsb out
; r3  left msb out
; r4  right lsb out
; r5  right msb out
; r6  left lsb in
; r7  left msb in
; r8  right lsb in
; r9  right msb in
; r10 adc accumulator fractional byte
; r11 adc accumulator lsb
; r12 actual delay lsb
; r13 actual delay msb
; r14 adc sample counter
; r15 switch sample counter
; r16 temporary swap register
; r17 temporary swap register
; r18 
; r19 adc accumulator msb
; r20 
; r21 
; r22 null register
; r23 read address third byte
; r24 write address lsb
; r25 write address msb
; r26 desired delay lsb
; r27 desired delay msb
; r28 read address lsb
; r29 read address msb
; r30 jump location for interrupt lsb
; r31 jump location for interrupt msb
; t   

;program starts here first time
ldi r30,$25 ; 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_000003: ; 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_000003 ; 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_000003 ; continue clearing

cleardone_000003: ; reset registers

clr r24 ; clear write register
clr r25
ldi r22,$00 ; setup null register
clr r28 ; set read address to minimum delay
ldi r29,$ff
ldi r23,$04 ; setup read address high byte
clr r21 ; set actual delay time to minimum delay
ldi r16,$01
mov r13,r16
clr r12
clr r2 ; initialize data output registers
clr r3
clr r4
clr r5
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,r3 ; send out left channel msb
cbi portb,portb0

;increment sram address
adiw r25:r24,$01 ; increment write address
adiw r29:r28,$01 ; increment read address

wait1_000003: ; check if byte has been sent

in r17,spsr
sbrs r17,spif
rjmp wait1_000003
in r7,spdr ; recieve in left channel msb
out spdr,r2 ; send out left channel lsb

;get left channel data from sram
out portd,r28 ; set address
sts porth,r29
nop ; wait input latch time of 2 clock cycles
nop ; wait input latch time of 2 clock cycles
in r2,pina ; get data
in r3,pinc ; get data
adiw r29:r28,$01 ; increment read address

wait2_000003: ; check if byte has been sent

in r17,spsr
sbrs r17,spif
rjmp wait2_000003
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,r22 ; 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,r22 ; set porta as input for data lines
out ddrc,r22 ; set portc as input for data lines

wait3_000003: ; check if byte has been sent

in r17,spsr
sbrs r17,spif
rjmp wait3_000003
in r9,spdr ; recieve in right channel msb
out spdr,r4 ; send out right channel lsb

;get right channel data from sram
out portd,r28 ; set address
sts porth,r29
nop ; wait input latch time of 2 clock cycles
nop ; wait input latch time of 2 clock cycles
in r4,pina ; get data
in r5,pinc ; get data
adiw r25:r24,$01 ; increment write address

wait4_000003: ; check if byte has been sent

in r17,spsr
sbrs r17,spif
rjmp wait4_000003
in r8,spdr ; recieve in left channel lsb

;write right channel data to sram
out portd,r24 ; set address
sts porth,r25
out portg,r22 ; 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,r8 ; set data
out portc,r9
sbi portg,portg2 ; pull we high to write
out ddra,r22 ; set porta as input for data lines
out ddrc,r22 ; set portc as input for data lines

;get delay settings
lds r17,adcsra ; get adc control register
sbrs r17,adif ; check if adc conversion is complete
rjmp shift_000003 ; skip adc sampling
lds r16,adcl ; get low byte adc value
lds r17,adch ; get high byte adc value
add r10,r16 ; accumulate adc samples
adc r11,r17
adc r19,r22 ; r22 is cleared above
ldi r17,$f7
sts adcsra,r17 ; clear interrupt flag
dec r14 ; countdown adc sample clock
brne shift_000003 ; get delay time if its been long enough
lsr r19 ; divide adc sample by 4
ror r11 ; makes adc value a 16b number
ror r10
lsr r19
ror r11
ror r10
ldi r16,$01 ; check if delay is below minimum
cp r10,r22 ; r22 is cleared above
cpc r11,r16
brsh deadband_000003 ; check if adc value changed enough to update delay
clr r10 ; set minimum delay to $0100 = 3ms
mov r11,r16

deadband_000003: ; set the low value of the delay

movw r17:r16,r11:r10 ; move adc sample to temporary register
sbc r16,r26 ; find difference between adc sample and desired delay time
sbc r17,r27
brsh check_000003 ; check for deadband if positive
neg r16 ; invert if negative
adc r17,r22 ; r22 is cleared above
neg r17 ; converts ones complement to twos complement

check_000003: ; check if difference is greater than deadband

cpi r16,$40 ; check if difference is less than 1 lsb of adc
cpc r17,r22 ; r22 cleared above
brlo empty_000003 ; do nothing if less than 1 lsb
movw r27:r26,r11:r10 ; move adc sample to delay time if large enough change
andi r26,$fc ; make sure delay time is a multiple of 4

empty_000003: ; empty accumulation registers and finish off

clr r10 ; empty accumulation registers
clr r11
clr r19

shift_000003: ; check if delay time is correct

cp r26,r12 ; compare desired delay to actual delay
cpc r27,r13
breq switchsample_000003 ; do nothing if the same
brlo indexdown_000003
ldi r17,$04 ; increment delay register (4 is used for stereo data)
add r12,r17 ; this makes it play forward at double speed
adc r13,r22 ; until desired delay is reached
rjmp switchsample_000003

indexdown_000003:

ldi r17,$02 ; decrement delay register (2 is used for stereo data)
sub r12,r17 ; this makes is play backwards until desired delay is reached
sbc r13,r22 ; r22 is cleared above

switchsample_000003: ; check state of rotary switch

dec r15 ; countdown switch counter
brne done_000003 ; finish off if not ready yet
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
cp r16,r31 ; check if location has changed
breq done_000003 ; finish off if no change
clr r30 ; reset jump register to new function if changed
mov r31,r16

done_000003:

movw r29:r28,r25:r24 ; move write address to read destination register
sub r28,r12 ; remove delay time
sbc r29,r13
reti ; return to waiting