1 // Copyright 2021 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 // 15 #pragma once 16 17 #include "pw_bytes/span.h" 18 #include "pw_chrono/system_clock.h" 19 #include "pw_i2c/address.h" 20 #include "pw_i2c/initiator.h" 21 #include "pw_status/status.h" 22 23 namespace pw { 24 namespace i2c { 25 26 /// The common interface for generic I2C devices. Reads and writes arbitrary 27 /// chunks of data over an I2C bus to an I2C device. This class contains 28 /// `pw::i2c::Address` and wraps the `pw::i2c::Initiator` API. Only works 29 /// with devices that have a single device address. 30 /// 31 /// `pw::i2c::Device` is intended to represent ownership of a specific 32 /// responder. Individual transactions are atomic but there's no synchronization 33 /// for sequences of transactions. Therefore, shared access should be faciliated 34 /// with higher-level application abstractions. To help enforce this, 35 /// `pw::i2c::Device` instances are only movable and not copyable. 36 class Device { 37 public: 38 /// Creates a `pw::i2c::Device` instance. 39 /// 40 /// The address for the I2C device is set in this constructor and can't be 41 /// modified later. 42 /// 43 /// @param[in] initiator A reference to a `pw::i2c::Initiator` instance. 44 /// 45 /// @param[in] device_address The address of the I2C device. 46 /// 47 /// @returns A `pw::i2c::Device` instance. Device(Initiator & initiator,Address device_address)48 constexpr Device(Initiator& initiator, Address device_address) 49 : initiator_(initiator), device_address_(device_address) {} 50 51 Device(const Device&) = delete; 52 Device(Device&&) = default; 53 ~Device() = default; 54 55 /// Wraps `pw::i2c::Initiator::WriteReadFor`. WriteReadFor(ConstByteSpan tx_buffer,ByteSpan rx_buffer,chrono::SystemClock::duration timeout)56 Status WriteReadFor(ConstByteSpan tx_buffer, 57 ByteSpan rx_buffer, 58 chrono::SystemClock::duration timeout) { 59 return initiator_.WriteReadFor( 60 device_address_, tx_buffer, rx_buffer, timeout); 61 } 62 /// Wraps the variation of `pw::i2c::Initiator::WriteReadFor` that accepts 63 /// explicit sizes for the amount of bytes to write to the device and read 64 /// from the device. WriteReadFor(const void * tx_buffer,size_t tx_size_bytes,void * rx_buffer,size_t rx_size_bytes,chrono::SystemClock::duration timeout)65 Status WriteReadFor(const void* tx_buffer, 66 size_t tx_size_bytes, 67 void* rx_buffer, 68 size_t rx_size_bytes, 69 chrono::SystemClock::duration timeout) { 70 return initiator_.WriteReadFor(device_address_, 71 tx_buffer, 72 tx_size_bytes, 73 rx_buffer, 74 rx_size_bytes, 75 timeout); 76 } 77 78 /// Wraps `pw::i2c::Initiator::WriteFor`. WriteFor(ConstByteSpan tx_buffer,chrono::SystemClock::duration timeout)79 Status WriteFor(ConstByteSpan tx_buffer, 80 chrono::SystemClock::duration timeout) { 81 return initiator_.WriteFor(device_address_, tx_buffer, timeout); 82 } 83 /// Wraps the variation of `pw::i2c::Initiator::WriteFor` that accepts an 84 /// explicit size for the amount of bytes to write to the device. WriteFor(const void * tx_buffer,size_t tx_size_bytes,chrono::SystemClock::duration timeout)85 Status WriteFor(const void* tx_buffer, 86 size_t tx_size_bytes, 87 chrono::SystemClock::duration timeout) { 88 return initiator_.WriteFor( 89 device_address_, tx_buffer, tx_size_bytes, timeout); 90 } 91 92 /// Wraps `pw::i2c::Initiator::ReadFor`. ReadFor(ByteSpan rx_buffer,chrono::SystemClock::duration timeout)93 Status ReadFor(ByteSpan rx_buffer, chrono::SystemClock::duration timeout) { 94 return initiator_.ReadFor(device_address_, rx_buffer, timeout); 95 } 96 /// Wraps the variation of `pw::i2c::Initiator::ReadFor` that accepts an 97 /// explicit size for the amount of bytes to read from the device. ReadFor(void * rx_buffer,size_t rx_size_bytes,chrono::SystemClock::duration timeout)98 Status ReadFor(void* rx_buffer, 99 size_t rx_size_bytes, 100 chrono::SystemClock::duration timeout) { 101 return initiator_.ReadFor( 102 device_address_, rx_buffer, rx_size_bytes, timeout); 103 } 104 105 /// Wraps `pw::i2c::Initiator::ProbeDeviceFor`. ProbeFor(chrono::SystemClock::duration timeout)106 Status ProbeFor(chrono::SystemClock::duration timeout) { 107 return initiator_.ProbeDeviceFor(device_address_, timeout); 108 } 109 110 private: 111 Initiator& initiator_; 112 const Address device_address_; 113 }; 114 115 } // namespace i2c 116 } // namespace pw 117