Forum: Digitale Signalverarbeitung / DSP / Machine Learning Skalierung auf Int bei einer FFT (128-Punkte)


von tiffy (Gast)


Lesenswert?

Hallo ich hab da glaub ich ein kleines Verständbisproblem beim skalieren 
auf Int Werte bei einer FFT.

Also ich habe eine FFT implementiert, die mit float zahlen auch richtig 
rechnet. Nun möchte ich diese auf Int "umbauen".
Ich bekomme vom ADC 12-Bit Zahlen, im Bereich von 2047 bis -2048.
Diese werden entsprechend umsortiert und gehen dann in den FFT 
Algorithmus.
Ein Int Wert ist auf meinem µC 16 Bit (MSP430).
Als Int Werte werden die ADC-Zahlen in eine 16-Bit Variable gespeichert.
Da die Werte der "Twiddlefaktoren" zwischen -1 und 1 liegen müsste ich 
diese skalieren. Ich kann diese dann doch mit 2^15 skalieren und dann 
nach jeder Multiplikation mit dem Hardware-Multiplizierer (16-bit *16 
bit) nur das Higher Word (also die oberen 16 Bit) des Ergebnisses für 
die weitere Berechnung nutzen oder verstehe ich das falsch? Wenn ich 
noch eine Fensterfunktion einsetze kann ich doch analog vorgehen oder?

: Verschoben durch Admin
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Hängt vom Format ab, das du wählst.

Deine Zahlen sind 13 Bit signed, also im 1.12 signed Q-Format. Um das in 
16 Bits einzubetten hast du 4 mögliche Positionen für den Dezimalpunkt, 
d.h. du hast die Wahl zwischen
1.15
2.14
3.13 und
4.12

1.15 bringt dir die maximale Genauigkeit an Nachkommastellen. ALlerdings 
ist zu bedenken, daß auch Überläufe aufteten könnten. So ist -1 = 0x8000 
= -0x8000 = -(-1) weil 1 = -1 ist.

Daher ist es u.U. günstiger, 2.14 zu wählen oder 4.12 wenn es um 
Effizienz geht. Da 2.14*2.14 = 4.28 ergibt sich der Ergebnis einer 
Multiplikation aus den oberen 16 Bit nach einem Linksshift um 2. Analog 
ergibt sich das Ergebnis bei 4.12*4.12 = 8.24 aus dem High-Word nach 
einem L-Shift um 4 und bei 1.15*1.15 = 2.30 nach einem L-Shift um 1.

Johann

von tiffy (Gast)


Lesenswert?

Als muss ich auch an den adc werten skalieren und nicht nur an den 
Twiddlefaktoren? Diese würde ich mit 2^15 erweitern, dann hätte ich ja 
das 1.15 Format richtig?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

tiffy schrieb:
> Als muss ich auch an den adc werten skalieren und nicht nur an den
> Twiddlefaktoren? Diese würde ich mit 2^15 erweitern, dann hätte ich ja
> das 1.15 Format richtig?

Ja. Wobei die Berechnung der 128-ten Einheitswurzeln und deren 
Skalierung mit 2¹⁵ zur Compilezeit (oder vorher) geschehen kann, also 
nicht auf dem µC berechnet werden muss.

Johann

von tiffy (Gast)


Lesenswert?

Ja über look-up tabel dann halt. Könnte ich dir evtl. mal den Code 
schicken den ich bis jetzt habe? Kan ihn hier natürlicha uch posten. Ich 
bin mir nämlich nicht ganz sicher, wie ich das Ergebnis so zu 
interpretieren habe.

von bingo (Gast)


Lesenswert?

Wenn ich nix an den Eingangswerten aus dem ADC aendere, also sie einfach 
so in eine 16 bit int variable speicher, und diese anschliessend mit der 
mit 2^15 skalierten Zahl (dem twiddlefaktor) multipliziere bekomme ich 
dann als Ergebnis eine 2.30 Zahl ?

von Detlef _. (detlef_a)


Lesenswert?

tiffy schrieb:

> Als Int Werte werden die ADC-Zahlen in eine 16-Bit Variable gespeichert.
> Da die Werte der "Twiddlefaktoren" zwischen -1 und 1 liegen müsste ich
> diese skalieren. Ich kann diese dann doch mit 2^15 skalieren und dann
> nach jeder Multiplikation mit dem Hardware-Multiplizierer (16-bit *16
> bit) nur das Higher Word (also die oberen 16 Bit) des Ergebnisses für
> die weitere Berechnung nutzen oder verstehe ich das falsch?

Was Du sagst ist richtig, Du verlierst natürlich Genauigkeit, i.e. Dein 
Rauschfloor geht hoch, aber das geht so.

Was nicht geht: Du kommst mit 12Bit Zahlen rein und machst eine 128er 
FFT, entsprechend 7 stages des Algorithmus. In jeder stage gewinnst Du 
maximal 1 Bit hinzu, selbst wenn Du die twiddle Faktoren skalierst, hast 
Du als Ergebnis der FFT 12+7 = 19 Bit Werte, die passen nicht in 16Bit 
Variablen rein. Der Overflow ist aber signalabhängig, breitbandiges 
Signal macht breitbandiges Spektrum, also nix mit Spitzen, Sinus macht 
einen peak, der zum Overflow führt. Entweder 32Bit rechnen oder 
dynamisch skalieren: runtershiften, wenn Overflow droht.

Cheers
Detlef

von tiffy (Gast)


Lesenswert?

Um dem vorzubeugen werden die Eingangsgroessen in jeder Stufe halbiert. 
Ich kanns ja m,al posten:
1
MPYS = (eingangsvektor_real[q]);
2
        OP2 = W_faktoren_128_real[W_exponent];
3
        MACS = -(eingangsvektor_imag[q]);
4
        OP2 = W_faktoren_128_imag[W_exponent];
5
        buffer_real = (RESHI);                         //dies entspricht der Haelfte des Ergebnisses der eigentlichen
6
                                                       //Multiplikation -->(Q_real*W_real-Q_imag*W_imag)/2
7
  
8
        MPYS = (eingangsvektor_real[q]);
9
        OP2 = W_faktoren_128_imag[W_exponent];
10
        MACS = (eingangsvektor_imag[q]);
11
        OP2 = W_faktoren_128_real[W_exponent];
12
        buffer_imag = (RESHI);                         //dies entspricht der Haelfte des Ergebnisses der eigentlichen
13
                                                       //Multiplikation -->(Q_real*W_imag+Q_imag*W_real)/2
14
        
15
        eingangsvektor_real[q] = ((eingangsvektor_real[p] >>1) - buffer_real);  //Q_real'=Q_real/2 - (Q_real*W_real-Q_imag*W_imag)/2
16
        eingangsvektor_imag[q] = ((eingangsvektor_imag[p] >>1) - buffer_imag);  //Q_imag'=Q_imag/2 - (Q_real*W_imag+Q_imag*W_real)/2
17
        eingangsvektor_real[p] = ((eingangsvektor_real[p] >>1) + buffer_real);  //P_real'=P_real/2 + (Q_real*W_real-Q_imag*W_imag)/2
18
        eingangsvektor_imag[p] = ((eingangsvektor_imag[p] >>1) + buffer_imag);  //P_imag'=P_imag/2 + (Q_real*W_imag+Q_imag*W_real)/2
so sieht bei mir die berechnung eines butterfly aus.

von tiffy (Gast)


Lesenswert?

ist aus engelehnt an einem application note von ti (SLAA042)

von tiffy (Gast)


Lesenswert?

Und jemand ne meinung dazu?

von Detlef _. (detlef_a)


Lesenswert?

tiffy schrieb:
> Und jemand ne meinung dazu?
Das verschenkt jede Menge Genauigkeit. Ich weiß nicht, was Du willst und 
Dir leisten kannst: Schnelle Berechnung mit hohem eingeschlepptem 
Rauschen oder langsamer und genauer oder irgendwas dazwischen.

Cheers
Detlef

von tiffy (Gast)


Lesenswert?

Sehr genau muesste es im Prinzip nicht sein, kann man den Fehler den man 
sich einheimst irgendwie beziffern?

von Detlef _. (detlef_a)


Lesenswert?

Sicher gibts Aussagen zur Genauigkeit und Fehlerfortpflanzung in 
integer-FFTs, konkrete Literatur ist mir aber nicht bekannt. Ich würds 
einfach in C auf einem PC ausprobieren.

Cheers
Detlef

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.