[components] Decode bytes with the shared helpers (#21080)

This commit is contained in:
J. Nick Koston
2026-10-18 20:00:48 -04:00
committed by GitHub
parent 03bf2de7df
commit d9242520e3
39 changed files with 136 additions and 230 deletions
+1 -6
View File
@@ -69,12 +69,7 @@ bool AM2320Component::read_data_(uint8_t *data) {
return false;
}
uint16_t checksum;
checksum = data[7] << 8;
checksum += data[6];
if (crc16(data, 6) != checksum) {
if (crc16(data, 6) != encode_value_le<uint16_t>(&data[6])) {
ESP_LOGW(TAG, "AM2320 Checksum invalid!");
return false;
}
+6 -6
View File
@@ -162,13 +162,13 @@ void APDS9960::read_color_data_(uint8_t status) {
return;
}
uint8_t raw[8];
APDS9960_WARNING_CHECK(this->read_bytes(0x94, raw, 8), "Reading color values failed.");
uint16_t raw[4];
APDS9960_WARNING_CHECK(this->read_bytes_16_le(0x94, raw, 4), "Reading color values failed.");
uint16_t uint_clear = (uint16_t(raw[1]) << 8) | raw[0];
uint16_t uint_red = (uint16_t(raw[3]) << 8) | raw[2];
uint16_t uint_green = (uint16_t(raw[5]) << 8) | raw[4];
uint16_t uint_blue = (uint16_t(raw[7]) << 8) | raw[6];
uint16_t uint_clear = raw[0];
uint16_t uint_red = raw[1];
uint16_t uint_green = raw[2];
uint16_t uint_blue = raw[3];
float clear_perc = (uint_clear / float(UINT16_MAX)) * 100.0f;
float red_perc = (uint_red / float(UINT16_MAX)) * 100.0f;
+2 -1
View File
@@ -1,3 +1,4 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "bh1900nux.h"
@@ -36,7 +37,7 @@ void BH1900NUXSensor::update() {
// Combined raw value, unsigned and unaligned 16 bit
// Temperature is represented in just 12 bits, shift needed
int16_t raw_temperature_register_value = encode_uint16(temperature_raw[0], temperature_raw[1]);
int16_t raw_temperature_register_value = encode_value<int16_t>(temperature_raw);
raw_temperature_register_value >>= 4;
float temperature_value = raw_temperature_register_value * SENSOR_RESOLUTION; // Apply sensor resolution
+11 -21
View File
@@ -2,6 +2,7 @@
#include <cinttypes>
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome::bm8563 {
@@ -67,28 +68,17 @@ void BM8563::read_time() {
time::RealTimeClock::synchronize_epoch_(rtc_time.timestamp);
}
uint8_t BM8563::bcd2_to_byte_(uint8_t value) {
const uint8_t tmp = ((value & 0xF0) >> 0x4) * 10;
return tmp + (value & 0x0F);
}
uint8_t BM8563::byte_to_bcd2_(uint8_t value) {
const uint8_t bcdhigh = value / 10;
value -= bcdhigh * 10;
return (bcdhigh << 4) | value;
}
void BM8563::get_time_(ESPTime &time) {
uint8_t buf[3] = {0};
this->read_register(TIME_FIRST_REG, buf, 3);
time.second = this->bcd2_to_byte_(buf[0] & 0x7f);
time.minute = this->bcd2_to_byte_(buf[1] & 0x7f);
time.hour = this->bcd2_to_byte_(buf[2] & 0x3f);
time.second = bcd_to_uint8(buf[0] & 0x7f);
time.minute = bcd_to_uint8(buf[1] & 0x7f);
time.hour = bcd_to_uint8(buf[2] & 0x3f);
}
void BM8563::set_time_(const ESPTime &time) {
uint8_t buf[3] = {this->byte_to_bcd2_(time.second), this->byte_to_bcd2_(time.minute), this->byte_to_bcd2_(time.hour)};
uint8_t buf[3] = {uint8_to_bcd(time.second), uint8_to_bcd(time.minute), uint8_to_bcd(time.hour)};
this->write_register_(TIME_FIRST_REG, buf, 3);
}
@@ -96,12 +86,12 @@ void BM8563::get_date_(ESPTime &time) {
uint8_t buf[4] = {0};
this->read_register(DATE_FIRST_REG, buf, sizeof(buf));
time.day_of_month = this->bcd2_to_byte_(buf[0] & 0x3f);
time.day_of_month = bcd_to_uint8(buf[0] & 0x3f);
// The chip counts weekdays 0-6 from Sunday (not BCD), ESPTime counts 1-7
time.day_of_week = (buf[1] & 0x07) + 1;
time.month = this->bcd2_to_byte_(buf[2] & 0x1f);
time.month = bcd_to_uint8(buf[2] & 0x1f);
uint8_t year_byte = this->bcd2_to_byte_(buf[3] & 0xff);
uint8_t year_byte = bcd_to_uint8(buf[3] & 0xff);
if (buf[2] & 0x80) {
time.year = 1900 + year_byte;
@@ -112,10 +102,10 @@ void BM8563::get_date_(ESPTime &time) {
void BM8563::set_date_(const ESPTime &time) {
uint8_t buf[4] = {
this->byte_to_bcd2_(time.day_of_month),
uint8_to_bcd(time.day_of_month),
static_cast<uint8_t>(time.day_of_week - 1),
this->byte_to_bcd2_(time.month),
this->byte_to_bcd2_(time.year % 100),
uint8_to_bcd(time.month),
uint8_to_bcd(time.year % 100),
};
if (time.year < 2000) {
-3
View File
@@ -29,9 +29,6 @@ class BM8563 final : public time::RealTimeClock, public i2c::I2CDevice {
void write_byte_(uint8_t reg, uint8_t value);
void write_register_(uint8_t reg, const uint8_t *data, size_t len);
optional<uint8_t> read_register_(uint8_t reg);
uint8_t bcd2_to_byte_(uint8_t value);
uint8_t byte_to_bcd2_(uint8_t value);
};
} // namespace esphome::bm8563
@@ -236,7 +236,7 @@ void BME280Component::update() {
});
}
float BME280Component::read_temperature_(const uint8_t *data, int32_t *t_fine) {
int32_t adc = ((data[3] & 0xFF) << 16) | ((data[4] & 0xFF) << 8) | (data[5] & 0xFF);
int32_t adc = encode_uint24(data[3], data[4], data[5]);
adc >>= 4;
if (adc == 0x80000) {
// temperature was disabled
@@ -256,7 +256,7 @@ float BME280Component::read_temperature_(const uint8_t *data, int32_t *t_fine) {
}
float BME280Component::read_pressure_(const uint8_t *data, int32_t t_fine) {
int32_t adc = ((data[0] & 0xFF) << 16) | ((data[1] & 0xFF) << 8) | (data[2] & 0xFF);
int32_t adc = encode_uint24(data[0], data[1], data[2]);
adc >>= 4;
if (adc == 0x80000) {
// pressure was disabled
+10 -9
View File
@@ -1,5 +1,6 @@
#include "bme680.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome::bme680 {
@@ -92,8 +93,8 @@ bool BME680Component::setup_registers_() {
return false;
}
this->calibration_.t1 = coeff2[9] << 8 | coeff2[8];
this->calibration_.t2 = coeff1[2] << 8 | coeff1[1];
this->calibration_.t1 = encode_value_le<uint16_t>(&coeff2[8]);
this->calibration_.t2 = encode_value_le<int16_t>(&coeff1[1]);
this->calibration_.t3 = coeff1[3];
this->calibration_.h1 = coeff2[2] << 4 | (coeff2[1] & 0x0F);
@@ -104,19 +105,19 @@ bool BME680Component::setup_registers_() {
this->calibration_.h6 = coeff2[6];
this->calibration_.h7 = coeff2[7];
this->calibration_.p1 = coeff1[6] << 8 | coeff1[5];
this->calibration_.p2 = coeff1[8] << 8 | coeff1[7];
this->calibration_.p1 = encode_value_le<uint16_t>(&coeff1[5]);
this->calibration_.p2 = encode_value_le<int16_t>(&coeff1[7]);
this->calibration_.p3 = coeff1[9];
this->calibration_.p4 = coeff1[12] << 8 | coeff1[11];
this->calibration_.p5 = coeff1[14] << 8 | coeff1[13];
this->calibration_.p4 = encode_value_le<int16_t>(&coeff1[11]);
this->calibration_.p5 = encode_value_le<int16_t>(&coeff1[13]);
this->calibration_.p6 = coeff1[16];
this->calibration_.p7 = coeff1[15];
this->calibration_.p8 = coeff1[20] << 8 | coeff1[19];
this->calibration_.p9 = coeff1[22] << 8 | coeff1[21];
this->calibration_.p8 = encode_value_le<int16_t>(&coeff1[19]);
this->calibration_.p9 = encode_value_le<int16_t>(&coeff1[21]);
this->calibration_.p10 = coeff1[23];
this->calibration_.gh1 = coeff2[14];
this->calibration_.gh2 = coeff2[12] << 8 | coeff2[13];
this->calibration_.gh2 = encode_value<int16_t>(&coeff2[12]);
this->calibration_.gh3 = coeff2[15];
uint8_t temp_var = 0;
+7 -7
View File
@@ -314,9 +314,9 @@ bool BMI270Component::update_data(motion::MotionData &data) {
};
float scale = ACCEL_SCALE[this->accel_range_];
data.acceleration[motion::X_AXIS] = (int16_t) ((raw_data[1] << 8) | raw_data[0]) * scale;
data.acceleration[motion::Y_AXIS] = (int16_t) ((raw_data[3] << 8) | raw_data[2]) * scale;
data.acceleration[motion::Z_AXIS] = (int16_t) ((raw_data[5] << 8) | raw_data[4]) * scale;
data.acceleration[motion::X_AXIS] = encode_value_le<int16_t>(raw_data) * scale;
data.acceleration[motion::Y_AXIS] = encode_value_le<int16_t>(&raw_data[2]) * scale;
data.acceleration[motion::Z_AXIS] = encode_value_le<int16_t>(&raw_data[4]) * scale;
// Gyroscope: registers 0x12–0x17 (6 bytes)
// Scale: full-scale range / 2^15
@@ -326,15 +326,15 @@ bool BMI270Component::update_data(motion::MotionData &data) {
static constexpr uint8_t GYR_OFFS = BMI270_REG_DATA_14 - BMI270_REG_DATA_8;
scale = GYRO_SCALE[this->gyro_range_];
data.angular_rate[motion::X_AXIS] = (int16_t) ((raw_data[GYR_OFFS + 1] << 8) | raw_data[GYR_OFFS + 0]) * scale;
data.angular_rate[motion::Y_AXIS] = (int16_t) ((raw_data[GYR_OFFS + 3] << 8) | raw_data[GYR_OFFS + 2]) * scale;
data.angular_rate[motion::Z_AXIS] = (int16_t) ((raw_data[GYR_OFFS + 5] << 8) | raw_data[GYR_OFFS + 4]) * scale;
data.angular_rate[motion::X_AXIS] = encode_value_le<int16_t>(&raw_data[GYR_OFFS]) * scale;
data.angular_rate[motion::Y_AXIS] = encode_value_le<int16_t>(&raw_data[GYR_OFFS + 2]) * scale;
data.angular_rate[motion::Z_AXIS] = encode_value_le<int16_t>(&raw_data[GYR_OFFS + 4]) * scale;
if (!this->temperature_callback_.empty()) {
// Temperature: registers 0x22–0x23
// Formula from datasheet: T[°C] = raw / 512 + 23
static constexpr uint8_t TEMP_OFFS = BMI270_REG_TEMP_0 - BMI270_REG_DATA_8;
int16_t raw_t = (int16_t) ((raw_data[TEMP_OFFS + 1] << 8) | raw_data[TEMP_OFFS + 0]);
int16_t raw_t = encode_value_le<int16_t>(&raw_data[TEMP_OFFS]);
float temperature = (raw_t / 512.0f) + 23.0f;
this->temperature_callback_.call(temperature);
}
@@ -1,5 +1,6 @@
#include "bmp280_base.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome::bmp280_base {
@@ -176,7 +177,7 @@ float BMP280Component::read_temperature_(int32_t *t_fine) {
if (!this->bmp_read_bytes(BMP280_REGISTER_TEMPDATA, data, 3))
return NAN;
ESP_LOGV(TAG, "Read temperature data, raw: %02X %02X %02X", data[0], data[1], data[2]);
int32_t adc = ((data[0] & 0xFF) << 16) | ((data[1] & 0xFF) << 8) | (data[2] & 0xFF);
int32_t adc = encode_uint24(data[0], data[1], data[2]);
adc >>= 4;
if (adc == 0x80000) {
// temperature was disabled
@@ -199,7 +200,7 @@ float BMP280Component::read_pressure_(int32_t t_fine) {
uint8_t data[3];
if (!this->bmp_read_bytes(BMP280_REGISTER_PRESSUREDATA, data, 3))
return NAN;
int32_t adc = ((data[0] & 0xFF) << 16) | ((data[1] & 0xFF) << 8) | (data[2] & 0xFF);
int32_t adc = encode_uint24(data[0], data[1], data[2]);
adc >>= 4;
if (adc == 0x80000) {
// pressure was disabled
@@ -1,4 +1,5 @@
#include "dallas_temp.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome::dallas_temp {
@@ -136,7 +137,7 @@ bool DallasTemperatureSensor::check_scratch_pad_() {
}
float DallasTemperatureSensor::get_temp_c_() {
int16_t temp = (this->scratch_pad_[1] << 8) | this->scratch_pad_[0];
int16_t temp = encode_value_le<int16_t>(this->scratch_pad_);
if ((this->address_ & 0xff) == DALLAS_MODEL_DS18S20) {
if (this->scratch_pad_[7] == 0) {
return NAN;
+12 -29
View File
@@ -58,26 +58,16 @@ bool DPS310Component::setup_registers_() {
return false;
}
this->c0_ = // we only ever use c0/2, so just divide by 2 here to save time later
DPS310Component::twos_complement(
int16_t(((uint16_t) coef_data_raw[0] << 4) | (((uint16_t) coef_data_raw[1] >> 4) & 0x0F)), 12) /
2;
this->c1_ =
DPS310Component::twos_complement(int16_t((((uint16_t) coef_data_raw[1] & 0x0F) << 8) | coef_data_raw[2]), 12);
this->c00_ = ((uint32_t) coef_data_raw[3] << 12) | ((uint32_t) coef_data_raw[4] << 4) |
(((uint32_t) coef_data_raw[5] >> 4) & 0x0F);
this->c00_ = DPS310Component::twos_complement(c00_, 20);
this->c10_ = encode_uint24(coef_data_raw[5] & 0x0F, coef_data_raw[6], coef_data_raw[7]);
this->c10_ = DPS310Component::twos_complement(c10_, 20);
this->c01_ = int16_t(((uint16_t) coef_data_raw[8] << 8) | (uint16_t) coef_data_raw[9]);
this->c11_ = int16_t(((uint16_t) coef_data_raw[10] << 8) | (uint16_t) coef_data_raw[11]);
this->c20_ = int16_t(((uint16_t) coef_data_raw[12] << 8) | (uint16_t) coef_data_raw[13]);
this->c21_ = int16_t(((uint16_t) coef_data_raw[14] << 8) | (uint16_t) coef_data_raw[15]);
this->c30_ = int16_t(((uint16_t) coef_data_raw[16] << 8) | (uint16_t) coef_data_raw[17]);
// we only ever use c0/2, so just divide by 2 here to save time later
this->c0_ = sign_extend<12>(encode_uint16(coef_data_raw[0], coef_data_raw[1]) >> 4) / 2;
this->c1_ = sign_extend<12>(encode_uint16(coef_data_raw[1], coef_data_raw[2]));
this->c00_ = sign_extend<20>(encode_uint24(coef_data_raw[3], coef_data_raw[4], coef_data_raw[5]) >> 4);
this->c10_ = sign_extend<20>(encode_uint24(coef_data_raw[5], coef_data_raw[6], coef_data_raw[7]));
this->c01_ = encode_value<int16_t>(&coef_data_raw[8]);
this->c11_ = encode_value<int16_t>(&coef_data_raw[10]);
this->c20_ = encode_value<int16_t>(&coef_data_raw[12]);
this->c21_ = encode_value<int16_t>(&coef_data_raw[14]);
this->c30_ = encode_value<int16_t>(&coef_data_raw[16]);
return true;
}
@@ -133,7 +123,7 @@ void DPS310Component::read_pressure_() {
return;
}
this->got_pres_ = true;
this->raw_pressure_ = DPS310Component::twos_complement(encode_uint24(bytes[0], bytes[1], bytes[2]), 24);
this->raw_pressure_ = sign_extend<24>(encode_uint24(bytes[0], bytes[1], bytes[2]));
}
void DPS310Component::read_temperature_() {
@@ -143,7 +133,7 @@ void DPS310Component::read_temperature_() {
return;
}
this->got_temp_ = true;
this->raw_temperature_ = DPS310Component::twos_complement(encode_uint24(bytes[0], bytes[1], bytes[2]), 24);
this->raw_temperature_ = sign_extend<24>(encode_uint24(bytes[0], bytes[1], bytes[2]));
}
// Calculations are taken from the datasheet which can be found here:
@@ -168,11 +158,4 @@ void DPS310Component::calculate_values_(int32_t raw_temperature, int32_t raw_pre
}
}
int32_t DPS310Component::twos_complement(int32_t val, uint8_t bits) {
if (val & ((uint32_t) 1 << (bits - 1))) {
val -= (uint32_t) 1 << bits;
}
return val;
}
} // namespace esphome::dps310
-1
View File
@@ -51,7 +51,6 @@ class DPS310Component final : public PollingComponent, public i2c::I2CDevice {
void read_pressure_();
void read_temperature_();
void calculate_values_(int32_t raw_temperature, int32_t raw_pressure);
static int32_t twos_complement(int32_t val, uint8_t bits);
sensor::Sensor *temperature_sensor_{nullptr};
sensor::Sensor *pressure_sensor_{nullptr};
+2 -1
View File
@@ -1,4 +1,5 @@
#include "ds3231.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
// Datasheet:
@@ -37,7 +38,7 @@ bool DS3231Component::read_temperature(float &out) {
return false;
}
// 10-bit two's complement, 0.25 degC per LSB.
int16_t value = static_cast<int16_t>((raw[0] << 8) | raw[1]) >> 6;
int16_t value = encode_value<int16_t>(raw) >> 6;
out = value * 0.25f;
return true;
}
@@ -235,7 +235,7 @@ void Ecocomfort2Hub::on_state_(const uint8_t *data, uint16_t len) {
ESP_LOGW(TAG, "[%s] C_STATE too short: %u bytes", this->parent_->address_str(), len);
return;
}
const float temperature = static_cast<int16_t>(encode_uint16(data[3], data[4])) / 100.0f;
const float temperature = encode_value<int16_t>(&data[3]) / 100.0f;
const float humidity = encode_uint16(data[5], data[6]) / 100.0f;
const uint16_t voc = encode_uint16(data[7], data[8]);
ESP_LOGD(TAG, "[%s] C_STATE: mode=0x%02x, speed=0x%02x, %.2f °C, %.2f %%, %u ppb, direction=%u",
+1 -1
View File
@@ -397,7 +397,7 @@ void HOT write_rgb565_row(uint8_t *byte, uint8_t mask, int step, size_t row_widt
const Rgb565ToMono &to_mono) {
const ptrdiff_t byte_step = SwapAxes ? step * static_cast<ptrdiff_t>(row_width) : 0;
for (; count != 0; count--, source += 2) {
const uint16_t value = BigEndianSource ? (source[0] << 8) | source[1] : source[0] | (source[1] << 8);
const uint16_t value = BigEndianSource ? encode_uint16(source[0], source[1]) : encode_value_le<uint16_t>(source);
if (to_mono(value)) {
*byte |= mask;
} else {
+1 -4
View File
@@ -66,10 +66,7 @@ void GCJA5Component::loop() {
}
bool GCJA5Component::calculate_checksum_() {
uint8_t crc = 0;
for (uint8_t i = 1; i < 30; i++)
crc = crc ^ this->rx_message_[i];
uint8_t crc = xor_bytes(&this->rx_message_[1], 29);
ESP_LOGVV(TAG, "Checksum packet was (0x%02X), calculated checksum was (0x%02X)", this->rx_message_[30], crc);
+3 -3
View File
@@ -192,7 +192,7 @@ void HlkFm22xComponent::handle_note_(const uint8_t *data, size_t length) {
int16_t info[8];
uint8_t offset = 1;
for (int16_t &i : info) {
i = ((int16_t) data[offset + 1] << 8) | data[offset];
i = encode_value_le<int16_t>(&data[offset]);
offset += 2;
}
ESP_LOGV(TAG, "Face state: status: %d, left: %d, top: %d, right: %d, bottom: %d, yaw: %d, pitch: %d, roll: %d",
@@ -259,7 +259,7 @@ void HlkFm22xComponent::handle_reply_(const uint8_t *data, size_t length) {
ESP_LOGE(TAG, "VERIFY response too short: %zu bytes", length);
break;
}
int16_t face_id = ((int16_t) data[2] << 8) | data[3];
int16_t face_id = encode_value<int16_t>(&data[2]);
const char *name_ptr = reinterpret_cast<const char *>(data + 4);
ESP_LOGD(TAG, "Face verified. ID: %d, name: %.*s", face_id, (int) HLK_FM22X_NAME_SIZE, name_ptr);
if (this->last_face_id_sensor_ != nullptr) {
@@ -272,7 +272,7 @@ void HlkFm22xComponent::handle_reply_(const uint8_t *data, size_t length) {
break;
}
case HlkFm22xCommand::ENROLL: {
int16_t face_id = ((int16_t) data[2] << 8) | data[3];
int16_t face_id = encode_value<int16_t>(&data[2]);
HlkFm22xFaceDirection direction = (HlkFm22xFaceDirection) data[4];
ESP_LOGI(TAG, "Face enrolled. ID: %d, Direction: 0x%.2X", face_id, direction);
this->enrollment_done_callback_.call(face_id, (uint8_t) direction);
+4 -10
View File
@@ -1,4 +1,5 @@
#include "ina226.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "esphome/core/hal.h"
#include <cinttypes>
@@ -109,7 +110,7 @@ void INA226Component::update() {
return;
}
// Convert for 2's compliment and signed value (though always positive)
float bus_voltage_v = this->twos_complement_(raw_bus_voltage, 16);
float bus_voltage_v = sign_extend<16>(raw_bus_voltage);
bus_voltage_v *= 0.00125f;
this->bus_voltage_sensor_->publish_state(bus_voltage_v);
}
@@ -121,7 +122,7 @@ void INA226Component::update() {
return;
}
// Convert for 2's compliment and signed value
float shunt_voltage_v = this->twos_complement_(raw_shunt_voltage, 16);
float shunt_voltage_v = sign_extend<16>(raw_shunt_voltage);
shunt_voltage_v *= 0.0000025f;
this->shunt_voltage_sensor_->publish_state(shunt_voltage_v);
}
@@ -133,7 +134,7 @@ void INA226Component::update() {
return;
}
// Convert for 2's compliment and signed value
float current_ma = this->twos_complement_(raw_current, 16);
float current_ma = sign_extend<16>(raw_current);
current_ma *= (this->calibration_lsb_ / 1000.0f);
this->current_sensor_->publish_state(current_ma / 1000.0f);
}
@@ -151,11 +152,4 @@ void INA226Component::update() {
this->status_clear_warning();
}
int32_t INA226Component::twos_complement_(int32_t val, uint8_t bits) {
if (val & ((uint32_t) 1 << (bits - 1))) {
val -= (uint32_t) 1 << bits;
}
return val;
}
} // namespace esphome::ina226
-2
View File
@@ -68,8 +68,6 @@ class INA226Component final : public PollingComponent, public i2c::I2CDevice {
sensor::Sensor *shunt_voltage_sensor_{nullptr};
sensor::Sensor *current_sensor_{nullptr};
sensor::Sensor *power_sensor_{nullptr};
int32_t twos_complement_(int32_t val, uint8_t bits);
};
} // namespace esphome::ina226
@@ -385,10 +385,10 @@ bool INA2XX::read_shunt_voltage_mv_(float &volt_out) {
if (this->ina_model_ == INAModel::INA_228 || this->ina_model_ == INAModel::INA_229) {
ret = this->read_unsigned_(RegisterMap::REG_VSHUNT, 3, raw);
raw >>= 4;
volt_reading = this->two_complement_(raw, 20);
volt_reading = sign_extend<20>(raw);
} else {
ret = this->read_unsigned_(RegisterMap::REG_VSHUNT, 2, raw);
volt_reading = this->two_complement_(raw, 16);
volt_reading = sign_extend<16>(raw);
}
if (ret) {
@@ -412,10 +412,10 @@ bool INA2XX::read_bus_voltage_(float &volt_out) {
if (this->ina_model_ == INAModel::INA_228 || this->ina_model_ == INAModel::INA_229) {
ret = this->read_unsigned_(RegisterMap::REG_VBUS, 3, raw);
raw >>= 4;
volt_reading = this->two_complement_(raw, 20);
volt_reading = sign_extend<20>(raw);
} else {
ret = this->read_unsigned_(RegisterMap::REG_VBUS, 2, raw);
volt_reading = this->two_complement_(raw, 16);
volt_reading = sign_extend<16>(raw);
}
if (ret) {
volt_out = this->cfg_.vbus_lsb * (float) volt_reading;
@@ -436,11 +436,11 @@ bool INA2XX::read_die_temp_c_(float &temp_out) {
if (this->ina_model_ == INAModel::INA_228 || this->ina_model_ == INAModel::INA_229) {
ret = this->read_unsigned_(RegisterMap::REG_DIETEMP, 2, raw);
temp_reading = this->two_complement_(raw, 16);
temp_reading = sign_extend<16>(raw);
} else {
ret = this->read_unsigned_(RegisterMap::REG_DIETEMP, 2, raw);
raw >>= 4;
temp_reading = this->two_complement_(raw, 12);
temp_reading = sign_extend<12>(raw);
}
if (ret) {
temp_out = this->cfg_.die_temp_lsb * (float) temp_reading;
@@ -461,10 +461,10 @@ bool INA2XX::read_current_a_(float &amps_out) {
if (this->ina_model_ == INAModel::INA_228 || this->ina_model_ == INAModel::INA_229) {
ret = this->read_unsigned_(RegisterMap::REG_CURRENT, 3, raw);
raw >>= 4;
amps_reading = this->two_complement_(raw, 20);
amps_reading = sign_extend<20>(raw);
} else {
ret = this->read_unsigned_(RegisterMap::REG_CURRENT, 2, raw);
amps_reading = this->two_complement_(raw, 16);
amps_reading = sign_extend<16>(raw);
}
ESP_LOGV(TAG, "read_current_a_ ret=%s. current_lsb=%f. reading_lsb=%f", OKFAILED(ret), this->current_lsb_,
+1 -2
View File
@@ -982,8 +982,7 @@ void HOT IT8951Display::draw_pixels_internal(int x_start, int y_start, int w, in
switch (bitness) {
case COLOR_BITNESS_565: {
const size_t i = source_idx * 2;
color_value = big_endian ? (static_cast<uint32_t>(ptr[i]) << 8) | ptr[i + 1]
: ptr[i] | (static_cast<uint32_t>(ptr[i + 1]) << 8);
color_value = big_endian ? encode_uint16(ptr[i], ptr[i + 1]) : encode_value_le<uint16_t>(&ptr[i]);
break;
}
case COLOR_BITNESS_888: {
+5 -14
View File
@@ -164,15 +164,6 @@ static inline int16_t decode_speed(uint8_t low_byte, uint8_t high_byte) {
return speed * 10; // mm/s
}
static inline int16_t hex_to_signed_int(const uint8_t *buffer, uint8_t offset) {
uint16_t hex_val = (buffer[offset + 1] << 8) | buffer[offset];
int16_t dec_val = static_cast<int16_t>(hex_val);
if (dec_val & 0x8000) {
dec_val -= 65536;
}
return dec_val;
}
static inline bool validate_header_footer(const uint8_t *header_footer, const uint8_t *buffer) {
return std::memcmp(header_footer, buffer, HEADER_FOOTER_SIZE) == 0;
}
@@ -389,10 +380,10 @@ void LD2450Component::process_zone_() {
uint8_t index, start;
for (index = 0; index < MAX_ZONES; index++) {
start = 12 + index * 8;
this->zone_config_[index].x1 = ld2450::hex_to_signed_int(this->buffer_data_, start);
this->zone_config_[index].y1 = ld2450::hex_to_signed_int(this->buffer_data_, start + 2);
this->zone_config_[index].x2 = ld2450::hex_to_signed_int(this->buffer_data_, start + 4);
this->zone_config_[index].y2 = ld2450::hex_to_signed_int(this->buffer_data_, start + 6);
this->zone_config_[index].x1 = encode_value_le<int16_t>(&this->buffer_data_[start]);
this->zone_config_[index].y1 = encode_value_le<int16_t>(&this->buffer_data_[start + 2]);
this->zone_config_[index].x2 = encode_value_le<int16_t>(&this->buffer_data_[start + 4]);
this->zone_config_[index].y2 = encode_value_le<int16_t>(&this->buffer_data_[start + 6]);
#ifdef USE_NUMBER
// only one null check as all coordinates are required for a single zone
if (this->zone_numbers_[index].x1 != nullptr) {
@@ -505,7 +496,7 @@ void LD2450Component::handle_periodic_data_() {
#ifdef USE_SENSOR
// RESOLUTION
start = TARGET_RESOLUTION + index * 8;
res = (this->buffer_data_[start + 1] << 8) | this->buffer_data_[start];
res = encode_value_le<uint16_t>(&this->buffer_data_[start]);
#endif
// SPEED
start = TARGET_SPEED + index * 8;
+3 -2
View File
@@ -1,6 +1,7 @@
#include "ld2460.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include <cmath>
#include <cstring>
@@ -117,8 +118,8 @@ void LD2460Component::handle_periodic_data_() {
continue;
}
const uint8_t *p = &data[7 + i * 4];
auto raw_x = static_cast<int16_t>(encode_uint16(p[1], p[0]));
auto raw_y = static_cast<int16_t>(encode_uint16(p[3], p[2]));
auto raw_x = encode_value_le<int16_t>(p);
auto raw_y = encode_value_le<int16_t>(&p[2]);
if (raw_x == t.last_x && raw_y == t.last_y) {
continue;
}
+13 -27
View File
@@ -203,22 +203,8 @@ static bool is_expected_control_report(uint32_t command, uint16_t type) {
}
#endif
uint16_t LD6002BComponent::read_u16_be(const uint8_t *data) { return (static_cast<uint16_t>(data[0]) << 8) | data[1]; }
uint32_t LD6002BComponent::read_u32_le(const uint8_t *data) {
return static_cast<uint32_t>(data[0]) | (static_cast<uint32_t>(data[1]) << 8) |
(static_cast<uint32_t>(data[2]) << 16) | (static_cast<uint32_t>(data[3]) << 24);
}
int32_t LD6002BComponent::read_int32_le(const uint8_t *data) {
uint32_t raw = read_u32_le(data);
int32_t value;
std::memcpy(&value, &raw, sizeof(value));
return value;
}
float LD6002BComponent::read_f32_le(const uint8_t *data) {
uint32_t raw = read_u32_le(data);
uint32_t raw = encode_value_le<uint32_t>(data);
float value;
std::memcpy(&value, &raw, sizeof(value));
return value;
@@ -537,9 +523,9 @@ void LD6002BComponent::parse_byte_(uint8_t byte) {
this->header_xor_ ^= byte;
this->header_pos_++;
if (this->header_pos_ == 6) {
this->frame_id_ = read_u16_be(this->data_buf_);
this->data_len_ = read_u16_be(this->data_buf_ + 2);
this->frame_type_ = read_u16_be(this->data_buf_ + 4);
this->frame_id_ = encode_value<uint16_t>(this->data_buf_);
this->data_len_ = encode_value<uint16_t>(this->data_buf_ + 2);
this->frame_type_ = encode_value<uint16_t>(this->data_buf_ + 4);
// The length is only trustworthy once the header checksum has been verified, so just
// remember that the frame is oversized and let the HCK state act on it.
this->frame_oversize_ = this->data_len_ > this->max_data_len_;
@@ -625,7 +611,7 @@ void LD6002BComponent::handle_frame_(uint16_t type, const uint8_t *data, uint16_
#ifdef ESPHOME_LOG_HAS_VERBOSE
const uint32_t active_control_command =
(this->command_active_ && this->active_command_.type == TYPE_CONTROL && this->active_command_.len >= 4)
? read_u32_le(this->active_command_.data.data())
? encode_value_le<uint32_t>(this->active_command_.data.data())
: 0;
if (active_control_command != 0 && is_expected_control_report(active_control_command, type)) {
ESP_LOGV(TAG, "Received %s (0x%04X) while waiting for %s (0x%02" PRIX32 ") ACK", frame_type_name(type), type,
@@ -691,7 +677,7 @@ void LD6002BComponent::handle_target_report_(const uint8_t *data, uint16_t len)
if (len < 4)
return;
uint32_t target_num = read_u32_le(data);
uint32_t target_num = encode_value_le<uint32_t>(data);
uint16_t available = (len - 4) / TARGET_DATA_LEN;
// Un-narrowed: a report of e.g. 256 targets must not truncate to 0 and read as "absent".
const uint32_t reported = std::min<uint32_t>(target_num, available);
@@ -704,7 +690,7 @@ void LD6002BComponent::handle_target_report_(const uint8_t *data, uint16_t len)
std::array<uint8_t, MAX_TARGETS> slot_wire{};
for (uint8_t i = 0; i < count; i++) {
uint16_t cluster_offset = 4 + (i * TARGET_DATA_LEN) + 16;
wire_cluster[i] = static_cast<int32_t>(read_u32_le(data + cluster_offset));
wire_cluster[i] = encode_value_le<int32_t>(data + cluster_offset);
}
for (uint8_t i = 0; i < count; i++) {
for (uint8_t s = 0; s < MAX_TARGETS; s++) {
@@ -761,7 +747,7 @@ void LD6002BComponent::handle_target_report_(const uint8_t *data, uint16_t len)
float x = read_f32_le(data + offset + 0);
float y = read_f32_le(data + offset + 4);
float z = read_f32_le(data + offset + 8);
int32_t dop_idx = read_int32_le(data + offset + 12);
int32_t dop_idx = encode_value_le<int32_t>(data + offset + 12);
int32_t cluster_id = this->slot_cluster_[i];
TargetSensors &target = this->targets_[i];
if (target.x != nullptr) {
@@ -811,7 +797,7 @@ void LD6002BComponent::handle_point_cloud_(const uint8_t *data, uint16_t len) {
return;
#ifdef USE_SENSOR
uint32_t point_num = read_u32_le(data);
uint32_t point_num = encode_value_le<uint32_t>(data);
if (this->point_count_sensor_ != nullptr) {
if (point_num != this->last_point_count_) {
this->point_count_sensor_->publish_state(point_num);
@@ -832,7 +818,7 @@ void LD6002BComponent::handle_area_presence_(const uint8_t *data, uint16_t len)
this->area_presence_any_ = false;
for (uint8_t i = 0; i < AREA_COUNT; i++) {
uint32_t state = read_u32_le(data + (i * AREA_PRESENCE_ENTRY_LEN));
uint32_t state = encode_value_le<uint32_t>(data + (i * AREA_PRESENCE_ENTRY_LEN));
bool present = state != 0;
this->area_presence_any_ = this->area_presence_any_ || present;
#ifdef USE_BINARY_SENSOR
@@ -903,7 +889,7 @@ void LD6002BComponent::handle_delay_report_(const uint8_t *data, uint16_t len) {
if (len < 4)
return;
#ifdef USE_NUMBER
uint32_t delay = read_u32_le(data);
uint32_t delay = encode_value_le<uint32_t>(data);
this->publish_number_clamped_(this->hold_delay_number_, delay);
#endif
}
@@ -978,7 +964,7 @@ void LD6002BComponent::handle_low_power_sleep_report_(const uint8_t *data, uint1
if (len < 4)
return;
#ifdef USE_NUMBER
uint32_t sleep_ms = read_u32_le(data);
uint32_t sleep_ms = encode_value_le<uint32_t>(data);
this->publish_number_clamped_(this->low_power_sleep_number_, sleep_ms);
#endif
}
@@ -1115,7 +1101,7 @@ void LD6002BComponent::process_command_queue_() {
if (this->command_sent_ && now - this->last_send_ms_ >= ack_timeout) {
const uint32_t active_control_command =
(this->active_command_.type == TYPE_CONTROL && this->active_command_.len >= 4)
? read_u32_le(this->active_command_.data.data())
? encode_value_le<uint32_t>(this->active_command_.data.data())
: 0;
if (this->retries_left_ > 0) {
#ifdef ESPHOME_LOG_HAS_VERBOSE
-3
View File
@@ -329,9 +329,6 @@ class LD6002BComponent : public Component, public uart::UARTDevice {
void apply_area_config_();
void wake_();
static uint16_t read_u16_be(const uint8_t *data);
static uint32_t read_u32_le(const uint8_t *data);
static int32_t read_int32_le(const uint8_t *data);
static float read_f32_le(const uint8_t *data);
static void write_u32_le(uint8_t *data, uint32_t value);
static void write_int32_le(uint8_t *data, int32_t value);
+2 -1
View File
@@ -1,4 +1,5 @@
#include "lm75b.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "esphome/core/hal.h"
@@ -21,7 +22,7 @@ void LM75BComponent::update() {
return;
}
// Obtain combined 16-bit value
int16_t raw_temperature = (buff[0] << 8) | buff[1];
int16_t raw_temperature = encode_value<int16_t>(buff);
// Read the 11-bit raw temperature value
raw_temperature >>= 5;
// Publish the temperature in °C
+1 -1
View File
@@ -88,7 +88,7 @@ bool MAX31888Sensor::read_temperature_(int16_t &raw) {
this->status_set_warning(LOG_STR("checksum invalid"));
return false;
}
raw = static_cast<int16_t>(encode_uint16(frame[3], frame[4]));
raw = encode_value<int16_t>(&frame[3]);
return true;
}
+1 -1
View File
@@ -61,7 +61,7 @@ void MPL3115A2Component::update() {
if (this->pressure_ != nullptr)
this->pressure_->publish_state(pressure);
}
int16_t t = encode_uint16(buffer[3], buffer[4]);
int16_t t = encode_value<int16_t>(&buffer[3]);
float temperature = float(t) / 256.0f;
if (this->temperature_ != nullptr)
this->temperature_->publish_state(temperature);
+2 -5
View File
@@ -1,5 +1,6 @@
#include "nau7802.h"
#include <cmath>
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "esphome/core/hal.h"
@@ -226,11 +227,7 @@ int32_t NAU7802Sensor::read_value_(uint8_t start_reg, size_t size) {
for (size_t i = 0; i < size; i++) {
result |= data[i] << (size - 1 - i) * 8;
}
// extend sign bit
if (result & 0x800000 && size == 3) {
result |= 0xFF000000;
}
return result;
return size == 3 ? sign_extend<24>(result) : result;
}
bool NAU7802Sensor::calibrate_(enum NAU7802CalibrationModes mode) {
+2 -1
View File
@@ -1,4 +1,5 @@
#include "pcf8574.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome::pcf8574 {
@@ -90,7 +91,7 @@ bool PCF8574Component::read_gpio_() {
this->status_set_warning();
return false;
}
this->input_mask_ = (uint16_t(data[1]) << 8) | data[0];
this->input_mask_ = encode_value_le<uint16_t>(data);
this->status_clear_warning();
return true;
}
+10 -10
View File
@@ -72,32 +72,32 @@ void PMWCS3Component::read_data_() {
// Wait for the sensor to be ready.
// 80ms empirically determined (conservative).
this->set_timeout(80, [this] {
uint8_t data[8];
uint16_t data[4];
float e25, ec, temperature, vwc;
if (!this->read_bytes(PMWCS3_REG_GET_DATA, (uint8_t *) &data, 8)) {
if (!this->read_bytes_16_le(PMWCS3_REG_GET_DATA, data, 4)) {
ESP_LOGVV(TAG, "Reading PMWCS3_REG_GET_DATA failed");
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (this->e25_sensor_ != nullptr) {
e25 = ((data[1] << 8) | data[0]) / 100.0;
e25 = data[0] / 100.0;
this->e25_sensor_->publish_state(e25);
ESP_LOGVV(TAG, "e25: data[0]=%d, data[1]=%d, result=%f", data[0], data[1], e25);
ESP_LOGVV(TAG, "e25: raw=%u, result=%f", data[0], e25);
}
if (this->ec_sensor_ != nullptr) {
ec = ((data[3] << 8) | data[2]) / 10.0;
ec = data[1] / 10.0;
this->ec_sensor_->publish_state(ec);
ESP_LOGVV(TAG, "ec: data[2]=%d, data[3]=%d, result=%f", data[2], data[3], ec);
ESP_LOGVV(TAG, "ec: raw=%u, result=%f", data[1], ec);
}
if (this->temperature_sensor_ != nullptr) {
temperature = ((data[5] << 8) | data[4]) / 100.0;
temperature = data[2] / 100.0;
this->temperature_sensor_->publish_state(temperature);
ESP_LOGVV(TAG, "temp: data[4]=%d, data[5]=%d, result=%f", data[4], data[5], temperature);
ESP_LOGVV(TAG, "temp: raw=%u, result=%f", data[2], temperature);
}
if (this->vwc_sensor_ != nullptr) {
vwc = ((data[7] << 8) | data[6]) / 10.0;
vwc = data[3] / 10.0;
this->vwc_sensor_->publish_state(vwc);
ESP_LOGVV(TAG, "vwc: data[6]=%d, data[7]=%d, result=%f", data[6], data[7], vwc);
ESP_LOGVV(TAG, "vwc: raw=%u, result=%f", data[3], vwc);
}
});
}
@@ -91,9 +91,9 @@ class ABBWelcomeData {
}
uint32_t get_destination_address() const {
if (this->get_address_length() == 2) {
return (this->data_[4] << 8) + this->data_[5];
return encode_uint16(this->data_[4], this->data_[5]);
}
return (this->data_[4] << 16) + (this->data_[5] << 8) + this->data_[6];
return encode_uint24(this->data_[4], this->data_[5], this->data_[6]);
}
void set_source_address(uint32_t address) {
if (this->get_address_length() == 2) {
@@ -107,9 +107,9 @@ class ABBWelcomeData {
}
uint32_t get_source_address() const {
if (this->get_address_length() == 2) {
return (this->data_[6] << 8) + this->data_[7];
return encode_uint16(this->data_[6], this->data_[7]);
}
return (this->data_[7] << 16) + (this->data_[8] << 8) + this->data_[9];
return encode_uint24(this->data_[7], this->data_[8], this->data_[9]);
}
void set_message_id(uint8_t message_id) { this->data_[4 + 2 * this->get_address_length()] = message_id; }
/// A configured id, which finalize() keeps instead of picking one
+4 -4
View File
@@ -56,10 +56,10 @@ bool RFBridgeComponent::parse_bridge_byte_(uint8_t byte) {
return true;
RFBridgeData data;
data.sync = (raw[2] << 8) | raw[3];
data.low = (raw[4] << 8) | raw[5];
data.high = (raw[6] << 8) | raw[7];
data.code = (raw[8] << 16) | (raw[9] << 8) | raw[10];
data.sync = encode_uint16(raw[2], raw[3]);
data.low = encode_uint16(raw[4], raw[5]);
data.high = encode_uint16(raw[6], raw[7]);
data.code = encode_uint24(raw[8], raw[9], raw[10]);
if (action == RF_CODE_LEARN_OK) {
ESP_LOGD(TAG, "Learning success");
@@ -48,25 +48,6 @@ void MR60BHA2Component::loop() {
}
}
/**
* @brief Calculate the checksum for a byte array.
*
* This function calculates the checksum for the provided byte array using an
* XOR-based checksum algorithm.
*
* @param data The byte array to calculate the checksum for.
* @param len The length of the byte array.
* @return The calculated checksum.
*/
static uint8_t calculate_checksum(const uint8_t *data, size_t len) {
uint8_t checksum = 0;
for (size_t i = 0; i < len; i++) {
checksum ^= data[i];
}
checksum = ~checksum;
return checksum;
}
/**
* @brief Validate the checksum of a byte array.
*
@@ -79,7 +60,7 @@ static uint8_t calculate_checksum(const uint8_t *data, size_t len) {
* @return True if the checksum is valid, false otherwise.
*/
static bool validate_checksum(const uint8_t *data, size_t len, uint8_t expected_checksum) {
return calculate_checksum(data, len) == expected_checksum;
return static_cast<uint8_t>(~xor_bytes(data, len)) == expected_checksum;
}
bool MR60BHA2Component::validate_message_() {
+1 -1
View File
@@ -43,7 +43,7 @@ void SenseAirComponent::update() {
}
uint16_t calc_checksum = crc16(response, 11);
uint16_t resp_checksum = (uint16_t(response[12]) << 8) | response[11];
uint16_t resp_checksum = encode_value_le<uint16_t>(&response[11]);
if (resp_checksum != calc_checksum) {
ESP_LOGW(TAG, "SenseAir checksum doesn't match: 0x%02X!=0x%02X", resp_checksum, calc_checksum);
this->status_set_warning();
@@ -7,7 +7,7 @@ namespace esphome::systa_bus {
ESPHOME_LOG_TAG(TAG, "systa_bus.sensor");
static int16_t get_i16be(std::span<const uint8_t> message, size_t start) {
return static_cast<int16_t>(encode_uint16(message[start], message[start + 1]));
return encode_value<int16_t>(&message[start]);
}
void SystaSolarAquaSensor::dump_config() {
@@ -7,11 +7,11 @@ namespace esphome::vbus {
ESPHOME_LOG_TAG(TAG, "vbus.sensor");
static inline uint16_t get_u16(std::vector<uint8_t> &message, int start) {
return (message[start + 1] << 8) + message[start];
return encode_value_le<uint16_t>(&message[start]);
}
static inline int16_t get_i16(std::vector<uint8_t> &message, int start) {
return (int16_t) ((message[start + 1] << 8) + message[start]);
return encode_value_le<int16_t>(&message[start]);
}
void DeltaSolBSPlusSensor::dump_config() {
@@ -51,12 +51,11 @@ uint16_t WaveshareIOCH32V003Component::get_adc_value() {
if (this->is_failed())
return 0;
uint8_t data[2];
if (!this->read_bytes(IO_EXTENSION_ADC_ADDR, data, 2)) {
uint16_t adc_value;
if (!this->read_byte_16_le(IO_EXTENSION_ADC_ADDR, &adc_value)) {
this->status_set_warning(LOG_STR("Failed to read ADC register"));
return 0;
}
uint16_t adc_value = (data[1] << 8) | data[0];
this->status_clear_warning();
return adc_value;
}
+5 -10
View File
@@ -1,4 +1,5 @@
#include "whirlpool.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome::whirlpool {
@@ -136,10 +137,8 @@ void WhirlpoolClimate::transmit_state() {
}
// Checksum
for (uint8_t i = 2; i < 13; i++)
remote_state[13] ^= remote_state[i];
for (uint8_t i = 14; i < 20; i++)
remote_state[20] ^= remote_state[i];
remote_state[13] = xor_bytes(&remote_state[2], 11, remote_state[13]);
remote_state[20] = xor_bytes(&remote_state[14], 6, remote_state[20]);
ESP_LOGV(TAG,
"Sending: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X "
@@ -269,13 +268,9 @@ bool WhirlpoolClimate::on_receive(remote_base::RemoteReceiveData data) {
return false;
}
uint8_t checksum13 = 0;
uint8_t checksum20 = 0;
// Calculate checksum and compare with signal value.
for (uint8_t i = 2; i < 13; i++)
checksum13 ^= remote_state[i];
for (uint8_t i = 14; i < 20; i++)
checksum20 ^= remote_state[i];
uint8_t checksum13 = xor_bytes(&remote_state[2], 11);
uint8_t checksum20 = xor_bytes(&remote_state[14], 6);
if (checksum13 != remote_state[13] || (!skip_footer && checksum20 != remote_state[20])) {
ESP_LOGVV(TAG, "Checksum fail");