ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
i2c.h
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <vector>
7#include "esphome/core/log.h"
9#include "i2c_bus.h"
10
11namespace esphome::i2c {
12
13#define LOG_I2C_DEVICE(this) ESP_LOGCONFIG(TAG, " Address: 0x%02X", this->address_);
14
15class I2CDevice; // forward declaration
16
19 uint8_t reg;
20 uint8_t value;
21};
22static_assert(sizeof(I2CRegValue) == 2, "each entry is sent to the bus as is");
23
25void log_wrong_chip_id(uint8_t id, uint8_t expected);
26
45 public:
49 I2CRegister &operator=(uint8_t value);
50
54 I2CRegister &operator&=(uint8_t value);
55
59 I2CRegister &operator|=(uint8_t value);
60
63 explicit operator uint8_t() const { return get(); }
64
67 uint8_t get() const;
68
69 protected:
70 friend class I2CDevice;
71
76 I2CRegister(I2CDevice *parent, uint8_t a_register) : parent_(parent), register_(a_register) {}
77
79 uint8_t register_;
80};
81
100 public:
104 I2CRegister16 &operator=(uint8_t value);
105
109 I2CRegister16 &operator&=(uint8_t value);
110
114 I2CRegister16 &operator|=(uint8_t value);
115
118 explicit operator uint8_t() const { return get(); }
119
122 uint8_t get() const;
123
124 protected:
125 friend class I2CDevice;
126
131 I2CRegister16(I2CDevice *parent, uint16_t a_register) : parent_(parent), register_(a_register) {}
132
134 uint16_t register_;
135};
136
137// like ntohs/htons but without including networking headers.
138// ("i2c" byte order is big-endian)
139inline uint16_t i2ctohs(uint16_t i2cshort) { return convert_big_endian(i2cshort); }
140inline uint16_t htoi2cs(uint16_t hostshort) { return convert_big_endian(hostshort); }
141
145 public:
147 I2CDevice() = default;
148
152
155 uint8_t get_i2c_address() const { return this->address_; }
156
159 void set_i2c_bus(I2CBus *bus) { bus_ = bus; }
160
164 I2CRegister reg(uint8_t a_register) { return {this, a_register}; }
165
169 I2CRegister16 reg16(uint16_t a_register) { return {this, a_register}; }
170
175 ErrorCode read(uint8_t *data, size_t len) const { return bus_->write_readv(this->address_, nullptr, 0, data, len); }
176
182 ErrorCode read_register(uint8_t a_register, uint8_t *data, size_t len);
183
189 ErrorCode read_register16(uint16_t a_register, uint8_t *data, size_t len);
190
195 ErrorCode write(const uint8_t *data, size_t len) const {
196 return bus_->write_readv(this->address_, data, len, nullptr, 0);
197 }
198
205 ErrorCode write_read(const uint8_t *write_data, size_t write_len, uint8_t *read_data, size_t read_len) const {
206 return bus_->write_readv(this->address_, write_data, write_len, read_data, read_len);
207 }
208
214 ErrorCode write_register(uint8_t a_register, const uint8_t *data, size_t len) const;
215
221 ErrorCode write_register16(uint16_t a_register, const uint8_t *data, size_t len) const;
222
225 bool write_registers(const I2CRegValue *table, size_t count) const;
226 template<size_t N> bool write_registers(const I2CRegValue (&table)[N]) const {
227 return this->write_registers(table, N);
228 }
229
232 bool check_chip_id(Component *component, uint8_t a_register, uint8_t expected, uint8_t mask = 0xFF) {
233 uint8_t id;
234 const ErrorCode err = this->read_register(a_register, &id, 1);
235 if (err == ERROR_OK && (id & mask) == (expected & mask))
236 return true;
237 if (err == ERROR_OK)
238 log_wrong_chip_id(id, expected & mask);
239 component->mark_failed(err == ERROR_OK ? LOG_STR("Wrong chip ID") : LOG_STR(ESP_LOG_MSG_COMM_FAIL));
240 return false;
241 }
242
248
249 bool read_bytes(uint8_t a_register, uint8_t *data, uint8_t len) {
250 return read_register(a_register, data, len) == ERROR_OK;
251 }
252
253 bool read_bytes_raw(uint8_t *data, uint8_t len) const { return read(data, len) == ERROR_OK; }
254
255 template<size_t N> optional<std::array<uint8_t, N>> read_bytes(uint8_t a_register) {
256 std::array<uint8_t, N> res;
257 if (!this->read_bytes(a_register, res.data(), N)) {
258 return {};
259 }
260 return res;
261 }
262 template<size_t N> optional<std::array<uint8_t, N>> read_bytes_raw() {
263 std::array<uint8_t, N> res;
264 if (!this->read_bytes_raw(res.data(), N)) {
265 return {};
266 }
267 return res;
268 }
269
270 bool read_bytes_16(uint8_t a_register, uint16_t *data, uint8_t len);
271
272 bool read_byte(uint8_t a_register, uint8_t *data) { return read_register(a_register, data, 1) == ERROR_OK; }
273
274 optional<uint8_t> read_byte(uint8_t a_register) {
275 uint8_t data;
276 if (!this->read_byte(a_register, &data))
277 return {};
278 return data;
279 }
280
281 bool read_byte_16(uint8_t a_register, uint16_t *data) { return read_bytes_16(a_register, data, 1); }
282
284 bool read_bytes_16_le(uint8_t a_register, uint16_t *data, uint8_t len) {
285 if (this->read_register(a_register, reinterpret_cast<uint8_t *>(data), len * 2) != ERROR_OK)
286 return false;
287 for (size_t i = 0; i < len; i++)
288 data[i] = convert_little_endian(data[i]);
289 return true;
290 }
291 bool read_bytes_16_le(uint8_t a_register, int16_t *data, uint8_t len) {
292 return this->read_bytes_16_le(a_register, reinterpret_cast<uint16_t *>(data), len);
293 }
294
296 bool read_byte_16_le(uint8_t a_register, uint16_t *data) { return this->read_bytes_16_le(a_register, data, 1); }
297
298 bool write_bytes(uint8_t a_register, const uint8_t *data, uint8_t len) const {
299 return write_register(a_register, data, len) == ERROR_OK;
300 }
301
302 bool write_bytes(uint8_t a_register, const std::vector<uint8_t> &data) const {
303 return write_bytes(a_register, data.data(), data.size());
304 }
305
306 template<size_t N> bool write_bytes(uint8_t a_register, const std::array<uint8_t, N> &data) {
307 return write_bytes(a_register, data.data(), data.size());
308 }
309
310 bool write_bytes_16(uint8_t a_register, const uint16_t *data, uint8_t len) const;
311
312 bool write_byte(uint8_t a_register, uint8_t data) const { return write_bytes(a_register, &data, 1); }
313
314 bool write_byte_16(uint8_t a_register, uint16_t data) const;
315
317 bool write_byte_16_le(uint8_t a_register, uint16_t data) const;
318
322 bool update_register(uint8_t a_register, uint8_t mask, uint8_t value);
323
324 protected:
325 I2CBus *bus_{nullptr};
326 // Last so a derived class can place its byte-sized members in the padding after it
327 uint8_t address_{0x00};
328};
329
330} // namespace esphome::i2c
uint8_t address
Definition bl0906.h:4
This Class provides the methods to read and write bytes from an I2CBus.
Definition i2c_bus.h:30
virtual ErrorCode write_readv(uint8_t address, const uint8_t *write_buffer, size_t write_count, uint8_t *read_buffer, size_t read_count)=0
This virtual method writes bytes to an I2CBus from an array, then reads bytes into an array of ReadBu...
This Class provides the methods to read/write bytes from/to an i2c device.
Definition i2c.h:144
ErrorCode write_register(uint8_t a_register, const uint8_t *data, size_t len) const
writes an array of bytes to a specific register in the I²C device
Definition i2c.cpp:37
ErrorCode write_read(const uint8_t *write_data, size_t write_len, uint8_t *read_data, size_t read_len) const
writes an array of bytes to a device, then reads an array, as a single transaction
Definition i2c.h:205
bool read_bytes_raw(uint8_t *data, uint8_t len) const
Definition i2c.h:253
bool write_bytes(uint8_t a_register, const std::array< uint8_t, N > &data)
Definition i2c.h:306
ErrorCode write_register16(uint16_t a_register, const uint8_t *data, size_t len) const
write an array of bytes to a specific register in the I²C device
Definition i2c.cpp:46
bool write_byte_16_le(uint8_t a_register, uint16_t data) const
Write a 16-bit value least significant byte first.
Definition i2c.cpp:106
bool check_chip_id(Component *component, uint8_t a_register, uint8_t expected, uint8_t mask=0xFF)
Read the 8-bit ID at a_register and accept it when it matches expected in the bits set in mask.
Definition i2c.h:232
bool write_bytes_16(uint8_t a_register, const uint16_t *data, uint8_t len) const
Definition i2c.cpp:87
void set_i2c_bus(I2CBus *bus)
we store the pointer to the I2CBus to use
Definition i2c.h:159
bool read_bytes_16_le(uint8_t a_register, uint16_t *data, uint8_t len)
Read len 16-bit values stored least significant byte first; no conversion is compiled on little-endia...
Definition i2c.h:284
ErrorCode write(const uint8_t *data, size_t len) const
writes an array of bytes to a device using an I2CBus
Definition i2c.h:195
uint8_t get_i2c_address() const
Returns the I2C address of the object.
Definition i2c.h:155
bool read_bytes_16_le(uint8_t a_register, int16_t *data, uint8_t len)
Definition i2c.h:291
bool write_registers(const I2CRegValue(&table)[N]) const
Definition i2c.h:226
optional< std::array< uint8_t, N > > read_bytes_raw()
Definition i2c.h:262
I2CBus * bus_
pointer to I2CBus instance
Definition i2c.h:325
optional< uint8_t > read_byte(uint8_t a_register)
Definition i2c.h:274
ErrorCode read(uint8_t *data, size_t len) const
reads an array of bytes from the device using an I2CBus
Definition i2c.h:175
uint8_t address_
store the address of the device on the bus
Definition i2c.h:327
bool write_byte(uint8_t a_register, uint8_t data) const
Definition i2c.h:312
bool read_byte(uint8_t a_register, uint8_t *data)
Definition i2c.h:272
bool read_byte_16(uint8_t a_register, uint16_t *data)
Definition i2c.h:281
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
Definition i2c.h:164
ErrorCode read_register16(uint16_t a_register, uint8_t *data, size_t len)
reads an array of bytes from a specific register in the I²C device
Definition i2c.cpp:32
optional< std::array< uint8_t, N > > read_bytes(uint8_t a_register)
Definition i2c.h:255
void set_i2c_address(uint8_t address)
We store the address of the device on the bus.
Definition i2c.h:151
bool write_bytes(uint8_t a_register, const std::vector< uint8_t > &data) const
Definition i2c.h:302
ErrorCode read_register(uint8_t a_register, uint8_t *data, size_t len)
reads an array of bytes from a specific register in the I²C device
Definition i2c.cpp:28
bool read_bytes_16(uint8_t a_register, uint16_t *data, uint8_t len)
Definition i2c.cpp:70
bool write_bytes(uint8_t a_register, const uint8_t *data, uint8_t len) const
Definition i2c.h:298
bool write_byte_16(uint8_t a_register, uint16_t data) const
Definition i2c.cpp:101
I2CRegister16 reg16(uint16_t a_register)
calls the I2CRegister16 constructor
Definition i2c.h:169
bool update_register(uint8_t a_register, uint8_t mask, uint8_t value)
Read a register, replace the bits in mask with those of value and write it back.
Definition i2c.cpp:78
bool read_bytes(uint8_t a_register, uint8_t *data, uint8_t len)
Compat APIs All methods below have been added for compatibility reasons.
Definition i2c.h:249
bool write_registers(const I2CRegValue *table, size_t count) const
Write each register and value of table in order, stopping at the first failure.
Definition i2c.cpp:56
bool read_byte_16_le(uint8_t a_register, uint16_t *data)
Read a 16-bit value stored least significant byte first.
Definition i2c.h:296
I2CDevice()=default
we use the C++ default constructor
This class is used to create I2CRegister16 objects that act as proxies to read/write internal registe...
Definition i2c.h:99
uint16_t register_
the internal 16 bits address of the register
Definition i2c.h:134
I2CRegister16(I2CDevice *parent, uint16_t a_register)
protected constructor that store the owning object and the register address.
Definition i2c.h:131
I2CRegister16 & operator&=(uint8_t value)
overloads the compound &= operator.
Definition i2c.cpp:136
I2CRegister16 & operator|=(uint8_t value)
overloads the compound |= operator.
Definition i2c.cpp:141
I2CDevice * parent_
I2CDevice object pointer.
Definition i2c.h:133
uint8_t get() const
returns the register value
Definition i2c.cpp:147
I2CRegister16 & operator=(uint8_t value)
overloads the = operator.
Definition i2c.cpp:132
This class is used to create I2CRegister objects that act as proxies to read/write internal registers...
Definition i2c.h:44
I2CRegister(I2CDevice *parent, uint8_t a_register)
protected constructor that stores the owning object and the register address.
Definition i2c.h:76
I2CRegister & operator|=(uint8_t value)
overloads the compound |= operator.
Definition i2c.cpp:120
uint8_t get() const
returns the register value
Definition i2c.cpp:126
I2CRegister & operator&=(uint8_t value)
overloads the compound &= operator.
Definition i2c.cpp:115
I2CDevice * parent_
I2CDevice object pointer.
Definition i2c.h:78
uint8_t register_
the internal address of the register
Definition i2c.h:79
I2CRegister & operator=(uint8_t value)
overloads the = operator.
Definition i2c.cpp:111
const Component * component
Definition component.cpp:34
uint16_t id
unsigned count
Definition gif.cpp:51
uint16_t i2ctohs(uint16_t i2cshort)
Definition i2c.h:139
ErrorCode
Error codes returned by I2CBus and I2CDevice methods.
Definition i2c_bus.h:13
@ ERROR_OK
No error found during execution of method.
Definition i2c_bus.h:15
void log_wrong_chip_id(uint8_t id, uint8_t expected)
Out of line so each check_chip_id() caller only pays for a call.
Definition i2c.cpp:24
uint16_t htoi2cs(uint16_t hostshort)
Definition i2c.h:140
constexpr T convert_big_endian(T val)
Convert a value between host byte order and big endian (most significant byte first) order.
Definition helpers.h:1098
constexpr T convert_little_endian(T val)
Convert a value between host byte order and little endian (least significant byte first) order.
Definition helpers.h:1107
const void size_t len
Definition hal.h:68
One register write for I2CDevice::write_registers(); tables of these may live in PROGMEM.
Definition i2c.h:18