Erstellt: 7. März 2013 (zuletzt geändert: 1. Januar 2018)

Tastaturmatrix

Wie die Tastatur funktioniert

Nach PETSCII und Char-ROM sollte man noch wissen, wie Tastatureingaben ausgelesen werden können.

Der C64 besitzt 66 Tasten, davon sind 64 in einer 8×8 Matrix organisiert (s. unten).

Die beiden fehlenden Tasten sind:

  • SHIFT LOCK : Diese ist parallel zur linken SHIFT-Taste <L.SHIFT> geschaltet und ermöglicht durchs Einrasten ein dauer Großschreiben, so wie Caps-Lock beim PC.
  • RESTORE : Diese Taste läßt sich nicht so einfach (eigentlich nur über Umwege) abfragen! Sie ist direkt mit der NMI-Leitung (None Maskable Interrupt / nicht maskierbarer Interrupt) des Prozessors verbunden. Ein NMI läßt sich nicht durch den SEI-Befehl unterdrücken, man kann höchstens die Einsprungadresse verbiegen und so den Interrupt umgehen.

Enter the Matrix 😉

Um unter Assembler Tastatureingaben abzufragen, kann man entwerder auf Systemroutinen (z. B. das GET vom Basic oder auf die Kernal-Funktion SCAN KEYBOARD) zurückgreifen oder man programmiert es selbst.

Schauen wir uns dazu erstmal die Tastaturmatrix an:

Die Tastaturmatrix des C64 inkl. Joystickports
Die Tastaturmatrix des C64 inkl. Joystickports

Als erstes fällt auf, dass wir zum Abfragen zwei Register ($dc00 Port A / $dc01 Port B) vom CIA-1 benötigen. Außerdem sehen wir, dass neben den Tasten, auch die beiden Joystickports über diese Matrix abgefragt werden (was durchaus zu Problemen führen kann).
Was wir in der Grafik nicht sehen können ist, dass alle nicht gedrückten Tasten einen High-Pegel aufweisen, sie liefern also eine 1!! Um zu erkennen, ob eine Taste gedrückt wurde müssen wir diese also auf 0 prüfen!!

Möchten wir auf eine spezielle Taste (nehmen wir mal HOME) warten, können wir z. B. so vorgehen:
Wir setzten das Bit PA6 in $dc00 auf 0, da sich unsere gesuchte Taste in dieser Spalte befindet. Anschließend prüfen wir, ob in $dc01 PB3 auf 0 steht, da sich HOME genau an der Kreuzung von PA6 und PB3 befindet.

An der Kreuzung von PA6 und PB3 befindet sich die HOME-Taste.

Ist das der Fall, dann wurde unsere Taste gedrückt, anderenfalls prüfen wir solange weiter, bis sie gedrückt wurde.

Hier ein kleines Assembler Beispiel:

CIA_A     = $dc00                   ;CIA-1 Port A
CIA_B     = $dc01                   ;CIA-1 Port B

;*** Startadresse BASIC-Zeile
*=$0801
 !word main-2
 !word 2018
 !text $9E," 2062",$00,$00,$00
 
;*** Start des Assemblerprogramms
main
 sei                                ;Interrupts sperren: Wichtig,
                                    ;sonst funkt man uns evtl. dazwischen

 lda #%10111111                     ;wir wollen PA6 maskieren
 sta CIA_A                          ;ins Register CIA-1 Port A schreiben

.loop
 lda CIA_B                          ;hole Register-Inhalt vom CIA-1 Port B
 and #%00001000                     ;hier PB3 prüfen (HOME-Taste)
 bne .loop                          ;wenn KEINE 0, dann zu .loop springen
                                    ;sonst wurde HOME gedrückt und wir sind fertig
 cli                                ;Interrupts wieder freigeben
 rts                                ;zurück zum Aufrufer (hier BASIC)

Die Tastaturabfrage des C64 macht übrigens nichts anderes. Sie schaltet einzeln jedes Bit in $dc00 einmal auf 0 und prüft dann über $dc01 welche Bits gelöscht sind. Falls ihr euch dafür interessiert, die entsprechende Kernal-Routine findet ihr ab $EA87.

In der Grafik könnt ihr sehen, dass auch die Joystickports auf PA (Joy-2) und PB (Joy-1) gemappt sind. Dies kann dazu führen, dass ihr Probleme bekommt, wenn ihr Tasten und Joysticks gleichzeitig abfragen möchtet. Bei der Tastaturroutine des KERNALs könnt ihr das z. B. sehen. Startet Vice wählt als Joystick den im Port-1 aus und drückt den Stick dann immer nach unten. Auf dem BS erscheinen verschiedene Zeichen, die auf PB1 zu finden sind.
Außerdem gibt es Schwierigkeiten, wenn ihr mehrere Tasten gleichzeitig erkennen wollt. Dies wird von Emulatoren bisher nicht simuliert, einzig im CCS64 könnt ihr das mal testen, indem ihr Cursor links und Cursor runter gleichzeitig drückt und dann wiederholt

Ein Phantom-Tastendruck
Ein Phantom-Tastendruck

die linke SHIFT-Taste betätigt. Es erscheint dann hin und wieder das -Symbol, dass SHIFT + A entspricht. Auf einem echten C64, könnt ihr dieses Verhalten für alle Tasten reproduzieren, die sich an den Ecken eines gedachten Rechtecks auf der Tastaturmatrix befinden. Haltet ihr zwei davon zusammen gedrückt und betätigt dann die dritte, erscheint ab und zu das Zeichen, dass sich an der 4. Ecke befindet.
Dieses Verhalten hat übrigens einen technischen Grund und ist kein Softwarefehler. Durch eine Diode je Taste, hätte man es verhindern können.

Keyscan mit dem Kernal

Normalerweise fragt der C64 60mal in der Sekunde die Tastatur ab. Solange der dazugehörige Interrupt aktiv ist, könnt ihr die aktuelle Taste auch über eine Zeropage-Adresse in Erfahrung bringen. Dazu müsst ihr nur schauen, was in der Adresse $cb steht. Dort legt die Keyscanroutine des Kernals nämlich die Matrixkoordinate der aktuell gedrückten Taste ab.

Exkurs: Was fängt das Betriebssystem mit dem Wert aus $cb an?
Jede der 64 möglichen Tasten, kann bis zu 4 verschiedene Zeichen erzeugen. Wie ihr wisst, ändert sich die Ausgabe abhängig davon, ob ihr SHIFT, CONTROL oder die Taste mit dem COMMODORE LOGO zusätzlich drückt. Um jetzt eine Matrixkoordinate in ein Zeichen unzuwandeln, nutzt der Kernal vier Hilfstabellen. Diese findet ihr ab $eb81. In jeder Tabelle sind 64 Zeichen abgelegt – für jede Zusatztaste eins.

  • $eb81 : weder SHIFT, CONTROL noch die Taste mit dem COMMODORE LOGO sind gedrückt
  • $ebc2 : SHIFT wurde zusätzlich gedrückt
  • $ec03 : COMMODORE LOGO wurde zusätzlich gedrückt
  • $ec78 : CONTROL wurde zusätzlich gedrückt

Um nun auf diese Tabellen einfach zugreifen zu können, wird auf der Zeropage bei $f5 und $f6 die Adresse der benötigten Tabelle, abhängig von der gedrückten Zusatztaste, abgelegt.

Steht bei $cb der Wert #$40 bzw. 64 dezimal, dann ist aktuell keine Taste gedrückt. Die Werte für die einzelnen Tasten findet ihr in der folgenden Grafik:

Matrixkoordinaten (Hex / Dez)
Matrixkoordinaten (Hex / Dez)

Wie euch evtl. aufgefallen ist, werden einige Tasten nicht dort abgelegt:
SHIFT, CONTROL und die Taste mit dem COMMODORE LOGO. Diese vier (es gibt ja links und rechts eine SHIFT-Taste!) werden abweichend behandelt und lassen sich daher nicht über $cb auswerten! Den Status dieser Tasten findet ihr bei $28d. Allerdings könnt ihr dort nicht erkennen, welche SHIFT-Taste gedrückt wurde! In den unteren drei BITs steht welche Taste es war…

  • %000 = weder SHIFT, CONTROL noch die Taste mit dem COMMODORE LOGO sind gedrückt
  • %001 = eine der SHIFT-Tasten ist gedrückt
  • %010 = die Taste mit dem COMMODORE LOGO wurde gedrückt
  • %100 = CONTROL wurde gedrückt
  • %011, %101, %110 und %111 : Werden mehrere Tasten gleichzeitig betätigt, dann addieren sich die Werte

Die Abfrage gestaltet sich nun relativ einfach, ich beschänke mich hier mal auf $cb

;*** Startadresse BASIC-Zeile
*=$0801
 !word main-2
 !word 2018
 !text $9E," 2062",$00,$00,$00

main
    lda $cb                         ;Matrixkoordinate lesen
    cmp #$40                        ;wurde eine Taste gedrückt?
    bne main                        ;falls nicht -> main
.wait
    inc $d020                       ;Rahmenfarbe erhöhen
    lda $cb                         ;Matrixkoordinate lesen
    cmp #$3c                        ;wurde SPACE gedrückt?
    bne .wait                       ;falls nicht -> .wait
    rts                             ;zurück zum BASIC

Zu Beginn warten wir, falls aktuell eine Taste gedrückt ist, bis diese losgelassen wird. Dies soll verhindern, dass das Programm evtl. versehentlich direkt wieder beendet wird. Dann lassen wir den Rahmen so lange blinken, bis SPCAE gedrückt wird. Ist dies der Fall, geht es zurück ins BASIC.


Schrott!!Naja...Geht so...Ganz gut...SUPER! (7 Bewertungen | Ø 5,00 von 5 | 100,00%)

Loading...


Zurück

4 Gedanken zu „Tastaturmatrix“

  1. Jetzt habe ich eine ganze Zeit mit dem “Problem” verbracht, dass das Prg auch bei F2 – und nicht nur F1 – aussteigt.
    Bis mir dann endlich wieder einfiel, dass das am C64 die gleiche Taste, nur mit SHIFT, ist… was man nicht alles vergisst, wenn man am Emulator sitzt. :))

    1. Da liegst du falsch, die hier gezeigte Matrix ist richtig!
      Wenn du dir den 2. Teil des Artikels (64’er 05/84 ab Seite 105) anschaust, erwähnt der Autor das auch.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Protected by WP Anti Spam