Download:
|

libam16: Accu-basierende Integerarithmetik-Library
für ATmega Controller
Version 0.20 (c) 2006 Jörg Wolfram (joerg@jcwolfram.de)
1 Allgemeines
Die Library unterliegt der LGPL (GNU Lesser General Public Licence)
Version 2 oder höher, jede Nutzung der Software/Informationen nonkonform
zur GPL oder ausserhalb des Geltungsbereiches der LGPL ist untersagt!
Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß
es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, auch
ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
FÜR EINEN BESTIMMTEN ZWECK.
2 Definitionen und Ressourcen
Um mit der Library arbeiten zu können, werden verschiedene Register benötigt.
Dazu gehören die temporären Register tempreg1...tempreg6 sowie das
Fehlerregisterereg. Dazu kommen noch acc1l, acc1h,
acc2l und acc2h für den Akkumulator acc1 und den Hilfsakkumulator
acc2, die alle im oberen Registerbereich liegen müssen.
|
Register |
Funktion |
|
r0,r1 |
werden für Multiplikationen und temporär genutzt |
|
byte0 |
beliebiges Register, welches mit 0x00 vorbelegt ist (normalerweise r2) |
|
byte1 |
beliebiges Register, welches mit 0x01 vorbelegt ist (normalerweise r3) |
|
tempreg1...tempreg4 |
temporäre Register aus dem oberen Registerbereich |
|
tempreg5...tempreg6 |
temporäre Register aus dem unteren Registerbereich |
|
ereg |
beliebiges Register aus dem oberen Registerbereich, liefert Fehlercode |
|
acc1l,acc1h,acc2l,acc2h |
Register aus dem unteren Registerbereich |
|
|
Fast alle Funktionsaufrufe sind mit bedingter Assemblierung geklammert.
Das dient dazu, daß das Tool avr_autolib.pl nur die benötigten
Routinen freigibt.
3 Fehlercodes
Nach jedem Funktionsaufruf wird in ereg-Register ein Wert zurückgegeben,
der zeigt ob ein Fehler aufgetreten ist. War alles in Ordnung, so
ist der Rückgabe-wert 0. Ansonsten ist einer der folgenden Fehler
aufgetreten:
|
ereg |
Fehler |
|
1 |
Überlauf, der gültige Zahlenbereich (+- 32768) wurde über- oder unterschritten |
|
2 |
Division durch Null |
|
3 |
Es wurde versucht, aus einer negativen Zahl die Quadratwurzel zu ziehen |
|
|
4 Funktionsreferenz
Die Funtionsreferenz gibt eine Übersicht über die einzelnen Funktionen. Die angegebenen Taktzahlen
sind Maximalwerte und durch manuelles Auszählen aus dem Quelltext entstanden. Sie beinhalten auch den
Grundmakro-Aufruf als call und sollten nur als ungefähr-Werte dienen.
4.1 Adressierungsarten
Der erste Operand ist immer der Akkumulator. Alle Funktionen erlauben mehrere Adressierungsarten,
die über Makros realisiert werden. Das Grundmakro hat die Bezeichnung libam16_xxxxx
wobei xxxxx für eine der Funtionen steht. Es nimmt als zweiten Operand den Inhalt des
Hilfsakkumulators. Eine Ausnahme ist die Funktion libam16_set, die den Akkumulator
mit dem gegebenen Wert lädt.
Die erweiterten Makros haben eine zusätzliche Endung, die ich versucht habe, so eindeutig und
einprägsam wie möglich zu gestalten. Zu beachten ist noch, daß alle Routinen das niederwertigere
Byte auf der ersten Adresse und das höherwertige Byte auf der darauffolgenden Adresse erwarten
bzw. speichern.
|
Makroaufruf |
Takte |
Words |
Adressierung |
|
libam16_xxxxx |
0 |
0 |
Operand ist der Inhalt des Hilfsakkus |
|
libam16_xxxxx_val nnnnn |
+2 |
+2 |
direkter 16-Bit Wert |
|
libam16_xxxxx_mem aaaaa |
+4 |
+4 |
direkte 16-Bit Adresse im SRAM |
|
libam16_xxxxx_y |
+4 |
+2 |
SRAM mit dem Y-Register adressiert, Y wird nicht verändert |
|
libam16_xxxxx_yi |
+4 |
+2 |
SRAM mit dem Y-Register adressiert, Y=Y+2 (Post-Inkrement) |
|
libam16_xxxxx_yd |
+4 |
+2 |
SRAM mit dem Y-Register adressiert, Y=Y-2 (Pre-Dekrement) |
|
libam16_xxxxx_z |
+4 |
+2 |
SRAM mit dem Z-Register adressiert, Z wird nicht verändert |
|
libam16_xxxxx_zi |
+4 |
+2 |
SRAM mit dem Z-Register adressiert, Z=Z+2 (Post-Inkrement) |
|
libam16_xxxxx_zd |
+4 |
+2 |
SRAM mit dem Z-Register adressiert, Z=Z-2 (Pre-Dekrement) |
|
|
4.2 Lade- und Speicherfunktionen
Die Ladefunktionen dienen zum Setzen (Initialisieren) des Akkumulators und zum
Abspeichern des Akkumulatorinhaltes in das SRAM.
|
Funktion |
Takte |
Beschreibung |
|
libam16_set_val nnnnn |
2 |
Setzt den Akkumulator auf den Wert nnnnn |
|
libam16_set_mem aaaaa |
4 |
Kopiert den Inhalt von (aaaaa) und (aaaaa+1) in den Akkumulator |
|
libam16_set_y |
4 |
Kopiert den Inhalt von (Y) und (Y+1) in den Akkumulator |
|
libam16_set_yi |
4 |
Kopiert den Inhalt von (Y+) und (Y+) in den Akkumulator |
|
libam16_set_yd |
4 |
Kopiert den Inhalt von (-Y) und (-Y) in den Akkumulator |
|
libam16_set_z |
4 |
Kopiert den Inhalt von (Z) und (Z+1) in den Akkumulator |
|
libam16_set_zi |
4 |
Kopiert den Inhalt von (Z+) und (Z+) in den Akkumulator |
|
libam16_set_zd |
4 |
Kopiert den Inhalt von (-Z) und (-Z) in den Akkumulator |
|
libam16_store_mem aaaaa |
4 |
Kopiert den Akkumulator nach (aaaaa) und (aaaaa+1) |
|
libam16_store_y |
4 |
Kopiert den Akkumulator nach (Y) und (Y+1) in den Akkumulator |
|
libam16_store_yi |
4 |
Kopiert den Akkumulator nach (Y+) und (Y+) in den Akkumulator |
|
libam16_store_yd |
4 |
Kopiert den Akkumulator nach (-Y) und (-Y) in den Akkumulator |
|
libam16_store_z |
4 |
Kopiert den Akkumulator nach (Z) und (Z+1) in den Akkumulator |
|
libam16_store_zi |
4 |
Kopiert den Akkumulator nach(Z+) und (Z+) in den Akkumulator |
|
libam16_store_zd |
4 |
Kopiert den Akkumulator nach (-Z) und (-Z) |
|
|
4.3 Arithmetikfunktionen
Bei den unten aufgeführten Arithmetikfunktionen fallen zwei etwas
aus der Reihe: libam16_dmul und libam16_mdiv.
Hier handelt es sich um Funktionen, bei denen intern mit 24 Bit gerechnet
wird. Das ist vor allen Dingen bei Meßwertskalierungen sinnvoll, um
zum Beispiel einen Wertebereich von 0-650 auf 0-1023 zu normalisieren.
In diesem Falle muß nur der Meßwert mit gerundeten 403 ($1024*256/650$)
multipliziert werden. Und da die ATmega-Serie einen Hardwaremultiplizierer
mit an Bord haben, geht das auch recht schnell vonstatten.
|
Funktion |
Takte |
Resultat |
Beschreibung |
|
libam16_abs |
16 |
acc1=|acc1| |
Absolutbetrag |
|
libam16_inv |
14 |
acc1=-acc1 |
Vorzeichenwechsel |
|
libam16_sign |
27 |
acc1=sign(acc1) [-1,0,+1] |
Vorzeichen |
|
libam16_add |
24 |
acc1=acc1+acc2 |
Addition |
|
libam16_sub |
39 |
acc1=acc1-acc2 |
Subtraktion |
|
libam16_mul |
101 |
acc1=acc1+acc2 |
Multiplikation |
|
libam16_dmul |
112 |
acc1=acc1*acc2/256 |
erweiterte Multiplikation |
|
libam16_div |
376 |
acc1=acc1/acc2 |
Division |
|
libam16_div2 |
39 |
acc1=acc1/2 |
Division mit 2 |
|
libam16_div4 |
42 |
acc1=acc1/4 |
Division mit 4 |
|
libam16_div |
70 |
acc1=acc1/32 |
Division mit 32 |
|
libam16_mod |
378 |
acc1=acc1%acc2 |
Modulo (Rest) |
|
libam16_mdiv |
604 |
acc1=acc1*256/acc2 |
erweiterte Division |
|
libam16_sqrt |
1498 |
acc1=sqrt(acc1) |
Quadratwurzel |
|
|
4.4 Vergleichsfunktionen
Die Vergleichsfunktionen ergeben 0 oder 1, entsprechend für "falsch"
und "wahr".
|
Funktion |
Takte |
Resultat |
Beschreibung |
|
libam16_eq |
15 |
acc1=1 if (acc2 == acc1) |
Test auf Gleichheit |
|
libam16_ne |
24 |
acc1=1 if (acc2 != acc1) |
Test auf Ungleichheit |
|
libam16_gt |
16 |
acc1=1 if (acc2 > acc1) |
Test auf "Größer als" |
|
libam16_lt |
16 |
acc1=1 if (acc2 < acc1) |
Test auf "Kleiner als" |
|
libam16_ge |
25 |
acc1=1 if (acc2 >= acc1) |
Test auf "Größer oder gleich" |
|
libam16_eq |
25 |
acc1=1 if (acc2 <= acc1) |
Test auf "Kleiner oder gleich" |
|
|
4.5 Logikfunktionen
Die Logikfunktionen wirken nur auf Bit 0, alle anderen Bits werden immer auf 0 gesetzt.
|
Funktion |
Takte |
Resultat |
Beschreibung |
|
libam16_not |
13 |
acc1=1 if (acc1 == 0) |
|
|
libam16_and |
11 |
acc1 = acc1 and acc2 |
logisches AND |
|
libam16_or |
11 |
acc1 = acc1 or acc2 |
logisches OR |
|
libam16_xor |
11 |
acc1 = acc1 xor acc2] |
logisches XOR |
|
|
4.6 Regelungstechnische Funktionen
Die Regelungsfuktionen sind im Laufe der Zeit dazugekommen und dienen hauptsächlich zur
Realisierung von Regelungsalgorithmen. Die Funktionen libam16_mean(n) sind Tiefpässe
(Mittelwertbildner) mit verschiedenen Wichtungen. Je größer der Wert n ist, um so
langsamer folgt das Resultat dem Eingangswert. Mit der Limit-Funktion libam16_limit
lässt sich das Ergebnis auf einen Wert begrenzen, während die Unterdrückungsfunktion
libam16_surp Werte unterhalb einer Grenze als Null zurückgibt.
Die beiden libam16_pwsc und libam16_pwlt-Funktionen
wandeln den obersten Stackwert derart um, dass im LOW-Byte der auf 255 skalierte oder begrenzte
Absolutwert und in den beiden niederwertigesten Bits des HIGH-Bytes die Steuerbits für
positives und negatives Vorzeichen stehen.
|
Funktion |
Takte |
Resultat |
Beschreibung |
|
libam16_mean2 |
62 |
acc1 = (acc1 + acc2)/2 |
Tiefpass mit der Wichtung 1:1 |
|
libam16_mean4 |
112 |
acc1 = (3*acc1 + acc2)/4 |
Tiefpass mit der Wichtung 1:3 |
|
libam16_mean8 |
148 |
acc1 = (7*acc1 + acc2)/8 |
Tiefpass mit der Wichtung 1:7 |
|
libam16_mean16 |
218 |
acc1 = (15*acc1 + acc2)/16 |
Tiefpass mit der Wichtung 1:15 |
|
libam16_mean32 |
180 |
acc1 = (31*acc1 + acc2)/32 |
Tiefpass mit der Wichtung 1:31 |
|
libam16_limit |
54 |
acc1 = acc1 im Bereich 0...acc2 |
Begrenzung des Wertebereiches auf |acc2| |
|
libam16_surp |
56 |
acc1a=0 if |acc1|<|acc2|] |
Unterdrückung von Werten <|acc2| |
|
libam16_pwsc |
32 |
acc1l=Betrag, acc1h=0,1,2 |
Aufbereitung für PWM, Skalierung auf 255 |
|
libam16_pwlt |
32 |
acc1l=Betrag, acc1h=0,1,2 |
Aufbereitung für PWM, Begrenzung auf 255 |
|
|
erzeugt mit latex2web.pl v0.4 © 2006 Joerg Wolfram
|