keyman64

Programmierbarer Tastatur- und Hardware-Controller

Keyman64 Rev.4

Der Keyman64 ist ein programmierbarer Tastatur- und Hardware-Controller für Heimcomputer, die mit einer einfachen 64-Tasten Matrixtastatur ausgestattet sind.

Das Gerät wird zwischen Tastatur und Computer installiert und überwacht dort die physische Tastatur, deren Zustand zunächst immer unmittelbar an den Computer weitergeleitet wird. Der Computer liest die vom Keyman64 bereitgestellte virtuelle Tastatur genau wie eine normale Tastatur aus. Der Keyman64 kann dadurch sowohl alle vom Benutzer getätigten Tastatureingaben überwachen als auch den vom Computer gelesenen Zustand der Tastatur bestimmen.

Der Keyman64 kann nun so programmiert werden, dass bestimmte Tastenkombinationen nicht an den Computer weitergeleitet werden, sondern stattdessen eine oder mehrere der sechzehn auf der Platine ausgeführten digitalen Steuerleitungen auf bestimme, benutzerdefierte Weise geschaltet werden. Mit Hilfe dieser Steuerleitungen kann im Computer verbaute Zusatzhardware anstelle von Schaltern oder Tastern kontrolliert werden.

Mit dem Keyman64 ist somit der Einbau von Schaltern oder Tastern in das Gehäuse des Computers nicht mehr notwendig.

Unter anderem bietet das Gerät zusätzlich die Möglichkeit, benutzerdefinierte Tastatur-Macros zu senden oder auch das Layout der Tastatur zu verändern. Alle Steuerbefehle können auch vom PC aus über USB oder über die integrierte serielle Schnittstelle Keyman64 gesendet werden, so dass sowohl eine Fernsteuerung von einem externen Rechner, dem Computer selbst oder durch andere Mikrokontroller möglich ist.

Einige konkrete Beispiele finden sich im Abschnitt Anwendungsbeispiele.

Die Dokumentation ist auf deutsch und englisch verfügbar.

Übersicht

Arbeitsweise

Während des normalen Betriebs leitet das Gerät alle Tastaturereignisse direkt an den Computer weiter, es sei denn, es wird die als Meta-Taste definierte Taste heruntergehalten. Solange Meta heruntergehalten wird, lösen zusätzliche Tastatureingaben die Ausführung der vom Benutzer für die jeweilige Tastenkombination definierten Schaltsequenzen aus. Wird die Meta-Taste wieder losgelassen, werden Tastaturereignisse wieder an den Computer weitergeleitet.

Wurde allerdings keine weitere Taste betätigt, während die Meta-Taste gedrückt war, so wird das Betätigen der Meta-Taste selbst an den Computer weitergeleitet. Auf diese Weise ist die Meta-Taste nicht “verloren”, und kann weiterhin wie vorgesehen verwendet werden. Der einzige Unterschied besteht darin, dass der Computer das Herunterdrücken und Loslassen der Taste erst registriert, nachdem die pyhsische Taste wieder losgelassen wurde.

Diese Vorgehensweise funktioniert gut, so lange die Meta-Taste lediglich kurz betätigt werden soll, um z.B. den jeweiligen Buchstaben oder das jeweilige Symbol einzugeben. Soll die Taste jedoch eine längere Zeit gedrückt gehalten werden, muss dies über eine weitere Tastenkombination realisiert werden, z.B.:

m: down ARROWLEFT

Unter der Annahme, dass der Linkspfeil als Meta-Taste verwendet wird, kann der Befehl “down ARROWLEFT” durch gleichzeitiges Drücken von Linkspfeil und der Taste “M” ausgelöst werden. Die virtuelle Linkspfeil-Taste wird nun solange vom Computer als gedrückt gesehen, wie die Meta-Taste gehalten wird. Sobald Meta losgelassen wird, scannt und übermittelt das Gerät wieder die physische Tastatur an den Computer, wodurch das Herunterhalten von Meta aus Sicht des Computers wieder beendet wird.

Als Meta-Taste dient in der Standardeinstellung die Linkspfeil-Taste. Um eine andere Taste als Meta-Taste zu verwenden, kann der unten beschriebene Befehl meta verwendet werden.

Software

Ein einfachen Kommandozeilen-Tool dient zur Konfiguration und zur Kontrolle des Geräts. Dieses tool übersetzt die vom Benutzer geschriebene Konfigurationsdatei in ein binäres Format, das in den EEPROM-Speicher des Mikrocontrollers geschrieben wird. Dies ist im Abschnitt Konfiguration detailliert beschrieben.

Zusätzlich erlaubt das tool die Kontrolle des Keyman64 über USB. Es können beliebige Befehle über USB an das Gerät gesendet und dort direkt ausgeführt werden.

Hardware

Das Gerät basiert auf einem Atmega1284p Mikrokontroller, einem Crosspoint-Switch IC sowie einigen diskreten 74xx ICs. Unterstützt werden als Crosspoint-Switch sowohl der CD74HC22106 als auch der MT8808, wahlweise in DIP- oder PLCC-Bauweise. Ein USB-Anschluss ermöglicht die einfache Konfiguration und das Update der Firmware mit Hilfe des auf dem Mikrokontroller vorinstallierten USB-Bootloaders. Weitere Details zu Schaltung und Aufbau der Platine finden sich in der Quelldistribution sowie in den folgenden Abschnitten.

Kompatibilität

Theoretisch ist das Gerät für den Einsatz in jedem Heimcomputer geeignet, der eine passive 8x8 Tasturmatrix verwendet. Allerdings folgen das Layout der Anschlüsse und die Bennenung der Tasten denen des C64. Ebenso verwendet der Befehl type die für den C64 notwendigen Tastatureingaben, um den übergebenen ASCII-Text auszugeben. Falls ihr softwareseitige Unterstützung für andere Computer benötigt, zögert nicht, einen Feature-Request auf dem Github-Issue-Tracker zu stellen, vorzugsweise unter Angabe der dazu benötigten Informationen.

Dokumentation

Downloads

Quellen

Die Quelldistribution umfasst den Quelltext für die Firmware und das Konfigurations-Tool sowie den Schaltplan und das Platinenlayout im KiCad-Format.

Die letzte stabile Version ist keyman64-1.6.tar.gz.

Alle veröffentlichten Versionen finden sich unter /download/keyman64

Neuste Entwicklungen können auf github verfolgt werden:

git clone https://github.com/hbekel/keyman64

Der Changelog führt alle Änderungen im Detail auf.

Binärdateien

Schaltplan

Errata

Revision 3

Die Schaltung für die USB-Pegelanpassung ist in allen Revisionen bis einschließlich Revision 3 fehlerhaft. Dies kann zu fehlender USB-Funktionalität führen. Diese ist abhängig von dem spezifischen Typ der verwendeten 3.6V Zenerdioden. Während die Dioden, die ich mit den Revisionen 1 und 2 ausgeliefert haben, zufälligerweise funktioniert haben, waren die mit den Bausätzen für Revision 3 verschickten Dioden nicht geeignet. Daher habe ich diesen Fehler leider erst nach Auslieferung der ersten Bausätze von Revision 3 entdeckt.

Beim Aufbau bzw. bei der Reparatur eines Geräts der Revision 3 müssen die Dioden daher wie im folgenden Bild gezeigt verbaut bzw. umgebaut werden:

Wie man sieht müssen die Kathoden der Dioden (d.h. die Seite mit dem Strich) vor den Widerständen an die USB-Datenleitungen D- und D+ angeschlossen werden. Diese können direkt an die Beinchen der 68Ω-Widgerstände gelötet werden, vorausgesetzt, dass die Widerstände so eingelötet wurden, wie es der Bestückungsdruck vorschlägt.

Dieser Fehler wurde in Revision 4 behoben.

Revision 2

Der Generator für negative Spannungen, ICL7660 wird nicht benötigt, obwohl es auch nicht schadet, wenn er eingebaut bleibt. Er wurde in Revision 3 zugunsten einen alternativen PLCC-Sockels für den Crosspoint-Switch entfernt.

Außerdem messen die Bohrlöcher in Revision 2 nur 3mm im Durchmesser und somit nicht geeignet für gebräuchliche selbstklebende Platinenhalter, die zumeist Löcher mit 4mm benötigen. Die Löcher wurden in Revision 3 auf 4mm Durchmesser erweitert.

Bestellung von Bausätzen

Ich biete Bausätze zum Preis von 30€ pro Stück an. Der Bausatz enthält eine Keyman64 Platine, eine vorprogrammierten Atmega, einen MT8808 in DIP-Bauweise und alle weiteren benötigten Bauteile und IC-Sockel (ausgenommen Verbindungskabel). Weltweiter Versand per Post ist kostenlos.

Bestellungen könnt Ihr per Mail an henning.liebenau@protonmail.com tätigen.

Bitte verwendet das Wort “keyman64” im Betreff. Gebt in der Mail euren vollen Namen, Eure Lieferadresse und die Anzahl der gewünschten Bausätze an. Bitte beachtet, dass die Anzahl der Bausätze pro Person auf zwei Stück beschränkt ist. Ihr bekommt dann von mir per Mail weitere Informationen zur Bezahlung per Überweisung. Bitte beachtet, dass im voraus gezahlt werden muss, um die Bestellung verbindlich zu bestätigen.

Hinweise zur Verfügbarkeit

Ich versuche stets eine ausreichende Menge an Bausätzen auf Lager zu halten. Bitte beachtet jedoch, dass dies mit geringem Budget und bei minimaler Gewinnmarge in meiner Freizeit passiert. Mein Ziel ist es primär, der Community meine Hardware zugänglich zu machen, und nicht etwa ein profitables Geschäft zu betreiben.

Sollte ich also momentan keine Bausätze auf Lager haben kann es durchaus einige Wochen dauern, bis ich eine neue Serie von Bausätzen produzieren und somit eurer Bestellung nachkommen kann. Unter Umständen muss ich auch warten, bis eine ausreichende Anzahl an Vorbestellungen eingeht, bevor ich selbst die nötigen Bauteile zu einem ausreichend günstigen Preis bestellen kann. In diesen Fällen werde ich Euch natürlich regelmäßig über den Status Eurer Bestellung informieren. Es bedarf also unter Umständen ein wenig Geduld und auch Vertrauen von Eurer Seite.

Aufbau

Der Aufbau sollte relativ problemlos von statten gehen können. Orientiert euch einfach and der Liste der Bauteile und am Bestückungsplan weiter unten.

Spannungsversorgung

Eine Versorgung mit +5V Gleichstrom muss an den mittleren Pin des Jumpers J1 geführt werden. Dazu können entweder +5V vom Computer direkt an diesen Pin geführt werden, oder es kann eine Brücke verwendet werden, um die Spannung von Pin 4 an des Tastaturanschlusses des Computers zu beziehen, oder die Spannung kann direkt von der USB-Buchse bezogen werden. Um Spannung aus dem Tastaturanschluss zu beziehen (die empfohlenen Methode für den C64), müssen der linke und mittlere Pin von J1 gebrückt werden. Um die Spannung über USB zu beziehen, müssen der mittlere und rechte Pin von J1 gebrückt werden.

Die Versorgung über den USB-Port ist nur dann zu empfehlen, wenn das Gerät ohne Anschluss an andere Geräte betrieben wird, das heißt wenn P1 nicht an die Ein/Ausgabeleitungen eines Computers angeschlossen ist und keines der anderen mit dem Gerät verbundenen Geräte von einer anderen Spannungsquelle versorgt wird. Generell müssen alle beteiligten Geräte (der Computer, der Keyman64 selbst und die von ihm kontrollierten Geräte) von derselben Spannungsquelle versorgt werden. Wäre der Keyman beispielsweise für die Versorgung über USB konfiguriert und an Leitungen des Computers angeschlossen und würde der Computer dann angeschaltet werden, ohne das gleichzeitig Spannung über den USB-Port bereitgestellt wird, würde der Keyman64 dennoch über die ESD-Schutzdioden der I/O-Ports des Atmels Strom zu ziehen versuchen, was erheblichen Schaden an den I/O-Ports aller beteiligten Geräte zur Folge haben kann.

Verbindungen

Die Pinbelegung von P1 und P2 folgen der Pinbelegung des C64-Tastaturanschlusses. Die Restore-Leitung wird lediglich durchgeschleift.

Liste der Bauteile

Referenz Typ Wert Bauweise/Rastermaß
C1 Keramikkondensator 18pF 2.5mm
C2 Keramikkondensator 18pF 2.5mm
C6 Keramik- oder Filmkondensator 100nF 2.5mm
C7 Keramik- oder Filmkondensator 100nF 2.5mm
C8 Keramik- oder Filmkondensator 100nF 2.5mm
C9 Keramik- oder Filmkondensator 100nF 2.5mm
C10 Keramik- oder Filmkondensator 100nF 2.5mm
C11 Keramik- oder Filmkondensator 100nF 2.5mm
D1 Zenerdiode 3.6V DO-204
D2 Zenerdiode 3.6V DO-204
R1 Präzisionswiderstand 1.5kΩ 6.5mm, ∅ 2.5mm
R2 Präzisionswiderstand 68Ω 6.5mm, ∅ 2.5mm
R3 Präzisionswiderstand 68Ω 6.5mm, ∅ 2.5mm
P3 USB Mini-B-Buchse - Through-Hole
SW1 Taster - 6x6mm print
SW2 Taster - 6x6mm print
X1 Quartz 16Mhz HC49/U-S
U1 74HC22106 oder MT8808 - DIP28
U2 Atmega1284P - DIP40
U3 74HC00 - DIP14
U4 74HC4051 - DIP16
U5 74HC4520 - DIP16
U6 74HC4051 - DIP16
U7 74HC22106 oder MT8808 - PLCC28

Als Crosspoint-Switch kann entweder ein MT8808 oder ein 74HC22106 verwendet werden, dabei kann entweder eine DIP28-Variante auf U1 oder eine PLCC28-Variante auf U7 verwendet werden.

Wird ein 74HC22106 verwendet, muss dies über den Konfigurationsbefehl using entsprechend mittgeteilt werden.

IC-Sockel sind nicht gelistet.

Bestückungsplan

Installation der Firmware

Falls ihr einen Bausatz von mir erworben habt, ist der mitgelieferte Atmega bereits mit der aktuellsten Firmware programmiert und einsatzbereit.

Wenn dies nicht der Fall ist und ihr keine Möglichkeit habt, den Atmega zu programmieren, schickt ihn mir zu und ich programmiere ihn für euch. Mailt dazu an henning.liebenau@protonmail.com.

Installation des kombinierten Firmware-Images

Die einfachste Möglichkeit besteht darin, das kombinierte Firmware-Image aufzuspielen. Es enthält bereits den Bootloader und die Firmware und kann mit einem externen Programmiergerät (z.B. dem TL866) aufgespielt werden.

Dabei muss darauf geachtet werden, die korrekten Werte für die Fuses des Atmega zu verwenden:

    Low:      0xd7
    High:     0xd0
    Extended: 0xfc

Diese Werte entsprechen den zu setzenden Fuses SUT1, CKSEL3, SPIEN, EESAVE, BOOTSZ0, BOOTSZ1, BOOTRST, BODLEVEL0 und BODLEVEL1. Alle anderen Fuses dürfen nicht gesetzt sein.

Manuelle Installation des Bootloaders

Der Atmega1284p benötigt den USBaspLoader, der vor Einbau auf der Platine über ISP programmiert werden muss.

In der Quelldistribution findet sich eine vorkonfigurierte Version des Bootloaders.

Im Verzeichnis bootloader müssen die PROGRAMMER-Optionen in der Datei Makefile.inc für das verwendete Programmiergerät angepasst werden. Dann kann aus diesem Verzeichnis heraus der Bootloader kompiliert und geflasht werden sowie die Fuses gesetzt werden:

 $ make flash fuse

Der Atmega kann nun in das Modul eingesetzt werden. Bei aktiviertem Bootloader identifiziert sich das Gerät gegenüber dem PC mit

16c0:05dc Van Ooijen Technische Informatica shared ID for use with libusb

Es kann mit avrdude wie folgt angesprochen werden:

avrdude -p m1284p -c usbasp <commands...>

Zuvor müssen jedoch die USB-Geräte auf dem PC konfiguriert werden.

Aktivieren des Bootloaders

Um den Bootloader manuell zu aktivieren, drückt man die BOOT-Taste herunter, betätigt die RESET-Taste und lässt schließlich die Boot-Taste wieder los.

Sobald die Keyman64-Anwendung auf dem Gerät installiert ist, kann auch eine Tastenkombination für das Aktivieren des Bootloader konfiguriert werden:

b: boot

Dadurch kann der Bootloader durch Drücken von Meta-B aktiviert werden.

Alternativ kann der boot-Befehl auch vom PC aus über USB ausgeführt werden:

$ keyman64 boot

Update des Bootloaders

Unter Umständen kann bei zukünftigen Firmware-Updates ein vorheriges Update des Bootloaders nötig werden.

Zu diesem Zweck wird eine Update-Anwendung bereitgestellt, aktuell keyman64-bootloader-updater-1.6.hex.

Um das Update des Bootloaders vorzunehmen, wird zunächst der bereits installierte Bootloader aktiviert. Dann wird das Update mit Hilfe von avrdude aufgespielt:

$ avrdude -p m1284p -c usbasp -U flash:w:keyman64-bootloader-updater-1.6.hex

Hierbei wird zunächst die vorhandene Keyman64-Anwendung mit der Update-Anwendung überschrieben. Diese wird dann unmittelbar ausgeführt und überschreibt den vorhandenen Bootloader mit der neuen Version.

Danach kann der neue Bootloader wieder aktiviert werden und die Anwendung wie im nächsten Abschnitt beschrieben neu installiert werden.

Installation und Update der Anwendung

Sobald der Bootloader installiert ist, kann der Anwendungsteil der Firmware mit dem folgenden Befehl installiert werden:

$ avrdude -p m1284p -c usbasp -U flash:w:keyman64-firmware-1.6.hex

Falls ihr die Firmware selbst kompiliert habt, kann alternativ auch ein make program aus dem Hauptverzeichnis der Quelldistribution heraus ausgeführt werden.

Ab Version 1.4 kann die Anwendung auch über den update-Befehl des Kommandozeilen-Tools aktualisiert werden:

$ keyman64 update keyman64-firmware-<version>.bin

Dabei wird der Bootloader automatisch aktiviert und das Update vorgenommen.

Ab Version 1.5 akzeptiert der update-Befehl auch Dateien im Intel-HEX-Format. Es wird dabei aus der Dateiendung .bin oder .hex auf das zu verwendende Format geschlossen.

Ab version 1.6 akzeptiert der update-Befehl auch eine Konfigurationsdatei als zweites, optionales Argument. Wird eine Konfigurationsdatei angegeben, so wird zunächst die im Gerät gespeicherte Konfiguration gelöscht. Danach wird die Firmware aktualisiert. Schließlich wird die Konfiguration aus der angegebenen Datei neu generiert und wieder auf das Gerät geschrieben. Diese Prozedur ist notwendig, wenn sich das binäre Format der Konfiguration mit dem Update der Firmware ändert. Falls dies der Fall ist, wird in den Release Notes und im Changelog explizit darauf hingewiesen.

Einrichten der USB-Geräte auf dem PC

Das Keyman64-Modul implementiert zwei verschiedene USB-Geräte, je nachdem, ob der Bootloader oder die Anwendung gerade aktiv ist.

Während des normalen Betriebs kann das Keyman64-Modul mit Hilfe des Konfigurationstools angesprochen werden. Dieses Gerät identifiziert sich gegenüber dem PC mit den folgenden Eigenschaften:

Vendor OpenMoko, Inc.
Manufacturer Henning Bekel
Device Keyman64
Vendor ID 1d50
Product ID 60e9

Im Bootloader-Modus wird das USBasp-Programmiergerät emuliert. Dieses Gerät identifiziert sich gegenüber dem PC mit den folgenden Eigenschaften:

Vendor Van Ooijen Technische Informatica shared ID for use with libusb
Manufacturer www.fischl.de
Device USBasp
Vendor ID 16c0
Product ID 05dc

Linux

Unter Linux werden die benötigten udev-Regeln zusammen mit dem Konfigurationstool installiert. Nach der Installation muss der folgende Befehl ausgeführt werden, um die Geräte sofort benutzen zu können:

# udevadm control --reload-rules

Im Bootloader-Modus erscheint das entsprechende Gerät als symlink unter /dev/usbasp. Im Normalbetrieb wird das entsprechende Gerät als symlink unter /dev/keyman64 angelegt. Diese symlinks werden mit den Dateiberechtigung 0666 angelegt und können so von jedem Benutzer verwendet werden. Um den Zugriff zu beschränken können die jeweiligen Regeln in /etc/udev/rules.d/10-keyman64.rules angepasst werden.

Windows

Wird unter Windows eines der USB-Geräte zum ersten mal angeschlossen, versucht Windows, einen Treiber für dieses Gerät herunterzuladen und zu installieren. Da es sich bei beiden Geräten jedoch um treiberlose Geräte handelt, ist dieser Versuch sinnlos, da es schlicht keine speziellen Treiber für diese Geräte gibt. Die Windows-Treiberinstallation muss abgebrochen werden, da Windows ansonsten den Zugriff auf diese Geräte dauerhaft verhindert, da es aus seiner Sicht keine brauchbaren Treiber finden konnte.

Stattdessen muss das frei erhältliche Tool Zadig verwendet werden. Dieses generiert minimale Treiber, die die Geräte lediglich mit den für den generischen Zugriff benötigten Bibliotheken verknüpfen.

Wird Zadig nun ausgeführt, sollte es das Gerät “Keyman64” erkennen. Es ist der “WinUSB” Treiber für dieses Gerät zu installieren. Die benötigte libusb-1.0.dll wird mit dem Konfigurationstool installiert.

Nun muss noch einmal in den Bootloader-Modus gewechselt werden, um auch für dieses Gerät (USBasp) einen Treiber zu installieren. Hier wird ebenfalls der “WinUSB”-Treiber verwendet.

Für den Fall, dass das USBasp-Gerät über avrdude und nicht über das keyman64-tool verwendet werden soll, muss unter Umständen der Zadig-Treiber “libusb-win32” installiert werden, da die für Windows erhältlichen Versionen von avrdude meist noch gegen die veraltete libusb-0.1 gelinkt sind, deren Verwendung nur mit Zadigs libusb-win32-Treiber möglich ist.

Installation des Konfigurationstools keyman64 auf dem PC

Binäres Installationspaket (Windows)

Die Windows-Version kann mit Hilfe des Win32-Installationspaketes installiert werden. Dieses installiert auch die benötigte libusb-1.0.dll und fügt das Installationsverzeichnis zur Umgebungsvariable PATH hinzu, so dass die keyman64.exe in der Eingabeaufforderung aus jedem beliebigen Verzeichnis heraus aufgerufen werden kann.

Kompilieren und Installieren aus den Quelltexten

Linux & MacOSX

libusb-1.0 und das entsprechende “devel”-Paket (falls bei eurer Distribution benötigt) müssen auf dem System vorhanden sein.

$ tar vxzf keyman64-1.6.tar.gz
$ cd keyman64-1.6
$ make
$ make install

Dies installiert nach erfolgreicher Kompilierung das Konfigurationstool keyman64 nach /usr/local/bin. Die PREFIX-Variable kann für die Installation mit einem anderen Präfix benutzt werden, z.B. installiert make PREFIX=/usr install nach /usr/bin. Die Variable DESTDIR kann für die Installation in ein lokales Verzeichnis mit dem gegebenen Präfix verwendet werden.

Unter Linux werden die benötigten udev-Regeln nach /etc/udev/rules.d/ installiert. Nach der Installation sollte als root-Benutzer zusätzlich der folgende Befehl ausgeführt werden:

# udevadm control --reload-rules

Windows

Falls Cygwin verwendet wird kann eine Windows-Version auf die gleiche Weise kompiliert und installiert werden wie unter Linux oder MacOSX. Die benötigten Cygwin-Pakete sind libusb-1.0 und libusb-1.0-devel. Die resultierende Anwendung benötigt jedoch weiterhin Cygwin-spezifische Bibliotheken (siehe ldd keyman64.exe).

Eine native Win32-Anwendung kann mit Hilfe der Cross-Compiler-Suite Mingw32 unter Linux oder Cygwin kompiliert werden. Falls nötig ist dazu das Makefile zu editieren und die MINGW32-Variable entsprechend des benötigten Präfixes für eure Mingw32-Installation anzupassen. Dann kann mit Hilfe von make win32 die keyman64.exe gebaut werden.

Konfiguration

Die Konfigurationsdatei ist eine einfache Textdatei, die die Befehle und Tastenkombinationen in lesbarem Format enthält. Mit Hilfe des Konfigurationstools wird diese Datei in ein binäres Format kovertiert und kann in den EEPROM-Speicher des Mikrokontrollers geschrieben werden. Siehe dazu den Abschnitt Übertragen der Konfiguration.

Syntax

Leerzeichen und Kommentare

Leere Zeilen und führende oder folgende Leerzeichen werden ignoriert. Leerzeichen sind nur relevant, wenn Schlüsselwörter oder Argumente voneinander getrennt werden

Kommentare beginnen mit einem Hash-Zeichen # und erstrecken sich bis zum Ende der aktuellen Zeile.

Schlüsselwörter

Alle Schlüsselwörter wie Befehle, Tastennamen sowie benutzerdefinierte Symbole werden ohne Rücksicht auf Groß- oder Kleinschreibung interpretiert. So ist z.B. die Schreibweise für den Befehl clear äquivalent zu CLEAR, Clear oder auch clEAr.

Befehle und Befehlstasten

Jede Zeile muss genau eine Befehlsangabe enthalten, auf die je nach Befehl weitere Argumente folgen können. Optional kann eine Tastenangabe vorangestellt werden.

[<Taste>:][<Regel>] <Befehl> [<Argumente>]

Wird keine Tastenangabe vorangestellt, wird der Befehl direkt beim Starten bzw. nach einem Reset ausgeführt, und kann so dazu verwendet werden, den Anfangszustand des Gerätes zu definieren.

Wird eine Tastenangabe vorangestellt, wird der Befehl an die angegebene Taste gebunden. Der Befehl kann dann durch Drücken der Meta-Taste und der angegebenen Taste ausgeführt werden.

Werden mehrere Befehle auf mehreren Zeilen an die gleiche Taste gebunden, so werden bei Betätigen der Tastenkombination alle Befehle nacheinander ausgeführt, und zwar in der Reihenfolge, in der sie in der Datei definiert wurden.

Befehle oder Befehlssequenzen können auch an “Slots” gebunden werden, indem numerische Werte zwischen $40 und $F9 verwendet werden. Diese Sequenzen können nicht direkt über Tastenkombinationen aufgerufen werden, sondern nur indirekt mit Hilfe des Befehls exec.

Tastenangaben können optional mit einem weiteren Argument versehen werden, indem direkt nach dem Doppelpunkt 0 oder 1 angehängt wird. Diese Werte bedeuten hier “gerade” oder “ungerade”. Wird “gerade” angegeben, wird der Befehl nur beim zweiten, vierten, sechsten usw. Betätigen der Taste ausgeführt, bei “ungrade” entsprechend nur beim ersten, dritten, fünften mal usw.

Tastennamen

Tasten können mit Hilfe von Tastennamen wie DEL, A, RUNSTOP oder ONE angegeben werden. Eine Liste von gültigen Tastennamen gibt das Konfigurationstool bei Angabe der Option --keys aus.

Alternativ können Tasten auch numerisch über ihre Postion innerhalb der C64-Tastatur-Matrix angegeben werden. Die Tasten werden dabei von links nach rechts zeilenweise durchnummeriert, beginnend bei Reihe 0, Spalte 0 und endend bei Reihe 7, Spalte 7.

So entspricht $00 der Taste DEL und $3f entspricht der Taste RUNSTOP.

Numerische Tastenangaben können dezimal oder hexadecimal angegeben werden. Hexadezimalen Werten muss entweder ein $ oder 0x vorangestellt werden.

Ports

Die sechzehn Steuerleitungen sind in zwei acht Bit breiten Ports organisiert. Für Befehle, die den Zustand der Steuerleitungen ändern, kann der gewünschte Port mit Hilfe des Schlüsselwortes port, gefolgt von a oder b angegeben werden:

port [a|b]

Bits

Befehle, die die Steuerleitungen beinflussen, können auf einzelne Kontrolleitungen oder auch nebeneinanderliegende Leitungen eines Ports eingeschränkt werden. Die einzelnen Leitungen (Bits) werden durch einen Dezimalwert im Bereich 0-7 angegeben. Dazu wird entweder das Schlüsselwort bit für einzelne Leitungen oder das Schlüsselwort bits für mehrere nebeneinanderliegende Leitungen verwendet:

bit <n>

bits <s>-<e>

Wobei n eine einzelne Leitung angibt und s und e Anfang und Ende eines Bereichs (inklusiv) angeben.

Kurznotation für Ports und Leitungen

Ab Version 1.6 können Port und Leitungen auch in Kurznotation angegeben werden:

<port>[[<s>][-<e>]]

So sind Ausdrücke wie port a bit 3 oder port b bits 0-2 gleichbedeutend mit a3 bzw. b0-2.

Zeitdauer

Eine Zeitdauer kann durch einen Dezimalwert, optional gefolgt von einer Zeiteinheit angegeben werden:

[<n><einheit>...][<n>]

Gültige Einheiten sind d, h, m, s und ms für Tage, Stunden, Minuten, Sekunden und Millisekunden. Wird keine Einheit angegeben, wird die Dauer als Angabe in Millisekunden interpretiert.

Die maximal verwendbare Zeitdauer beträgt 232 Millisekunden, dies entspricht ungefähr 49 Tagen. Angaben, die diese Dauer überschreiten, werden auf die Maximaldauer gekürzt.

Beispiele:

1m30s = Eine Minute und dreißig Sekunden

1s500 = Eine Sekunde und fünfhundert Millisekunden

10 = Zehn Millisekunden

Numerische Werte

Numerische Werte können in dezimaler, hexadezimaler oder binärer Schreibweise angegeben werden. Hexadezimalen Werten wird ein $ vorangestellt, binäre Werte müssen mit % eingeleitet werden.

Symbole

Benutzerdefinierte Symbole können verwendet werden, um die Lesbarkeit der Konfigurationsdatei zu verbessern. Symbole werden als einfache Schlüssel/Wert-Paare durch folgende Syntax definiert:

<name> = <value>

Symbolnamen dürfen nur aus alphanumerischen Zeichen oder Unterstrichen bestehen. Es wird eine Warnung ausgegeben, wenn ein Konflikt mit bereits definierten Schlüsselwörtern oder Symbolen entsteht.

Sobald ein Symbol definiert wurde, werden alle folgenden Verwendungen durch den angegebenen literalen Wert ersetzt. Wird ein Symbol verwendet, bevor es definiert wurde, wird eine entsprechende Fehlermeldung ausgegeben.

Zum Beispiel kann die folgende Definition einer Befehlssequenz

    r: clear port a bit 0
    r: sleep 10
    r: tristate port a bit 0

durch die Verwendung von Symbolen sehr viel lesbarer gestaltet werden:

    RESETLINE = port a bit 0
    RESET = r

    RESET: clear RESETLINE
    RESET: sleep 10
    RESET: tristate RESETLINE

Konfigurations- und Wartungsbefehle

using

using <8808|22106>

Gibt an, welche Crosspoint-Switch-Variante verwendet wird. Es kann entweder ein CD74HC22106 oder ein MT8808 verwendet werden. Der Standardwert ist 8808.

speed

speed <fast|slow>

Gibt an, in welcher Geschwindigkeit die Matrix der physischen Tastatur gescannt wird. Schnell (fast) ist die Standardeinstellung und sollte in den meisten Fällen problemlos funktionieren. Der langsame Modus (slow) wird nur benötigt, wenn die Länge der Kabel zur Tastatur deutlich länger ist, als es bei einer üblichen C64-Tastatur der Fall ist, zum Beispiel wenn das Gerät in einem Commodore SX64 installiert wird.

Der langsame Modus beeinträchtigt dabei in keinster Weise die Geschwindigkeit der Tastaturabfrage. Beide Modi scannen die Tastatur schnell genug, um eine unmittelbare Reaktion auf Tastatureingaben zu gewährleisten.

expand

expand ports=<n> clock=<line> data=<line> latch=<line> enable=<line>

Konfiguriert eine Porterweiterung durch <n> hintereinandergeschaltete 74595 serielle Schieberegister, wobei die Leitungen für CLOCK, DATA, LATCH und ENABLE des ersten Schieberegisters mit den angegebenen Steuerleitungen verbunden werden.

Hierbei müssen die Steuerleitungen in Kurznotation angegeben werden.

Siehe Porterweiterung für weitere Details.

meta

meta <Taste>

Der Befehl meta definiert die zu verwendende Meta-Taste. Standardeinstellung ist die Linkspfeil-Taste (ARROWLEFT).

boot

boot

Aktiviert den Bootloader. Der Bootloader erwartet Konfigurations- oder Firmware-Updates über USB. Das Gerät verbleibt im Bootloader-Modus bis eine neue Konfiguration oder Firmware übertragen wurde oder der RESET-Button am Gerät betätigt wird.

Wird dieser Befehl über die USB-Fernsteuerung durch ausführen des Befehls keyman64 boot auf dem PC ausgeführt, springt der Mikrokontroller direkt in den Bootloader, ohne die USB-Kommunikation ordnungsgemäß zu beenden. Dies führt zur Ausgabe der folgenden unbedenklichen Fehlermeldung:

error: could send usb control message: Pipe error

Diese Fehlermeldung kann ignoriert werden sofern der Bootloader erfolgreich aktiviert wurde.

save

save

Speichert den aktuellen Zustand der Steuerleitungen dauerhaft im EEPROM-Speicher. Dieser Zustand kann später mit Hilfe des Befehls restore wieder hergestellt werden.

restore

restore

Stellt den zuvor durch den Befehl save im EEPROM-Speicher gespeicherten Zustand der Steuerleitungen wieder her. Wurde zuvor kein Zustand gespeichert, werden alle Steuerleitungen in den Tristate-Zustand versetzt.

memorize

memorize

Speichert den aktuellen Zustand der Steuerleitungen temporär im RAM. RAM. Dieser Zustand kann später über den Befehl recall wieder hergestellt werden.

recall

recall

Stellt den zuvor über den Befehl recall im RAM abgelegten Zustand der Steuerleitungen wieder her. Wurde zuvor kein Zustand im RAM abgelegt, werden alle Steuerleitungen in den Tristate-Zustand versetzt.

Befehle zur Kontrolle der Steuerleitungen

set

set <Port> [<Bits>] [to <Wert>]

Setzt die angegebenen Bits des angegebenen Ports auf den angegebenen Wert. Wird kein Wert angegeben, werden alle betroffenen Bits auf 1 (high) gesetzt. Werden keine explizit Bits angegeben, wird der gesamte Port auf den angegebenen Wert gesetzt.

Beispiele:

set port a bit 3 to 1 – Setzt Bit 3 des Ports A auf high

set port b bits 3-4 to 2 – Setzt für Port B Bit 3 auf low und Bit vier auf high (2 dezimal = 10 binär)

set port a – Setzt die Bits 0-7 von Port A auf high

clear

clear <Port> [<Bits>]

Löscht die angegebenen Bits des angegebenen Ports, also setzt sie auf 0 (low). Werden keine Bits angegeben, werden alle Bits des angegebenen Ports gelöscht.

tristate

tristate <Port> [<Bits>]

Versetzt die angegebenen Bits des angegebenen Ports in den Tristate-Zustand. Werden keine Bits angegeben, werden alle Bits des angegebenen Ports in den Tristate-Zustand versetzt.

Eine Leitung in den Tristate-Zustand zu versetzen bedeutet, die Leitung in einen hochohmigen Zustand zu bringen, der von angeschlossenen digitalen Bausteinen weder als “High” noch als “Low” interpretiert wird. In digitalen Schaltungen ist entspricht dieser Zustand einer nicht verbundenen Leitung.

Dies ist vor allem für die Simulation von Tastern notwendig. Ein zweipoliger Taster stellt keinen Kontakt her, solange er nicht gedrückt wird. Die angeschlossene Steuerleitung ist somit meist im Tristate-Zustand. Wird der Schalter geschlossen, wird die angeschlossene Steuerleitung in der Regel entweder mit VCC (high) oder GND (high) verbunden.

So verbindet zum Beispiel ein im C64 verbauter Reset-Taster die RESET-Leitung des C64 kurzzeitig mit Masse, das RESET-Signal geht auf low und der C64 wird zurückgesetzt.

Um dies im Keyman zu realisieren, verbindet man die Reset-Leitung mit einer der Steuerleitungen des Keymans, zum Beispiel mit der Leitung 0 auf Port A. Nun kann ein Reset über eine Tastenkombination wie folgt konfiguriert werden:

tristate a0    # Beim Einschalten ist der Taster erstmal offen,
               # die RESET-Leitung wird also vom Keyman nicht beeinflusst

r: clear a0    # Wird Meta-r gedrückt, wird der Taster "geschlossen",
               # also die RESET-Leitung wird auf Low gezogen

r: sleep 20    # Wir halten die RESET-Leitung für 20 Millisekunden auf low...

r: tristate a0 # Und "lassen den Taster dann wieder los",
               # so dass die RESET-Leitung nicht länger vom Keyman beeinflusst wird

invert

invert <Port> [<Bits>]

Invertiert den Zustand der angegebenen Bits auf dem angegebenen Port. Werden keine Bits angegeben, werden alle Bits des angegebenen Ports invertiert. Ist eine Leitung zuvor im Tristate-Zustand, wird sie auf High gesetzt.

increment

increment <Port> [<Bits>]

Erhöht die angegebenen Bits auf dem angegebenen Port um eins. Dabei werden die Zustände der angegebenen Bits als binärer Wert interpretiert. Werden keine Bits angegeben, wird der Wert aller Bits des angegebenen Ports erhöht.

Dies kann zur Realisierung eines Binärzählers auf einem Port oder einem bestimmten Bereich eines Ports verwendet werden. Sind alle Bits des angegebenen Bereichs bereits auf 1 gesetzt (also hat der Zähler sein Maximum ereicht), werden alle Bits wieder gelöscht.

Beispiel für einen vier Bit breiten Binärzähler im unteren Teil von Port A:

increment port a bits 0-3

decrement

decrement <port> [<bits>]

Erniedrigt die angegebenen Bits um eins. Gegenstück zum Befehl decrement.

Befehle zur Steuerung der Tastaturmatrix

Die folgenden Befehle Steuern den Zustand der vom Computer gescannten, virtuellen Tastaturmatrix.

down

down <Taste>

Hält die angegebene Taste herunter. Die Taste bleibt solange gedrückt, bis sie durch den Befehl up wieder losgelassen wird oder die Meta-Taste losgelassen wird.

up

up <Taste>

Lässt die angegebene Taste wieder los, sofern sie zuvor durch den Befehl down gedrückt gehalten wurde.

press

press <key>

Betätigt die angegebene Taste einmalig. Die Taste wird für 20 Millisekunden heruntergedrückt und dann wieder losgelassen.

Dies ist also die Kurzform für:

down <Taste>
sleep 20
up <Taste>

type

type <Zeichenkette>

Gibt die angegebene Zeichenkette auf der virtuellen Tastatur ein. Um das Betätigen der Return-Taste hinzuzufügen kann die Escape-Sequenz \r angehängt werden.

ASCII-Kleinbuchstaben bewirken das Drücken der entsprechenden Taste ohne weitere Modifier wie SHIFT, CONTROL oder CBM. ASCII-Großbuchstaben bewirken das Drücken der entsprechenden Taste in Verbindung mit dem dazu nötigen Modifier.

Um PETSCII-Buchstaben einzugeben, die nicht im ASCII-Zeichensatz vorhanden sind, kann einfach das ASCII-Zeichen an der entsprechenden Postion verwendet werden. Zum Beispiel befindet sich im PETSCII-Zeichensatz das Pfund-Symbol an Position 92, im ASCII-Zeichensatz findet sich dort der Backslash \. Verwendet man in der angegebenen Zeichenkette also einen Backslash, führt dies zur Ausgabe eines Pfund-Symbols am C64.

Alternativ kann jedes PETSCII-Zeichen durch eine numerische Escape-Sequenz angegeben werden, entweder in dezimaler oder hexadezimaler Schreibweise:

\xnn   -- hexadezimale Schreibweise, z.B. \x0a
\{ddd} -- dezimale Schreibweise, z.B. \{147}

Zusätzlich werden die folgenden Escape-Squenzen interpretiert:

\\ -- literaler Backslash, (0x5c) (Pfund-Symbol auf dem C64)
\r -- return (0x0d), entspricht dem Drücken der Taste RETURN
\n -- newline (0xa), entspricht dem Drücken der Tasten SHIFT und RETURN
\f -- form feed (0x0c), entspricht dem Drücken der Tasten SHIFT und CLRHOME

Der Keyman kann allerdings nur solche Zeichen eingeben, die tatsächlich auch auf einer physikalischen Tastatur erzeugt werden können. Dies schließt die PETSCII-Steuerzeichen für das Umschalten des Zeichensatzes (Codes 14 und 142) sowie die Steuerzeichen für das Sperren und Freigeben des Zeichensatzwechsels (Codes 8 und 9) aus. Diese können auch am C64 nur programmatisch (z.B. durch print chr$(9) erzeugt werden.

Beispiel (für den C64):

type load"*",8,1\r – gibt LOAD"*",8,1 ein und betätigt RETURN

swap

swap <Taste> <Taste>

Tauscht die angegebenen Tasten gegeneinander aus, bevor sie an den Computer weitergeleitet werden. So kann die Tastaturbelegung des Computers verändert werden, z.B. um ein QUERTZ-Layout zu erhalten:

swap Z Y

Dies wirkt sich allerdings nur auf die Tasten aus, die zum Computer weitergeleitet werden. Eine an Meta-Z gebundene Befehlssequenz wird hier also nach wie vor durch Betätigen der physischen Z-Taste ausgelöst.

map

map <Port> <Bit> to <Taste>

Verknüpft die angegebene, einzelne Steuerleitung mit der angegebenen Taste. Die Leitung wird zu einer low-aktiven Eingangsleitung. Solange die Leitung auf Low gezogen wird, wird die angegebene Taste gedrückt.

Sobald ein Pin auf diese Weise mit einer Taste verknüpft wurde, darf sein Zustand nicht länger durch andere Befehle verändert werden.

password

password

Ermöglicht es dem Benutzer, ein Passwort einzugeben, mit dem die Tastatur wieder entsperrt werden kann, nachdem sie über den Befehl lock gesperrt wurde. Dazu muss der C64 im Direktmodus sein, damit die Tastaturausgaben des Keymans auf dem Bildschirm sichtbar werden.

Das Password muss zweimal eingegeben werden. Stimmen beide Eingaben überein, wird das Passwort dauerhaft im EEPROM-Speicher hinterlegt.

Um das Password zurückzusetzen genügt es, zweimal ein leeres Passwort einzugeben.

lock

lock

Sofern ein Passwort über den Befehl password gesetzt wurde, wird die Tastatur gesperrt. Es werden keine Eingaben mehr an den Computer weitergeleitet, bis der Benutzer das Passwort auf der Tastatur eingibt und mit RETURN bestätigt.

Bevor die Tastatur gesperrt wird, werden alle Befehle ausgeführt, die an die virtuelle Taste LOCKED gebunden sind. Wird die Tastatur wieder freigegeben, werden alle Befehle ausgeführt, die an die virtuelle Taste UNLOCKED gebunden sind.

Dies kann dazu verwendet werden, beim Sperren oder Entsperren der Tastatur zusätzliche Befehle auszuführen. So kann zum Beispiel beim Sperren der Tastatur auf einen unleserlichen Zeichensatz geschaltet werden, um damit auch den Bildschirm (genauer gesagt den Text darauf) zu “sperren”. Bei UNLOCKED kann dann wieder auf einen lesbaren Zeichensatz geschaltet werden.

Kontrollfluss-Befehle

exec

exec <Taste>|<Slot>

Führt die an die angegebene Taste oder den angegebenen Slot gebundene Befehlssequenz aus. Die Ausführung der aktuellen Befehlssequenz wird fortgesetzt, nach dem die angegebene Sequenz ausgeführt wurde.

sleep

sleep <duration>

Pausiert die Ausführung von Befehlen für die angegebene Zeitdauer. Während dieser Zeit werden keine Tastatureingaben weitergeleitet oder als gebundene Tastenkombinationen interpretiert.

requires

<Taste>: requires <n>

Diese Anweisung bewirkt, dass die an die angegebene Taste gebundene Befehlssequenz nur ausgeführt wird, nachdem die Taste n-mal betätigt wurde, während die Meta-Taste durchgehend gehalten wurde.

Dies ist nützlich, wenn eine potentiell destruktive Aktion wie ein Reset vor versehentlicher Ausführung geschützt werden soll. So benötigt die folgende Reset-Sequenz eine dreimalige Betätigung der Taste R bei durchgängig gedrückter Meta-Taste:

r: requires 3
r: clear port a bit 0
r: sleep 20
r: tristate port a bit 0

Dies betrifft allerdings nur die interaktive Ausführung über die Tastatur. Der Befehl exec r würde die Sequenz auch in diesem Fall unmittelbar ausführen.

Befehle zur Anzeige von Informationen

Damit die von diesen Befehlen ausgegebene Information auf dem Bildschirm erscheint, muss der Computer im Eingabemodus sein.

version

version

Gibt die aktuelle Version der Firmware aus.

status

status

Gibt den aktuellen Status der Steuerleitungen aus in der folgenden Form aus:

A XXXX0010
B 11111001

Dabei ist 0 = low, 1 = high und X = tristate

Konfigurationstool

$ keyman64 --help

Keyman64 v1.6
Copyright (C) 2016 Henning Bekel.
License GPLv3: GNU GPL version 3 <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Usage:
      keyman64 [<options>] convert [<infile>|-] [<outfile>|-]
      keyman64 [<options>] configure [<infile>]
      keyman64 [<options>] update <firmware> [<config>]
      keyman64 [<options>] reset
      keyman64 [<options>] <command>
      keyman64 [<options>] <script>|-

  Options:
           -v, --version  : print version information
           -h, --help     : print this help text
           -d, --device   : specify usb device (default: /dev/keyman64)
           -D, --delay    : delay in ms between commands
           -k, --keys     : list key names and synonyms
           -p, --preserve : deprecated as of version 1.5
           -i, --identify : request firmware identification via USB

  Files:
           <infile>   : input file, format is autodetected
           <outfile>  : output file, format determined by extension
           <script>   : script file containing keyman64 commands
           <firmware> : binary or ihex firmware image (.bin or .hex)

           *.conf : plain text config file format
           *.bin  : binary file format (default)

           Optional arguments default to stdin or stdout

  Command:
            (any valid keyman64 command)

Übertragen der Konfiguration

Version 1.4 und folgende Versionen

Ab der Version 1.4 kann die Konfiguration über den Befehl configure in einem Schritt konvertiert und über USB zum Gerät übertragen werden:

$ keyman64 configure keyman64.conf

Hier wird die Konfigurationsdatei keyman64.conf eingelesen und in das binäre Format konvertiert. Danach wird das Gerät über USB in den Bootloader-Modus versetzt und die Konfiguration in den EEPROM-Speicher des Atmega übertragen. Schließlich wird das Gerät zurückgesetzt und die Anwendung startet mit der neuen Konfiguration.

Die im nächsten Abschnitt beschriebene Methode kann weiterhin verwendet werden.

Version 1.3 und frühere Versionen

Über den convert-Befehl wird die Konfigurationsdatei in das Binärformat konvertiert:

$ keyman64 convert keyman64.conf keyman64.bin

Falls die Konfigurationsdatei keine Fehler enthält wird die Datei keyman64.bin erzeugt.

Nun muss der Bootloader aktiviert werden.

Die binäre Konfiguration wird nun mittels avrdude übertragen:

$ avrdude -p m1284p -c usbasp -U eeprom:w:keyman64.bin:r

Nach der Übertragung wird das Gerät automatisch zurückgesetzt und startet mit der neuen Konfiguration.

Der Bootloader setzt den Mikrokontroller unmittelbar nach dem Update zurück. Dies geschieht noch bevor die aktuelle USB-Kommunikation zwischen dem Bootloader und avrdude ordnungsgemäß beendet wird. Daher erscheint die folgende unbedenkliche Fehlermeldung:

error: usbasp_transmit: usb_control_msg: sending control message failed

Diese Fehlermeldung kann ignoriert werden sofern avrdude zuvor die erfolgreiche Übetragung der Daten gemeldet hat.

Erhalten des gespeicherten Zustands der Steuerleitungen

Die in diesem Abschnitt beschriebene Option –preserve ist ab Version 1.5 nicht mehr notwendig. Ab Version 1.6 wird der gespeicherte Zustand nicht mehr beim Übertragen der Konfiguration überschrieben.

Um den gespeicherten Zustand zu erhalten kann die Option --preserve zusammen mit dem Befehl convert verwendet werden. In diesem Fall wird zunächst der aktuell gespeicherte Zustand per USB vom Gerät gelesen und später wieder zu der neu erzeugten Binärdatei hinzugefügt. Dazu muss das Gerät allerdings über USB angeschlossen sein.

Bei Verwendung des oben beschriebenen configure-Befehls wird der Zustand automatisch erhalten.

Fernsteuerung über USB

Mit Hilfe des Konfigurationstools können auch beliebige Befehle vom PC über USB zum Gerät übermittelt und dort direkt ausgeführt werden.

Ein einzelner Befehl kann direkt über die Kommandozeile abgesetzt werden, zum Beispiel

$ keyman64 press F5

Werden keine Argumente auf der Kommandozeile angegeben, so liest das Konfigurationstool Befehle von der Standardeingabe ein. Dabei muss jede Zeile nur einen Befehl enthalten. Allerdings werden die Befehle erst gelesen und ausgeführt, nachdem die Standardeingabe geschlossen wurde, also alle Befehle eingegeben oder aus einer Pipe gelesen wurden:

$ keyman64
reading commands from stdin...
> type load"$",8\r
> sleep 5s
> type list\r
> ^D
$

Handelt es sich beim ersten Argument um eine Datei, werden Befehler aus dieser Datei gelesen und an das Gerät übermittelt.

So kann man ein Skript wie das folgende in einer Datei speichern:

exec rightshift
press f5
press cursordown
press cursordown
press cursordown
press return

und mit folgendem Befehl ausführen:

$ keyman64 --delay 250 script.txt

Die Option --delay fügt hier eine Verzögerung von 250ms nach jedem Befehl hinzu. Dies verhindert, nach jedem Befehl einen expliziten sleep-Befehl hinzufügen zu müssen.

Unter Linux und MacOSX kann der #!-Mechanismus verwendet werden um solche Skripte direkt ausführbar zu machen. Dazu macht man das Skript ausführbar und fügt eine entsprechende #!-Zeile am Anfang der Datei hinzu, zum Beispiel:

#!/usr/bin/keyman64 --delay 250
press f5
press cursordown
press return

Dann kann das Skript wie jeder andere Befehl ausgeführt werden.

Porterweiterung

Ab Version 1.6 kann die Anzahl der verfügbaren Steuerleitungen auf einfache Weise erweitert werden. Es können ein oder mehrere serielle Schieberegister des Typs 74595 in Serie angeschlossen werden. Lediglich vier der auf dem Gerät ausgeführten Steuerleitungen müssen dazu mit dem ersten Schieberegister verbunden werden. Das erste Schieberegister kann somit effektiv vier weitere Leitungen bereitstellen. Jedes weitere angeschlossene Schieberegister erweitert das Gerät dann um einen weiteren 8-Bit breiten Port.

Schieberegister des Typs 74595 sind auch auf kleinen Breakout-Boards erhältlich. Diese können auf einfache Weise hintereinander gehängt werden. Zum Beispiel bietet Artekit ein günstiges Breakout-Board an, das für diesen Zweck gut geeignet ist.

Der Befehl expand wird dabei verwendet, um dem Gerät mitzuteilen, wie viele zusätzliche Ports angeschlossen sind und welche der nativen Steuerleitungen mit den vier Eingängen des ersten Schieberegisters verbunden sind. Die zusätzlichen Ports werden dann beginnend mit dem Buchstaben “c” in alphabetischer Reihenfolge benannt. So können die zusätzlichen Ports genau wie die nativen Ports a und b in anderen Direktiven und Befehlen angegeben werden.

Der Befehl expand erwartet die Angabe der für das Schieberegister nötigen Steuerleitungen unter den Bezeichnungen CLOCK, DATA, LATCH und ENABLE. Abhängig vom Datenblatt des ICs oder des verwendeten Breakout-Boards können diese Leitungen unterschiedlich benannt sein:

Keyman64 74595 Pinnummer Beschreibung Andere geräuchliche Bezeichnungen
CLOCK 11 shift register clock input CLK, SCK, SHCP, SRCLK
DATA 14 serial data input DS, SER, SER-IN
LATCH 12 storage register clock input STCP, RCLK
ENABLE 13 output enable input (active low) OE, EN
RESET 10 serial clear input (active low) MR, CLR, SRCLR

Die ENABLE- und die RESET-Leitung des Schieberegisters sollten jeweils über einen 4.7k Widerstand auf High-Pegel gezogen werden. Beim oben verlinkten Artekit-Board ist dies bereits der Fall.

Beim Einschalten oder nach einem Reset werden alle erweiterten Leitungen zunächst in den Tristate-Zustand versetzt. Sobald eine dieser Leitungen durch einen Befehl gesetzt wird, werden alle Register aktiviert. Leitungen, deren Zustand noch nicht definiert ist, werden dann auf Low gezogen. Es empfielt sich daher, den Zustand der zusätzlichen immer explizt zu initialisieren.

Die erweiterten Leitungen können weder in den Tristate-Zustand versetzt werden noch als Eingangsleitungen verwendet werden. Daher ist sind die Befehle tristate und map für erweiterte Leitungen nicht zulässig. Das Konfigurationstool wird in diesem Fall eine entsprechende Fehlermeldung ausgeben.

Beispiel

Dieses Bild zeigt, wie ein oder mehrere 74595-Breakout-Boards angeschlossen werden können. Hier werden die unteren vier Steuerleitungen von Port B mit dem ersten Schieberegister verbunden.

Der entsprechende expand-Befehl lautet:

expand PORTS=2 DATA=b0 CLOCK=b1 LATCH=b2 ENABLE=b3

Alle auf diesen Befehl folgenden Befehle in der Konfigurationsdatei können die zusätzlichen Ports nun als Port C bzw. Port D ansprechen, zum Beispiel:

X: set port d bit 5
Y: inc port c bits 0-1

Serielle Schnittstelle

Der Anschluss P4 stellt eine einfache serielle Schnittstelle zur Verfügung, über die der Keyman64 von externer Hardware kontrolliert werden kann. Der linke Pin ist dabei der Eingang für ein low-aktives Clock-Signal (auf der Platine mit /CLK gekennzeichnet). Der rechte Pin stellt das Eingangssignal DATA bereit. Bei fallender Flanke des Clock-Signals wird der an DATA anliegende Wert vom Gerät übernommen.

Jeder Befehl besteht aus einem Befehlsbyte, gefolgt von einem oder mehreren Parameterbytes. Bytes werden jeweils in little-endian Reihenfolge übermittelt, das heißt das niederwertigste Bit wird zuerst übermittelt. Um zum Beispiel die Taste RUNSTOP zu betätigen, sieht der eigentliche Befehl wie folgt aus:

00000100 00111111 => 0x4 (Befehl) 0x3f (Parameter)

muss jedoch wie folgt übermittelt werden:

00100000 11111100 => Befehl, dann Parameter, je LSB zuerst.

Die folgenden Befehle stehen zur Verfügung:

  • 00000001 <key> : An Taste oder Slot gebundene Befehlssequenz ausführen
  • 00000010 <Taste> : Taste gedrückt halten
  • 00000011 <Taste> : Taste loslassen
  • 00000100 <Taste> : Taste betätigen (für 20ms drücken)
  • 00000101 <Pin> <Taste>: Pin mit Taste verknüpfen (entspricht map)
  • 00000111 <Code> : PETSCII code auf der Tastatur eingeben

Beim Verknüpfen eines Pins mit einer Taste wird der Pin über die Bits 0-2 angegeben, die höherwertigen Bits bezeichnen den Port (0 = a, 1 = b, 10 = c usw).

Wird eine Taste über die serielle Schnittstelle gedrückt gehalten, so bleibt sie gedrückt, bis sie auch über die serielle Schnittstelle wieder losgelassen wird. Der Zustand der physischen Taste wird währenddessen ignoriert.

Verbindung der seriellen Schnittstelle mit dem C64

Eine Möglichkeit der Verwendung der seriellen Schnittstelle ist der Anschluss an die Bits 3 und 4 des 6510 IO-Ports. Diese sind als “Cassette Sense” and “Casette Write” am Tapeport verfügbar (natürlich nur, wenn der Tapeport ansonsten nicht verwendet wird). “Cassette Sense” wird dann an /CLK angeschlossen, “Cassette Write” wird als DATA-Signal verwendet.

Die Quelldistribution enthält die Dateien serial.h und serial.asm im KickAssembler3-Format. Diese können benutzt werden um serielle Befehle vom C64 über den Kassettenport zum Keyman64 zu senden.

Zum Beispiel führt der folgende Code die Keyman64-Befehlsequenz aus, die an die Tastenkombination Meta-RUNSTOP gebunden ist:

.import source "serial.h"

jsr serial.open    // Kassettenport-Leitungen auf Ausgang schalten

lda #Command.exec  // Befehlsbyte für den exec-Befehl in den Akku
jsr serial.write   // Die Bits werden nach rechts rausgeschoben (lsb first)

lda #$3f           // Dies ist der Code für die "RUNSTOP" Taste
jsr serial.write   // Wieder nach rechts rauschieben

jsr serial.close   // Kassettenport-Leitungen zurück auf Eingang schalten

rts

.import source "serial.asm"

Anwendungsbeispiele

Kernal umschalten und Reset auslösen

Nehmen wir an, im C64 ist ein zweifacher Kernelumschalter verbaut. Diese Umschalter haben meistens eine Leitung, der die höchste Adressleitung des Eproms kontrolliert und so den Kernal auswählt, der vom C64 gelesen wird. In der Regel wird erwartet, diese Leitung mit Hilfe eines Schalters umzuschalten, der im Gehäuse verbaut wird.

Anstelle des Schalters kann man nun den Keyman64 verwenden.

Man entfernt einfach den Schalter und verbindet die Steuerleitung mit einer der sechzehn Steuerleitungen des Keymans. Für dieses Beispiel verwenden wir die höchste Leitung des ersten Ports (port a bit 7).

Wir erzeugen nun eine Konfigurationsdatei folgenden Inhalts:

clear port a
clear port b

k: invert port a bit 7

Und übertragen diese Konfiguration auf den Keyman:

$ keyman64 configure example.conf

Nachdem die Konfiguration übertragen wurde startet der Keyman neu. Zunächst werden alle Befehle ausgeführt, die nicht an eine Tastenkombination gebunden sind. Dies erlaubt es uns, den Anfangszustand der Leitungen zu bestimmen. Hier verwenden wir den Befehl clear, um alle Leitungen zunächst auf low zu setzen. Die Leitung zum Kernal-Umschalter ist also auch low, der erste Kernal ist ausgewählt.

Die Tastenkombination Meta-k invertiert nun die Eprom-Adressleitung des Kernelumschalters und schaltet so effektiv zwischen den beiden Kernaln hin und her.

Das reicht zwar auf Hardwareebene, allerdings kann dies den C64 immer noch abstürzen lassen, falls der Kernal gerade dann umgeschaltet wird, wenn Code aus dem Kernal ausgeführt wird. Besser wäre es, den C64 nach dem Wechsel des Kernals gleich zurückzusetzen.

Wir verbinden also die Reset-Leitung des C64 mit der ersten Steuerleitung des Ports A und verändern die Konfiguration wie folgt:

tristate port a bit 0
clear port a bits 1-7
clear port b

r: clear port a bit 0
r: sleep 10
r: tristate port a bit 0

k: invert port a bit 7
k: exec r

Wenn wir nun Meta-R drücken, wird die Reset-Leitung, die zuvor im Tristate-Zustand war, für 10 Millisekunden auf low gezogen and danach wieder in den Tristate-Zustand versetzt, was zu einem Reset des C64 führt.

Wenn wir nun Meta-K drücken, wird der Kernel wie zuvor umgeschaltet. Dannach führen wir aber mit Hilfe des Befehls exec noch die Reset-Sequenz aus, die bereits an Meta-R gebunden ist.

So können wir den Kernal wechseln und einen Reset durchführen, indem wir einfach Meta-K drücken, anstatt jedesmal den C64 auszuschalten, einen Schalter umzulegen und den C64 wieder einzuschalten, wenn wir den Kernal wechseln wollen.

Während des Resets eine Taste gedrückt halten

Einige Expansionsport-Module führen spezielle Funktionen aus, wenn eine Taste während des Resets gedrückt wird. Auch das kann der Keyman für uns erledigen. Die folgende Tastenkombination führt einen Reset aus und hält dabei die Taste RUNSTOP gedrückt:

u: down runstop
u: clear port a bit 0
u: sleep 10
u: tristate port a bit 0
u: sleep 1s
u: up runstop

Tastaturmacros definieren

Der Befehl type kann ebenfalls an eine Taste gebunden werden:

d: type load"$",8\r

Wenn wir nun Meta-D drücken, tippt der Keyman load"$",8<return> für uns. Die Escape-Sequenz \r steht hierbei für die Taste RETURN.

Tastaturlayout ändern

Der Befehl swap kann verwendet werden, um zwei Tasten auf der Tastatur gegeneinander auszutauschen. Um zum Beispiel ein QWERTZ-Layout zu verwenden, genügt der folgende Befehl:

swap z y

Soll zwischen QWERTY und QWERTZ umgeschaltet werden können, kann der Befehl wie jeder andere Befehl an eine Taste gebunden werden:

y: swap z y

Meta-Y schaltet nun zwischen den Layouts hin und her.

Lizensierung

Copyright (C) 2016 Henning Bekel <h.bekel@googlemail.com>

Hardware lizensiert unter CERN OHL v.1.2, siehe ./hardware/LICENSE.txt
Software und Firmware lizensiert unter GNU GPLv3, siehe ./LICENSE

Die Software enthält Quelltext unter MIT-Lizenz von https://github.com/arkku/ihex für das Lesen von Intel HEX Dateien, Copyright (C) 2013-2015 Kimmo Kulovesi, siehe ./intelhex/LICENSE

Die Firmware enthält den V-USB-Treiber (https://www.obdev.at/vusb), (C)2008 Objective Development GmbH.

Mitgeliefert wird im ./bootloader Verzeichnis der USBasp bootloader, (C)2013 Stephan Baerwolf (matrixstorm@gmx.de) und (C)2008 Objective Development GmbH (https://www.obdev.at/vusb).

In Übereinstimmung mit den (identischen) Lizenzen für den V-USB-Treiber und den USBasp-Bootloader (./firmware/usbdrv/License.txt and ./bootloader/License.txt, ist das gesamte Projekt veröffentlicht unter

http://www.henning-bekel.de/keyman64

Zusätzlich enthält die Distribution

Die USB-Product- und USB-Vendor-IDs für das Keyman64 USB-Gerät wurden freundlicherweise bereitgestellt von OpenMoko, Inc (http://openmoko.org).