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