\documentclass[ngerman]{article}
\usepackage[T1]{fontenc}
\usepackage[utf-8]{inputenc}
\usepackage{multicol}
\usepackage{url}
\usepackage{graphicx,color}
\usepackage{graphics}
\DeclareGraphicsExtensions{.eps}
\usepackage{moreverb}
\setcounter{secnumdepth}{0}
\setcounter{tocdepth}{0}

\begin{document}

\renewcommand{\figurename}{Tabelle}

\title{Das Display auf dem AVR–Butterfly mit amforth ansteuern}[AVR–Butterfly Display]
\author{Michael Kalus}
\maketitle

\begin{multicols}{2}
\parskip   = 0.33\baselineskip \advance\parskip by 0pt plus 2pt

Der AVR--Butterfly ist komplett ausgerüstet, um den AVR--Microcontroller  ATmega169 zu erkunden und dessen Fähigkeiten darzustellen. Mit Hilfe des amforth kann das AVR--Butterfly interaktiv erkundet werden. Beispiele dafür findet ihr im Forth-eV Wiki \url{www.forth-ev.de/wiki}. Mir hat es Spass gemacht zu sehen, wie das Display betrieben wird. Die Einzelheiten sind beschrieben im doc2530.pdf, dem LCDdriver--Dokument von Atmel.

Der ATmega169 hat den Display--Treiber integriert. Das Display auf dem AVR--Butterfly ist sehr einfach. Es kann 6 Zeichen darstellen, zwei Doppelpunkte und einige Rauf--Runter--Pfeile. Auch einige der Nummernsymbole können angesteuert werden. Folgende Segmente sind angeschlossen (mehr Treiber hat der ATmega169 nicht):

\begin{center}
\includegraphics[width=0.95\columnwidth]{2007-01/display_bild1_2}\\
{Das Display auf dem AVR--Butterfly--Board}
\end{center}

Jedes Zeichen besteht aus 14 Segmenten. Die Zeichen Nr.\ 2 bis Nr.\ 7 können benutzt werden. Die Segmente werden einzeln geschaltet von den Bits in den LCD--Data--Registern LCDDR0..18 im ATmega169. Diese Register sind in 4 Gruppen angeordnet, je \emph{common backplane} eine Gruppe. 

\begin{center}
\includegraphics[width=0.4\columnwidth]{2007-01/display_bild2_2a}\\
{Ein Display--Zeichen besteht aus 14 Segmenten.}
\end{center}

\begin{figure*}[t]
\begin{center}
\begin{footnotesize}
\begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|}
\hline Adresse & Name & Bit7 & Bit6 & Bit5 & Bit4 & Bit3 & Bit2 & Bit1 & Bit0 & Page \\
\hline
(0xFF) & reserved & - & - & - & - & - & - & - & - &  \\
(0xFE) & LCDDR18 & - & - & - & - & - & - & - & 324 & 225 \\
(0xFD) & LCDDR17 & 323 & 322 & 321 & 320 & 319 & 318 & 317 & 316 & 225 \\
(0xFC) & LCDDR16 & 315 & 314 & 313 & 312 & 311 & 310 & 309 & 308 & 225 \\
(0xFB) & LCDDR15 & 307 & 306 & 305 & 304 & 303 & 302 & 301 & 300 & 225 \\
(0xFA) & reserved & - & - & - & - & - & - & - & - &  \\
(0xF9) & LCDDR13 & - & - & - & - & - & - & - & 224 & 225 \\
(0xF8) & LCDDR12 & 223 & 222 & 221 & 220 & 219 & 218 & 217 & 216 & 225 \\
(0xF7) & LCDDR11 & 215 & 214 & 213 & 212 & 211 & 210 & 209 & 208 & 225 \\
(0xF6) & LCDDR10 & 207 & 206 & 205 & 204 & 203 & 202 & 201 & 200 & 225 \\
(0xF5) & reserved & - & - & - & - & - & - & - & - &  \\
(0xF4) & LCDDR8 & - & - & - & - & - & - & - & 124 & 225 \\
(0xF3) & LCDDR7 & 123 & 122 & 121 & 120 & 119 & 118 & 117 & 116 & 225 \\
(0xF2) & LCDDR6 & 115 & 114 & 113 & 112 & 111 & 110 & 109 & 108 & 225 \\
(0xF1) & LCDDR5 & 107 & 106 & 105 & 104 & 103 & 102 & 101 & 100 & 225 \\
(0xF0) & reserved & - & - & - & - & - & - & - & - &  \\
(0xEF) & LCDDR3 & - & - & - & - & - & - & - & 24 & 225 \\
(0xEE) & LCDDR2 & 23 & 22 & 21 & 20 & 19 & 18 & 17 & 16 & 225 \\
(0xED) & LCDDR1 & 15 & 14 & 13 & 12 & 11 & 10 & 9 & 8 & 225 \\
(0xEC) & LCDDR0 & 7 & 6 & 5 & 4 & 3 & 2 & 1 & 0 & 225 \\
(0xEB) & reserved & - & - & - & - & - & - & - & - &  \\
(0xEA) & reserved & - & - & - & - & - & - & - & - &  \\
(0xE9) & reserved & - & - & - & - & - & - & - & - &  \\
(0xE8) & reserved & - & - & - & - & - & - & - & - &  \\
(0xE7) & LCDCCR & LCDD2 & LCDCD1 & LCDCC0 & -- & LCDCC3 & LCDCC2 & LCDCC1 & LCDCC0 & 223 \\
(0xE6) & LCDFFR & -- & LCDPS2 & LCDPS1 & LCDPS0 & -- & LCDD2 & LCDD1 & LCDD0 & 221 \\
(0xE5) & LCDCRB & LCDCS & LCD2B & LCDMUX1 & LCDMUX0 & -- & LCDPM2 & LCDPM1 & LCDPM0 & 220 \\
(0xE4) & LCDCRA & LCDEN & LCDAB & -- & LCDIF & LCDIE & -- & -- & LCDBL & 219 \\
(0xE3) & reserved & - & - & - & - & - & - & - & - &  \\
\hline
\end{tabular}
\end{footnotesize}
\caption{Die LCD--Register im ATMega169}
\end{center}
\end{figure*}

Die Anordnung der Leitungen hat eine eigenartige Verteilung dieser Nibbles im LCD--Data--Register zur Folge. Vom Basisregister aus sind die Nibbles mit einem Offset von 0, 5, 10, 15 in den Registern aufgestapelt.

Die Zeichen Nr.\ 3, 5, 7 werden von den oberen Nibbles, also Bits 7..4 eines Data--Byte--Stapels geschrieben. Die Zeichen Nr.\ 2, 4, 6 werden mit den unteren, also Bits 3..0, geschreiben. Dabei codieren immer 4x4 Nibbles eines Stapels ein ganzes Zeichen. 

\begin{center}
\includegraphics[width=0.95\columnwidth]{2007-01/display_bild4}\\
\end{center}

Aus einer Segment--Code--Tabelle kann entnommen werden, welche Segmente an sein müsssen, um ein ASCII--Zeichen darzustellen. Der Segment--Code braucht 14bit. Somit kann ein Datenwort im Flash des ATmega169 ein ganzes Zeichen codieren (cell=16Bit). Diese look-up-table ist im Beispielcode angegeben.

Gesteuert wird der Displaytreiber über 4 Control--Register im ATmega169, wie Tabelle \ref{lcdregister} 
auf Seite \pageref{lcdregister} zeigt.

\begin{figure*}[t]
\begin{center}
\begin{footnotesize}
\begin{verbatim}
 $E7 constant LCDCCR \ contrast control register
    \ LCDCCR7..5 = LCDCD CLK driver time disply is on; %111 = 50%.
    \ LCDCCR4 ist nc
    \ LCDCCR3..0 = LCDCC Contrast Control; %1111 = 3,35V; %0000 = 2,60V.

  $E6 constant LCDFRR \ frame rate register
    \ LCDFRR7 is nc 
    \ LCDFRR6..4 = LCDPS prescaler for clock divide; %0000 = CLK/16.
    \ LCDFRR3 ist nc
    \ LCDFRR2..0 = LCDCD clock divide; %110 = 7 is common framerate.

  $E5 constant LCDCRB \ control register B
    \ LCDCRB7 = LCDCS clock source; %0 = internal clock.
    \ LCDCRB6 = LCD2B bias; %1 = 1/3 bias für alle 4 backplanes.
    \ LCDCRB5..4 = LCDMUX duty cyles; %11 = 1/4 weil es 4 backplanes sind.
    \ LCDCRB3 ist nc
    \ LCDCRB2..0 = LCDPM port mask; %111 = alle Segmentleitungen werden benutzt.
 
  $E4 constant LCDCRA \ control register A
    \ LCDCRA7 = LCDEN enable display driver; %1 = on, %0 = off.
    \ LCDCRA6 = LCDAB low power wave form; %1 = use low power.
    \ LCDCRA5 is nc
    \ LCDCRA4 = LCDIF interrupt flag; gesetzt wenn ein Frame fertig ist.
    \ LCDCRA3 = LCDIE interrupt enable; %1 = interrupt enabled.
    \ LCDCRA2..1 sind nc
    \ LCDCRA0 = LCDBL blank display; entlädt das Display über alle Segmenttreiber; data register bleiben erhalten.  
\end{verbatim}
\end{footnotesize}
\caption{\label{lcdregister}Der Display--Treiber verwendet 4 ATmega169--Control--Register}
\end{center}
\end{figure*}

Mein Beispiel zeigt, wie man Text und Ziffern im Display des Butterfly zeigen kann. Es wurde der Ansatz verfolgt, die Zeichen zunächst in einen Ausgabepuffer zu schreiben von dem aus das LCD Display geladen werden kann. Das gibt die Möglichkeit den Ursprung der Zeichen später frei bestimmen zu können. So können nun Zeichen aus dem regulären Ausgabestrom dorthin umgelenkt werden mit der Phrase: \verb|<lcd> ." hallo" </lcd>| oder ähnlichem. Oder es wird \verb|lcd"| oder \verb|lcd.| benutzt. Natürlich ist auch die direkte Beschriftung des \verb|TOB| möglich mittels \verb|c!| oder \verb|move|. Die Länge des Puffers ermöglicht es auch die Anzeige zu scrollen oder Menüs zu machen. Aber das sei der Fantasie der Leser überlassen. Viel Vergnügen beim Ausprobieren und Experimentieren.

Mein Dank gebührt Matthias Trute für das amforth und seine Hilfe bei Fragen dazu. Und Ulrich Hoffmann für die anregende Disskussion und gute Hinweise wenn ich nicht weiter wusste. 

\end{multicols}

\subsection{Links}
\begin{tabular}{ll}
Butterfly im Forth--Wiki & \url{http://www.forth-ev.de/wiki/doku.php/projects:avr:atmega169}\\
Atmel--Homepage & \url{http://www.atmel.com/}\\
Atmel--LCD--Treiber & AVR065: LCD Driver for the STK502 and AVR Butterfly (doc2530.pdf) 
\end{tabular}
\newpage
\label{displaylisting}
\listinginput[1]{1}{2007-01/lcd.fs}
