diff --git a/esphome/components/i2c/i2c.cpp b/esphome/components/i2c/i2c.cpp index fdc9fd1ddf..2b2190d28b 100644 --- a/esphome/components/i2c/i2c.cpp +++ b/esphome/components/i2c/i2c.cpp @@ -14,6 +14,14 @@ ErrorCode I2CDevice::read_register(uint8_t a_register, uint8_t *data, size_t len return bus_->read(address_, data, len); } +ErrorCode I2CDevice::read_register16(uint16_t a_register, uint8_t *data, size_t len, bool stop) { + a_register = convert_big_endian(a_register); + ErrorCode const err = this->write(reinterpret_cast(&a_register), 2, stop); + if (err != ERROR_OK) + return err; + return bus_->read(address_, data, len); +} + ErrorCode I2CDevice::write_register(uint8_t a_register, const uint8_t *data, size_t len, bool stop) { WriteBuffer buffers[2]; buffers[0].data = &a_register; @@ -23,6 +31,16 @@ ErrorCode I2CDevice::write_register(uint8_t a_register, const uint8_t *data, siz return bus_->writev(address_, buffers, 2, stop); } +ErrorCode I2CDevice::write_register16(uint16_t a_register, const uint8_t *data, size_t len, bool stop) { + a_register = convert_big_endian(a_register); + WriteBuffer buffers[2]; + buffers[0].data = reinterpret_cast(&a_register); + buffers[0].len = 2; + buffers[1].data = data; + buffers[1].len = len; + return bus_->writev(address_, buffers, 2, stop); +} + bool I2CDevice::read_bytes_16(uint8_t a_register, uint16_t *data, uint8_t len) { if (read_register(a_register, reinterpret_cast(data), len * 2) != ERROR_OK) return false; @@ -60,5 +78,26 @@ uint8_t I2CRegister::get() const { return value; } +I2CRegister16 &I2CRegister16::operator=(uint8_t value) { + this->parent_->write_register16(this->register_, &value, 1); + return *this; +} +I2CRegister16 &I2CRegister16::operator&=(uint8_t value) { + value &= get(); + this->parent_->write_register16(this->register_, &value, 1); + return *this; +} +I2CRegister16 &I2CRegister16::operator|=(uint8_t value) { + value |= get(); + this->parent_->write_register16(this->register_, &value, 1); + return *this; +} + +uint8_t I2CRegister16::get() const { + uint8_t value = 0x00; + this->parent_->read_register16(this->register_, &value, 1); + return value; +} + } // namespace i2c } // namespace esphome diff --git a/esphome/components/i2c/i2c.h b/esphome/components/i2c/i2c.h index 780528a5c7..eb5d463b65 100644 --- a/esphome/components/i2c/i2c.h +++ b/esphome/components/i2c/i2c.h @@ -31,6 +31,25 @@ class I2CRegister { uint8_t register_; }; +class I2CRegister16 { + public: + I2CRegister16 &operator=(uint8_t value); + I2CRegister16 &operator&=(uint8_t value); + I2CRegister16 &operator|=(uint8_t value); + + explicit operator uint8_t() const { return get(); } + + uint8_t get() const; + + protected: + friend class I2CDevice; + + I2CRegister16(I2CDevice *parent, uint16_t a_register) : parent_(parent), register_(a_register) {} + + I2CDevice *parent_; + uint16_t register_; +}; + // like ntohs/htons but without including networking headers. // ("i2c" byte order is big-endian) inline uint16_t i2ctohs(uint16_t i2cshort) { return convert_big_endian(i2cshort); } @@ -44,12 +63,15 @@ class I2CDevice { void set_i2c_bus(I2CBus *bus) { bus_ = bus; } I2CRegister reg(uint8_t a_register) { return {this, a_register}; } + I2CRegister16 reg16(uint16_t a_register) { return {this, a_register}; } ErrorCode read(uint8_t *data, size_t len) { return bus_->read(address_, data, len); } ErrorCode read_register(uint8_t a_register, uint8_t *data, size_t len, bool stop = true); + ErrorCode read_register16(uint16_t a_register, uint8_t *data, size_t len, bool stop = true); ErrorCode write(const uint8_t *data, uint8_t len, bool stop = true) { return bus_->write(address_, data, len, stop); } ErrorCode write_register(uint8_t a_register, const uint8_t *data, size_t len, bool stop = true); + ErrorCode write_register16(uint16_t a_register, const uint8_t *data, size_t len, bool stop = true); // Compat APIs