Skip to main content

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.

The SDVX Controller firmware runs on an STM32F401CEU6 “BlackPill” v3.0 board. Every peripheral — buttons, rotary encoders, the WS2812B LED strip, and the DFU bootloader-control line — is assigned to a specific GPIO pin. This page is the authoritative reference for those assignments, drawn directly from main.h and the peripheral initialisation code in main.c.
All button inputs are configured with the STM32’s internal PULLUP resistor enabled. This means each GPIO pin sits at 3.3 V when the button is open, and is pulled to GND when the button is pressed — active-low logic. Do not add an external pull-down resistor to any of these pins.

Full pin assignment table

PinPortFirmware symbolFunctionNotes
PA1GPIOABTN4_PinBT-D buttonGPIO_PULLUP, EXTI1, active-low
PA2GPIOABTN3_PinBT-C buttonGPIO_PULLUP, EXTI2, active-low
PA3GPIOABTN2_PinBT-B buttonGPIO_PULLUP, EXTI3, active-low
PA4GPIOAFXL_PinFX-L buttonGPIO_PULLUP, EXTI4, active-low
PA5GPIOABTN1_PinBT-A buttonGPIO_PULLUP, EXTI9_5, active-low
PA6GPIOAKNOBLA_PinVOL-L encoder — channel ATIM3_CH1, quadrature input
PA7GPIOAKNOBLB_PinVOL-L encoder — channel BTIM3_CH2, quadrature input
PA9GPIOAFXR_PinFX-R buttonGPIO_PULLUP, EXTI9_5, active-low
PA10GPIOASTART_PinSTART button / DFU triggerGPIO_PULLUP, EXTI15_10, active-low; hold 5 s to enter bootloader
PA15GPIOABOOT0_PINBOOT0 control outputPush-pull output; driven HIGH before system reset to select DFU mode
PB0GPIOB(ws2812b.h)WS2812B LED strip data out12 LEDs, DMA-driven PWM via TIM1
PB6GPIOBKNOBRA_PinVOL-R encoder — channel ATIM4_CH1, quadrature input
PB7GPIOBKNOBRB_PinVOL-R encoder — channel BTIM4_CH2, quadrature input

Timer configuration

Both rotary encoders are read in hardware using the STM32’s dedicated timer encoder interface. The firmware configures them identically.

TIM3 — VOL-L (Left knob)

ParameterValue
PinsPA6 (CH1 / A), PA7 (CH2 / B)
Encoder modeTIM_ENCODERMODE_TI12
Period (ARR)0xFFFF (65 535)
Prescaler0 (no division)
IC polarityRising on both channels
IC filter5

TIM4 — VOL-R (Right knob)

ParameterValue
PinsPB6 (CH1 / A), PB7 (CH2 / B)
Encoder modeTIM_ENCODERMODE_TI12
Period (ARR)0xFFFF (65 535)
Prescaler0 (no division)
IC polarityRising on both channels
IC filter5
Both timers use TIM_ENCODERMODE_TI12, which counts edges on both quadrature channels, giving four counts per physical detent on a standard encoder.

EXTI interrupt configuration

All button EXTI lines share the same priority settings, set during MX_GPIO_Init():
EXTI lineIRQ handlerPriority (preempt, sub)
EXTI1EXTI1_IRQn(0, 0)
EXTI2EXTI2_IRQn(0, 0)
EXTI3EXTI3_IRQn(0, 0)
EXTI4EXTI4_IRQn(0, 0)
EXTI9_5EXTI9_5_IRQn(0, 0)
EXTI15_10EXTI15_10_IRQn(0, 0)
Each EXTI line is configured for GPIO_MODE_IT_RISING_FALLING so the callback fires on both press and release edges. Software debouncing (3 ms lockout window) is applied inside HAL_GPIO_EXTI_Callback().

DFU bootloader entry

PA15 is a push-pull output that controls the BlackPill’s BOOT0 signal. When the START button (PA10) is held for 5 000 ms, GoToBootloader() drives PA15 HIGH and calls NVIC_SystemReset(). The MCU boots into the built-in USB DFU bootloader on the next power cycle.
This mechanism requires a 150 nF ceramic capacitor modification on the BlackPill board (see the hardware README). Without the capacitor, PA15 cannot reach BOOT0 in time before the reset cycle completes. If the modification has not been made, use the physical BOOT0 button on the BlackPill instead.

Build docs developers (and LLMs) love