Compare commits

...
3 changed files with 42 additions and 2 deletions
+2 -2
View File
@@ -211,8 +211,8 @@ file does, and it is the authority when they disagree. The most useful starting
logged with `get_log_str` and `LOG_STR_ARG`, copied out with `ESPHOME_strncpy_P` before `publish_state`.
A `dump_config` helper that picks a name returns `const LogString *` from `LOG_STR(...)`.
* **CRCs and bit tricks** come from `esphome/core/helpers.h` (`crc8`, `crc16`, `xor_bytes`, `sum16_bytes`,
`reverse_bits`, `encode_uint16`, `encode_value_le`, `sign_extend<BITS>`, `bcd_to_uint8`); pick the helper's
arguments instead of writing a loop. Epson style 7-byte RTC calendars (one-hot weekday) use
`reverse_bits`, `encode_uint16`, `encode_value_le`, `sign_extend<BITS>`, `bcd_to_uint8`, `assign_bits`); pick
the helper's arguments instead of writing a loop. Epson style 7-byte RTC calendars (one-hot weekday) use
`time::decode_bcd_calendar`.
* **Bus helpers:** UART drains with `read_available(on_byte)` and `discard_available()`, text lines with
`LineReader<N>`; I2C has `update_register`, `write_registers` (PROGMEM `I2CRegValue` table), `check_chip_id`
+10
View File
@@ -1067,6 +1067,16 @@ constexpr uint8_t bcd_to_uint8(uint8_t bcd) { return (bcd >> 4) * 10 + (bcd & 0x
/// 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); }
/// Set the bits of \p mask in \p value when \p on is true, clear them otherwise.
/// Use an unsigned mask for a register wider than int; a negative int mask is sign-extended.
template<typename T> ESPHOME_ALWAYS_INLINE constexpr void assign_bits(T &value, std::type_identity_t<T> mask, bool on) {
if (on) {
value |= mask;
} else {
value &= ~mask;
}
}
/// Reverse the order of 8 bits.
inline uint8_t reverse_bits(uint8_t x) {
x = ((x & 0xAA) >> 1) | ((x & 0x55) << 1);
@@ -0,0 +1,30 @@
#include <gtest/gtest.h>
#include "esphome/core/helpers.h"
namespace esphome::core::testing {
static_assert([] {
uint8_t v = 0;
assign_bits(v, 1 << 3, true);
return v;
}() == 0x08);
TEST(AssignBits, SetsAndClearsOnlyTheMask) {
uint8_t reg = 0b1010'0001;
assign_bits(reg, 0b0000'0110, true);
EXPECT_EQ(reg, 0b1010'0111);
assign_bits(reg, 0b1000'0010, false);
EXPECT_EQ(reg, 0b0010'0101);
}
TEST(AssignBits, ClearsAtTheTargetWidth) {
uint16_t reg16 = 0xFFFF;
assign_bits(reg16, 1 << 15, false);
EXPECT_EQ(reg16, 0x7FFF);
uint64_t reg64 = UINT64_MAX;
assign_bits(reg64, uint32_t{1} << 31, false);
EXPECT_EQ(reg64, UINT64_MAX & ~(uint64_t{1} << 31));
}
} // namespace esphome::core::testing