% Content-encoding: UTF-8 \documentclass[ngerman]{article} \usepackage[T1]{fontenc} \usepackage[latin1]{inputenc} \setcounter{secnumdepth}{0} \setcounter{tocdepth}{0} \begin{document} \title{Named Bits} \author{Text: Michael Kalus, Idee und Code: Matthias Trute} \maketitle Die Handhabung von benannten Bits in Daten--Registern für Ports, Data--Direction--Registern und anderen Registern am Beispiel des ATmega169. \section{Zusammenfassung:} Mittels \verb|CREATE| und \verb|DOES>| werden auf einfache Weise soviele einzelne Bits benannt, wie man möchte. In den zugehörigen Registern können diese Bits dann einfach gesetzt oder zurückgesetzt werden. So lassen sich Pins in den INPUT-- oder OUTPUT--Modus schalten oder andere Registeroperationen durchführen. \section{Summary:} We use \verb|CREATE| and \verb|DOES>| to give names to individual bits of registers. These may be used to toggle the bits, and for example switch INPUT and OUTPUT modus easily. Or do other operations on registers. \begin{multicols}{2} Motiviert durch häufige Versuche mit den Prozessoren Atmega8, Atmega32 und ATmega169 entstanden diese kleinen Test--Helfer. Der Leser mag selbst entscheiden, ob er so etwas auch in Applikationen einbauen möchte. Man kann solchen syntaktischen Code als Ballast sehen. Doch in Phasen intensiver Testung war es ausgesprochen nützlich. Außerdem erhöht sich die Lesbarkeit von Quellcodes damit, ein Kriterium, das nicht gering geschätzt werden sollte. Ich persönlich halte so etwas also nicht für \emph{Ballast}. \section{Die Aufgabe} Immer wieder mussten Bits in den Daten--Registern der Ports Px und auch in den korrespondierenden Data Direction Registern DDRx des ATmaga169 gesetzt und wieder gelöscht werden, ohne dabei die anderen Bits des Registers zu verändern. Die Routinen dafür sind ja bekannt --- Byte aus dem Register lesen, mit einer Bitmaske verknüpfen und das Byte zurückschreiben. Soll dabei das Bit gesetzt werden, wird der geholte Wert mit der Bit--Maske OR--verknüpft und das Ergebnis zurückgeschrieben. Und soll das Bit gelöscht werden, wird der Wert mit der invertierten Bit--Maske AND--verküpft. Bei sieben Ports zu je acht Bits ist es irgendwann einfach lästig, immer wieder nach zu sehen, wie die Adresse des Data--Registers für den Port lautet, und mit welcher Bitmaske denn das Data--Direction--Register gesetzt, oder der Port selbst beschrieben oder gelesen werden muss. \section{Die Lösung} Diese wiederkehrende Routineaufgabe hat die Registeradresse und die Pin--Nummer als Basis. Jedes einzelne Bit lässt sich durch diese beiden Werte charakterisieren. Und bei den ATmegas liegt das DDRx immer eine Adresse tiefer als sein Port. Was liegt also näher, als für die viel benutzten Bits einen eigenen \emph{intelligenten} Namen zu vergeben? So ein Bit sollte sozusagen selber wissen, wer es ist. Es soll Auskunft geben können, zu welcher Adresse es gehört, und dazu auch mitteilen können, wo in der Bitfolge es sich befindet. Letzteres ist ja unter dem Begriff der Bitmaske bekannt. Im konkreten Anwendungsfall der ATmegas und des amforth passt diese Information gerade ganz gut zusammen in eine einzelne Zelle im internen Flash--Speicher. Die DRx und ihre DDRx liegen alle im Adress--Bereich von 0x20 bis 0x34, da genügt also ein Byte als Speicherplatz für die Adresse. Und die Bitmaske passt in das andere Byte einer Speicherzelle. Im Falle der Ports soll diese Maske allerdings Pin--Maske heißen. So kann mit Hilfe der shift--Operation aus der Pin--Nummer eine Bit--Maske erzeugt werden, die dann zusammengepackt mit Adresse ins Flash geschrieben wird. Diese Speicherstelle bekommt einen Namen. Und wird dieser aufgerufen, legt er nun die Bit--Maske und die Adresse des Registers auf den Stack. Nun können Operatoren wie \verb|ON| und \verb|OFF| oder \verb|IS_INPUT| und \verb|IS_OUTPUT| gemacht werden. Diese benutzen die Informationen z.~B., um einen Portpin an-- oder aus zu schalten oder um die Datenrichtung des Pins im Port umzukehren. Das Listing zeigt wie das gemacht werden kann. Hier noch ein kleiner Test, um die Helfer zu erproben: \begin{verbatim} hex 2B constant PD PD 0 portpin: PD0 PD0 is_output PD0 on PD0 off \end{verbatim} \section{Hinweis} Die solcherart definierten Bits sind nun nicht auf die PORTx Adressen beschränkt. Sie gelten für alle mit 8 Bit erreichbaren Adressen, und das sind alle IO--Adressn (wers doll treiben will, kann im ATmega auch die CPU--Register damit manipulieren). Man kann also beispielsweise die diversen Steuerregister bis hin zum SREG damit lesbar ansprechen. Lediglich die Worte \verb|is_input|/\verb|is_output| setzen auf der Abhängigkeit $\mathrm{DDRx} = \mathrm{PORTx} - 1$ auf, sind aber ohnehin nur für diese sinnvoll. Viel Vergnügen beim Ausprobieren. \end{multicols} \section{Links:} \begin{tabular}{ll} amforth& \url{http://amforth.sourceforge.net/} \\ Datenblatt des ATmega169 & \url{http://www.atmel.com/dyn/resources/prod_documents/doc2514.pdf} \end{tabular} \vfill \label{namedbitlisting} \listinginput[1]{1}{2007-02/named_bits_v1_1a.fs} \hfill Fortsetzung des Listings auf Seite \pageref{namedbitlistingteil2} \vfill % \end{document}