9.6 KiB
ERTOtech Refleks Lite Arcade Stick
This directory contains the hardware and firmware files for the ERTOtech Refleks Lite arcade stick project.
codespid/
├── ArcadeStick_hardware/ PCB and hardware design files
└── arcadestick_software/ STM32 firmware, bootloader, and USB code
Architecture
The board uses an STM32F103RBT6. Its 128 KB flash is divided into three regions:
| Region | Start address | Size | USB VID:PID |
|---|---|---|---|
| Bootloader / DFU | 0x08000000 |
24 KB | 1209:E667 |
| App1 / XInput | 0x08006000 |
52 KB | 1209:E668 |
| App2 / DInput | 0x08013000 |
52 KB | 1209:E669 |
The USB manufacturer string is ERTOtech.
Boot and firmware selection
The bootloader runs after every reset, reads the slide switch, and jumps to the selected application's vector table.
The current electrical switch logic is:
PA4 LOW,PA5 HIGH: run XInput App1.PA4 HIGH,PA5 LOW: run DInput App2.- If both inputs have the same level, the selection is invalid and DFU starts.
- Holding
STARTduring reset starts DFU regardless of the switch position. - If the selected application's stack pointer or reset vector is invalid, the bootloader remains in DFU mode.
When the switch is moved while an application is running, the new state must
remain stable for 50 ms. USB is then stopped, the firmware waits 100 ms, and
calls NVIC_SystemReset(). After reset, the bootloader starts the application
selected by the new switch position.
DInput application
DInput runs as a standard USB HID game pad. Its input report is 9 bytes:
Bytes 0..1: 11 buttons plus padding
Byte 2: 4-bit hat switch plus padding
Bytes 3..8: X, Y, Z, Rx, Ry, and Rz (unsigned 8-bit axes)
The neutral hat value is 8; directions use HID hat-switch values 0..7.
The six neutral axis values are 0x80. Physical buttons are active LOW and
use GPIO pull-ups. Button 11 is present in the descriptor but is not connected
to a physical input.
The DInput USB configuration contains three interfaces:
| Interface | Purpose | Endpoints | Behavior |
|---|---|---|---|
| IF0 | Gamepad HID | 0x81 IN |
Functional 9-byte input reports |
| IF1 | Setup HID | 0x82 IN, 0x02 OUT |
Compatibility stub |
| IF2 | Raw HID | 0x83 IN |
Compatibility stub |
The Setup and Raw report descriptors match the original device layout, but the original configuration protocol is not implemented. Unsupported control requests are stalled, unused IN endpoints remain at NAK, and Setup OUT data is accepted and discarded.
XInput application
XInput uses a vendor-specific Xbox 360 wired-controller interface:
Interface class : 0xFF
Interface subclass : 0x5D
Interface protocol : 0x01
IN endpoint : 0x81, interrupt, 64 bytes
OUT endpoint : 0x02, interrupt, 64 bytes
Input report : 20 bytes
The 20-byte input report carries the D-pad, Start, Back, A/B/X/Y, LB/RB, and
digital LT/RT values. LT and RT send 0xFF while pressed and 0x00 while
released. Eight-byte rumble packets received through the OUT endpoint are
parsed and the left/right motor values are stored. Unless motor outputs are
connected, those values remain software-only.
The XInput configuration also exposes Setup HID on IF1 (0x83 IN and 0x03
OUT) and Raw HID on IF2 (0x84 IN). These are compatibility stubs with the
same behavior described for DInput.
There are no Microsoft OS, compatible-ID, MSFT100, or WinUSB descriptors in
the XInput application. Windows currently binds IF0 to xusb22.inf by its
class/subclass/protocol match. Xbox console authentication is not implemented;
the target is Windows/PC.
GPIO mapping
All arcade inputs are active LOW and configured with pull-ups.
| Function | Pin |
|---|---|
| Up | PC0 |
| Down | PC1 |
| Right | PC2 |
| Left | PC3 |
| A | PC4 |
| B | PC5 |
| Y | PC6 |
| X | PC7 |
| RB | PC8 |
| RT | PC9 |
| LB | PC10 |
| LT | PC11 |
| Start | PC14 |
| Select / Back | PA2 |
| Switch input 1 | PA4 |
| Switch input 2 | PA5 |
| USB D- | PA11 |
| USB D+ | PA12 |
Building
The project uses the VS Code STM32Cube and CMake tools. In VS Code, press
Ctrl+Shift+B and run CMake: build to build the bootloader, both
applications, and the combined package.
The CMake presets can also be used from a terminal:
cube-cmake --preset Debug
cube-cmake --build --preset Debug
cube-cmake --preset Release
cube-cmake --build --preset Release
Main CMake targets:
| Target | Description |
|---|---|
arcadestick_bootloader |
USB DFU bootloader |
arcadestick_xinput |
App1 XInput firmware |
arcadestick |
App2 DInput firmware |
arcadestick_package |
Combines all three firmware images into one BIN/HEX |
Each firmware target produces .elf, .hex, and .bin files.
Initial programming
For a blank MCU, program the following combined image with an ST-Link:
arcadestick_software/build/Release/arcadestick_full.hex
This HEX contains the bootloader, XInput App1, and DInput App2 at their correct flash addresses. The combined BIN is exactly 128 KB:
arcadestick_software/build/Release/arcadestick_full.bin
Updating with USB DFU
To enter DFU, hold START while resetting the board. The USB device appears as
ERTOtech Refleks Lite DFU with VID:PID 1209:E667.
The bootloader uses standard DFU 1.1 and does not use DfuSe address commands. Select the destination firmware with the alternate interface number:
# Update XInput App1
dfu-util -d 1209:e667 -a 0 `
-D arcadestick_software/build/Release/arcadestick_xinput.bin
# Update DInput App2
dfu-util -d 1209:e667 -a 1 `
-D arcadestick_software/build/Release/arcadestick.bin
-a 0writes only the XInput slot.-a 1writes only the DInput slot.- The bootloader region cannot be written through DFU.
- Data is received in 1024-byte blocks. The corresponding 1 KB flash page is erased and programmed as half-words.
- A zero-length DFU packet at the end of the download completes the update. The bootloader resets after approximately 100 ms.
- The slide switch's current position, not the downloaded file, determines which application runs after reset.
Windows driver setup
This DFU bootloader does not expose Microsoft OS or automatic WinUSB
descriptors. On each Windows computer, WinUSB must therefore be installed once
for Refleks Lite DFU (1209:E667) before dfu-util can access the device.
Use Zadig as follows:
- Start the board in DFU mode and open Zadig.
- Select
Options > List All Devices. - Select only
Refleks Lite DFU (1209:E667). - Select
WinUSBas the target driver and clickInstall Driver.
Do not replace the drivers of the XInput (1209:E668), DInput (1209:E669),
ST-Link, or any other USB device. The Zadig operation is required only once per
Windows computer unless the driver is later removed. dfu-util must also be
installed and available in PATH.
If an update is interrupted, hold START during reset to re-enter DFU. This
simple bootloader does not provide atomic or power-fail-safe updates; do not
remove power while an update is in progress.
Debugging with VS Code
The Run and Debug list contains:
STM32: Debug Arcade Stick (ST-Link): DInput App2STM32: Debug Arcade Stick XInput (ST-Link): XInput App1STM32: Debug Arcade Stick Bootloader (ST-Link): bootloader
The applications no longer begin at the start of flash. The bootloader must
already be programmed before debugging App1 or App2. While debugging the
bootloader, hold START to prevent it from jumping immediately to an app and
to keep execution in main().
Place XInput breakpoints in XInput_AppProcess() in
Core/Src/xinput_app.c. Place DInput breakpoints in DInput_AppProcess() in
Core/Src/dinput_app.c.
CubeMX code generation
The main CubeMX project file is:
arcadestick_software/arcadestick.ioc
The custom DInput, XInput, and DFU classes are stored in project-owned source
files. The root CMakeLists.txt replaces CubeMX's single-interface HID
application source list with the custom composite DInput sources. No
post-generation repair script is required.
Important source files
| File | Purpose |
|---|---|
Core/Src/bootloader_main.c |
Boot selection, app validation, and jump |
Core/Src/main.c |
Shared app startup and switch reset control |
Core/Src/xinput_app.c |
XInput button/report mapping |
Core/Src/dinput_app.c |
DInput button/report mapping |
USB_DEVICE/App/usbd_xinput.c |
Composite XInput USB class and rumble OUT handling |
USB_DEVICE/App/usbd_dinput.c |
Composite DInput USB class |
USB_DEVICE/App/usbd_dfu_bootloader.c |
DFU state machine and flash programming |
STM32F103xx_FLASH.ld |
Parameterized flash/RAM linker layout |
CMakeLists.txt |
Bootloader, App1, App2, and package targets |
tools/package_firmware.ps1 |
Creates the combined 128 KB firmware package |
Known limitations
- Do not distribute products with these PID values until they are formally assigned by pid.codes.
- Xbox console authentication/security is not implemented.
- The Setup and Raw HID interfaces are compatibility stubs; the original device configuration protocol is not implemented.
- The XInput application does not expose Microsoft OS or compatible-ID descriptors.
- DFU has no redundant image or rollback protection against power loss.
- Do not confuse the switch signal names with the observed LOW pins: on the
current board, XInput is
PA4 LOWand DInput isPA5 LOW.
Licensing
- Project-authored firmware: MIT License
- Hardware design sources: CERN-OHL-P-2.0
- STM32 HAL, CMSIS, and other third-party components: their respective upstream licenses
See the root LICENSE file and the component-specific license files for the
complete terms.