鬼子做的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???"));
}
}
} ;-----------------------------------------------------------------------------;
; 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"); 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) NB ;-----------------------------------------------------------------------------;
; 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 你发得晚了点。。。 回复【5楼】myqiang1990 小松鼠
你发得晚了点。。。
-----------------------------------------------------------------------
晚了好几年呀 一点也不晚,好的东西一点不晚,因为我还没做过, mark 呵呵,甚是有名的fft啊 还有个视频演示吧 灰常的NB
第一次看见代码 膜拜一下 汇编的,看得头大 MARK! mark 牛啊 不错 我觉得这个面包板焊得挺漂亮的,程序慢慢看 好程序,学习了! mark准备用 回复【6楼】zhuyi25762
回复【5楼】myqiang1990 小松鼠
你发得晚了点。。。
-----------------------------------------------------------------------
晚了好几年呀
-----------------------------------------------------------------------
之前的,贴来看下~ 干嘛发FGPA版来啊!
FPGA上汇编神马的都是浮云 支持一下 擦,都上汇编了。FPGA牛叉 好东西,多谢楼主(1)! 标记一下
页:
[1]