Skip to content

System Overview

System Overview

OpenArcade consists of three main layers: child modules (ESP32), the parent hub (Raspberry Pi), and the configuration app.

High-Level Architecture

┌───────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ESP32 CONTROLLER (Firmware) │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Buttons │────►│ Debounce │────►│ Aggregate │────►│ GATT │────►│ BLE │ │
│ │ (GPIO) │ │ Filter │ │ State │ │ Service │ │ Radio │ │
│ └───────────┘ └───────────┘ └───────────┘ └───────────┘ └─────┬─────┘ │
│ │ │
└─────────────────────────────────────────────────────────────────────────────────┼──────────────────────┘
BLE GATT Notifications (4 bytes @ 100Hz)
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ RASPBERRY PI (Server) │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐ │
│ │ MAIN PROCESS (Async Runtime) │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Discovery │───►│ Session │──►│ Device │─►│ State │──►│ Report │ │ │
│ │ │ Service │ │ Supervisor │ │Session (xN) │ │ Reducer │ │ Builder │ │ │
│ │ │(BleakScanner│ │ (Lifecycle) │ │(Per-device) │ │ (Aggregate) │ │ (8-byte HID)│ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ └──────┬──────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────────┼───────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────────────────┼───────────────┐ │
│ │ HID OUTPUT WORKER PROCESS │ │ │
│ │ ▼ │ │
│ │ Queue.get() ──────────────────────────► Write to /dev/hidg0 │ │
│ └─────────────────────────────────────────────────────────────────────────────────────────────────┘ │
│ │ │
└───────────────────────────────────────────────────────────────────┼─────────────────────────────────────┘
USB HID Protocol
┌───────────────────┐
│ Host PC │
│ (USB Keyboard) │
└───────────────────┘

Component Summary

ESP32 Child Modules

Each child module is an independent input unit containing:

  • 8 action buttons – Configurable GPIO inputs
  • 4-way joystick – Digital directional input
  • System buttons – Select, Start, Pair
  • OLED display – Status information
  • Battery monitoring – ADC-based level sensing

The module runs FreeRTOS with tasks for:

  • GPIO polling and debouncing (10ms loop)
  • NimBLE host for BLE communication
  • Battery monitoring (2s interval)

Raspberry Pi Parent Hub

The parent hub aggregates all connected modules and presents them as a unified USB HID device:

ComponentPurpose
DiscoveryServiceBLE scanning for “NimBLE_GATT” devices
SessionSupervisorDevice connection lifecycle management
DeviceSessionPer-device BLE connection handling
StateReducerAggregate states from all devices
ReportBuilderBuild 8-byte USB HID keyboard reports
HID WorkerBlocking writes to /dev/hidg0

Configuration Layer

  • React Config App – 3D layout designer with Three.js
  • WebSerial API – Browser-based serial communication
  • USB Serial Device/dev/ttyGS0 on the Pi

Communication Protocols

ProtocolDirectionData Format
BLE GATTESP32 → RPi4-byte state notifications
USB SerialConfig App → RPiJSON-lines commands
Unix SocketConfig Service → RuntimeIPC updates
USB HIDRPi → PC8-byte keyboard reports

Next Steps