\documentclass[12pt,a4paper]{scrartcl} \usepackage[utf8]{inputenc} \usepackage[ngerman]{babel} \usepackage{graphicx} \usepackage{amsmath,amssymb,amsfonts} \usepackage[table,dvipsnames]{xcolor} \usepackage{array} \usepackage{makecell} \definecolor{tablehead}{hsb}{0,0,0.9} \newcolumntype{C}[1]{>{\centering\arraybackslash}p{#1}} \title{Pinlock: Dokumentation} \subtitle{Mikrocontroller-Seminar} \author{Leonard Kugis, Mattes Melius} \begin{document} \maketitle \tableofcontents \newpage \section{Idee} \section{Hardware} \subsection{Platinenaufbau} \subsection{Mikrocontroller ATmega16A} \subsection{Sonstige Komponenten} \section{Software} Das Programm wurde in AVR-Assembler geschrieben, mit Assemblerdirektiven für den \emph{Avra}-Assembler. Grundsätzlich wurden für dieses Programm die in Tabelle~\ref{tbl:registermap} Register-Neudefinitionen vorgenommen, um den Code lesbarer zu gestalten. \begin{table}[!htb] \centering \begin{tabular}{|C{0.2\linewidth}|C{0.2\linewidth}|C{0.5\linewidth}|} \hline \rowcolor{tablehead} ATmega16A Register & Neu definierte Registerbezeichnung & Funktion \\ \hline \texttt{r16} & \texttt{tmp0} & Temporäres Pufferregister 0 \\ \hline \texttt{r17} & \texttt{par0} & Parameterregister 0 \\ \hline \texttt{r18} & \texttt{par1} & Parameterregister 1 \\ \hline \texttt{r19} & \texttt{tmp1} & Temporäres Pufferregister 1 \\ \hline \texttt{r20} & \texttt{tmp2} & Temporäres Pufferregister 2 \\ \hline \texttt{r21} & \texttt{ret0} & Rückgaberegister 0 \\ \hline \texttt{r22} & \texttt{ret1} & Rückgaberegister 1 \\ \hline \texttt{r23} & \texttt{par2} & Parameterregister 2 \\ \hline \texttt{r24} & \texttt{par3} & Parameterregister 3 \\ \hline \texttt{r25} & \texttt{par4} & Parameterregister 4 \\ \hline \texttt{r26} & \texttt{ret2} & Rückgaberegister 2 \\ \hline \texttt{r27} & \texttt{heart} & Debug \\ \hline \texttt{r28} & \texttt{dig0} & Pufferregister für Ziffern 0 und 1 \\ \hline \texttt{r29} & \texttt{dig1} & Pufferregister für Ziffern 2 und 3 \\ \hline \end{tabular} \caption{Neu definierte Registerbezeichnungen für Register des ATmega16A} \label{tbl:registermap} \end{table} \subsection{Grundprinzip} Nach Zurücksetzen des Mikrocontrollers durchläuft das Programm eine Initialisierungsroutine. Diese beinhaltet im Wesentlichen folgende Schritte: \begin{enumerate} \item Initialisierung des Stackpointers mit den Grenzen des verfügbaren RAMs \item Konfiguration der GPIO-Ports \item Initialisierung der Displays \item Lesen des Zugangscodes aus dem EEPROM \end{enumerate} Anschließend wird eine endlose Hauptschleife durchlaufen, die folgende Aktionen periodisch ausführt: \begin{enumerate} \item Warte 12240 Zyklen. \item Lese alle Tasten der Eingabematrix aus. \item Ermittle Änderungen des neuen Tastenstatus zu dem alten Tastenstatus. \item Bei positiver Flanke (Taste war vorher nicht gedrückt und ist jetzt gedrückt): Behandle den Tastendruck bezüglich des aktuellen Zustands (s.u.). \item Puffere den neuen Tastenstatus. \end{enumerate} Die einzelnen Routinen, die dabei aufgerufen werden, werden genauer in Sektion~\ref{sec:functions} erläutert. Die Behandlung der (neu) gedrückten Taste bezüglich des aktuellen Zustandes erfolgt nach der in Abbildung~\ref{fig:states} dargestellten \emph{Finite-State-Machine} (FSM). Die Zustände sind dabei nach folgendem Schema benannt: \begin{tabular}{r@{: }l r@{: }l} \texttt{A} & \emph{Authenticating}, Authentifizierung findet gerade durch Codeeingabe statt \\ \texttt{AS} & \emph{Authentication Submitted}, Code wurde bestätigt und wird überprüft \\ \texttt{AD} & \emph{Authenticated}, Benutzer ist authentifiziert und hat Zugriff \\ \texttt{C} & \emph{Change}, Benutzer ändert den Zugriffscode \end{tabular} Dabei folgt die Notation der Transitionsbedingungen dem Schema \\ \colorbox{lightgray}{\texttt{ / }}. Die Tastendarstellungen innerhalb des Programmes unterliegen dabei der Zuordnung in Tabelle~\ref{tbl:keymap}. \begin{figure}[!htb] \centering \includegraphics[width=0.7\linewidth, keepaspectratio]{resources/states} \caption{FSM der Behandlung von Tastendrücken (schematisch)} \label{fig:states} \end{figure} \begin{table}[!htb] \centering \begin{tabular}{|c|c|} \hline \rowcolor{tablehead} Taste extern & Taste intern \\ \hline \texttt{0..9} & \texttt{0x00..0x09} \\ \hline \texttt{A..D} & \texttt{0x0A..0x0D} \\ \hline \texttt{*} & \texttt{0x0E} \\ \hline \texttt{\#} & \texttt{0x0F} \\ \hline \end{tabular} \caption{Zuordnung von externen zu internen Tastendarstellungen} \label{tbl:keymap} \end{table} \subsection{Routinen}\label{sec:functions} \subsubsection{\texttt{wait}} \begin{tabular}{r@{: }l r@{: }l} Parameter & \makecell[l]{\texttt{par0}: Wartezyklen Stufe 1, \\ \texttt{par1}: Wartezyklen Stufe 2, \\ \texttt{par2}: Wartezyklen Stufe 3} \\ Rückgabe & - \end{tabular} Warte über drei verschachtelte Schleifen mit verschiedenen Durchlaufzahlen. Die gesamte, zu wartende Zyklendauer beträgt somit $\Delta t_\text{ges} = \text{\texttt{par0}} \cdot \text{\texttt{par1}} \cdot \text{\texttt{par2}}$. \subsubsection{\texttt{write\_code}} \begin{tabular}{r@{: }l r@{: }l} Parameter & - \\ Rückgabe & - \end{tabular} Schreibe statisch die Werte 0x01 und 0x23 (entspricht der Zahlenkombination \texttt{0123}) in das EEPROM an die Adressen 0x00 und 0x01. \subsubsection{\texttt{load\_code}} \begin{tabular}{r@{: }l r@{: }l} Parameter & - \\ Rückgabe & \makecell[l]{\texttt{ret0}: Ziffern 0 und 1, \\ \texttt{ret1}: Ziffern 2 und 3} \end{tabular} Lese die gespeicherte Zahlenkombination aus dem EEPROM (Adressen 0x00 und 0x01) aus. \subsubsection{\texttt{shift\_out}} \begin{tabular}{r@{: }l r@{: }l} Parameter & \makecell[l]{\texttt{par0}: Zu schreibendes Byte, \\ \texttt{par1..par2}: Adresse zur Funktion, um 0 zu schreiben, \\ \texttt{par3..par4}: Adresse zur Funktion, um 1 zu schreiben} \\ Rückgabe & - \end{tabular} Schreibe ein Byte Bit für Bit durch Funktionsaufrufe, welche das Schreiben des 0- und 1-Bits implementieren. Das können beispielsweise Funktionen sein, die 0 bzw. 1 an ein Schieberegister anlegen. \subsubsection{\texttt{shift\_in}} \begin{tabular}{r@{: }l r@{: }l} Parameter & \makecell[l]{\texttt{par0..par1}: Adresse zur Funktion, um einen Clockzyklus zu durchlaufen, \\ \texttt{par2..par3}: Adresse zur Funktion, das zugehörige Bit zu lesen} \\ Rückgabe & \makecell[l]{\texttt{ret0}: Gelesenes Byte} \end{tabular} Lese ein Byte Bit für Bit aus einem Schieberegister. Das Durchlaufen eines Clockzyklus und Lesen des Bits ist in übergebenen Funktionen implementiert. \subsubsection{\texttt{eeprom\_write}} \begin{tabular}{r@{: }l r@{: }l} Parameter & \makecell[l]{\texttt{par0..par1}: Zieladresse, \\ \texttt{par2}: Zu schreibender Wert} \\ Rückgabe & - \end{tabular} Schreibt ein Byte an die gegebene Adresse in das interne EEPROM. \subsubsection{\texttt{eeprom\_read}} \begin{tabular}{r@{: }l r@{: }l} Parameter & \makecell[l]{\texttt{par0..par1}: Adresse} \\ Rückgabe & \makecell[l]{\texttt{ret0}: Gelesener Wert} \end{tabular} Liest ein Byte von der gegebenen Adresse im internen EEPROM. \subsubsection{\texttt{status}} \begin{tabular}{r@{: }l r@{: }l} Parameter & \makecell[l]{\texttt{par0}: Statusbits} \\ Rückgabe & - \end{tabular} Gibt die gegebenen Statusbits über die LEDs aus. Dabei wird das Schieberegister dafür benutzt. \subsubsection{\texttt{display}} \begin{tabular}{r@{: }l r@{: }l} Parameter & \makecell[l]{\texttt{par0}: Displaynummer, \\ \texttt{par1}: Darzustellende Ziffer} \\ Rückgabe & - \end{tabular} Zeige die gegebene Ziffer auf dem gegebenen Display. \subsubsection{\texttt{set\_digit}} \begin{tabular}{r@{: }l r@{: }l} Parameter & \makecell[l]{\texttt{par0}: Ziffernstelle, \\ \texttt{par1}: Ziffer} \\ Rückgabe & - \end{tabular} Schreibt die Ziffer an die Ziffernstelle des internen Puffers. \subsubsection{\texttt{get\_digit}} \begin{tabular}{r@{: }l r@{: }l} Parameter & \makecell[l]{\texttt{par0}: Ziffernstelle} \\ Rückgabe & \makecell[l]{\texttt{ret0}: Ziffer an der Stelle} \end{tabular} Liest die Ziffer der gegebenen Stelle von dem internen Puffer. \subsubsection{\texttt{input}} \begin{tabular}{r@{: }l r@{: }l} Parameter & - \\ Rückgabe & \makecell[l]{\texttt{ret0}: Tastenstatus mit Belegung: \texttt{0852*741}, \\ \texttt{ret1}: Tastenstatus mit Belegung: \texttt{DCBA\#963}} \end{tabular} Liest den Tastenstatus aller Tasten aus. Ein 1-Bit entspricht einer gedrückten, ein 0-Bit einer nicht gedrückten Taste. Das Auslesen der Tasten der Eingabematrix erfolgt über die Schieberegister: eines (Serial-In-Parallel-Out) zur Selektion der auszulesenden Zeile und eines (Parallel-In-Serial-Out) zum eigentlichen Auslesen selbiger. Dies wird innerhalb der Ausleseroutine mit jeder Zeile gemacht, um gedrückte Tasten zu identifizieren. \subsubsection{\texttt{translate}} \begin{tabular}{r@{: }l r@{: }l} Parameter & \makecell[l]{\texttt{par0}: Tastenstatus Bits \texttt{7..0}, \\ \texttt{par1}: Tastenstatus Bits \texttt{15..8}} \\ Rückgabe & \makecell[l]{\texttt{ret0}: Übersetzter Tastencode} \end{tabular} Übersetzt den Tastenstatus in die entsprechende, interne Tastendarstellung. Dabei wird nach der Zuordnung aus Tabelle~\ref{tbl:keymap} vorgegangen. \subsubsection{\texttt{handle}} \begin{tabular}{r@{: }l r@{: }l} Parameter & \makecell[l]{\texttt{par0}: Aktueller Zustand, \\ \texttt{par1}: Tastencode} \\ Rückgabe & \makecell[l]{\texttt{ret0}: Neuer Zustand} \end{tabular} Behandle den Tastencode unter dem aktuellen Zustand. Das Zustandsfeld hat folgende Belegung (ein Zeichen entspricht einem Bit): \begin{center} \texttt{CSSSSSDD} \end{center} \begin{tabular}{r@{: }l r@{: }l} \texttt{0} & Reserviert \\ \texttt{C} & Pufferbit für Blinken der ausgewählten Stelle \\ \texttt{S} & Zustandsinformationen \\ \texttt{D} & Aktuell ausgewähltes Display \end{tabular} Die Behandlung erfolgt nach dem in Abbildung~\ref{fig:states} dargestellten Schema. \section{Bedienung} \end{document}