.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"