# Protocol interfaces Nine interface classes, each with an `Async` twin — eighteen classes in all. None of them is constructed directly. Eight come from an accessor on {py:obj}`~pycosmicsdk.Device` or {py:obj}`~pycosmicsdk.AsyncDevice`, which caches it per device (and, for I2C, per bus — the controller and the target for one bus are cached under distinct keys, so they are two objects rather than one). The ninth, {py:obj}`~pycosmicsdk.I3cCcc`, is a sub-interface reached through the {py:obj}`I3cController.ccc ` property rather than from the device. Three of the accessors are themselves capability-guarded, and refusing at the accessor is deliberate: a caller who cannot obtain the object cannot write the rest of the program against it. {py:obj}`Device.i3c() ` refuses on a Pulsar, and {py:obj}`Device.spi_target() ` refuses on a hardware revision that cannot receive a chip select. | Accessor | Blocking | asyncio | |---|---|---| | `dev.i2c(bus=...)` | {py:obj}`~pycosmicsdk.I2cController` | {py:obj}`~pycosmicsdk.AsyncI2cController` | | `dev.i2c_target(bus=...)` | {py:obj}`~pycosmicsdk.I2cTarget` | {py:obj}`~pycosmicsdk.AsyncI2cTarget` | | `dev.i3c()` | {py:obj}`~pycosmicsdk.I3cController` | {py:obj}`~pycosmicsdk.AsyncI3cController` | | `dev.i3c().ccc` | {py:obj}`~pycosmicsdk.I3cCcc` | {py:obj}`~pycosmicsdk.AsyncI3cCcc` | | `dev.i3c_target()` | {py:obj}`~pycosmicsdk.I3cTarget` | {py:obj}`~pycosmicsdk.AsyncI3cTarget` | | `dev.uart()` | {py:obj}`~pycosmicsdk.Uart` | {py:obj}`~pycosmicsdk.AsyncUart` | | `dev.spi()` | {py:obj}`~pycosmicsdk.SpiController` | {py:obj}`~pycosmicsdk.AsyncSpiController` | | `dev.spi_target()` | {py:obj}`~pycosmicsdk.SpiTarget` | {py:obj}`~pycosmicsdk.AsyncSpiTarget` | | `dev.gpio()` | {py:obj}`~pycosmicsdk.Gpio` | {py:obj}`~pycosmicsdk.AsyncGpio` | {py:obj}`~pycosmicsdk.I2cTarget` is reached per *bus* by design — `i2cTargetInit` takes a bus id as its first parameter, which is forced by the upstream surface rather than chosen. {py:obj}`~pycosmicsdk.SpiTarget` and {py:obj}`~pycosmicsdk.I3cTarget` are not, because their peripherals are not. The narrative counterparts are the [protocol guides](../guides/index.md), and the two roles that share the bulk plane have their own page: [Target mode](../guides/target-mode.md). ## I2C ```{eval-rst} .. autoclass:: pycosmicsdk.I2cController .. autoclass:: pycosmicsdk.AsyncI2cController ``` ## I2C — target mode ```{eval-rst} .. autoclass:: pycosmicsdk.I2cTarget .. autoclass:: pycosmicsdk.AsyncI2cTarget ``` ## I3C — controller ```{eval-rst} .. autoclass:: pycosmicsdk.I3cController .. autoclass:: pycosmicsdk.AsyncI3cController ``` ## I3C — common command codes ```{eval-rst} .. autoclass:: pycosmicsdk.I3cCcc .. autoclass:: pycosmicsdk.AsyncI3cCcc ``` ## I3C — target mode ```{eval-rst} .. autoclass:: pycosmicsdk.I3cTarget .. autoclass:: pycosmicsdk.AsyncI3cTarget ``` ## UART ```{eval-rst} .. autoclass:: pycosmicsdk.Uart .. autoclass:: pycosmicsdk.AsyncUart ``` ## SPI ```{eval-rst} .. autoclass:: pycosmicsdk.SpiController .. autoclass:: pycosmicsdk.AsyncSpiController ``` ## SPI — target mode ```{eval-rst} .. autoclass:: pycosmicsdk.SpiTarget .. autoclass:: pycosmicsdk.AsyncSpiTarget ``` ## GPIO ```{eval-rst} .. autoclass:: pycosmicsdk.Gpio .. autoclass:: pycosmicsdk.AsyncGpio ```