Full Version : The BKL Digital Guitar Tuner (ASM)
avr >>SOUND & MUSIC PROJECTS >>The BKL Digital Guitar Tuner (ASM)


AVR_Admin- 04-22-2006
Design of a Real-Time Digital Guitar Tuner

Steve Berman, Mark Krangle, Rich Levy

Introduction

The goal of this project is to design an algorithm for a real-time digital guitar tuner and implement it using an Atmel AT90S8535 microcontroller. Each of the six strings of a guitar has a unique fundamental frequency, and our goal is to measure this frequency and compare it to the correct frequency. This project combines digital filter design, analog amplifier design, and several data analysis techniques.

High level design

The microcontroller accepts push button inputs which allow the user to select which guitar string is being tuned. It then samples the input waveform at 3000 Hz using the 8535's on-board ADC. Each time a waveform sample is obtained, the following FIR (finite impulse response) filter algorithm is performed.

Link: http://instruct1.cit.cornell.edu/courses/e...an/project.html



AVR_Admin- 04-22-2006
CODE

.include "c:\tmp\8535def.inc"
 
.device  AT90S8535

;***** Subroutine Register Variables
;****WARNING!!!! DUPLICATE REGISTER NAMES!!!!!!!!!!!!


.def    mc8u    =r6    ;multiplicand
.def    mp8u    =r7    ;multiplier
.def    m8uL    =r7    ;result Low byte
.def    m8uH    =r8    ;result High byte


.def    addsubA0=r2    ;LSB of first operand and answer
.def    addsubA1=r3
.def    addsubA2=r4
.def    addsubA3=r5



.def    addsubB0=r7    ;LSB of second operand
.def    addsubB1=r8
.def    addsubB2=r9
.def    addsubB3=r10

.def    filtout0=r2    ;Current filter output (LSB)
.def    filtout1=r3
.def    filtout2=r4
.def    filtout3=r5    ;(MSB)


;*********zero crossing detecting registers
.def    old_sign    =r12
.def    sum_low     =r17
.def    sum_hi      =r18
.def    avg_count   =r13
.def    samp_count  =r11
.def    num_avg     =r6
.def    min_samp    =r8

;***** Temp Variables
.def    signbit =r21
.def    temp    =r22       ;8 bit temp variable    
.def    temp2   =r23        
.def    count   =r25       ;loop counter
.def    cur_pos =r16       ;current position of input in array
.def    signs   =r15
.def    save    =r14

;button reg
.def    button  =r24


;***** Regs for ADCval
.def    ADCvalc =r1    ;holds 8bit current ADC val

***********number of input values
.equ    NS  =20
.equ    NSp1    =21

;***** button assignments
.equ    lowE_str    =   0b00111110
.equ    A_str       =   0b00111101
.equ    D_str       =   0b00111011
.equ    G_str       =   0b00110111
.equ    B_str       =   0b00101111
.equ    HiE_str     =   0b00011111


; Numavs for each note
.equ    num_avg_lowE    =   16 ;number of half-wavelength averages
.equ    num_avg_A   =   22  
.equ    num_avg_D   =   29  
.equ    num_avg_G   =   39
.equ    num_avg_B   =   49
.equ    num_avg_HiE =   66

;**** DC_offsets per string
.equ    dc_off_lowE0    =   0xC0
.equ    dc_off_lowE1    =   0xD4
.equ    dc_off_lowE2    =   0x01
.equ    dc_off_lowE3    =   0x00

.equ    dc_off_B0   =   0x80
.equ    dc_off_B1   =   0x31
.equ    dc_off_B2   =   0x00
.equ    dc_off_B3   =   0x00

.equ    dc_off_A0   =   0xC0
.equ    dc_off_A1   =   0xD4
.equ    dc_off_A2   =   0x01
.equ    dc_off_A3   =   0x00

.equ    dc_off_D0   =   0x90
.equ    dc_off_D1   =   0x5F
.equ    dc_off_D2   =   0x01
.equ    dc_off_D3   =   0x00

.equ    dc_off_G0   =   0x20
.equ    dc_off_G1   =   0x4E
.equ    dc_off_G2   =   0x00
.equ    dc_off_G3   =   0x00

.equ    dc_off_HiE0 =   0x80
.equ    dc_off_HiE1 =   0x01
.equ    dc_off_HiE2 =   0x00
.equ    dc_off_Hie3 =   0x00


;*** Minimum rising edge time for each string
.equ    lowE_edge   =   29
.equ    A_edge      =   22
.equ    D_edge      =   16
.equ    G_edge      =   13
.equ    B_edge      =   8
.equ    HiE_edge    =   6


;**** Output threshold levels per string
.equ    lowE_TH1    =   38 ;685   ; -15%
.equ    lowE_TH2    =   34 ;647   ; -10%
.equ    lowE_TH3    =   25 ;613   ; -5%
.equ    lowE_TH4    =   11 ;588   ; -1%
.equ    lowE_TH5    =   12 ;577   ; +1%
.equ    lowE_TH6    =   25 ;555   ; +5%
.equ    lowE_TH7    =   24 ;530   ; +10%
.equ    lowE_TH8    =   485;  ; +15%

.equ    B_TH1   =   39 ;700   ; -15%
.equ    B_TH2   =   34 ;661   ; -10%
.equ    B_TH3   =   26 ;627   ; -5%
.equ    B_TH4   =   12 ;601   ; -1%
.equ    B_TH5   =   22 ;589   ; +1%
.equ    B_TH6   =   26 ;567   ; +5%
.equ    B_TH7   =   23 ;541   ; +10%
.equ    B_TH8   =   505;518   ; +15%


.equ    A_TH1   =   39 ;706   ; -15%
.equ    A_TH2   =   35 ;667   ; -10%
.equ    A_TH3   =   26 ;632   ; -5%
.equ    A_TH4   =   12 ;606   ; -1%
.equ    A_TH5   =   23 ;594   ; +1%
.equ    A_TH6   =   26 ;571   ; +5%
.equ    A_TH7   =   23 ;545   ; +10%
.equ    A_TH8   =   500;522   ; +15%

.equ    D_TH1   =   39 ;697   ; -15%
.equ    D_TH2   =   34 ;658   ; -10%
.equ    D_TH3   =   25 ;624   ; -5%
.equ    D_TH4   =   12 ;599   ; -1%
.equ    D_TH5   =   23 ;587   ; +1%
.equ    D_TH6   =   25 ;564   ; +5%
.equ    D_TH7   =   24 ;539   ; +10%
.equ    D_TH8   =   497;515   ; +15%

.equ    G_TH1   =   39 ;702   ; -15%
.equ    G_TH2   =   35 ;663   ; -10%
.equ    G_TH3   =   25 ;628   ; -5%
.equ    G_TH4   =   12 ;603   ; -1%
.equ    G_TH5   =   22 ;591   ; +1%
.equ    G_TH6   =   26 ;569   ; +5%
.equ    G_TH7   =   24 ;543   ; +10%
.equ    G_TH8   =   512;519   ; +15%


.equ    hiE_TH1 =   40 ;707   ; -15%
.equ    hiE_TH2 =   35 ;667   ; -10%
.equ    hiE_TH3 =   31 ;632   ; -5%
.equ    hiE_TH4 =   6  ;601   ; -1%
.equ    hiE_TH5 =   23 ;595   ; +1%
.equ    hiE_TH6 =   26 ;572   ; +5%
.equ    hiE_TH7 =   24 ;546   ; +10%
.equ    hiE_TH8 =   514;522   ; +15%


;seven segment display equ's
.equ    sevlowE =   0b00111110
.equ    sevA =      0b01011111
.equ    sevD =      0b01111001
.equ    sevG =      0b01101111
.equ    sevB =      0b01111100
.equ    sevHiE =    0b10111110


.dseg
;*****coeff table  
lowEb:  .BYTE   11
lowEsign: .BYTE 3

Ab: .BYTE   11
Asign:  .BYTE   3

Db: .BYTE   11
Dsign:  .BYTE   3

Gb: .BYTE   26
Gsign:  .BYTE   7

Bb: .BYTE   26
Bsign:  .BYTE   7

HiEb:   .BYTE   26
HiEsign: .BYTE 7

ADCInputs: .BYTE NS

;***** Initialization
.cseg
.org $0000
   rjmp    RESET  ;reset entry vector
   reti       ;Ext int req0  
   reti       ;Ext int req1
   reti       ;Timer/Counter2 compare match
   reti       ;Timer/Counter2 Ovfl
   reti       ;Timer/Counter1 Capture event
   rjmp    cp_match;Timer/Counter1 Compare match A
   reti       ;Timer/Counter1 Compare match B
   reti       ;Timer/Counter1 Ovfl
   reti       ;Timer/Counter0 Ovfl
   reti       ;Serial Transfer Complete
   reti       ;UART, Rx Complete
   reti       ;UART Data Reg Empty
   reti       ;Uart Tx complete
   reti       ;ADC conversion complete
   reti       ;EEPROM ready
   reti       ;Analog comparator


RESET:  ldi temp, LOW(RAMEND);setup stack pointer
   out     SPL, temp
   ldi temp, HIGH(RAMEND)
   out SPH, temp


;set up coefficients in SRAM

;lowE coefficients
   ldi     ZL,LOW(lowEb)
   ldi ZH,HIGH(lowEb)
   ldi temp,1
   ST  Z+,temp
   ldi temp,0
   ST  Z+,temp
   ldi temp,3
   ST  Z+,temp
   ldi temp,10
   ST  Z+,temp
   ldi temp,21
   ST  Z+,temp
   ldi temp,37
   ST  Z+,temp
   ldi temp,55
   ST  Z+,temp
   ldi temp,74
   ST  Z+,temp
   ldi temp,90
   ST  Z+,temp
   ldi temp,101
   ST  Z+,temp
   ldi temp,105
   ST  Z+,temp
       
;setup signs for lowE
   ldi     XL,LOW(lowEsign)
   ldi XH,HIGH(lowEsign)
   ldi temp,0x80
   ST  X+,temp
   ldi temp,0x00
   ST  X+,temp
   ldi temp,0x08
   ST  X+,temp
   


;A coefficients
   ldi     ZL,LOW(Ab)
   ldi ZH,HIGH(Ab)
   ldi temp,7
   ST  Z+,temp
   ldi temp,6
   ST  Z+,temp
   ldi temp,6
   ST  Z+,temp
   ldi temp,2
   ST  Z+,temp
   ldi temp,9
   ST  Z+,temp
   ldi temp,27
   ST  Z+,temp
   ldi temp,51
   ST  Z+,temp
   ldi temp,78
   ST  Z+,temp
   ldi temp,103
   ST  Z+,temp
   ldi temp,120
   ST  Z+,temp
   ldi temp,126
   ST  Z+,temp
       
;setup signs for A
   ldi     XL,LOW(Asign)
   ldi XH,HIGH(Asign)
   ldi temp,0xf0
   ST  X+,temp
   ldi temp,0x00
   ST  X+,temp
   ldi temp,0x78
   ST  X+,temp


;D coefficients
   ldi     ZL,LOW(Db)
   ldi ZH,HIGH(Db)
   ldi temp,11
   ST  Z+,temp
   ldi temp,13
   ST  Z+,temp
   ldi temp,18
   ST  Z+,temp
   ldi temp,21
   ST  Z+,temp
   ldi temp,15
   ST  Z+,temp
   ldi temp,2
   ST  Z+,temp
   ldi temp,32
   ST  Z+,temp
   ldi temp,68
   ST  Z+,temp
   ldi temp,104
   ST  Z+,temp
   ldi temp,130
   ST  Z+,temp
   ldi temp,140
   ST  Z+,temp
       
;setup signs for D
   ldi     XL,LOW(Dsign)
   ldi XH,HIGH(Dsign)
   ldi temp,0xf8
   ST  X+,temp
   ldi temp,0x00
   ST  X+,temp
   ldi temp,0xf8
   ST  X+,temp

;G coefficients
   ldi     ZL,LOW(Gb)
   ldi ZH,HIGH(Gb)
   ldi temp,6
   ST  Z+,temp
   ldi temp,12
   ST  Z+,temp
   ldi temp,23
   ST  Z+,temp
   ldi temp,37
   ST  Z+,temp
   ldi temp,44
   ST  Z+,temp
   ldi temp,36
   ST  Z+,temp
   ldi temp,8
   ST  Z+,temp
   ldi temp,38
   ST  Z+,temp
   ldi temp,88
   ST  Z+,temp
   ldi temp,128
   ST  Z+,temp
   ldi temp,143
   ST  Z+,temp
       
;setup signs for G
   ldi     XL,LOW(Gsign)
   ldi XH,HIGH(Gsign)
   ldi temp,0xf7
   ST  X+,temp
   ldi temp,0x03
   ST  X+,temp
   ldi temp,0xf8
   ST  X+,temp


;setup coefficients for B
   ldi     ZL,LOW(Bb)
   ldi ZH,HIGH(Bb)
   ldi temp,5
   ST  Z+,temp
   ldi temp,1
   ST  Z+,temp
   ldi temp,13
   ST  Z+,temp
   ldi temp,34
   ST  Z+,temp
   ldi temp,57
   ST  Z+,temp
   ldi temp,65
   ST  Z+,temp
   ldi temp,46
   ST  Z+,temp
   ldi temp,2
   ST  Z+,temp
   ldi temp,66
   ST  Z+,temp
   ldi temp,121
   ST  Z+,temp
   ldi temp,143
   ST  Z+,temp

;setup sign bit for B
   ldi     XL,LOW(Bsign)
   ldi XH,HIGH(Bsign)
   ldi temp,0x7E
   ST  X+,temp
   ldi temp,0x03
   ST  X+,temp
   ldi temp,0xf0
   ST  X+,temp


;setup coefficients for HiE
   ldi     ZL,LOW(HiEb)
   ldi ZH,HIGH(HiEb)
   ldi temp,8
   ST  Z+,temp
   ldi temp,13
   ST  Z+,temp
   ldi temp,17
   ST  Z+,temp
   ldi temp,5
   ST  Z+,temp
   ldi temp,28
   ST  Z+,temp
   ldi temp,71
   ST  Z+,temp
   ldi temp,89
   ST  Z+,temp
   ldi temp,56
   ST  Z+,temp
   ldi temp,24
   ST  Z+,temp
   ldi temp,107
   ST  Z+,temp
   ldi temp,143
   ST  Z+,temp

;setup sign bit for HiE
   ldi     XL,LOW(HiEsign)
   ldi XH,HIGH(HiEsign)
   ldi temp,0x0F
   ST  X+,temp
   ldi temp,0x07
   ST  X+,temp
   ldi temp,0x80
   ST  X+,temp

  ;set up current position in array
   ldi cur_pos, 0
   
  ;set up port B to run LEDS
   ser temp       ;set PORTB to be
   out DDRB,temp  ;all outputs to LEDs
   clr temp
   out PORTB, temp

  ;set up port C to run 7seg display
   ser temp       ;set PORTB to be
   out DDRC,temp  ;all outputs to LEDs
   

  ;set up portD for inputs
   clr temp
   out DDRD,temp
   


  ;initialize vars for display code
   clr sum_low        ;reset sum_hi / sum_low
   clr sum_hi
   ldi temp2, 1
   mov avg_count, temp2   ;reset average counter
   clr old_sign

  ;clear ADCval register
   clr ADCvalc
   

  ;set up analog converter to read channel zero
   ldi temp, 0
   out ADMUX, temp

  ;enable and set up ADC
  ;prescaler = 64
  ;ADC free run mode disbaled
  ;ADC start conversion off (turn on when ready)
   ldi temp, 0b10000110
   out ADCSR, temp
   
   
   
;start the ADC initalization
   ldi temp, 0b01000000   ;start A to D conversion    
   in  temp2, ADCSR
   or  temp, temp2
   out ADCSR, temp

;spin until the ADC is finished
rwait:  in      temp, ADCSR    ;wait for A to D done
       sbrc    temp, 6        ;by checking ADSC bit
       rjmp    rwait          ;this bit is cleared by the AtoD hardware
   
   clt        ;clear t bit

  ;set up timers and match register
  ;enable compareA match register int
   ldi temp, 0b00010000
   out TIMSK, temp

  ;set match regs for fs=3000hz (2667ticks for fs=2999.6)
   ldi temp, 0x0A ;set the match A register to
   out OCR1AH, temp   ;
   ldi temp, 0x6B ;2667 = 0x0A6B
   out OCR1AL, temp
   
  ;set prescaler to 1 and clear on compare/match
   ldi temp, 0b00001001    
   out TCCR1B, temp
   
   
   ldi temp2,0xff
   out PORTC,temp2
   sei;enable all interrupts  
;**************do button stuff

spin:   in  temp, PIND
   andi    temp, 0b00111111    
   cpi temp, 0x3f
   breq    spin

crunch:

   in  temp,PIND
   andi    temp,0b00111111
start:  
  ;point Yreg to correct coeff sets
   cpi temp, LowE_str
   brne    check1
   ldi     YL, LOW(lowEb) ;
       ldi     YH, HIGH(lowEb);shifted becuase pgm memory is words
   ldi XL, LOW(lowEsign)
   ldi     XH, HIGH(lowEsign)
   LD  signs,X+
   ldi temp2,sevlowE
   out     PORTC,temp2
check1: cpi temp, A_str
   brne    check2
   ldi     YL, LOW(Ab) ;
       ldi     YH, HIGH(Ab);shifted becuase pgm memory is words
   ldi     XL, LOW(Asign) ;
       ldi     XH, HIGH(Asign)
   LD  signs,X+
   ldi temp2,sevA  
   out     PORTC,temp2
check2: cpi temp, D_str
   brne    check3
   ldi     YL, LOW(Db) ;
       ldi     YH, HIGH(Db);shifted becuase pgm memory is words
   ldi     XL, LOW(Dsign) ;
       ldi     XH, HIGH(Dsign);
   LD  signs,X+
   ldi temp2,sevD
   out     PORTC,temp2
check3: cpi temp, G_str
   brne    check4
   ldi     YL, LOW(Gb) ;
       ldi     YH, HIGH(Gb);shifted becuase pgm memory is words
   ldi     XL, LOW(Gsign) ;
       ldi     XH, HIGH(Gsign);
   LD  signs,X+
   ldi temp2,sevG
   out     PORTC,temp2
check4: cpi temp, B_str
   brne    check5
   ldi     YL, LOW(Bb) ;
       ldi     YH, HIGH(Bb);shifted becuase pgm memory is words
   ldi     XL, LOW(Bsign) ;
       ldi     XH, HIGH(Bsign);
   LD  signs,X+
   ldi temp2,sevB
   out     PORTC,temp2
check5: cpi temp, HiE_str
   brne    check_done
   ldi     YL, LOW(HiEb) ;
       ldi     YH, HIGH(HiEb);shifted becuase pgm memory is words
   ldi     XL, LOW(HiEsign) ;
       ldi     XH, HIGH(HiEsign);
   LD  signs,X+
   ldi temp2,sevHiE
   out     PORTC,temp2
check_done:
   andi    temp, 0b00111111
   cpi temp,0x3f
   brne    really_done
   mov temp,button
   rjmp    start
   
really_done:
   mov button,temp
       
   clr filtout0
   clr filtout1
   clr filtout2
   clr filtout3
   
   
;loop counter setup
   clr     count
   
init:  

  ;set z pointer the oldest input in array
   ldi ZL,LOW(ADCInputs);
   ldi ZH, HIGH(ADCInputs);
   clr temp2
   add ZL,cur_pos
   adc ZH,temp2


  ;ldi    temp2,1
  ;mov    temp,cur_pos
  ;sub    temp, temp2
  ;cpi    temp,0
  ;brge   place
  ;ldi    temp,NSP1
;place: clr temp2
  ;add    ZL,temp
  ;adc    ZH,temp2
   
   ldi signbit, 128   ;only MSB high
   clr addsubB2   ;clear upper bits of add/sub operand
   clr     addsubB3




loop:  

   cpi count, NS  ;is the input comming from the ADC?
   brne    get_input
   
await:  
   brtc    await      ;wait if t bit is cleared
   in      temp, ADCSR    ;wait for A to D done        
   sbrc    temp, 6        ;by checking ADSC bit
   rjmp    await          ;this bit is cleared by the AtoD hardware
   clt        ;clear the t bit in the status register
   in  temp, ADCL
   in  temp2, ADCH
   ror temp2
   ror temp
   ror     temp2
   ror temp
  ;store new input in Ram
   cp  count,cur_pos
   breq    jmpit
   rjmp    normal
jmpit:  adiw    ZL,NS
   st  Z,temp
   sbiw    ZL,NS
   rjmp    get_input
normal: st  -Z,temp
   adiw    ZL,1
       

;get old ADCinput from RAM
get_input:  
   cp  count,cur_pos  ;when count equals cur_pos the z pointer rolls over
   brne    noprob
   adiw    ZL,NSP1
noprob: LD  mc8u,-Z
   
;get coefficent from RAM
   cpi count,11
   brsh    countdown
   LD  mp8u,Y+
   rjmp    norm_count
   
countdown:
   cpi count,11
   brne    countdown_1
   sbiw    YL,1
countdown_1:
   LD  mp8u,-Y
norm_count:

;Get sign
   cpi count,8
   breq    new_signs
   cpi count,16
   breq    new_signs
   cpi count,24
   breq    new_signs
   rjmp    start_crunchin

new_signs:
   LD  signs, X+

start_crunchin:
   rcall   mpy8u
   mov temp, signbit
   and temp, signs
   breq    add_term
   rcall   sub32
   rjmp    cont_crunchin
add_term:
   rcall   add32
cont_crunchin:
   cpi signbit, 1
   breq    reload
   lsr signbit
   rjmp    sign_done
reload: ldi signbit, 128

sign_done:
   inc count
   cpi count,NSP1
   brne    loop
************freq counting stuff

; zero-crossing detect and freq. average
;
;after 16-bit current output has been determined...
;first, remove offset

;get correct constants for averaging and dc offset per string
   cpi button, LowE_str
   brne    check1a
   ldi temp,   dc_off_lowE0
   mov addsubB0, temp
   ldi temp,   dc_off_lowE1
   mov addsubB1, temp
   ldi temp,   dc_off_lowE2
   mov addsubB2, temp
   ldi temp,   dc_off_lowE3
   mov addsubB3, temp
   ldi temp, num_avg_lowE
   mov num_avg, temp
   ldi temp, lowE_edge
   mov min_samp, temp  
   
check1a:
   cpi button, A_str
   brne    check2a
   ldi temp,   dc_off_A1
   mov addsubB0, temp
   ldi temp,   dc_off_A1
   mov addsubB1, temp
   ldi temp,   dc_off_A2
   mov addsubB2, temp
   ldi temp,   dc_off_A3
   mov addsubB3, temp
   ldi temp, num_avg_A
   mov num_avg, temp
   ldi temp, A_edge
   mov min_samp, temp  
check2a:
   cpi button, D_str
   brne    check3a
   ldi temp,   dc_off_D0
   mov addsubB0, temp
   ldi temp,   dc_off_D1
   mov addsubB1, temp
   ldi temp,   dc_off_D2
   mov addsubB2, temp
   ldi temp,   dc_off_D3
   mov addsubB3, temp
   ldi temp, num_avg_D
   mov num_avg, temp
   ldi temp, D_edge
   mov min_samp, temp  
check3a:
   cpi button, G_str
   brne    check4a
   ldi temp,   dc_off_G0
   mov addsubB0, temp
   ldi temp,   dc_off_G1
   mov addsubB1, temp
   ldi temp,   dc_off_G2
   mov addsubB2, temp
   ldi temp,   dc_off_G3
   mov addsubB3, temp
   ldi temp, num_avg_G
   mov num_avg, temp
   ldi temp, G_edge
   mov min_samp, temp  
check4a:
   cpi button, B_str
   brne    check5a
   ldi temp,   dc_off_B0
   mov addsubB0, temp
   ldi temp,   dc_off_B1
   mov addsubB1, temp
   ldi temp,   dc_off_B2
   mov addsubB2, temp
   ldi temp,   dc_off_B3
   mov addsubB3, temp
   ldi temp, num_avg_B
   mov num_avg, temp
   ldi temp, B_edge
   mov min_samp, temp  
check5a:
   cpi button, HiE_str
   brne    check_donea
   ldi temp,   dc_off_HiE0
   mov addsubB0, temp
   ldi temp,   dc_off_HiE1
   mov addsubB1, temp
   ldi temp,   dc_off_HiE2
   mov addsubB2, temp
   ldi temp,   dc_off_HiE3
   mov addsubB3, temp
   ldi temp, num_avg_HiE
   mov num_avg, temp
   ldi temp, HiE_edge
   mov min_samp, temp  
check_donea:
   rcall   sub32      ;subtract DC offset from filter output
count_freq:
   ldi temp, 1    ;set temp according to sign of filtout
   sbrs    filtout3, 7;if filtout < 0, temp = 1
   ldi temp, 0    ;if filtout > 0, temp = 0

   cp  temp, old_sign ;look for zero-crossing
   brne    sign_change;branch if zero-crossind detected
false_edge:
   inc samp_count ;increment sample counter (# samples since last zero-crossing)
   rjmp    count_freq_done

sign_change:
   sbrc    filtout3, 7
   rjmp    false_edge
   cp  samp_count, min_samp
   brmi    false_edge
                  ;at this point, rising edge has been detected
   ldi temp2, 0       ;8 bit plus 16 bit
   add sum_low, samp_count;add lower bytes
   adc sum_hi, temp2      ;add carry to hi byte
   ldi temp2, 1       ;reset samp_count
   mov samp_count, temp2
   inc avg_count      ;increment average counter
   cp  num_avg, avg_count ;compare average count to number of averages
   brne    count_freq_done    ; branch if average counter is less than/equal to num_avg
                  ;average counter > num_avg
   
  ;Display code for each string

   rcall Display_code
   
   clr sum_low        ;reset sum_hi / sum_low
   clr sum_hi
   ldi temp2, 1
   mov avg_count, temp2   ;reset average counter
   
count_freq_done:
   mov old_sign, temp



      ;DISPLAY AND AVERAGING CODE!!!!!

;decrement current position
   dec cur_pos        ;increment position of most recent sample
   cpi cur_pos, -1
   brne    go_1
   subi    cur_pos,-NSP1
go_1:   rjmp    crunch
   

       
   



;**** timer 1 compare A match
cp_match:
   in  save, SREG

   ldi temp, 0b01000000   ;start A to D conversion    
   in  temp2, ADCSR
   or  temp, temp2
   out ADCSR, temp

                  ;sets the T flag in status reg
   out SREG, save
   set
   reti    






;***** 32-bit Add function, result in addsubA0..3
;***** Code
add32:  add addsubA0, addsubB0     ;Add low bytes
   adc addsubA1, addsubB1     ;Add high bytes with carry
   adc addsubA2, addsubB2
   adc addsubA3, addsubB3
   ret

;***** 32-bit Subtract function, result in addsubA0..3 (A-B)
;***** Code
sub32:  sub addsubA0,addsubB0      ;Subtract low bytes
   sbc addsubA1,addsubB1      ;Add high byte with carry
   sbc addsubA2,addsubB2
   sbc addsubA3,addsubB3
   ret

;***************************************************************************
;*
;* "mpy8u" - 8x8 Bit Unsigned Multiplication
;*
;* This subroutine multiplies the two register variables mp8u and mc8u.
;* The result is placed in registers m8uH, m8uL
;*  
;* Number of words  :34 + return
;* Number of cycles :34 + return
;* Low registers used   :None
;* High registers used  :3 (mc8u,mp8u/m8uL,m8uH)    
;*
;* Note: Result Low byte and the multiplier share the same register.
;* This causes the multiplier to be overwritten by the result.
;*
;***************************************************************************

;***** Code

mpy8u:  clr m8uH       ;clear result High byte
   lsr mp8u       ;shift multiplier
   
   brcc    noad80     ;if carry set
   add m8uH,mc8u  ;    add multiplicand to result High byte
noad80: ror m8uH       ;shift right result High byte
   ror m8uL       ;rotate right result L byte and multiplier

   brcc    noad81     ;if carry set
   add m8uH,mc8u  ;    add multiplicand to result High byte
noad81: ror m8uH       ;shift right result High byte
   ror m8uL       ;rotate right result L byte and multiplier

   brcc    noad82     ;if carry set
   add m8uH,mc8u  ;    add multiplicand to result High byte
noad82: ror m8uH       ;shift right result High byte
   ror m8uL       ;rotate right result L byte and multiplier

   brcc    noad83     ;if carry set
   add m8uH,mc8u  ;    add multiplicand to result High byte
noad83: ror m8uH       ;shift right result High byte
   ror m8uL       ;rotate right result L byte and multiplier

   brcc    noad84     ;if carry set
   add m8uH,mc8u  ;    add multiplicand to result High byte
noad84: ror m8uH       ;shift right result High byte
   ror m8uL       ;rotate right result L byte and multiplier

   brcc    noad85     ;if carry set
   add m8uH,mc8u  ;    add multiplicand to result High byte
noad85: ror m8uH       ;shift right result High byte
   ror m8uL       ;rotate right result L byte and multiplier

   brcc    noad86     ;if carry set
   add m8uH,mc8u  ;    add multiplicand to result High byte
noad86: ror m8uH       ;shift right result High byte
   ror m8uL       ;rotate right result L byte and multiplier

   brcc    noad87     ;if carry set
   add m8uH,mc8u  ;    add multiplicand to result High byte
noad87: ror m8uH       ;shift right result High byte
   ror m8uL       ;rotate right result L byte and multiplier
   
   ret

.include "c:\tmp\finalrc.asm"

AVR_Admin- 04-22-2006
CODE

Display_code:
   cpi button, LowE_str
   brne    check1b
   subi    sum_low,LOW(lowE_TH8)  ;Subtract low bytes
   sbci    sum_hi,HIGH(lowE_TH8)  ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000001
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(lowE_TH7)  ;Subtract low bytes
   sbci    sum_hi,HIGH(lowE_TH7)  ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000010
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(lowE_TH6)  ;Subtract low bytes
   sbci    sum_hi,HIGH(lowE_TH6)  ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000100
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(lowE_TH5)  ;Subtract low bytes
   sbci    sum_hi,HIGH(lowE_TH5)  ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00001000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(lowE_TH4)  ;Subtract low bytes
   sbci    sum_hi,HIGH(lowE_TH4)  ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00011000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(lowE_TH3)  ;Subtract low bytes
   sbci    sum_hi,HIGH(lowE_TH3)  ;Sub high byte with carry  
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00010000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(lowE_TH2)  ;Subtract low bytes
   sbci    sum_hi,HIGH(lowE_TH2)  ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00100000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(lowE_TH1)  ;Subtract low bytes
   sbci    sum_hi,HIGH(lowE_TH1)  ;Sub high byte with carry  
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b01000000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   ldi temp2, 0b10000000
   rjmp    display_out

check1b:
   cpi button, A_str
   brne    check2b
   subi    sum_low,LOW(A_TH8) ;Subtract low bytes
   sbci    sum_hi,HIGH(A_TH8) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000001
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(A_TH7) ;Subtract low bytes
   sbci    sum_hi,HIGH(A_TH7) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000010
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(A_TH6) ;Subtract low bytes
   sbci    sum_hi,HIGH(A_TH6) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000100
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(A_TH5) ;Subtract low bytes
   sbci    sum_hi,HIGH(A_TH5) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00001000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(A_TH4) ;Subtract low bytes
   sbci    sum_hi,HIGH(A_TH4) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00011000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(A_TH3) ;Subtract low bytes
   sbci    sum_hi,HIGH(A_TH3) ;Sub high byte with carry  
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00010000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(A_TH2) ;Subtract low bytes
   sbci    sum_hi,HIGH(A_TH2) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00100000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(A_TH1) ;Subtract low bytes
   sbci    sum_hi,HIGH(A_TH1) ;Sub high byte with carry  
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b01000000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   ldi temp2, 0b10000000
   rjmp    display_out
   



check2b:
   cpi button, D_str
   brne    check3b
   subi    sum_low,LOW(D_TH8) ;Subtract low bytes
   sbci    sum_hi,HIGH(D_TH8) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000001
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(D_TH7) ;Subtract low bytes
   sbci    sum_hi,HIGH(D_TH7) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000010
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(D_TH6) ;Subtract low bytes
   sbci    sum_hi,HIGH(D_TH6) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000100
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(D_TH5) ;Subtract low bytes
   sbci    sum_hi,HIGH(D_TH5) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00001000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(D_TH4) ;Subtract low bytes
   sbci    sum_hi,HIGH(D_TH4) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00011000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(D_TH3) ;Subtract low bytes
   sbci    sum_hi,HIGH(D_TH3) ;Sub high byte with carry  
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00010000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(D_TH2) ;Subtract low bytes
   sbci    sum_hi,HIGH(D_TH2) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00100000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(D_TH1) ;Subtract low bytes
   sbci    sum_hi,HIGH(D_TH1) ;Sub high byte with carry  
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b01000000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   ldi temp2, 0b10000000
   rjmp    display_out


check3b:
   cpi button, G_str
   brne    check4b
   subi    sum_low,LOW(G_TH8) ;Subtract low bytes
   sbci    sum_hi,HIGH(G_TH8) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000001
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(G_TH7) ;Subtract low bytes
   sbci    sum_hi,HIGH(G_TH7) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000010
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(G_TH6) ;Subtract low bytes
   sbci    sum_hi,HIGH(G_TH6) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000100
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(G_TH5) ;Subtract low bytes
   sbci    sum_hi,HIGH(G_TH5) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00001000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(G_TH4) ;Subtract low bytes
   sbci    sum_hi,HIGH(G_TH4) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00011000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(G_TH3) ;Subtract low bytes
   sbci    sum_hi,HIGH(G_TH3) ;Sub high byte with carry  
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00010000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(G_TH2) ;Subtract low bytes
   sbci    sum_hi,HIGH(G_TH2) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00100000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(G_TH1) ;Subtract low bytes
   sbci    sum_hi,HIGH(G_TH1) ;Sub high byte with carry  
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b01000000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   ldi temp2, 0b10000000
   rjmp    display_out

check4b:
   cpi button, B_str
   brne    check5b
   subi    sum_low,LOW(B_TH8) ;Subtract low bytes
   sbci    sum_hi,HIGH(B_TH8) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000001
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(B_TH7) ;Subtract low bytes
   sbci    sum_hi,HIGH(B_TH7) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000010
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(B_TH6) ;Subtract low bytes
   sbci    sum_hi,HIGH(B_TH6) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000100
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(B_TH5) ;Subtract low bytes
   sbci    sum_hi,HIGH(B_TH5) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00001000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(B_TH4) ;Subtract low bytes
   sbci    sum_hi,HIGH(B_TH4) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00011000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(B_TH3) ;Subtract low bytes
   sbci    sum_hi,HIGH(B_TH3) ;Sub high byte with carry  
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00010000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(B_TH2) ;Subtract low bytes
   sbci    sum_hi,HIGH(B_TH2) ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00100000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(B_TH1) ;Subtract low bytes
   sbci    sum_hi,HIGH(B_TH1) ;Sub high byte with carry  
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b01000000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   ldi temp2, 0b10000000
   rjmp    display_out


check5b:
   cpi button, HiE_str
   brne    check_doneb
   subi    sum_low,LOW(hiE_TH8)   ;Subtract low bytes
   sbci    sum_hi,HIGH(hiE_TH8)   ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000001
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(hiE_TH7)   ;Subtract low bytes
   sbci    sum_hi,HIGH(hiE_TH7)   ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000010
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(hiE_TH6)   ;Subtract low bytes
   sbci    sum_hi,HIGH(hiE_TH6)   ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00000100
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(hiE_TH5)   ;Subtract low bytes
   sbci    sum_hi,HIGH(hiE_TH5)   ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00001000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(hiE_TH4)   ;Subtract low bytes
   sbci    sum_hi,HIGH(hiE_TH4)   ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00011000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(hiE_TH3)   ;Subtract low bytes
   sbci    sum_hi,HIGH(hiE_TH3)   ;Sub high byte with carry  
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00010000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(hiE_TH2)   ;Subtract low bytes
   sbci    sum_hi,HIGH(hiE_TH2)   ;Sub high byte with carry
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b00100000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   subi    sum_low,LOW(hiE_TH1)   ;Subtract low bytes
   sbci    sum_hi,HIGH(hiE_TH1)   ;Sub high byte with carry  
   sbrc    sum_hi, 7      ; checking MSB for sign
   ldi temp2, 0b01000000
   sbrc    sum_hi, 7      ; checking MSB for sign
   rjmp    display_out
   ldi temp2, 0b10000000
   rjmp    display_out

check_doneb:
   
display_out:
   com temp2
   out PORTB, temp2

   ret
;-


Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.