Bugfix: disable channels after IO if multiple tca9548a I2C multiplexers are configured (#5317)

This commit is contained in:
kahrendt 2023-09-01 16:55:59 -04:00 committed by GitHub
parent bec53f97a2
commit 211b3eddea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 12 deletions

View file

@ -7,23 +7,27 @@ namespace tca9548a {
static const char *const TAG = "tca9548a"; static const char *const TAG = "tca9548a";
i2c::ErrorCode TCA9548AChannel::readv(uint8_t address, i2c::ReadBuffer *buffers, size_t cnt) { i2c::ErrorCode TCA9548AChannel::readv(uint8_t address, i2c::ReadBuffer *buffers, size_t cnt) {
auto err = parent_->switch_to_channel(channel_); auto err = this->parent_->switch_to_channel(channel_);
if (err != i2c::ERROR_OK) if (err != i2c::ERROR_OK)
return err; return err;
return parent_->bus_->readv(address, buffers, cnt); err = this->parent_->bus_->readv(address, buffers, cnt);
this->parent_->disable_all_channels();
return err;
} }
i2c::ErrorCode TCA9548AChannel::writev(uint8_t address, i2c::WriteBuffer *buffers, size_t cnt, bool stop) { i2c::ErrorCode TCA9548AChannel::writev(uint8_t address, i2c::WriteBuffer *buffers, size_t cnt, bool stop) {
auto err = parent_->switch_to_channel(channel_); auto err = this->parent_->switch_to_channel(channel_);
if (err != i2c::ERROR_OK) if (err != i2c::ERROR_OK)
return err; return err;
return parent_->bus_->writev(address, buffers, cnt, stop); err = this->parent_->bus_->writev(address, buffers, cnt, stop);
this->parent_->disable_all_channels();
return err;
} }
void TCA9548AComponent::setup() { void TCA9548AComponent::setup() {
ESP_LOGCONFIG(TAG, "Setting up TCA9548A..."); ESP_LOGCONFIG(TAG, "Setting up TCA9548A...");
uint8_t status = 0; uint8_t status = 0;
if (this->read(&status, 1) != i2c::ERROR_OK) { if (this->read(&status, 1) != i2c::ERROR_OK) {
ESP_LOGI(TAG, "TCA9548A failed"); ESP_LOGE(TAG, "TCA9548A failed");
this->mark_failed(); this->mark_failed();
return; return;
} }
@ -37,15 +41,16 @@ void TCA9548AComponent::dump_config() {
i2c::ErrorCode TCA9548AComponent::switch_to_channel(uint8_t channel) { i2c::ErrorCode TCA9548AComponent::switch_to_channel(uint8_t channel) {
if (this->is_failed()) if (this->is_failed())
return i2c::ERROR_NOT_INITIALIZED; return i2c::ERROR_NOT_INITIALIZED;
if (current_channel_ == channel)
return i2c::ERROR_OK;
uint8_t channel_val = 1 << channel; uint8_t channel_val = 1 << channel;
auto err = this->write(&channel_val, 1); return this->write(&channel_val, 1);
if (err == i2c::ERROR_OK) { }
current_channel_ = channel;
void TCA9548AComponent::disable_all_channels() {
if (this->write(&TCA9548A_DISABLE_CHANNELS_COMMAND, 1) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Failed to disable all channels.");
this->status_set_error(); // couldn't disable channels, set error status
} }
return err;
} }
} // namespace tca9548a } // namespace tca9548a

View file

@ -6,6 +6,8 @@
namespace esphome { namespace esphome {
namespace tca9548a { namespace tca9548a {
static const uint8_t TCA9548A_DISABLE_CHANNELS_COMMAND = 0x00;
class TCA9548AComponent; class TCA9548AComponent;
class TCA9548AChannel : public i2c::I2CBus { class TCA9548AChannel : public i2c::I2CBus {
public: public:
@ -28,10 +30,10 @@ class TCA9548AComponent : public Component, public i2c::I2CDevice {
void update(); void update();
i2c::ErrorCode switch_to_channel(uint8_t channel); i2c::ErrorCode switch_to_channel(uint8_t channel);
void disable_all_channels();
protected: protected:
friend class TCA9548AChannel; friend class TCA9548AChannel;
uint8_t current_channel_ = 255;
}; };
} // namespace tca9548a } // namespace tca9548a
} // namespace esphome } // namespace esphome