Forum: Digitale Signalverarbeitung / DSP / Machine Learning Faltung mit langen Impulsantworten auf TMS320C6713 Warteschleifen unterbrechen?!


von Felix H. (flexo)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich will auf dem TMS320C6713 DSK von Spectrum Digital eine Faltung mit 
langen Impulsantworten realisieren. Dazu hab ich im Vorfeld den 
Algorithmus von Zölzer in Matlab implementiert und das hat wunderbar 
funktioniert.

Nun will ich das alles in C auf den DSP bringen aber hab da so ein paar 
Probleme.

Meine E/A geschieht durch einen Interrupt. In der 
Interruptserviceroutine AIC_RX() wird das am Codec anliegende Abtastwert 
eingelesen und in einen Vektor zwischengespeichert. Anschließend wird 
der Ausgabewert an den Codec gesendet, welcher den D/A Wandelt.
Danach werden die Pointer auf die nächste stelle gesetzt.

Nun kommts: Hat der Pointer eine bestimmte Stelle erreicht, wird ein 
Signal (Buffer_full) auf 1 gesetzt und der komlette Buffer 
zwischengespeichert. Das funktioniert auch soweit!

In der main funktion passiert folgendes:
Nach der Initialisierung des DSKs kommt eine Arbeitsschleife, die 
unendlich lange durchlaufen wird. bis zum manuellen Abbruch.

Darin befindet sich eine Warteschleife (while(Buffer_full == 0)) Danach 
soll es mit dem Algorithmus weiter gehen.

Problem: Die Warteschleife wird nicht unterbrochen, obwohl in der ISR 
Buffer_full auf 1 gesetzt wird und die Schleifenbedingung damit auf 0 
ist.

Solche Warteschleifen habe ich 2 Stück im Programm...beide Signale 
werden in der ISR gesetzt. und beide werden nicht unterbrochen.

Was mache ich falsch?
Danke schonmal für die Antworten

: Bearbeitet durch User
von Doffel (Gast)


Lesenswert?

Hallo Felix,

hast du Buffer_full als volatile deklariert? Das braucht der Compiler 
damit er bei jedem Lesen die Variable neu aus dem Speicher holt. Die 
6000er DSPs können nicht direkt auf Speicherzellen arbeiten, sie müssen 
erst den Wert in ein Register laden. Ohne volatile macht das der 
Compiler nur einmal und arbeitet dann immer mit dem Registerwert weiter. 
Dabei kriegt er nicht mit das deine ISR längst einen neuen Wert in den 
Speicher geschrieben hat.

von Felix H. (flexo)


Lesenswert?

Super Danke...das hat funktioniert. Jetzt werden die Warteschleifen 
unterbrochen, aber das ausgangssignal will nicht so richtig zu dem 
werden, was ich erwarte :(

werd noch ein bisschen rumdoktorn...

von Felix H. (flexo)


Angehängte Dateien:

Lesenswert?

So Leute da bin ich wieder

Ich stehe nun vor dem nächsten Problem: Ich habe die Filterkoeffizienten 
in einer .wav - Datei bekommen. Die hab ich nun mittels Matlab 
partitioniert, zu komplexen Zahlenpaaren verschachtelt und 
Fourier-Transformiert. Anschließend hab ich die Spektren ins 
HEX-Zahlensystem umgewandelt und in eine Header-Datei gepackt.

Wenn ich nun mein Programm compiliere und auf den DSP lade, sind die 
Speichereinträge falsch.

IM Anhang hab ich die Bilder angefügt, um euch zu zeigen wie das 
"Memory-Window" in CCStudio aussieht.

Es sind zwar ziemlich viele Einträge aber der Speicher reicht eigentlich 
vollkommen aus.

Woran liegt das? Könnt ihr mir sagen was ich falsch mache?

Vielen Dank schonmal für eure Hilfe.

von Joe F. (easylife)


Lesenswert?

Tip: dieses Forum beherrsch auch den Upload von .txt

von Felix H. (flexo)


Lesenswert?

Joe F. schrieb:
> Tip: dieses Forum beherrsch auch den Upload von .txt

Ich denke mehr kann ich nicht wirklich zeigen, um das Problem besser 
verständlich zu machen...und wenn doch sag(t) mir bitte, was ihr noch 
sehen wollt um das Problem zu lösen ;)

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Die Speichereintraege stimmen. Hab' ich hier auf nem PC genauso:
1
float f=0xc0a59340;
2
printf("%08x\n",*(unsigned int*)&f);

liefert mir wie dir zurueck: 4f40a593

Wahrscheinlich willst du was anderes, als du deinem C-Compiler gesagt 
hast, aber nach:

Felix H. schrieb:
> Die hab ich nun mittels Matlab
> partitioniert, zu komplexen Zahlenpaaren verschachtelt und
> Fourier-Transformiert. Anschließend hab ich die Spektren ins
> HEX-Zahlensystem umgewandelt und in eine Header-Datei gepackt.

hab' ich keine Ahnung, was du wirklich willst...

Gruss
WK

von Joe F. (easylife)


Lesenswert?

1
float f=0xc0a59340;
wandelt dir erstmal einen unsigned int in einen float.

Wenn du folgendes machst:
1
printf("hex: %08x unsigned int: %u float: %f\n", 0xc0a59340, 0xc0a59340, (float)0xc0a59340 );

kommt das dabei raus:

hex: c0a59340 unsigned int: 3232076608 float: 3232076544.000000

Der float weicht also auch noch leicht vom integer Wert ab...
Im Speicher sieht der float dann natürlich ganz anders aus.

von Felix H. (flexo)


Lesenswert?

Zuerst einmal DANKE für die Antworten

Dergute W. schrieb:
> Felix H. schrieb:
>> Die hab ich nun mittels Matlab
>> partitioniert, zu komplexen Zahlenpaaren verschachtelt und
>> Fourier-Transformiert. Anschließend hab ich die Spektren ins
>> HEX-Zahlensystem umgewandelt und in eine Header-Datei gepackt.
>
> hab' ich keine Ahnung, was du wirklich willst...

ach da hab ich mich wohl blöde ausgedrückt. Was ich damit sagen wollte 
ist, dass ich eine Menge single precision Floating point Zahlen habe, 
die ich auf den DSP mittles Header Datei packen will.

Dafür habe ich alle Zahlen in die entsprechenden Hex Werte konvertiert, 
weil wenn ich die dezimalzahlen habe und so in eine txt datei packen 
will, werden die Exponenten nicht mit übernommen. Deshalb hab ich mir 
gedacht einfach die Floats, bzw. deren Bitrepräsentation in Matlab 
nehmen und in Hex zahlen darstellen, dann könne auch der DSP so die 
zahlen richtig dechiffrieren.

Ich will also die 0xc0a59340 im Speicher zu stehen haben und nicht die 
0x4f40a593 (erster Eintrag).

Was muss ich dafür machen? Ich hätte nicht gedacht/gewusst, dass die 
bits erst als Integer interpretiert werden.

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Naja, ist halt etwas hemdsaemelig - erklaerende Kommentare waeren da 
vielleicht eine gute Idee...aber vielleicht so ungefaehr:
1
const unsigned int FFT_FH_INT[]={0xc0a.. , ... , ... };
2
float * FFT_FH = (float*)FFT_FH_INT;

Solche Scherze sollte man aber nur treiben, wenn man sich sicher ist, 
dass unsigned int und float gleich gross sind, die floating point 
Repraesentation passt, und was weiss ich nicht noch alles, was schief 
gehen kann, eben nicht schief geht.

Gruss
WK

von Joe F. (easylife)


Lesenswert?

Die einfachste Lösung wäre wohl, die floats auch in ein float array 
abzulegen, und nicht den Umweg über hex zu gehen. Ist auch besser 
lesbar.
1
const float FTT_TH[] =
2
{
3
  -5.174225, 0.000000, 3.747160, 3.742679, -0.139410, 
4
  (...) 
5
};

ergibt im Speicher:
1
0xC0A59340 0x00000000 0x406FD178 0x406F880E 0xBE0EC17

: Bearbeitet durch User
von Jim M. (turboj)


Lesenswert?

Felix H. schrieb:
> Ich stehe nun vor dem nächsten Problem: Ich habe die Filterkoeffizienten
> in einer .wav - Datei bekommen. Die hab ich nun mittels Matlab
> partitioniert, zu komplexen Zahlenpaaren verschachtelt und
> Fourier-Transformiert.

Du hättest den Scheiss dann als .csv ausgeben können. Clever formatiert 
geht dann sowas:
1
float fArray[] ={
2
#include "floatValues.csv"
3
};

Die .csv muss dabei so aussehen:
1
0.0,
2
1.1120,

von Felix H. (flexo)


Lesenswert?

Dergute W. schrieb:
> aber vielleicht so ungefaehr:
> const unsigned int FFT_FH_INT[]={0xc0a.. , ... , ... };
> float * FFT_FH = (float*)FFT_FH_INT;

JA super DANKE vielmals...genau so funktioniert es wunderbar.  nun 
stehen die richtigen Werte im Speicher und der Faltungshall hört sich 
nach Hall an :)

Joe F. schrieb:
> Die einfachste Lösung wäre wohl, die floats auch in ein float array
> abzulegen, und nicht den Umweg über hex zu gehen. Ist auch besser
> lesbar.
> const float FTT_TH[] =
> {
>   -5.174225, 0.000000, 3.747160, 3.742679, -0.139410,
>   (...)
> };
>
> ergibt im Speicher:

Das hab ich so am Anfang gemacht, aber die exponenten wurden immer 
abgeschnitten. 5,4 x 10^(-3) wurde als 5,4 interpretiert. Das hatte dann 
keinen Sinn mehr gemacht.

Jim M. schrieb:
> Du hättest den Scheiss dann als .csv ausgeben können. Clever formatiert
> geht dann sowas:float fArray[] ={
> #include "floatValues.csv"
> };
>
> Die .csv muss dabei so aussehen:0.0,
> 1.1120,

Sehr interessant...das werd ich mal ausprobieren, wenn ich die zeit 
dafür finde :)

von Felix H. (flexo)


Angehängte Dateien:

Lesenswert?

Guten Tag liebe Forumgeeks ;)

ich sehe es nun ein...ich hab nicht so wirklich ahnung von der 
Informatik und dem Umgang mit Compiler, Linker und den ganzen 
Schmarrn...scheinbar.

ich krieg die Faltung einfach nicht richtig hin und bin mittlerweile 
seeeehr verzweifelt. Deshalb komme ich nun nochmal um eure Omnipotenz zu 
befragen :D

Im Anhang hab ich mein gezipptes Projekt aus CCS sowie die Simulation 
via MATLAB beigefügt.

Wie oben beschrieben benutze ich ein TMS320C6713 DSK mit CCS v3.1.
Die Aufgabe besteht darin die schnelle Faltung eines Eingangsignals mit 
einer relativ langen (6sek.) Impulsantwort auf den DSP zu 
implementieren. Dafür hab ich das alles erstmal per MATLAB simuliert 
(siehe Anhang).
Anschließend sollte ich die Simulation auf den DSP in C, mit bestimmten 
modifikationen, übersetzen, sodass die verhallte Stimme (Echtzeitfähig 
mit Latenz) rauskommt und über Lautsprecher hörbar gemacht wird. Das 
Eingangssignal wird erstmal mittels Handy eingespielt.

Jetzt zum Algorithmus:
In der ISR wird ein Sample vom McBSP eingelesen und abgespeichert. 
Anschließend wird der nächste auszugebende Abtastwert an den Codec 
gesendet.
Dann werden die Indizes aktualisiert. Zuerst werden 512 Werte auf alle 
geraden Speichereinträge, danach die nächsten 512 auf alle ungeraden, 
gelegt. Damit ist derBuffer für die FFT vorbereitet und kann 
abgespeichert werden.
Der Output muss dann 1024 Werte nacheinander ausgeben.

mit fa=16kHz folgt delta t=1/fa=62,5 mikrosekunden
-> 1024*62,5 mikrosekunden= 64 ms.

d.h. der DSP muss, wenn er einen Block mit 1024 Abtastwerten ausgeben 
soll, 64ms Signal ausgeben. Wenn ich aber mit dem Oszi messe, kommt das 
heraus, was im Bild zu sehen ist. Der DSP gibt komischer weise ein rund 
113ms langes Signal heraus (Messwerteerfassung von einer FFT des 
Eingangssignals zur nächsten FFT des Folgeblocks).

Ich weis nicht was ich falsch mache. I/O hab ich kontrolliert, 
FFT-DSV-IFFT hab ich getestet: funktioniert. OLA sollte auch 
funktionieren laut Simulation.

Wenn ich das einfach durchlaufen lasse, hackt das Ausgangssignal. Es 
hört sich so an als würde man schnell die Lautstärke auf und wieder 
runter drehen...amplitudenmoduliert mit ner Rechteckfunktion oder so... 
:D

Man kann aber das verhallte Signal erkennen. Aber es knackt und ist 
verzerrt.
Video dazu:

https://youtu.be/RCfJy_lpmvQ

ich weis jetzt wirklich nicht mehr weiter, aber vlt kann einer von Euch 
mal über den quellcode rüber gucken und mir helfen?!

Bei Fragen fragt bitte :)

mit freundlichen Gruß
Felix

von Joe F. (easylife)


Lesenswert?

Felix H. schrieb:
> Dann werden die Indizes aktualisiert. Zuerst werden 512 Werte auf alle
> geraden Speichereinträge, danach die nächsten 512 auf alle ungeraden,
> gelegt. Damit ist derBuffer für die FFT vorbereitet und kann
> abgespeichert werden.
> Der Output muss dann 1024 Werte nacheinander ausgeben.

Also ohne den sehr eigenwillig formatierten Sourcecode im Detail gelesen 
zu haben:
So ganz klar ist mir nicht, was du da so machst.
Wenn ich es richtig sehe, sind die geraden/ungeraden Speichereinträge 
jeweils der Real-/imaginär-Anteil (oder umgekehrt).
Vor der FFT sollte es so aussehen, dass 512 Samples jeweils in den 
ersten 512 Real-Anteilen liegen, die restlichen 512 Speichereinträge 
sind genullt.
Die Imaginäranteile sind alle auf 0.
Dann machst du die FFT.
Danach die Faltung.
Dann die IFFT.
Hierbei fallen 1024 samples heraus (jeweils nur die Real-Anteile...), 
von denen du die ersten 512 nimmst, und mit den hinteren 512 der letzten 
Faltung addierst (OLA). Dann sollte eigentlich alles gut sein.

Tip: der Code sollte sehr einfach zu portieren sein, um ihn auf einem 
normalen Rechner (offline) laufen zu lassen.
Was du ergänzen müsstest, sind 2 Funktionen, um ein .wav File als Quelle 
einzulesen, und das Resultat wieder in ein .wav File rauszuschreiben.
.wav ist ein sehr einfach zu verstehendes Dateiformat.
Dadurch fällt das Debuggen dann wesentlich leichter.

: Bearbeitet durch User
von Felix H. (flexo)


Lesenswert?

Hallo Leute,

nun hab ich ein weiteres akkutes Problem dazu bekommen:

Meine ISR verhält sich falsch. Aber eigentlich ist sie richtig, denn 
wenn ich in der main() alles auskommentiere, sodass nur noch eine leere 
Endlosschleife da steht und damit eigentlich nur noch die ISR abarbeiten 
sollte. Die Ausgabe läuft dann einwandfrei.

Wenn ich jetzt nun z.B. nur die FFT des aktuellen Eingangsblocks in der 
main zu stehen habe, gibt die ISR teilweise falsche Samples aus, obwohl 
der frame nicht geändert wird.

Warum? muss ich irgendwas mit dem Speicher machen?
Bitte helft mir! ich bin am verzweifeln...

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Naja, klingt irgendwie so, als ob sich irgendwelche Zugriffe aus main() 
und isr() in die Quere kommen koennten. Und das dann auch manchmal tun.
Gibts da Variable/Speicherbereiche auf die beide zugreifen koennen? 
Wahrscheinlich. Und wie ist sichergestellt, dass sich die Zugriffe nicht 
gegenseitig beeinflussen koennen?

Klassisches Beispiel:
1
int counter;
2
main() {
3
    ...
4
    counter++;
5
    ...
6
}
7
8
isr() {
9
    ...
10
    counter--;
11
    ...
12
}
Sowas geht oft gut, aber manchmal (zu oft) schief.

Gruss
WK

von Felix H. (flexo)


Lesenswert?

Ja das Problem ist, dass ich in der main() einen Buffer 
zwischenspeichern will. der DSP braucht dabei 7,104 Mikrosekunden für 
das umschreiben.

Das Abtastinterval ist aber 62,5 Mikrosekunden groß. D.h. er hat genug 
zeit um sich nicht in die Quere zu kommen. Im Rest der main() wird kein 
Parameter der isr() verändert.

Das Problem ist eher der Rest der main(), denn wenn ich alles 
auskommentiert hab und nur dieses oben genannte Umschreiben 
(Zwischenspeichern) in der main() hab, ist die Ausgabe der isr() ja 
richtig.

Ich habe ein bisschen rumprobiert und herausgefunden, dass ich noch 
kleine Codezeilen einfügen kann ohne eine Beeinflussung zu haben. Das 
sind aber nur 3 oder 4 Zeilen. Wenn ich mehr einfüge bekomme ich halt 
wieder soein Knacken am Ausgang heraus.

Das große Problem dabei ist halt, dass ich keinen weiteren Zugriff in 
der main auf den inhalt der isr mache.

Dergute W. schrieb:
> Gibts da Variable/Speicherbereiche auf die beide zugreifen koennen?
> Wahrscheinlich. Und wie ist sichergestellt, dass sich die Zugriffe nicht
> gegenseitig beeinflussen koennen?

Wie kann ich das machen?

von Joe F. (easylife)


Lesenswert?

Der sichere Weg wäre ein Flip-Buffer.

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Felix H. schrieb:
> Ja das Problem ist, dass ich in der main() einen Buffer
> zwischenspeichern will. der DSP braucht dabei 7,104 Mikrosekunden für
> das umschreiben.
>
> Das Abtastinterval ist aber 62,5 Mikrosekunden groß. D.h. er hat genug
> zeit um sich nicht in die Quere zu kommen. Im Rest der main() wird kein
> Parameter der isr() verändert.

Felix H. schrieb:
> Wie kann ich das machen?

Interrupts waehrend der 7.104µs Bufferzwischenspeicherei sperren?

Gruss
WK

von Felix H. (flexo)


Lesenswert?

Dergute W. schrieb:
> Moin,
>
> Felix H. schrieb:
>> Ja das Problem ist, dass ich in der main() einen Buffer
>> zwischenspeichern will. der DSP braucht dabei 7,104 Mikrosekunden für
>> das umschreiben.
>>
>> Das Abtastinterval ist aber 62,5 Mikrosekunden groß. D.h. er hat genug
>> zeit um sich nicht in die Quere zu kommen. Im Rest der main() wird kein
>> Parameter der isr() verändert.
>
> Felix H. schrieb:
>> Wie kann ich das machen?
>
> Interrupts waehrend der 7.104µs Bufferzwischenspeicherei sperren?
>
> Gruss
> WK

Habs ausprobiert: geht leider immer noch nicht, trotz dem globalen 
IRQ_Disable beim Zugriff.

Danach hab ich das Programm so eingestellt dass ich an 2 Parametern und 
damit an den Umfang der Berechnungen, was verstellen kann. Einmal die 
Puffergröße und einmal die Anzahl an Blöcken, die ich jetzt einfach mal 
P nenne.

Wenn ich P auf 1 setze kommt das Ausgangssignal exakt raus. Wenn ich 
jetzt P erhöhe auf bis zu 4, funktioniert es immer noch. Aber P sollte 
noch viel Größer sein so 80 zB.

Könnte es sein, dass es daran liegt, dass die ganzen Arrays im SDRAM 
abgespeichert werden und der Zugriff langsamer ist, sodass der DSP nicht 
mehr genug Zeit hat um die aufwendigen Berechnungen durchzuführen?

MfG
Flexo, Benders böser Zwilling

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Felix H. schrieb:
> Könnte es sein, dass es daran liegt, dass die ganzen Arrays im SDRAM
> abgespeichert werden und der Zugriff langsamer ist, sodass der DSP nicht
> mehr genug Zeit hat um die aufwendigen Berechnungen durchzuführen?

Naja, sein kann viel. Musst doch du wissen, mit welchem Takt dein DSP 
laeuft, was du ihm alles fuer Berechnungen auferlegst, wie lange die 
dauern, wie dein DRAM angebunden ist; wie lange da Zugriffe dauern (das 
ist was, was seeeehr stark schwankt; gibts da nen Cache, sind das 
burstartige Zugriffe oder wahllos?) koennen...
Und ob's vom Fehlerbild her ueberhaupt sein kann, dass irgendwas nicht 
rechtzeitig fertig ist.

Gruss
WK

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.