Compare commits

..
23 changed files with 301 additions and 88 deletions

No files matched your search

+2
View File
@@ -449,6 +449,8 @@ file does, and it is the authority when they disagree. The most useful starting
```
Restore an owned or standalone switch in `setup()` with `sw->restore()`, or `restore(default)`
to still drive a state when the restore mode is disabled.
A hub that applies its switches' restored states itself reads `sw->get_initial_write_state()`, which
already applies `inverted`.
- **Other codegen helpers:** `uart.new_uart_component(config, *ctor_args)` (and `i2c.new_i2c_component`,
`spi.new_spi_component`, `modbus.new_modbus_client_component`, `ble_client.new_ble_node_component`)
+13 -5
View File
@@ -6,11 +6,19 @@ namespace esphome::as3935_i2c {
ESPHOME_LOG_TAG(TAG, "as3935_i2c");
void I2CAS3935Component::write_register(uint8_t reg, uint8_t mask, uint8_t bits, uint8_t start_pos) {
const uint8_t value = bits << start_pos;
// Bits of value outside mask were ORed in before, so they stay part of the update
// Also called at runtime, so a transient bus error only warns, like read_register()
if (!this->update_register(reg, mask | value, value)) {
ESP_LOGW(TAG, "Failed to update register 0x%02X", reg);
uint8_t write_reg;
if (!this->read_byte(reg, &write_reg)) {
this->mark_failed();
ESP_LOGW(TAG, "read_byte failed - increase log level for more details!");
return;
}
write_reg &= (~mask);
write_reg |= (bits << start_pos);
if (!this->write_byte(reg, write_reg)) {
ESP_LOGW(TAG, "write_byte failed - increase log level for more details!");
return;
}
}
+8 -2
View File
@@ -240,11 +240,17 @@ bool AS7341Component::write_register_bit(uint8_t address, bool value, uint8_t bi
}
bool AS7341Component::set_register_bit(uint8_t address, uint8_t bit_position) {
return this->update_register(address, 1 << bit_position, 1 << bit_position);
uint8_t data;
this->read_byte(address, &data);
data |= (1 << bit_position);
return this->write_byte(address, data);
}
bool AS7341Component::clear_register_bit(uint8_t address, uint8_t bit_position) {
return this->update_register(address, 1 << bit_position, 0);
uint8_t data;
this->read_byte(address, &data);
data &= ~(1 << bit_position);
return this->write_byte(address, data);
}
} // namespace esphome::as7341
+6 -1
View File
@@ -264,7 +264,12 @@ bool AS734XComponent::select_bank_(uint8_t reg) {
}
bool AS734XComponent::update_bits_(uint8_t reg, uint8_t mask, bool value) {
return this->select_bank_(reg) && this->update_register(reg, mask, value ? mask : 0);
uint8_t data = 0;
if (!this->select_bank_(reg) || !this->read_byte(reg, &data)) {
return false;
}
data = value ? (data | mask) : (data & ~mask);
return this->write_byte(reg, data);
}
// The exposure is applied before every measurement, so a gain, ATIME or ASTEP changed at runtime
+30 -5
View File
@@ -139,24 +139,49 @@ bool BME680Component::setup_registers_() {
this->calibration_.ambient_temperature = 25; // prime ambient temperature
// Config register
if (!this->update_register(BME680_REGISTER_CONFIG, 0b00011100, (this->iir_filter_ & 0b111) << 2)) {
uint8_t config_register;
if (!this->read_byte(BME680_REGISTER_CONFIG, &config_register)) {
return false;
}
config_register &= ~0b00011100;
config_register |= (this->iir_filter_ & 0b111) << 2;
if (!this->write_byte(BME680_REGISTER_CONFIG, config_register)) {
return false;
}
// Humidity control register
if (!this->update_register(BME680_REGISTER_CONTROL_HUMIDITY, 0b00000111, this->humidity_oversampling_ & 0b111)) {
uint8_t hum_control;
if (!this->read_byte(BME680_REGISTER_CONTROL_HUMIDITY, &hum_control)) {
return false;
}
hum_control &= ~0b00000111;
hum_control |= this->humidity_oversampling_ & 0b111;
if (!this->write_byte(BME680_REGISTER_CONTROL_HUMIDITY, hum_control)) {
return false;
}
// Gas 1 control register: run gas, heater profile 0
if (!this->update_register(BME680_REGISTER_CONTROL_GAS1, 0b00011111, 1 << 4)) {
// Gas 1 control register
uint8_t gas1_control;
if (!this->read_byte(BME680_REGISTER_CONTROL_GAS1, &gas1_control)) {
return false;
}
gas1_control &= ~0b00011111;
gas1_control |= 1 << 4;
gas1_control |= 0; // profile 0
if (!this->write_byte(BME680_REGISTER_CONTROL_GAS1, gas1_control)) {
return false;
}
const bool heat_off = this->heater_temperature_ == 0 || this->heater_duration_ == 0;
// Gas 0 control register
if (!this->update_register(BME680_REGISTER_CONTROL_GAS0, 0b00001000, heat_off << 3)) {
uint8_t gas0_control;
if (!this->read_byte(BME680_REGISTER_CONTROL_GAS0, &gas0_control)) {
return false;
}
gas0_control &= ~0b00001000;
gas0_control |= heat_off << 3;
if (!this->write_byte(BME680_REGISTER_CONTROL_GAS0, gas0_control)) {
return false;
}
+7 -4
View File
@@ -28,10 +28,13 @@ bool BQ25186Component::write_register_(uint8_t reg, uint8_t value) {
}
bool BQ25186Component::update_register_(uint8_t reg, uint8_t mask, uint8_t value) {
if (this->update_register(reg, mask, value))
return true;
ESP_LOGW(TAG, "Failed to update register 0x%02X", reg);
return false;
uint8_t reg_value;
if (!this->read_byte(reg, &reg_value)) {
ESP_LOGW(TAG, "Failed to read register 0x%02X", reg);
return false;
}
reg_value = (reg_value & ~mask) | (value & mask);
return this->write_register_(reg, reg_value);
}
uint8_t BQ25186Component::expected_register_(size_t index) const {
+1 -1
View File
@@ -71,12 +71,12 @@ class BQ25186Component : public PollingComponent, public i2c::I2CDevice {
protected:
bool write_register_(uint8_t reg, uint8_t value);
bool update_register_(uint8_t reg, uint8_t mask, uint8_t value);
uint8_t expected_register_(size_t index) const;
bool config_matches_(const BQ25186StatusRegisters &regs) const;
#ifdef USE_BQ25186_PG_GPO
void check_pg_gpo_(const BQ25186StatusRegisters &status, bool &pending);
#endif
bool update_register_(uint8_t reg, uint8_t mask, uint8_t value);
#ifdef BQ25186_BINARY_SENSOR_COUNT
StaticVector<BQ25186BinarySensor *, BQ25186_BINARY_SENSOR_COUNT> binary_sensors_;
+4 -2
View File
@@ -42,8 +42,10 @@ void CAP1188Component::finish_setup_() {
}
// Set sensitivity
// The threshold replaces the upper nibble and is ORed into the lower one, as before
this->update_register(CAP1188_SENSITVITY, 0xF0 | this->touch_threshold_, this->touch_threshold_);
uint8_t sensitivity = 0;
this->read_byte(CAP1188_SENSITVITY, &sensitivity);
sensitivity = sensitivity & 0x0f;
this->write_byte(CAP1188_SENSITVITY, sensitivity | this->touch_threshold_);
// Allow multiple touches
this->write_byte(CAP1188_MULTI_TOUCH, this->allow_multiple_touches_);
+25 -18
View File
@@ -50,7 +50,7 @@ void ES7210::setup() {
ES7210_ERROR_FAILED(this->write_byte(ES7210_ADC34_HPF1_REG21, 0x2a));
// Secondary I2S mode settings
ES7210_ERROR_FAILED(this->update_register(ES7210_MODE_CONFIG_REG08, 0x01, 0x00));
ES7210_ERROR_FAILED(this->es7210_update_reg_bit_(ES7210_MODE_CONFIG_REG08, 0x01, 0x00));
// Configure analog power
ES7210_ERROR_FAILED(this->write_byte(ES7210_ANALOG_REG40, 0xC3));
@@ -141,39 +141,39 @@ bool ES7210::configure_sample_rate_() {
bool ES7210::configure_mic_gain_() {
for (uint8_t i = 0; i < 4; ++i) {
ES7210_ERROR_CHECK(this->update_register(ES7210_MIC1_GAIN_REG43 + i, 0x10, 0x00));
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC1_GAIN_REG43 + i, 0x10, 0x00));
}
ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC12_POWER_REG4B, 0xff));
ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC34_POWER_REG4C, 0xff));
// Configure mic 1
ES7210_ERROR_CHECK(this->update_register(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00));
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00));
ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC12_POWER_REG4B, 0x00));
ES7210_ERROR_CHECK(this->update_register(ES7210_MIC1_GAIN_REG43, 0x10, 0x10));
ES7210_ERROR_CHECK(
this->update_register(ES7210_MIC1_GAIN_REG43, 0x0f, this->es7210_gain_reg_value_(this->channel_gains_[0])));
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC1_GAIN_REG43, 0x10, 0x10));
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC1_GAIN_REG43, 0x0f,
this->es7210_gain_reg_value_(this->channel_gains_[0])));
// Configure mic 2
ES7210_ERROR_CHECK(this->update_register(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00));
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00));
ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC12_POWER_REG4B, 0x00));
ES7210_ERROR_CHECK(this->update_register(ES7210_MIC2_GAIN_REG44, 0x10, 0x10));
ES7210_ERROR_CHECK(
this->update_register(ES7210_MIC2_GAIN_REG44, 0x0f, this->es7210_gain_reg_value_(this->channel_gains_[1])));
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC2_GAIN_REG44, 0x10, 0x10));
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC2_GAIN_REG44, 0x0f,
this->es7210_gain_reg_value_(this->channel_gains_[1])));
// Configure mic 3
// MIC3 uses the ADC3/4 and MIC3/4 clock domains (bits 2 and 4), not the MIC1/2 domains.
ES7210_ERROR_CHECK(this->update_register(ES7210_CLOCK_OFF_REG01, 0x15, 0x00));
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x15, 0x00));
ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC34_POWER_REG4C, 0x00));
ES7210_ERROR_CHECK(this->update_register(ES7210_MIC3_GAIN_REG45, 0x10, 0x10));
ES7210_ERROR_CHECK(
this->update_register(ES7210_MIC3_GAIN_REG45, 0x0f, this->es7210_gain_reg_value_(this->channel_gains_[2])));
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC3_GAIN_REG45, 0x10, 0x10));
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC3_GAIN_REG45, 0x0f,
this->es7210_gain_reg_value_(this->channel_gains_[2])));
// Configure mic 4
ES7210_ERROR_CHECK(this->update_register(ES7210_CLOCK_OFF_REG01, 0x15, 0x00));
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x15, 0x00));
ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC34_POWER_REG4C, 0x00));
ES7210_ERROR_CHECK(this->update_register(ES7210_MIC4_GAIN_REG46, 0x10, 0x10));
ES7210_ERROR_CHECK(
this->update_register(ES7210_MIC4_GAIN_REG46, 0x0f, this->es7210_gain_reg_value_(this->channel_gains_[3])));
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC4_GAIN_REG46, 0x10, 0x10));
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC4_GAIN_REG46, 0x0f,
this->es7210_gain_reg_value_(this->channel_gains_[3])));
return true;
}
@@ -227,4 +227,11 @@ bool ES7210::configure_i2s_format_() {
return true;
}
bool ES7210::es7210_update_reg_bit_(uint8_t reg_addr, uint8_t update_bits, uint8_t data) {
uint8_t regv;
ES7210_ERROR_CHECK(this->read_byte(reg_addr, &regv));
regv = (regv & (~update_bits)) | (update_bits & data);
return this->write_byte(reg_addr, regv);
}
} // namespace esphome::es7210
+7
View File
@@ -40,6 +40,13 @@ class ES7210 final : public audio_adc::AudioAdc, public Component, public i2c::I
float mic_gain() override { return this->channel_gains_[0]; };
protected:
/// @brief Updates an I2C registry address by modifying the current state
/// @param reg_addr I2C register address
/// @param update_bits Mask of allowed bits to be modified
/// @param data Bit values to be written
/// @return True if successful, false otherwise
bool es7210_update_reg_bit_(uint8_t reg_addr, uint8_t update_bits, uint8_t data);
/// @brief Convert floating point mic gain value to register value
/// @param mic_gain Gain value to convert
/// @return Corresponding register value for specified gain
+13 -2
View File
@@ -91,9 +91,20 @@ float ES8156::volume() {
}
bool ES8156::set_mute_state_(bool mute_state) {
uint8_t reg13;
this->is_muted_ = mute_state;
const uint8_t mask = BIT(1) | BIT(2);
return this->update_register(ES8156_REG13_DAC_MUTE, mask, mute_state ? mask : 0);
if (!this->read_byte(ES8156_REG13_DAC_MUTE, &reg13)) {
return false;
}
ESP_LOGV(TAG, "Read ES8156_REG13_DAC_MUTE: %u", reg13);
assign_bits(reg13, BIT(1) | BIT(2), mute_state);
ESP_LOGV(TAG, "Setting ES8156_REG13_DAC_MUTE to %u (muted: %s)", reg13, YESNO(mute_state));
return this->write_byte(ES8156_REG13_DAC_MUTE, reg13);
}
} // namespace esphome::es8156
+35 -11
View File
@@ -134,9 +134,12 @@ bool ES8311::configure_clock_() {
}
// Register 0x02
ES8311_ERROR_CHECK(
this->update_register(ES8311_REG02_CLK_MANAGER, 0xF8,
((coefficient->pre_div - 1) << 5) | (encode_pre_mult(coefficient->pre_mult) << 3)));
uint8_t reg02;
ES8311_ERROR_CHECK(this->read_byte(ES8311_REG02_CLK_MANAGER, &reg02));
reg02 &= 0x07;
reg02 |= (coefficient->pre_div - 1) << 5;
reg02 |= encode_pre_mult(coefficient->pre_mult) << 3;
ES8311_ERROR_CHECK(this->write_byte(ES8311_REG02_CLK_MANAGER, reg02));
// Register 0x03
const uint8_t reg03 = (coefficient->fs_mode << 6) | coefficient->adc_osr;
@@ -150,13 +153,23 @@ bool ES8311::configure_clock_() {
ES8311_ERROR_CHECK(this->write_byte(ES8311_REG05_CLK_MANAGER, reg05));
// Register 0x06
uint8_t reg06 = coefficient->bclk_div < 19 ? coefficient->bclk_div - 1 : coefficient->bclk_div;
if (this->sclk_inverted_)
reg06 |= BIT(5);
ES8311_ERROR_CHECK(this->update_register(ES8311_REG06_CLK_MANAGER, BIT(5) | 0x1F, reg06));
uint8_t reg06;
ES8311_ERROR_CHECK(this->read_byte(ES8311_REG06_CLK_MANAGER, &reg06));
assign_bits(reg06, BIT(5), this->sclk_inverted_);
reg06 &= 0xE0;
if (coefficient->bclk_div < 19) {
reg06 |= (coefficient->bclk_div - 1) << 0;
} else {
reg06 |= (coefficient->bclk_div) << 0;
}
ES8311_ERROR_CHECK(this->write_byte(ES8311_REG06_CLK_MANAGER, reg06));
// Register 0x07
ES8311_ERROR_CHECK(this->update_register(ES8311_REG07_CLK_MANAGER, 0x3F, coefficient->lrck_h));
uint8_t reg07;
ES8311_ERROR_CHECK(this->read_byte(ES8311_REG07_CLK_MANAGER, &reg07));
reg07 &= 0xC0;
reg07 |= coefficient->lrck_h << 0;
ES8311_ERROR_CHECK(this->write_byte(ES8311_REG07_CLK_MANAGER, reg07));
// Register 0x08
ES8311_ERROR_CHECK(this->write_byte(ES8311_REG08_CLK_MANAGER, coefficient->lrck_l));
@@ -167,7 +180,10 @@ bool ES8311::configure_clock_() {
bool ES8311::configure_format_() {
// Configure I2S mode and format
ES8311_ERROR_CHECK(this->update_register(ES8311_REG00_RESET, BIT(6), 0));
uint8_t reg00;
ES8311_ERROR_CHECK(this->read_byte(ES8311_REG00_RESET, &reg00));
reg00 &= 0xBF;
ES8311_ERROR_CHECK(this->write_byte(ES8311_REG00_RESET, reg00));
// Configure SDP in resolution
uint8_t reg09 = calculate_resolution_value(this->resolution_in_);
@@ -196,9 +212,17 @@ bool ES8311::configure_mic_() {
}
bool ES8311::set_mute_state_(bool mute_state) {
uint8_t reg31;
this->is_muted_ = mute_state;
const uint8_t mask = BIT(6) | BIT(5);
return this->update_register(ES8311_REG31_DAC, mask, mute_state ? mask : 0);
if (!this->read_byte(ES8311_REG31_DAC, &reg31)) {
return false;
}
assign_bits(reg31, BIT(6) | BIT(5), mute_state);
return this->write_byte(ES8311_REG31_DAC, reg31);
}
} // namespace esphome::es8311
+6 -2
View File
@@ -265,8 +265,12 @@ bool FUSB302B::init_chip_() {
return false;
// Let the chip retransmit unacknowledged messages up to 3 times
if (!this->update_register(FUSB_CONTROL3, FUSB_CONTROL3_N_RETRIES_MASK | FUSB_CONTROL3_AUTO_RETRY,
(3 << FUSB_CONTROL3_N_RETRIES_SHIFT) | FUSB_CONTROL3_AUTO_RETRY))
uint8_t control3 = 0;
if (!this->read_byte(FUSB_CONTROL3, &control3))
return false;
control3 =
(control3 & ~FUSB_CONTROL3_N_RETRIES_MASK) | (3 << FUSB_CONTROL3_N_RETRIES_SHIFT) | FUSB_CONTROL3_AUTO_RETRY;
if (!this->write_byte(FUSB_CONTROL3, control3))
return false;
if (!this->write_byte(FUSB_POWER, FUSB_POWER_ALL))
+33 -6
View File
@@ -32,22 +32,49 @@ bool MPU6050Component::setup_registers_() {
}
ESP_LOGV(TAG, " Setting up Power Management");
// Clock source X-Gyro, sleep off, temperature on
if (!this->update_register(MPU6050_REGISTER_POWER_MANAGEMENT_1,
0b111 | (1 << MPU6050_BIT_SLEEP_ENABLED) | (1 << MPU6050_BIT_TEMPERATURE_DISABLED),
MPU6050_CLOCK_SOURCE_X_GYRO)) {
// Setup power management
uint8_t power_management;
if (!this->read_byte(MPU6050_REGISTER_POWER_MANAGEMENT_1, &power_management)) {
return false;
}
ESP_LOGV(TAG, " Input power_management: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(power_management));
// Set clock source - X-Gyro
power_management &= 0b11111000;
power_management |= MPU6050_CLOCK_SOURCE_X_GYRO;
// Disable sleep
power_management &= ~(1 << MPU6050_BIT_SLEEP_ENABLED);
// Enable temperature
power_management &= ~(1 << MPU6050_BIT_TEMPERATURE_DISABLED);
ESP_LOGV(TAG, " Output power_management: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(power_management));
if (!this->write_byte(MPU6050_REGISTER_POWER_MANAGEMENT_1, power_management)) {
return false;
}
ESP_LOGV(TAG, " Setting up Gyro Config");
// Set scale - 2000DPS
if (!this->update_register(MPU6050_REGISTER_GYRO_CONFIG, 0b00011000, MPU6050_SCALE_2000_DPS << 3)) {
uint8_t gyro_config;
if (!this->read_byte(MPU6050_REGISTER_GYRO_CONFIG, &gyro_config)) {
return false;
}
ESP_LOGV(TAG, " Input gyro_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(gyro_config));
gyro_config &= 0b11100111;
gyro_config |= MPU6050_SCALE_2000_DPS << 3;
ESP_LOGV(TAG, " Output gyro_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(gyro_config));
if (!this->write_byte(MPU6050_REGISTER_GYRO_CONFIG, gyro_config)) {
return false;
}
ESP_LOGV(TAG, " Setting up Accel Config");
// Set range - 2G
return this->update_register(MPU6050_REGISTER_ACCEL_CONFIG, 0b00011000, MPU6050_RANGE_2G << 3);
uint8_t accel_config;
if (!this->read_byte(MPU6050_REGISTER_ACCEL_CONFIG, &accel_config)) {
return false;
}
ESP_LOGV(TAG, " Input accel_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(accel_config));
accel_config &= 0b11100111;
accel_config |= (MPU6050_RANGE_2G << 3);
ESP_LOGV(TAG, " Output accel_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(accel_config));
return this->write_byte(MPU6050_REGISTER_ACCEL_CONFIG, accel_config);
}
void MPU6050Component::dump_config() {
ESP_LOGCONFIG(TAG, "MPU6050:");
+33 -6
View File
@@ -36,22 +36,49 @@ bool MPU6886Component::setup_registers_() {
}
ESP_LOGV(TAG, " Setting up Power Management");
// Clock source X-Gyro, sleep off, temperature on
if (!this->update_register(MPU6886_REGISTER_POWER_MANAGEMENT_1,
0b111 | (1 << MPU6886_BIT_SLEEP_ENABLED) | (1 << MPU6886_BIT_TEMPERATURE_DISABLED),
MPU6886_CLOCK_SOURCE_X_GYRO)) {
// Setup power management
uint8_t power_management;
if (!this->read_byte(MPU6886_REGISTER_POWER_MANAGEMENT_1, &power_management)) {
return false;
}
ESP_LOGV(TAG, " Input power_management: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(power_management));
// Set clock source - X-Gyro
power_management &= 0b11111000;
power_management |= MPU6886_CLOCK_SOURCE_X_GYRO;
// Disable sleep
power_management &= ~(1 << MPU6886_BIT_SLEEP_ENABLED);
// Enable temperature
power_management &= ~(1 << MPU6886_BIT_TEMPERATURE_DISABLED);
ESP_LOGV(TAG, " Output power_management: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(power_management));
if (!this->write_byte(MPU6886_REGISTER_POWER_MANAGEMENT_1, power_management)) {
return false;
}
ESP_LOGV(TAG, " Setting up Gyroscope Config");
// Set scale - 2000DPS
if (!this->update_register(MPU6886_REGISTER_GYRO_CONFIG, 0b00011000, MPU6886_SCALE_2000_DPS << 3)) {
uint8_t gyro_config;
if (!this->read_byte(MPU6886_REGISTER_GYRO_CONFIG, &gyro_config)) {
return false;
}
ESP_LOGV(TAG, " Input gyroscope_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(gyro_config));
gyro_config &= 0b11100111;
gyro_config |= MPU6886_SCALE_2000_DPS << 3;
ESP_LOGV(TAG, " Output gyro_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(gyro_config));
if (!this->write_byte(MPU6886_REGISTER_GYRO_CONFIG, gyro_config)) {
return false;
}
ESP_LOGV(TAG, " Setting up Accelerometer Config");
// Set range - 2G
return this->update_register(MPU6886_REGISTER_ACCEL_CONFIG, 0b00011000, MPU6886_RANGE_2G << 3);
uint8_t accel_config;
if (!this->read_byte(MPU6886_REGISTER_ACCEL_CONFIG, &accel_config)) {
return false;
}
ESP_LOGV(TAG, " Input accelerometer_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(accel_config));
accel_config &= 0b11100111;
accel_config |= (MPU6886_RANGE_2G << 3);
ESP_LOGV(TAG, " Output accel_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(accel_config));
return this->write_byte(MPU6886_REGISTER_ACCEL_CONFIG, accel_config);
}
void MPU6886Component::dump_config() {
+5
View File
@@ -60,6 +60,11 @@ optional<bool> Switch::get_initial_state_with_restore_mode() {
}
return initial_state;
}
optional<bool> Switch::get_initial_write_state() {
if (auto initial = this->get_initial_state_with_restore_mode())
return *initial != this->inverted_;
return {};
}
void Switch::restore() {
if (auto initial = this->get_initial_state_with_restore_mode())
this->control(*initial);
+2
View File
@@ -114,6 +114,8 @@ class Switch : public EntityBase {
* state.
*/
optional<bool> get_initial_state_with_restore_mode();
/// get_initial_state_with_restore_mode() with inverted applied: the level write_state() takes.
optional<bool> get_initial_write_state();
/// Drive the switch to the state its restore mode yields, through control(), so inversion and
/// write_state() apply; a disabled restore mode drives \p when_disabled, or nothing without one.
+30 -11
View File
@@ -153,6 +153,7 @@ void SX1509Component::pin_mode(uint8_t pin, gpio::Flags flags) {
void SX1509Component::setup_led_driver(uint8_t pin) {
uint16_t temp_word = 0;
uint8_t temp_byte = 0;
this->read_byte_16(REG_INPUT_DISABLE_B, &temp_word);
temp_word |= (1 << pin);
@@ -161,11 +162,16 @@ void SX1509Component::setup_led_driver(uint8_t pin) {
this->ddr_mask_ &= ~(1 << pin); // 0=output
this->write_byte_16(REG_DIR_B, this->ddr_mask_);
// Internal 2MHz oscillator: set bit 6, clear bit 5
this->update_register(REG_CLOCK, (1 << 6) | (1 << 5), 1 << 6);
this->read_byte(REG_CLOCK, &temp_byte);
temp_byte |= (1 << 6); // Internal 2MHz oscillator part 1 (set bit 6)
temp_byte &= ~(1 << 5); // Internal 2MHz oscillator part 2 (clear bit 5)
this->write_byte(REG_CLOCK, temp_byte);
// Linear mode for banks A (bit 3) and B (bit 7); LED driver clock ClkX of all IOs (bits 6:4)
this->update_register(REG_MISC, (1 << 7) | (1 << 3) | 0x70, 0x70);
this->read_byte(REG_MISC, &temp_byte);
temp_byte &= ~(1 << 7); // set linear mode bank B
temp_byte &= ~(1 << 3); // set linear mode bank A
temp_byte |= 0x70; // Frequency of the LED Driver clock ClkX of all IOs:
this->write_byte(REG_MISC, temp_byte);
this->read_byte_16(REG_LED_DRIVER_ENABLE_B, &temp_word);
temp_word |= (1 << pin);
@@ -188,7 +194,11 @@ void SX1509Component::clock_(uint8_t osc_source, uint8_t osc_pin_function, uint8
this->clk_x_ = 2000000;
osc_divider = (osc_divider & 0b111) << 4; // 3-bit value, bits 6:4
this->update_register(REG_MISC, 0b111 << 4, osc_divider);
uint8_t reg_misc = 0;
this->read_byte(REG_MISC, &reg_misc);
reg_misc &= ~(0b111 << 4);
reg_misc |= osc_divider;
this->write_byte(REG_MISC, reg_misc);
}
void SX1509Component::setup_keypad_() {
@@ -202,11 +212,15 @@ void SX1509Component::setup_keypad_() {
this->ddr_mask_ |= (1 << i);
this->write_byte_16(REG_DIR_B, this->ddr_mask_);
const uint8_t row_bits = (1 << this->rows_) - 1;
this->update_register(REG_OPEN_DRAIN_A, row_bits, row_bits);
this->read_byte(REG_OPEN_DRAIN_A, &temp_byte);
for (int i = 0; i < this->rows_; i++)
temp_byte |= (1 << i);
this->write_byte(REG_OPEN_DRAIN_A, temp_byte);
const uint8_t col_bits = (1 << this->cols_) - 1;
this->update_register(REG_PULL_UP_B, col_bits, col_bits);
this->read_byte(REG_PULL_UP_B, &temp_byte);
for (int i = 0; i < this->cols_; i++)
temp_byte |= (1 << i);
this->write_byte(REG_PULL_UP_B, temp_byte);
if (debounce_time_ >= scan_time_) {
debounce_time_ = scan_time_ >> 1; // Force debounce_time to be less than scan_time
@@ -235,8 +249,13 @@ uint16_t SX1509Component::read_key_data() {
void SX1509Component::set_debounce_config_(uint8_t config_value) {
// First make sure clock is configured
this->update_register(REG_MISC, 1 << 4, 1 << 4); // Just default to no divider if not set
this->update_register(REG_CLOCK, 1 << 6, 1 << 6); // default to internal osc.
uint8_t temp_byte = 0;
this->read_byte(REG_MISC, &temp_byte);
temp_byte |= (1 << 4); // Just default to no divider if not set
this->write_byte(REG_MISC, temp_byte);
this->read_byte(REG_CLOCK, &temp_byte);
temp_byte |= (1 << 6); // default to internal osc.
this->write_byte(REG_CLOCK, temp_byte);
config_value &= 0b111; // 3-bit value
this->write_byte(REG_DEBOUNCE_CONFIG, config_value);
+7 -4
View File
@@ -45,10 +45,13 @@ bool SY6970Component::write_register_(uint8_t reg, uint8_t value) {
}
bool SY6970Component::update_register_(uint8_t reg, uint8_t mask, uint8_t value) {
if (this->update_register(reg, mask, value))
return true;
ESP_LOGW(TAG, "Failed to update register 0x%02X", reg);
return false;
uint8_t reg_value;
if (!this->read_byte(reg, &reg_value)) {
ESP_LOGW(TAG, "Failed to read register 0x%02X for update", reg);
return false;
}
reg_value = (reg_value & ~mask) | (value & mask);
return this->write_register_(reg, reg_value);
}
void SY6970Component::setup() {
+6 -4
View File
@@ -159,10 +159,12 @@ bool TAS2780::select_page_(uint8_t page) {
}
bool TAS2780::update_bits_(uint8_t reg, uint8_t mask, uint8_t value) {
if (this->select_page_(TAS2780_PAGE_0) && this->update_register(reg, mask, value))
return true;
ESP_LOGW(TAG, "Failed to update register 0x%02X", reg);
return false;
uint8_t current;
if (!this->select_page_(TAS2780_PAGE_0) || !this->read_byte(reg, &current)) {
ESP_LOGE(TAG, "Failed to read register 0x%02X", reg);
return false;
}
return this->write_byte(reg, (current & ~mask) | (value & mask));
}
bool TAS2780::init_() {
+8 -2
View File
@@ -17,8 +17,14 @@ void UFireECComponent::setup() {
ESP_LOGI(TAG, "Found ufire_ec board version 0x%02X", version);
// Write option for temperature adjustments
const bool compensate = this->temperature_sensor_ != nullptr || this->temperature_sensor_external_ != nullptr;
this->update_register(REGISTER_CONFIG, CONFIG_TEMP_COMPENSATION, compensate ? CONFIG_TEMP_COMPENSATION : 0);
uint8_t config;
this->read_byte(REGISTER_CONFIG, &config);
if (this->temperature_sensor_ == nullptr && this->temperature_sensor_external_ == nullptr) {
config &= ~CONFIG_TEMP_COMPENSATION;
} else {
config |= CONFIG_TEMP_COMPENSATION;
}
this->write_byte(REGISTER_CONFIG, config);
// Update temperature compensation
this->set_compensation_(this->temperature_compensation_);
+8 -2
View File
@@ -18,8 +18,14 @@ void UFireISEComponent::setup() {
ESP_LOGI(TAG, "Found uFire_ise board version 0x%02X", version);
// Write option for temperature adjustments
const bool compensate = this->temperature_sensor_ != nullptr || this->temperature_sensor_external_ != nullptr;
this->update_register(REGISTER_CONFIG, CONFIG_TEMP_COMPENSATION, compensate ? CONFIG_TEMP_COMPENSATION : 0);
uint8_t config;
this->read_byte(REGISTER_CONFIG, &config);
if (this->temperature_sensor_ == nullptr && this->temperature_sensor_external_ == nullptr) {
config &= ~CONFIG_TEMP_COMPENSATION;
} else {
config |= CONFIG_TEMP_COMPENSATION;
}
this->write_byte(REGISTER_CONFIG, config);
}
void UFireISEComponent::update() {
+12
View File
@@ -46,4 +46,16 @@ TEST(SwitchRestore, DefaultAppliesOnlyWhenTheModeIsDisabled) {
EXPECT_EQ(on.writes, std::vector<bool>{true});
}
TEST(SwitchRestore, InitialWriteStateAppliesInversion) {
RecordingSwitch on, inverted, disabled;
on.set_restore_mode(SWITCH_ALWAYS_ON);
inverted.set_restore_mode(SWITCH_ALWAYS_ON);
inverted.set_inverted(true);
disabled.set_restore_mode(SWITCH_RESTORE_DISABLED);
disabled.set_inverted(true);
EXPECT_EQ(on.get_initial_write_state(), optional<bool>(true));
EXPECT_EQ(inverted.get_initial_write_state(), optional<bool>(false));
EXPECT_FALSE(disabled.get_initial_write_state().has_value());
}
} // namespace esphome::switch_::testing