ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
tca9548a.cpp
Go to the documentation of this file.
1#include "tca9548a.h"
2
3#include <algorithm>
4#include "esphome/core/log.h"
5
7
8ESPHOME_LOG_TAG(TAG, "tca9548a");
9
10i2c::ErrorCode TCA9548AChannel::write_readv(uint8_t address, const uint8_t *write_buffer, size_t write_count,
11 uint8_t *read_buffer, size_t read_count) {
12#ifdef I2C_PORT_FREQUENCY_COUNT
13 const uint32_t select_frequency = this->select_frequency_();
14 if (select_frequency != 0) {
15 return this->write_readv_at_port_frequency_(select_frequency, address, write_buffer, write_count, read_buffer,
16 read_count);
17 }
18#endif
19 auto err = this->parent_->switch_to_channel(this->channel_);
20 if (err != i2c::ERROR_OK)
21 return err;
22 err = this->parent_->bus_->write_readv(address, write_buffer, write_count, read_buffer, read_count);
24 return err;
25}
26
27#ifdef I2C_PORT_FREQUENCY_COUNT
28// The multiplexer's own frequency, else the slower of the bus and the port
30 if (this->parent_->frequency_ != 0)
31 return this->parent_->frequency_;
32 if (this->frequency_ == 0)
33 return 0;
34 // A bus that does not report its frequency gets the port's, and fails the switch
35 const uint32_t bus_frequency = this->parent_->bus_->get_frequency();
36 return bus_frequency != 0 ? std::min(this->frequency_, bus_frequency) : this->frequency_;
37}
38
39// The port frequency, else the multiplexer's
41 return this->frequency_ != 0 ? this->frequency_ : this->parent_->frequency_;
42}
43
45 const uint8_t *write_buffer, size_t write_count,
46 uint8_t *read_buffer, size_t read_count) {
47 const uint32_t original_frequency = this->parent_->bus_->get_frequency();
48 // A failed switch leaves the bus as it was
49 auto err = this->switch_bus_(select_frequency);
50 if (err != i2c::ERROR_OK)
51 return err;
52
53 err = this->parent_->switch_to_channel(this->channel_);
54 if (err == i2c::ERROR_OK) {
55 err = this->transfer_(select_frequency, address, write_buffer, write_count, read_buffer, read_count);
57 }
58 const i2c::ErrorCode restored = this->switch_bus_(original_frequency);
59 return err != i2c::ERROR_OK ? err : restored;
60}
61
62// Transfer at the port frequency, back to the select frequency for the deselect
63i2c::ErrorCode TCA9548AChannel::transfer_(uint32_t select_frequency, uint8_t address, const uint8_t *write_buffer,
64 size_t write_count, uint8_t *read_buffer, size_t read_count) {
65 const uint32_t transfer_frequency = this->transfer_frequency_();
66 if (transfer_frequency == select_frequency) {
67 return this->parent_->bus_->write_readv(address, write_buffer, write_count, read_buffer, read_count);
68 }
69 auto err = this->switch_bus_(transfer_frequency);
70 if (err == i2c::ERROR_OK) {
71 err = this->parent_->bus_->write_readv(address, write_buffer, write_count, read_buffer, read_count);
72 }
73 const i2c::ErrorCode restored = this->switch_bus_(select_frequency);
74 return err != i2c::ERROR_OK ? err : restored;
75}
76
77// Forward to the shared upstream bus
81
83 const i2c::ErrorCode err = this->switch_frequency(frequency);
84 if (err != i2c::ERROR_OK) {
85 this->parent_->status_set_error(LOG_STR("Failed to switch the bus frequency"));
86 }
87 return err;
88}
89
91#endif
92
94 uint8_t status = 0;
95#ifdef I2C_PORT_FREQUENCY_COUNT
96 const uint32_t original_frequency = this->bus_->get_frequency();
97 if (this->frequency_ != 0 && this->bus_->switch_frequency(this->frequency_) != i2c::ERROR_OK) {
98 this->mark_failed(LOG_STR("Failed to switch the bus frequency"));
99 return;
100 }
101#endif
102 const i2c::ErrorCode err = this->read(&status, 1);
103#ifdef I2C_PORT_FREQUENCY_COUNT
104 const bool restored = this->frequency_ == 0 || this->bus_->switch_frequency(original_frequency) == i2c::ERROR_OK;
105#endif
106 if (err != i2c::ERROR_OK) {
107 ESP_LOGE(TAG, "TCA9548A failed");
108 this->mark_failed();
109 return;
110 }
111#ifdef I2C_PORT_FREQUENCY_COUNT
112 if (!restored) {
113 this->mark_failed(LOG_STR("Failed to switch the bus frequency"));
114 return;
115 }
116#endif
117 ESP_LOGD(TAG, "Channels currently open: %d", status);
118}
120 ESP_LOGCONFIG(TAG, "TCA9548A:");
121 LOG_I2C_DEVICE(this);
122}
123
125 if (this->is_failed())
127
128 const uint8_t channel_val = 1 << channel;
129 return this->write(&channel_val, 1);
130}
131
133 if (this->write(&TCA9548A_DISABLE_CHANNELS_COMMAND, 1) != i2c::ERROR_OK) {
134 this->status_set_error(LOG_STR("Failed to disable all channels."));
135 }
136}
137
138} // namespace esphome::tca9548a
uint8_t address
Definition bl0906.h:4
uint8_t status
Definition bl0942.h:8
uint16_le_t frequency
Definition bl0942.h:6
void mark_failed()
Mark this component as failed.
bool is_failed() const
Definition component.h:274
virtual ErrorCode write_readv(uint8_t address, const uint8_t *write_buffer, size_t write_count, uint8_t *read_buffer, size_t read_count)=0
This virtual method writes bytes to an I2CBus from an array, then reads bytes into an array of ReadBu...
virtual uint32_t get_frequency() const
The frequency the bus runs at.
Definition i2c_bus.h:63
virtual ErrorCode switch_frequency(uint32_t frequency)
Switch the bus frequency for the transactions that follow; an external bus that does not override thi...
Definition i2c_bus.h:60
ErrorCode write(const uint8_t *data, size_t len) const
writes an array of bytes to a device using an I2CBus
Definition i2c.h:195
I2CBus * bus_
pointer to I2CBus instance
Definition i2c.h:325
ErrorCode read(uint8_t *data, size_t len) const
reads an array of bytes from the device using an I2CBus
Definition i2c.h:175
i2c::ErrorCode write_readv_at_port_frequency_(uint32_t select_frequency, uint8_t address, const uint8_t *write_buffer, size_t write_count, uint8_t *read_buffer, size_t read_count)
Definition tca9548a.cpp:44
uint32_t transfer_frequency_() const
Definition tca9548a.cpp:40
uint32_t get_frequency() const override
Definition tca9548a.cpp:90
i2c::ErrorCode write_readv(uint8_t address, const uint8_t *write_buffer, size_t write_count, uint8_t *read_buffer, size_t read_count) override
Definition tca9548a.cpp:10
i2c::ErrorCode switch_frequency(uint32_t frequency) override
Definition tca9548a.cpp:78
i2c::ErrorCode switch_bus_(uint32_t frequency)
Switch the upstream bus, flagging the multiplexer on failure.
Definition tca9548a.cpp:82
TCA9548AComponent * parent_
Definition tca9548a.h:38
i2c::ErrorCode transfer_(uint32_t select_frequency, uint8_t address, const uint8_t *write_buffer, size_t write_count, uint8_t *read_buffer, size_t read_count)
Definition tca9548a.cpp:63
i2c::ErrorCode switch_to_channel(uint8_t channel)
Definition tca9548a.cpp:124
ErrorCode
Error codes returned by I2CBus and I2CDevice methods.
Definition i2c_bus.h:13
@ ERROR_OK
No error found during execution of method.
Definition i2c_bus.h:15
@ ERROR_NOT_INITIALIZED
call method to a not initialized bus
Definition i2c_bus.h:19
ESPHOME_LOG_TAG(TAG, "tca9548a")
static void uint32_t