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
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.
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...
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.
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 ;)
Moin,
Die Speichereintraege stimmen. Hab' ich hier auf nem PC genauso:
1
floatf=0xc0a59340;
2
printf("%08x\n",*(unsignedint*)&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
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.
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.
Moin,
Naja, ist halt etwas hemdsaemelig - erklaerende Kommentare waeren da
vielleicht eine gute Idee...aber vielleicht so ungefaehr:
1
constunsignedintFFT_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
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:
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 :)
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
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.
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...
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
intcounter;
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
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?
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
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
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