Also bei der Initialisierung sezt du das Z Register (R30,R31) auf die
(16bit) Addresse deiner Tabelle, da die Tabelle "nur" 256 Daten hat
kannst du R31 somit auch schon wieder Vergessen das würde aber bei einer
Inkrementierung von R30 auch automatisch nachgeführt werden.
Die Eigentlich Magie findet hier statt:
1 | LOOP1:
|
2 | add r28,r24 ; 1
|
3 | adc r29,r25 ; 1
|
4 | adc r30,r26 ; 1
|
5 | lpm ; 3
|
6 | out PORTB,r0 ; 1
|
7 | rjmp LOOP1 ; 2 => 9 cycles
|
Hier wird der 24bit Inkrementierungswert (Proportional zur Frequenz) der
in R24,R25,R26 gespeichert ist auf den Zeiger im Phasenraum
(R28,R29,R30) aufaddiert, das ist erstmal einfach eine Zahl die immer
grösser wird, umso schneller je grösser unsere Frequenz/Inkrement. Somit
zählt er bis zum Überlauf und fängt dann wieder bei 0 an. Die MSBs
dieses Zeigers im Phasenraum sind, oh wie praktisch, auch gleichzeitig
unser Z Register, d.h. Z zeigt an die entsprechende Stelle unserer
Tabelle und legt diesen Wert nach einem LPM, freundlich für uns in R0
(und R1 für 16bit Werte) ab, wo wir es dann sogleich verwenden könnne.
Daher muss bei dieser Implementierung auch eine volle Periode in der .db
sein.
Wenn man jetzt z.B. immer nur mit 1 inkrementiert, würde man 65535 mal
den ersten Wert der Tabelle erhalten dann 65536 man den 2ten usw.
bei einem Inkrementierungswert > 65535, erhält man nicht einmal mehr
jeden Wert der Tabelle sondern eben nur noch einen Bruchteil, was aber
natürlich Sinn ergibt, da wir dann eine Frequenz erreicht haben die wir
gar nicht mehr mit 256 Samplen abarbeiten könnten.
Am Ende kann man die Frequenz fein in 24bit Auflösung einstellen, von
dem ersten Beispiel in dem man 256*65535 Takte braucht um die Tabelle
auch nur ein einziges mal auszulessen bis hin zu 1Takt pro Tabelle
auslesen (was natürlich nicht mehr sinnvoll ist, da es ja dann ein DC
wäre). -wiebel