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