---
title: "Hardware & Input System"
description: "COPILOT keyboard hardware, joystick, serial/HID protocols, and key mapping"
---
# Hardware & Input System
## Physical Hardware
The COPILOT keyboard is a custom-built control panel with three input subsystems:
```
┌──────────────────────────────────────────────────────────────────┐
│ COPILOT KEYBOARD │
│ │
│ ┌────────────────────────┐ ┌───────────────┐ ┌────────────┐ │
│ │ BUTTON PANEL │ │ JOYSTICK │ │ JOG/ │ │
│ │ │ │ │ │ SHUTTLE │ │
│ │ [Home] [F1-F7] │ │ ╱───╲ │ │ │ │
│ │ [0-9] [.] [*] │ │ │ ● │ │ │ ◄──●──► │ │
│ │ [+] [-] [(] [)] │ │ ╲───╱ │ │ │ │
│ │ [< >] │ │ 3-axis │ │ 7 speeds │ │
│ │ │ │ X/Y/Z │ │ per dir │ │
│ │ Serial (COM port) │ │ USB HID │ │ Serial │ │
│ └────────────────────────┘ └───────────────┘ └────────────┘ │
│ │
│ Arduino Leonardo (ATmega32U4) │
│ USB Composite: Serial + HID │
└───────────────────────────────┬──────────────────────────────────┘
│ USB
LattePanda SBC
```
## Communication Protocol
### Serial Port (Buttons + Jog/Shuttle)
Messages are newline-terminated strings with a single-character prefix:
| Prefix | Type | Example | Meaning |
|--------|------|---------|---------|
| `p` | Key Pressed | `pH\r\n` | Home key pressed |
| `r` | Key Released | `rH\r\n` | Home key released |
| `h` | Heartbeat | `h\r\n` | Keepalive (ignored) |
| `j` | Jog | `j+1\r\n` / `j-1\r\n` | Jog wheel step right/left |
| `s` | Shuttle | `s3\r\n` / `s-5\r\n` | Shuttle position (-7 to +7) |
| `v` | Version | `v2.1\r\n` | Firmware version response |
Startup: App sends byte `0xDC` to request firmware version.
### HID Device (Joystick)
| Property | Value |
|----------|-------|
| Vendor ID | `10959` (0x2ACF) |
| Product ID | `257` (0x0101) |
| Axes | X (pan), Y (tilt), Z (zoom) |
| Raw range | Scaled to **-255 to +255** |
| Buttons | Button1, Button2, Button3 |
```mermaid
graph TD
subgraph "HID Input Processing"
Raw["Raw HID Report"] --> Parser["DeviceItemInputParser"]
Parser --> Changed{"HasChanged?"}
Changed -->|Yes| Usage{"Usage Type"}
Usage -->|GenericDesktopX| PanEvt["JoystickX event
(-255 to +255)"]
Usage -->|GenericDesktopY| TiltEvt["JoystickY event
(-255 to +255)"]
Usage -->|GenericDesktopZ| ZoomEvt["JoystickZ event
(-255 to +255)"]
Usage -->|Button1| B1["JoystickButton1
Pressed/Released"]
Usage -->|Button2| B2["JoystickButton2
Pressed/Released"]
Usage -->|Button3| Ignore["Ignored"]
end
```
## Key Mapping
### Hardware Keys → Virtual Keys
The serial protocol uses ASCII character codes:
| Serial Code | Char | Virtual Key | UI Function |
|-------------|------|-------------|-------------|
| 72 | `H` | Home | Home position / Jump to live |
| 65 | `A` | F1 | Function button 1 |
| 66 | `B` | F2 | Function button 2 |
| 67 | `C` | F3 | Function button 3 |
| 68 | `D` | F4 | Function button 4 |
| 69 | `E` | F5 | Function button 5 |
| 70 | `F` | F6 | Function button 6 |
| 71 | `G` | F7 | Function button 7 |
| 46 | `.` | Prefix | Camera number prefix cycle |
| 42 | `*` | FullScreen | Toggle monitor maximize |
| 41 | `)` | Sequence | Open sequence menu |
| 40 | `(` | Backspace | Delete last digit |
| 48 | `0` | D0 | Digit 0 |
| 55-51 | `7-3` | D1-D5 | Digits 1-5 (note: remapped!) |
| 49-51 | `1-3` | D7-D9 | Digits 7-9 (note: remapped!) |
| 52-54 | `4-6` | D4-D6 | Digits 4-6 |
| 60 | `<` | Minus | Previous camera / Focus far |
| 62 | `>` | Plus | Next camera / Focus near |
| 43 | `+` | Lock | Toggle camera PTZ lock |
| 45 | `-` | Enter | Confirm camera number |
**Important:** The digit key wiring is non-standard — D1 maps to ASCII 55 (`7`), not 49 (`1`). This is a hardware layout choice.
### Joystick Buttons
| Button | Virtual Key | Function |
|--------|-------------|----------|
| Button1 | JoystickButton1 | (Context-dependent) |
| Button2 | JoystickButton2 | Toggle camera PTZ lock |
### Development Keyboard Emulation
When no serial port is detected, the app falls back to standard keyboard input via `VirtualKeyboard.Emulate()`:
| PC Key | Virtual Key |
|--------|-------------|
| Home | Home |
| F1-F7 | F1-F7 |
| F10 | Prefix |
| F11 | FullScreen |
| F12 | Sequence |
| 0-9 / Numpad | D0-D9 |
| Backspace | Backspace |
| Enter | Enter |
| +/- | Plus/Minus |
| Left/Right arrow | JogLeft/JogRight |
| Shift+Left/Right | Shuttle (incremental) |
| Shift+Up | Shuttle center (reset) |
## Shuttle Speed Mapping
The shuttle wheel has 7 positions per direction. Speeds are configurable per deployment:
```
Position: -7 -6 -5 -4 -3 -2 -1 0 +1 +2 +3 +4 +5 +6 +7
◄── backward ──────────── center ──────────── forward ──►
Config: [250,100, 30, 15, 5, 2, 1] ● [ 1, 2, 5, 15, 30,100,250]
```
Default playback speeds (from config): `[1, 2, 5, 15, 30, 100, 250]`
## Service Key (Hidden Menu)
Holding the **Backspace** key for 3 seconds opens the Service Menu page. This provides access to firmware update and diagnostic functions.