Uebung 8: DSP-Realisierung FIR
Transcription
Uebung 8: DSP-Realisierung FIR
ZHAW, DSV1, 2009/01, Rumc, Hhrt, Dqtm 1 Uebung 8: DSP-Realisierung FIR-Filter Teil 1: Bandpass Matlab-Entwurf a) Entwerfen Sie mit Hilfe der Fenster-Methode (Hamming-Fenster) ein FIR-Bandpass-Filter der Ordnung N = 126 (127 Filterkoeffizienten), das einen Durchlassbereich von fDBu = 400 Hz bis fDBo = 3400 Hz aufweist (-6 dB Eckfrequenzen). Plotten Sie die Impulsantwort und den Amplitudengang [dB] des BP-Filters. Speichern Sie die FIR-Filterkoeffizienten im h-File bp.h, mit dem Sie dann den entsprechenden Koeffizientenvektor im C-File initialisieren können. Beachten Sie, dass Sie bei einem Fixed-Point-DSP die Koeffizienten im Q15-Format abspeichern müssen (= mit 2^15 multiplizieren und Nachkommastellen abschneiden). Hinweis: Sie können die Vorlage dsv1ueb8.m verwenden DSP-Realisierung Vorbereiten: 1. Die Vorlage für alle sample-basierten DSP-Labors finden Sie im Web unter https://home.zhaw.ch/~rumc/dsv1/uebungen/DSK5510_vorlage.zip Kopieren und dekomprimieren Sie dieses Archiv in ein lokales Verzeichnis und entfernen Sie allenfalls den Schreibschutz. 2. Starten Sie die Entwicklungsumgebung Code Composer Studio und öffnen Sie das Projekt mit Project -> Open... -> tone.pjt Klicken Sie auf das + links von tone.pjt, unter Source finden Sie die Quelldatei tone.c. Öffnen Sie diese durch Doppelklick. 3. Eine kurze Anleitung für die Arbeit mit der Entwicklungs-Umgebung finden Sie am Ende der Datei tone.c Hier wird auch beschrieben, wie Sie zum Debuggen Variablen verfolgen und ändern können. 4. Die while-Schleife in der Vorlage liest den linken und den rechten Kanal ein, kopiert diese beiden Samples um und gibt sie aus. Damit lässt sich testen, ob die Entwicklungsumgebung und das Evaluationboard laufen, bevor mit dem Programmieren begonnen wird. b) Compilieren, laden und starten Sie das Programm. Das Signal am Eingang wird zum Ausgang durchgeschlauft. Bevor Sie weitermachen testen Sie das mit CD-Player und Kopfhörer oder mit Funktionsgenerator und Oszilloskop. c) Messen Sie die Zeitverzögerung zwischen Eingangs- und Ausgangssignal. Sie stammt alleine vom Codec. Wieviele Abtastperioden Ts verzögert dieser Codec das Signal bei der AD-DA-Wandlung insgesamt? Hinweis: Für welche Eingangsfrequenz ist die Zeitverschiebung 1 Periode? 2 ZHAW, DSV1, 2009/01, Rumc, Hhrt, Dqtm d) Verwenden Sie die C-Funktion fir aus der DSPLIB (die mit dem DSP mitgeliefert wird). Hier ist ein Ausschnitt aus dem Manual (Manual SPRU422i unter DSV1 Webpage, FIR Befehl S.4-46): ushort oflag = fir (DATA *x, DATA *h, DATA *r, DATA *dbuffer, ushort nx, ushort nh) dbuffer[nh+2] x x[j+126] x[j+125] x[j+124] … x[j+2] x[j+1] x[j] … b2 b1 b0 x[j-1] h[nh] b126 b125 b124 r x[nx] h[nh] Pointer to input vector of nx real elements. Pointer to coefficient vector of size nh in normal order. For example, if nh=6, then h[nh] = {h0, h1, h2, h3, h4, h5} where h0 resides at the lowest memory address in the array.·This array must be located in internal memory since it is accessed by the C55x coefficient bus. r[nx] Pointer to output vector of nx real elements. In-place computation (r = x) is allowed. dbuffer[nh+2] Pointer to delay buffer of length nh = nh + 2· In the case of multiplebuffering schemes, this array should be initialized to 0 for the first filter block only. Between consecutive blocks, the delay buffer preserves the previous r output elements needed.The first element in this array is special in that it contains the array index-1 of the oldest input entry in the delay buffer. This is needed for multiple-buffering schemes, and should be initialized to 0 (like all the other array entries) for the first block only. nx Number of input samples nh The number of coefficients of the filter. For example, if the filter coefficients are {h0, h1, h2, h3, h4, h5}, then nh = 6. Must be a minimum value of 3. For smaller filters, zero pad the coefficients to meet the minimum value. oflag Overflow error flag (returned value)· If oflag = 1, a 32-bit data overflow occurred in an intermediate or final result. If oflag = 0, a 32-bit overflow has not occurred. Um zu testen, ob man eine Funktion richtig aufruft, verwendet man oft Trivialfilter, deren Verhalten einfach und bekannt ist. Bei einem FIR-Filter ist das z.B. b0 = 1, b1 = 0, b2 = 0. Was muss dieses Filter ausgeben? Deklarieren und initialisieren Sie alle benötigten Variablen. Packen Sie die Filter so in eine if-Verzweigung, dass die Filter nur bei gedrücktem DIPSchalter aktiv sind und das Signal sonst zum Ausgang durchgeschlauft wird. Das erleichtert das Testen. Erscheint das erwartete Signal am Ausgang Hinweise: • DATA ist das Q15-Format für den Fixed-Point-DSP Werte-Bereich -1 .. +0.99997 entspricht -32768 .. +32767 In diesem Bereich müssen alle Zahlen vorliegen, sonst gibt es einen Overflow. Die Signale x vom ADC und r zum DAC sind bereits im Q15-Format. dbuffer ist der interne Verzögerungspuffer (beim Programmstart auf 0 init.). h sind die Filter-Koeffizienten: aus b = {1, 0, 0} wird h = {32767, 0, 0} 3 ZHAW, DSV1, 2009/01, Rumc, Hhrt, Dqtm • • • Die Funktion fir arbeitet grundsätzlich mit Arrays (= Vektoren). Für Arrays werden in C beim Funktionsaufruf standardmässig nur die Speicheradressen übergeben (per reference). Die * bezeichnen also eine Adresse (= Pointer). Einfache Variablen hingegen werden auf den Stack kopiert (per value). Wenn wir Sample um Sample abarbeiten, sind die Samples in einfachen Variabeln gespeichert. Die Adresse der Variabeln bekommt man durch voranstellen eines & vor den Variablennamen. Jedes Filter (je für den linken und für den rechten Kanal) benötigt einen eigenen Verzögerungspuffer. Die Funktionsaufrufe sehen dann so aus: oflag_l = fir(&sample_in_l, h, &sample_out_l, dbuffer_l, 1, 3); oflag_r = fir(&sample_in_r, h, &sample_out_r, dbuffer_r, 1, 3); e) Implementieren Sie nun das FIR-BP-Filter, indem Sie den Koeffizientenvektor mit Hilfe des hFiles bp.h initialisieren. Messen Sie den Amplitudengang mit dem Funkionsgenerator und dem KO aus. Bei welchen Frequenzen ist die Amplitude um -6 dB bzw. -20 dB abgefallen? Hinweis: Sie können das Filter auch mit dem NF-Spektrumanalysator (NWA) ausmessen. Tracking out (sweep output) HP3580A Spek.Analyzer f) DSP-C55x Zünden Sie eine LED unmittelbar vor dem fir-Befehl an und unmittelbar nach dem firBefehl wieder aus. Messen Sie die Rechenzeit in Sekunden und in DSP-Zyklen für der FIR-Routine (127 MACBefehle1) mit dem Oszilloskop (siehe unten wie). Vergleichen Sie diese Rechenzeit mit der ADDA Abtastperiode. Wie stark ist der DSP mit dieser FIR-Berechnung ausgelastet? Der DSP arbeitet mit 200 MHz. Verbinden Sie den DSP-Board-Ausgang mit Kanal 2 des Osziloskops (um den Signal-Ground herzustellen). Messen Sie die Spannung mit der Messspitze am Kanal 1 direkt am LEDAnschluss am Rand des Boardes. Die LED brennt, wenn die Spannung = 0 ist. g) Hören Sie sich die Filterwirkung mit einem Audio-Signal an. 1 Number of cycles for FIR command (preliminary benchmark from Programmers Reference ): (25+nx*(2+nh)) Zyklen 4 ZHAW, DSV1, 2009/01, Rumc, Hhrt, Dqtm Teil 2: Tiefpass- und Komplementärfilter = Frequenzweiche Matlab-Entwurf: Tiefpassfilter, Einfluss eines Koeffizienten betrachten a) Entwerfen Sie mit Hilfe der Fenster-Methode (Hamming-Fenster) ein FIR-TP-Filter der Ordnung N=126 (127 Filterkoeffizienten) mit einem Durchlassbereich bis fDB = 1000 Hz (-6 dB Eckfrequenz). b) Ändern Sie den 62ten Koeffizienten um 1% und kontrollieren Sie den Einfluss auf H(f). Wiederholen Sie diese Analyse für eine Änderung von 5%. c) Subtrahieren Sie ‚1’ von dem 63ten Koeffizient und kontrollieren Sie den Einfluss auf H(f). Wie können Sie diese Änderung erklären? DSP-Realisierung: Tiefpass- und Komplementärfilter d) Realisieren Sie das Tiefpass Filter und das komplementäre Hochpass-Filter (aus Punkt (c)) und geben Sie die entsprechenden Ausgänge auf den linken und rechten Kanal aus. Messen Sie die Filter aus und hören Sie sich die Filterwirkung an. Aufpassen „-1“ in Q15 bedeutet – (2^15). Hinweise: Das DSP-Programm kann aus Aufgabe 1 übernommen werden. Der Koeffizientenvektor muss allerdings mit den TP-Filterkoeffizienten (tp.h) initialisiert werden. sample_in_r = sample_in_l; damit gleiches Eingangssignal für beide Filter. DSP-Realisierung: Tiefpass- und Komplementärfilter, Rechenaufwand ~ halbiert e) Nehmen Sie das Tiefpass Filter von Aufgabe d) und realisieren Sie das komplementäre Hochpass-Filter HHP(z) = z-N/2 - HTP(z) wie in der folgenden Abbildung dargestellt: yTP[n] zum linken Kanal ausgeben HTP(z) x[n] z -N/2 + yHP[n] zum rechten Kanal ausgeben Das Hochpass-Filter HHP(z) = z-N/2 - HTP(z) muss nicht mit einem Filter realisiert werden. Es kann durch Verzögerung des Eingangssignals x[n] (Ringbuffer) und Subtraktion von yTP[n] realisiert werden. Man spart so 127 MAC-Operationen! Die Verzögerung z-N/2 entspricht der Verzögerung des Tiefpass-Filters. Beide Signale müssen gleich lange verzögert werden, bevor sie subtrahiert werden können. Realisieren Sie die Verzögerung z-N/2 mit einem Ringbuffer der Länge N/2. Geben Sie die beiden Ausgangssignale yTP[n] und yHP[n] gleichzeitig über den linken und den rechten Kanal aus. Messen Sie die Filter aus und hören Sie sich die Filterwirkung an. Hinweise: Sie benötigen als Variablen nur einen DATA-Array für den Ringbuffer und eine Integervariable für den Pointer. Der neueste Wert wird an die Stelle im Ringbuffer-Array geschrieben, die durch den Pointer indiziert wird. Der Pointer wird anschliessend inkrementiert. Wenn der Pointer an der Arraygrenze angelangt ist, wird er auf 0 zurückgesetzt. sample_in_r = sample_in_l; damit gleiches Eingangssignal für beide Filter.