Tomas_Yung 发表于 2011-12-6 21:19:03

鬼子做的fft

/*------------------------------------------------*/
/* FFTEST : A test program for FFT module         */

#include <avr/io.h>
#include <avr/pgmspace.h>
#include "suart.h"                /* Defs for using Software UART module (Debugging via AVRSP-COM) */
#include "ffft.h"                /* Defs for using Fixed-point FFT module */

#define        SYSCLK                16000000



/*------------------------------------------------*/
/* Global variables                               */

char pool;        /* Console input buffer */

int16_t capture;                        /* Wave captureing buffer */
complex_t bfly_buff;                /* FFT buffer */
uint16_t spektrum;                /* Spectrum output buffer */



/*------------------------------------------------*/
/* Capture waveform                               */

void capture_wave (int16_t *buffer, uint16_t count)
{
        ADMUX = _BV(REFS0)|_BV(ADLAR)|_BV(MUX2)|_BV(MUX1)|_BV(MUX0);        // channel

        do {
                ADCSRA = _BV(ADEN)|_BV(ADSC)|_BV(ADFR)|_BV(ADIF)|_BV(ADPS2)|_BV(ADPS1);
                while(bit_is_clear(ADCSRA, ADIF));
                *buffer++ = ADC - 32768;
        } while(--count);

        ADCSRA = 0;
}


/* This is an alternative function of capture_wave() and can omit captureing buffer.

void capture_wave_inplace (complex_t *buffer, uint16_t count)
{
        const prog_int16_t *window = tbl_window;
        int16_t v;

        ADMUX = _BV(REFS0)|_BV(ADLAR)|_BV(MUX2)|_BV(MUX1)|_BV(MUX0);        // channel

        do {
                ADCSRA = _BV(ADEN)|_BV(ADSC)|_BV(ADFR)|_BV(ADIF)|_BV(ADPS2)|_BV(ADPS1);
                while(bit_is_clear(ADCSRA, ADIF));
                v = fmuls_f(ADC - 32768, pgm_read_word_near(window));
                buffer->r = v;
                buffer->i = v;
                buffer++; window++;
        } while(--count);

        ADCSRA = 0;
}
*/

/*------------------------------------------------*/
/* Online Monitor via an ISP cable                */

int main (void)
{
        char *cp;
        uint16_t m, n, s;
        uint16_t t1,t2,t3;


        DDRE = 0b00000010;        /* PE1:<conout>, PE0:<conin> in N81 38.4kbps */
        TCCR1B = 3;        /* clk/64 */

        xmitstr(PSTR("\r\nFFT sample program\r\n"));

        for(;;) {
                xmitstr(PSTR("\r\n>"));                        /* Prompt */
                rcvrstr(pool, sizeof(pool));        /* Console input */
                cp = pool;

                switch (*cp++) {        /* Pick a header char (command) */
                        case '\0' :                /* Blank line */
                                break;

                        case 'w' :                /* w: show waveform */
                                capture_wave(capture, FFT_N);
                                for (n = 0; n < FFT_N; n++) {
                                        s = capture;
                                        xmitf(PSTR("\r\n%4u:%6d "), n, s);
                                        s = (s + 32768) / 1024;
                                        for (m = 0; m < s; m++) xmit(' ');
                                        xmit('*');
                                }
                                break;

                        case 's' :                /* s: show spectrum */
                                capture_wave(capture, FFT_N);
                                TCNT1 = 0;        /* performance counter */
                                fft_input(capture, bfly_buff);
                                t1 = TCNT1; TCNT1 = 0;
                                fft_execute(bfly_buff);
                                t2 = TCNT1; TCNT1 = 0;
                                fft_output(bfly_buff, spektrum);
                                t3 = TCNT1;
                                for (n = 0; n < FFT_N / 2; n++) {
                                        s = spektrum;
                                        xmitf(PSTR("\r\n%4u:%5u "), n, s);
                                        s /= 512;
                                        for (m = 0; m < s; m++) xmit('*');
                                }
                                xmitf(PSTR("\r\ninput=%u, execute=%u, output=%u (x64clk)"), t1,t2,t3);
                                break;

                        default :                /* Unknown command */
                                xmitstr(PSTR("\n???"));
                }
        }
}

Tomas_Yung 发表于 2011-12-6 21:24:25

;-----------------------------------------------------------------------------;
; Audio Waveform Monitor R0.2                               May 29, 2011      ;
; (C)ChaN, 2012; http://elm-chan.org/                                       ;
;-----------------------------------------------------------------------------;
;
.include "m8def.inc"
.include "avr.inc"
.include "akiglcd.inc"

.equ        MOSI        = 3        ;Port B bit definitions
.equ        LCDCLK        = 1        ;/

.equ        RW        = 5        ;Port C bit definitions
.equ        E        = 4        ;
.equ        CS2        = 3        ;
.equ        CS1        = 2        ;
.equ        A0        = 1        ;
.equ        RES        = 0        ;/

.equ        FFT_N        = 128        ;Number of samples
.equ        LCD_W        = 122        ;LCD size
.equ        LCD_H        = 32        ;/
.equ        WAV_W        = (LCD_W-FFT_N/2)

.def        _0        = r15        ;Zero
.def        _Flags        = r25        ;b0:In captureing
                        ;b1:In pause
                        ;b2:MOSI edge detector

;----------------------------------------------------------;
; 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
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        ;/
        lds        YL, AdPtr        ;Write pointer
        clr        YH                ;
        addiw        Y, CaptBuf        ;/
        inw        A, ADC                ;Store A/D value
        subiw        A, 32768        ;
        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:

        lds        AL, LcdDiv        ;Drive LCD clock (2.4kHz)
        inc        AL                ;
        sts        LcdDiv, AL        ;
        bst        AL, 1                ;
        in        AL, PORTB        ;
        bld        AL, LCDCLK        ;
        out        PORTB, AL        ;/

        popw        Y
        popw        A
        out        SREG, AL
        pop        AL
        reti



;----------------------------------------------------------;
; Initialize peripherals (ATmega8-16AC @16MHz)

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        PORTC, 0b00001100        ;Port C         outi        DDRC,0b00111111

        ; 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=10, WGM1=10
        outi        TCCR1B, 0b00011001        ;WGM1=11, CS1=001

        ; Start A/D with ch6, free running, 9.6ksps
        outi        ADMUX, 0b00100110        ;ADLAR=1, MUX=0110
        outi        ADCSR, 0b11101111        ;ADEN=1,ADSC=1,ADFR=1,ADIE=1,ADPS=111

       rcall        lcd_init

        clr        _Flags
        sei
        sbr        _Flags, bit0        ;Start wave form captureing


;----------------------------------------------------------;
; Main


main:
        sbrc        _Flags, 0        ;Wait for end of wave captureing
        rjmp        PC-1                ;/

       rcall        make_wave        ;Make wave form                               
       rcall        rfsh_wave        ;Display wave form into LCD               

       rcall        do_window        ;Fill butterfly table                       
        sbr        _Flags, bit0        ;Restart captureing for next
       rcall        do_fft                ;Butterfly operations                       
       rcall        make_bars        ;Get scalar values, update spectrum       
       rcall        rfsh_bars        ;Display spectrum bars into LCD               

       rcall        check_pause        ;Check MOSI pin for Pause/Resume       

        rjmp        main                ; (approx. 70 cycles/sec)



;----------------------------------------------------------;
; Oscilloscope

make_wave:
        ldiw        Z, CaptBuf        ;Search zero crossing point
        ldiw        C, FFT_N-WAV_W        ;to still cyclic wave form.
        lddw        A, Z+0                ;
        ldiw        B, -2000        ;
        cpw        A, B                ;
        brge        PC+2                ;
        sbr        CH, bit0        ;
        ldiw        B, 1000                ;
        cpw        A, B                ;
        brlt        PC+3                ;
        sbrc        CH, 0                ;
        rjmp        PC+4                ;
        adiw        ZL, 2                ;
        dec        CL                ;
        brne        PC-17                ;/

        ldiw        Y, BflyBuf        ;Y = Destination
        ldi        CL, WAV_W        ;Loop counter
        ldw        A, Z+                ;Get a value into A
        addiw        A, 32768        ;
        mov        AL, AH                ;AL /= 2048 (LCD Y position)
        lsr        AL                ;
        lsr        AL                ;
        lsr        AL                ;/
        st        Y+, AL                ;Store value into destinatation
        dec        CL                ;Repeat WAV_W times
        brne        PC-10                ;/

        ldiw        X, WAV_W*4        ;Clear drawing buffer
        st        Y+, _0                ;
        sbiw        XL, 1                ;
        brne        PC-2                ;/
        sbiw        YL, WAV_W        ;Drawing start poitnt
        movw        T2L, YL                ;/

        ldiw        Z, BflyBuf        ;Express waveform into drawing buffer
        ld        AL, Z
        mov        AH, AL
        andi        AL, 7
        clr        BL
        sec
        ror        BL
        subi        AL, 1
        brcc        PC-2
        lsr        AH
        lsr        AH
        lsr        AH
        andi        AH, 3
        ldi        AL, WAV_W
        mul        AL, AH
        movw        YL, T2L
        subw        Y, T0
        ldi        DH, WAV_W-1
dn_l1:        ld        CL, Z+
        ld        CH, Z
        sub        CL, CH
        mov        DL, CL
        brcc        PC+2
        neg        CL
        mov        CH, CL
        lsr        CH
dn_l2:        ld        AL, Y
        or        AL, BL
        st        Y, AL
        subi        CH, 1
        brcc        PC+2
        adiw        YL, 1
        cpi        DL, 0
        breq        PC+11
        brmi        PC+6
        lsl        BL
        brne        PC+8
        ldi        BL, 0x01
        adiw        YL, WAV_W
        rjmp        PC+5
        lsr        BL
        brne        PC+3
        ldi        BL, 0x80
        sbiw        YL, WAV_W
        subi        CL, 1
        brcs        PC+2
        brne        dn_l2
        dec        DH
        brne        dn_l1

        ret


rfsh_wave:
        sbrc        _Flags, 1        ;Skip if in pause
        ret                        ;/
        ldiw        Y, BflyBuf+WAV_W
        clr        BH
        ldi        BL, FFT_N/2
       rcall        lcd_setadr
        ld        AL, Y+
       rcall        lcd_put
        cpi        BL, 0
        brne        PC-3
        cpi        BH, 4
        brcs        PC-7
        ret



;----------------------------------------------------------;
; Spectrum analyzer
;----------------------------------------------------------;
; 16bit fixed point FFT performance with megaAVR @16MHz
;
;Points:Input,    FFT, Output,   Total: Throughput
;   64pts:.17ms,1.9ms,1.4ms,   3.5ms:   18.3kpps   (expected)
;128pts:.34ms,4.4ms,2.6ms,   7.3ms:   17.5kpps   (measured)
;256pts:.68ms, 10.1ms,5.2ms,16.0ms:   16.0kpps   (expected)
;512pts:1.4ms, 22.6ms, 10.4ms,34.4ms:   14.8kpps   (expected)
;
; Input: Input waveform into butterfly table with applying window
; FFT: Execute butterfly operations
; Output: Descramble and output the spectrum as scalar values


do_window: ; Fill butterfly table with applying window function
        ldiw        X, CaptBuf        ;Source
        ldiw        Y, BflyBuf        ;Destination
        ldiw        Z, t_hamming*2        ;Window table
        ldi        CL, FFT_N
ms_l1:        lpmw        A, Z+                ;Get a window attenuation ratio
        ldw        B, X+                ;Get an input value
        FMULS16        A, B, T4, T2        ;Apply window
        stw        Y+, T4                ;Store real and image
        stw        Y+, T4                ;/
        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 = - , +=
        asrw        A                ;
        movw        CL, AL                ;B = - , +=
        lddw        D, Y+0                ;
        asrw        D                ;
        subw        A, D                ;
        addw        C, D                ;
        stw        Z+, C                ;
        lddw        B, Z+0                ;
        asrw        B                ;
        movw        CL, BL                ;
        lddw        D, Y+2                ;
        asrw        D                ;
        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_sin*2        ;
        lpmw        C, Z+                ;
        lpmw        D, Z+                ;/
        movw        ZL, T0L
        FMULS16        A, C, T4, T2        ; = A * C + B * D
        FMULS16        B, D, T8, T6        ; = 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_bars: ;Get scalar spectrum and update spectrum bar length
        ldiw        Z, t_desc*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                        ;/
        pushw        Z                ;CL = log(A)
        ldi        CL, 0                ;
        ldiw        Z, logs*2        ;
        lpmw        B, Z+                ;
        cpw        A, B                ;
        brcs        PC+3                ;
        inc        CL                ;
        rjmp        PC-6                ;
        popw        Z                ;/
        ld        AH, Y                ;Update bar length with peak holding
        subi        AH, 2                ; <-peak decay rate
        brcs        PC+3                ;
        cp        AH, CL                ;
        brcc        PC+2                ;
        mov        AH, CL                ;
        st        Y+, AH                ;/
        dec        CH
        rjne        ub_l1
        ret


rfsh_bars: ;Draw spectrum bars
        sbrc        _Flags, 1        ;Skip refresh if in pause.
        ret                        ;/
        ldi        DL, LCD_H-8+1        ; (This routine refreshes LCD with bar length
        ldiw        B, 0                ;list on the LvlBuf. 1st value is DC
       rcall        lcd_setadr        ;component, 2nd value is fundamental freq
       rcall        ds_hl                ;and last value is highest freq)
        clr        BL
        inc        BH
        subi        DL, 8
        brcc        PC-5
        ret
ds_hl:        ldiw        Y, LvlBuf
        ldi        CL, FFT_N/2
        ld        AL, Y+
        sub        AL, DL
        brcc        PC+3
        ldi        AH, 0
        rjmp        PC+9
        ldi        AH, 0xFF
        cpi        AL, 8
        brcc        PC+6
        ldi        AH, bit7
        subi        AL, 1
        brcs        PC+3
        asr        AH
        rjmp        PC-3
        mov        AL, AH
       rcall        lcd_put
        dec        CL
        brne        PC-16
        ret


; These tables must be rebuilt when change FFT_N

t_cos_sin:        ; {cos(x),sin(x)} table (0 <= x < pi, in 64 steps)
        .dw        32767, 0, 32727, 1607, 32609, 3211, 32412, 4807
        .dw        32137, 6392, 31785, 7961, 31356, 9511, 30851, 11038
        .dw        30272, 12539, 29621, 14009, 28897, 15446, 28105, 16845
        .dw        27244, 18204, 26318, 19519, 25329, 20787, 24278, 22004
        .dw        23169, 23169, 22004, 24278, 20787, 25329, 19519, 26318
        .dw        18204, 27244, 16845, 28105, 15446, 28897, 14009, 29621
        .dw        12539, 30272, 11038, 30851, 9511, 31356, 7961, 31785
        .dw        6392, 32137, 4807, 32412, 3211, 32609, 1607, 32727
        .dw        0, 32767, -1607, 32727, -3211, 32609, -4807, 32412
        .dw        -6392, 32137, -7961, 31785, -9511, 31356, -11038, 30851
        .dw        -12539, 30272, -14009, 29621, -15446, 28897, -16845, 28105
        .dw        -18204, 27244, -19519, 26318, -20787, 25329, -22004, 24278
        .dw        -23169, 23169, -24278, 22005, -25329, 20787, -26318, 19519
        .dw        -27244, 18204, -28105, 16845, -28897, 15446, -29620, 14009
        .dw        -30272, 12539, -30851, 11038, -31356, 9511, -31784, 7961
        .dw        -32137, 6392, -32412, 4807, -32609, 3211, -32727, 1607

t_hamming: ; Hamming window (for 128 samples)
        .dw        2621, 2639, 2693, 2784, 2910, 3073, 3270, 3502
        .dw        3768, 4068, 4401, 4765, 5161, 5587, 6042, 6525
        .dw        7036, 7571, 8132, 8715, 9320, 9945, 10588, 11249
        .dw        11926, 12616, 13318, 14031, 14753, 15482, 16216, 16954
        .dw        17694, 18433, 19171, 19905, 20634, 21356, 22069, 22772
        .dw        23462, 24138, 24799, 25443, 26068, 26673, 27256, 27816
        .dw        28352, 28862, 29345, 29800, 30226, 30622, 30987, 31319
        .dw        31619, 31885, 32117, 32315, 32477, 32603, 32694, 32748
        .dw        32767, 32748, 32694, 32603, 32477, 32315, 32117, 31885
        .dw        31619, 31319, 30987, 30622, 30226, 29800, 29345, 28862
        .dw        28352, 27816, 27256, 26673, 26068, 25443, 24799, 24138
        .dw        23462, 22772, 22069, 21356, 20634, 19905, 19171, 18433
        .dw        17694, 16954, 16216, 15482, 14753, 14031, 13318, 12616
        .dw        11926, 11249, 10588, 9945, 9320, 8715, 8132, 7571
        .dw        7036, 6526, 6042, 5587, 5161, 4765, 4401, 4068
        .dw        3768, 3502, 3270, 3073, 2910, 2784, 2693, 2639

t_desc:        ; Descramble table (for 128 point FFT)
        .dw        0*4, 64*4, 32*4, 96*4, 16*4, 80*4, 48*4, 112*4
        .dw        8*4, 72*4, 40*4, 104*4, 24*4, 88*4, 56*4, 120*4
        .dw        4*4, 68*4, 36*4, 100*4, 20*4, 84*4, 52*4, 116*4
        .dw        12*4, 76*4, 44*4, 108*4, 28*4, 92*4, 60*4, 124*4
        .dw        2*4, 66*4, 34*4, 98*4, 18*4, 82*4, 50*4, 114*4
        .dw        10*4, 74*4, 42*4, 106*4, 26*4, 90*4, 58*4, 122*4
        .dw        6*4, 70*4, 38*4, 102*4, 22*4, 86*4, 54*4, 118*4
        .dw        14*4, 78*4, 46*4, 110*4, 30*4, 94*4, 62*4, 126*4



;----------------------------------------------------------;


check_pause:
        sbic        PINB, MOSI
        rjmp        PC+7
        sbrs        _Flags, 2
        ret
        ldi        AL, bit1
        eor        _Flags, AL
        cbr        _Flags, bit2
        ret
        sbr        _Flags, bit2
        ret



;----------------------------------------------------------;
; LCD control functions (for dual SED1520 based module)


lcd_init:
        ldiw        A, 50000        ;12.5ms
        subiw        A, 1                ;
        brne        PC-2                ;/

        sbi        PORTC, RES        ;RES = H
        outi        DDRD, -1        ;Set Port D as data port

        ldiw        A, 10000        ;2.5ms
        subiw        A, 1                ;
        brne        PC-2                ;/

        ldiw        B, 0                ;Clear all
       rcall        lcd_setadr        ;
        ldi        AL, 0                ;
       rcall        lcd_put                ;
        cpi        BH, 4                ;
        brcs        PC-3                ;/

        cbi        PORTC, CS1        ;Enable Display
        cbi        PORTC, CS2        ;
        cbi        PORTC, A0        ;
        ldi        AL, 0xAF        ;
       rcall        lcd_write        ;/

        ret


lcd_setadr:
        push        BL
        clr        AL
        cpi        BL, 61
        brcs        PC+3
        ldi        AL, 2
        subi        BL, 61
       rcall        lcd_setdst
        mov        AL, BH
        andi        AL, 3
        ori        AL, 0xB8
       rcall        lcd_write
        mov        AL, BL
        andi        AL, 63
        pop        BL
        rjmp        PC+1
       rcall        lcd_write
        sbi        PORTC, A0
        rjmp        PC+1
        ret


lcd_put:
       rcall        lcd_write
        inc        BL
        cpi        BL, 61
        breq        lcd_setadr
        cpi        BL, LCD_W
        brne        PC+4
        inc        BH
        clr        BL
       rcall        lcd_setadr
        ret


lcd_write:
        out        PORTD, AL
        sbi        PORTC, E
        cbi        PORTC, E
        ret


lcd_setdst:
        in        AH, PORTC
        sbr        AH, (1<<CS1)+(1<<CS2)
        sbrc        AL, 1
        cbr        AH, (1<<CS2)
        sbrs        AL, 1
        cbr        AH, (1<<CS1)
        bst        AL, 0
        bld        AH, A0
        out        PORTC, AH
        rjmp        PC+1
        rjmp        PC+1
        rjmp        PC+1
        rjmp        PC+1
        ret

logs:        ; 60dB - 32 point log conversion table
        .dw        15, 19, 24, 30, 37, 47, 58, 72, 89, 111, 138, 171, 213, 264, 328, 407, 505, 627, 778, 966, 1199, 1488, 1846, 2292, 2844, 3529, 4380, 5436, 6746, 8371, 10389, 12892, 16000, 0xFFFF

;        for($a = -32; $a <= 0; $a++) {
;                $v = exp($a*1.875*2.303/20);
;                printf("%d, ", $v * 16000)
;        }
;        printf("0xFFFF\n");

Tomas_Yung 发表于 2011-12-6 21:29:10

http://cache.amobbs.com/bbs_upload782111/files_48/ourdev_702270R24TYR.png
(原文件名:1.png)

http://cache.amobbs.com/bbs_upload782111/files_48/ourdev_702271Q7NTAG.png
(原文件名:2.png)

http://cache.amobbs.com/bbs_upload782111/files_48/ourdev_702272W2TQ2U.jpg
(原文件名:3.jpg)

http://cache.amobbs.com/bbs_upload782111/files_48/ourdev_702273CLZ4YK.jpg
(原文件名:4.jpg)

http://cache.amobbs.com/bbs_upload782111/files_48/ourdev_702274L88MA9.jpg
(原文件名:5.jpg)

http://cache.amobbs.com/bbs_upload782111/files_48/ourdev_702275WT6OH3.jpg
(原文件名:6.jpg)

http://cache.amobbs.com/bbs_upload782111/files_48/ourdev_702276RQMN2V.jpg
(原文件名:7.jpg)

zhanshenguilai 发表于 2011-12-6 21:31:53

NB

Tomas_Yung 发表于 2011-12-6 21:35:26

;-----------------------------------------------------------------------------;
; Radio Spectrum Monitor R0.2                               October 8, 2011   ;
; (C)ChaN, 2012; http://elm-chan.org/                                       ;
;-----------------------------------------------------------------------------;
;
.include "m8def.inc"
.include "avr.inc"
.include "akiglcd.inc"

.equ        SYSCLK        = 16000000        ;MCU clock
.equ        FCLK        = 1400000        ;SCF clock (50fc)
.equ        FFT_N        = 128                ;Number of samples


;Port C bit definitions
.equ        RES        = 4
.equ        ADCS        = 3
.equ        ADCK        = 2

; Port B bit definitions
.equ        RW        = 5
.equ        DI        = 4
.equ        E        = 2
.equ        CSL        = 1
.equ        CSR        = 0

; Port D bit definitions (LCD data and Key input)
.equ        K_UP        = 0b10000000
.equ        K_DOWN        = 0b01000000
.equ        K_RIGHT        = 0b00010000
.equ        K_LEFT        = 0b00001000
.equ        K_PUSH        = 0b00000100
.equ        K_MASK        = 0b11011100



.def        _0        = r15        ;Zero register


;----------------------------------------------------------;
; Data memory area

.dseg
        .org        RAMTOP
BflyBuf:.byte        FFT_N*4                ;Butterfly operation table, Wave form buffer
LvlBuf:        .byte        FFT_N                ;Spectrum bar length
LvlBufA:.byte        FFT_N*2                ;Spectrum bar length averaging buffer

Offset:        .byte        6+6                ;DC null level for I,Q input
Null:        .byte        2                ;
Freq:        .byte        2                ;

Key:        .byte        3                ;Key input buffer {Cmd, Stat, Filter}
Modes:        .byte        3                ;Operation mode { Acquire Mode, Bar Mode, Window }
Run:        .byte        1                ;1=Enable display
Ave:        .byte        1                ;Averaging count

Pool:        .byte        16


;----------------------------------------------------------;
; 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        isr_tc0_ovf        ; TC0 OVF
        rjmp        0                ; SPI
        rjmp        0                ; USART RXC
        rjmp        0                ; USART UDRE
        rjmp        0                ; USART TXC
        rjmp        0                ; ADC
        rjmp        0                ; EE_RDY
        rjmp        0                ; ANA_COMP
        rjmp        0                ; TWI
        rjmp        0                ; SPM_RDY


;----------------------------------------------------------;
; 100Hz timer interrupt

isr_tc0_ovf:
        push        AL
        in        AL, SREG
        pushw        A

        outi        TCNT0, -(SYSCLK/100/1024)

        in        AL, PIND        ;Get key input
        com        AL                ;
        andi        AL, K_MASK        ;/
        lds        AH, Key+2        ;Check if stabled or not.
        sts        Key+2, AL        ;
        cp        AL, AH                ;
        brne        isc_exit        ;/
        lds        AL, Key+1        ;Check button down.
        sts        Key+1, AH        ;
        eor        AL, AH                ;
        and        AL, AH                ;
        breq        isc_exit        ;/
        sts        Key+0, AL        ;Store pressed button as a key command.

isc_exit:
        popw        A
        out        SREG, AL
        pop        AL
        reti



;----------------------------------------------------------;
; Initialize peripherals (ATmega8-16AC @16MHz)

reset:
        clr        _0                        ;Zero reg.
        ldiw        A, RAMEND                ;SP
        outw        SP, A                        ;/
        ldiw        Z, RAMTOP                ;Clear SRAM
        ldiw        X, RAMEND-RAMTOP+1        ;
        st        Z+, _0                        ;
        sbiw        XL, 1                        ;
        brne        PC-2                        ;/

        outi        PORTC, 0b00101100        ;Port C
        outi        DDRC,0b00011100

        outi        PORTB, 0b00000011        ;Port B
        outi        DDRB,0b00111111

        outi        PORTD, 0b11111111        ;Port D

        ; Start TC2 with FCLK on OC2 pin (for MAX295 clock)
        outi        OCR2, SYSCLK/FCLK/2-1
        outi        TCCR2, 0b00011001

        ; Start TC0 (100Hz interval timer)
        outi        TCCR0, 0b00000101
        outi        TIMSK, (1<<TOIE0)

       rcall        lcd_init

        ldiw        A, 4096/2        ;Initial offset (=0.5Vcc)
        stsw        Offset+0, A        ;
        stsw        Offset+6, A        ;/

        stsi        Null, 1

        sei
        ldi        AL, K_PUSH


;----------------------------------------------------------;
; Main


main:
       rcall        menu
        lds        AL, Modes+0
        cpi        AL, 0
        brne        main_w

main_s:        ; Spectrum Mode (60 cycles/sec)
       rcall        capture                ; Fill butterfly table
       rcall        normalize        ; Normalize A-D value to int16
       rcall        do_window        ; Apply hamming window
       rcall        do_fft                ; Butterfly operations
       rcall        make_bars        ; Get scalar values, update spectrum
       rcall        rfsh_bars        ; Display spectrum bars into LCD
       rcall        get_key
        breq        main_s
        rjmp        main


main_w:
       rcall        capture
       rcall        normalize
       rcall        rfsh_wave
       rcall        get_key
        breq        main_w
        rjmp        main


menu:
        cpi        AL, K_PUSH
        breq        mn_enter
        cpi        AL, K_UP
        breq        mn_hold
        cpi        AL, K_DOWN
        breq        mn_clr
        cpi        AL, K_LEFT
        breq        mn_null
        ret
mn_null:
        stsi        Null, 1
        ret
mn_clr:
        sts        Ave, _0
        ret
mn_hold:
        ldi        AH, 1
        lds        AL, Run
        eor        AL, AH
        sts        Run, AL
        ret

mn_enter:
        ldiw        E, 0
        ldiw        X, 128*6
        ldi        AL, 0
       rcall        lcd_putb
        sbiw        XL, 1
        brne        PC-3
        ldi        EH, 2
       rcall        disp_item0
        ldi        EH, 1
       rcall        disp_item0
        ldi        EH, 0
menu_l:       rcall        disp_item1
       rcall        get_key
        breq        PC-1
        cpi        AL, K_UP
        breq        mm_up
        cpi        AL, K_DOWN
        breq        mm_down
        cpi        AL, K_RIGHT
        breq        mm_right
        cpi        AL, K_PUSH
        brne        menu_l
        stsi        Run, 1
        sts        Ave, _0
        ret
mm_up:
        cpi        EH, 0
        breq        menu_l
       rcall        disp_item0
        dec        EH
        rjmp        menu_l
mm_down:
        cpi        EH, 2
        brcc        menu_l
       rcall        disp_item0
        inc        EH
        rjmp        menu_l
mm_right:
        ldiw        X, Modes
        add        XL, EH
        adc        XH, _0
        ldiw        Z, ms_tbl*2
        ldi        AL, 10
        mul        AL, EH
        addw        Z, T0
        lpm        AH, Z
        ld        AL, X
        inc        AL
        cp        AL, AH
        brcs        PC+2
        clr        AL
        st        X, AL
        rjmp        menu_l


disp_item0:
        clt
        rjmp        PC+2
disp_item1:
        set
        push        EH
        ldi        AL, 5*2
        mul        AL, EH
        ldiw        Z, ms_tbl*2 + 2
        addw        Z, T0
        lpmw        T4, Z+
        ldiw        Y, Modes
        add        YL, EH
        adc        YH, _0
        ld        AL, Y
        lsl        AL
        add        ZL, AL
        adc        ZH, _0
        lpmw        T2, Z+
        movw        ZL, T4L
        clr        EL
       rcall        lcd_puts
        ldi        AL, ' '
        brtc        PC+2
        ldi        AL, '['
       rcall        lcd_putc
        movw        ZL, T2L
       rcall        lcd_puts
        ldi        AL, ' '
        brtc        PC+2
        ldi        AL, ']'
       rcall        lcd_putc
        pop        EH
        ret


get_key:
        cli
        ldsw        A, Key+0
        sts        Key+0, _0
        sei
        cpi        AL, 0
        ret



ms_tbl:        .dw        2, ms_m1*2, ms_s10*2, ms_s11*2, 0
        .dw        3, ms_m2*2, ms_s20*2, ms_s21*2, ms_s22*2
        .dw        5, ms_m3*2, ms_s30*2, ms_s31*2, ms_s32*2, ms_s33*2, ms_s34*2

ms_m1:        .db        "Acq Moce:",0
ms_s10:        .db        "Spectrum",0
ms_s11:        .db        "Waveform",0
ms_s20:        .db        "Sampling ",0

ms_m2:        .db        "DispMode:",0
ms_s21:        .db        "Peak Hold",0
ms_s22:        .db        "Averaging",0

ms_m3:        .db        "Window:",0
ms_s30:        .db        "Hann   ",0
ms_s31:        .db        "Hamming",0
ms_s32:        .db        "Blackman ",0
ms_s33:        .db        "Flattop",0
ms_s34:        .db        "Rectangle",0


;----------------------------------------------------------;
;Sampling functions

;----------------------------------------;
;Capture IQ signal (128samples in 64ksps)
;Ret: BflyBuf = captured data, Freq = number of osc clocks during captureing process

capture:
        ldiw        Y, BflyBuf
        out        TCNT1H, _0
        out        TCNT1L, _0
        cli
        outi        TCCR1B, 7
        ldi        CL, FFT_N
cap_l1:        cbi        PORTC, ADCS        ;Read I and Q channel into A and B. (229clk)
        clr        DL                ;
        ldi        CH, 16                ;
cap_l2:        cbi        PORTC, ADCK        ;
        lsr        DL                ;
        rolw        B                ;
        lsr        DL                ;
        in        DL, PINC        ;
        sbi        PORTC, ADCK        ;
        rolw        A                ;
        dec        CH                ;
        brne        cap_l2                ;
        sbi        PORTC, ADCS        ;/
        stw        Y+, A                ;Store A and B into fft buffer. (8clk)
        stw        Y+, B                ;/
        rjmp        PC+1                ;Delay (10clk)
        rjmp        PC+1                ;
        rjmp        PC+1                ;
        rjmp        PC+1                ;
        rjmp        PC+1                ;/
        dec        CL                ;loop (3clk)
        brne        cap_l1                ;/

        out        TCCR1B, _0        ;Stop counter
        sei
        inw        A, TCNT1        ;Freq = osc frequency in unit of 500Hz
        stsw        Freq, A                ;/

        ret


;----------------------------------------;
;Normalize captured IQ data
;Call: BflyBuf = captured data to be normalized

normalize:
        ldiw        Z, Offset
        lddw        T0, Z+0                ;T0 = Null value for I
        lddw        T2, Z+6                ;T2 = Null value for Q
        clrw        T4                ;T6:T4 = 0 (averaging reg for I)
        clrw        T6                ;/
        clrw        T8                ;T10:T8 = 0 (averaging reg for Q)
        clrw        T10                ;/

        ldiw        Y, BflyBuf
        ldi        CL, FFT_N
nm_l1:        lddw        A, Y+0                ;A = I data (0..4095);
        addw        T4, A                ;T6:T4 += A;
        adc        T6L, _0                ;/
        subw        A, T0                ;A -= T0;
        lslw        A                ;A *= 16;
        lslw        A                ;
        lslw        A                ;
        lslw        A                ;/
        stw        Y+, A                ;Write it back
        lddw        A, Y+0                ;Apply same porcess to Q data
        addw        T8, A                ;
        adc        T10L, _0        ;
        subw        A, T2                ;
        lslw        A                ;
        lslw        A                ;
        lslw        A                ;
        lslw        A                ;
        stw        Y+, A                ;/
        dec        CL                ;Repeat
        brne        nm_l1                ;/

        lds        AL, Null
        sbrs        AL, 0
        ret

        lddw        A, Z+2                ;B:A = averaging reg for I
        lddw        B, Z+4                ;/
        lddw        C, Z+8                ;D:C = averaging reg for Q
        lddw        D, Z+10                ;/

        ldi        EL, 7                ;T6:T4 /= 128;
        lsrw        T6                ;T10:T8 /= 128;
        rorw        T4                ;
        lsrw        T10                ;
        rorw        T8                ;
        dec        EL                ;
        brne        PC-9                ;/
        addw        A, T4                ;B:A += T6:T4;
        adcw        B, T6                ;/
        addw        C, T8                ;D:C += T10:T8;
        adcw        D, T10                ;/

        lds        EL, Null+1        ;averaging count ++
        inc        EL                ;
        sts        Null+1, EL        ;/
        brne        PC+15                ;Null values are updated every 256 cycles to cancel DC offset at A-D input.
        std        Z+0, AH                ;
        std        Z+1, BL                ;
        std        Z+6, CH                ;
        std        Z+7, DL                ;
        clrw        A                ;
        clrw        B                ;
        clrw        C                ;
        clrw        D                ;
        sts        Null+0, _0        ;/

        stdw        Z+2, A                ;Restore averaging regs...
        stdw        Z+4, B                ;
        stdw        Z+8, C                ;
        stdw        Z+10, D                ;/

        ret



;----------------------------------------------------------;
; FFT functions


;----------------------------------------;
;Apply window function
;Call: BflyBuf = IQ waveform to be processed


do_window:
        lds        ZL, Modes+2        ;Window table
        lsl        ZL
        clr        ZH
        addiw        Z, dw_tbl*2
        lpmw        T0, Z+
        movw        ZL, T0L
        ldiw        Y, BflyBuf        ;Destination
        ldi        CL, FFT_N
ms_l1:        lpmw        A, Z+                ;Get a window attenuation ratio
        lddw        B, Y+0                ;Get an I data
        FMULS16        A, B, T4, T2        ;Apply window
        stw        Y+, T4                ;Restore it
        lddw        B, Y+0                ;Get a Q data
        FMULS16        A, B, T4, T2        ;Apply window
        stw        Y+, T4                ;Restore it
        dec        CL                ;Repeat for all samples
        brne        ms_l1                ;/
        ret

dw_tbl:        .dw        tw_hann*2, tw_hamming*2, tw_blackman*2, tw_flattop1*2, tw_rect*2


;----------------------------------------;
;Execute an FFT

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 = - , +=
        asrw        A                ;
        movw        CL, AL                ;B = - , +=
        lddw        D, Y+0                ;
        asrw        D                ;
        subw        A, D                ;
        addw        C, D                ;
        stw        Z+, C                ;
        lddw        B, Z+0                ;
        asrw        B                ;
        movw        CL, BL                ;
        lddw        D, Y+2                ;
        asrw        D                ;
        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_sin*2        ;
        lpmw        C, Z+                ;
        lpmw        D, Z+                ;/
        movw        ZL, T0L
        FMULS16        A, C, T4, T2        ; = A * C + B * D
        FMULS16        B, D, T8, T6        ; = 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


;----------------------------------------;
;Get scalar spectrum and update spectrum bar buffer

make_bars:
        ldiw        Z, t_reorder*2        ;Reordering table
        ldi        CH, FFT_N        ;Number of elements
        lds        AL, Modes+1
        cpi        AL, 1
        breq        mb_m1
        cpi        AL, 2
        breq        mb_m2

mb_m0:        ldiw        Y, LvlBuf        ;Bar length buffer
mb_l0:       rcall        get_scaler
        st        Y+, CL                ;Update bar length
        dec        CH
        brne        mb_l0
        ret

mb_m1:        ldiw        Y, LvlBuf        ;Bar length buffer
        lds        EH, Ave
mb_l1:       rcall        get_scaler
        clr        AL
        sbrc        EH, 0
        ld        AL, Y
        cp        AL, CL
        brcc        PC+2
        mov        AL, CL
        st        Y+, AL                ;Update bar length
        dec        CH
        brne        mb_l1
        stsi        Ave, 1
        ret

mb_m2:        ldiw        Y, LvlBufA        ;Bar length buffer
        lds        EH, Ave
mb_l2:       rcall        get_scaler
        mov        AL, CL
        clr        AH
        lddw        B, Y+0
        cpi        EH, 0
        breq        PC+3
        addw        A, B
        stw        Y+, A
        dec        CH
        brne        mb_l2
        inc        EH
        andi        EH, 7
        sts        Ave, EH
        breq        PC+2
        ret
        ldiw        Y, LvlBufA
        ldiw        X, LvlBuf
        ldi        CH, FFT_N
mb_v2:        ldw        A, Y+
        lsrw        A
        lsrw        A
        lsrw        A
        st        X+, AL
        dec        CH
        brne        mb_v2
        ret


get_scaler:
        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                        ;/
        pushw        Z                ;CL = log(A)
        lds        BL, Freq+1        ;
        cpi        BL, 0                ;
        ldiw        Z, logs48*2        ;
        breq        PC+3                ;
        ldiw        Z, logs40*2        ;
        ldi        CL, 0                ;
        lpmw        B, Z+                ;
        cpw        A, B                ;
        brcs        PC+3                ;
        inc        CL                ;
        rjmp        PC-6                ;
        popw        Z                ;/
        ret




; These tables must be rebuilt when change FFT_N

t_cos_sin:        ; {cos(x),sin(x)} table (0 <= x < pi, in 64 steps)
        .dw        32767, 0, 32727, 1607, 32609, 3211, 32412, 4807
        .dw        32137, 6392, 31785, 7961, 31356, 9511, 30851, 11038
        .dw        30272, 12539, 29621, 14009, 28897, 15446, 28105, 16845
        .dw        27244, 18204, 26318, 19519, 25329, 20787, 24278, 22004
        .dw        23169, 23169, 22004, 24278, 20787, 25329, 19519, 26318
        .dw        18204, 27244, 16845, 28105, 15446, 28897, 14009, 29621
        .dw        12539, 30272, 11038, 30851, 9511, 31356, 7961, 31785
        .dw        6392, 32137, 4807, 32412, 3211, 32609, 1607, 32727
        .dw        0, 32767, -1607, 32727, -3211, 32609, -4807, 32412
        .dw        -6392, 32137, -7961, 31785, -9511, 31356, -11038, 30851
        .dw        -12539, 30272, -14009, 29621, -15446, 28897, -16845, 28105
        .dw        -18204, 27244, -19519, 26318, -20787, 25329, -22004, 24278
        .dw        -23169, 23169, -24278, 22005, -25329, 20787, -26318, 19519
        .dw        -27244, 18204, -28105, 16845, -28897, 15446, -29620, 14009
        .dw        -30272, 12539, -30851, 11038, -31356, 9511, -31784, 7961
        .dw        -32137, 6392, -32412, 4807, -32609, 3211, -32727, 1607

tw_hamming: ; Hamming window (for 128 samples)
        .dw 2621, 2639, 2693, 2784, 2910, 3073, 3270, 3502
        .dw 3768, 4068, 4401, 4765, 5161, 5587, 6042, 6525
        .dw 7036, 7571, 8132, 8715, 9320, 9945, 10588, 11249
        .dw 11926, 12616, 13318, 14031, 14753, 15482, 16216, 16954
        .dw 17694, 18433, 19171, 19905, 20634, 21356, 22069, 22772
        .dw 23462, 24138, 24799, 25443, 26068, 26673, 27256, 27816
        .dw 28352, 28862, 29345, 29800, 30226, 30622, 30987, 31319
        .dw 31619, 31885, 32117, 32315, 32477, 32603, 32694, 32748
        .dw 32767, 32748, 32694, 32603, 32477, 32315, 32117, 31885
        .dw 31619, 31319, 30987, 30622, 30226, 29800, 29345, 28862
        .dw 28352, 27816, 27256, 26673, 26068, 25443, 24799, 24138
        .dw 23462, 22772, 22069, 21356, 20634, 19905, 19171, 18433
        .dw 17694, 16954, 16216, 15482, 14753, 14031, 13318, 12616
        .dw 11926, 11249, 10588, 9945, 9320, 8715, 8132, 7571
        .dw 7036, 6526, 6042, 5587, 5161, 4765, 4401, 4068
        .dw 3768, 3502, 3270, 3073, 2910, 2784, 2693, 2639

tw_hann: ; Hann Window
        .dw 0, 19, 78, 177, 314, 490, 705, 957
        .dw 1247, 1572, 1934, 2330, 2761, 3224, 3718, 4244
        .dw 4798, 5381, 5989, 6623, 7281, 7960, 8660, 9378
        .dw 10113, 10864, 11627, 12402, 13187, 13979, 14777, 15579
        .dw 16383, 17187, 17989, 18787, 19579, 20364, 21139, 21902
        .dw 22653, 23388, 24106, 24806, 25485, 26143, 26777, 27385
        .dw 27968, 28522, 29048, 29542, 30005, 30436, 30832, 31193
        .dw 31519, 31809, 32061, 32275, 32452, 32589, 32688, 32747
        .dw 32766, 32747, 32688, 32589, 32452, 32276, 32061, 31809
        .dw 31519, 31194, 30832, 30436, 30005, 29542, 29048, 28522
        .dw 27968, 27386, 26777, 26143, 25485, 24806, 24106, 23388
        .dw 22653, 21902, 21139, 20364, 19579, 18787, 17989, 17187
        .dw 16383, 15579, 14777, 13979, 13187, 12402, 11627, 10864
        .dw 10113, 9378, 8660, 7960, 7281, 6623, 5989, 5381
        .dw 4798, 4244, 3718, 3224, 2761, 2330, 1934, 1573
        .dw 1247, 957, 705, 491, 314, 177, 78, 19

tw_blackman: ; Blackman window (for 128 samples)
        .dw 0, 7, 28, 64, 115, 181, 263, 362
        .dw 479, 614, 769, 945, 1142, 1363, 1608, 1879
        .dw 2177, 2502, 2857, 3241, 3656, 4103, 4582, 5094
        .dw 5638, 6216, 6826, 7469, 8144, 8849, 9585, 10349
        .dw 11140, 11957, 12796, 13657, 14536, 15431, 16338, 17255
        .dw 18178, 19103, 20028, 20949, 21861, 22760, 23644, 24507
        .dw 25346, 26158, 26938, 27682, 28387, 29050, 29667, 30235
        .dw 30752, 31214, 31619, 31966, 32252, 32476, 32637, 32734
        .dw 32766, 32734, 32637, 32476, 32252, 31966, 31619, 31214
        .dw 30752, 30235, 29667, 29050, 28387, 27682, 26938, 26158
        .dw 25347, 24507, 23644, 22760, 21861, 20949, 20028, 19104
        .dw 18178, 17255, 16338, 15431, 14536, 13657, 12797, 11957
        .dw 11140, 10349, 9585, 8849, 8144, 7469, 6826, 6216
        .dw 5638, 5094, 4582, 4103, 3656, 3241, 2857, 2502
        .dw 2177, 1879, 1608, 1363, 1142, 945, 769, 614
        .dw 479, 362, 263, 181, 115, 64, 28, 7

tw_flattop1:
        .dw 0, -41, -86, -134, -189, -250, -319, -397
        .dw -484, -582, -690, -807, -934, -1067, -1207, -1350
        .dw -1493, -1633, -1766, -1887, -1993, -2077, -2135, -2160
        .dw -2147, -2090, -1983, -1820, -1597, -1307, -947, -512
        .dw 0, 593, 1269, 2029, 2872, 3798, 4803, 5886
        .dw 7041, 8263, 9546, 10883, 12265, 13683, 15127, 16586
        .dw 18049, 19504, 20940, 22344, 23704, 25007, 26243, 27400
        .dw 28467, 29434, 30292, 31033, 31649, 32134, 32484, 32696
        .dw 32766, 32696, 32484, 32134, 31649, 31033, 30292, 29434
        .dw 28467, 27400, 26243, 25008, 23704, 22344, 20940, 19504
        .dw 18049, 16586, 15127, 13683, 12265, 10883, 9547, 8263
        .dw 7041, 5886, 4803, 3798, 2872, 2029, 1269, 593
        .dw 0, -512, -947, -1307, -1597, -1820, -1983, -2090
        .dw -2147, -2160, -2135, -2077, -1993, -1887, -1766, -1633
        .dw -1493, -1350, -1207, -1067, -934, -807, -690, -582
        .dw -484, -397, -319, -250, -189, -134, -86, -41

tw_rect: ; Rectanguler window (for 128 samples)
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
        .dw 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767

t_reorder:        ;Reordering table (for 128 point complex FFT)
        .dw        1*4, 65*4, 33*4, 97*4, 17*4, 81*4, 49*4, 113*4, 9*4, 73*4, 41*4, 105*4, 25*4, 89*4, 57*4, 121*4
        .dw        5*4, 69*4, 37*4, 101*4, 21*4, 85*4, 53*4, 117*4, 13*4, 77*4, 45*4, 109*4, 29*4, 93*4, 61*4, 125*4
        .dw        3*4, 67*4, 35*4, 99*4, 19*4, 83*4, 51*4, 115*4, 11*4, 75*4, 43*4, 107*4, 27*4, 91*4, 59*4, 123*4
        .dw        7*4, 71*4, 39*4, 103*4, 23*4, 87*4, 55*4, 119*4, 15*4, 79*4, 47*4, 111*4, 31*4, 95*4, 63*4, 127*4
        .dw        0*4, 64*4, 32*4, 96*4, 16*4, 80*4, 48*4, 112*4, 8*4, 72*4, 40*4, 104*4, 24*4, 88*4, 56*4, 120*4
        .dw        4*4, 68*4, 36*4, 100*4, 20*4, 84*4, 52*4, 116*4, 12*4, 76*4, 44*4, 108*4, 28*4, 92*4, 60*4, 124*4
        .dw        2*4, 66*4, 34*4, 98*4, 18*4, 82*4, 50*4, 114*4, 10*4, 74*4, 42*4, 106*4, 26*4, 90*4, 58*4, 122*4
        .dw        6*4, 70*4, 38*4, 102*4, 22*4, 86*4, 54*4, 118*4, 14*4, 78*4, 46*4, 110*4, 30*4, 94*4, 62*4, 126*4



logs40:        ; 60dB - 40 point log conversion table
        .dw        15, 18, 22, 26, 31, 37, 45, 53, 63, 75, 89, 106, 126, 150, 179, 213, 253, 301, 357, 425, 505, 600, 714, 848, 1009, 1199, 1425, 1694, 2013, 2393, 2844, 3380, 4018, 4775, 5675, 6746, 8017, 9529, 11326, 13461, 16000, 0xFFFF

logs48:        ; 60dB - 48 point log conversion table
        .dw        19, 23, 26, 30, 35, 41, 47, 54, 63, 72, 84, 97, 112, 129, 149, 173, 199, 230, 266, 307, 355, 410, 473, 547, 632, 729, 842, 973, 1124, 1298, 1499, 1731, 1999, 2308, 2666, 3078, 3555, 4105, 4741, 5475, 6323, 7302, 8432, 9738, 11245, 12986, 14997, 17318, 20000, 0xFFFF



;-------------------------------------------------------------------------------;
; Drawing functions


;----------------------------------------;
;Draw in spectrum mode
;Call: LvlBuf=bar data buffer

rfsh_bars:
        lds        AL, Run
        sbrs        AL, 0
        ret
        clrw        E
        lds        BL, Freq+1
        cpi        BL, 0
        ldi        CH, 48
        breq        PC+2
        ldi        CH, 40
rb_l2:        subi        CH, 8
        ldi        CL, FFT_N
        ldiw        Y, LvlBuf
rb_l3:        ld        BL, Y+
        clr        AL
        sub        BL, CH
        brcs        PC+8
        ldi        AL, -1
        cpi        BL, 8
        brcc        PC+5
        lsr        AL
        subi        BL, 1
        brcc        PC-2
        com        AL
       rcall        lcd_putb
        dec        CL
        brne        rb_l3
        cpi        CH, 0
        brne        rb_l2

        ldsw        A, Freq
        cpi        AH, 0
        brne        PC+2
        ret
        subiw        A, (455-32)*2
        clr        DH
        ldi        CL, 16
        lslw        A
        rol        DH
        cpi        DH, 36
        brcs        PC+3
        subi        DH, 36
        inc        AL
        dec        CL
        brne        PC-8
        subi        DH, 36+8
        addiw        A, 1

        ldi        AH, 18
        mul        AL, AH
        movw        AL, T0L
        ldi        CL, 5
        push        CL
       rcall        put_valn2
        subiw        A, 18
        pop        CL
        dec        CL
        brne        PC-6

        ret



put_valn2:
        pushw        A
        ldi        CH, 0
pv_l1:        inc        CH
        clr        BL
        ldi        CL, 16
pv_l2:        lslw        A
        rol        BL
        cpi        BL, 10
        brcs        PC+3
        subi        BL, 10
        inc        AL
        dec        CL
        brne        pv_l2
        push        BL
        cp        AL, _0
        cpc        AH, _0
        brne        pv_l1
        cpi        CH, 4
        brcc        PC+5
        inc        CH
        ldi        BL, 10
        push        BL
        rjmp        PC-5

        ldiw        X, Pool
        pop        AL
       rcall        lcd_putn
        dec        CH
        brne        PC-3
        ldiw        X, Pool
        clr        CL
        ld        AL, X+
        cpi        CL, 8
        brne        PC+2
        ori        AL, 3
       rcall        lcd_putbm
        inc        CL
        cpi        CL, 16
        brcs        PC-7
        ldi        AL, 0
        cpi        CL, 8+18
        brne        PC+2
        ori        AL, 3
       rcall        lcd_putbm
        inc        CL
        cpi        CL, 36
        brcs        PC-7

        popw        A
        ret

lcd_putn:
        pushw        Z
        ldi        AH, 3
        mul        AL, AH
        ldiw        Z, font35*2
        addw        Z, T0
        lpm        AL, Z+
        st        X+, AL
        lpm        AL, Z+
        st        X+, AL
        lpm        AL, Z+
        st        X+, AL
        st        X+, _0
        popw        Z
        ret

lcd_putbm:
        sbrs        DH, 7
       rcall        lcd_putb
        inc        DH
        ret



;----------------------------------------;
;Draw in wave form mode
;Call: BflyBuf = normalized IQ wave form

rfsh_wave:
        lds        AL, Run
        sbrs        AL, 0
        ret
        clrw        E
        ldi        CH, 64-8
rw_l2:        subi        CH, 8
        ldi        CL, FFT_N
        ldiw        Y, BflyBuf
rw_l3:        clrw        A
        ldw        B, Y+
        addi        BH, 128
        lsr        BH
        lsr        BH
        sub        BH, CH
        brcs        rw_s1
        cpi        BH, 8
        brcc        rw_s1
        ror        AL
        subi        BH, 1
        brcc        PC-2
rw_s1:        ldw        B, Y+
        addi        BH, 128
        lsr        BH
        lsr        BH
        sub        BH, CH
        brcs        rw_s2
        cpi        BH, 8
        brcc        rw_s2
        ror        AH
        subi        BH, 1
        brcc        PC-2
rw_s2:        or        AL, AH
       rcall        lcd_putb
        dec        CL
        brne        rw_l3

        cpi        CH, 8
        brne        rw_l2

        ret



;-------------------------------------------------------------------------------;
; LCD control functions (for dual HD61202 based LCD module)
;

;----------------------------------------;
;Initialize LCD module

lcd_init:
        sbi        PORTC, RES        ;RES,CS = H

        cbi        PORTB, CSL        ;Enable Display
        cbi        PORTB, CSR        ;
        cbi        PORTB, DI        ;
        ldi        AL, 0x3F        ;
       rcall        lcd_write        ;
        ldi        AL, 0xC0        ;
       rcall        lcd_write        ;/

        ret


;----------------------------------------;
;Put an ascii character
; Call: AL = data, EL = X(0..127), EH = Y(0..5)
; Ret: EL,EH = next address



lcd_putc:
        pushw        Z
        subi        AL, ' '
        ldi        AH, 5
        mul        AL, AH
        ldiw        Z, font58*2
        addw        Z, T0
        ldi        AH, 5
        lpm        AL, Z+
       rcall        lcd_putb
        dec        AH
        brne        PC-3
        clr        AL
       rcall        lcd_putb
        popw        Z
        ret

lcd_puts:
        lpm        AL, Z+
        cpi        AL, 0
        brne        PC+2
        ret
       rcall        lcd_putc
        rjmp        lcd_puts


font58:
.include "font5x8.asm"

font35:
.include "font3x5.asm"


;----------------------------------------;
; Put a pattern byte into LCDC memory
; Call: AL = data, EL = X(0..127), EH = Y(0..5)
; Ret: EL,EH = next address

lcd_putb:
        push        AL
        mov        AL, EL
        andi        AL, 63
        brne        pd_s
        cbi        PORTB, DI
        sbrc        EL, 6
        rjmp        pd_rh
pd_lh:        sbi        PORTB, CSR
        cbi        PORTB, CSL
        mov        AL, EH
        ori        AL, 0b10111000
       rcall        lcd_write
        ldi        AL, 0b01000000
       rcall        lcd_write
        rjmp        pd_s
pd_rh:        sbi        PORTB, CSL
        cbi        PORTB, CSR
        mov        AL, EH
        ori        AL, 0b10111000
       rcall        lcd_write
        ldi        AL, 0b01000000
       rcall        lcd_write
        inc        EH
pd_s:        pop        AL
        sbi        PORTB, DI
       rcall        lcd_write
        inc        EL
        ret


;----------------------------------------;
;Write a byte to LCDC register
;Call: AL=data, CSL,CLR,D/I=destination

lcd_write:
        cli

        in        T0L, PORTB        ;Save D/I,R/W bit
        cbi        PORTB, DI        ;D/I = L
        sbi        PORTB, RW        ;R/W = H
        sbi        PORTB, E        ;E = H
        rjmp        PC+1                ;Delay
        rjmp        PC+1                ;
        rjmp        PC+1                ;
        rjmp        PC+1                ;/
        in        T0H, PIND        ;Read data
        cbi        PORTB, E        ;E = L
        sbrc        T0H, 7                ;Loop while not ready
        rjmp        PC-8                ;/
        out        PORTB, T0L        ;Restore D/I,R/W bit

        sbi        PORTB, E        ;E = H
        out        PORTD, AL        ;PORTD = data
        outi        DDRD, -1        ;/
        rjmp        PC+1                ;Delay
        rjmp        PC+1                ;/
        cbi        PORTB, E        ;E = L

        out        PORTD, AL        ;PD = pull-up
        out        DDRD, _0        ;/

        sei
        ret

myqiang1990 发表于 2011-12-6 21:40:29

你发得晚了点。。。

zhuyi25762 发表于 2011-12-6 21:46:50

回复【5楼】myqiang1990 小松鼠
你发得晚了点。。。
-----------------------------------------------------------------------

晚了好几年呀

wjfblack 发表于 2011-12-6 21:50:50

一点也不晚,好的东西一点不晚,因为我还没做过,

yuzr 发表于 2011-12-6 21:58:40

mark

icefier 发表于 2011-12-6 23:01:20

呵呵,甚是有名的fft啊

wear778899 发表于 2011-12-7 08:05:14

还有个视频演示吧   灰常的NB

第一次看见代码   膜拜一下

chenguanghua 发表于 2011-12-7 08:19:11

汇编的,看得头大

changhui0222 发表于 2011-12-7 08:34:44

MARK!

p4s5j6 发表于 2011-12-7 09:22:21

mark

jiayue12450 发表于 2011-12-7 09:54:57

牛啊   不错

love595 发表于 2011-12-7 10:33:14

我觉得这个面包板焊得挺漂亮的,程序慢慢看

colinin 发表于 2011-12-7 14:17:22

好程序,学习了!

myfriend6042 发表于 2012-2-28 13:56:45

mark准备用

reflecter 发表于 2012-2-28 13:59:30

回复【6楼】zhuyi25762
回复【5楼】myqiang1990 小松鼠
你发得晚了点。。。
-----------------------------------------------------------------------
晚了好几年呀
-----------------------------------------------------------------------
之前的,贴来看下~

caizijian 发表于 2012-2-28 21:50:14

干嘛发FGPA版来啊!

FPGA上汇编神马的都是浮云

century99 发表于 2012-5-2 14:28:52

支持一下

orange-208 发表于 2012-5-2 16:31:37

擦,都上汇编了。FPGA牛叉

Niandet 发表于 2012-5-2 16:47:24

好东西,多谢楼主(1)!

小蚂蚁慧慧 发表于 2012-7-6 22:07:31

标记一下
页: [1]
查看完整版本: 鬼子做的fft