;****************************************************
;EE 476 - Final Project
.include "c:\windows\desktop\projects\8515def.inc" ;Uses the 8535 chip
;******************
;Register Defs
.def AnaLo =r4 ;ADC convert values
.def past =r5
.def past2 =r6
.def temp =r16 ;temporary value register
.def temp2 =r17
.def effect =r18 ;current effect
.def ADCFlag =r19 ;Tells if the ADC is finished or not
.def TXbusy =r20 ;transmit busy flag
.def RXchar =r21 ;a received character
.def parameterL=r22 ;low byte of input parameter
.def parameterH=r23 ;high byte of input parameter
;EQUATES
;MACROS
.macro outi ;out immediate macro
ldi temp, @1
out @0, temp
.endmacro
;timer schtuff
.equ timskVal=0b01000000 ;sets Timer1 Compare A match
.equ t1cAVal =0 ;no timer1 Output Stuff
.equ t1cBVal =0b00001001 ;clear on match, prescale = 1
.equ t1oAVal =666 ;6kHz sampling rate
;.equ t1oAVal =1200 ;300Hz sampling rate
;.equ t1oAVal =2400 ;Really Slow!!
;UART schtuff
.equ baud96 =25 ;9600 baud constant for 4Mhz crystal
;Effects
.equ wire =0 ;no effects
.equ inversion =1 ;inverting every other bit
.equ swapping =2 ;reverse high order bits with low order
.equ delay =3 ;delay is effect 1
.equ clipping =4 ;amplitude clipping
.equ echo =5 ;echo effect
.equ needsparameters =3 ;the lowest effect # that needs parameters
;port D bit definitions, outputs to ADC and input from it
.equ ADCSCLK = 5 ;ADC serial clock output
.equ ADCCS = 0 ;ADC chip select (active low)
.equ ADCDIN = 2 ;ADC serial data
.equ ADCDout = 3 ;ADC output
.equ ADCSTRB = 4 ;ADC STROBE output to signal end of conversion
;other stuff
.equ MaxDelay =15000
.equ Ack =0x55 ;Acknowledgement String
;*******************
;Data
.dseg
.org RAMEND+1
delayline: .byte 15000 ;the delay line
;*******************
;Code
.cseg
.org $0000
rjmp RESET ;reset entry vector
reti ;IRQ0
reti ;IRQ1
reti ;Timer 1 Capture
rjmp TIMER1A ;Timer 1 CompareA
reti ;Timer 1 CompareB
reti ;Timer 1 Overflow
reti ;timer0 overflow
reti ;SPI TX Complete
rjmp RXDONE ;UART RX Complete
reti ;UDR Empty
reti ;rjmp TXDONE ;UART TX Complete
reti ;Analog Compare
;**********RESET ISR
RESET:
;RAM setup
outi SPL, LOW(RAMEND)
outi SPH, HIGH(RAMEND)
outi MCUCR, 0b10000000 ;use external RAM
;Port setup
outi DDRD, 0b000100100 ;set bits 2 & 5 to outputs and all
outi portd, 0x00
outi DDRB, 0xFF ;make port B output
outi PORTB, 0xFF
;Timer 1 Setup
outi TIMSK, timskVal
outi TCCR1A, t1cAVal
outi TCCR1B, t1cBVal
outi OCR1AH, HIGH(t1oAVal)
outi OCR1AL, LOW(t1oAVal)
;setup UART -- enable TXempty & RXdone int, and RX, TX pins
outi UCR, 0b10011000
outi UBRR, baud96 ;set baud rate to 9600
;setup RAM Pointers
ldi ZL, LOW(delayline)
ldi ZH, HIGH(delayline)
;Initial Effect conditions
ldi effect, wire
ldi YL, LOW(delayline)
ldi YH, HIGH(delayline)
sei
MAIN:
tst ADCFlag ;Has the ADC given us an input yet?
breq MAIN
;**************ADC Conversion
READADC:
cbi portD, ADCSCLK ;clear the clock line
cbi portB, ADCCS ;chip select the ADC
ldi temp, 0b10001110 ;the ADC command word
;unipolar (channel1) single ended conversion
;with internal clocking
;Change this for different functions of the
;ADC such as bipolar conversion or external
;clocking.
ldi temp2,8 ;the bit counter
ADC_SENDCOMMAND:
rol temp ;shift out the 8-bit command
.SET _skipcc = PC+2
brcc _skipcc
sbi portD,ADCDin ;set the bit in Din
.set _skipcs = PC+2
brcs _skipcs
cbi portD, ADCDin ;clear the bit in Din
sbi PortD, ADCSCLK ;SCLK high
.SET _nextstep = PC+1 ;wait at least 200 nS
rjmp _nextstep
.SET _nextstep = PC+1
rjmp _nextstep
cbi PortD, ADCSCLK ;SCLK low
dec temp2
brne ADC_SENDCOMMAND
_WAITLOOP:
sbic portD, ADCSTRB ; wait until you receive a signal from strobe
rjmp _WAITLOOP
clr AnaLo ;refresh Main 3
ldi temp2, 10 ;shift in 8+2 bit result (2 leading 0's)
ADC_RECEIVEDATA:
clc ;first set the carry
sbi PortD, ADCSCLK ;SCLK high
.SET _nextstep = PC+1 ;wait at least 200 nS
rjmp _nextstep
.SET _nextstep = PC+1
rjmp _nextstep
cbi PortD, ADCSCLK ;SCLK low
sbis PinD, ADCDOUT ;if ADC data low is high, set carry
sec ;inverted since low turns led on
rol AnaLo ;shift carry into data buffer
dec temp2
brne ADC_RECEIVEDATA;repeat until all bits read
sbi PortB, ADCCS ;release ADC chip select
clr ADCFlag
;+++++
st Z+, AnaLo ;save input value, increment pointer
ldi temp, HIGH(delayline+MaxDelay) ;if reached end of delayline, go back to begining
cpi ZL, LOW(delayline+MaxDelay)
cpc ZH, temp
brne _chooseEffects
ldi ZL, LOW(delayline)
ldi ZH, HIGH(delayline)
;--------------------Choose Effects----------------------
_chooseEffects:
ld r0, Y+ ;load input value, increment value
_selector:
cpi effect, wire
breq _output
cpi effect, inversion
breq _inversion
cpi effect, swapping
breq _swap
cpi effect, delay
breq _output
cpi effect, clipping
breq _clipping
cpi effect, echo
breq _echo
;--------------------------------------------------------
_output:
ldi temp, 1
or r0, temp
out PORTB, r0 ;out to LEDs
ldi temp, HIGH(delayline+MaxDelay) ;if reached end of delayline, go back to begining
cpi YL, LOW(delayline+MaxDelay)
cpc YH, temp
brne _dojump
ldi YL, LOW(delayline)
ldi YH, HIGH(delayline)
rjmp _dojump
_dojump:
rjmp MAIN
_inversion:
sbrs YL, 0
com r0 ;inverts every other bit
rjmp _output
_swap:
swap r0
rjmp _output
_clipping:
cp r0, parameterL
brlt _lowclipping ;if below the low threshold, set value to threshold
cp r0, parameterH ;
brge _highclipping
rjmp _output
_lowclipping:
mov r0, parameterL
rjmp _output
_highclipping:
mov r0, parameterH
rjmp _output
_echo:
mov XL, YL
mov XH, YH
ldi temp, 1
ldi temp2, 0
sub XL, temp
sbc XH, temp2
mov temp, parameterL
mov temp2, parameterH
sub XL, temp
sbc XH, temp2
ldi temp, high(delayLine) ;check to see if X<0... if so, wrap around
cpi XL, low(delayLine)
cpc XH, temp
brge _processEcho
ldi temp, low(MaxDelay) ;if X<0, then add MaxDelay for wrap around
ldi temp2, high(MaxDelay)
add XL, temp
adc XH, temp2
_processEcho:
ld past, X
lsr past
mov past2, past
lsr past2
add past, past2
lsr past
lsr r0
add r0, past ;this is the current sample plus 75% of a previous sample
_echostage2:
mov temp, parameterL
mov temp2, parameterH
sub XL, temp
sbc XH, temp2
ldi temp, high(delayLine) ;check to see if X<0... if so, wrap around
cpi XL, low(delayLine)
cpc XH, temp
brge _processEcho2
ldi temp, low(MaxDelay) ;if X<0, then add MaxDelay for wrap around
ldi temp2, high(MaxDelay)
add XL, temp
adc XH, temp2
_processEcho2:
ld past, X
lsr past
lsr past
add r0, past ;this is the current sample plus 75% of a previous sample + 50% of a previous sample
rjmp _output
;****************Timer 1 A Compare Match
TIMER1A:
push temp
ser ADCFlag
;outi ADCSR, 0b11001001 ;Enable & Start ADC for one run at 2div prescale
pop temp
reti
;****************ADC Complete
;ADCDONE:
; ser ADCFlag ;sets the ADC done flag
; reti
;****************UART guys
; TX done -- buffer is empty
TXDONE: push temp
in temp, SREG ;save processor status
push temp
pop temp
out SREG, temp ;restore proc status
pop temp
reti ;back to pgm
; UART read a character
RXDONE: push temp
in temp, SREG ;save processor status
push temp
in RXchar, UDR ;get the character
; out UDR, RXchar ;echo character - for Hyperterminal only
; subi RXChar, 0x30 ;convert to decimal -- NEEDS to be for HYPERTERM
;Calculate effects
mov effect, RXchar
mov YL, ZL ;setup initial conditions for Y to current Z value
mov YH, ZH
cpi effect, needsparameters ;check to see if effect needs parameters
brlt InitEffects ;if no, skip parameter check.
;-------------------------Send/Receive Parameters--------------------
ldi temp, Ack ;acknowledgement string
mov RXChar, temp
out UDR, RXChar ;send acknowledgement
CharSent:
sbis USR, TXC ;check to see if transmit is complete
rjmp CharSent
cbi USR, TXC ;clear the transmit complete bit
ParamLRead:
sbis USR, RXC ;have we received the data yet?
rjmp ParamLRead
cbi USR, RXC ;clear the receive complete bit
in parameterL, UDR ;get the character
; subi parameterL, '0'
out PORTB, parameterL
ldi temp, Ack ;acknowledgement string
mov RXChar, temp
out UDR, RXChar ;send acknowledgement
NextCharSent:
sbis USR, TXC ;check to see if transmit is complete
rjmp NextCharSent
cbi USR, TXC ;clear the transmit complete bit
ParamHRead:
sbis USR, RXC ;have we received the data yet?
rjmp ParamHRead
cbi USR, RXC ;clear the receive complete bit
in parameterH, UDR ;get the character
; subi parameterH, '0'
out PORTB, parameterH
;-------------------------End of Send/Receive Parameters--------------------
InitEffects:
;wire?
cpi effect, wire
brne _inversionsetup
rjmp _endcase
_inversionsetup:
cpi effect, inversion
brne _delay
rjmp _endcase
_delay:;delay?
cpi effect, delay
brne _amplitudeclipping
sub YL, parameterL ;subtract the delay offset
sbc YH, parameterH
ldi temp, high(delayLine) ;check to see if Y<0... if so, wrap around
cpi YL, low(delayLine)
cpc YH, temp
brge _endcase
ldi temp, low(MaxDelay) ;if Y<0, then add MaxDelay for wrap around
ldi temp2, high(MaxDelay)
add YL, temp
adc YH, temp2
rjmp _endcase
_amplitudeclipping:
cpi effect, clipping
brne _echoEffect
rjmp _endcase
_echoEffect:
cpi effect, echo
brne _nexteffect
rjmp _endcase
_nexteffect:
_endcase:
pop temp
out SREG, temp ;restore proc status
pop temp
reti ;back to program