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
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
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?
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
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.
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 ?
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
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.
ist aus engelehnt an einem application note von ti (SLAA042)
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
Sehr genau muesste es im Prinzip nicht sein, kann man den Fehler den man sich einheimst irgendwie beziffern?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.