welcome: please sign in
location: Diff for "DelayTutorialAsm"
Differences between revisions 11 and 14 (spanning 3 versions)
Revision 11 as of 2010-07-18 03:39:07
Size: 18754
Comment:
Revision 14 as of 2010-08-05 06:35:53
Size: 20366
Editor: guest
Comment:
Deletions are marked like this. Additions are marked like this.
Line 23: Line 23:
; * new data is written to the memory from the codec. the rotary encoder *
; * increments or decrements the read address, adjusting the delay time. *
; * new data is written to the memory from the codec. the delay time is set *
; * by the potentiometer (MOD1) on ADC0. the ADC is sampled 256 times, and *
; * the value is averaged to get the full 10 bit depth. this value is then *
; * compared to the current value, and a deadband of 1 lsb is used to *
; * eliminate glitches. if a large enough change has occurred to warrant *
; * updating the delay time, the value is stored as the desired delay. the *
; * actual delay is compared to this desired delay once per sample period, *
; * and the actual delay is either incremented or decremented to bring them *
; * closer together. the delay time is either incremented by 2 samples, or *
; * decremented by 1 sample, as the memory data pointer is always moving *
; * forward by 1 sample. this gives a relative increase of 1 sample or *
; * decrease of 2 samples, basically playing the memory forward at double *
; * speed, or going backwards at normal speed, until the desired delay time *
; * is reached. this process eliminates pops when the potentiometer (MOD1) *
; * is turned. *
Line 43: Line 56:
; * r15 switch sample counter     * ; * r15 switch/adc sample counter *
Line 50: Line 63:
; * r22 write address third byte/null register * ; * r22 null register (always equals $00) *
Line 60: Line 73:
; * t *
Line 63: Line 77:
; * NOTES: - all unprocessed (dry) raw data comes in off of the SPI port, via spdr
; - all processed (wet) data goes out over the SPI port, also via spdr
; - all external memory addressing happens over ports D and H
; - all data we are saving and reading back (like our delay audio) travels over ports A and C


; * NOTES: - all unprocessed (dry) audio data comes in from the SPI port, via
; the SPDR i/o registe
r
; - all processed (wet) audio goes out over the SPI port, also via
; the SPDR i/o registe
r
; - all external memory addressing happens over the PORTD and PORTH
; i/o registers
; - all external memory control happens over PORTG i/o register

; - all data we are saving and reading back (like our delayed audio)
; goes out over the PORT
A and PORTC i/o registers, and comes in
; via the PINA and PINC i/o registers
Line 76: Line 93:
; initiate data transfer to codec

sbi portb, portb0 ; set bit portb0  (aka DACLRC aka DAC sample rate left/right clock)
; ### initiate data transfer to the codec

sbi portb, portb0 ; set bit PORTB0 (aka DACLRC - DAC sample rate
                            ;
left/right clock)
Line 81: Line 99:
                            ;                   "DACLRC is an alignment clock that controls whether Left or Right channel
                            ; data is present
on DACTAT"

; (now on SPI - LEFT MSB) *********************************************************************************************

out spdr, r3 ; send out processed left channel msb (or whatever's currently in r3) to SPI data register
cbi portb, portb0 ; clear DACLRC

adiw r25:r24, 0x01 ; increment write address pointer by 0x01
adiw r29:r28, 0x01 ; increment  read address pointer by 0x01
ldi r22, 0x00 ; setup write high byte with null
                            ; "DACLRC is an alignment clock that controls
                            ;
whether Left or Right channel data is present
                            ;
on DACDAT"

; ### now on SPI - LEFT MSB OUT

out spdr, r3     ; send out processed left channel msb (or
                            ;
whatever's currently in r3) to SPI data register
cbi portb, portb0     ; clear DACLRC

adiw r25:r24, 0x01     ; increment write address pointer by 1
adiw r29:r28, 0x01     ; increment read address pointer by 1
ldi r22, 0x00     ; setup null register
Line 98: Line 118:
wait1_UID: ; wait to see if processed left channel msb has been sent

in r17, spsr ; move spi status register to r17 so we can look at it
sbrs r17, spif ; skip next instruction if the SPIF (spi interrupt flag) bit is set
wait1_UID: ; wait to see if processed left channel msb has
                           ;
been sent

in r17, spsr ; move SPSPR i/o register (SPI status register) to
                           ;
r17 so we evaluate it
sbrs r17, spif ; skip next instruction if the SPIF (SPIF interrupt
                           ;
flag) bit is set
Line 103: Line 126:
                           ;                    "When a serial transfer is complete, the SPIF flag is set"
rjmp wait1_UID ; aka: loop until SPIF is set
                           ; "When a serial transfer is complete, the SPIF
                           ;
flag is set"
rjmp wait1_UID ; keep checking until SPIF is set
Line 107: Line 131:
; ### after wait1, new spi data ready

in r7, spdr ; move spi data register into r7  (remember spdr is read/write, page 162)
                           ; this moves the incoming (dry) left channel msb to r7

; (end of wet/dry left msb transfer) ***********************************************************************************

; (
now on SPI - LEFT LSB) ***********************************************************************************
; ### after wait1, new SPI data ready

in r7, spdr ; move SPIDR (SPI data register) into r7
                           ;
(remember SPDR is read/write, page 162)
                           ; this moves the incoming (dry) left channel msb
                           ;
to r7

; ### end of wet/dry left msb transfer
; ###
now on SPI - LEFT LSB OUT
Line 120: Line 145:
out portd, r28 ; move read address lsb pointer to portd (see schematic)
sts porth, r29 ; move read address msb pointer to portH
                           ; **NOTE: - this is a special instruction because the I/O portH register is wayyy up there in the sram
                           ;             - 'out' completes in one cycle, 'sts' completes in two
out portd, r28 ; move read address lsb pointer to PORTD
sts porth, r29 ; move read address msb pointer to PORTH
                           ; **NOTE: - this is a special instruction because
                           ;
the i/o PORTH register is wayyy up there in the
                           ; sram - 'out' completes in one cycle, 'sts'
                           ;
completes in two
Line 128: Line 155:
                           ; DING!  your data is ready, please pick it up!
in r2, pina ; (see schematic) D0-7,  aka lsb, is on port A, now stored in r2
in r3, pinc ;             and D8-15, aka msb, is on port C, now stored in r3

; ###  left channel SRAM retrieve completed
                           ; DING! your data is ready, please pick it up!
in r2, pina ; D0-7, aka lsb, is on PORTA, now stored in r2
in r3, pinc ; D8-15, aka msb, is on PORTC, now stored in r3

; ### left channel SRAM retrieve completed
Line 144: Line 171:
in r17, spsr ; spi status reg. to r17 (looking familiar?) in r17, spsr ; SPI status register to r17 (looking familiar?)
Line 149: Line 176:
                           ;            - it can only move within 2k of memory (ie, can't jump all the way to the start, or end, of a long program)
                           ;            - it doesn't do anything to the stack (so if it loops a thousand times, the stack isn't going to overflow)
                           ;            - it takes two cycles

; ### after wait2 is finished, new spi data ready
                           ; - it can only move within 2k of memory (ie,
                           ;
can't jump all the way to the start, or end,
                           ;
of a long program)
                           ; - it doesn't do anything to the stack (so if
                           ;
it loops a thousand times, the stack isn't
                           ;
going to overflow)
                           ; - it takes two cycles

; ### after wait2 is finished, new SPI data ready
Line 156: Line 187:
                           ; **NOTE: that gives us both bytes of the incoming left channel, and both wet bytes have been sent
                           ;
we can now move on to the right channel

; (end of wet/dry left lsb transfer) ************************************************************************************

; (
now on SPI - RIGHT MSB) ************************************************************************************
                           ; **NOTE: that gives us both bytes of the
                           ;
incoming left channel, and both wet bytes have
                           ; been sent so
we can now move on to the right
                           ;
channel

; ### end of wet/dry left lsb transfer
; ###
now on SPI - RIGHT MSB OUT
Line 166: Line 198:
out portd, r24 ; update data address ports to reflect where we want to write
out portd, r24 ; update data address ports to reflect where we
                           ;
want to write
Line 169: Line 203:
out portg, r22 ; woah, portG? what's this? Check out the SRAM data sheet and the schematic:
                           ; r22 is currently 0x00, so we are pulling CE and WE low, and writing our high address bits to zero
                           ; CE (chip enable) and WE (write enable) are asserted low
out portg, r22 ; woah, PORTG? what's this? Check out the SRAM
                           ;
data sheet and the schematic:

                           ;
r22 is currently 0x00, so we are pulling CE
                           ; (Chip Enable)
and WE (Write Enable) low, and
                           ;
writing our high address bits to zero
Line 174: Line 211:
                           ;                     "Data on input pins io1-io16 is written on the rising edge of WE..."
                           ; "To avoid bus contention, external devices should drio i/o pins only after
                           ;
outputs have been disabled with OE (output enable) or WE"
                           ; "A read cycle is accomplished by asserting OE and CE, with WE high."

ldi r17, 0xFF ; prepare a salad of ones
out ddra, r17 ; send them to the portA direction register
out ddrC, r17 ; and to the portC direction register
                     ; (see ATmega3250P data sheet, page 65, 'Switching Between Input and Output')

out porta, r6 ; with these two 'out' instructions
out portc, r7 ; we send left channel dry data directly to the sram


sbi portg, portg2 ; and as soon as we pull WE (write enable) on portG_2 high,
                     ; zzztt!  a single audio sample is written into memory, just like that.

                           ; "Data on input pins IO1-IO16 are written on
                           ;
the rising edge of WE..."

                           ;
"To avoid bus contention, external devices
                           ; should drive IO
pins only after outputs have
                           ;
been disabled with OE (output enable) or WE"

                           ;
"A read cycle is accomplished by asserting OE
                           ;
and CE, with WE high."

ldi r17, 0xFF       ; prepare a salad of ones
out ddra, r17       ; send them to the PORTA direction register
out ddrC, r17       ; and to the PORTC direction register
                           ; to set the ports as output
                           ;
see ATmega3250P data sheet, page 65,
                           ;
'Switching Between Input and Output'

out porta, r6       ; with these two 'out' instructions
out portc, r7       ; we send left channel dry data to the SRAM

sbi portg, portg2       ; and as soon as we pull WE on PORTG2 high,
       ; zzztt! a single audio sample is written into
                           ;
memory, just like that.
Line 195: Line 237:

out ddra, r22 ; now, we happen to know that r22 contains a bunch of zeros
out ddrc, r22 ;
so we can use that register to set ports A and C back to an input state.

out ddra, r22        ; now, we happen to know that r22 contains a
out ddrc, r22 ;
bunch of zeros so we can use that register to
                           ; set PORTA and PORTC back to an in
put state.
Line 206: Line 246:
wait3_UID: ; meanwhile, back at the codec, we are still transferring the right channel lsb

in r17, spsr ; check out the spsr, check out the spif,
sbrs r17, spif ; we know what we're doing here now, right?
rjmp wait3_UID ; loop until transfer completed
wait3_UID:    ; meanwhile, back at the codec, we are still
                           ;
transferring the right channel lsb

in r17, spsr    ; check out the SPSR, check out the SPIF,
sbrs r17, spif    ; we know what we're doing here now, right?
rjmp wait3_UID    ; loop until transfer completed
Line 214: Line 255:
in r9, spdr ; recieve in (dry) right channel msb

; (end of wet/dry right msb transfer) ***********************************************************************************

; (
now on SPI - RIGHT LSB) ***********************************************************************************

out spdr, r4 ; send out (wet) right channel lsb
in r9, spdr    ; recieve in (dry) right channel msb

; ### end of wet/dry right msb transfer  ; ### now on SPI - RIGHT LSB OUT

out spdr, r4    ; send out (wet) right channel lsb
Line 223: Line 263:
out portd, r28 ; set up the address we want to read from
sts porth, r29 ; on ports d and h

nop
; killing time again...
nop ; two cycles, while the SRAM latches the address

                        ; and once more, ding! our data is now waiting on the SRAM data lines
in r4, pina ; right lsb
in r5, pinc ; right msb    (this is audio data we saved in the past)

out portd, r28    ; set up the address we want to read from
sts porth, r29    ; on PORTD and PORTH

nop
; killing time again...
nop    ; two cycles, while the SRAM latches the address

                           ; and once more, ding! our data is now waiting
                           ;
on the SRAM data lines
in r4, pina    ; right lsb
in r5, pinc    ; right msb (this is audio data we saved in the
                           ;
past)
Line 235: Line 278:
adiw r25:r24, 0x01 ; increment the write address (we're going to be using that pointer next) adiw r25:r24, 0x01    ; increment the write address (we're going to be
                           ;
using that pointer next)
Line 242: Line 286:
wait4_UID:      ; checking up on that SPI transfer wait4_UID: ; checking up on that SPI transfer
Line 246: Line 290:
rjmp wait4_UID      ; loop until SPIF is set rjmp wait4_UID ; loop until SPIF is set
Line 249: Line 293:
in r8, spdr      ; bring in right channel lsb

; (end of wet/dry right lsb transfer) ***********************************************************************************
; now that we have both bytes of the right channel dry audio, we can store it in the SRAM

in r8, spdr ; bring in right channel lsb

; ### end of wet/dry right lsb transfer

   
; now that we have both bytes of the right
                           ;
channel dry audio, we can store it in the
                           ;
SRAM...
Line 256: Line 304:
out portd, r24 ; give the sram the write address, lsb
sts porth, r25 ; now msb

out portg, r22
; pull WE low, (CE is already low, WE was high for read operations)
ldi r17, 0xFF ; prepare a bevy of ones
out ddra, r17 ; set porta as output
out ddrc, r17 ; set portc as output
out porta, r8 ; put the data on the ports, l
sb
out portc, r9 ; msb
sbi portg, portg2
; zzzt! pull WE high and write the data

out ddra, r22 ; reconfigure porta as input
out ddrc, r22 ; reconfigure portc as input
out portd, r24    ; give the SRAM the write address, lsb
sts porth, r25 ; now
msb

out portg, r22
; pull WE low, (CE is already low, WE was high
                           ;
for read operations)
ldi r17, 0xFF    ; prepare a bevy of ones
out ddra, r17    ; set PORTA as output
out ddrc, r17    ; set PORTC as output
out porta, r8 ; put the data on the ports, lsb
ou
t portc, r9 ; msb
sbi portg, portg2 ; zzzt! pull WE high and write the data

out ddra, r22    ; reconfigure PORTA as input
out ddrc, r22    ; reconfigure PORTC as input

DelayTutorial.asm

Writing code in assembly is a lot like that riddle about the farmer who has a chicken, a fox, and a bag of corn that he's trying to take across a river, but he only has one boat to do it with.

But on the bright side, none of our registers are going to eat each other, and we're not going to be attacked by any foxes! (i hope)

   1 ; ****************************************************************************
   2 ; * program: delay-16b-rotary.asm                                            *
   3 ; * UID = Tutorial - unique id to eliminate conflicts between variables,     *
   4 ; *       replace each instance of UID in the code with this unique id.      *
   5 ; * 16b address space (.7s delay time)                                       *
   6 ; * stereo data                                                              *
   7 ; * pot controlled delay time (0s - .7s)                                     *
   8 ; ****************************************************************************
   9 ; *                                                                          *
  10 ; * PROGRAM OVERVIEW                                                         *
  11 ; *                                                                          *
  12 ; * data is read in from memory and written to the codec at the same time    *
  13 ; * new data is written to the memory from the codec.  the delay time is set *
  14 ; * by the potentiometer (MOD1) on ADC0.  the ADC is sampled 256 times, and  *
  15 ; * the value is averaged to get the full 10 bit depth.  this value is then  *
  16 ; * compared to the current value, and a deadband of 1 lsb is used to        *
  17 ; * eliminate glitches.  if a large enough change has occurred to warrant    *
  18 ; * updating the delay time, the value is stored as the desired delay.  the  *
  19 ; * actual delay is compared to this desired delay once per sample period,   *
  20 ; * and the actual delay is either incremented or decremented to bring them  *
  21 ; * closer together.  the delay time is either incremented by 2 samples, or  *
  22 ; * decremented by 1 sample, as the memory data pointer is always moving     *
  23 ; * forward by 1 sample.  this gives a relative increase of 1 sample or      *
  24 ; * decrease of 2 samples, basically playing the memory forward at double    *
  25 ; * speed, or going backwards at normal speed, until the desired delay time  *
  26 ; * is reached.  this process eliminates pops when the potentiometer (MOD1)  *
  27 ; * is turned.                                                               *
  28 ; *                                                                          *
  29 ; * register usage - may be redefined in other sections                      *
  30 ; *                                                                          *
  31 ; * r0                                                                       *
  32 ; * r1                                                                       *
  33 ; * r2  left lsb out                                                         *
  34 ; * r3  left msb out                                                         *
  35 ; * r4  right lsb out                                                        *
  36 ; * r5  right msb out                                                        *
  37 ; * r6  left lsb in                                                          *
  38 ; * r7  left msb in                                                          *
  39 ; * r8  right lsb in                                                         *
  40 ; * r9  right msb in                                                         *
  41 ; * r10                                                                      *
  42 ; * r11                                                                      *
  43 ; * r12 desired delay lsb                                                    *
  44 ; * r13 desired delay msb                                                    *
  45 ; * r14                                                                      *
  46 ; * r15 switch/adc sample counter                                            *
  47 ; * r16 temporary swap register                                              *
  48 ; * r17 temporary swap register                                              *
  49 ; * r18                                                                      *
  50 ; * r19                                                                      *
  51 ; * r20                                                                      *
  52 ; * r21                                                                      *
  53 ; * r22 null register (always equals $00)                                    *
  54 ; * r23                                                                      *
  55 ; * r24 write address lsb                                                    *
  56 ; * r25 write address msb                                                    *
  57 ; * r26 actual delay lsb                                                     *
  58 ; * r27 actual delay msb                                                     *
  59 ; * r28 read address lsb                                                     *
  60 ; * r29 read address msb                                                     *
  61 ; * r30 jump location for interrupt lsb                                      *
  62 ; * r31 jump location for interrupt msb                                      *
  63 ; * t                                                                        *
  64 ; ****************************************************************************
  65 
  66 
  67 ; * NOTES: - all unprocessed (dry) audio data comes in from the SPI port, via
  68 ;            the SPDR i/o register
  69 ;          - all processed (wet) audio goes out over the SPI port, also via
  70 ;            the SPDR i/o register
  71 ;          - all external memory addressing happens over the PORTD and PORTH
  72 ;            i/o registers  
  73 ;          - all external memory control happens over PORTG i/o register
  74 ;          - all data we are saving and reading back (like our delayed audio)
  75 ;            goes out over the PORTA and PORTC i/o registers, and comes in
  76 ;            via the PINA and PINC i/o registers
  77 
  78 
  79 ; **********************
  80 ; **** PROGRAM START
  81 ; **********************
  82 
  83 ; ### initiate data transfer to the codec
  84 
  85 sbi portb, portb0           ; set bit PORTB0 (aka DACLRC - DAC sample rate
  86                             ; left/right clock)
  87                             ;
  88                             ; **NOTE: from WM8731 data sheet, page 36:
  89                             ; "DACLRC is an alignment clock that controls
  90                             ; whether Left or Right channel data is present
  91                             ; on DACDAT"
  92 
  93 ; ### now on SPI - LEFT MSB OUT
  94 
  95 out spdr, r3                ; send out processed left channel msb (or
  96                             ; whatever's currently in r3) to SPI data register
  97 cbi portb, portb0           ; clear DACLRC
  98 
  99 adiw r25:r24, 0x01          ; increment write address pointer by 1
 100 adiw r29:r28, 0x01          ; increment read address pointer by 1
 101 ldi  r22, 0x00              ; setup null register
 102 
 103 
 104 ; **********************
 105 ; **** wait1
 106 ; **********************
 107 
 108 wait1_UID:                 ; wait to see if processed left channel msb has
 109                            ; been sent
 110 
 111 in   r17, spsr             ; move SPSPR i/o register (SPI status register) to
 112                            ; r17 so we evaluate it
 113 sbrs r17, spif             ; skip next instruction if the SPIF (SPIF interrupt
 114                            ; flag) bit is set
 115                            ; **NOTE: from atmega3250P data sheet, page 162:
 116                            ; "When a serial transfer is complete, the SPIF
 117                            ; flag is set"
 118 rjmp wait1_UID             ; keep checking until SPIF is set
 119                            ; and then...
 120 
 121 ; ### after wait1, new SPI data ready
 122 
 123 in r7, spdr                ; move SPIDR (SPI data register) into r7
 124                            ; (remember SPDR is read/write, page 162)
 125                            ; this moves the incoming (dry) left channel msb
 126                            ; to r7
 127 
 128 ; ### end of wet/dry left msb transfer
 129 ; ### now on SPI - LEFT LSB OUT
 130 
 131 out spdr, r2               ; send the processed (wet) left lsb out
 132 
 133 ; ### retrieve stored left channel data from SRAM:
 134 
 135 out portd, r28             ; move read address lsb pointer to PORTD
 136 sts porth, r29             ; move read address msb pointer to PORTH
 137                            ; **NOTE: - this is a special instruction because
 138                            ; the i/o PORTH register is wayyy up there in the
 139                            ; sram - 'out' completes in one cycle, 'sts'
 140                            ; completes in two
 141 
 142 nop                        ; read address msb hits the port, now wait for  (1)
 143 nop                        ; a latch time of two cycles...                 (2)
 144 
 145                            ; DING! your data is ready, please pick it up!
 146 in r2, pina                ; D0-7, aka lsb, is on PORTA, now stored in r2
 147 in r3, pinc                ; D8-15, aka msb, is on PORTC, now stored in r3
 148 
 149 ; ### left channel SRAM retrieve completed
 150 
 151                            ; now we've got a little time to kill, so...
 152 adiw r29:r28, 0x01         ; increment read address pointer by 1
 153 
 154 
 155 ; **********************
 156 ; **** wait2
 157 ; **********************
 158 
 159 wait2_UID:                 ; wait to see if wet left channel lsb has been sent
 160 
 161 in   r17, spsr             ; SPI status register to r17 (looking familiar?)
 162 sbrs r17, spif             ; skip next if SPIF bit not set...
 163 rjmp wait2_UID             ; loop until SPIF set
 164 
 165                            ; **NOTE: and now a couple of words about rjmp:
 166                            ; - it can only move within 2k of memory (ie,
 167                            ;   can't jump all the way to the start, or end,
 168                            ;   of a long program)
 169                            ; - it doesn't do anything to the stack  (so if
 170                            ;   it loops a thousand times, the stack isn't
 171                            ;   going to overflow)
 172                            ; - it takes two cycles
 173 
 174 ; ### after wait2 is finished, new SPI data ready
 175 
 176 in r6, spdr                ; receive in dry left channel lsb
 177                            ; **NOTE: that gives us both bytes of the
 178                            ; incoming left channel, and both wet bytes have
 179                            ; been sent so we can now move on to the right
 180                            ; channel
 181 
 182 ; ### end of wet/dry left lsb transfer
 183 ; ### now on SPI - RIGHT MSB OUT
 184 
 185 out spdr, r5               ; send out (wet) right msb
 186 
 187 ; ### writing (dry) left channel to SRAM:
 188 
 189 out portd, r24             ; update data address ports to reflect where we
 190                            ; want to write
 191 sts porth, r25             ; remember 'out' and 'sts'?
 192 
 193 out portg, r22             ; woah, PORTG? what's this?  Check out the SRAM
 194                            ; data sheet and the schematic:
 195 
 196                            ; r22 is currently 0x00, so we are pulling CE
 197                            ; (Chip Enable) and WE (Write Enable) low, and
 198                            ; writing our high address bits to zero
 199 
 200                            ; **NOTE:  from AS7C4098 data sheet, page 2:
 201                            ; "Data on input pins IO1-IO16 are written on
 202                            ; the rising edge of WE..."
 203 
 204                            ; "To avoid bus contention, external devices
 205                            ; should drive IO pins only after outputs have
 206                            ; been disabled with OE (output enable) or WE"
 207 
 208                            ; "A read cycle is accomplished by asserting OE
 209                            ; and CE, with WE high."
 210 
 211 ldi r17, 0xFF              ; prepare a salad of ones
 212 out ddra, r17              ; send them to the PORTA direction register
 213 out ddrC, r17              ; and to the PORTC direction register
 214                            ; to set the ports as output
 215                            ; see ATmega3250P data sheet, page 65,
 216                            ; 'Switching Between Input and Output'
 217 
 218 out porta, r6              ; with these two 'out' instructions
 219 out portc, r7              ; we send left channel dry data to the SRAM
 220 
 221 sbi portg, portg2          ; and as soon as we pull WE on PORTG2 high,
 222                            ; zzztt! a single audio sample is written into
 223                            ; memory, just like that.
 224 
 225 ; ### left channel SRAM write completed
 226 
 227 out ddra, r22              ; now, we happen to know that r22 contains a
 228 out ddrc, r22              ; bunch of zeros so we can use that register to
 229                            ; set PORTA and PORTC back to an input state.
 230 
 231 
 232 ; **********************
 233 ; **** wait3
 234 ; **********************
 235 
 236 wait3_UID:                 ; meanwhile, back at the codec, we are still
 237                            ; transferring the right channel lsb
 238 
 239 in   r17, spsr             ; check out the SPSR, check out the SPIF,
 240 sbrs r17, spif             ; we know what we're doing here now, right?
 241 rjmp wait3_UID             ; loop until transfer completed
 242 
 243 ; ### end of wait3, new data ready!
 244 
 245 in r9, spdr                ; recieve in (dry) right channel msb
 246 
 247 ; ### end of wet/dry right msb transfer 
 248 ; ### now on SPI - RIGHT LSB OUT
 249 
 250 out spdr, r4               ; send out (wet) right channel lsb
 251 
 252 ; ### retrieve stored right channel data from SRAM
 253 
 254 out portd, r28             ; set up the address we want to read from
 255 sts porth, r29             ; on PORTD and PORTH
 256 
 257 nop                        ; killing time again...
 258 nop                        ; two cycles, while the SRAM latches the address
 259 
 260                            ; and once more, ding!  our data is now waiting
 261                            ; on the SRAM data lines
 262 in r4, pina                ; right lsb
 263 in r5, pinc                ; right msb (this is audio data we saved in the
 264                            ; past)
 265 
 266 ; ### right channel SRAM data retrieval completed
 267 
 268 adiw r25:r24, 0x01         ; increment the write address (we're going to be
 269                            ; using that pointer next)
 270 
 271 
 272 ; **********************
 273 ; **** wait4
 274 ; **********************
 275 
 276 wait4_UID:                 ; checking up on that SPI transfer
 277 
 278 in r17, spsr
 279 sbrs r17, spif
 280 rjmp wait4_UID             ; loop until SPIF is set
 281 
 282 ; ### end of wait4, more new data!
 283 
 284 in r8, spdr                ; bring in right channel lsb
 285 
 286 ; ### end of wet/dry right lsb transfer
 287 
 288                            ; now that we have both bytes of the right
 289                            ; channel dry audio, we can store it in the
 290                            ; SRAM...
 291 
 292 ; ### writing (dry) right channel to SRAM
 293 
 294 out portd, r24             ; give the SRAM the write address, lsb
 295 sts porth, r25             ; now msb
 296 
 297 out portg, r22             ; pull WE low, (CE is already low, WE was high
 298                            ; for read operations)
 299 ldi r17, 0xFF              ; prepare a bevy of ones
 300 out ddra, r17              ; set PORTA as output
 301 out ddrc, r17              ; set PORTC as output
 302 out porta, r8              ; put the data on the ports, lsb
 303 out portc, r9              ; msb
 304 sbi portg, portg2          ; zzzt!  pull WE high and write the data
 305 
 306 out ddra, r22              ; reconfigure PORTA as input
 307 out ddrc, r22              ; reconfigure PORTC as input
 308 
 309 
 310 ; **********************************************************************************
 311 ; **** check rotary encoder and adjust delay time
 312 ; **********************************************************************************
 313 ; * The rotary encoder is externally debounced, so we don't have to do that here.
 314 ; * You'll see it in the schematic labeled MOD2 on portJ0, portJ1, and portJ2.
 315 ; *
 316 ; * The encoder's pin1 is sampled on a transition from high to low on pin0.
 317 ; * if pin1 is high, a left turn occured, if pin1 is low, a right turn occured.
 318 ; **********************************************************************************
 319 
 320 dec r15                 ; well, let's do a little debouncing anyway
 321 brne adjust_UID         ; brne checks the Z register,
 322                         ; if r15 was not zero after the last operation, it will branch us to adjust_UID
 323 
 324 ldi r17, 0x40           ; prepare a constant in r17
 325 mov r15, r17            ; put 0x40 in the sample freq bin to catch all rising edges (results in 1.5ms sampletime)
 326 lds r17, pinj           ; move port J data into r17
 327 sbrs r17, PINJ0         ; skip next if PINJ0 is set
 328 rjmp edgecheck_UID      ; if it's not set, is it a falling edge?
 329 
 330 clt                     ; clear T reg (in SREG)
 331 rjmp switchsample_UID   ; done looking at mod2, look at the program selector
 332 
 333 ; **********************
 334 ; **** edgecheck
 335 ; **********************
 336 
 337 edgecheck_UID:                  ; checks for falling edge
 338 brts switchsample_UID           ; if the T flag in SREG is set, assume the edge was already detected
 339 set                             ; otherwise set the T flag
 340 sbrs r17, PINJ1                 ; check if PINJ1 is high
 341 rjmp upcount_UID                ; if PINJ0 has just gone low and PINJ1 is low, a right turn has transpired
 342                                 ; upcount will therefore increase the delay
 343                                 ; otherwise, PINJ1 is high and a left turn has transpired, so we should decrease the delay
 344 ; **** downcount
 345 ldi r17, 0x01                   ; load our decrement amount into r17  (0x01 = 256 samples = 0.006s)
 346 sub r13, r17                    ; decrement delay MSB
 347 
 348 rjmp switchsample_UID           ; done looking at mod2, look at the program selector
 349 
 350 ; **** upcount
 351 upcount_UID:                    ; increment delay register
 352 ldi r17, 0x01                   ; load increment amount into r17
 353 add r13, r17                    ; increment MSB
 354 
 355 
 356 ; **********************
 357 ; **** switchsample
 358 ; **********************
 359 
 360 switchsample_UID:               ; sample the program select dial
 361 
 362 lds  r31, pinj                  ; put switch data into jump location MSB reg
 363 andi r31, 0x78                  ; mask off rotary encoder 0b01111000
 364 ldi  r17, 0x02                  ; 0x02 into r17
 365 lsr  r31                        ; shift r31 to the right
 366 lsr  r31                        ; shift again
 367 add r31, r17                    ; convert switch position data to program memory location
 368 
 369 
 370 ; **********************
 371 ; **** adjust
 372 ; **********************
 373 
 374 adjust_UID:                     ; since we've only changed the desired delay in the previous section, we need to implement that delay
 375                                 ; this checks to see if the delay time is correct,
 376                                 ; and if it's not it makes an effort to move slightly closer to the correct delay
 377 
 378 andi r26, 0xFE                  ; is the delay time even?
 379 cp r26, r22                     ; compare actual delay lsb to zero
 380 cpc r27, r13                    ; compare with carry actual delay msb with desired delay msb
 381 breq done_UID                   ; If equal, head to done, yay!
 382 brsh indexdown_UID              ; If the same or higher, branch to indexdown
 383                                 ; otherwise, we can assume it is too low
 384 ; **** indexup
 385 adiw r27:r26, 0x04              ; so increment delay register by 0x04
 386 rjmp done_UID                   ; and head to the end
 387 
 388 ; **** indexdown
 389 indexdown_UID:
 390 sbiw r27:r26, 0x02              ; decrement delay reg by 0x02
 391 
 392 
 393 
 394 ; **********************
 395 ; **** done
 396 ; **********************
 397 
 398 done_UID:                       ; It's been a long hard row to hoe, but we did it!
 399                                 ; oh wait, what?  We're going to have to do it again?  from the beginning?
 400                                 ; but we still need to get our pointers all lined up!
 401 
 402 movw r29:r28, r25:r24           ; sync write destination and read address
 403 sub r28, r26                    ; now subtract by the delay in samples (first lsb)
 404 sbc r29, r27                    ; subtract msb with carry from previous
 405 
 406 reti                            ; return from interrupt so we can get back to our idling
 407 

MICrODEC

Microdec Software

DelayTutorialAsm (last edited 2010-08-21 01:53:49 by guest)