Wie am geschicktesten DD Synthese in C Programmieren?

Persönliche Seite #966113
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?
Gast #966182
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"
Moderator (Firma: Titel) Persönliche Seite #966293
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.
Gast #966751
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; ?
Moderator (Firma: Titel) Persönliche Seite #967227
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
}
Gast #970491
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.
Gast #996040
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"

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