.. _module-pw_i2c-quickstart-and-guides: ===================== Quickstart and guides ===================== .. pigweed-module-subpage:: :name: pw_i2c .. _module-pw_i2c-quickstart: ---------- Quickstart ---------- .. tab-set:: .. tab-item:: Bazel Depend on the ``pw_i2c`` API and an appropriate implementation of the API like ``pw_i2c_linux``. See :ref:`module-pw_i2c-impl` for the list of existing implementations and to learn how to create your own. .. code-block:: python cc_library( # ... deps = [ # ... "@pigweed//pw_i2c:address", "@pigweed//pw_i2c:device", # ... ] + select({ "@platforms//os:linux": [ "@pigweed//pw_i2c_linux:initiator", ], "//conditions:default": [ # Fake example of a custom implementation. "//lib/pw_i2c_my_device:initiator", ], }), ) .. note:: This assumes that your Bazel ``WORKSPACE`` has a `repository `_ named ``@pigweed`` that points to the upstream Pigweed repository. If creating your own implementation, depend on the virtual interface: .. code-block:: python cc_library( name = "initiator", srcs = ["initiator.cc"], hdrs = ["initiator.h"], deps = ["@pigweed//pw_i2c:initiator"], ) Write some C++ code to interact with an I2C device: .. include:: ../pw_i2c_rp2040/docs.rst :start-after: .. pw_i2c_rp2040-example-start :end-before: .. pw_i2c_rp2040-example-end .. _module-pw_i2c-guides: ------ Guides ------ .. _module-pw_i2c-guides-mock: Mock I2C transactions ===================== See the example in :cpp:class:`pw::i2c::MockInitiator`. .. _module-pw_i2c-guides-registerdevice: Configure and read an I2C device's registers ============================================ .. code-block:: c++ #include #include #include #include "pw_bytes/bit.h" #include "pw_i2c/address.h" #include "pw_i2c/register_device.h" #include "pw_log/log.h" #include "pw_status/status.h" using ::pw::Status; using namespace std::chrono_literals; // Search for `pi4ioe5v6416` in the Kudzu codebase to see real usage of // pw::i2c::RegisterDevice namespace pw::pi4ioe5v6416 { namespace { constexpr pw::i2c::Address kAddress = pw::i2c::Address::SevenBit<0x20>(); enum Register : uint32_t { InputPort0 = 0x0, ConfigPort0 = 0x6, PullUpDownEnablePort0 = 0x46, PullUpDownSelectionPort0 = 0x48, }; } // namespace // This particular example instantiates `pw::i2c::RegisterDevice` // as part of a higher-level general "device" interface. // See //lib/pi4ioe5v6416/public/pi4ioe5v6416/device.h in Kudzu. Device::Device(pw::i2c::Initiator& initiator) : initiator_(initiator), register_device_(initiator, kAddress, endian::little, pw::i2c::RegisterAddressSize::k1Byte) {} Status Device::Enable() { // Set port 0 as inputs for buttons (1=input) device_.WriteRegister8(Register::ConfigPort0, 0xff, pw::chrono::SystemClock::for_at_least(10ms)); // Select pullup resistors for button input (1=pullup) device_.WriteRegister8(Register::PullUpDownSelectionPort0, 0xff, pw::chrono::SystemClock::for_at_least(10ms)); // Enable pullup/down resistors for button input (1=enable) device_.WriteRegister8(Register::PullUpDownEnablePort0, 0xff, pw::chrono::SystemClock::for_at_least(10ms)); return OkStatus(); } pw::Result Device::ReadPort0() { return device_.ReadRegister8(Register::InputPort0, pw::chrono::SystemClock::for_at_least(10ms)); } } // namespace pw::pi4ioe5v6416 The code example above was adapted from :ref:`docs-kudzu`. See the following files for real ``pw::i2c::RegisterDevice`` usage: * `//lib/pi4ioe5v6416/device.cc `_ * `//lib/pi4ioe5v6416/public/pi4ioe5v6416/device.h `_ .. _module-pw_i2c-guides-rpc: Access an I2C device's registers over RPC ========================================= .. TODO: b/331292234 - Make this content less confusing and more helpful. :cpp:class:`pw::i2c::I2cService` enables accessing an I2C device's registers over RPC. Using :ref:`module-pw_console`, invoke the service to perform an I2C read: .. code-block:: python # Read register `0x0e` from the device at `0x22`. device.rpcs.pw.i2c.I2c.I2cRead( bus_index=0, target_address=0x22, register_address=b'\x0e', read_size=1 ) For responders that support 4-byte register width, you can specify the register address like this: .. code-block:: python device.rpcs.pw.i2c.I2c.I2cRead( bus_index=0, target_address=
, register_address=b'\x00\x00\x00\x00', read_size=4 ) To perform an I2C write: .. code-block:: python device.rpcs.pw.i2c.I2c.I2cWrite( bus_index=0, target_address=0x22, register_address=b'\x0e', value=b'\xbc' ) Multi-byte writes can also be specified with the bytes fields for ``register_address`` and ``value``. I2C responders that require multi-byte access may expect a specific endianness. The order of bytes specified in the bytes field will match the order of bytes sent or received on the bus. The maximum supported value for multi-byte access is 4 bytes.