Forum: Compiler & IDEs Wie am geschicktesten DD Synthese in C Programmieren?


von Marc (Gast)


Lesenswert?

Hallo,

wie kann ich am geschickstesten eine DD Synthese in C Programmieren? Wie 
kann ich die Funktionswerte am besten abspeichern und dann ausgeben?

Gruß Marc

von daniel (Gast)


Lesenswert?

was ist DD und mit was isst man es?

von gast (Gast)


Lesenswert?

DD Synthese =>DDS => direct digital synthesis....

von Ralf S. (spacedog) Benutzerseite


Lesenswert?

Ringspeicher, mit einer Periode des gewünschten Signals. Dann zum 
Pointer, der darauf zeigt, immer das Tuning-Byte/Word dazuaddieren und 
den Wert an der entsprechenden Speicherstelle via DAC, PWM oder WDTW 
ausgeben. Aber da findet man echt viel im Netz dazu, ist ja auch nicht 
so schwierig; das sind etwa zwei Zeilen C-Code plus noch der Datensatz.

Aber was ist eigentlich genau deine Frage?

von Marc (Gast)


Lesenswert?

@Ralf Schwarz:

Du hast meine Frage eigentlich weitestgehend beantwortet. (Stichwort 
Pointer, Ringspeicher!) Dankeschön

von Marc (Gast)


Lesenswert?

OK habe nun die Daten im Array nun komm ich aber nicht weiter mit dem 
Zeiger auslesen. Ich dacht an so etwas:

unsigned char iArray[251];

z = &iArray[0];
z++;
z++;
PORTD = *z;

Geht das vom Prinzip her? Als was muss ich z deklarieren? Kann ich ein 
Byte einfach überspringen indem ich z++; schreibe oder wie macht man 
das?

von Matthias L. (Gast)


Lesenswert?

>Als was muss ich z deklarieren?
1
int8_t   iArray[251];
2
uint8_t  *z           = &iArray[0];
3
4
5
//-- zyklisch aufrufen, zB im Timerinterrupt
6
z += x;      // x: Tuningbyte
7
if ( z > (sizeof(iArray)/sizeof(iArray[0]) )
8
{
9
 z -= (sizeof(iArray)/sizeof(iArray[0]);
10
}
11
PORTD = *z;

>Byte einfach überspringen indem ich z++;
z++ geht nur zum Nächsten. Zum Überspringen musst du mindestens zwei 
addieren, oder das tuningbyte x. Bei dem Tuningbyte ist allerdings der 
Überlauf besonders zu beachten! Mein Beispiel ist da noch nicht 
"bombenfest"

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

@  Matthias Lipinsky
Nicht dein Tag heute? ;-)
Das
> if ( z > sizeof(iArray)/sizeof(iArray[0]) )
ist doch das selbe wie
> if ( z > 251 )
und müsste, damit es keinen amoklaufenden Pointer gibt, zumindest so 
heissen
> if ( z >= 251 )
damit nicht hinter das Array gegriffen wird.

Leider ist es auch dann noch falsch, weil z ja irgendein Wert (Pointer) 
ist. Fast sicher ist z aber kein Wert zwischen 0 und 250...


>int8_t   iArray[251];
Warum nicht einfach eine Array-Größe von 256 definieren? Dann geht das 
mit dem Überlauf fast von alleine. So z.B.:
1
int8_t   iArray[256];
2
uint8_t  z;
3
// -- zyklisch aufrufen, zB im Timerinterrupt
4
z += x;            // x Tuningbyte
5
PORTD = iArray[z]; // z kann nie größer werden als das Array (0...255)

Die Welt ist einfach und schön rund, wenn für binäre Prozessoren auch 
binär gedacht wird.

von Matthias L. (Gast)


Lesenswert?

>Nicht dein Tag heute? ;-)

Sieht so aus..

Ich leg mich nochmal hin

von Marc (Gast)


Lesenswert?

Klasse hat geklappt. Vielen Dank!

Das Array ging nur bis 251 weil ich zum testen nen Sinus ausgerechnet 
hab:
for (l=0;l<251;l++) {
x = (sin(0.025*l))*127.5 +127.5;
iArray[l] = x;
}
(ab 252 ginge der x Wert über 127.5 und es würde einen Zacken geben. Die 
Kurve hat sowieso einen Zacken weiß auch nich warum aber zum testen 
isses OK, besser als 200 Werte von Hand auszurechnen^^)


Hier meine Provisorische Lösung:

signed char  iArray[251];
unsigned char *z = &iArray[0];
unsigned char *save = &iArray[0];
      z++;
      zaehler++;

      if (lol >251) {
                z = save;
                zaehler=0;
      }
      PORTB = *z;

Eins noch: Was macht dieser Befehl: z += x; ?

von Detlef _. (detlef_a)


Lesenswert?

>>Eins noch: Was macht dieser Befehl: z += x; ?

Das ist dasgleiche wie z = z+x; Das geht auch mit weiteren Operatoren.

Cheers
Detlef

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Wie schon gesagt, (Matthias war schlecht aufgestanden :-)
das
>      if (lol > 251) {
geht schief, weil dein Array zwar 251 Elemente hat, aber die Indices für 
diese Elemente zwischen 0 und 250 liegen müssen. Du lässt aber einen 
Index von 251 noch ohne Überlauf durchgehen!! Korrekt müsste es so 
heissen:

>      if (lol >= 251) {

Dann tauchen auch diese Zacken nicht mehr auf. Allerdings ist auch deine 
Berechnung etwas gewöhnungsbedürftig...


So wäre sie vielleicht etwas besser durchschaubar:
1
char iArray[256]; // sollte das nicht besser cArray heissen?
2
unsigend char w;
3
:
4
for (w=0; w; w++) { // solange, bis w wieder 0 ist, also 256 mal
5
  iArray[w] = (char)(sin(((float)w/256)*6.283185))*127.5 +127.5;
6
}

Alternativ auf dein 251 Elementiges Array
1
char iArray[251]; // sollte das nicht besser cArray heissen?
2
unsigend char w;
3
:
4
for (w=0; w<=250; w++) {
5
  iArray[w] = (char)(sin(((float)w/251)*6.283185))*127.5 +127.5;
6
}

von Marc (Gast)


Lesenswert?

Ah da kommt dieser zacken her. (Das lol soll eigentlich zaehler heißen 
und  cArray wäre sicher sinvoller).
Ich muss sagen deine Berechnung von dem Array gefällt mir sehr. Is viel 
genauer als meine. Dankeschön!!!

von Schwurbl (Gast)


Lesenswert?

Kaum zu glauben, dass die Schleife 256 mal durchlaufen wird. Ich würde 
eher sagen, gar nicht. Aber ich kann die gewollte Pfiffigkeit erkennen 
:-)
1
char iArray[256]; // sollte das nicht besser cArray heissen?
2
unsigend char w;
3
for (w=0; w; w++) { // solange, bis w wieder 0 ist, also 256 mal
4
  iArray[w] = (char)(sin(((float)w/256)*6.283185))*127.5 +127.5;
5
}

Um das Niveau dennoch hoch zu halten, spare ich mir die Korrektur.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

@ Schwurbl
> for (w=0; w; w++)...
Gut, wenigstens einer merkt es ;-)
>  ...// solange, bis w wieder 0 ist, also 256 mal
Die Funktionsweise ist im Kommentar doch klar beschrieben :)
> Um das Niveau dennoch hoch zu halten, spare ich mir die Korrektur.
Ganz in deinem Sinne...

von eProfi (Gast)


Lesenswert?

Die Tabelle unbedingt 256 Bytes groß machen, spart die Abfrage nach 
>249.

Der Phasenakkumulator muss doch viel breiter als der Pointer sein.

#define hi 0  //je nach Endianess des Zielsystems

union {t_int32 i32;t_int8 Byte[4]} ddsSum,ddsAdd;
ddsSum.i32 += ddsAdd.i32;
PORTB = iArray[ddsSum.Byte[hi]];


Evtl. löst der Compiler folgendes elegant:

PORTB = iArray[(ddsSum.i32+=ddsAdd.i32)>>24];



Eine DDS ist in Assembler wesentlich eleganter.
Beitrag "Re: atmega8, pwm, tongenerator ganz einfach"
Ganzen Thread lesen.
"poor man's dds"

von eProfi (Gast)


Lesenswert?


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.