> Complete documentation index: [llms.txt](/llms.txt). Markdown versions of all pages are available by appending `.md` to page URLs.

# PyCosmicSDK

> Python SDK for the Binho Supernova and Pulsar host adapters and the Binho Atira debug probe

## Summary

`pycosmicsdk` is the Python SDK for the **Binho Supernova** and **Binho Pulsar** host adapters and the **Binho Atira** debug probe. One package covers all three and every protocol they offer. The host adapters use a blocking API (`Device`) and an `asyncio` API (`AsyncDevice`); the Atira uses `DebugProbe` and `AsyncDebugProbe`.

It replaces the older per-product packages (`BinhoSupernova`, `SupernovaController` and `BinhoPulsar`) and ships drop-in compatibility layers for them, so existing scripts keep working during the move. See [Migrating to PyCosmicSDK](/software/pycosmicsdk/migrating-to-pycosmicsdk/).

| Protocol | What it can do                                       | Supernova                              | Pulsar          | Atira                                  |
| -------- | ----------------------------------------------------- | -------------------------------------- | --------------- | -------------------------------------- |
| I2C      | Controller (write, read, bus scan) and target mode    | Bus A                                  | Buses A and B   | No                                     |
| I3C      | Controller, Common Command Codes (CCCs), target mode  | Yes                                    | No               | No                                     |
| SPI      | Controller and target mode                            | Controller; target mode not on rev B   | Yes             | Controller, with SPI flash programming |
| UART     | Send, query and receive                               | Yes                                    | Yes             | Bridge port                            |
| GPIO     | Digital I/O and interrupts                            | Yes                                    | Yes             | No                                     |

The Atira is a debug probe. Besides SPI and the UART bridge, `DebugProbe` covers target power and SWD debug. It needs PyCosmicSDK 1.7.0 or newer. See [Binho Atira](/hardware/atira/) and the [debug probe guide](https://binhollc.github.io/pycosmicsdk/guides/debugprobe.html).

Large transfers travel over a second USB pipe instead of the ordinary 1024-byte limit: up to 32,768 bytes on a Supernova (32,767 for I3C) and 16,384 bytes on a Pulsar. The SDK asks the adapter for its limit, so the limit never needs hard-coding. See [Large transfers](https://binhollc.github.io/pycosmicsdk/guides/bulk.html).

## Prerequisites

* Python 3.10 to 3.14.
* One of: Windows (x64), macOS on Apple Silicon, or Linux (x86\_64). Other platforms, such as Intel Macs and Linux on ARM, have no package yet.
* A Binho Supernova or Pulsar running **firmware 4.x**, or a Binho Atira running **Atira firmware 1.0** or newer. Firmware 3.x cannot be reached by this package; see [Updating Firmware](/guides/firmware-updates/).
* On **Linux**, allow the current user to access the adapter once: [Solving USB Connection Issues on Linux](/support/troubleshooting/solving-usb-connection-issues-on-linux/). Windows and macOS need no driver install.

:::caution
Use the latest firmware. Some features need a minimum version:

| Feature | Minimum firmware |
| --- | --- |
| Large transfers and target mode | 4.5.0 |
| I2C SCL duty cycle, I2C clock stretching on the I3C port | 4.6.0 |
| An SDR command after an HDR-DDR read | 4.6.1 |

:::

:::note
Install into a virtual environment (`python -m venv .venv`) so the SDK does not conflict with other packages.

:::

## Installation

```sh
pip install pycosmicsdk
```

The package includes everything it needs, the native USB library included, so there is nothing else to install.

[https://pypi.org/project/pycosmicsdk/](https://pypi.org/project/pycosmicsdk/)

## Check the Adapter First

`list_devices()` reads each connected adapter's model, serial number and firmware version straight from USB, without opening it:

```python
from pycosmicsdk import list_devices

for found in list_devices():
    print(found.model.name, found.serial_number, "firmware", found.fw_version)
```

* A version like `4.6.1` is ready to use.
* `3.x.x` means firmware 3.x: update the firmware before using this package.
* `bootloader` means the adapter is waiting in its bootloader instead of running firmware.

Opening an adapter whose firmware is too old raises an SDK error that says so, instead of timing out.

## Getting Started

This example opens the first adapter it finds, brings up I2C bus A at 400 kHz, scans the bus, and writes and reads back three bytes of an I2C EEPROM at address `0x50`:

```python
import time

from pycosmicsdk import Device, I2cBus, I2cPullUp, list_devices

# List every connected adapter. This only reads USB information; it opens nothing.
for found in list_devices():
    print(found.model.name, found.serial_number, "firmware", found.fw_version)

# Open the first adapter found (or pass serial="..." to pick one).
with Device.open() as dev:
    i2c = dev.i2c(bus=I2cBus.A)
    i2c.set_voltage(voltage_mv=3300)                          # target voltage first
    i2c.bring_up(frequency_hz=400_000, pull_up=I2cPullUp.KOHM_2_2)

    print("Devices on the bus:", [hex(a) for a in i2c.scan().addresses_7bit])

    i2c.write(0x50, b"\x01\x02\x03", subaddress=b"\x00\x10")  # 3 bytes at 0x0010
    time.sleep(0.01)  # an EEPROM ignores its address while it finishes the write
    print("Read back:", i2c.read(0x50, 3, subaddress=b"\x00\x10").hex())
```

* `Device.open()` also accepts `serial="..."`, `model=...` or `path="..."` when more than one adapter is connected.
* `bring_up()` can be run again safely: if the bus is already up, it applies the new settings instead of failing.
* The other protocols follow the same pattern: `dev.i3c()`, `dev.spi()`, `dev.uart()`, `dev.gpio()`, and `dev.i2c_target()`, `dev.spi_target()` and `dev.i3c_target()` for target mode.

## Using `asyncio`

Every class has an `asyncio` twin with the same methods. Use `AsyncDevice` in place of `Device` and `await` each call:

```python
import asyncio

from pycosmicsdk import AsyncDevice, I2cBus, I2cPullUp


async def main() -> None:
    async with AsyncDevice.open() as dev:
        i2c = dev.i2c(bus=I2cBus.A)
        await i2c.set_voltage(voltage_mv=3300)
        await i2c.bring_up(frequency_hz=400_000, pull_up=I2cPullUp.KOHM_2_2)
        print([hex(a) for a in (await i2c.scan()).addresses_7bit])


asyncio.run(main())
```

## When Something Fails

Every error the SDK raises derives from `CosmicError` and carries the `status_code` the adapter or the SDK reported. Catch the subclass that can be acted on:

| Error | Meaning |
| --- | --- |
| `ValidationError` | The call was rejected before anything was sent to the adapter. |
| `CapabilityError` | This adapter model or hardware revision cannot do it. Nothing was sent. |
| `FirmwareError` (`I2cError`, `I3cError`, `SpiError`, …) | The adapter refused the command. `exc.status_code` says why, for example `FW_I2C_NACK_ADDRESS`. |
| `CosmicTimeoutError` | No answer in time. Also caught by `except TimeoutError`. |

The [errors reference](https://binhollc.github.io/pycosmicsdk/reference/errors.html) lists every error and status code.

## Examples

The SDK comes with more than 50 runnable example scripts, one folder per protocol, for both the blocking and the `asyncio` API. [PyCosmicSDK Examples](/software/pycosmicsdk/examples/) has the download link, how to run them, and copy-paste snippets for I2C, SPI, I3C, UART and GPIO.

## Documentation

The full documentation is at [binhollc.github.io/pycosmicsdk](https://binhollc.github.io/pycosmicsdk/). Start with the guide for the protocol:

| Guide | Covers |
| --- | --- |
| [I2C](https://binhollc.github.io/pycosmicsdk/guides/i2c.html) | Bring-up, pull-ups, duty cycle, write, read, scan |
| [I3C](https://binhollc.github.io/pycosmicsdk/guides/i3c.html) | Bus voltage and ports, dynamic addressing, SDR and HDR-DDR transfers, CCCs, legacy I2C on the I3C port |
| [SPI](https://binhollc.github.io/pycosmicsdk/guides/spi.html) | Modes, chip selects, full-duplex and half-duplex transfers |
| [UART](https://binhollc.github.io/pycosmicsdk/guides/uart.html) | Baud rates, request/response, streaming reception |
| [GPIO](https://binhollc.github.io/pycosmicsdk/guides/gpio.html) | Digital I/O and interrupts |
| [Large transfers](https://binhollc.github.io/pycosmicsdk/guides/bulk.html) | The bulk USB pipe and its size limits |
| [Target mode](https://binhollc.github.io/pycosmicsdk/guides/target-mode.html) | The adapter as an I2C, SPI or I3C target |
| [Device lifecycle](https://binhollc.github.io/pycosmicsdk/guides/lifecycle.html) | Discovery, opening by serial or model, closing, rebooting |
| [Testing](https://binhollc.github.io/pycosmicsdk/guides/testing.html) | Testing code without an adapter, using `pycosmicsdk.testing` |

Also in the documentation:

* [Getting started](https://binhollc.github.io/pycosmicsdk/getting-started.html): install, platform setup, first device.
* [Blocking and asyncio](https://binhollc.github.io/pycosmicsdk/asyncio.html): where `Device` and `AsyncDevice` differ.
* [Migrating from the legacy packages](https://binhollc.github.io/pycosmicsdk/migration.html): every difference per package.
* [Errors](https://binhollc.github.io/pycosmicsdk/reference/errors.html) and the [API reference](https://binhollc.github.io/pycosmicsdk/reference/index.html): every class, method, enum and status code.
* [Support](https://binhollc.github.io/pycosmicsdk/support.html): what to include in a problem report.

## Target Voltage

With firmware 4.7.0 or later (coming soon), `set_voltage()` on a port that already has an external supply leaves the adapter's supply off and raises an error with status `FW_EXTERNAL_VOLTAGE_DETECTED` (`0x0102`).

:::danger
With firmware 4.6.x and earlier, `set_voltage()` connects the adapter's supply to a target that powers itself. On a self-powered target, call `use_external_voltage()` instead of `set_voltage()`.

:::

## Getting Help

If something does not work as described here, [contact us](/support/contact-us/) or email [support@binho.io](mailto:support@binho.io). Include:

* the version printed by `python -c "import pycosmicsdk; print(pycosmicsdk.__version__)"`,
* the Python version and operating system,
* the output of the `list_devices()` example above (model, serial number, firmware),
* the full traceback, or the `status_code` of the error raised.