Guten Morgen, ich mache gerade ein paar Gedankenexperimente zu simplem DSP auf einem AVR. Dabei bin ich auf folgendes Dilemma gestoßen: Ich krieg regelmäßig Samples vom ADC, die ich für den nachgeschalteten Filter puffern muss. Eigentlich ein klassischer Ringpuffer, aber... der Filter greift immer auf "absolute" Positionen im Buffer zu. Irgendwie habe ich hier die Wahl zwischen pest oder Cholera: Variante 1: "Schiebe-Buffer": immer wenn ein neuer Wert vom ADC kommt, schiebe ich den gesamten Buffer um eins weiter. Vorteil: effizienter Zugriff des Filters auf den Buffer Nachteil: das Schieben ist ineffizient, jeweils ein Load/Store (je zwei takte), bei einer bufferlänge von 64 sind das schon 256 takte. Schlechte Idee. Variante 2: Ringbuffer Vorteil: Eintragen eines neuen Wertes geht sehr einfach: Wert Schreiben, Index erhöhen, Wrap-around Nachteil: Der Filter greift auf variable Adressen zu, ich muss für jeden Koeffizienten den Index addieren und ein mögliches Wrap-Around berücksichtigen. Je nach Länge des Buffers und der Anzahl der Zugriffe vom Filter wird vielleicht die eine oder andere variante optimaler sein. ich überlege die ganze Zeit, obs da nicht noch eine dritte oder vierte Variante gibt, die das eleganter (und effizienter) macht... Eine Idee wäre, die Filterkoeffizienten zweimal hintereinander im Speicher abzulegen, den offset (=Index) statt für den Ringbuffer für die Koeffizienten zu verwenden (kommt aufs gleiche raus), nachdem die Koeffizienten zweimal da sind, gibts kein Wrap-Around. Bei 64 Koeffizienten ist das halt ziemliche Verschwendung... Eine weitere (böse) Idee wäre self-modifying code: das Displacement des "LD r, Y+i" zu verändern.. (nein, bitte nicht schlagen, ist nicht ganz ernst gemeint) Sonst noch Ideen? Ein weiteres Gedankenproblem harrt einer Lösung: u.U. werden die Werte vom ADC nicht in einen 64 Byte langen Buffer geschrieben, sondern nacheinander auf 8 Buffer aufgeteilt, es gibt auch 8 verschiedene Filter mit verschiedenen Koeffizienten... im Prinzip also 8 ähnliche, aber verschiedene Funktionen, bei jedem Sample wird reihum eine der Funktionen aufgerufen. Wie böse ist es, 8 ISRs zu machen, und reihum den Vektor zu verbiegen? (angenommen man wäre wirklich auf jeden clock cycle angewiesen) Edit: Vektor verbiegen ist natürlich eine dämliche Idee, nachdem der im ROM liegt, und die Schreibzyklen endlich sind...
Michael Reinelt schrieb: > Nachteil: Der Filter greift auf variable Adressen zu, ich muss ... ein > mögliches Wrap-Around berücksichtigen. Bei einer Zweierpotenz als Pufferlänge ist das nicht soo arg schlimm. > (angenommen man wäre wirklich auf jeden clock cycle angewiesen) Ich würde dann einfach auf einen potenteren Rechner umsteigen. Man muss nicht jedes Problem mit dem kleinsten derzeit verfügbaren Rechner erledigen... > Eine weitere (böse) Idee wäre self-modifying code Wie willst du das beim AVR machen? > ist nicht ganz ernst gemeint "Nicht ganz"? Also "ein wenig" durchaus?
Lothar Miller schrieb: > Bei einer Zweierpotenz als Pufferlänge ist das nicht soo arg schlimm. Insbesondere wenn der Puffer genau eine 256-Byte Seite belegt.
Lothar Miller schrieb: > Michael Reinelt schrieb: >> Nachteil: Der Filter greift auf variable Adressen zu, ich muss ... ein >> mögliches Wrap-Around berücksichtigen. > Bei einer Zweierpotenz als Pufferlänge ist das nicht soo arg schlimm. Trotzdem... es geht mir ums (gedankliche) Prinzip >> (angenommen man wäre wirklich auf jeden clock cycle angewiesen) > Ich würde dann einfach auf einen potenteren Rechner umsteigen. Man > muss nicht jedes Problem mit dem kleinsten derzeit verfügbaren Rechner > erledigen... Siehe oben. Ist ja mehr ein Gedankenexperiment, und es macht mir einfach Spaß, Probleme durch "fortschrittliches Denken" zu lösen, statt es mit GHz zu bewerfen. >> Eine weitere (böse) Idee wäre self-modifying code > Wie willst du das beim AVR machen? Ok, der Punkt geht eindeutig an dich :-) >> ist nicht ganz ernst gemeint > "Nicht ganz"? Also "ein wenig" durchaus? Mehr so als Reminiszenz an "the Story of Mel" :-)
Filter macht man mit der MAC Anweisung : Multiply and Accumulate. Zwei Pointer : Einen aufs erste Sample einen auf den ersten Koeffizienten. Dann einen Loop drueber, mit autoincrement der beiden Pointer. Wo liegt das Problem. Nein, ein Tiny ist da nicht passend. Aber auch der koennte das. Schnell.
Jetzt Nicht schrieb: > Wo liegt das Problem. Sorry, aber ich fürchte du hast das problem nicht verstanden, oder?
Jetzt Nicht schrieb: > Nein, ein Tiny ist da nicht passend. Aber auch der koennte das. Schnell. Tinys haben allerdings keinen Multiplier.
Michael Reinelt schrieb: > aber... der > Filter greift immer auf "absolute" Positionen im Buffer zu. Dann eben ändern. Der AVR kann auch Pointerzugriffe mit Autoincrement oder Displacement. Und für das Wrap around unterteilt man die Filter-Loop in 2 Loops oder testet jedesmal.
Peter Dannegger schrieb: > Michael Reinelt schrieb: >> aber... der >> Filter greift immer auf "absolute" Positionen im Buffer zu. > > Dann eben ändern. Der AVR kann auch Pointerzugriffe mit Autoincrement > oder Displacement. Beides hat aber das problem des WrapArounds, was ich für jede position prüfen müsste. > Und für das Wrap around unterteilt man die Filter-Loop in 2 Loops Ja! Natürlich! (sich mit dem hammer auf den kopf hauend...) Danke, Peter. Wie so oft sehe ich das naheliegende nicht...
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.