Forum: Digitale Signalverarbeitung / DSP / Machine Learning Koeffizienten an 24 bit Festkommaformat anpassen, Matlab


von Carol W. (carol)


Lesenswert?

Hallo,

ich würde gerne mit Matlab eingelesene Koeffizienten als 24 Bit Zahl 
darstellen.

-1 entspicht $800000 (hex)
1-2^(-23) entspricht $7FFFFF

Die eingelesenen Koeffizienten sehen so aus:
0.001953125

Gibt es eine Möglichkeit mit Matlab die Werte in die entsprechende 
Hexadezimale Darstellung zu wandeln?

mfg

von remote1 (Gast)


Lesenswert?

Matlab hat ebenso sprintf...

von Carol W. (carol)


Lesenswert?

Wie würde der Befehl aussehen, der aus 0.9999998808 --> 7FFFFF macht?

von Gerrit B. (gbuhe)


Lesenswert?

Hallo Carol,

eigentlich verstehen die Preprozessoren der Assembler/Compiler die 
q23-Zahlen direkt. Bei Deiner Wortbreite von 24 Bit tippe ich auf einen 
Motorola/Freescale DSP56xxx. Auch dort kann man die Koeffizienten 
einfach so angeben:

  dc  -0.0000005734  ;coef1
  dc  0.0000016536  ;coef2
  dc  0.0000003550  ;coef3
  dc  0.0000002282  ;coef4
  dc  0.0000054611  ;coef5
  dc  0.0000015115  ;coef6
  dc  0.0000027512  ;coef7
  dc  0.0000112883  ;coef8
  dc  0.0000017115  ;coef9
  dc  0.0000057759  ;coef10 .....

Ich lasse das immer gleich von Matlab in eine Koeffizienten-Datei 
schreiben, die ich per "include" einbinde.

Wenn Du es dennoch in Matlab auf 2er-Komplement-Darstellung in hex 
bringen möchtest, geht das wie folgt:

numbits=24;
q=quantizer('fix',[numbits 0]);

s_in = -1:0.1:1;                  //floating point
s_dez = s_in * 2^(numbits-1);     //fix point 2er Komplement
s_hex = num2hex(q, s_dez);        //und in hex verwandelt

Viel Erfolg!

Gerrit, DL9GFA

von Carol W. (carol)


Lesenswert?

Stimmt, DSP56371.
Hatte ich bisher auch so gemacht.
Die Koeffizienten werden alle in ein text file geschrieben.

A=data;
fid=fopen('koeff.txt','wt+');
fprintf(fid,' DC %0.8f\n',A);
fclose(fid)

...
 DC 0.00041151
 DC 0.00018835
 DC -0.00004542
 DC -0.00028038
...

Das Ausgangssignal geht dann aber oft in die Sättigung. Denke das die 
Skalierung der Werte in der DALU nicht stimmt

von Gerrit B. (gbuhe)


Lesenswert?

Hallo Carol,

> Das Ausgangssignal geht dann aber oft in die Sättigung. Denke das die
> Skalierung der Werte in der DALU nicht stimmt

wenn Du darauf achtest, daß die Verstärkung eines FIR-Filters 1 bleibt, 
sollte es auch angesichts des großen Akkus von 56 bit kein Problem mit 
Sättigung geben. Bei IIR-Filtern sieht das anders aus. Hier kann es 
schnell Überläufe in den Taps geben, die ja i.d.R. nur in 
24Bit-Speicherzellen abgelegt sind. Um das zu vermeiden, sollte man die 
Ordnung nicht über zwei wählen und ggf. mehrere IIR-Filter zweiter 
Ordnung kaskadieren. Natürlich ist auch eine Erweiterung der 
Tap-Speicher auf doppelte Wortbreite (48 bit) möglich. Falls Du auch bei 
IIR-Filtern zweiter Ordnung Probleme hast, möchte ich Deine 
Aufmerksamkeit auf die Scaling-Modes lenken (siehe Beschreibung SR - 
Status Register), die korrekt eingestellt sein sollten.

Gruß,

Gerrit, DL9GFA

von Carol W. (carol)


Lesenswert?

Mit den Koeffizienten des FIR Filters müsste dann soweit alles richtig 
sein.
Der Fehler könnte bei Ringspeichern liegen.

Zwei Modulo Register(m0,m4) werden mit Anzahl der Koeffizienten - 1 
geladen. Die Register r0,r4 zeigen dann jeweils auf die "Buffer Base 
Address".
1
  org y:(COEFF_BASE_ADDRESS)
2
  include "..\Koeff.fir"                   
3
    
4
NUM_COEFF equ Anzahl_Koeff
5
6
  org X:(SAMPLE_BASE_ADDRESS)     
7
8
RX_BUFF_BASE  dsm    Anzahl_Koeff

Wäre das soweit richtig?

von Gerrit B. (gbuhe)


Lesenswert?

Hallo Carol,

Deine Zeilen sind soweit korrekt. Ein vollständiges Beispiel von mir, 
ordentlich dokumentiert, findest Du unter folgendem Link:

http://unidsp56.de/downloads.html

--> "Kleine Beispielprogramme" --> "FIR-Filter mit Scilab-Skript..."

Laß Dich nicht irritieren davon, daß ich die Koeffizienten erst im 
p-Speicher ablege und bei der Initialisierung in den x-Speicher kopiere. 
Das ist nötig, wenn Du das Beispielprogramm aus einem Flash-Speicher per 
Boot-Loader holst, der nur P-Speicher kennt. Du kannst die 
include-Anweisung direkt unter x: oder y: so lassen, wenn Du das 
Programm per Debugger lädst.

Viel Erfolg!

Gerrit, DL9GFA

von Carol W. (carol)


Lesenswert?

Danke für deine Hilfe. Es funktioniert ...

Die Verstärkung des FIR-Filters ist immer kleiner als 1, wenn alle 
Koeffizienten kleiner als 1 sind?

mfg

von Gerrit B. (gbuhe)


Lesenswert?

Hallo Carol,

> Danke für deine Hilfe. Es funktioniert ...

Super!

> Die Verstärkung des FIR-Filters ist immer kleiner als 1, wenn alle
> Koeffizienten kleiner als 1 sind?

Nein, die Verstärkung ist die (vorzeichenbehaftete) Summe aller 
Koeffizienten des FIR-Filters. Wenn Du in das Scilab-Skript meiner 
letzten Referenz schaust, findest Du folgendes zum Design eines 
FIR-Tiefpasses:

lv =-N/2+0.5:N/2;                           // N - number of coeffs
coef=sinc(2*%pi*fc/fs*lv).*window('kr',N,10);   //calculate coeffs, 
apply windowing
coef=coef/sum(coef);                       //normalize to have unity 
gain

Ein Rechteck (idealer Tiefpaß) im Frequenzbereich eintspricht einer 
sin(x)/x = sinc(x) Funktion im Zeitbereich als Impulsantwort. Daher 
werden die Koeffizienten oben als Abtastwerte einer Sinc-Funktion 
ermittelt. Um die Verstärkung des TP-Filters auf 0dB, bzw. 1, zu setzen, 
habe ich die letzte Zeile eingefügt, die alle Koeffizienten durch die 
vorherige Summe aller Koeffizienten teilt. Diese Art der Skalierung der 
Koeffizienten kann man auch nutzen, um von 0dB abweichende Verstärkungen 
im Durchlassbereich einzustellen, z.B. anschließend coef = coef * 2, 
wenn 6dB verstärkt werden soll.

Viele Grüße!

Gerrit, DL9GFA

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.