ESPHome 2026.3.0
Loading...
Searching...
No Matches
i2c_sensirion.cpp
Go to the documentation of this file.
1#include "i2c_sensirion.h"
2#include "esphome/core/hal.h"
4#include "esphome/core/log.h"
5#include <cinttypes>
6
7namespace esphome {
8namespace sensirion_common {
9
10static const char *const TAG = "sensirion_i2c";
11// To avoid memory allocations for small writes a stack buffer is used
12static const size_t BUFFER_STACK_SIZE = 16;
13
14bool SensirionI2CDevice::read_data(uint16_t *data, const uint8_t len) {
15 const size_t required_buffer_len = len * 3;
16 SmallBufferWithHeapFallback<BUFFER_STACK_SIZE> buffer(required_buffer_len);
17 uint8_t *temp = buffer.get();
18
19 this->last_error_ = this->read(temp, required_buffer_len);
20 if (this->last_error_ != i2c::ERROR_OK) {
21 return false;
22 }
23
24 for (size_t i = 0; i < len; i++) {
25 const size_t j = i * 3;
26 // Use MSB first since Sensirion devices use CRC-8 with MSB first
27 uint8_t crc = crc8(&temp[j], 2, 0xFF, CRC_POLYNOMIAL, true);
28 if (crc != temp[j + 2]) {
29 ESP_LOGE(TAG, "CRC invalid @ %zu! 0x%02X != 0x%02X", i, temp[j + 2], crc);
31 return false;
32 }
33 data[i] = encode_uint16(temp[j], temp[j + 1]);
34 }
35 return true;
36}
37/***
38 * write command with parameters and insert crc
39 * use stack array for less than 4 parameters. Most Sensirion I2C commands have less parameters
40 */
41bool SensirionI2CDevice::write_command_(uint16_t command, CommandLen command_len, const uint16_t *data,
42 const uint8_t data_len) {
43 size_t required_buffer_len = data_len * 3 + 2;
44 SmallBufferWithHeapFallback<BUFFER_STACK_SIZE> buffer(required_buffer_len);
45 uint8_t *temp = buffer.get();
46 // First byte or word is the command
47 uint8_t raw_idx = 0;
48 if (command_len == 1) {
49 temp[raw_idx++] = command & 0xFF;
50 } else {
51 // command is 2 bytes
52 temp[raw_idx++] = command >> 8;
53 temp[raw_idx++] = command & 0xFF;
54 }
55 // add parameters followed by crc
56 // skipped if len == 0
57 for (size_t i = 0; i < data_len; i++) {
58 temp[raw_idx++] = data[i] >> 8;
59 temp[raw_idx++] = data[i] & 0xFF;
60 // Use MSB first since Sensirion devices use CRC-8 with MSB first
61 uint8_t crc = crc8(&temp[raw_idx - 2], 2, 0xFF, CRC_POLYNOMIAL, true);
62 temp[raw_idx++] = crc;
63 }
64 this->last_error_ = this->write(temp, raw_idx);
65 return this->last_error_ == i2c::ERROR_OK;
66}
67
68bool SensirionI2CDevice::get_register_(uint16_t reg, CommandLen command_len, uint16_t *data, const uint8_t len,
69 const uint8_t delay_ms) {
70 if (!this->write_command_(reg, command_len, nullptr, 0)) {
71 ESP_LOGE(TAG, "Write failed: reg=0x%X (%d) err=%d,", reg, command_len, this->last_error_);
72 return false;
73 }
74 delay(delay_ms);
75 bool result = this->read_data(data, len);
76 if (!result) {
77 ESP_LOGE(TAG, "Read failed: reg=0x%X err=%d,", reg, this->last_error_);
78 }
79 return result;
80}
81
82} // namespace sensirion_common
83} // namespace esphome
Helper class for efficient buffer allocation - uses stack for small sizes, heap for large This is use...
Definition helpers.h:558
ErrorCode write(const uint8_t *data, size_t len) const
writes an array of bytes to a device using an I2CBus
Definition i2c.h:183
ErrorCode read(uint8_t *data, size_t len) const
reads an array of bytes from the device using an I2CBus
Definition i2c.h:163
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
Definition i2c.h:152
bool get_register_(uint16_t reg, CommandLen command_len, uint16_t *data, uint8_t len, uint8_t delay)
get data words from I2C register.
i2c::ErrorCode last_error_
last error code from I2C operation
bool read_data(uint16_t *data, uint8_t len)
Read data words from I2C device.
bool write_command_(uint16_t command, CommandLen command_len, const uint16_t *data, uint8_t data_len)
Write a command with arguments as words.
@ ERROR_CRC
bytes received with a CRC error
Definition i2c_bus.h:21
@ ERROR_OK
No error found during execution of method.
Definition i2c_bus.h:14
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string size_t len
Definition helpers.h:892
uint8_t crc8(const uint8_t *data, uint8_t len, uint8_t crc, uint8_t poly, bool msb_first)
Calculate a CRC-8 checksum of data with size len.
Definition helpers.cpp:46
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
Definition helpers.h:728
void HOT delay(uint32_t ms)
Definition core.cpp:28