StuBS
|
Die Tastatur ist das haupsächliche Eingabegerät, was wir in BSB für Signale an das Betriebssystem verwenden wollen.
Für die Tastaturabfrage sind mehrere verschiedene Codes von Bedeutung:
Der "American Standard Code for Information Interchange" ist eine in der Computerwelt sehr weit verbreitete Zuordnungstabelle für die Darstellung von Buchstaben, Ziffern und Sonderzeichen. Ursprünglich waren pro Zeichen 7 Bits vorgesehen, mittlerweile haben sich 8 Bits, also ein Byte durchgesetzt. Zeichen und Zeichenketten werden üblicherweise in ASCII abgespeichert.
Tastaturen schicken allerdings keine ASCII-Zeichen an den Computer, sondern verwenden andere Codes, die vom Prozessor verarbeitet werden müssen.
Mit dem Scancode werden den Tasten der PC-Tastatur eindeutige Nummern zugeordnet. Damit ist es auch möglich, Tasten, wie die Cursortasten, denen kein druckbares Zeichen entspricht, zu identifizieren. Bei Scancodes wird nicht zwischen Groß- und Kleinbuchstaben unterschieden, da beide mit derselben Taste erreicht werden.
Taste | Scancode |
---|---|
A | 30 |
S | 31 |
D | 32 |
Cursor hoch | 72 |
Cursor runter | 80 |
... |
Im Laufe der PC-Entwicklungsgeschichte wurden unterschiedliche Tastaturen mit einer unterschiedlichen Anzahl und Bedeutung von Tasten herausgebracht. Gerade bei den Funktions- und Spezialtasten gibt es daher auch unterschiedliche Scancodes. Da PC-Tastaturen nur wenig mehr als 100 Tasten besitzen, genügen 7 Bits, um den Scancode darzustellen.
Programme müssen nicht nur feststellen können, welche der „normalen“ Tasten gedrückt wurden, sondern auch, ob gleichzeitig die Shift (Umschalt)-Taste, die Control (Steuerungs)-Taste oder die ALT-Taste festgehalten wurden. Daher sendet die Tastatur statt eines einfachen Scancodes einen oder mehrere sogenannte Makecodes für jedes Drücken und einen oder mehrere Breakcodes für jedes Loslassen einer Taste. Wenn eine Taste länger als eine bestimmte Zeitspanne festgehalten wird, werden darüberhinaus zusätzliche Makecodes gesendet, durch die die Wiederholungsfunktion realisiert wird. Bei den meisten Tasten entspricht der Makecode dem Scancode und der Breakcode dem Scancode mit gesetztem siebten Bit. Einige Tasten erzeugen jedoch aus historischen Gründen schon beim einmaligen Drücken und Loslassen mehrere Make- und Breakcodes. Der Tastaturtreiber (im Übungssystem PS2Controller) muss aus den Make- und Breakcodes der gedrückten Tasten die gewünschten Zeichen ermitteln.
Anmerkung: Da die Interpretation der Make- und Breakcodes ziemlich mühsam, langweilig und wenig lehrreich ist, haben wir euch die Dekodierung abgenommen (siehe KeyDecoder). Allerdings kann diese Funktion nicht immer alle Zeichen, insbesondere deutsche Umlaute, korrekt erkennen. Entweder müsst ihr dann mit ein paar falschen Zeichen leben oder die Dekodiertabellen anpassen.
Wenn bei einer PC-Tastatur eine Taste gedrückt wird, werden zwei sich kreuzende Leitungen der Scan-Matrix innerhalb der Tastatur verbunden. Der Tastaturprozessor (8042 für PC/XT-, 8048 für AT und MF II-Tastaturen) ermittelt die Position der gedrückten Taste und daraus den Scancode. Über eine serielle Schnittstelle wird der Code zum Motherboard des PCs gesendet.
Auf dem Motherboard des PCs befindet sich ein Tastaturcontroller. Dieser kommuniziert über einen Eingabeport und einen Ausgabeport (für Kommandos an die Tastur) mit ebendieser. Weiter exportiert er einige Register, die als I/O-Ports mit in
und out
-Befehlen gelesen und beschrieben werden können. Der Tastaturcontroller wird zunächst im Polling-Betrieb verwendet, erst in der Aufgabe 3, soll er Interrupt-getrieben verwendet werden (siehe Polling vs. Interrupt-based Signaling).
Der Tastaturcontroller verwendet 2 I/O-Ports:
0x64
0x60
Beide Ports können sowohl beschrieben als auch gelesen werden. Jedoch verändert sich je nach Operation die Semantik der Ports.
Wird der Control-Port gelesen, erhalten wir den Wert des Statusregisters des Controllers zurück. Schreiben wir den Port, wird dem Controller allerdings ein Kommando erteilt.
Das Gleiche gilt für den Data-Port, der, wenn gelesen, aus dem Output-Puffer liest (von der Tastatur gesehen), und beim Schreiben in den Input-Puffer schreibt. Beim Schreibzugriff können wir also Kommandos an die Tastatur senden.
Port | lesen(R), schreiben(W) | Register | Bedeutung |
---|---|---|---|
0x60 | R | Ausgabepuffer | Make/Breakcode von der Tastatur |
0x60 | W | Eingabepuffer | Befehle für den Tastaturprozessor (z.B. LEDs setzen) |
0x64 | W | Steuerregister | Befehle für den Tastaturcontroller (von uns nicht verwendet) |
0x64 | R | Statusregister | Zustand des Tastaturcontrollers (z.B. Ausgabepuffer voll?) |
Beim Polling kann der Tastaturcontroller dem Prozessor kein Signal senden, dass neue Make-/Breakcodes im Ausgabepuffer vorhanden sind. Stattdessen muss der Prozessor das Statusregister aktiv überprüfen, also pollen, um festzustellen, ob neue Codes verfügbar sind (Flag outb
). Das Statusregister ist über den Control-Port (0x64
) zu erreichen. Beim Anschluss der Eingabegeräte über PS/2 ist die Maus ebenfalls an den Tastaturcontroller angebunden. Dadurch werden sowohl Codes der Tastatur als auch von der Maus in denselben Ausgabepuffer gespeichert. Also muss zusätzlich noch überprüft werden muss, ob die Codes von der Maus oder der Tastatur gesendet worden sind (Flag auxb
== 0).
Zum Schreiben von Kommandos muss gewartet werden, bis wieder freier Platz im Eingabepuffer vorhanden ist (Flag inpb
).
Bit | Maske | Name | Bedeutung |
---|---|---|---|
0 | 0x01 | outb | Gesetzt, wenn ein Zeichen im Ausgabepuffer des Tastaturcontrollers zum Lesen bereit steht |
1 | 0x02 | inpb | Gesetzt, solange der Tastaturcontroller ein von der CPU geschriebenes Zeichen noch nicht abgeholt hat |
5 | 0x20 | auxb | Gesetzt, wenn der Wert im Ausgabepuffer von der Maus und nicht von der Tastatur stammt |
Immer, wenn ein Byte vom Tastaturcontroller in seinen Ausgabepuffer geschrieben wird, signalisiert er dies der CPU durch das Setzen der Interrupt-Leitung. Der Prozessor muss darauf reagieren, indem er das angekommene Byte aus dem Ausgabepuffer liest. Im Statusregister wird dann angezeigt, wenn/dass der Ausgabepuffer wieder leer ist. Die Einrichtung von Interrupts ist etwas komplizierter und ist daher erst Teil von Aufgabe 2.
Der Tastaturcontroller kann auch Kommandos an die Tastatur senden, unter anderem um die Status-LEDs oder die Wiederholungsrate zu setzen. Dazu wird der Befehlscode in den Daten-Port des Tastaturcontrollers geschrieben. Eigentlich sollte nach dem Senden des Kommands auf ein ACK (0xfa
) der Tastatur gewartet werden, allerdings ist es schwierig, eine wirklich standardkomforme Implementierung zu erreichen. Daher ignorieren wir in diesem Fall einfach die ACK-Nachricht.
Von den etwa 20 Befehlen, die eine PS/2-Tastatur versteht, werden wir nur zwei verwenden:
Befehlscode | Name | Beschreibung |
---|---|---|
0xed | set_led | Ein-/Ausschalten der Tastatur-LEDs, gefolgt von einem weiteren Zustands-Byte. |
0xf3 | set_speed | Wiederholungsrate und Verzögerung, gefolgt von einem weiteren Byte. |
Zum Setzen der Status-LEDs an der Tastatur wird das Steuerbyte 0xed
gefolgt von einem weiteren Byte, was den Zustand angibt, gesendet. Die folgende Tabelle gibt den Aufbau des Zustands-Bytes an:
MSB (0x08) | LSB (0x01) | ||||||
---|---|---|---|---|---|---|---|
Always 0 | Always 0 | Always 0 | Always 0 | Always 0 | Caps Lock | Num Lock | Scroll Lock |
Um die Wiederholungsrate und Verzögerung einzustellen, wird der Befehlscode 0xf3
verwendet. Der Befehl erwartet als Parameter ein zweites Byte, welches die Konfiguration an die Tastatur sendet. Die Wiederholungsrate wird durch die Bits 0-4 spezifiziert, die Verzögerung durch Bit 5 und 6.
Das Konfigurationsbyte hat folgendes Format:
MSB (0x80) | 0x40 | 0x20 | 0x10 | 0x08 | 0x04 | 0x02 | LSB (0x01) | |
---|---|---|---|---|---|---|---|---|
- | - | Verzögerung | Wiederholungsrate |
Die Wiederholungsrate kann folgende Werte annehmen. Es gilt: je höher der Wert desto geringer die Wiederholrate. Die vollständige Tabelle kann unter The PS/2 keyboard interface eingesehen werden.
Wert (5 Bit) | Wiederholungsrate (Zeichen pro Sekunde) |
---|---|
0x000 | 30 |
0x002 | 25 |
0x004 | 20 |
0x008 | 15 |
0x00c | 10 |
0x010 | 7 |
0x014 | 5 |
Die Verzögerung wird in Sekunden angegeben, und kann folgende Werte annehmen:
Wert (2 Bit) | Verzögerung (in Sekunden) |
---|---|
0x0 | 0.25 |
0x1 | 0.5 |
0x2 | 0.75 |
0x3 | 1.0 |
Der Empfang des Konfigurationsbytes wird vom Tastaturcontroller ebenfalls mit einem ACK-Byte quittiert.