Abschaltung des Microsoft Comfort Curve Keyboard 3000 unter Windows 10 verhindern

Seit Jahren nutze ich als Tastatur an den meisten Geräten ein Microsoft Comfort Curve Keyboard 3000. Im Gegensatz zu anderen ergonomischen Tastaturen, kann das Microsoft Comfort Curve Keyboard 3000 relativ normal genutzt werden. Bisher lief die Tastatur unter allen möglichen Betriebssystemen wie Linux oder verschiedenen Windows-Versionen ohne Probleme. Unter Windows 10 zeigte die Tastatur allerdings ein merkwürdiges Verhalten.

Über die Num-Lock-Leuchte der Tastatur kann das Problem eingegrenzt werden

Wenn man die Tastatur einige Sekunden nicht nutzt, kann anschließend nicht mehr auf der Tastatur geschrieben werden. Erst einige Sekunden intensiver Nutzung später übermittelt die Tastatur ihre Eingaben wieder an den Rechner. Das Betriebssystem versucht die Tastatur abzuschalten, um Energie zu sparen. Sichtbar wird die am flackern der Num-Lock-Leuchte auf der Tastatur. Allerdings schaltet sich die Tastatur nicht ab und dies führt zum beschriebenen Problem.

Im Geräte-Manager muss das entsprechende Eingabegerät gefunden werden

Über den Geräte-Manager kann dieses Problem allerdings gelöst werden. Dort muss unter dem Punkt Eingabegeräte das entsprechende Gerät gefunden werden. Befinden sich dort mehrere Geräte, so sollte nach dem Gerät mit der VID 045E und der PID 07B6 gesucht werden. Diese findet man in den Eigenschaften des Gerätes unter dem Punkt Details. Dort muss die Eigenschaft Hardware-IDs ausgewählt werden.

Im Tab Energieverwaltung befindet sich die gesuchte Option

Wichtig ist es den Punkt Eingabegeräte zu nutzen. Die Tastaturen befinden sich im Geräte-Manager ebenfalls unter dem Punkt Tastaturen. Dort kann die Option allerdings nicht ausgewählt werden, da sie ausgegraut ist.

Wurde das entsprechende Gerät identifiziert, so kann in den Eigenschaften zu diesem Gerät der Tab Energieverwaltung geöffnet werden. Dort findet sich der Punkt:

Computer kann das Gerät ausschalten, um Energie zu sparen

Nachdem dieser Punkt deaktiviert wurde, kann das Microsoft Comfort Curve Keyboard 3000 auch unter Windows 10 normal genutzt werden.

Z-Wave im Home Assistant aktivieren

Die freie Heimautomationslösung Home Assistant verfügt unter anderem über eine Unterstützung des Z-Wave-Protokolls. Möchte man die Unterstützung für Z-Wave hinzufügen, so muss theoretisch nur die passende Konfiguration hinterlegt werden. In der Praxis gibt es allerdings ein paar Kleinigkeiten mehr zu beachten. Hier wird davon ausgegangen, dass Hass.io als Betriebssystem für Home Assistant genutzt wird. Bevor man mit der Konfiguration beginnt, benötigt man Gerät um sich mit dem Z-Wave-Netzwerk zu verbinden. Empfehlenswert ist hier z.B. der Aeotec Z-Stick Series 5. Daneben existieren eine Reihe weiterere Controller, welche vom Home Assistant unterstützt werden.

Die Anzeige der installierten Add-Ons für Hass.io

Im ersten Schritt sollten im Hass.io-Menü die Add-Ons für SSH und Samba aktiviert werden. Dazu wird die Weboberfläche über die URL:

http://hassio.local:8123

aufgerufen. Nach der Installation der Add-Ons ist es wichtig, diese über den Button Start direkt zu aktivieren. Nachdem das Samba-Add-On aktiviert wurde, kann über die Freigabe der Hass.io-Instanz im Ordner config die Konfiguration eingesehen werden. Wichtig ist hierbei die Datei configuration.yaml. An das Ende dieser Datei fügt man folgende Konfiguration ein:

# Z-Wave
zwave:
  usb_path: /dev/ttyACM0

Damit ist die Konfiguration für Z-Wave abgeschlossen. Um das korrekte Gerät für den Z-Wave-Stick zu ermitteln, loggen wir uns per SSH auf der Hass.io-Instanz ein:

ssh 

und geben dort den Befehl:

hassio host hardware

Dieser Befehl zeigt uns, welche Hardware an dem Raspberry Pi angeschlossen ist. Eine Ausgabe könnte dann z.B. so aussehen:

{
  "serial": [
    "/dev/ttyAMA0"
  ],
  "input": [],
  "disk": [],
  "gpio": [
    "gpiochip0",
    "gpiochip100"
  ],
  "audio": {
    "0": {
      "name": "bcm2835 - bcm2835 ALSA",
      "type": "ALSA",
      "devices": {
        "0": "digital audio playback",
        "1": "digital audio playback"
      }
    }
  }
}

Nachdem der Befehl eingegeben wurde, wird der Z-Wave-Stick an den Raspberry Pi angeschlossen:

{
  "serial": [
    "/dev/ttyACM0",
    "/dev/ttyAMA0"
  ],
  "input": [],
  "disk": [],
  "gpio": [
    "gpiochip0",
    "gpiochip100"
  ],
  "audio": {
    "0": {
      "name": "bcm2835 - bcm2835 ALSA",
      "type": "ALSA",
      "devices": {
        "0": "digital audio playback",
        "1": "digital audio playback"
      }
    }
  }
}

Bei dem neuen Gerät im Abschnitt serial handelt es sich um den Z-Wave-Stick. Seine Gerätebezeichnung übernehmen wir in die Konfiguration. Wird der Stick ab- und später wieder angesteckt, so kann sich die Gerätebezeichnung ändern, so dass dieser Prozess anschließend wiederholt werden muss. Im Falle einer falsch konfigurierten Gerätebezeichnung erhält man auf dem Dashboard eine Fehlermeldung das Z-Wave nicht angesprochen werden konnte. Nachdem der Stick angesteckt ist und die Konfiguration entsprechend erweitert wurde, muss Home Assistant neugestartet werden. Dazu wählt man im Menü Einstellungen den Punkt General und wählt dort im Bereich Server Managment den Button Restart. Nach knapp einer Minute sollte die Weboberfläche wieder verfügbar und Z-Wave aktiv sein.

Nintendo NX wurde enthüllt

Gestern um 9 Uhr Ortzeit (16 UHR MEZ) wurde im Nintendo Hauptquartier in Kyōto enthüllt was es mit dem neuen Projekt mit dem Codenamen NX auf sich hat. Der Nintendo CEO Satoru Iwata stellte das Projekt und die dazugehörige Hardware nun ausführlich vor.

Der erste Versuch von Nintendo die virtuelle Realität einzubinden

Der erste Versuch von Nintendo die virtuelle Realität einzubinden

Bei NX handelt es sich um den geistigen Nachfolger des Virtual Boy welchem vor 20 Jahren leider kein Erfolg beschieden war. Die neue Konsole dessen offizieller Name Nintendo Immersion lautet besteht dabei aus einer der VR-Brille, mit integriertem Head- und Positionstracking, sowie zwei VR-Handschuhen und ist dabei als mobiles System konzipiert. Die VR-Brille verfügt über zwei eingebaute Kameras, so das auch Argumented-Reality Anwendungen und Spiele möglich sind. Spiele werden über den integrierten Shop, per WLAN, auf dem internen Speicher (128 GB) installiert. Laut Iwata soll die Akkulaufzeit knapp 8 Stunden betragen.

Offene Kerne

Bei der Software hat es die Open Source Bewegung schon weit gebracht, für so ziemlich jeden Anwendungsfall gibt es auch eine freie Applikation. Anders sieht das bei der Hardware aus. Hier ist vieles noch proprietär. Damit das nicht auf ewig so bleibt gibt es Projekte wie OpenCores welches unter http://opencores.org/ zu finden ist.

Die Projektübersicht von OpenCores

Die Projektübersicht von OpenCores

Gegründet im Oktober 1999 von Damjan Lampret, gibt es auf den Webseiten des Projektes eine Reihe von offenen Rechenwerken bis hin zu ganzen Prozessoren. Geschrieben ist das ganze meist in einer Hardwarebeschreibungssprache wie VHDL, Verilog oder SystemVerilog. Die Lizenzen variieren je nach Projekt meist zwischen der LGPL oder einer BSD Lizenz.

Eine eigene CPU Architektur

Wenn man mal auf der Suche nach einem kleinen Zeitvertreib ist, kann man natürlich so einiges ausdenken, so z. B. eine eigene CPU-Architektur. Dabei muss man diese nicht in Hardware gießen, sondern es reicht wenn man diese emuliert. Und so entstand in einiger Zeit eine CPU, welche auf den Namen Structura hört. Ein Designziel war es dabei, die CPU nur mit den nötigsten Maschinenbefehlen auszustatten. Das führte bei der Structura zu folgenden Befehlen (hier als Assembler Mnemonics dargestellt):

  • [0] – JUMP
  • [1] – ADD
  • [2] – COPY

Das bedeutet, dass es unter anderem keine Nichtoperation wie z.B. NOOP bzw. NOP im Befehlssatz der CPU gibt. Der Grund dafür ist ganz einfach. Eine Nichtoperation lässt sich durch einen JUMP um null Byte emulieren, was im Endeffekt nur eine Erhöhung des Instruction Counters kurz IC zur Folge hat. Da JUMP auf den Opcode 0 gelegt wurde führt, dies zu einer interessanten Reaktion der CPU, wenn sie das Ende des Programms erreicht und versucht den restlichen Speicher zu interpretieren. Die CPU interpretiert das als Sprung an die Adresse 0 und beginnt mit dem Programm von vorne.

Der Befehlsaufbau der Maschinenbefehle stellt sich dabei so da:

JUMP (Breite: 40 Byte)
  [Int64|Befehlswort - 0]
  [Int64|Adressinterpretation - 0/ANCTAAV 1/ACTAAV 2/RNCTAAV 3/RCTAAV]
      ANCTAAV - Adress not contains target adress as value
      ACTAAV - Adress contains target adress as value
      RNCTAAV - Register not contains target adress as value
      RCTAAV - Register contains target adress as value
  [Int64|Sprungbedingung - 0/NONE 1/ZERO 2/POS 3/NEG 4/OVF]
  [Int64|Sprungadressierung - 0/ABS 1/REL] 
  [Int64|Adresse oder Wert]

ADD (Breite: 32 Byte)
  [Int64|Befehlswort - 1]
  [Int64|Modus - 0/RAR 1/RANR 2/RAV] 
      RAR - Register and register
      RANR - Register and negative register
      RAV - Register and value
  [Int64|Register] 
  [Int64|Register oder Wert]

COPY (Breite: 40 Byte)
  [Int64|Befehlswort - 2] 
  [Int64|Modus - 0/NACTAAV 1/FACTAAV 2/SACTAAV 3/BACTAAV]
    NACTAAV - No adress contains target adress as value
    FACTAAV - First adress contains target adress as value
    SACTAAV - Second adress contains target adress as value
    BACTAAV - Both adress contains target adress as value
  [Int64|Menge an kopierenden Daten in Byte]
  [Int64|Register, Speicheradresse oder ZERO] 
  [Int64|Register oder Speicheradresse]

Jeder Opcode auf der CPU ist 8 Byte lang und wird als Int64 interpretiert. Die Structura ist mit den Registern A bis Z ausgestattet, was 26 Allzweckregister mit einer Breite von 8 Byte sind. Neben diesen Allzweckregistern besitzt es das Spezialregister IC bei welchem es sich um den Instruction Counter handelt und einige Flags mit den Namen Zero, Positive, Negative und Overflow. Beim Start beginnt die CPU mit der Ausführung des Programms ab der Adresse 0. Eine Besonderheit ist, das die CPU keinen Stack und keine Interrupts unterstützt.

Damit Peripherie angesprochen werden kann, gibt es bestimmte Bereiche im Speicher, in welche sich diese Geräte einblenden. Der Bereich für Einblendungen ist dabei ab der Adresse 9.000.000.000.000.000.000 (7CE66C50E2840000) bis 9.223.372.036.854.775.807 (7FFFFFFFFFFFFFFF) zu finden.

Die Grafikkarte wird dabei ab der Adresse 9.000.000.000.000.000.000 bis einschließlich 9.099.999.999.999.999.999 eingeblendet. In den ersten 4096 Byte befindet sich dabei der Konfigurationsblock der Grafikkarte, welcher Informationen über die Auflösung und andere Einstellungen enthält.

Ab der Adresse 9.100.000.000.000.000.000 bis einschließlich 9100000000000008191 wird die Tastatur bzw. deren Eingabepuffer eingeblendet. Die ersten zwei Byte im Speicher der CPU sind dabei ein UInt16 welcher den aktuellen Zeichenindex der Tastatur in ihrem Tastaturpuffer angibt. Jede Eingabe auf der wird dabei vom Tastaturgerät in Form eines Bytearrays mit der Größe von fünf Byte übertragen. Das erste Byte gibt dabei den Modifier an, die restlichen 4 Bytes enthalten das erzeugte Zeichen in Form eines UTF-32 Zeichens.

Der schematische Aufbau der CPU und deren Peripherie

Der schematische Aufbau der CPU und deren Peripherie

Der Assembler für die CPU unterstützt eine Reihe von Mnemonics, welche anschließend in die Maschinensprache übersetzt werden. Diese sind:

ABS [Register]
ADD [Register] [Register oder Wert]
CLR [Register oder ALL]
COPY [Int64|Menge an kopierenden Daten in Byte] [Register oder Speicheradresse] [Register oder Speicheradresse]
DIV [Register] [Register oder Wert]
LOAD [Speicheradresse] [Register]
DEC [Register]
INC [Register]
JUMP [Sprungbedingung|NONE|ZERO|POS|NEG|OVL] [Sprungadressierung|ABS|REL] [Adresse oder Wert]
MOD [Register] [Register oder Wert]
MUL [Register] [Register oder Wert]
NEG [Register]
NOOP
SHIFTL [Register] [Register oder Wert]
SHIFTR [Register] [Register oder Wert]
WRITE [Register] [Speicheradresse]

Beim Assembler handelt es sich genaugenommen nicht um einen Assembler der reinen Lehre, sondern um eine Kreuzung aus Assembler, Makroassembler und Hochsprache. Für die komplexeren Kommandos wie MUL oder SHIFTL werden bestimmte Register während der Berechnung belegt (im Fall von MUL z. B. das W, X, Y und Z Register). Die vom Kommando belegten Register sind dabei in der Dokumentation aufgeführt. Das führt natürlich dazu das eine solche Multiplikation nach der Auflösung aus sehr vielen Befehlen besteht:

COPY 8 Y A;
COPY 8 Z ZERO;
ADD Z 3;
COPY 8 X ZERO;
ADD Y 0;
JUMP POS REL 72;
JUMP ZERO REL 32;
ADD X 1;
ADD Z 0;
JUMP POS REL 72;
JUMP ZERO REL 32;
ADD X 1;
COPY 8 A ZERO;
ADD Y 0;
JUMP POS REL 184;
JUMP ZERO REL 144;
COPY 8 W Y;
ADD Y -W;
ADD Y -W;
COPY 8 W ZERO;
ADD Z 0;
JUMP POS REL 184;
JUMP ZERO REL 144;
COPY 8 W Z;
ADD Z -W;
ADD Z -W;
COPY 8 W ZERO;
ADD A Y;
ADD Z -1;
JUMP POS REL -104;
COPY 8 W X;
ADD W -2;
JUMP ZERO REL 368;
COPY 8 W X;
ADD W -1;
JUMP ZERO REL 112;
COPY 8 W X;
ADD W 0;
JUMP ZERO REL 144;
COPY 8 W A;
ADD A -W;
ADD A -W;
COPY 8 W ZERO;
COPY 8 X ZERO;
COPY 8 Y ZERO;
COPY 8 Z ZERO;

Während der Entwicklung gab es dabei einige interessante Ideen wie man bestimmte Sachen im Assembler lösen könnte. So zum Beispiel folgendes Problem:

ADD A 555;   // Fülle das Register A mit dem Wert 555
COPY 8 B A;  // Kopiere Register A zu B
DEC B;       // Reduziere B um 1
COPY 8 *A B; // Kopiere der Wert von B an die Adresse welche im A Register A definiert ist (555)
COPY 8 D *A; // Kopiere das was ab 555 steht in den Register D

Im D Register sollte nun der Wert 554 stehen. Möglich wird dies dadurch, das die CPU weiß, dass sie nicht den Wert nach A kopieren soll, sondern den Wert welcher in A enthalten ist, als Zieladresse benutzt. Theoretisch wäre dies auch anders lösbar gewesen. So hätte der Assembler das * in selbst modifizierenden Quellcode auflösen können. Aus einem COPY 8 *A D wäre dann in etwa folgender Quelltext erzeugt worden:

COPY 8 (IC+32) A;
COPY B [IC+32];

Das Problem an dieser Geschichte ist, das der Assembler bei dieser Variante sehr viel über die Innereien der CPU wissen muss. So muss z. B. genau definiert sein, wann der IC erhöht wird, da dieser für den selbst modifizierenden Code benötigt wird. Zur Erklärung: Die erste Zeile kopiert die Adresse welche in A liegt in die nächste Zeile und modifiziert somit den COPY Befehl während der Laufzeit. Dadurch wird die Adressierung über den Registerwert möglich.

Interessant ist auch die Berechnung eines Sprungzieles. Möchte man z. B. folgendes Programm ausführen:

ADD A 7;
JUMP NONE REL -104

stellt sich die Frage wie man die relative Sprungweite ausrechnet. Hierbei kommt es auf die Breite der Befehle an. Bei den Grundbefehlen (ADD, COPY und JUMP) entspricht diese den in der Maschinencodebeschreibung angegebenen Breite. Andere Befehle wie MUL oder SHIFTL zählen zu den komplexen Befehlen, da diese im Maschinencode aus mehreren Anweisungen bestehen.

Hier besteht die einfachste Möglichkeit darin, den JUMP-Befehl im ersten Moment mit Fantasiewerten zu füllen. Anschließend wird der Emulator mittels:

Structura.exe program.asm -disassemble -withIC

aufgerufen. Bei der Darstellung mittels withIC wird der Wert des ICs am Anfang des Befehls und am Ende des Befehls angezeigt.

(256/296)            JUMP ZERO REL 32;
(296/328)            ADD X 1;
(328/360)            ADD Z 0;

Möchte man nun also zum Befehl ADD Z 0; springen so rechnet man 328-296 und hat so das richtige Sprungziel errechnet.

Und natürlich fehlt auch noch eine Umsetzung in Hardware, aber bis das so weit ist, kann es naturgemäß dauern. Bei der Structura handelt es sich natürlich nicht um eine effiziente CPU, sondern um eine bei welcher versucht wurde, die CPU internen Befehle auf ein Minimum zu begrenzen und das Design als solches einfach zu halten. Dies schlägt sich unter anderem darin nieder, das jedes Befehlswort 8 Byte lang ist, und somit für 3 Befehle überdimensioniert, aber dafür die Einfachheit der Maschine intern gegeben ist.

Und natürlich erkauft man sich dies mit einigen Nachteilen, so sind die Bitverschiebungsoperation eigentlich eine der schnellsten in einer CPU. Durch die Emulation über zusätzlichen Assemblercode wird es eine der langsamsten Operation. Aber eine CPU mit einem großen Befehlssatz zu emulieren, ist schließlich einfach und das war nicht der Sinn der Übung.

Anschauen kann man sich das unter der GPLv3 stehende Projekt unter https://github.com/seeseekey/Structura/. Eine vorkompilierte Version zum Testen gibt es hier zum Download. In der Implementation befinden sich sicherlich noch einige Fehler, auf welche mich gerne hingewiesen werden darf. Jetzt müsste nur noch jemand Linux auf das System portieren, wobei dies ohne weiteres nicht funktionieren sollte, das die CPU Dinge wie Interrupts nicht unterstützt. Allerdings wäre es natürlich durchaus möglich ein eigenes minimales Betriebssystem für das emulierte System zu schreiben.