FAQ
General
How do I connect to a specific device?
Use serial-number-based connection when you know the adapter serial. Use HID path when you want to bind to a specific OS device path.
C++ API
auto sdk = std::make_unique<CosmicSDK>(2000);
bool okSerial = sdk->connectWithSerialNumber("SN12345678");
bool okPath = sdk->connect(R"(\\?\hid#vid_2e8a&pid_...)");
C API
CosmicSDK_Handle* h = CosmicSDK_Create(2000);
bool ok_serial = CosmicSDK_ConnectWithSerialNumber(h, "SN12345678");
bool ok_path = CosmicSDK_Connect(h, "\\\\?\\hid#vid_2e8a&pid_...");
I2C
Which I2C role is supported by the host adapters?
The host adapter works as I2C Controller (Master) only. Support for the Target (Slave) role is planned for a future release.
C++ API
// Controller/Master initialization entry point
uint16_t rc = sdk->i2cControllerInit(I2C_BUS_A, 400000, I2C_PULLUP_2_2kOhm);
C API
// Controller/Master initialization entry point
uint16_t rc = CosmicSDK_I2cControllerInit(h, I2C_BUS_A, 400000, I2C_PULLUP_2_2kOhm);
How many I2C buses are supported on Supernova and Pulsar?
Supernova supports one I2C bus (I2C_BUS_A). Pulsar supports two I2C buses (I2C_BUS_A and I2C_BUS_B).
C++ API
uint16_t rcA = sdk->i2cControllerInit(I2C_BUS_A, 400000, I2C_PULLUP_2_2kOhm);
uint16_t rcB = sdk->i2cControllerInit(I2C_BUS_B, 400000, I2C_PULLUP_2_2kOhm); // Pulsar only
C API
uint16_t rcA = CosmicSDK_I2cControllerInit(h, I2C_BUS_A, 400000, I2C_PULLUP_2_2kOhm);
uint16_t rcB = CosmicSDK_I2cControllerInit(h, I2C_BUS_B, 400000, I2C_PULLUP_2_2kOhm); // Pulsar only
How do I differentiate I2C buses in the API?
Use the bus argument (I2C_BUS_A or I2C_BUS_B) in all I2C methods.
C++ API
sdk->i2cWrite(I2C_BUS_A, 0x50, {0x00}, {0xAA, 0xBB});
sdk->i2cWrite(I2C_BUS_B, 0x50, {0x00}, {0xCC, 0xDD});
C API
uint8_t sub[] = {0x00};
uint8_t dataA[] = {0xAA, 0xBB};
uint8_t dataB[] = {0xCC, 0xDD};
CosmicSDK_I2cWrite(h, I2C_BUS_A, 0x50, sub, 1, dataA, 2, false);
CosmicSDK_I2cWrite(h, I2C_BUS_B, 0x50, sub, 1, dataB, 2, false);
How do I initialize the I2C interface?
Set bus voltage (if needed), then call the I2C controller init method.
C++ API
sdk->i2cSetBusVoltage(3300);
uint16_t rc = sdk->i2cControllerInit(I2C_BUS_A, 400000, I2C_PULLUP_2_2kOhm);
C API
CosmicSDK_I2cSetBusVoltage(h, 3300, false);
uint16_t rc = CosmicSDK_I2cControllerInit(h, I2C_BUS_A, 400000, I2C_PULLUP_2_2kOhm);
How do I change I2C bus configuration after initialization?
Call the set-parameters method instead of calling init again.
C++ API
uint16_t rc = sdk->i2cSetParameters(I2C_BUS_A, 1000000, I2C_PULLUP_1kOhm);
C API
uint16_t rc = CosmicSDK_I2cSetParameters(h, I2C_BUS_A, 1000000, I2C_PULLUP_1kOhm);
How do I write to and read from an I2C target (slave)?
Use i2cWrite / CosmicSDK_I2cWrite to send bytes to the target address, and i2cRead / CosmicSDK_I2cRead to read bytes from that target.
C++ API
std::vector<uint8_t> tx = {0xAA, 0xBB, 0xCC};
std::vector<uint8_t> rx;
sdk->i2cWrite(I2C_BUS_A, 0x50, {0x00, 0x10}, tx, false); // Write at subaddress 0x0010
sdk->i2cRead(I2C_BUS_A, 0x50, {0x00, 0x10}, 8, rx, false); // Read 8 bytes from subaddress 0x0010
C API
uint8_t subaddr[] = {0x00, 0x10};
uint8_t tx[] = {0xAA, 0xBB, 0xCC};
uint8_t rx[8] = {0};
CosmicSDK_I2cWrite(h, I2C_BUS_A, 0x50, subaddr, 2, tx, 3, false); // Write at subaddress 0x0010
CosmicSDK_I2cRead(h, I2C_BUS_A, 0x50, subaddr, 2, 8, rx, false); // Read 8 bytes from subaddress 0x0010
How can I scan the bus and discover the static address of the I2C targets connected to the USB host adapter?
Use i2cScanBus / CosmicSDK_I2cScanBus. The discovered static addresses are returned in the output vector/buffer.
Note
Depending on the bus characteristics, such as frequency, voltage, number of targets connected, and the length of the wires used in the
hardware setup, the performance of the I2C SCAN BUS may be affected, and as a result, it might return a wrong list of detected addresses,
an SDK_ERROR_TIMEOUT error, and the firmware might indeed get stuck, especially in the Pulsar. In order to avoid this scenario, consider
the following recommendations to run a smooth scan bus procedure:
Set the clock frequency to low values, such as 100KHz and 400 KHz.
Disable the pull-up resistors, or set their value to high values - weak pull-ups.
In the case of the Pulsar, suggested values are:
I2C_PULLUP_DISABLE,I2C_PULLUP_4kOhm, orI2C_PULLUP_2_2kOhmIn the case of the Supernova, suggested values are:
I2C_PULLUP_DISABLE,I2C_PULLUP_10kOhm, orI2C_PULLUP_4_7kOhm
C++ API
std::vector<uint8_t> addresses;
uint8_t count7Bit = 0;
uint8_t count10Bit = 0;
uint16_t rc = sdk->i2cScanBus(addresses, &count7Bit, &count10Bit, I2C_BUS_A, true);
C API
uint8_t addresses[32] = {0};
uint8_t count7Bit = 0;
uint8_t count10Bit = 0;
uint16_t rc = CosmicSDK_I2cScanBus(h, addresses, 32, &count7Bit, &count10Bit, I2C_BUS_A, true);
Does the API support I2C 10-bit addresses?
Only bus scan supports 10-bit addresses today. 10-bit transfer support already exists in firmware but is not yet exposed in the public API. We plan to add API support for 10-bit transfers in a future release.
Which I2C pull-up resistor values are valid for Supernova and which for Pulsar?
The two devices differ on the available pull-up resistor values. The constants from 150 Ω to 2.2 kΩ are shared; above 2.2 kΩ each device provides its own set. Passing an unsupported value returns FW_INVALID_PARAMETER.
Constant |
Supernova |
Pulsar |
|---|---|---|
|
Yes |
Yes |
|
Yes |
Yes |
|
Yes |
Yes |
|
Yes |
Yes |
|
Yes |
Yes |
|
Yes |
Yes |
|
Yes |
Yes |
|
Yes |
Yes |
|
Yes |
No |
|
No |
Yes |
|
Yes |
No |
|
Yes |
No |
|
Yes |
Yes |
SPI
Which SPI role is supported by the host adapters?
The host adapter works as SPI Controller (Master) only.
C++ API
uint16_t rc = sdk->spiControllerInit(
SPI_BIT_ORDER_MSB, SPI_MODE_0, SPI_DATA_WIDTH_8_BITS,
SPI_CHIP_SELECT_0, SPI_CS_ACTIVE_LOW, 1000000);
C API
uint16_t rc = CosmicSDK_SpiControllerInit(
h, SPI_BIT_ORDER_MSB, SPI_MODE_0, SPI_DATA_WIDTH_8_BITS,
SPI_CHIP_SELECT_0, SPI_CS_ACTIVE_LOW, 1000000);
How do I initialize the SPI interface?
Set SPI voltage (if needed), then call SPI controller init.
C++ API
sdk->spiSetBusVoltage(3300);
uint16_t rc = sdk->spiControllerInit(
SPI_BIT_ORDER_MSB, SPI_MODE_0, SPI_DATA_WIDTH_8_BITS,
SPI_CHIP_SELECT_0, SPI_CS_ACTIVE_LOW, 10000000);
C API
CosmicSDK_SpiSetBusVoltage(h, 3300, false);
uint16_t rc = CosmicSDK_SpiControllerInit(
h, SPI_BIT_ORDER_MSB, SPI_MODE_0, SPI_DATA_WIDTH_8_BITS,
SPI_CHIP_SELECT_0, SPI_CS_ACTIVE_LOW, 10000000);
How do I change SPI bus configuration after initialization?
Use SPI set-parameters to reconfigure without reinitializing.
C++ API
uint16_t rc = sdk->spiSetParameters(
SPI_BIT_ORDER_MSB, SPI_MODE_3, SPI_DATA_WIDTH_8_BITS,
SPI_CHIP_SELECT_1, SPI_CS_ACTIVE_LOW, 5000000);
C API
uint16_t rc = CosmicSDK_SpiSetParameters(
h, SPI_BIT_ORDER_MSB, SPI_MODE_3, SPI_DATA_WIDTH_8_BITS,
SPI_CHIP_SELECT_1, SPI_CS_ACTIVE_LOW, 5000000);
How do I transmit and receive data in SPI?
Current host adapters support 4-wire SPI. In this mode, TX (MOSI) and RX (MISO) run in parallel during a transfer clock window. For this reason, the API exposes a single method, spiTransfer / CosmicSDK_SpiTransfer, for both transmit and receive. Provide TX data and transfer length, and read the received bytes from the output buffer/vector.
C++ API
std::vector<uint8_t> tx = {0x9F}; // JEDEC ID command
std::vector<uint8_t> rx;
uint16_t rc = sdk->spiTransfer(tx, rx, 4); // 1 command byte + 3 response bytes
C API
uint8_t tx[1] = {0x9F}; // JEDEC ID command
uint8_t rx[4] = {0};
uint16_t rc = CosmicSDK_SpiTransfer(h, tx, 1, rx, 4); // 1 command byte + 3 response bytes
UART
How do I initialize the UART interface?
Configure the UART line settings with uartInit / CosmicSDK_UartInit before sending data.
C++ API
uint16_t rc = sdk->uartInit(
UART_BAUD_115200, UART_HW_HANDSHAKE_DIS,
UART_PARITY_NONE, UART_DATA_SIZE_8, UART_STOP_BIT_1);
C API
uint16_t rc = CosmicSDK_UartInit(
h, UART_BAUD_115200, UART_HW_HANDSHAKE_DIS,
UART_PARITY_NONE, UART_DATA_SIZE_8, UART_STOP_BIT_1);
How do I change UART configuration after initialization?
Use the UART set-parameters method.
C++ API
uint16_t rc = sdk->uartSetParameters(
UART_BAUD_9600, UART_HW_HANDSHAKE_DIS,
UART_PARITY_NONE, UART_DATA_SIZE_8, UART_STOP_BIT_1);
C API
uint16_t rc = CosmicSDK_UartSetParameters(
h, UART_BAUD_9600, UART_HW_HANDSHAKE_DIS,
UART_PARITY_NONE, UART_DATA_SIZE_8, UART_STOP_BIT_1);
How do I transmit data in UART?
Use uartSendMessage / CosmicSDK_UartSendMessage after UART initialization.
C++ API
std::vector<uint8_t> msg = {'H', 'e', 'l', 'l', 'o', '\n'};
uint16_t rc = sdk->uartSendMessage(msg);
C API
uint8_t msg[] = "Hello\n";
uint16_t rc = CosmicSDK_UartSendMessage(h, msg, 6);
How does UART reception work?
UART RX is asynchronous only. Register a notification callback and parse UART notifications with helper accessors/functions. Polling is not supported.
C++ API
sdk->onNotification([](const Notification& n) {
if (const UartRxNotification* rx = n.uartRx()) {
// rx->data / rx->dataLength
}
});
C API
static void cb(const Notification* n) {
UartRxNotification rx;
if (CosmicSDK_notificationAsUartRx(n, &rx)) {
// rx.data / rx.dataLength
}
}
CosmicSDK_onNotification(h, cb);
GPIO
How do I configure GPIOs?
Call GPIO configure pin with the pin number and desired mode (input or output).
C++ API
sdk->gpioConfigurePin(GPIO_1, GPIO_DIGITAL_INPUT);
sdk->gpioConfigurePin(GPIO_3, GPIO_DIGITAL_OUTPUT, GPIO_LOW);
C API
CosmicSDK_GpioConfigurePin(h, GPIO_1, GPIO_DIGITAL_INPUT, false, GPIO_LOW);
CosmicSDK_GpioConfigurePin(h, GPIO_3, GPIO_DIGITAL_OUTPUT, true, GPIO_LOW);
How do I enable GPIO interrupts?
First configure the pin as digital input, then configure the interrupt trigger type.
C++ API
sdk->gpioConfigurePin(GPIO_1, GPIO_DIGITAL_INPUT);
sdk->gpioConfigureInterrupt(GPIO_1, GPIO_TRIGGER_BOTH_EDGES);
C API
CosmicSDK_GpioConfigurePin(h, GPIO_1, GPIO_DIGITAL_INPUT, false, GPIO_LOW);
CosmicSDK_GpioConfigureInterrupt(h, GPIO_1, GPIO_TRIGGER_BOTH_EDGES);
How do I receive and handle asynchronous GPIO interrupt notifications?
Register a notification callback and parse GPIO notifications using helper accessors/functions.
C++ API
sdk->onNotification([](const Notification& n) {
if (const GpioInterruptNotification* g = n.gpio()) {
// g->pinNumber
}
});
C API
static void cb(const Notification* n) {
GpioInterruptNotification gpio;
if (CosmicSDK_notificationAsGpio(n, &gpio)) {
// gpio.pinNumber
}
}
CosmicSDK_onNotification(h, cb);
I3C
Which I3C role does Supernova support?
Supernova supports the I3C Controller role in the current API.
C++ API
uint16_t rc = sdk->i3cControllerInit(
PUSH_PULL_10_MHz_DC_40, OPEN_DRAIN_400_KHz, FAST_MODE, FAST);
C API
uint16_t rc = CosmicSDK_I3cControllerInit(
h, PUSH_PULL_10_MHz_DC_40, OPEN_DRAIN_400_KHz, FAST_MODE, FAST);
Which I3C modes do Supernova and the I3C API support?
The supported transfer modes are:
I3C SDR
Legacy I2C over the I3C bus
I3C HDR-DDR
Write/read method mapping per mode:
I3C SDR:
i3cSdrWrite/i3cSdrReadLegacy I2C over I3C:
i3cLegacyI2cWrite/i3cLegacyI2cReadI3C HDR-DDR:
i3cHdrDdrWrite/i3cHdrDdrRead
C++ API
std::vector<uint8_t> out;
std::vector<uint8_t> in = {0x11, 0x22};
// I3C SDR
sdk->i3cSdrWrite(0x08, {0x00}, in, I3C_XFER_NONE);
sdk->i3cSdrRead(0x08, {0x00}, 8, out, I3C_XFER_NONE);
// Legacy I2C over I3C
sdk->i3cLegacyI2cWrite(0x50, {0x00}, in, I3C_XFER_NONE);
sdk->i3cLegacyI2cRead(0x50, {0x00}, 8, out, I3C_XFER_NONE);
// I3C HDR-DDR
sdk->i3cHdrDdrWrite(0x08, 0x20, in);
sdk->i3cHdrDdrRead(0x08, 0x20, 8, out);
C API
uint8_t in[2] = {0x11, 0x22};
uint8_t out[32];
uint8_t out_len = 0;
// I3C SDR
CosmicSDK_I3cSdrWrite(h, 0x08, NULL, 0, in, 2, I3C_XFER_NONE);
CosmicSDK_I3cSdrRead(h, 0x08, NULL, 0, 8, out, &out_len, I3C_XFER_NONE);
// Legacy I2C over I3C
CosmicSDK_I3cLegacyI2CWrite(h, 0x50, NULL, 0, in, 2, I3C_XFER_NONE);
CosmicSDK_I3cLegacyI2CRead(h, 0x50, NULL, 0, 8, out, I3C_XFER_NONE);
// I3C HDR-DDR
CosmicSDK_I3cHdrDdrWrite(h, 0x08, 0x20, in, 2);
CosmicSDK_I3cHdrDdrRead(h, 0x08, 0x20, 8, out);
How do I initialize the I3C interface?
Set I3C voltage and then initialize the controller.
C++ API
sdk->i3cSetBusVoltage(1200);
uint16_t rc = sdk->i3cControllerInit(
PUSH_PULL_10_MHz_DC_40, OPEN_DRAIN_400_KHz, FAST_MODE, FAST);
C API
CosmicSDK_I3cSetBusVoltage(h, 1200);
uint16_t rc = CosmicSDK_I3cControllerInit(
h, PUSH_PULL_10_MHz_DC_40, OPEN_DRAIN_400_KHz, FAST_MODE, FAST);
How do I change I3C bus configuration after initialization?
Use I3C set-parameters.
C++ API
uint16_t rc = sdk->i3cSetParameters(
PUSH_PULL_2_5_MHz_DC_25, OPEN_DRAIN_100_KHz, STANDARD_MODE, STANDARD);
C API
uint16_t rc = CosmicSDK_I3cSetParameters(
h, PUSH_PULL_2_5_MHz_DC_25, OPEN_DRAIN_100_KHz, STANDARD_MODE, STANDARD);
How do I initialize the I3C bus with or without a target table?
Call InitBus with an empty table for controller-driven discovery (RSTDAA + ENTDAA). Pass a target table when you need deterministic setup (mixed I3C/I2C, predefined addressing/configuration). The table uses I3cTargetInfo, including I3cBCR and I3cTargetConfiguration.
C++ API
// Discovery flow (no predefined table)
sdk->i3cInitBus();
// Deterministic flow with predefined targets
I3cBCR bcrI3c{};
bcrI3c.byte = 0x27; // non-zero BCR
I3cTargetConfiguration confI3c{};
confI3c.bits.targetType = 0; // I3C target
confI3c.bits.daaUseENTDAA = true;
confI3c.bits.IBIRequest = true;
I3cBCR bcrI2c{};
bcrI2c.byte = 0x00;
I3cTargetConfiguration confI2c{};
confI2c.bits.targetType = 1; // Legacy I2C target
confI2c.bits.daaUseENTDAA = false;
std::vector<I3cTargetInfo> targets = {
// Supernova can use this desired dynamic address during ENTDAA by matching PID/BCR/DCR.
{0x69, 0x2A, {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}, bcrI3c, 0x5D, 0, 0, 0, confI3c},
{0x50, 0x00, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, bcrI2c, 0x00, 0, 0, 0, confI2c}
};
sdk->i3cInitBus(targets);
C API
// Discovery flow (no predefined table)
CosmicSDK_I3cInitBus(h, NULL, 0);
// Deterministic flow with predefined targets
I3cBCR bcr_i3c = {0};
bcr_i3c.byte = 0x27; // non-zero BCR
I3cTargetConfiguration conf_i3c = {0};
conf_i3c.bits.targetType = 0; // I3C target
conf_i3c.bits.daaUseENTDAA = true;
conf_i3c.bits.IBIRequest = true;
I3cBCR bcr_i2c = {0};
bcr_i2c.byte = 0x00;
I3cTargetConfiguration conf_i2c = {0};
conf_i2c.bits.targetType = 1; // Legacy I2C target
conf_i2c.bits.daaUseENTDAA = false;
I3cTargetInfo targets[2] = {
// Supernova can use this desired dynamic address during ENTDAA by matching PID/BCR/DCR.
{0x69, 0x2A, {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}, bcr_i3c, 0x5D, 0, 0, 0, conf_i3c},
{0x50, 0x00, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, bcr_i2c, 0x00, 0, 0, 0, conf_i2c}
};
CosmicSDK_I3cInitBus(h, targets, 2);
How do I assign dynamic addresses?
Use InitBus for default assignment, or explicit CCCs: ENTDAA for dynamic discovery, SETDASA for static-to-dynamic mapping, and SETAASA for assigning from known static-address targets.
C++ API
sdk->i3cInitBus();
sdk->i3cCccENTDAA();
sdk->i3cCccSETDASA(0x69, 0x0B);
sdk->i3cCccSETAASA({0x69, 0x6B});
C API
CosmicSDK_I3cInitBus(h, NULL, 0);
CosmicSDK_I3cCccENTDAA(h);
CosmicSDK_I3cCccSETDASA(h, 0x69, 0x0B);
uint8_t static_addresses[] = {0x69, 0x6B};
CosmicSDK_I3cCccSETAASA(h, static_addresses, 2);
Which CCCs are supported by the API?
The API supports common controller-side CCC operations, including:
Address assignment and discovery:
RSTDAA,ENTDAA,SETDASA,SETAASA,SETNEWDATarget identification and capabilities:
GETPID,GETBCR,GETDCR,GETSTATUS,GETCAPSEvent and reset control:
ENEC(broadcast/direct),DISEC(broadcast/direct),RSTACT(broadcast/direct)Transfer limits:
GETMWL,SETMWL(broadcast/direct),GETMRL,SETMRL(broadcast/direct)
C++ API
sdk->i3cCccRSTDAA();
sdk->i3cCccENTDAA();
sdk->i3cCccSETDASA(0x69, 0x0B);
sdk->i3cCccSETAASA({0x69, 0x6B});
sdk->i3cCccSETNEWDA(0x08, 0x09);
std::vector<uint8_t> pid, status, caps;
uint8_t bcr = 0, dcr = 0;
uint16_t mwl = 0, mrl = 0;
std::optional<uint8_t> ibiLen;
sdk->i3cCccGETPID(0x08, pid);
sdk->i3cCccGETBCR(0x08, bcr);
sdk->i3cCccGETDCR(0x08, dcr);
sdk->i3cCccGETSTATUS(0x08, status, ibiLen);
sdk->i3cCccGETCAPS(0x08, caps, ibiLen);
sdk->i3cCccENECBroadcast(IBI);
sdk->i3cCccENECDirect(0x08, IBI);
sdk->i3cCccDISECBroadcast(IBI);
sdk->i3cCccDISECDirect(0x08, IBI);
sdk->i3cCccRSTACTBroadcast(RESET_I3C_PERIPHERAL);
uint8_t resetTime = 0;
sdk->i3cCccRSTACTDirect(0x08, RETURN_TIME_RESET_PERIPHERAL, resetTime);
sdk->i3cCccGETMWL(0x08, mwl);
sdk->i3cCccSETMWLBroadcast(256);
sdk->i3cCccSETMWLDirect(0x08, 256);
sdk->i3cCccGETMRL(0x08, mrl, ibiLen);
sdk->i3cCccSETMRLBroadcast(256);
sdk->i3cCccSETMRLDirect(0x08, 256);
C API
CosmicSDK_I3cCccRSTDAA(h);
CosmicSDK_I3cCccENTDAA(h);
CosmicSDK_I3cCccSETDASA(h, 0x69, 0x0B);
uint8_t static_addresses[] = {0x69, 0x6B};
CosmicSDK_I3cCccSETAASA(h, static_addresses, 2);
CosmicSDK_I3cCccSETNEWDA(h, 0x08, 0x09);
uint8_t pid[6] = {0};
uint8_t bcr = 0, dcr = 0;
uint8_t status[8] = {0}, caps[8] = {0};
uint8_t status_len = 0, caps_len = 0;
uint16_t mwl = 0, mrl = 0;
bool has_ibi_len = false;
uint8_t ibi_len = 0;
CosmicSDK_I3cCccGETPID(h, 0x08, pid);
CosmicSDK_I3cCccGETBCR(h, 0x08, &bcr);
CosmicSDK_I3cCccGETDCR(h, 0x08, &dcr);
CosmicSDK_I3cCccGETSTATUS(h, 0x08, status, sizeof(status), &status_len, &has_ibi_len, &ibi_len);
CosmicSDK_I3cCccGETCAPS(h, 0x08, caps, sizeof(caps), &caps_len, &has_ibi_len, &ibi_len);
CosmicSDK_I3cCccENECBroadcast(h, IBI);
CosmicSDK_I3cCccENECDirect(h, 0x08, IBI);
CosmicSDK_I3cCccDISECBroadcast(h, IBI);
CosmicSDK_I3cCccDISECDirect(h, 0x08, IBI);
CosmicSDK_I3cCccRSTACTBroadcast(h, RESET_I3C_PERIPHERAL);
uint8_t reset_time = 0;
CosmicSDK_I3cCccRSTACTDirect(h, 0x08, RETURN_TIME_RESET_PERIPHERAL, &reset_time);
CosmicSDK_I3cCccGETMWL(h, 0x08, &mwl);
CosmicSDK_I3cCccSETMWLBroadcast(h, 256);
CosmicSDK_I3cCccSETMWLDirect(h, 0x08, 256);
CosmicSDK_I3cCccGETMRL(h, 0x08, &mrl, &has_ibi_len, &ibi_len);
CosmicSDK_I3cCccSETMRLBroadcast(h, 256, false, 0);
CosmicSDK_I3cCccSETMRLDirect(h, 0x08, 256, false, 0);
How can I know the actual transfer length in an I3C SDR read?
An I3C target can terminate a read early using End-Of-Data (EOD, T-bit = 0), so the actual returned length may be shorter than requested.
In C++, check
outData.size()afteri3cSdrRead.In C, check
outDataLengthfromCosmicSDK_I3cSdrRead.
C++ API
std::vector<uint8_t> outData;
uint16_t rc = sdk->i3cSdrRead(0x08, {0x00}, 32, outData, I3C_XFER_NONE);
if (rc == SUCCESS) {
size_t actualLen = outData.size(); // May be < 32 when target signals EOD
}
C API
uint8_t out[32];
uint8_t actual_len = 0;
uint16_t rc = CosmicSDK_I3cSdrRead(h, 0x08, NULL, 0, 32, out, &actual_len, I3C_XFER_NONE);
if (rc == SUCCESS) {
// actual_len may be < 32 when target signals EOD
}
How do I handle I3C IBIs?
IBIs are asynchronous notifications. Register a callback and decode notifications using the helper accessors/functions.
C++ API
sdk->onNotification([](const Notification& n) {
if (const I3cIbiNotification* ibi = n.i3cIbi()) {
// ibi->address, ibi->payload, ibi->payloadLength
}
});
C API
static void cb(const Notification* n) {
I3cIbiNotification ibi;
if (CosmicSDK_notificationAsI3cIbi(n, &ibi)) {
// ibi.address, ibi.payload, ibi.payloadLength
}
}
CosmicSDK_onNotification(h, cb);
How do I handle I3C Hot-Join notifications?
Hot-Join is also asynchronous. Register a callback and parse the notification using the helper accessors/functions.
C++ API
sdk->onNotification([](const Notification& n) {
if (const I3cHotJoinNotification* hj = n.i3cHotJoin()) {
// hj->dynamicAddress, hj->bcr, hj->dcr
// PID bytes: hj->pid[0] ... hj->pid[5]
}
});
C API
static void cb(const Notification* n) {
I3cHotJoinNotification hj;
if (CosmicSDK_notificationAsI3cHotJoin(n, &hj)) {
// hj.dynamicAddress, hj.bcr, hj.dcr
// PID bytes: hj.pid[0] ... hj.pid[5]
}
}
CosmicSDK_onNotification(h, cb);