Key Strike Developer Documentation

The Key Strike is a programmable keyboard and game controller developed by Jochen Zurborg (hardware) and Michael Pohl (software) of ArcadeForge. It is based on the Arduino Leonardo.

Here the Key Strike settings files as well as the serial protocol are documented.

Settings Files

A Key Strike settings file is an XML document which describes all the settings of a Key Strike.

Example File

Here is an example settings file for two players with the default values, remove one PlayerSettings element for a one-player configuration:

<DeviceSettings>
  <FirmwareVersion>
    <Number>0</Number>
    <Number>1</Number>
  </FirmwareVersion>
  <Name>Key Strike</Name>
  <UseAltMapping>true</UseAltMapping>
  <Players>
    <PlayerSettings>
      <UseGamepad>false</UseGamepad>
      <KeystrokeMappings>
        <Right>
          <Primary>RightArrow</Primary>
          <Alternate>RightArrow</Alternate>
        </Right>
        <Down>
          <Primary>DownArrow</Primary>
          <Alternate>DownArrow</Alternate>
        </Down>
        <Left>
          <Primary>LeftArrow</Primary>
          <Alternate>LeftArrow</Alternate>
        </Left>
        <Up>
          <Primary>UpArrow</Primary>
          <Alternate>UpArrow</Alternate>
        </Up>
        <Button1>
          <Primary>LeftControl</Primary>
          <Alternate>Return</Alternate>
        </Button1>
        <Button2>
          <Primary>LeftAlt</Primary>
          <Alternate>Escape</Alternate>
        </Button2>
        <Button3>
          <Primary>Space</Primary>
          <Alternate>F2</Alternate>
        </Button3>
        <Button4>
          <Primary>LeftShift</Primary>
          <Alternate>F3</Alternate>
        </Button4>
        <Button5>
          <Primary>X</Primary>
          <Alternate>NoEvent</Alternate>
        </Button5>
        <Button6>
          <Primary>Z</Primary>
          <Alternate>NoEvent</Alternate>
        </Button6>
        <Button7>
          <Primary>Return</Primary>
          <Alternate>NoEvent</Alternate>
        </Button7>
        <Button8>
          <Primary>Escape</Primary>
          <Alternate>NoEvent</Alternate>
        </Button8>
        <ButtonStart>
          <Primary>Number1</Primary>
          <Alternate>Tab</Alternate>
        </ButtonStart>
        <ButtonSelect>
          <Primary>Number2</Primary>
          <Alternate>NoEvent</Alternate>
        </ButtonSelect>
        <ButtonCoin>
          <Primary>Number5</Primary>
          <Alternate>Number9</Alternate>
        </ButtonCoin>
      </KeystrokeMappings>
    </PlayerSettings>
    <PlayerSettings>
      <UseGamepad>false</UseGamepad>
      <KeystrokeMappings>
        <Right>
          <Primary>G</Primary>
          <Alternate>NoEvent</Alternate>
        </Right>
        <Down>
          <Primary>F</Primary>
          <Alternate>NoEvent</Alternate>
        </Down>
        <Left>
          <Primary>D</Primary>
          <Alternate>NoEvent</Alternate>
        </Left>
        <Up>
          <Primary>R</Primary>
          <Alternate>NoEvent</Alternate>
        </Up>
        <Button1>
          <Primary>A</Primary>
          <Alternate>NoEvent</Alternate>
        </Button1>
        <Button2>
          <Primary>S</Primary>
          <Alternate>NoEvent</Alternate>
        </Button2>
        <Button3>
          <Primary>Q</Primary>
          <Alternate>NoEvent</Alternate>
        </Button3>
        <Button4>
          <Primary>W</Primary>
          <Alternate>NoEvent</Alternate>
        </Button4>
        <Button5>
          <Primary>K</Primary>
          <Alternate>NoEvent</Alternate>
        </Button5>
        <Button6>
          <Primary>I</Primary>
          <Alternate>NoEvent</Alternate>
        </Button6>
        <Button7>
          <Primary>NoEvent</Primary>
          <Alternate>NoEvent</Alternate>
        </Button7>
        <Button8>
          <Primary>NoEvent</Primary>
          <Alternate>NoEvent</Alternate>
        </Button8>
        <ButtonStart>
          <Primary>Number2</Primary>
          <Alternate>NoEvent</Alternate>
        </ButtonStart>
        <ButtonSelect>
          <Primary>NoEvent</Primary>
          <Alternate>NoEvent</Alternate>
        </ButtonSelect>
        <ButtonCoin>
          <Primary>Number6</Primary>
          <Alternate>NoEvent</Alternate>
        </ButtonCoin>
      </KeystrokeMappings>
    </PlayerSettings>
  </Players>
</DeviceSettings>

Element Contraints

The FirmwareVersion children’s content is currently fixed. The content of the Name element is an arbitrary string, which encoded in UTF–8 must not exceed 100 bytes. The UseAltMapping and UseGamepad elements allow the values true and false as contents.

Here’s a list of the valid values for the Primary and Alternate element contents, they refer to values of the HID Keyboard/Keypad usage page[1]:

Typewriter Keys
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, Number1, Number2, Number3, Number4, Number5, Number6, Number7, Number8, Number9, Number0, Enter, Escape, Backspace, Tab, Space, Minus, Equals, BracketOpen, BracketClose, Backslash, Semicolon, Apostrophe, GraveAccent, Comma, Period, Slash, CapsLock
Function Keys
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24
Control
PrintScreen, ScrollLock, Pause, Insert, Home, PageUp, Delete, End, PageDown, RightArrow, LeftArrow, DownArrow, UpArrow, LeftControl, LeftShift, LeftAlt, LeftGui, RightControl, RightShift, RightAlt, RightGui
Number Pad
NumpadNumLock, NumpadSlash, NumpadStar, NumpadMinus, NumpadPlus, NumpadEnter, Numpad1, Numpad2, Numpad3, Numpad4, Numpad5, Numpad6, Numpad7, Numpad8, Numpad9, Numpad0, NumpadPeriod, NumpadEquals, NumpadComma, NumpadEqualSign
Special
NoEvent, Application, Execute, Help, Menu, Select, Stop, Again, Undo, Cut, Copy, Paste, Find, Mute, VolumeUp, VolumeDown, AlternateErase, Sysreq, Cancel, Clear, Prior, Return, Separator, Out, Oper, ClearAgain, CrselProps, Exsel
International
NonUsNumberSign, NonUsBackslash, Kanji1, Kanji2, Kanji3, Kanji4, Kanji5, Kanji6, Kanji7, Kanji8, Kanji9, Lang1, Lang2, Lang3, Lang4, Lang5, Lang6, Lang7, Lang8, Lang9

Serial Communication with the Key Strike

The Key Strike can be configured and data about its settings can be retrieved over a virtual serial port. Keystrokes must be values from the HID Keyboard/Keypad usage page[1].

Protocol

This handshake protocol uses ASCII encoding. Communication is initialized from the host. Requests and responses consist of a text prefix and a text postfix. Between these only integer values are recognized, which are divided by any non-decimal character except the postfix.

The first of these integer values denotes one of the predefined commands. Each command has a defined number of arguments and return values. Each fully recognized command is acknowledged by a response. This also has a prefix and a postfix, between these only integers and spacing characters are printed. The first integer denotes the command, it is followed by a command-specific number of return values.

If an error occurs the response data between prefix and postfix starts with ERROR followed by the command number (0 if no command could be recognized) and an error description.

Command Syntax

Request
ks( {command} ({argument})* )
Response
ks[ ( {command} {return value}* | ERROR {command} {message} ) ]

{command}, {argument} and {return value} are integer values (they are read as long int). Consecutive Zeros may be omitted, but this should not be used. {message} is an textual error description. {command} must be defined here below.

Command Specifications

The command specifications have the following format:

{command name} ({command})
Command description.
arguments: {value specification}*
return values: {value specification}*

arguments and return values are optional.

{value specification} has the following syntax:

{content} is:

version (1)
Returns the Key Strike firmware version.
return values: {major version} {minor version}
player count (2)
Returns the number of players.
return values: {player count}
reset (3)
Resets the settings to defaults.
get muffled (4)
Returns if the Key Strike is muffled, that is it does not send any keyboard or gamepad signals.
return values: {muffled: 0 - no | 1 - yes}
set muffled (5)
Muffles or unmuffles the Key Strike.
arguments: {muffled: 0 - no | 1 - yes}
return values: {muffled}
get signals (6)
Returns the state of the input signals.
return values: {signal: 0 - inactive | 1 - active}[KEY_STRIKE_SIGNAL_COUNT * _playerCount]
get name (7)
Returns the length of this Key Strike’s name as well as its characters’ values.
return values: {name length} {name character}[name length]
set name (8)
Set the name of the Key Strike.
arguments: {name length} {name character}[name length]
return values: {name length} {name character}[name length]
get keystroke (9)
Returns the keystroke for the specified signal.
arguments: {player} {alternate: 0 - normal mapping | 1 - alternate mapping} {signal}
*return values: {player} {alternate} {signal} {keystroke}
set keystroke (10)
Sets the keystroke for the specified signal.
arguments: {player} {alternate: 0 - normal mapping | 1 - alternate mapping} {signal} {keystroke}
*return values: {player} {alternate} {signal} {keystroke}
get keystrokes (11)
Gets the keystrokes for all players. For each player the normal and alternate mapping are returned.
*return values: {keystroke}[KEY_STRIKE_SIGNAL_COUNT * _playerCount * 2]
set keystrokes (12)
Sets the keystrokes for all players. For each player the normal and alternate mapping have to be given.
arguments: {keystroke}[KEY_STRIKE_SIGNAL_COUNT * _playerCount * 2]
return values: {keystroke}[KEY_STRIKE_SIGNAL_COUNT * _playerCount * 2]
get use gamepad (13)
Returns for each player if the gamepad should be used.
return values: {use gamepad: 0 - no | 1 - yes}[_playerCount]
set use gamepad (14)
Sets for the specified player if the gamepad should be used.
arguments: {player} {use gamepad: 0 - no | 1 - yes}
return values: {player} {use gamepad}
get use alternate mapping (15)
Returns if the alternate mapping is used.
return values: {use alt mapping: 0 - no | 1 - yes}
set use alternate mapping (16)
Sets if the alternate mapping should be used.
arguments: {use alt mapping: 0 - no | 1 - yes}
return values: {use alt mapping}

  1. Section 10 Keyboard/Keypad Page (0x07) in the HID Usage Tables [PDF] defines the values to be used as keystrokes except for the usage IDs 1–3.  ↩