All of the SDVX Controller’s inputs and outputs connect to an STM32F401 microcontroller running on a BlackPill v3.0 development board. The seven buttons land on GPIOA with internal pull-up resistors enabled, the two LPD3806 rotary encoders feed into dedicated hardware timer inputs (TIM3 and TIM4), and the WS2812B LED strip is driven from a single GPIO data line on PB0. Understanding these assignments is essential both for assembling the controller and for any future firmware modifications.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/MrJefter/sdvx-controller/llms.txt
Use this file to discover all available pages before exploring further.
Complete Pin Assignment Table
| Signal | MCU Pin | GPIO Port | Timer / Mode | Notes |
|---|---|---|---|---|
| BTN1 (BT-A) | PA5 | GPIOA | EXTI, RISING_FALLING | Internal PULLUP; active-low when pressed |
| BTN2 (BT-B) | PA3 | GPIOA | EXTI, RISING_FALLING | Internal PULLUP; active-low when pressed |
| BTN3 (BT-C) | PA2 | GPIOA | EXTI, RISING_FALLING | Internal PULLUP; active-low when pressed |
| BTN4 (BT-D) | PA1 | GPIOA | EXTI, RISING_FALLING | Internal PULLUP; active-low when pressed |
| FX-L | PA4 | GPIOA | EXTI, RISING_FALLING | Internal PULLUP; active-low when pressed |
| FX-R | PA9 | GPIOA | EXTI, RISING_FALLING | Internal PULLUP; active-low when pressed |
| START | PA10 | GPIOA | EXTI, RISING_FALLING | Internal PULLUP; also triggers DFU if held ≥ 5 s |
| VOL-L Channel A (KNOBLA) | PA6 | GPIOA | TIM3 CH1 (Encoder mode) | — |
| VOL-L Channel B (KNOBLB) | PA7 | GPIOA | TIM3 CH2 (Encoder mode) | — |
| VOL-R Channel A (KNOBRA) | PB6 | GPIOB | TIM4 CH1 (Encoder mode) | — |
| VOL-R Channel B (KNOBRB) | PB7 | GPIOB | TIM4 CH2 (Encoder mode) | — |
| WS2812B Data | PB0 | GPIOB | GPIO Output (DMA/PWM) | 12 LEDs in series |
| BOOT0 Control | PA15 | GPIOA | GPIO Output PP | Driven HIGH before reset to enter DFU |
Buttons
Every button shares the same wiring pattern:- One terminal of the switch connects to the designated GPIO pin listed in the table above.
- Other terminal of the switch connects to GND.
GPIO_PULLUP). This means the pin reads HIGH (logic 1) at rest and is pulled LOW (logic 0) when the button is pressed and shorts the pin to GND.
Buttons use active-low logic. A pressed button reads
GPIO_PIN_RESET (0 V / logical 0) because the internal pull-up is overcome by the direct GND connection through the switch. The firmware inverts this internally when building the HID report, so button presses are correctly reported as “pressed” to the host PC.GPIO_MODE_IT_RISING_FALLING, meaning the STM32 generates an interrupt on both the press (falling edge) and release (rising edge). Software debouncing with a 3 ms lockout window prevents false triggers from switch bounce.
Verified button GPIO definitions (from main.h)
Rotary Encoders (VOL-L and VOL-R)
The two LPD3806 incremental encoders are connected to the STM32’s hardware timer encoder interface. The hardware counts pulses automatically in the background with no CPU overhead.| Encoder | Timer | Channel A | Channel B |
|---|---|---|---|
| VOL-L | TIM3 | PA6 (KNOBLA) | PA7 (KNOBLB) |
| VOL-R | TIM4 | PB6 (KNOBRA) | PB7 (KNOBRB) |
- +5V — connect to the 5 V rail (BlackPill 5V pin or USB power)
- GND — connect to the common GND
- A (Channel A) — connect to the Channel A pin listed in the table above
- B (Channel B) — connect to the Channel B pin listed in the table above
- Shield/GND (if present) — connect to GND
0xFFFF). The firmware reads the counter delta each main loop iteration, applies exponential smoothing (α = 0.15), and maps the result to the HID joystick axes reported to the PC.
Encoder GPIO definitions (from main.h)
WS2812B LED Strip
The addressable RGB LED strip uses a single data line driven by the STM32 via DMA-backed PWM output on PB0 (WS2812B_PINS = GPIO_PIN_0, WS2812B_PORT = GPIOB).
The strip contains 12 LEDs in series (WS2812B_NUMBER_OF_LEDS = 12).
Connect the LED strip as follows:
| Strip wire | Connect to |
|---|---|
| DIN (Data In) | PB0 on the BlackPill / PCB data connector |
| +5V | 5 V power rail (USB 5 V or dedicated supply) |
| GND | Common GND |
WS2812B LEDs are optional — the controller operates fully without them. If you choose not to install the LED strip, simply leave the data connector unconnected. The firmware drives PB0 regardless, but with no LEDs attached there is no functional effect.
DFU Mode and BOOT0 Control (PA15)
The firmware includes an optional mechanism to enter USB DFU (Device Firmware Upgrade) bootloader mode without needing an ST-Link or physical BOOT0 button press. When the START button is held for 5 seconds, the firmware:- Drives PA15 HIGH (via
BOOT0_PORT = GPIOA,BOOT0_PIN = GPIO_PIN_15) - Issues a system reset
GPIO_MODE_OUTPUT_PP) and held LOW at all other times.
Optional 150 nF capacitor modification
To make the BOOT0 control work reliably, the README describes an optional hardware modification to the BlackPill board: add a 150 nF ceramic capacitor between PA15 and the BlackPill’s BOOT0 pin. This capacitor filters the reset glitch so that the STM32 samples BOOT0 as HIGH before the reset completes. Without this capacitor, the DFU entry trick may be unreliable on some BlackPill revisions. The capacitor bridges the PA15 output pad on the BlackPill header to the BOOT0 pin on the board itself — refer to the assembly photos in the repository for the exact placement.Wiring Summary
Buttons (×7)
One switch terminal to the assigned GPIO pin (PA1–PA10), the other to GND. No external resistors needed — internal PULLUP is enabled in firmware.
Encoders (×2)
VOL-L A/B → PA6/PA7 (TIM3). VOL-R A/B → PB6/PB7 (TIM4). Power encoder from the 5 V rail; share common GND.
LED Strip
Data → PB0. Power from 5 V rail. GND to common GND. 12 × WS2812B LEDs in series.
DFU / BOOT0
PA15 drives BOOT0 HIGH on a 5-second START hold. Optional 150 nF capacitor improves reliability.