Source file: /~heha/hs/kcemu/kcswberg.zip/DISK/FFT.ASM

;
;Schnelle Fouriertrafo mit
;genau 256 Stuetzstellen
;haftmann#software 1993
;=================================
os	equ	0f003h
anfang	equ	7000h
	org	anfang
;Sprungtabelle u. Uebergabezelle
	jr	plotb	;anfang
what	db	tabhi	;anfang+2
	jp	fft	;anfang+3
	jp	coswin	;anfang+6
	jp	betrag	;anfang+9
;Schnittstellenbeschreibung
;(ShortInt = -128..127)
;(Integer = -32768..32767)
;
;*****************
;PLOT (Anfang +0)
;Zeichnet ein Oszillogramm in die
;linke "Bildschirmhaelfte" unter
;Verwendung von CAOS-LINE
;
;PE:	*(Anfang+2): High-Adresse
;der abzubildenden 100h-Tabelle
;	*eine 100h lange Tabelle
;mit ShortInt-Werten belegt
;
;***************
;FFT (Anfang +3)
;Führt mit 256 komplexen ShortInt-
;Daten eine FFT aus. Das Ergebnis
;sind 256 komplexe Integer-Daten
;(=400h Bytes), also die A(i) und
;B(i).
;
;PE:	*in (Anfang +400h) die
;Realteile als ShortInt
;	*in (Anfang +500h) die
;Imaginaerteile als ShortInt
;
;PA:	*in (Anfang +400h) die
;Low-Realteile als Integer
;	*in (Anfang +500h) die
;Low-Imaginaerteile als Integer
;	*in (Anfang +600h) die
;High-Realteile als Integer
;	*in (Anfang +700h) die
;High-Imaginaerteile als Integer
;
;Hinweis: Die FFT-Routine wandelt
;als erstes die angebotenen ShortInts
;zu Integers und rechnet intern damit.
;
;******************
;COSWIN (Anfang +6)
;Legt über eine 100h lange ShortInt-
;Tabelle ein Cosinusquadratfenster
;(auch Hanning-Fenster genannt); d.h.
;alle Werte werden mit der COS^2-Funk-
;tion multipliziert.
;
;PE:	*(Anfang +2): High-Adresse
;der zu fensternden 100h-Tabelle
;	*die Tabelle selbst mit 100h
;ShortInt-Werten
;
;PA:	*dieselbe Tabelle gefenstert
;
;******************
;BETRAG (Anfang +9)
;Rechnet die komplexen Ausgabewerte
;der FFT in Bytes um, bereitet die
;Rücktransformation vor und erzeugt
;eine Tabelle mit Betraegen (als Byte
;= unsigned ShortInt). Geplant ist
;eine Ausgabe einer Phasenliste.
;
;PE:	*Siehe PA der FFT!
;
;PA:	*(Anfang +400h): 100h Imagi-
;naerteile(!!!) als ShortInt
;	*(Anfang +500h): 100h Real-
;teile als ShortInt
;	*(Anfang +600h): 100h Betraege
;als Byte-80h (fuer PLOT guenstig)
;	*(Anfang +700h): 100h Phasen
;als ShortInt (geplant)
;-128=-Pi/2, 0=0, 127= knapp Pi/2
;
;Hinweis: Die Integerwerte werden
;durch 16 dividiert. Falls sie dann
;immer noch betragsmaeszig groeszer
;als 127 (128) sind, werden die Werte
;beschnitten. In diesem Fall kann die
;Ruecktransformation kein befriedigen-
;des Ergebnis liefern. Als Gegenmasz-
;nahme gegen dieses Clipping sind die
;Eingangswerte kleiner zu bemessen.
;Ganz sicher sind Eingangswerte nur
;im Bereich -8..8.
;
;Kernel
;*** Unterfunktion PLOT fuer BASIC ***
plotb	in	a,88h
	bit	2,a
	jr	nz,plot	;fuer MC-Progs
	call	0f018h
	call	plot
	call	0f01bh
	ret
plot
	ld	hl,0b782h
	ld	b,8
	xor	a
plo1	ld	m,a	;Args zu Null
	inc	l
	djnz	plo1
	ld	e,a
	ld	a,(what)
	ld	d,a
	ld	a,(de)
	add	80h
	ld	l,88h
	ld	m,a
	inc	e
	jr	plot2
plot1
	ld	l,82h
	inc	m
plot2	ld	l,86h
	inc	m
	ld	l,88h
	ld	a,m
	ld	l,84h
	ld	m,a
	ld	a,(de)
	add	80h
	ld	l,88h
	ld	m,a

	push	hl
	push	de
	call	os
	db	3eh
	pop	de
	pop	hl
	inc	e
	jr	nz,plot1
	ret	;(plot)
;
;*** Die eigentliche FFT ***
fft
;Vorbereitung: High-Teile Vorzeichenset!
	ld	h,tabhi
	call	xcbw
	inc	h
	call	xcbw
	dec	h
	;
	ld	a,80h	;hy=n2
	ld	b,1	;b=argument
fftl1	;Aeuszere Schleife
	;8fach Durchlauf
	ld	hy,a
	ld	c,0	;c=angle
	ld	l,0	;l=j
fftl2	;Mittlere Schleife
	push	hl
	 ld	a,c
	 call	cosinus
	 ld	(cos),hl
	 ld	a,c
	 call	sinus
	 ld	(sin),hl
	pop	hl
	push	hl	;l=i
	 ld	a,l
	 add	hy
	 ld	e,a
	 ld	d,h
	 push	bc	;angle und arg
fftl3	;Innere Schleife
	;i=l
	;hl=^x(i)
	;de=^x(l)
	ld	c,m
	inc	h
	inc	h
	ld	b,m
	push	bc	;Stack:x(i)
	 ex	de,hl
	 ld	c,m
	 inc	h
	 inc	h
	 ld	b,m	;bc:x(l)
	ex	(sp),hl	;Stack:^x(l)
	 or	a
	 sbc	hl,bc
	 ld	(xdum),hl
	 add	hl,bc
	 add	hl,bc
	 ex	de,hl	;hl:^x(i)
	 ld	m,d
	 dec	h
	 dec	h
	 ld	m,e
	pop	de
	;
	inc	d
	inc	h
	ld	c,m
	inc	h
	inc	h
	ld	b,m
	push	bc	;Stack:y(i)
	 ex	de,hl
	 ld	b,m
	 dec	h
	 dec	h
	 ld	c,m	;bc:y(l)
	ex	(sp),hl	;Stack:^y(l)
	 or	a
	 sbc	hl,bc
	 ld	(ydum),hl
	 add	hl,bc
	 add	hl,bc
	 ex	de,hl	;hl:^y(i)
	 ld	m,d
	 dec	h
	 dec	h
	 ld	m,e
	pop	de
	dec	h
	dec	d
	;
	push	hl
	 push	de
	  ld	de,(xdum)
	  ld	bc,(cos)
	  call	mult
	   push	hl
	   ld	de,(ydum)
	   ld	bc,(sin)
	   call	mult
	  pop	de
	  add	hl,de
	 pop	de
	 ex	de,hl
	 ld	m,e
	 inc	h
	 inc	h
	 ld	m,d
	 push	hl	;hl:^y(l)
	  ld	de,(xdum)
;	  ld	bc,(sin)
	  call	mult
	   push	hl
	   ld	de,(ydum)
	   ld	bc,(cos)
	   call	mult
	  pop	de
	  or	a
	  sbc	hl,de
	 pop	de
	 ex	de,hl
	 inc	h
	 ld	m,d
	 dec	h
	 dec	h
	 ld	m,e
	 dec	h
	 ex	de,hl

	pop	hl
	;
;	call	os
;	db	23h,'i',0
	ld	a,hy
	add	a	;n2 2mal=n1
	add	e
	ld	e,a
	ld	a,l
	add	hy	;n2 2mal=n1
	jr	c,fftl3e
	add	hy	;Ueberlauf?
	ld	l,a
	jp	nc,fftl3
fftl3e	;Innere Schleife ENDE
;	call	os
;	db	23h,'j',0
	 pop	bc
	pop	hl
	inc	l	;j=Startindex
	ld	a,c
	add	b
	ld	c,a
	rla
	jp	nc,fftl2
	;Mittlere Schleife ENDE
;	call	os
;	db	23h,'k',0
	rlc	b	;Argument
	ld	a,hy
	rrca		;n2 halbieren
	jp	nc,fftl1
	;Aeuszere Schleife ENDE
;*** fft 2.Teil ***
	;z.Z.D=H=tabhi
	;de=^x(j)
	;hl=^x(i)
	ld	e,0	;e=j=0
	ld	l,0	;l=i=0
fftl4	;Schleife 4
	ld	a,l
	cp	e	;i<j?
	jr	nc,fftv1
	ld	b,4
fftx	 ld	c,m
	 ld	a,(de)
	 ex	de,hl
	 ld	m,c
	 ld	(de),a
	 inc	d
	 inc	h
	 djnz	fftx
	dec	h
	dec	h
	dec	h
	dec	h
	ld	d,h
;	call	os
;	db	23h,'e',0
fftv1	ld	c,80h	;c=k=n/2
	jr	fftw1
	;begin (WHILE)
fftw2	ld	e,a
	rr	c
;	call	os
;	db	23h,'2',0
fftw1	ld	a,e
	sub	c
	jr	nc,fftw2
	;end (WHILE)
	add	c
	add	c
	ld	e,a
	inc	l	;i++
;	call	os
;	db	23h,'I',0
	ld	a,l
	inc	a
	jr	nz,fftl4
	ret	;(END FFT)
;
;*** Cosinusquadratfenster ***
coswin
	ld	a,(what)
	ld	ly,0
	ld	hy,a
	ld	hl,0	;1.Sinuswert
coswl1
	push	hl	;Sinuswert
	call	coswup
	ld	a,ly
	inc	a
	srl	a
	call	sinus
	pop	de
	push	hl
	add	hl,de
	srl	h
	rr	l	;Arit.Mittel
	call	coswup
	pop	hl	;Sinuswert
	jr	nz,coswl1
	ret
;
coswup	ld	b,h
	ld	c,l
	ld	d,h
	ld	e,l
	push	iy
	call	mult
	pop	iy
	ld	c,l
	ld	b,h
	ld	e,(iy)
	ld	a,e
	rla
	sbc	a
	ld	d,a	;cbw
	push	iy
	call	mult
	pop	iy
	ld	(iy),l
	inc	ly
	ret
;
;*** Betragsbildung und ***
;*** Vorbereitung Ruecktrafo ***
betrag
	ld	hl,tab
	call	betr0
	inc	h
	call	betr0
	ld	de,tab+256
	inc	h
	call	copy
	inc	h
	dec	d
	call	copy
	inc	d	;"Real"teil
betrag1	ld	a,(de)
	call	quad
	push	hl
	dec	d
	ld	a,(de)
	call	quad
	pop	bc
	add	hl,bc
	jr	nc,betrag2
	ld	a,0ffh
betrag2	call	sqrt	;Pythagoras
	inc	d
	inc	d
betrag3	sub	80h ;anzeigeguenstig
	ld	(de),a	;Betrag
	dec	d
	inc	e
	jr	nz,betrag1
	ret

copy	;256 Bytes LDIR
	push	bc
	ld	bc,256
	ldir
	dec	h
	dec	d
	pop	bc
	ret
betr0	;Division/16 und Anschlag
	rld
	ld	e,m
	inc	h
	inc	h
	rld
	bit	7,e
	jr	z,betr5
	inc	m
	jr	nz,betr5;Carry-Ersatz
	inc	a
betr5	bit	3,a	;Vorzeichen
	jr	nz,betr1
	and	0fh
	jr	nz,betr3
	bit	7,m
	jr	z,betr2
betr3	ld	m,7fh	;Anschlag+
	jr	betr2
	;
betr1	or	0f0h
	inc	a
	jr	nz,betr4
	bit	7,m
	jr	nz,betr2
betr4	ld	m,80h	;Anschlag-
betr2	dec	h
	dec	h
	inc	l
	jr	nz,betr0
	ret
;
;*** Unterprogramme ***
xcbw	;Byte-zu-Word-Trafo
	ld	l,0
xcbw1	ld	a,m
	rla
	sbc	a	;wie CBW
	inc	h
	inc	h
	ld	m,a
	dec	h
	dec	h
	inc	l
	jr	nz,xcbw1
	ret
;
cosinus	;Cosinus
	add	40h
sinus	;Sinuswert ermitteln (Tabelle)
	;hl:=sin(a)
	;hl-Aufbau: V000000Y YYYYYYYY
	;(Vorzeichen - Betrag)
	ld	d,0
	ld	l,a
	rla		;Bit 7
	rr	d	;=Vorzeichen
	rla		;Bit 6
	ld	a,l
	jr	nc,sinu1
	cpl
	inc	a
	and	3fh	;Gipfel?
	jr	nz,sinu1
	set	0,d	;Gipfel!!!
sinu1
	or	0c0h
	cp	0feh
	jr	c,sinu2
	set	0,d	;100h
sinu2	ld	l,a
	ld	h,sintab/256
	ld	e,m
	ex	de,hl
	ret
;
quad	;Quadrat hl:=a^2 vzb=>vzl
	;VR:A,B,HL
	bit	7,a
	jr	z,quad1
	neg
quad1	push	de
	ld	b,8
	ld	d,0
	ld	e,a
	ld	h,d
	ld	l,d	;hl=0
quad2	add	hl,hl
	rla
	jr	nc,quad3
	add	hl,de
quad3	djnz	quad2
	pop	de
	ret
;
sqrt	;Wurzel a:=sqrt(hl) vzl=>vzl
	xor	a
	dec	a
	push	de
	ld	e,a
	ld	d,a
sqr1	inc	a
	inc	de
	inc	de
	sbc	hl,de
	jr	nc,sqr1
	sra	d	;halbieren
	rr	e	;cy=1
	add	hl,de
	bit	7,h
	jr	nz,sqr2
	inc	a       ;aufrunden
	jr	nz,sqr2	;100h?
	dec	a	;ffh!
sqr2	pop	de
	ret
;
mult	;Multiplikation
	;bc: 16bit Vorzeichen-Betrag
	;de: 16bit ZWK
	;hl: Ergebnis
	;VR:hl,de,af,ly
	ld	hl,0
	bit	0,b
	jr	z,mul1
	add	hl,de
	jr	mul2	;praktisch!
mul1	push	bc
	xor	a
	ld	b,a
	ld	ly,8
mul3	sra	d
	rr	e
	rr	b
	rlc	c
	jr	nc,mul4
	add	b
	adc	hl,de
mul4	dec	ly
	jr	nz,mul3
	pop	bc
	rla		;aufrunden?
	jr	nc,mul2
	inc	hl
mul2	bit	7,b
	ret	z
	ld	e,l
	ld	d,h
	ld	hl,0
	or	a
	sbc	hl,de
	ret
;
;*** Testteil ***
	db 7fh,7fh,'SINUS',1
	ld	a,l
	call	sinus
outhl	call	os
	db	1ah
	ret
	db 7fh,7fh,'MULT',1
	ld	b,h
	ld	c,l
	call	mult
	jr	outhl
	db 7fh,7fh,'QUAD',1
	ld	a,l
	call	quad
	jr	outhl
	db 7fh,7fh,'SQRT',1
	call	sqrt
	ld	l,a
	ld	h,0
	jr	outhl
	db 7fh,7fh,'JPHL',1
	jp	(hl)
;
;*** Variablen ***
xdum	dw	0
ydum	dw	0
sin	dw	0
cos	dw	0
;*** Tabellenteil ***
	ds	anfang+3c0h-$
sintab
	DB	00H,06H,0DH,13H
	DB	19H,1FH,26H,2CH
	DB	32H,38H,3EH,44H
	DB	4AH,50H,56H,5CH
	DB	62H,68H,6DH,73H
	DB	79H,7EH,84H,89H
	DB	8EH,93H,98H,9DH
	DB	0A2H,0A7H,0ACH,0B1H
	DB	0B5H,0B9H,0BEH,0C2H
	DB	0C6H,0CAH,0CEH,0D1H
	DB	0D5H,0D8H,0DCH,0DFH
	DB	0E2H,0E5H,0E7H,0EAH
	DB	0EDH,0EFH,0F1H,0F3H
	DB	0F5H,0F7H,0F8H,0FAH
	DB	0FBH,0FCH,0FDH,0FEH
	DB	0FFH,0FFH,00H,00H
;Datentabellen ab anfang+400h
tab	
tabhi	equ	$/256
;	Hintrafo	Ruecktrafo
;+400h:	X Low		B Low
;+500h:	Y Low		A Low
;+600h:	X High		Beträge
;+700h:	Y High		(Phasen)
	END
ääää ä!ä"ä#ä$ä%ä&ä'ä(ä)ä*ä+ä,ä-ä.ä  0ä1ä2ä3ä4ä5ä7äLà8ä9ä:ä;ä<ä=ä>ä?ä@ä
Detected encoding: OEM (CP437)1
Wrong umlauts? - Assume file is ANSI (CP1252) encoded