ESPHome 2025.5.0
Loading...
Searching...
No Matches
tca9555.cpp
Go to the documentation of this file.
1#include "tca9555.h"
2#include "esphome/core/log.h"
3
4static const uint8_t TCA9555_INPUT_PORT_REGISTER_0 = 0x00;
5static const uint8_t TCA9555_INPUT_PORT_REGISTER_1 = 0x01;
6static const uint8_t TCA9555_OUTPUT_PORT_REGISTER_0 = 0x02;
7static const uint8_t TCA9555_OUTPUT_PORT_REGISTER_1 = 0x03;
8static const uint8_t TCA9555_POLARITY_REGISTER_0 = 0x04;
9static const uint8_t TCA9555_POLARITY_REGISTER_1 = 0x05;
10static const uint8_t TCA9555_CONFIGURATION_PORT_0 = 0x06;
11static const uint8_t TCA9555_CONFIGURATION_PORT_1 = 0x07;
12
13namespace esphome {
14namespace tca9555 {
15
16static const char *const TAG = "tca9555";
17
19 ESP_LOGCONFIG(TAG, "Setting up TCA9555...");
20 if (!this->read_gpio_modes_()) {
21 this->mark_failed();
22 return;
23 }
24 if (!this->read_gpio_outputs_()) {
25 this->mark_failed();
26 return;
27 }
28}
30 ESP_LOGCONFIG(TAG, "TCA9555:");
31 LOG_I2C_DEVICE(this)
32 if (this->is_failed()) {
33 ESP_LOGE(TAG, "Communication with TCA9555 failed!");
34 }
35}
36void TCA9555Component::pin_mode(uint8_t pin, gpio::Flags flags) {
37 if (flags == gpio::FLAG_INPUT) {
38 // Set mode mask bit
39 this->mode_mask_ |= 1 << pin;
40 } else if (flags == gpio::FLAG_OUTPUT) {
41 // Clear mode mask bit
42 this->mode_mask_ &= ~(1 << pin);
43 }
44 // Write GPIO to enable input mode
45 this->write_gpio_modes_();
46}
48
50 if (this->is_failed())
51 return false;
52 uint8_t data[2];
53 if (!this->read_bytes(TCA9555_OUTPUT_PORT_REGISTER_0, data, 2)) {
54 this->status_set_warning("Failed to read output register");
55 return false;
56 }
57 this->output_mask_ = (uint16_t(data[1]) << 8) | (uint16_t(data[0]) << 0);
59 return true;
60}
61
63 if (this->is_failed())
64 return false;
65 uint8_t data[2];
66 bool success = this->read_bytes(TCA9555_CONFIGURATION_PORT_0, data, 2);
67 if (!success) {
68 this->status_set_warning("Failed to read mode register");
69 return false;
70 }
71 this->mode_mask_ = (uint16_t(data[1]) << 8) | (uint16_t(data[0]) << 0);
72
74 return true;
75}
77 if (this->is_failed())
78 return false;
79 uint8_t data;
80 uint8_t bank_number = pin < 8 ? 0 : 1;
81 uint8_t register_to_read = bank_number ? TCA9555_INPUT_PORT_REGISTER_1 : TCA9555_INPUT_PORT_REGISTER_0;
82 if (!this->read_bytes(register_to_read, &data, 1)) {
83 this->status_set_warning("Failed to read input register");
84 return false;
85 }
86 uint8_t second_half = this->input_mask_ >> 8;
87 uint8_t first_half = this->input_mask_;
88 if (bank_number) {
89 this->input_mask_ = (data << 8) | (uint16_t(first_half) << 0);
90 } else {
91 this->input_mask_ = (uint16_t(second_half) << 8) | (data << 0);
92 }
93
95 return true;
96}
97
98void TCA9555Component::digital_write_hw(uint8_t pin, bool value) {
99 if (this->is_failed())
100 return;
101
102 if (value) {
103 this->output_mask_ |= (1 << pin);
104 } else {
105 this->output_mask_ &= ~(1 << pin);
106 }
107
108 uint8_t data[2];
109 data[0] = this->output_mask_;
110 data[1] = this->output_mask_ >> 8;
111 if (!this->write_bytes(TCA9555_OUTPUT_PORT_REGISTER_0, data, 2)) {
112 this->status_set_warning("Failed to write output register");
113 return;
114 }
115
116 this->status_clear_warning();
117}
118
120 if (this->is_failed())
121 return false;
122 uint8_t data[2];
123
124 data[0] = this->mode_mask_;
125 data[1] = this->mode_mask_ >> 8;
126 if (!this->write_bytes(TCA9555_CONFIGURATION_PORT_0, data, 2)) {
127 this->status_set_warning("Failed to write mode register");
128 return false;
129 }
130 this->status_clear_warning();
131 return true;
132}
133
134bool TCA9555Component::digital_read_cache(uint8_t pin) { return this->input_mask_ & (1 << pin); }
135
137
138void TCA9555GPIOPin::setup() { this->pin_mode(this->flags_); }
139void TCA9555GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
140bool TCA9555GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
141void TCA9555GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
142std::string TCA9555GPIOPin::dump_summary() const { return str_sprintf("%u via TCA9555", this->pin_); }
143
144} // namespace tca9555
145} // namespace esphome
virtual void mark_failed()
Mark this component as failed.
bool is_failed() const
void status_set_warning(const char *message="unspecified")
void status_clear_warning()
bool write_bytes(uint8_t a_register, const uint8_t *data, uint8_t len, bool stop=true)
Definition i2c.h:252
bool read_bytes(uint8_t a_register, uint8_t *data, uint8_t len)
Compat APIs All methods below have been added for compatibility reasons.
Definition i2c.h:216
bool digital_read_hw(uint8_t pin) override
Definition tca9555.cpp:76
bool digital_read_cache(uint8_t pin) override
Definition tca9555.cpp:134
uint16_t mode_mask_
Mask for the pin mode - 1 means output, 0 means input.
Definition tca9555.h:33
void setup() override
Check i2c availability and setup masks.
Definition tca9555.cpp:18
uint16_t input_mask_
The state read in digital_read_hw - 1 means HIGH, 0 means LOW.
Definition tca9555.h:37
float get_setup_priority() const override
Definition tca9555.cpp:136
uint16_t output_mask_
The mask to write as output state - 1 means HIGH, 0 means LOW.
Definition tca9555.h:35
void digital_write_hw(uint8_t pin, bool value) override
Definition tca9555.cpp:98
void pin_mode(uint8_t pin, gpio::Flags flags)
Definition tca9555.cpp:36
void digital_write(bool value) override
Definition tca9555.cpp:141
void pin_mode(gpio::Flags flags) override
Definition tca9555.cpp:139
std::string dump_summary() const override
Definition tca9555.cpp:142
@ FLAG_OUTPUT
Definition gpio.h:19
@ FLAG_INPUT
Definition gpio.h:18
const float IO
For components that represent GPIO pins like PCF8573.
Definition component.cpp:17
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string str_sprintf(const char *fmt,...)
Definition helpers.cpp:323