Compare commits

..
11 changed files with 75 additions and 31 deletions

No files matched your search

@@ -114,10 +114,10 @@ void BME280Component::setup() {
this->calibration_.h1 = read_u8_(BME280_REGISTER_DIG_H1);
this->calibration_.h2 = read_s16_le_(BME280_REGISTER_DIG_H2);
this->calibration_.h3 = read_u8_(BME280_REGISTER_DIG_H3);
this->calibration_.h4 =
sign_extend<12>(read_u8_(BME280_REGISTER_DIG_H4) << 4 | (read_u8_(BME280_REGISTER_DIG_H4 + 1) & 0x0F));
this->calibration_.h5 =
sign_extend<12>(read_u8_(BME280_REGISTER_DIG_H5 + 1) << 4 | (read_u8_(BME280_REGISTER_DIG_H5) >> 4));
this->calibration_.h4 = sign_extend<12>(
encode_uint12(read_u8_(BME280_REGISTER_DIG_H4), low_nibble(read_u8_(BME280_REGISTER_DIG_H4 + 1))));
this->calibration_.h5 = sign_extend<12>(
encode_uint12(read_u8_(BME280_REGISTER_DIG_H5 + 1), high_nibble(read_u8_(BME280_REGISTER_DIG_H5))));
this->calibration_.h6 = read_u8_(BME280_REGISTER_DIG_H6);
uint8_t humid_control_val = 0;
+4 -3
View File
@@ -70,8 +70,9 @@ bool BME680Component::setup_registers_() {
this->calibration_.t2 = encode_value_le<int16_t>(&coeff1[1]);
this->calibration_.t3 = coeff1[3];
this->calibration_.h1 = coeff2[2] << 4 | (coeff2[1] & 0x0F);
this->calibration_.h2 = encode_uint16(coeff2[0], coeff2[1]) >> 4;
// H1 and H2 are 12-bit values sharing byte 1: its low nibble ends H1, its high nibble ends H2
this->calibration_.h1 = encode_uint12(coeff2[2], low_nibble(coeff2[1]));
this->calibration_.h2 = encode_uint12(coeff2[0], high_nibble(coeff2[1]));
this->calibration_.h3 = coeff2[3];
this->calibration_.h4 = coeff2[4];
this->calibration_.h5 = coeff2[5];
@@ -243,7 +244,7 @@ void BME680Component::read_data_() {
uint32_t raw_pressure = encode_uint24(data[2], data[3], data[4]) >> 4;
uint32_t raw_humidity = encode_uint16(data[8], data[9]);
uint16_t raw_gas = encode_uint16(data[13], data[14]) >> 6;
uint8_t gas_range = data[14] & 0x0F;
uint8_t gas_range = low_nibble(data[14]);
float temperature = this->calc_temperature_(raw_temperature);
float pressure = this->calc_pressure_(raw_pressure);
@@ -1,4 +1,5 @@
#include "cst328_touchscreen.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome::cst328 {
@@ -99,7 +100,7 @@ void CST328Touchscreen::update_touches() {
return;
}
uint8_t touch_cnt = touch_data[CST_REG_FINGER_COUNT_IDX] & 0x0F;
uint8_t touch_cnt = low_nibble(touch_data[CST_REG_FINGER_COUNT_IDX]);
if (touch_cnt == 0 || touch_cnt > CST328_TOUCH_MAX_POINTS) {
this->update_button_state_(false);
} else {
+10 -3
View File
@@ -37,11 +37,18 @@ struct TouchRecord {
uint8_t z;
};
/// Decodes record `index` of a touch report.
/// Decodes record `index` of a touch report. Each record is 5 bytes:
/// [id:4 | event:4] [x 11..4] [y 11..4] [x 3..0 | y 3..0] [z].
/// The first record is followed by 2 extra bytes, so later records start 2 bytes further on.
inline TouchRecord decode_touch(const uint8_t *report, uint8_t index) {
const uint8_t *r = report + index * 5 + (index == 0 ? 0 : 2);
return {static_cast<uint8_t>(r[0] >> 4), static_cast<uint8_t>(r[0] & 0x0F),
static_cast<uint16_t>(r[1] << 4 | r[3] >> 4), static_cast<uint16_t>(r[2] << 4 | (r[3] & 0x0F)), r[4]};
return {
.id = high_nibble(r[0]),
.event = low_nibble(r[0]),
.x = encode_uint12(r[1], high_nibble(r[3])),
.y = encode_uint12(r[2], low_nibble(r[3])),
.z = r[4],
};
}
class CSTTouchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice {
@@ -35,12 +35,12 @@ void EKTF2232Touchscreen::setup() {
if (err == i2c::ERROR_OK) {
err = this->read(received, 4);
if (err == i2c::ERROR_OK) {
this->x_raw_max_ = ((received[2])) | ((received[3] & 0xf0) << 4);
this->x_raw_max_ = encode_uint16(high_nibble(received[3]), received[2]);
err = this->write(GET_Y_RES, 4);
if (err == i2c::ERROR_OK) {
err = this->read(received, 4);
if (err == i2c::ERROR_OK) {
this->y_raw_max_ = ((received[2])) | ((received[3] & 0xf0) << 4);
this->y_raw_max_ = encode_uint16(high_nibble(received[3]), received[2]);
}
}
}
@@ -74,8 +74,9 @@ void EKTF2232Touchscreen::update_touches() {
for (int i = 0; i < touch_count; i++) {
uint8_t *d = raw + 1 + (i * 3);
x_raw = (d[0] & 0xF0) << 4 | d[1];
y_raw = (d[0] & 0x0F) << 8 | d[2];
// d[0] holds the top 4 bits of X (high nibble) and of Y (low nibble)
x_raw = encode_uint16(high_nibble(d[0]), d[1]);
y_raw = encode_uint16(low_nibble(d[0]), d[2]);
this->add_raw_touch_position_(i, x_raw, y_raw);
}
}
@@ -69,8 +69,8 @@ void FT5x06Touchscreen::update_touches() {
for (uint8_t i = 0; i != touch_cnt; i++) {
uint8_t status = data[i][0] >> 6;
uint8_t id = data[i][2] >> 3;
uint16_t x = encode_uint16(data[i][0] & 0x0F, data[i][1]);
uint16_t y = encode_uint16(data[i][2] & 0xF, data[i][3]);
uint16_t x = encode_uint16(low_nibble(data[i][0]), data[i][1]);
uint16_t y = encode_uint16(low_nibble(data[i][2]), data[i][3]);
ESP_LOGV(TAG, "Read %X status, id: %d, pos %d/%d", status, id, x, y);
if (status == 0 || status == 2) {
+5 -5
View File
@@ -90,31 +90,31 @@ void FT63X6Touchscreen::update_touches() {
}
}
uint8_t FT63X6Touchscreen::read_touch_number_() { return this->read_byte_(FT63X6_ADDR_TD_STATUS) & 0x0F; }
uint8_t FT63X6Touchscreen::read_touch_number_() { return low_nibble(this->read_byte_(FT63X6_ADDR_TD_STATUS)); }
// Touch 1 functions
uint16_t FT63X6Touchscreen::read_touch_x_(uint8_t touch) {
uint8_t read_buf[2];
read_buf[0] = this->read_byte_(FT63X6_ADDR_TOUCH1_X + (touch * 6));
read_buf[1] = this->read_byte_(FT63X6_ADDR_TOUCH1_X + 1 + (touch * 6));
return encode_uint16(read_buf[0] & 0x0f, read_buf[1]);
return encode_uint16(low_nibble(read_buf[0]), read_buf[1]);
}
uint16_t FT63X6Touchscreen::read_touch_y_(uint8_t touch) {
uint8_t read_buf[2];
read_buf[0] = this->read_byte_(FT63X6_ADDR_TOUCH1_Y + (touch * 6));
read_buf[1] = this->read_byte_(FT63X6_ADDR_TOUCH1_Y + 1 + (touch * 6));
return encode_uint16(read_buf[0] & 0x0f, read_buf[1]);
return encode_uint16(low_nibble(read_buf[0]), read_buf[1]);
}
uint8_t FT63X6Touchscreen::read_touch_event_(uint8_t touch) {
return this->read_byte_(FT63X6_ADDR_TOUCH1_X + (touch * 6)) >> 6;
}
uint8_t FT63X6Touchscreen::read_touch_id_(uint8_t touch) {
return this->read_byte_(FT63X6_ADDR_TOUCH1_ID + (touch * 6)) >> 4;
return high_nibble(this->read_byte_(FT63X6_ADDR_TOUCH1_ID + (touch * 6)));
}
uint8_t FT63X6Touchscreen::read_touch_weight_(uint8_t touch) {
return this->read_byte_(FT63X6_ADDR_TOUCH1_WEIGHT + (touch * 6));
}
uint8_t FT63X6Touchscreen::read_touch_misc_(uint8_t touch) {
return this->read_byte_(FT63X6_ADDR_TOUCH1_MISC + (touch * 6)) >> 4;
return high_nibble(this->read_byte_(FT63X6_ADDR_TOUCH1_MISC + (touch * 6)));
}
uint8_t FT63X6Touchscreen::read_byte_(uint8_t addr) {
@@ -1,6 +1,7 @@
#include "gsl3670_touchscreen.h"
#include "esphome/core/log.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
namespace esphome::gsl3670 {
@@ -66,10 +67,11 @@ void GSL3670Touchscreen::update_touches() {
// Build gsl_touch_info exactly as the Seeed driver does
for (uint8_t j = 0; j != finger_num; j++) {
// buf[(j+1)*4 + 0..3]: byte0=y_lo, byte1=y_hi, byte2=x_lo, byte3=id|x_hi
auto x = (uint16_t) (((buf[(j + 1) * 4 + 3] & 0x0f) << 8) | buf[(j + 1) * 4 + 2]);
auto y = (uint16_t) ((buf[(j + 1) * 4 + 1] << 8) | buf[(j + 1) * 4 + 0]);
auto id = (buf[(j + 1) * 4 + 3] >> 4) & 0x0f;
// Record: y_lo, y_hi, x_lo, then the id (high nibble) and the top 4 bits of X (low nibble)
const uint8_t *record = &buf[(j + 1) * 4];
auto x = encode_uint16(low_nibble(record[3]), record[2]);
auto y = encode_uint16(record[1], record[0]);
auto id = high_nibble(record[3]);
ESP_LOGV(TAG, "Touch id=%u, x=%u y=%u", id, x, y);
if (x <= 8192 && y <= 8192)
this->add_raw_touch_position_(id, x, y);
@@ -62,7 +62,7 @@ void LilygoT547Touchscreen::update_touches() {
return;
}
point = buffer[5] & 0xF;
point = low_nibble(buffer[5]);
if (point > 2) {
ESP_LOGW(TAG, "Invalid touch point count: %d", point);
point = 2;
@@ -88,9 +88,11 @@ void LilygoT547Touchscreen::update_touches() {
uint16_t id, x_raw, y_raw;
for (uint8_t i = 0; i < point; i++) {
id = (buffer[i * 5] >> 4) & 0x0F;
y_raw = (uint16_t) ((buffer[i * 5 + 1] << 4) | ((buffer[i * 5 + 3] >> 4) & 0x0F));
x_raw = (uint16_t) ((buffer[i * 5 + 2] << 4) | (buffer[i * 5 + 3] & 0x0F));
const uint8_t *record = buffer + i * 5;
id = high_nibble(record[0]);
// The low 4 bits of Y and X share byte 3
y_raw = encode_uint12(record[1], high_nibble(record[3]));
x_raw = encode_uint12(record[2], low_nibble(record[3]));
this->add_raw_touch_position_(id, x_raw, y_raw);
}
+11 -1
View File
@@ -1155,6 +1155,16 @@ bool random_bytes(uint8_t *data, size_t len);
/// @name Bit manipulation
///@{
/// The high 4 bits of a byte, e.g. high_nibble(0xA5) == 0xA.
constexpr uint8_t high_nibble(uint8_t byte) { return byte >> 4; }
/// The low 4 bits of a byte, e.g. low_nibble(0xA5) == 0x5.
constexpr uint8_t low_nibble(uint8_t byte) { return byte & 0x0F; }
/// Encode a 12-bit value from its high 8 and low 4 bits, e.g. encode_uint12(0x12, 0x3) == 0x123.
/// Bits above the low 4 of \p low_bits are ignored.
constexpr uint16_t encode_uint12(uint8_t high_bits, uint8_t low_bits) {
return (static_cast<uint16_t>(high_bits) << 4) | low_nibble(low_bits);
}
/// Encode a 16-bit value given the most and least significant byte.
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb) {
return (static_cast<uint16_t>(msb) << 8) | (static_cast<uint16_t>(lsb));
@@ -1257,7 +1267,7 @@ constexpr uint8_t *put_le32(uint8_t *dst, uint32_t value) {
}
/// Decode a two-digit packed BCD byte (tens in the high nibble) to its value, e.g. 0x59 to 59.
constexpr uint8_t bcd_to_uint8(uint8_t bcd) { return (bcd >> 4) * 10 + (bcd & 0x0F); }
constexpr uint8_t bcd_to_uint8(uint8_t bcd) { return high_nibble(bcd) * 10 + low_nibble(bcd); }
/// Encode a value from 0 to 99 as a two-digit packed BCD byte, e.g. 59 to 0x59.
constexpr uint8_t uint8_to_bcd(uint8_t value) { return ((value / 10) << 4) | (value % 10); }
+20
View File
@@ -55,6 +55,26 @@ TEST(HelpersTest, Ilog10RoundTripMatchesLog10) {
}
}
TEST(HelpersTest, Nibbles) {
EXPECT_EQ(high_nibble(0xA5), 0xA);
EXPECT_EQ(low_nibble(0xA5), 0x5);
EXPECT_EQ(high_nibble(0x0F), 0x0);
EXPECT_EQ(low_nibble(0xF0), 0x0);
static_assert(high_nibble(0xFF) == 0xF && low_nibble(0xFF) == 0xF, "usable in constant expressions");
}
TEST(HelpersTest, EncodeUint12) {
EXPECT_EQ(encode_uint12(0x12, 0x3), 0x123);
EXPECT_EQ(encode_uint12(0xFF, 0xF), 0xFFF);
EXPECT_EQ(encode_uint12(0x00, 0x0), 0x000);
EXPECT_EQ(encode_uint12(0x12, 0xA3), 0x123);
// A touch record byte packing the low nibbles of X (high) and Y (low)
const uint8_t shared = 0x5C;
EXPECT_EQ(encode_uint12(0x34, high_nibble(shared)), 0x345);
EXPECT_EQ(encode_uint12(0x67, low_nibble(shared)), 0x67C);
static_assert(encode_uint12(0xAB, 0xC) == 0xABC, "usable in constant expressions");
}
TEST(HelpersTest, SignExtend) {
EXPECT_EQ(sign_extend<24>(0x000000), 0);
EXPECT_EQ(sign_extend<24>(0x7FFFFF), 8388607);