Skip to content
binho.io (opens in a new tab)Contact Us

Binho Supernova: Protocols

How I3C, I2C, SPI, UART and GPIO work on the Binho Supernova, with large transfers and code examples.

ParameterValue
SpecificationMIPI I3C Basic v1.0, v1.1.1, v1.2
RolesController or target, one at a time. No Secondary Controller role.
ModesSDR, HDR-DDR (controller and target). HDR-TSP, HDR-TSL, HDR-BT and multi-lane are not supported.
Voltage0.8 V to 1.2 V (LV port), 1.2 V to 3.3 V (HV port)
Push-pull clock100 kHz to 12.5 MHz: 100 kHz, 400 kHz, 1 MHz, 2.5, 3.125, 5, 6.25, 7.5, 10 and 12.5 MHz, several with a choice of duty cycle
Open-drain clock100 kHz, 400 kHz, 1 MHz, 2 MHz, 4.17 MHz
Controller featuresDynamic address assignment (ENTDAA, SETDASA, SETAASA), user-seeded device table, private SDR read/write, HDR-DDR read/write, CCCs, In-Band Interrupts, Hot-Join, group addressing, repeated-start chaining of transfers
Target featuresPrivate read/write and HDR-DDR. Configurable PID, BCR, DCR and static address. 1024-byte memory as 1024 × 8-bit, 512 × 16-bit or 256 × 32-bit registers, with wrap-around. IBI and Hot-Join as a target are not yet available.
Targets on the busUp to 11 at once (the controller’s target table). Adding a 12th returns FW_FULL_TARGET_DEVICES_TABLE (0x0601).
Max transfer32,767 bytes per SDR frame, including the register address on a write. HDR-DDR: 1024 bytes per transfer.
Pull-upBuilt-in 1 kΩ SDA pull-up, switched by the controller in open-drain phases. SCL has no on-board pull-up.

Legacy I2C and SMBus devices can share the bus with I3C targets. Both I3C ports run legacy I2C transfers. Firmware 4.6.0 and later adds three features on the I3C HV port for SMBus and MCTP targets, for example the NVMe-MI SMBus-to-I3C detection flow:

FeatureRangeNotes
Clock stretching10 kHz to 1 MHzLegacy I2C transfers wait while the target holds SCL low. A stretch longer than 35 ms (SMBus tTIMEOUT) returns BUS_TIMEOUT. The rate is measured on the wire at each enable and depends on the pull-up and bus capacitance; the reply carries the rate in effect (a 1 MHz request ran at 290–746 kHz on our benches). I3C SDR, HDR and CCC commands are refused with I3C_I2C_CLOCK_STRETCHING_ACTIVE until it is turned off.
Hold SCL low1 µs to 1 sSMBus interface reset (T2wrst). SDA is released. Returns the measured hold.
SDA pull-upAUTO, OFF, ONControls the on-board 1 kΩ SDA pull-up while clock stretching is on. AUTO is the default. SCL has no on-board pull-up: fit an external one.

PyCosmicSDK 1.8.0 (upcoming) adds SMBus block read/write, PEC and Quick Command on the I3C port.

For a bus of I2C devices only, use the Dedicated I2C or Multifunction port. It supports the full I2C feature set below.

ParameterValue
RolesController and target (target needs firmware 4.5 or later)
Voltage1.2 V to 3.3 V (Multifunction domain)
Clock100 kHz to 1 MHz rated. See frequency rules below.
Duty cycleSCL high time 20 % to 80 % in 10 % steps (firmware 4.6.0 or later)
Addressing7-bit. A bus scan also reports 10-bit addresses; the SDK transfer calls take a 7-bit address.
TransactionsWrite, read, write-then-read with a register address, non-stop (repeated start) chaining of reads and writes, bus scan
Clock stretchingYes
Pull-upsSoftware-set: off, 150, 220, 330, 470, 680 Ω, 1, 1.5, 2.2, 3.3, 4.7, 10 kΩ.
Target emulationMemory (8- or 16-bit register addressing, auto-increment), EEPROM (24Cxx-style: page size, write and erase busy time, NACK or clock-stretch while busy, write-protect region), Register map (per-region RW, RO, WO, read-to-clear, write-1-to-clear)
Max transfer32,768 bytes

Frequency rules

  • Duty cycle set (firmware 4.6.0 or later): the clock is exact, never above the request and at most 0.29 % below it from 1 kHz to 1.2 MHz. 550 kHz runs at 549.8 kHz.
  • Default timing, firmware 4.6.2 and later: the clock never runs above the request and rounds down (550 → 500 kHz, 858 → 800 kHz). Requests below 11 Hz or above 3 MHz are refused with INVALID_PARAMETER; 3.4 MHz is refused.
  • Default timing, firmware 4.6.1 and earlier: some requests round up (550 → 600 kHz), and some run far below the request (858 kHz runs at about 273 kHz). A request above 3 MHz or below 11 Hz answers success and the bus runs at about 11 Hz. On 4.5.0 and earlier a 3.4 MHz request could make the adapter re-enumerate. Set a duty cycle to get an exact clock, and stay within 100 kHz to 1 MHz.
ParameterControllerPeripheral
Voltage1.2 V to 3.3 V1.2 V to 3.3 V
Clock2.29 kHz to 37.5 MHz10 kHz to 16 MHz
Modes0, 1, 2, 30, 1, 2, 3
Bit orderMSB-first or LSB-firstMSB-first or LSB-first
Chip selects4, each active-high or active-lowCS0
Max transfer32,768 bytes32,768 bytes
Emulation modelsn/aMemory (full duplex), 25-series Flash (READ, FAST_READ, PAGE_PROGRAM, RDSR, WREN, WRDI, RDID; configurable JEDEC ID, address width, page size, program time), Register map

The SPI peripheral role needs firmware 4.5 or later and is not available on hardware revision B.

Clock rule (firmware 4.6.0 or later): SCK is 150 MHz divided by an integer, and a request rounds down to the next step: 150, 75, 50, 37.5, 30, 25 MHz and so on. 29 MHz runs at 25 MHz. A request below 2.29 kHz is refused with INVALID_PARAMETER and the bus keeps its clock. Firmware 4.5.1 and earlier could round up.

ParameterValue
Voltage1.2 V to 3.3 V
Baud rate600 baud to 2 Mbaud
ParityNone, even, odd
Data bits7 or 8
Stop bits1 or 2
Flow controlNone or RTS/CTS

With firmware 4.4 or later the UART is also a USB virtual COM port, usable from any serial terminal or from the Mission Control 3 Serial Terminal while the other protocols run over HID.

ParameterValue
Pins6 (GPIO 1 to GPIO 6 on the Multifunction port)
ModesDigital input, digital output (with a chosen initial level, firmware 4.4 or later)
InterruptsRising, falling or both edges. Notifications report the edge and pin level.
VoltageRev. C: 1.2 V to 3.3 V, shared with I2C, SPI and UART
PWMNot yet available

Through the USB HID interface a transfer carries up to 1024 bytes. With firmware 4.5 or later the Supernova also moves I2C, SPI and I3C payloads over a second USB interface (bulk endpoints):

ProtocolMax per transfer
I2C32,768 bytes
SPI32,768 bytes
I3C SDR32,767 bytes per frame, register address included
I3C HDR-DDR1024 bytes

PyCosmicSDK and CosmicSDK pick the bulk route automatically when it is available. A payload over the limit is refused, never split. See the PyCosmicSDK bulk guide.

The examples use PyCosmicSDK: pip install pycosmicsdk (Python 3.10 to 3.14). More in the PyCosmicSDK guides and on the PyCosmicSDK page.

I2C scan and read

from pycosmicsdk import Device, I2cBus, I2cPullUp
with Device.open() as dev:
i2c = dev.i2c(bus=I2cBus.A)
i2c.set_voltage(voltage_mv=3300) # set the rail before the bus
i2c.bring_up(frequency_hz=400_000, pull_up=I2cPullUp.KOHM_2_2)
found = i2c.scan()
print([hex(a) for a in sorted(found.addresses_7bit)])
# Read 16 bytes from register 0x00 of an EEPROM at 0x50
data = i2c.read(0x50, 16, subaddress=bytes([0x00]))
print(data.hex())

I3C DAA, CCC, private transfer

from pycosmicsdk import (
Device, DeviceModel, I2cOpenDrainRate, I3cOpenDrainRate, I3cPushPullRate,
)
with Device.open(model=DeviceModel.SUPERNOVA) as dev:
i3c = dev.i3c()
i3c.set_voltage(voltage_mv=1800) # 1200-3300 mV selects the HV port
i3c.bring_up(
push_pull_rate=I3cPushPullRate.PUSH_PULL_5_MHZ_DC_50,
open_drain_rate=I3cOpenDrainRate.OPEN_DRAIN_400_KHZ,
i2c_open_drain_rate=I2cOpenDrainRate.FAST_MODE,
)
targets = i3c.init_bus() # RSTDAA + ENTDAA
for t in targets:
print(hex(t.dynamic_address), t.pid.hex(), hex(t.bcr), hex(t.dcr))
addr = targets[0].dynamic_address
print("GETPID:", i3c.ccc.getpid(addr).hex())
i3c.sdr_write(addr, bytes([0xAA, 0x55]), subaddress=bytes([0x10]))
print(i3c.sdr_read(addr, 2, subaddress=bytes([0x10])).hex())

SMBus target with clock stretching

from pycosmicsdk import (
Device, DeviceModel, I2cOpenDrainRate, I3cOpenDrainRate, I3cPushPullRate,
)
# Firmware 4.6.0 or later, I3C HV port, external pull-up on SCL
with Device.open(model=DeviceModel.SUPERNOVA) as dev:
i3c = dev.i3c()
i3c.set_voltage(voltage_mv=3300)
i3c.bring_up(
push_pull_rate=I3cPushPullRate.PUSH_PULL_5_MHZ_DC_50,
open_drain_rate=I3cOpenDrainRate.OPEN_DRAIN_400_KHZ,
i2c_open_drain_rate=I2cOpenDrainRate.STANDARD_MODE,
)
i3c.hold_scl_low(35_000) # SMBus interface reset, 35 ms
state = i3c.enable_i2c_clock_stretching(100_000)
print("SCL in effect:", state.frequency_hz, "Hz")
try:
data = i3c.legacy_i2c_read(0x1D, 4, subaddress=bytes([0x00]))
print(data.hex())
finally:
i3c.disable_i2c_clock_stretching() # I3C commands are refused until off