Koeffizienten an 24 bit Festkommaformat anpassen, Matlab

OP #2066206
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
#2066351
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
OP #2066512
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
#2066878
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
OP #2068011
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?
#2068083
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
#2069401
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren