I2C, SPI, UART configuration system with pin validation, address selection, and device-agnostic JSON schema.
Last updated: August 15, 2026
{
"I2C0": {
"SDA": [0, 4, 8, 12, 16, 20],
"SCL": [1, 5, 9, 13, 17, 21],
"min_address": 0,
"max_address": 127,
"default_pins": {"SDA": 4, "SCL": 5},
"common_addresses": [0x50, 0x51, 0x68, 0x69]
}
}{
"SPI0": {
"SCK": [2, 6, 18, 22],
"TX": [3, 7, 19, 23],
"RX": [0, 4, 16, 20],
"CS": [1, 5, 17, 21],
"addresses": [0, 1, 2, 3],
"max_address": 3,
"min_address": 0,
"default_pins": {"SCK": 6, "TX": 7, "RX": 4, "CS": 5}
}
}{
"UART0": {
"TX": [0, 12, 16],
"RX": [1, 13, 17],
"CTS": [2, 14, 18],
"RTS": [3, 15, 19],
"default_pins": {"TX": 0, "RX": 1}
}
}Updated request schema for configuring multi-pin peripherals:
class PinConfigRequest(BaseModel):
gpio: int
peripheral: str # "GPIO", "I2C", "SPI", "UART", "PWM", "ADC"
peripheral_instance: Optional[str] # e.g. "I2C0", "SPI1", "UART0"
mode: Optional[int] = None # for GPIO only
baudrate: Optional[int] = None # for SPI/I2C/UART
device_address: Optional[int] = None # for I2C (0x00-0x7F) or SPI (0-3)
extra_pins: Optional[dict] = None # {"SCL": 5, "SDA": 4} or {"MOSI": 7, ...}
label: Optional[str] = ""{
"gpio": 4,
"peripheral": "I2C",
"peripheral_instance": "I2C0",
"device_address": 0x68,
"extra_pins": {
"SDA": 4,
"SCL": 5
},
"label": "MPU6050 IMU"
}{
"gpio": 6,
"peripheral": "SPI",
"peripheral_instance": "SPI0",
"device_address": 0,
"baudrate": 1000000,
"extra_pins": {
"SCK": 6,
"MOSI": 7,
"MISO": 4,
"CS": 5
},
"label": "SPI Flash"
}{
"gpio": 0,
"peripheral": "UART",
"peripheral_instance": "UART0",
"baudrate": 9600,
"extra_pins": {
"TX": 0,
"RX": 1
},
"label": "GPS Module"
}Returns available peripheral instances grouped by type:
{
"I2C": ["I2C0", "I2C1"],
"SPI": ["SPI0", "SPI1"],
"UART": ["UART0", "UART1"]
}Request valid pins and defaults for a peripheral instance:
// Request
{
"peripheral": "I2C",
"peripheral_instance": "I2C0"
}
// Response
{
"instance": "I2C0",
"available_pins": {
"SDA": [0, 4, 8, 12, 16, 20],
"SCL": [1, 5, 9, 13, 17, 21]
},
"default_pins": {"SDA": 4, "SCL": 5},
"address_range": {"min": 0, "max": 127},
"common_addresses": [0x50, 0x51, 0x68, 0x69]
}Real-time validation of pin configuration:
// Request
{
"peripheral": "I2C",
"peripheral_instance": "I2C0",
"pins": {"SDA": 4, "SCL": 5},
"device_address": 0x68
}
// Success
{"ok": true}
// Error
{
"ok": false,
"error": "GPIO 99 is not valid for I2C0 SDA. Valid: [0, 4, 8, 12, 16, 20]"
}| Method | Description |
|---|---|
| validate_i2c_pins(instance, sda, scl, address) | Validates I2C pin combo and 7-bit address |
| validate_spi_pins(instance, sck, mosi, miso, cs, address) | Validates SPI pin combo and chip-select |
| validate_uart_pins(instance, tx, rx, cts, rts) | Validates UART pin combo |
| get_default_pins(instance) | Returns recommended pin combination |
| suggest_valid_pins(peripheral, instance, primary_pin) | Suggests compatible pins for a primary pin |
| get_common_addresses(instance) | Returns frequently-used I2C addresses |
User selects "I2C" peripheral
↓
[Load available instances] GET /api/io/peripheral-instances
↓
User picks "I2C0"
↓
[Load pin hints] POST /api/io/peripheral-pin-hints
↓
Populate dropdowns with valid pins (SDA, SCL)
Show default pins highlighted
Show common I2C addresses in preset list
↓
User selects pins + address
↓
[Real-time validation] POST /api/io/validate-peripheral-config
↓
Show validation result (error or ✓)
↓
User submits config
↓
[Backend validates again] POST /api/io/configureChanges are backward compatible. Old code continues to work while new fields are optional.
PinConfigRequest(
gpio=4,
peripheral="I2C",
extra_pins={"SCL": 5, "SDA": 4}
)PinConfigRequest(
gpio=4,
peripheral="I2C",
peripheral_instance="I2C0",
device_address=0x68,
extra_pins={"SCL": 5, "SDA": 4}
)