mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 06:33:51 +00:00 
			
		
		
		
	Merge branch 'i2c_std_vector_heap' into memory_api
This commit is contained in:
		| @@ -39,18 +39,22 @@ ErrorCode I2CDevice::read_register16(uint16_t a_register, uint8_t *data, size_t | ||||
| } | ||||
|  | ||||
| ErrorCode I2CDevice::write_register(uint8_t a_register, const uint8_t *data, size_t len) const { | ||||
|   std::vector<uint8_t> v{}; | ||||
|   v.push_back(a_register); | ||||
|   v.insert(v.end(), data, data + len); | ||||
|   return bus_->write_readv(this->address_, v.data(), v.size(), nullptr, 0); | ||||
|   SmallBufferWithHeapFallback<17> buffer_alloc;  // Most I2C writes are <= 16 bytes | ||||
|   uint8_t *buffer = buffer_alloc.get(len + 1); | ||||
|  | ||||
|   buffer[0] = a_register; | ||||
|   std::copy(data, data + len, buffer + 1); | ||||
|   return bus_->write_readv(this->address_, buffer, len + 1, nullptr, 0); | ||||
| } | ||||
|  | ||||
| ErrorCode I2CDevice::write_register16(uint16_t a_register, const uint8_t *data, size_t len) const { | ||||
|   std::vector<uint8_t> v(len + 2); | ||||
|   v[0] = a_register >> 8; | ||||
|   v[1] = a_register; | ||||
|   std::copy(data, data + len, v.begin() + 2); | ||||
|   return bus_->write_readv(this->address_, v.data(), v.size(), nullptr, 0); | ||||
|   SmallBufferWithHeapFallback<18> buffer_alloc;  // Most I2C writes are <= 16 bytes + 2 for register | ||||
|   uint8_t *buffer = buffer_alloc.get(len + 2); | ||||
|  | ||||
|   buffer[0] = a_register >> 8; | ||||
|   buffer[1] = a_register; | ||||
|   std::copy(data, data + len, buffer + 2); | ||||
|   return bus_->write_readv(this->address_, buffer, len + 2, nullptr, 0); | ||||
| } | ||||
|  | ||||
| bool I2CDevice::read_bytes_16(uint8_t a_register, uint16_t *data, uint8_t len) { | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
| #include <cstddef> | ||||
| #include <cstdint> | ||||
| #include <cstring> | ||||
| #include <memory> | ||||
| #include <utility> | ||||
| #include <vector> | ||||
|  | ||||
| @@ -10,6 +11,22 @@ | ||||
| namespace esphome { | ||||
| namespace i2c { | ||||
|  | ||||
| /// @brief Helper class for efficient buffer allocation - uses stack for small sizes, heap for large | ||||
| template<size_t STACK_SIZE> class SmallBufferWithHeapFallback { | ||||
|  public: | ||||
|   uint8_t *get(size_t size) { | ||||
|     if (size <= STACK_SIZE) { | ||||
|       return stack_buffer_; | ||||
|     } | ||||
|     heap_buffer_ = std::unique_ptr<uint8_t[]>(new uint8_t[size]); | ||||
|     return heap_buffer_.get(); | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   uint8_t stack_buffer_[STACK_SIZE]; | ||||
|   std::unique_ptr<uint8_t[]> heap_buffer_; | ||||
| }; | ||||
|  | ||||
| /// @brief Error codes returned by I2CBus and I2CDevice methods | ||||
| enum ErrorCode { | ||||
|   NO_ERROR = 0,                ///< No error found during execution of method | ||||
| @@ -74,14 +91,17 @@ class I2CBus { | ||||
|     for (size_t i = 0; i != count; i++) { | ||||
|       total_len += read_buffers[i].len; | ||||
|     } | ||||
|     std::vector<uint8_t> buffer(total_len); | ||||
|     auto err = this->write_readv(address, nullptr, 0, buffer.data(), total_len); | ||||
|  | ||||
|     SmallBufferWithHeapFallback<128> buffer_alloc;  // Most I2C reads are small | ||||
|     uint8_t *buffer = buffer_alloc.get(total_len); | ||||
|  | ||||
|     auto err = this->write_readv(address, nullptr, 0, buffer, total_len); | ||||
|     if (err != ERROR_OK) | ||||
|       return err; | ||||
|     size_t pos = 0; | ||||
|     for (size_t i = 0; i != count; i++) { | ||||
|       if (read_buffers[i].len != 0) { | ||||
|         std::memcpy(read_buffers[i].data, buffer.data() + pos, read_buffers[i].len); | ||||
|         std::memcpy(read_buffers[i].data, buffer + pos, read_buffers[i].len); | ||||
|         pos += read_buffers[i].len; | ||||
|       } | ||||
|     } | ||||
| @@ -91,11 +111,21 @@ class I2CBus { | ||||
|   ESPDEPRECATED("This method is deprecated and will be removed in ESPHome 2026.3.0. Use write_readv() instead.", | ||||
|                 "2025.9.0") | ||||
|   ErrorCode writev(uint8_t address, const WriteBuffer *write_buffers, size_t count, bool stop = true) { | ||||
|     std::vector<uint8_t> buffer{}; | ||||
|     size_t total_len = 0; | ||||
|     for (size_t i = 0; i != count; i++) { | ||||
|       buffer.insert(buffer.end(), write_buffers[i].data, write_buffers[i].data + write_buffers[i].len); | ||||
|       total_len += write_buffers[i].len; | ||||
|     } | ||||
|     return this->write_readv(address, buffer.data(), buffer.size(), nullptr, 0); | ||||
|  | ||||
|     SmallBufferWithHeapFallback<128> buffer_alloc;  // Most I2C writes are small | ||||
|     uint8_t *buffer = buffer_alloc.get(total_len); | ||||
|  | ||||
|     size_t pos = 0; | ||||
|     for (size_t i = 0; i != count; i++) { | ||||
|       std::memcpy(buffer + pos, write_buffers[i].data, write_buffers[i].len); | ||||
|       pos += write_buffers[i].len; | ||||
|     } | ||||
|  | ||||
|     return this->write_readv(address, buffer, total_len, nullptr, 0); | ||||
|   } | ||||
|  | ||||
|  protected: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user