ESP32 firmware for DCS World cockpit panels connected via DCS-BIOS protocol
CockpitOS connects physical cockpit hardware/panels to DCS World via the DCS-BIOS protocol. It runs natively across the entire ESP32 family—Classic, C3, C5, C6, P4, S2, and S3—supporting buttons, switches, encoders, LEDs, TFT displays, and segment displays out of the box. With transport options spanning legacy Serial (socat), Wi-Fi, and native USB, CockpitOS delivers the flexibility modern cockpit builders demand. Think of it as the DCS-BIOS Arduino Library—reimagined for performance and scale on ESP32 devices with native USB support or Wi-Fi
Inputs
- Buttons, toggle switches, rotary encoders, multi-position selectors
- Analog axes with self-calibration
- I²C expanders (PCA9555) and shift registers (74HC165) for high pin counts
- Matrix scanning for rotary switches
- Debouncing and edge detection built-in
Outputs
- GPIO LEDs with PWM dimming
- WS2812 addressable RGB LEDs
- TM1637 and GN1640T LED drivers
- HT1622 segment LCD displays (IFEI, UFC, etc.)
- SPI TFT gauges via LovyanGFX
Connectivity
- USB HID (recommended) — works with included HID Manager
- WiFi UDP — for wireless panels
- Serial — legacy support (socat)
Architecture
- Static memory allocation — no heap fragmentation
- Non-blocking I/O throughout
- O(1) label lookups via perfect hashing
- 250 Hz input polling, 30-60 Hz display refresh
- Per-aircraft configuration via Label Sets
| MCU | Status |
|---|---|
| ESP32-S2 | ✅ Recommended (native USB) |
| ESP32-S3 | ✅ Recommended (native USB) |
| ESP32 (original) | ✅ Works (Serial/WiFi only) |
| ESP32-C3 and C6 | ✅ Works (Serial/WiFi only) |
Popular boards: LOLIN S2 Mini, LOLIN S3 Mini (or any other Classic, S2 or S3 dev board from Amazon)
- Install Arduino IDE 2.x with ESP32 Arduino Core ≥ 3.3.0
- Open CockpitOS in the IDE
- Select a label set in
src/LABELS/(start withLABEL_SET_TEST_ONLY) - Configure transport in
Config.h(USB, WiFi, or Serial) - Compile and upload to your ESP32
For USB mode, run HID Manager/HID_Manager.py on your PC to bridge to DCS-BIOS.
| Guide | Description |
|---|---|
| Getting Started | First-time setup, compile, upload |
| Creating Label Sets | Configure for your aircraft, METADATA system, LabelSetConfig |
| Hardware Wiring | Wiring diagrams for all input/output types |
| Transport Modes | USB, WiFi, Serial configuration |
| Advanced Displays | HT1622 segment displays, TFT gauges |
| Advanced Controls | Custom panels, CoverGate, subscriptions, panel registration |
| Config Reference | Complete Config.h flag reference |
| Python Tools | HID Manager, generators, debug tools CLI reference |
| FAQ | Common questions and answers |
| Your First Panel in 30 Minutes (WiFi) | How to build your first Wi-Fi panel in 30 min |
| AI Assistant | Interactive help for any CockpitOS task |
| LLM Docs | Raw documentation for AI tools |
Need help uploading code to your device?
Need help building your first panel? Stuck on a wiring issue? Want to understand the code?
💬 Chat with CockpitOS Assistant
Our AI assistant knows the entire CockpitOS codebase, all APIs, and common pitfalls. It can:
- Guide you through creating a new panel from scratch
- Generate InputMapping.h and LEDMapping.h entries
- Explain any part of the architecture
- Troubleshoot connection and configuration issues
Works for beginners and experts alike.
CockpitOS/
├── src/
│ ├── Core/ # Protocol handling, LED control, HID management
│ ├── Panels/ # Panel implementations (IFEI, ECM, etc.)
│ └── LABELS/ # Aircraft/panel configurations
├── lib/
│ └── CUtils/ # Hardware drivers (GPIO, I²C, displays)
├── HID Manager/ # PC-side USB bridge application
├── Tools/ # RAM walker, test utilities
└── Docs/ # Documentation
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ DCS World │───▶│ DCS-BIOS │────▶│ CockpitOS │────▶│ Hardware │
│ │◀───│ (LUA) │◀────│ (ESP32) │◀────│ (Panel) │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
Sim Export/Import Firmware Physical I/O
DCS-BIOS exports cockpit state from the simulator. CockpitOS receives this data and drives your physical hardware. When you flip a switch, CockpitOS sends the command back through DCS-BIOS to the simulator.
Label Sets define your panel's configuration:
- InputMapping.h — Buttons, switches, encoders, their GPIO pins, and DCS-BIOS commands
- LEDMapping.h — LEDs, their hardware type, and which DCS-BIOS indicators they represent
Run python generate_data.py in your label set folder to generate the runtime data files.
Included label sets:
LABEL_SET_TEST_ONLY— Minimal test configurationLABEL_SET_IFEI— F/A-18C IFEI display panel
- Arduino IDE ≥ 2.3.6
- ESP32 Arduino Core ≥ 3.3.0
- Python 3.x (for generators and HID Manager)
- DCS World with DCS-BIOS installed
Optional:
- LovyanGFX (for TFT displays)
CockpitOS follows embedded best practices:
- No dynamic memory — All buffers statically allocated
- No blocking calls — State machines and interrupts instead of delays
- Bounded execution — All loops have iteration limits
- Fail-safe defaults — Graceful handling of disconnections and errors
This isn't certified avionics software, but it's built with reliability in mind for long simulation sessions.
This section covers internal architecture. Skip if you just want to build panels.
CockpitOS adapts to DCS-BIOS, it doesn't reinvent it. We kept the original protocol.cpp state machine intact — the same sync-frame detection, address parsing, and delta-compressed 16-bit word handling. The wire format is efficient; we saw no reason to change it.
Panel logic (inputs, LEDs, displays) is fully decoupled from the data transport:
┌─────────────────────────────────────────────────────────────────┐
│ PANEL LOGIC │
│ (subscriptions, callbacks, hardware drivers) │
└─────────────────────────┬───────────────────────────────────────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌─────────┐ ┌───────────┐ ┌──────────┐
│ USB HID │ │ WiFi UDP │ │ Serial │
└─────────┘ └───────────┘ └──────────┘
Swapping transports requires no panel code changes. This also means the architecture could theoretically adapt to different protocols — if another sim exposed a binary stream with address/value pairs, we'd swap the transport layer, not rewrite panels.
Traditional DCS-BIOS clients receive the entire aircraft state — every address, every update, whether you need it or not. CockpitOS inverts this:
- Each Label Set defines which DCS-BIOS addresses the panel cares about
- At compile time, we generate hash tables for O(1) address lookup
- At runtime, irrelevant addresses are skipped in microseconds
- Result: A panel with 50 controls doesn't process 2,000+ addresses per frame
This matters for multi-panel pits where each ESP32 handles a specific section.
Native USB on ESP32-S2/S3 eliminates socat and virtual COM ports entirely:
- Device exposes as HID gamepad with Feature Reports as a bidirectional mailbox
HID_Manager.pypolls Feature Reports and relays to/from DCS-BIOS UDP- Lightweight: <1% CPU on Raspberry Pi, tested with 20+ devices on Windows 11
- No COM port enumeration, no driver issues, no socat configuration
Trade-off: USB has hub/controller limits that serial doesn't. For typical pit builds (5-15 panels), USB is simpler. For 30+ devices, serial scales better.
The DCS-BIOS Arduino Library is excellent for getting started. CockpitOS exists because we needed:
- Native USB support (not available on classic Arduino)
- WiFi transport for wireless panels
- Static memory model for long session stability
- Per-panel address filtering at scale
We're not replacing DCS-BIOS — we're providing an alternative client implementation that respects the protocol while expanding hardware and transport options.
MIT — See LICENSE
Free for personal and commercial use. Not certified for actual aircraft.
- DCS-BIOS Skunkworks — The protocol that makes this possible
- LovyanGFX — The TFT library that powers our displays
- DCS-BIOS Arduino Library — The library that inspired our project
Built by the CockpitOS Project Dev Team.
