;-----------------------------------------------------------------------------; ; Audio Waveform Monitor R0.1 Nov 11, 2004 ; ; (C)ChaN, 2004; http://elm-chan.org/ ; ;-----------------------------------------------------------------------------; ; .include "m8def.inc" .include "avr.inc" .include "akiglcd.inc" .equ Sync = 2 ;Port D bit definitions .equ FFT_N = 128 ;Number of samples .equ LCD_H = 16 ;/ .def _0 = r15 ;Zero .def _Flags = r25 ;b0:In captureing ;b1:In pause ;b2:MOSI edge detector ;b3:Low/High Freq ;b4:ADC Divider (für 5,5kHz Samplerate) ;b5:WDR Flag 0 ;b6:WDR Flag 1 .equ WDRF0=5 .equ WDRF1=6 ;----------------------------------------------------------; ; Data memory area .dseg .org RAMTOP CaptBuf:.byte FFT_N*2 ;Sampling buffer BflyBuf:.byte FFT_N*4 ;Butterfly operation table, Wave form buffer LvlBuf: .byte FFT_N/2 ;Spectrum bar length, High Freq LvlBuf2:.byte FFT_N/2 ;Spectrum bar length, Low Freq LvlBuf3:.byte FFT_N/2 ;Spectrum bar length, Gesamt AdPtr: .byte 1 ;Sampling pointer LcdDiv: .byte 1 ;Divider for LCD drive ;----------------------------------------------------------; ; Program code area .cseg rjmp reset ; RESET rjmp 0 ; INT0 rjmp 0 ; INT1 rjmp 0 ; TC2 COMP rjmp 0 ; TC2 OVF rjmp 0 ; TC1 CAPT rjmp 0 ; TC1 COMPA rjmp 0 ; TC1 COMPB rjmp 0 ; TC1 OVF rjmp 0 ; TC0 OVF rjmp 0 ; SPI rjmp 0 ; USART RXC rjmp 0 ; USART UDRE rjmp 0 ; USART TXC ; rjmp isr_adc ; ADC ; rjmp 0 ; EE_RDY ; rjmp 0 ; ANA_COMP ; rjmp 0 ; TWI ; rjmp 0 ; SPM_RDY ;----------------------------------------------------------; ; ADC interrupt (9.6ksps) isr_adc: push AL in AL, SREG pushw A pushw Y sbrs _Flags, 0 ;Skip if in Idle rjmp adc_skip ;/ sbrs _Flags, 3 rjmp nodiv sbrs _Flags, 4 rjmp setd cbr _Flags, (1<<4) rjmp adc_skip setd: sbr _Flags, (1<<4) nodiv: lds YL, AdPtr ;Write pointer clr YH ; addiw Y, CaptBuf ;/ inw A, ADC ;Store A/D value stw Y+, A ;/ lds AL, AdPtr ;Next pointer addi AL, 2 ; sts AdPtr, AL ;/ brne PC+2 ;Terminate if 128 samples captured. cbr _Flags, bit0 ;/ adc_skip: popw Y popw A out SREG, AL pop AL reti ;----------------------------------------------------------; ; Initialize peripherals (ATmega8 @ 18,432MHz) reset: clr _0 ;Zero reg. ldiw Z, RAMTOP ;Clear all variables ldiw X, RAMEND-RAMTOP+1 ; st Z+, _0 ; sbiw XL, 1 ; brne PC-2 ;/ sbiw ZL, 1 ;SP ‰Šú‰» outw SP, Z ;/ outi PORTB, 0b00101000 ;Port B ‰Šú‰» outi DDRB, 0b00010110 outi DDRC, 0 outi PORTD, 0b00000100 ;Port D outi DDRD, 0b00000100 ;Port D ; Start TC1 with 444kHz on OC1B pin (for MAX293 clock) ldiw A, 36-1 ;TOP value outw ICR1, A ;/ ldiw A, 36/2 ;half value outw OCR1B, A ;/ outi TCCR1A, 0b00100010 ;COM1B[1:0]=10, WGM1[1:0]=10 outi TCCR1B, 0b00011001 ;WGM1[3:2]=11, CS1[2:0]=001 ; Start A/D with ch0, free running, 44ksps outi ADMUX, 0b00000000 ;MUX[3:0]=0000 outi ADCSR, 0b11101111 ;ADEN=1,ADSC=1,ADFR=1,ADIE=1,ADPS[2:0]=110 outi ucsrb, 8 outi ubrrh, 0 outi ubrrl, 9 in r16, WDTCR ori r16, (1< signed FMULS16 A, B, T4, T2 ;Apply window stw Y+, T4 ;Store real st Y+, _0 ;Clear image st Y+, _0 ;/ dec CL brne ms_l1 ret do_fft: ; Execute butterfly operations (not optimized) ldi XH, 1 ;u ldi EL, FFT_N/2 ;l df_l1: ldiw Z, BflyBuf ;Z = BflyBuf ldiw Y, BflyBuf ;Y = BflyBuf + l * 4 muli EL, 4 ; addw Y, T0 ;/ mul AL, XH ;T10L = u * 4 mov T10L, T0L ;/ mov XL, XH ;w = u df_l2: clr T14L ;p=0 df_l3: lddw A, Z+0 ;A = [Z+0] - [Y+0], [Z+0] += [Y+0] movw CL, AL ;B = [Z+2] - [Y+2], [Z+2] += [Y+2] lddw D, Y+0 ; subw A, D ; addw C, D ; stw Z+, C ; lddw B, Z+0 ; movw CL, BL ; lddw D, Y+2 ; subw B, D ; addw C, D ; stw Z+, C ;/ movw T0L, ZL movw ZL, T14L ;C=cos(p), D=sin(p) addiw Z, t_cos_sin128*2 ; lpmw C, Z+ ; lpmw D, Z+ ;/ movw ZL, T0L FMULS16 A, C, T4, T2 ;[Y+0] = A * C + B * D FMULS16 B, D, T8, T6 ;[Y+2] = B * C - A * D addw T2, T6 ; adcw T4, T8 ; stw Y+, T4 ; FMULS16 B, C, T4, T2 ; FMULS16 A, D, T8, T6 ; subw T2, T6 ; sbcw T4, T8 ; stw Y+, T4 ;/ add T14L, T10L ;p += u rjne df_l3 muli EL, 4 ;Y += l * 4, Z += l * 4; (skip split segment) addw Y, T0 ; addw Z, T0 ;/ dec XL ;--w rjne df_l2 lsl XH ;u *= 2 lsr EL ;l /= 2 rjne df_l1 ret make_barsl: ;Get scalar spectrum and update spectrum bar length ldiw Z, t_desc128*2 ;Descramble table ldiw Y, LvlBuf ;Bar length buffer ldi CH, FFT_N/2 ;Number of elements ub_l1: lpmw A, Z+ ;Get a vector value (A = r, B = i) ldiw X, BflyBuf ; addw X, A ; ldw A, X+ ; ldw B, X+ ;/ FMULS16 A, A, T4, T2 ;A = sqrt(A * A + B * B); 0..32767 (scalar) FMULS16 B, B, T8, T6 ; addw T2, T6 ; adcw T4, T8 ; SQRT32 ;/ movw T2L, AL ; AL = sqrt(A); 0..181 (root compression) SQRT16 ; / * remove this for linear scale ldi AH, 100 ;T0H = AL/3; (scaling) (Orginal: 256/3) mul AL, AH ;/ ld AH, Y ;Update bar length with peak holding subi AH, 2 ; <-peak decay rate brcs PC+3 ; cp AH, T0H ; brcc PC+2 ; mov AH, T0H ; subi AH, 1 brcc notzero clr AH notzero: st Y+, AH ;/ dec CH rjne ub_l1 sbr _Flags, (1<