1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_i2c-quickstart-and-guides: 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker===================== 4*61c4878aSAndroid Build Coastguard WorkerQuickstart and guides 5*61c4878aSAndroid Build Coastguard Worker===================== 6*61c4878aSAndroid Build Coastguard Worker.. pigweed-module-subpage:: 7*61c4878aSAndroid Build Coastguard Worker :name: pw_i2c 8*61c4878aSAndroid Build Coastguard Worker 9*61c4878aSAndroid Build Coastguard Worker.. _module-pw_i2c-quickstart: 10*61c4878aSAndroid Build Coastguard Worker 11*61c4878aSAndroid Build Coastguard Worker---------- 12*61c4878aSAndroid Build Coastguard WorkerQuickstart 13*61c4878aSAndroid Build Coastguard Worker---------- 14*61c4878aSAndroid Build Coastguard Worker.. tab-set:: 15*61c4878aSAndroid Build Coastguard Worker 16*61c4878aSAndroid Build Coastguard Worker .. tab-item:: Bazel 17*61c4878aSAndroid Build Coastguard Worker 18*61c4878aSAndroid Build Coastguard Worker Depend on the ``pw_i2c`` API and an appropriate implementation of the 19*61c4878aSAndroid Build Coastguard Worker API like ``pw_i2c_linux``. See :ref:`module-pw_i2c-impl` for the 20*61c4878aSAndroid Build Coastguard Worker list of existing implementations and to learn how to create your own. 21*61c4878aSAndroid Build Coastguard Worker 22*61c4878aSAndroid Build Coastguard Worker .. code-block:: python 23*61c4878aSAndroid Build Coastguard Worker 24*61c4878aSAndroid Build Coastguard Worker cc_library( 25*61c4878aSAndroid Build Coastguard Worker # ... 26*61c4878aSAndroid Build Coastguard Worker deps = [ 27*61c4878aSAndroid Build Coastguard Worker # ... 28*61c4878aSAndroid Build Coastguard Worker "@pigweed//pw_i2c:address", 29*61c4878aSAndroid Build Coastguard Worker "@pigweed//pw_i2c:device", 30*61c4878aSAndroid Build Coastguard Worker # ... 31*61c4878aSAndroid Build Coastguard Worker ] + select({ 32*61c4878aSAndroid Build Coastguard Worker "@platforms//os:linux": [ 33*61c4878aSAndroid Build Coastguard Worker "@pigweed//pw_i2c_linux:initiator", 34*61c4878aSAndroid Build Coastguard Worker ], 35*61c4878aSAndroid Build Coastguard Worker "//conditions:default": [ 36*61c4878aSAndroid Build Coastguard Worker # Fake example of a custom implementation. 37*61c4878aSAndroid Build Coastguard Worker "//lib/pw_i2c_my_device:initiator", 38*61c4878aSAndroid Build Coastguard Worker ], 39*61c4878aSAndroid Build Coastguard Worker }), 40*61c4878aSAndroid Build Coastguard Worker ) 41*61c4878aSAndroid Build Coastguard Worker 42*61c4878aSAndroid Build Coastguard Worker .. note:: 43*61c4878aSAndroid Build Coastguard Worker 44*61c4878aSAndroid Build Coastguard Worker This assumes that your Bazel ``WORKSPACE`` has a `repository 45*61c4878aSAndroid Build Coastguard Worker <https://bazel.build/concepts/build-ref#repositories>`_ named 46*61c4878aSAndroid Build Coastguard Worker ``@pigweed`` that points to the upstream Pigweed repository. 47*61c4878aSAndroid Build Coastguard Worker 48*61c4878aSAndroid Build Coastguard Worker If creating your own implementation, depend on the virtual interface: 49*61c4878aSAndroid Build Coastguard Worker 50*61c4878aSAndroid Build Coastguard Worker .. code-block:: python 51*61c4878aSAndroid Build Coastguard Worker 52*61c4878aSAndroid Build Coastguard Worker cc_library( 53*61c4878aSAndroid Build Coastguard Worker name = "initiator", 54*61c4878aSAndroid Build Coastguard Worker srcs = ["initiator.cc"], 55*61c4878aSAndroid Build Coastguard Worker hdrs = ["initiator.h"], 56*61c4878aSAndroid Build Coastguard Worker deps = ["@pigweed//pw_i2c:initiator"], 57*61c4878aSAndroid Build Coastguard Worker ) 58*61c4878aSAndroid Build Coastguard Worker 59*61c4878aSAndroid Build Coastguard WorkerWrite some C++ code to interact with an I2C device: 60*61c4878aSAndroid Build Coastguard Worker 61*61c4878aSAndroid Build Coastguard Worker.. include:: ../pw_i2c_rp2040/docs.rst 62*61c4878aSAndroid Build Coastguard Worker :start-after: .. pw_i2c_rp2040-example-start 63*61c4878aSAndroid Build Coastguard Worker :end-before: .. pw_i2c_rp2040-example-end 64*61c4878aSAndroid Build Coastguard Worker 65*61c4878aSAndroid Build Coastguard Worker.. _module-pw_i2c-guides: 66*61c4878aSAndroid Build Coastguard Worker 67*61c4878aSAndroid Build Coastguard Worker------ 68*61c4878aSAndroid Build Coastguard WorkerGuides 69*61c4878aSAndroid Build Coastguard Worker------ 70*61c4878aSAndroid Build Coastguard Worker 71*61c4878aSAndroid Build Coastguard Worker.. _module-pw_i2c-guides-mock: 72*61c4878aSAndroid Build Coastguard Worker 73*61c4878aSAndroid Build Coastguard WorkerMock I2C transactions 74*61c4878aSAndroid Build Coastguard Worker===================== 75*61c4878aSAndroid Build Coastguard WorkerSee the example in :cpp:class:`pw::i2c::MockInitiator`. 76*61c4878aSAndroid Build Coastguard Worker 77*61c4878aSAndroid Build Coastguard Worker.. _module-pw_i2c-guides-registerdevice: 78*61c4878aSAndroid Build Coastguard Worker 79*61c4878aSAndroid Build Coastguard WorkerConfigure and read an I2C device's registers 80*61c4878aSAndroid Build Coastguard Worker============================================ 81*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 82*61c4878aSAndroid Build Coastguard Worker 83*61c4878aSAndroid Build Coastguard Worker #include <chrono> 84*61c4878aSAndroid Build Coastguard Worker #include <cstddef> 85*61c4878aSAndroid Build Coastguard Worker #include <cstdint> 86*61c4878aSAndroid Build Coastguard Worker 87*61c4878aSAndroid Build Coastguard Worker #include "pw_bytes/bit.h" 88*61c4878aSAndroid Build Coastguard Worker #include "pw_i2c/address.h" 89*61c4878aSAndroid Build Coastguard Worker #include "pw_i2c/register_device.h" 90*61c4878aSAndroid Build Coastguard Worker #include "pw_log/log.h" 91*61c4878aSAndroid Build Coastguard Worker #include "pw_status/status.h" 92*61c4878aSAndroid Build Coastguard Worker 93*61c4878aSAndroid Build Coastguard Worker using ::pw::Status; 94*61c4878aSAndroid Build Coastguard Worker using namespace std::chrono_literals; 95*61c4878aSAndroid Build Coastguard Worker 96*61c4878aSAndroid Build Coastguard Worker // Search for `pi4ioe5v6416` in the Kudzu codebase to see real usage of 97*61c4878aSAndroid Build Coastguard Worker // pw::i2c::RegisterDevice 98*61c4878aSAndroid Build Coastguard Worker namespace pw::pi4ioe5v6416 { 99*61c4878aSAndroid Build Coastguard Worker 100*61c4878aSAndroid Build Coastguard Worker namespace { 101*61c4878aSAndroid Build Coastguard Worker 102*61c4878aSAndroid Build Coastguard Worker constexpr pw::i2c::Address kAddress = pw::i2c::Address::SevenBit<0x20>(); 103*61c4878aSAndroid Build Coastguard Worker enum Register : uint32_t { 104*61c4878aSAndroid Build Coastguard Worker InputPort0 = 0x0, 105*61c4878aSAndroid Build Coastguard Worker ConfigPort0 = 0x6, 106*61c4878aSAndroid Build Coastguard Worker PullUpDownEnablePort0 = 0x46, 107*61c4878aSAndroid Build Coastguard Worker PullUpDownSelectionPort0 = 0x48, 108*61c4878aSAndroid Build Coastguard Worker }; 109*61c4878aSAndroid Build Coastguard Worker 110*61c4878aSAndroid Build Coastguard Worker } // namespace 111*61c4878aSAndroid Build Coastguard Worker 112*61c4878aSAndroid Build Coastguard Worker // This particular example instantiates `pw::i2c::RegisterDevice` 113*61c4878aSAndroid Build Coastguard Worker // as part of a higher-level general "device" interface. 114*61c4878aSAndroid Build Coastguard Worker // See //lib/pi4ioe5v6416/public/pi4ioe5v6416/device.h in Kudzu. 115*61c4878aSAndroid Build Coastguard Worker Device::Device(pw::i2c::Initiator& initiator) 116*61c4878aSAndroid Build Coastguard Worker : initiator_(initiator), 117*61c4878aSAndroid Build Coastguard Worker register_device_(initiator, 118*61c4878aSAndroid Build Coastguard Worker kAddress, 119*61c4878aSAndroid Build Coastguard Worker endian::little, 120*61c4878aSAndroid Build Coastguard Worker pw::i2c::RegisterAddressSize::k1Byte) {} 121*61c4878aSAndroid Build Coastguard Worker 122*61c4878aSAndroid Build Coastguard Worker Status Device::Enable() { 123*61c4878aSAndroid Build Coastguard Worker // Set port 0 as inputs for buttons (1=input) 124*61c4878aSAndroid Build Coastguard Worker device_.WriteRegister8(Register::ConfigPort0, 125*61c4878aSAndroid Build Coastguard Worker 0xff, 126*61c4878aSAndroid Build Coastguard Worker pw::chrono::SystemClock::for_at_least(10ms)); 127*61c4878aSAndroid Build Coastguard Worker // Select pullup resistors for button input (1=pullup) 128*61c4878aSAndroid Build Coastguard Worker device_.WriteRegister8(Register::PullUpDownSelectionPort0, 129*61c4878aSAndroid Build Coastguard Worker 0xff, 130*61c4878aSAndroid Build Coastguard Worker pw::chrono::SystemClock::for_at_least(10ms)); 131*61c4878aSAndroid Build Coastguard Worker // Enable pullup/down resistors for button input (1=enable) 132*61c4878aSAndroid Build Coastguard Worker device_.WriteRegister8(Register::PullUpDownEnablePort0, 133*61c4878aSAndroid Build Coastguard Worker 0xff, 134*61c4878aSAndroid Build Coastguard Worker pw::chrono::SystemClock::for_at_least(10ms)); 135*61c4878aSAndroid Build Coastguard Worker return OkStatus(); 136*61c4878aSAndroid Build Coastguard Worker } 137*61c4878aSAndroid Build Coastguard Worker 138*61c4878aSAndroid Build Coastguard Worker pw::Result<uint8_t> Device::ReadPort0() { 139*61c4878aSAndroid Build Coastguard Worker return device_.ReadRegister8(Register::InputPort0, 140*61c4878aSAndroid Build Coastguard Worker pw::chrono::SystemClock::for_at_least(10ms)); 141*61c4878aSAndroid Build Coastguard Worker } 142*61c4878aSAndroid Build Coastguard Worker 143*61c4878aSAndroid Build Coastguard Worker } // namespace pw::pi4ioe5v6416 144*61c4878aSAndroid Build Coastguard Worker 145*61c4878aSAndroid Build Coastguard WorkerThe code example above was adapted from :ref:`docs-kudzu`. See the following 146*61c4878aSAndroid Build Coastguard Workerfiles for real ``pw::i2c::RegisterDevice`` usage: 147*61c4878aSAndroid Build Coastguard Worker 148*61c4878aSAndroid Build Coastguard Worker* `//lib/pi4ioe5v6416/device.cc <https://pigweed.googlesource.com/pigweed/kudzu/+/refs/heads/main/lib/pi4ioe5v6416/device.cc>`_ 149*61c4878aSAndroid Build Coastguard Worker* `//lib/pi4ioe5v6416/public/pi4ioe5v6416/device.h <https://pigweed.googlesource.com/pigweed/kudzu/+/refs/heads/main/lib/pi4ioe5v6416/public/pi4ioe5v6416/device.h>`_ 150*61c4878aSAndroid Build Coastguard Worker 151*61c4878aSAndroid Build Coastguard Worker.. _module-pw_i2c-guides-rpc: 152*61c4878aSAndroid Build Coastguard Worker 153*61c4878aSAndroid Build Coastguard WorkerAccess an I2C device's registers over RPC 154*61c4878aSAndroid Build Coastguard Worker========================================= 155*61c4878aSAndroid Build Coastguard Worker.. TODO: b/331292234 - Make this content less confusing and more helpful. 156*61c4878aSAndroid Build Coastguard Worker 157*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::i2c::I2cService` enables accessing an I2C device's registers 158*61c4878aSAndroid Build Coastguard Workerover RPC. 159*61c4878aSAndroid Build Coastguard Worker 160*61c4878aSAndroid Build Coastguard WorkerUsing :ref:`module-pw_console`, invoke the service to perform an I2C read: 161*61c4878aSAndroid Build Coastguard Worker 162*61c4878aSAndroid Build Coastguard Worker.. code-block:: python 163*61c4878aSAndroid Build Coastguard Worker 164*61c4878aSAndroid Build Coastguard Worker # Read register `0x0e` from the device at `0x22`. 165*61c4878aSAndroid Build Coastguard Worker device.rpcs.pw.i2c.I2c.I2cRead( 166*61c4878aSAndroid Build Coastguard Worker bus_index=0, 167*61c4878aSAndroid Build Coastguard Worker target_address=0x22, 168*61c4878aSAndroid Build Coastguard Worker register_address=b'\x0e', 169*61c4878aSAndroid Build Coastguard Worker read_size=1 170*61c4878aSAndroid Build Coastguard Worker ) 171*61c4878aSAndroid Build Coastguard Worker 172*61c4878aSAndroid Build Coastguard WorkerFor responders that support 4-byte register width, you can specify the register 173*61c4878aSAndroid Build Coastguard Workeraddress like this: 174*61c4878aSAndroid Build Coastguard Worker 175*61c4878aSAndroid Build Coastguard Worker.. code-block:: python 176*61c4878aSAndroid Build Coastguard Worker 177*61c4878aSAndroid Build Coastguard Worker device.rpcs.pw.i2c.I2c.I2cRead( 178*61c4878aSAndroid Build Coastguard Worker bus_index=0, 179*61c4878aSAndroid Build Coastguard Worker target_address=<address>, 180*61c4878aSAndroid Build Coastguard Worker register_address=b'\x00\x00\x00\x00', 181*61c4878aSAndroid Build Coastguard Worker read_size=4 182*61c4878aSAndroid Build Coastguard Worker ) 183*61c4878aSAndroid Build Coastguard Worker 184*61c4878aSAndroid Build Coastguard WorkerTo perform an I2C write: 185*61c4878aSAndroid Build Coastguard Worker 186*61c4878aSAndroid Build Coastguard Worker.. code-block:: python 187*61c4878aSAndroid Build Coastguard Worker 188*61c4878aSAndroid Build Coastguard Worker device.rpcs.pw.i2c.I2c.I2cWrite( 189*61c4878aSAndroid Build Coastguard Worker bus_index=0, 190*61c4878aSAndroid Build Coastguard Worker target_address=0x22, 191*61c4878aSAndroid Build Coastguard Worker register_address=b'\x0e', 192*61c4878aSAndroid Build Coastguard Worker value=b'\xbc' 193*61c4878aSAndroid Build Coastguard Worker ) 194*61c4878aSAndroid Build Coastguard Worker 195*61c4878aSAndroid Build Coastguard WorkerMulti-byte writes can also be specified with the bytes fields for 196*61c4878aSAndroid Build Coastguard Worker``register_address`` and ``value``. 197*61c4878aSAndroid Build Coastguard Worker 198*61c4878aSAndroid Build Coastguard WorkerI2C responders that require multi-byte access may expect a specific endianness. 199*61c4878aSAndroid Build Coastguard WorkerThe order of bytes specified in the bytes field will match the order of bytes 200*61c4878aSAndroid Build Coastguard Workersent or received on the bus. The maximum supported value for multi-byte access 201*61c4878aSAndroid Build Coastguard Workeris 4 bytes. 202