2

Ich möchte ein SDR-System zusammenstellen, das zuerst AM, später FM usw. stimmt. Das System, das ich dazu verwenden möchte, wird eine Sinus-Nachschlagetabelle für Direct Digital Synthesis (DDS) haben. Um richtig abstimmen zu können, muss ich in der Lage sein, die Frequenz der dem Mixer zugeführten Sinuswelle genau zu steuern (Multiplikator in diesem Fall). Ich erwarte, dass die lineare Interpolation nah ist, aber denke, dass eine nicht-lineare Methode bessere Ergebnisse liefern wird.Sinus-Tabellen-Interpolation

Was ist eine gute und schnelle Interpolationsmethode für Sinus-Tabellen. Multiplikation und Addition sind günstig auf dem Zielsystem; Teilung ist teuer.

Edit: Ich plane die Implementierung von Konstanten mit Multiply/Shift-Funktionen, um die Konstanten zu skalierten Ganzzahlen zu normalisieren. Zwischenwerte verwenden breite Additionen, und Multiplikationen verwenden 18 oder 17 Bits. Fließkomma-Vorberechnung kann verwendet werden, jedoch nicht auf der Zielplattform. Wenn ich sage "Teilung ist teuer", meine ich, dass es mit den Multiplikatoren und viel Code implementiert werden muss. Es ist nicht undenkbar, sollte aber vermieden werden. True-Floating-Point-IEEE-Methoden erfordern jedoch eine erhebliche Menge an Ressourcen auf dieser Plattform sowie eine benutzerdefinierte Implementierung.

Alle SDR-Erfahrungen wären hilfreich.

+0

Haben Sie eine lineare Interpolation ausgewertet? Ein schnelles Programm auf einem PC, das die erwarteten Eingaben durchläuft, sollte Ihnen die Fehlergröße einer vorgeschlagenen Lösung anzeigen. –

+0

Ich habe DDS nicht gemacht, aber ich habe FM und Phasenverzerrungssynthese gemacht. Ich habe gerade ein wenig über DDS nachgelesen. Es hört sich so an, als ob lineare Interpolation oft verwendet wird, aber ich denke, dass Sie den Grundrauschen etwas mit etwas besser als linear senken können. Wenn Sie mit der Implementierung beginnen, sollten Sie eine FFT an der Ausgabe vornehmen und bekannte Wellen durch die Eingabe setzen, um zu sehen, was Ihr Grundrauschen ist und ob Sie irgendwelche Artefakte erhalten. – Nosredna

Antwort

3

Interpolation in einer Sinustabelle ist effektiv Resampling. Natürlich können Sie perfekte Ergebnisse durch einen einzigen Anruf an sin erhalten, also was auch immer Ihre Lösung ist, muss es übertreffen. Für das Resampling mit festen Filtern steht Ihnen immer noch ein fester Satz verfügbarer Punkte zur Verfügung (ein 3: 1 Upsampler bedeutet, dass Sie zwischen jedem Punkt in Ihrer Tabelle 2 neue Punkte haben). Wie teuer ist der Speicher auf dem Zielsystem? Meine primäre Empfehlung ist einfach die Tabellenauflösung zu verbessern und lineare Interpolation zu verwenden. Sie erhalten dieselben Ergebnisse wie eine kleinere Tabelle und eine einfache Upsamples, jedoch mit weniger Rechenaufwand.

+0

Leider werde ich nicht eine "Sünde" -Funktion nennen.Ich könnte ein C-Programm auf meinem PC schreiben, um die Sinustabelle für mich zu erzeugen, aber keine C-lib auf dem Ziel. Speicher ist nicht billig, ich kann Logic für schnellen Speicher tauschen, aber es ist eine begrenzte Systemressource. Ich sollte in der Lage sein, Mathe zu pipelineieren, solange es nicht zu verrückt wird. – NoMoreZealots

7

Wenn Sie mit der linearen Interpolation keine sehr guten Ergebnisse erzielen, können Sie die trigonometrischen Beziehungen ausprobieren.

Summe und Differenz Formeln

sin(A+B)=sinA*cosB + cosA*sinB 
sin(A-B)=sinA*cosB - cosA*sinB 
cos(A+B)=cosA*cosB - sinA*sinB 
cos(A-B)=cosA*cosB + sinA*sinB 

und Sie vorberechnete sin haben können und cos-Werte für A, B reicht, dh

A range: 0, 10, 20, ... 90 
B range: 0.01 ... 0.99 
+0

Das klingt nach einer anständigen Idee. Ich muss darüber nachdenken. Ich plane, eine FPGA-Plattform zu verwenden und VHDL zu codieren, deshalb mag ich die Tatsache, dass dies nur mit Multiplikatoren und Volladdierern funktionieren kann. Ich muss einen Testcode schreiben, um zu sehen, ob er mich dahin bringt, wo ich sein möchte. – NoMoreZealots

+0

Entweder muss der A-Bereich in 1-Grad-Schritten oder der B-Bereich bis 9,99 verlängert werden - oder Sie müssen den Vorgang mehrmals wiederholen, um zu Sinus (27,5) zu gelangen. –

+0

@ Jonathan Leffler Ich denke, du hast Recht, aber ich habe die Idee. Mit 18-Bit-Multiplizierern gelangt man zu dem Punkt, dass der Nulldurchgang 5 Tabelleneinträge benötigt, um von 1 bis -1 zu gehen, was der steilste Teil der Kurve ist, mit 2 1k-Tabellen (effektiv 20-Bit-Auflösung bei der Suche, die schnell ist Verwenden von CLBs als Mini ROMs.). Mathematische Methoden würden mehr Multiplizierer und Addierer erfordern und bringen mich in meiner Auflösungsbande nicht näher zu erhöhter Komplexität. – NoMoreZealots

4

Tabelleninterpolation für glatte Funktionen = ick schleudern bleah. IMHO würde ich nur Tabelleninterpolation auf irgendeine wirklich merkwürdige Funktion verwenden, oder wo Sie unbedingt sicherstellen mussten, dass Sie Diskontinuitäten vermeiden (beachten Sie, dass die Ableitungen für interpolierte Tabellen jedoch diskontinuierlich sind). Zu dem Zeitpunkt, an dem Sie mit der Suche nach Tabellen und dem erforderlichen Interpolationscode fertig sind, könnten Sie bereits ein oder zwei Polynome ausgewertet haben, zumindest, wenn die Multiplikation nicht zu viel Sodbrennen verursacht.

IMHO Sie sind viel besser dran mit Chebyshev approximation für jedes Segment (zB -90 bis +90 Grad oder -45 bis +45 Grad, und dann andere Segmente der gleichen Breite) der Sinus-Wellenform, und die Auswahl der Minimum-Grad-Polynom, das Ihren Fehler auf einen gewünschten Wert reduziert. Wenn das Segment klein genug ist, könnte man mit einem quadratischen oder sogar einem linearen Polynom davonkommen; Es gibt Kompromisse zwischen der Genauigkeit und der Anzahl der Segmente und dem Grad des Polynoms.

Siehe my post in this other question, es wird Ihnen die Mühe ersparen, Koeffizienten zu berechnen (zumindest, wenn Sie meiner Mathematik glauben).

(bearbeiten: falls dies nicht klar war, machen Sie die Chebyshev-Näherung zur Entwurfszeit auf Ihrem bevorzugten Hochleistungs-PC, so dass Sie zur Laufzeit einen Dirtbag-Mikrocontroller oder FPGA oder was auch immer mit a Einfaches Polynom von Grad 1-4 Gehen Sie nicht über Grad 4 hinaus, es sei denn, Sie wissen, was Sie tun, 3 oder weniger wären besser.)

+0

Eigentlich komme ich mit diesem Algorithmus noch nicht ganz dahin, wo der Precomputed PC/Embedded System Breakpoint liegt. Es scheint, es kostet 6 Multiplikatoren zu tun. Ich muss Nick vergleichen. D Antwort der Antwort darauf für 18-Bit-Multiplikatoren. Ich benutze die FP eines armen Mannes, skalierte Konstanten mit einem fest verdrahteten Bitshift. – NoMoreZealots

1

Haben Sie in Betracht gezogen, die Taylor-Serie für die trigonometrischen Funktionen zu verwenden (gefunden here) Dies beinhaltet Multiplikation und Division, aber abhängig davon, wie Ihre Zahlen dargestellt werden, können Sie die Division in Multiplikation umwandeln (oder Bit-Shifts, wenn Sie viel Glück haben). Sie können so viele Terme der Serie berechnen, wie Sie benötigen, und erhalten so Ihre Präzision.

Wenn diese Sinuswelle an einem bestimmten Punkt ein analoges Signal ist, können Sie alternativ einen Lookup-Tabellenansatz verwenden und einen analogen Filter verwenden, um die Abtastfrequenz von der resultierenden Wellenform zu entfernen. Wenn Ihre Abtastfrequenz das 100-fache der Sinusfrequenz beträgt, ist sie leicht zu entfernen. Sie benötigen dazu einen variablen Filter. Ich habe noch nie so etwas gemacht, aber ich weiß, dass es digitale Potentiometer gibt, die eine Binärzahl nehmen und ihren Widerstand ändern. Das könnte die Basis eines variablen RC-Filters sein - wahrscheinlich mit einigen Operationsverstärkern für die Verstärkung usw.

Viel Glück!

+0

Taylor kommt viel zu langsam, IMO. Und das Filtern verändert die Phase. – Nosredna

+0

Division ist nicht undenkbar, ich habe es mir selbst gedacht, aber es ist sehr teuer auf dieser Plattform und sollte für Anwendungen reserviert werden, die nicht anders möglich sind – NoMoreZealots

+1

Taylor-Serie nicht Division verwenden ... und in den meisten Fällen sollte zugunsten der Chebyshev-Näherungen vermieden werden, da sie Konvergenz und Fehler garantiert haben, die absichtlich gleichmäßig verteilt sind. –

4

Warum eine Tabelle? This very fast function hat seinen stärksten Geräuschpegel bei -90db, wenn das Signal bei -20db liegt. Das ist verrückt gut.

Für das Resampling von Audio verwende ich immer einen der Interpolatoren vom Elephant Papier. Dies wurde in einer previous SO question diskutiert.

Wenn Sie auf einem Prozessor sind, der nicht fp hat, können Sie diese Dinge immer noch tun, aber sie sind schwieriger. Ich war dort. Ich fühle deinen Schmerz. Viel Glück! Früher habe ich Conversions für fp in Integer gemacht, aber jetzt müsstest du mich dafür bezahlen.

:-)

Coole Online-Referenzen, die auf Ihr Problem anwenden:

http://www.audiomulch.com/~rossb/code/sinusoids/

http://www.dattalo.com/technical/theory/sinewave.html


Edit: zusätzliche Gedanken basierend auf Ihre Kommentare

Da Sie an einem kniffligen Prozessor arbeiten, sollten Sie sich vielleicht überlegen, wie Sie Ihren Sinustisch mehr Winkel zum Nachschlagen haben lassen, aber trotzdem klein bleiben.

Angenommen, Sie brechen einen Quadranten in 90 Teile (in Wirklichkeit würden Sie wahrscheinlich 256 Teile verwenden, aber lassen Sie es 90 für Vertrautheit und Klarheit). Codiere diese als 16 Bits. Das sind bisher 180 Byte Tabelle.

Nun werden wir für jeden dieser Grade 9 (in Wirklichkeit wahrscheinlich 8 oder 16) Zwischenpunkte haben.

Nehmen wir als Beispiel den Bereich zwischen 3 Grad und 4 Grad.

sin(3)=0.052335956 //this will be in your table as a 16-bit number 
sin(4)=0.069756474 //this will be in your table as a 16-bit number 

Also werden wir uns die Sünde ansehen (3.1)

sin(3.1)=0.054978813 //we're going to be tricky and store the result 
        // in 8 bits as a percentage of the distance between 
        // sin(3) and sin(4) 

Was Sie tun möchten, ist, herauszufinden, wie sin (3.1) passt zwischen sin (3) und sin (4). Wenn es auf halbem Wege liegt, codiere das als ein Byte von 128. Wenn es ein Viertel ist, codiere das als 64.

Das sind zusätzliche 90 Bytes und du hast bis zu einem Zehntel Grad in 16-Bit res in nur 180 + 90 * 9 Bytes. Sie können nach Bedarf erweitern (bis zu 32-Bit-Winkel und 16-Bit-Tween-Winkel) und dazwischen sehr schnell interpolieren. Um Speicherplatz zu sparen, nutzen Sie die Tatsache, dass aufeinanderfolgende Werte nahe beieinander liegen.


Edit 2: bessere Art und Weise die in-zwischen den Winkeln in einer Tabelle

ich gerade daran erinnert, dass, wenn ich das tat ich sehr kompakt die zwischen dem erwarteten Unterschied zum Ausdruck endete bis zu kodieren Wert nach linearer Interpolation und dem tatsächlichen Wert. Dieser Fehler ist immer in der gleichen Richtung.

Zuerst berechnete ich den maximalen Fehler in dem Bereich und dann basierte die Skala darauf.

Großartig gearbeitet. Ich habe das Gefühl, ich sollte den Code in einem Blogeintrag illustrieren. :-)

+0

@Nosredna: Ich denke, du verpasst etwas: diese zusätzlichen 90 Bytes sind nicht für jedes der 90 Stücke gleich; Sie müssten 90 Bytes x 90 Pieces = 8100 Bytes für Ihr Schema hinzufügen. –

+0

(Sie könnten Winkelsummen-/Differenzformeln nach Nick Ds Vorschlag verwenden) –

+0

Ja! Ich habe das vermasselt. Festsetzung. – Nosredna

0

Die Leute haben einen erstaunlich cleveren Code für die schnelle Berechnung von sin() auf Systemen mit winzigen Mengen an Speicher geschrieben, die nicht einmal einen Hardware-Multiplikationsbefehl haben, geschweige denn einen Divisionsbefehl.

Um die zunehmende Komplexität:

  • eine Rechteckwelle verwenden. Viele AM-Radios verwenden Rechteckwellen in ihrem ring demodulator, und ich verstehe nicht, warum Ihr AM-Demodulator etwas Komplizierteres erfordert.

  • Ungefähre sin() durch Nachschlagen des "nächsten Werts" in einer Rohtabelle von 256 Werten pro Viertelzyklus. Ja, Sie sehen schrecklich aussehende Treppenstufen, aber (mit ein wenig analoger Filterung) funktioniert das oft gut. (In der Tat ist dies oft übertrieben, und eine viel kürzere Tabelle ist angemessen).

  • Ungefähre sin() durch Nachschlagen der 2 am nächsten liegenden Werte in einer Rohtabelle und lineares Interpolieren zwischen ihnen.

  • Ungefähr sin() mit 16 kurzen, gleichmäßig beabstandeten kubischen Splines pro Viertelzyklus "ergibt mehr als 16-Bit-Genauigkeit" für sin (x).

Wikibooks: Fixed-Point Numbers Links zu einigen cleveren Implementierungen der letzten 3.