welcome: please sign in

Please enter your password of your account at the remote wiki below.
/!\ You should trust both wikis because the password could be read by the particular administrators.

Clear message
location: Delay6sMono

MICrODEC: Stock Functions

6s Mono Delay

This program performs a simple delay routine. It stores the incoming data from the codec, and plays back a delayed sample. The input data is mono, and is taken from the left channel. The output is also mono, and is presented on both the left and right channels. However, if you're using a mono plug, you can only mix in the dry signal on the left channel (as there is no input signal on the right).

The pot (MOD1) controls the delay time. It goes from 6ms to 6s. MOD2 does nothing for this program. Most analog delay pedals change the rate at which data is being clocked in and out, to change the delay time. This gives a smooth change in audio when the delay is varied, although it also changes the frequency resolution of the signal. To change the delay time in the MICrODEC, the easiest way is to just jump to the new delay time, although this gives an audible pop as the data abruptly switches. In this program, we increment the delay time (or decrement it) at a rate of one sample per sample, until it matches what you want it to be. This gives the effect of frequency doubling (or reversing) during delay transitions, which can be interesting sonically.

delay_6s_mono.asm


   1 ; program: delay-18b-pot-mono.asm
   2 ; UID = 000033 - unique id to eliminate conflicts between variables
   3 ; 18b address space (6s delay time)
   4 ; mono data (left in only, output on left and right)
   5 ; pot (MOD1) controlled delay time (6ms - 6s)
   6 
   7 ; program overview
   8 ;
   9 ; data is read in from memory and written out the codec at the same time
  10 ; new data is written to the memory from the codec.  ADC0 (MOD1) is read
  11 ; and averaged over 256 samples to reduce jitter.  this value is subtracted
  12 ; from the write address to create the desired read address.  if the actual
  13 ; read address doesnt match the desired read address, it is either
  14 ; incremented or decremented by one sample each sample period until it
  15 ; matches.  this reduces noise during delay time transitions.
  16 
  17 ; register usage - may be redefined in other sections
  18 ;
  19 ; r0  desired delay time fractional byte
  20 ; r1  
  21 ; r2  left/right lsb out
  22 ; r3  left/right msb out
  23 ; r4  
  24 ; r5  
  25 ; r6  left lsb in
  26 ; r7  left msb in
  27 ; r8  
  28 ; r9  
  29 ; r10 adc accumulator lsb
  30 ; r11 adc accumulator msb
  31 ; r12 actual delay lsb
  32 ; r13 actual delay msb
  33 ; r14 adc sample counter
  34 ; r15 switch sample counter
  35 ; r16 temporary swap register
  36 ; r17 temporary swap register
  37 ; r18 null register
  38 ; r19 adc accumulator fractional byte
  39 ; r20 temporary swap register
  40 ; r21 actual delay fractional byte
  41 ; r22 write address third byte
  42 ; r23 read address third byte
  43 ; r24 write address lsb
  44 ; r25 write address msb
  45 ; r26 desired delay lsb
  46 ; r27 desired delay msb
  47 ; r28 read address lsb
  48 ; r29 read address msb
  49 ; r30 jump location for interrupt lsb
  50 ; r31 jump location for interrupt msb
  51 ; t   
  52 
  53 ;program starts here first time
  54 ldi r30,$23 ; set jump location to program start
  55 clr r24 ; clear write register
  56 clr r25
  57 ldi r22,$00 ; setup write address high byte
  58 clr r18 ; setup r18 as null register for carry addition and ddr setting
  59 ldi r17,$ff ; setup r17 for ddr setting
  60 
  61 clear_000033: ; clear delay buffer
  62 ; eliminates static when first switching to the delay setting
  63 
  64 adiw r25:r24,$01 ; increment write register
  65 adc r22,r18 ; increment write third byte
  66 cpi r22,$04 ; check if full memory space has been cleared
  67 breq cleardone_000033 ; continue until end of buffer reached
  68 out portd,r24 ; set address
  69 sts porth,r25
  70 out portg,r22 ; pull ce low,we low,and set high bits of address
  71 out ddra,r17 ; set porta as output for data write
  72 out ddrc,r17 ; set portc as output for data write
  73 out porta,r18 ; set data
  74 out portc,r18 ; r18 is cleared above
  75 sbi portg,portg2 ; pull we high to write
  76 out ddra,r18 ; set porta as input for data lines
  77 out ddrc,r18 ; set portc as input for data lines
  78 rjmp clear_000033 ; continue clearing
  79 
  80 cleardone_000033: ; reset registers
  81 
  82 clr r24 ; clear write register
  83 clr r25
  84 ldi r22,$00 ; setup write address high byte
  85 clr r28 ; set read address to minimum delay
  86 ldi r29,$ff
  87 ldi r23,$07 ; setup read address high byte
  88 clr r21 ; set actual delay time to minimum delay
  89 ldi r16,$01
  90 mov r12,r16
  91 clr r13
  92 clr r2 ; initialize data output registers
  93 clr r3
  94 reti ; finish with initialization and wait for next interrupt
  95 
  96 ;program starts here every time but first
  97 ;initiate data transfer to codec
  98 sbi portb,portb0 ; toggle slave select pin
  99 out spdr,r3 ; send out left channel msb
 100 cbi portb,portb0
 101 
 102 ;increment sram addresses
 103 adiw r25:r24,$01 ; increment write address
 104 adc r22,r18 ; increment write third byte
 105 andi r22,$03 ; mask off unsed bits
 106 adiw r29:r28,$01 ; increment read address
 107 adc r23,r18 ; increment read third byte
 108 andi r23,$03 ; mask off unsed bits
 109 ori r23,$04 ; set we bit for reading
 110 
 111 wait1_000033: ; check if byte has been sent
 112 
 113 in r17,spsr
 114 sbrs r17,spif
 115 rjmp wait1_000033
 116 in r7,spdr ; recieve in left channel msb
 117 out spdr,r2 ; send out left channel lsb
 118 
 119 wait2_000033: ; check if byte has been sent
 120 
 121 in r17,spsr
 122 sbrs r17,spif
 123 rjmp wait2_000033
 124 in r6,spdr ; recieve in left channel lsb
 125 out spdr,r3 ; send out right channel msb
 126 
 127 ;write left channel data to sram
 128 out portd,r24 ; set address
 129 sts porth,r25
 130 out portg,r22 ; pull ce low,we low,and set high bits of address
 131 ldi r17,$ff
 132 out ddra,r17 ; set porta as output for data write
 133 out ddrc,r17 ; set portc as output for data write
 134 out porta,r6 ; set data
 135 out portc,r7
 136 sbi portg,portg2 ; pull we high to write
 137 out ddra,r18 ; set porta as input for data lines
 138 out ddrc,r18 ; set portc as input for data lines
 139 
 140 wait3_000033: ; check if byte has been sent
 141 
 142 in r17,spsr
 143 sbrs r17,spif
 144 rjmp wait3_000033
 145 in r9,spdr ; recieve in right channel msb
 146 out spdr,r2 ; send out right channel lsb
 147 
 148 ;get left channel data from sram
 149 out portg,r23 ; pull ce low,we high,oe low, and set high bits of address
 150 out portd,r28 ; set address
 151 sts porth,r29
 152 nop ; wait microcontroller setup time of 2 cycles
 153 nop
 154 in r2,pina ; get data
 155 in r3,pinc ; get data
 156 
 157 wait4_000033: ; check if byte has been sent
 158 
 159 in r17,spsr
 160 sbrs r17,spif
 161 rjmp wait4_000033
 162 in r8,spdr ; recieve in left channel lsb
 163 
 164 ; get delay settings
 165 lds r17,adcsra ; get adc control register
 166 sbrs r17,adif ; check if adc conversion is complete
 167 rjmp shift_000033 ; skip adc sampling
 168 lds r16,adcl ; get low byte adc value
 169 lds r17,adch ; get high byte adc value
 170 add r19,r16 ; accumulate adc samples
 171 adc r10,r17
 172 adc r11,r18 ; r18 is cleared above
 173 ldi r17,$f7
 174 sts adcsra,r17 ; clear interrupt flag
 175 dec r14 ; countdown adc sample clock
 176 brne shift_000033 ; get delay time if its been long enough
 177 ldi r17,$01 ; check if adc value is less than $000100
 178 cp r19,r18 ; r18 is cleared above
 179 cpc r10,r17
 180 cpc r11,r18
 181 brsh deadband_000033 ; check if adc value changed enough to update delay
 182 inc r10 ; set minimum delay to $000100 = 6ms
 183 clr r19
 184 
 185 deadband_000033: ; check for change in adc value
 186 
 187 movw r17:r16,r11:r10 ; move adc sample to temporary register
 188 mov r20,r19
 189 sub r20,r0 ; find difference between adc sample and desired delay time
 190 sbc r16,r26
 191 sbc r17,r27
 192 brsh check_000033 ; check for deadband if positive
 193 com r20 ; invert if negative
 194 com r16 ; using ones complement as it is faster, and only has 1 bit error
 195 com r17
 196 
 197 check_000033: ; check if difference is greater than deadband
 198 
 199 cpi r16,$01 ; check if difference is less than 1 lsb
 200 cpc r17,r18 ; r18 cleared above
 201 brlo empty_000033 ; do nothing if less than 1 lsb
 202 movw r27:r26,r11:r10 ; move adc sample to delay time if large enough change
 203 andi r19,$fe ; make sure delay time is even
 204 mov r0,r19
 205 
 206 empty_000033: ; empty accumulation registers and finish off
 207 
 208 clr r10 ; empty accumulation registers
 209 clr r11
 210 clr r19
 211 
 212 shift_000033: ; check if delay time is correct
 213 
 214 cp r0,r21 ; compare desired delay to actual delay
 215 cpc r26,r12
 216 cpc r27,r13
 217 breq switchsample_000033 ; do nothing if the same
 218 brlo indexdown_000033
 219 ldi r17,$02 ; increment delay register
 220 add r21,r17 ; this doubles playback speed until desired delay is reached
 221 adc r12,r18 ; r18 is cleared above
 222 adc r13,r18
 223 ldi r17,$03
 224 and r13,r17 ; mask off unused bits
 225 rjmp switchsample_000033
 226 
 227 indexdown_000033:
 228 
 229 subi r21,$01 ; decrement delay register
 230 sbc r12,r18 ; r18 is cleared above
 231 sbc r13,r18 ; this plays backwards until desired delay is reached
 232 ldi r17,$03
 233 and r13,r17 ; mask off unused bits
 234 
 235 switchsample_000033: ; check state of rotary switch
 236 
 237 dec r15
 238 brne done_000033
 239 lds r16,pinj ; get switch data
 240 andi r16,$78 ; mask off rotary switch
 241 lsr r16  ; adjust switch position to program memory location
 242 lsr r16
 243 ldi r17,$02
 244 add r16,r17
 245 cp r16,r31 ; check if location has changed
 246 breq done_000033 ; finish off if no change
 247 clr r30 ; reset jump register to new function if it changed
 248 mov r31,r16
 249 
 250 done_000033:
 251 
 252 movw r29:r28,r25:r24 ; move write address to read destination register
 253 mov r23,r22 ; move write third byte to read third byte
 254 sub r28,r21 ; subtract delay time
 255 sbc r29,r12
 256 sbc r23,r13
 257 andi r23,$03 ; mask off unsed bits
 258 ori r23,$04 ; set we bit for reading
 259 reti
 260