Blog
Technology Sharing
I3C Host adapter Pro+ (11)hits:4


Easyi3C is a leading supplier of embedded system tools that simplify the development and debugging of various communication protocols. The company offers a range of products designed to help engineers and developers use I3C/I2C , USB and MIPI, JEDEC, MCTP and other protocols more efficiently.


11. Message Combined send (2):


1. APIs

Easyi3C API provides APIs to allow user can control the bus freely. With APIs, users can combine any message and send them out by I2C or I3C protocol.  

3609217c-0d8a-429c-8c1e-86a211698ab1.png

2. I2C messages Example

# ==========================================================================
# Easyi3C Tower USB to I3C Host Adapter
# --------------------------------------------------------------------------
# Copyright © 2026 by Easyi3C, Inc.
# All rights reserved.
# --------------------------------------------------------------------------
# ==========================================================================
import sys
from ezi3c.api import *
from ezi3c.protocol import WriteMsg, ReadMsg, IdleMsg
from ezi3c import utils


ez = ez_open()
if not ez:
    print("Cannot open Adapter")
    sys.exit(-1)
clk = ez_set_bus_clk_freq(ez, 1000, 4000)
print("Cur Clk Freq: {}".format(clk))
ret = ez_set_io_voltage(ez, 1.0)
assert ret == 0, "Failed to set IO voltage"

try:
    print("---------------------------------------------")
    print("   Message test example: used JEDEC DDR5 TS   ")
    print("---------------------------------------------")
    addr = 0x37
    reg = 28

    ez_ccc_rstdaa(ez)

    print("> i2c Message write test ...")
    wdata = 0xF0
    msgs = [WriteMsg(addr, [reg, wdata])]
    for msg in msgs:
        print(msg)
    result = ez_send_i2c_msgs(ez, msgs)
    if not result.err == 0:
        print("Failed to send msgs: err: {}".format(result.err))
    else:
        for i, rx in enumerate(result.rx_data):
            print("Msg {}: rx_data: {}".format(i, utils.hex_string(rx)))

    print("> i2c Message write read test ...")
    rx_len = 1
    msgs = [
        WriteMsg(addr, reg, stop=False),
        ReadMsg(addr, rx_len),
    ]
    for msg in msgs:
        print(msg)
    result = ez_send_i2c_msgs(ez, msgs)
    if not result.err == 0:
        print("Failed to send msgs: err: {}".format(result.err))
    else:
        for i, rx in enumerate(result.rx_data):
            print("Msg {}: rx_data: {}".format(i, utils.hex_string(rx)))

    print("> i2c Message write read insert idle test ...")
    rx_len = 1
    duration = 10
    msgs = [
        WriteMsg(addr, reg, stop=False),
        IdleMsg(duration),
        ReadMsg(addr, rx_len),
    ]
    for msg in msgs:
        print(msg)
    result = ez_send_i2c_msgs(ez, msgs)
    if not result.err == 0:
        print("Failed to send msgs: err: {}".format(result.err))
    else:
        for i, rx in enumerate(result.rx_data):
            print("Msg {}: rx_data: {}".format(i, utils.hex_string(rx)))


finally:
    ez_close(ez)


3. I3C messages Example

# ==========================================================================
# Easyi3C Tower USB to I3C Host Adapter
# --------------------------------------------------------------------------
# Copyright © 2026 by Easyi3C, Inc.
# All rights reserved.
# --------------------------------------------------------------------------
# ==========================================================================
import sys
from ezi3c.api import *
from ezi3c import crc
from ezi3c.protocol import WriteMsg, ReadMsg, IdleMsg
from ezi3c import utils


ez = ez_open()
if not ez:
    print("Cannot open Adapter")
    sys.exit(-1)
clk = ez_set_bus_clk_freq(ez, 1000, 4000)
print("Cur Clk Freq: {}".format(clk))
ret = ez_set_io_voltage(ez, 1.0)
assert ret == 0, "Failed to set IO voltage"

try:
    print("---------------------------------------------")
    print("   Message test example: used JEDEC DDR5 TS   ")
    print("---------------------------------------------")
    addr = 0x37
    reg = 28

    ez_ccc_setaasa(ez)

    print(">  i3c Message write test ...")
    wdata = 0xF0
    msgs = [WriteMsg(addr, [reg, wdata])]
    for msg in msgs:
        print(msg)
    result = ez_send_i3c_msgs(ez, msgs)
    if not result.err == 0:
        print("Failed to send msgs: err: {}".format(result.err))
    else:
        for i, rx in enumerate(result.rx_data):
            print("Msg {}: rx_data: {}".format(i, utils.hex_string(rx)))

    print("> i3c Message write read test ...")
    rx_len = 1
    msgs = [
        WriteMsg(addr, reg, stop=False),
        ReadMsg(addr, rx_len),
    ]
    for msg in msgs:
        print(msg)
    result = ez_send_i3c_msgs(ez, msgs)
    if not result.err == 0:
        print("Failed to send msgs: err: {}".format(result.err))
    else:
        for i, rx in enumerate(result.rx_data):
            print("Msg {}: rx_data: {}".format(i, utils.hex_string(rx)))

    print("> i3c Message write read insert idle test ...")
    rx_len = 1
    duration = 10
    msgs = [
        WriteMsg(addr, reg, stop=False),
        ReadMsg(addr, rx_len),
        IdleMsg(duration),
        WriteMsg(addr, reg, stop=False),
        ReadMsg(addr, rx_len),
    ]
    for msg in msgs:
        print(msg)
    result = ez_send_i3c_msgs(ez, msgs)
    if not result.err == 0:
        print("Failed to send msgs: err: {}".format(result.err))
    else:
        for i, rx in enumerate(result.rx_data):
            print("Msg {}: rx_data: {}".format(i, utils.hex_string(rx)))

    print("> Enable PEC ...")
    BROADCAST = 0x7
    ez_ccc_devctrl(ez, BROADCAST, 0, 0, 0, 0, [0x01 << 7])

    print("> i3c Message write with PEC test ...")
    wdata = 0x0

    # Follow by JEDEC DDR5 Ts spec define
    cmd = 0x0
    pec_bytes = [addr << 1 | 0x00] + [reg, cmd, wdata]
    pec_cal = crc.crc(pec_bytes)

    msgs = [WriteMsg(addr, [reg, cmd, wdata, pec_cal])]
    result = ez_send_i3c_msgs(ez, msgs)
    if not result.err == 0:
        print("Failed to send msgs: err: {}".format(result.err))
    else:
        for i, rx in enumerate(result.rx_data):
            print("Msg {}: rx_data: {}".format(i, utils.hex_string(rx)))


    print("> i3c Message write read with PEC test ...")
    rx_len = 1
    pec_count = 1

    # Follow by JEDEC DDR5 Ts spec define
    cmd = 1 << 4
    pec_bytes = [addr << 1 | 0x00] + [reg] + [cmd]
    pec_cal = crc.crc(pec_bytes)
    msgs = [
        WriteMsg(addr, [reg, cmd, pec_cal], stop=False),
        ReadMsg(addr, rx_len + pec_count)
    ]

    result = ez_send_i3c_msgs(ez, msgs)
    if not result.err == 0:
        print("Failed to send msgs: err: {}".format(result.err))
    else:
        for i, rx in enumerate(result.rx_data):
            print("Msg {}: rx_data: {}".format(i, utils.hex_string(rx)))
            # check pec value
            pec_value = rx[1]
            pec_bytes = [addr << 1 | 0x01] + [rx[0]]
            pec_cal = crc.crc(pec_bytes)
            if pec_value != pec_cal:
                print(f"PEC mismatch: expected {pec_cal}, got {pec_value}.")

    print("> Diable PEC ...")

    print("> DEVCTRL CCC Broadcast with PEC ...")
    # Follow by JEDEC DDR5 Ts spec define
    addr_ccc = 0x7E
    broadcast = 0x62
    addrmask = 0x7
    startoffset = 0x0
    pecbl = 0x0
    regmod = 0x0
    data = addrmask << 5 | startoffset << 3 | pecbl << 1 | regmod
    devid = 0x0
    payload = [0]

    pec_bytes = [broadcast] + [data] + [devid << 1] + payload
    pec_cal = crc.crc(pec_bytes)

    send_bytes = [broadcast] + [data] + [devid << 1] + payload + [pec_cal]

    msgs = [WriteMsg(addr_ccc, send_bytes)]
    result = ez_send_i3c_msgs(ez, msgs)
    if not result.err == 0:
        print("Failed to send msgs: err: {}".format(result.err))
    else:
        for i, rx in enumerate(result.rx_data):
            print("Msg {}: rx_data: {}".format(i, utils.hex_string(rx)))

finally:
    ez_close(ez)



Service Line:

Address:Silicon Valley
Email:support@easyi3c.com

Copyright © Easyi3C Co., LTD