Initial Refleks Lite hardware and firmware release
This commit is contained in:
283
README.md
Normal file
283
README.md
Normal file
@@ -0,0 +1,283 @@
|
||||
# ERTOtech Refleks Lite Arcade Stick
|
||||
|
||||
This directory contains the hardware and firmware files for the ERTOtech
|
||||
Refleks Lite arcade stick project.
|
||||
|
||||
```text
|
||||
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 `START` during 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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```powershell
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```powershell
|
||||
# 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 0` writes only the XInput slot.
|
||||
- `-a 1` writes 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:
|
||||
|
||||
1. Start the board in DFU mode and open Zadig.
|
||||
2. Select `Options > List All Devices`.
|
||||
3. Select only `Refleks Lite DFU (1209:E667)`.
|
||||
4. Select `WinUSB` as the target driver and click `Install 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 App2
|
||||
- `STM32: Debug Arcade Stick XInput (ST-Link)`: XInput App1
|
||||
- `STM32: 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:
|
||||
|
||||
```text
|
||||
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 LOW` and DInput is `PA5 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.
|
||||
Reference in New Issue
Block a user