ESPHome  2024.4.0
pca6416a.cpp
Go to the documentation of this file.
1 #include "pca6416a.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace pca6416a {
6 
8  // 0 side
15  // 1 side
22 };
23 
24 static const char *const TAG = "pca6416a";
25 
27  ESP_LOGCONFIG(TAG, "Setting up PCA6416A...");
28  // Test to see if device exists
29  uint8_t value;
30  if (!this->read_register_(PCA6416A_INPUT0, &value)) {
31  ESP_LOGE(TAG, "PCA6416A not available under 0x%02X", this->address_);
32  this->mark_failed();
33  return;
34  }
35 
36  // Test to see if the device supports pull-up resistors
37  if (this->read_register(PCAL6416A_PULL_EN0, &value, 1, true) == esphome::i2c::ERROR_OK) {
38  this->has_pullup_ = true;
39  }
40 
41  // No polarity inversion
44  // Set all pins to input
45  this->write_register_(PCA6416A_CONFIG0, 0xff);
46  this->write_register_(PCA6416A_CONFIG1, 0xff);
47  // Read current output register state
50 
51  ESP_LOGD(TAG, "Initialization complete. Warning: %d, Error: %d", this->status_has_warning(),
52  this->status_has_error());
53 }
54 
56  if (this->has_pullup_) {
57  ESP_LOGCONFIG(TAG, "PCAL6416A:");
58  } else {
59  ESP_LOGCONFIG(TAG, "PCA6416A:");
60  }
61  LOG_I2C_DEVICE(this)
62  if (this->is_failed()) {
63  ESP_LOGE(TAG, "Communication with PCA6416A failed!");
64  }
65 }
66 
68  uint8_t bit = pin % 8;
69  uint8_t reg_addr = pin < 8 ? PCA6416A_INPUT0 : PCA6416A_INPUT1;
70  uint8_t value = 0;
71  this->read_register_(reg_addr, &value);
72  return value & (1 << bit);
73 }
74 
75 void PCA6416AComponent::digital_write(uint8_t pin, bool value) {
76  uint8_t reg_addr = pin < 8 ? PCA6416A_OUTPUT0 : PCA6416A_OUTPUT1;
77  this->update_register_(pin, value, reg_addr);
78 }
79 
81  uint8_t io_dir = pin < 8 ? PCA6416A_CONFIG0 : PCA6416A_CONFIG1;
82  uint8_t pull_en = pin < 8 ? PCAL6416A_PULL_EN0 : PCAL6416A_PULL_EN1;
83  uint8_t pull_dir = pin < 8 ? PCAL6416A_PULL_DIR0 : PCAL6416A_PULL_DIR1;
84  if (flags == gpio::FLAG_INPUT) {
85  this->update_register_(pin, true, io_dir);
86  if (has_pullup_) {
87  this->update_register_(pin, true, pull_dir);
88  this->update_register_(pin, false, pull_en);
89  }
90  } else if (flags == (gpio::FLAG_INPUT | gpio::FLAG_PULLUP)) {
91  this->update_register_(pin, true, io_dir);
92  if (has_pullup_) {
93  this->update_register_(pin, true, pull_dir);
94  this->update_register_(pin, true, pull_en);
95  } else {
96  ESP_LOGW(TAG, "Your PCA6416A does not support pull-up resistors");
97  }
98  } else if (flags == gpio::FLAG_OUTPUT) {
99  this->update_register_(pin, false, io_dir);
100  }
101 }
102 
103 bool PCA6416AComponent::read_register_(uint8_t reg, uint8_t *value) {
104  if (this->is_failed()) {
105  ESP_LOGD(TAG, "Device marked failed");
106  return false;
107  }
108 
109  if ((this->last_error_ = this->read_register(reg, value, 1, true)) != esphome::i2c::ERROR_OK) {
110  this->status_set_warning();
111  ESP_LOGE(TAG, "read_register_(): I2C I/O error: %d", (int) this->last_error_);
112  return false;
113  }
114 
115  this->status_clear_warning();
116  return true;
117 }
118 
119 bool PCA6416AComponent::write_register_(uint8_t reg, uint8_t value) {
120  if (this->is_failed()) {
121  ESP_LOGD(TAG, "Device marked failed");
122  return false;
123  }
124 
125  if ((this->last_error_ = this->write_register(reg, &value, 1, true)) != esphome::i2c::ERROR_OK) {
126  this->status_set_warning();
127  ESP_LOGE(TAG, "write_register_(): I2C I/O error: %d", (int) this->last_error_);
128  return false;
129  }
130 
131  this->status_clear_warning();
132  return true;
133 }
134 
135 void PCA6416AComponent::update_register_(uint8_t pin, bool pin_value, uint8_t reg_addr) {
136  uint8_t bit = pin % 8;
137  uint8_t reg_value = 0;
138  if (reg_addr == PCA6416A_OUTPUT0) {
139  reg_value = this->output_0_;
140  } else if (reg_addr == PCA6416A_OUTPUT1) {
141  reg_value = this->output_1_;
142  } else {
143  this->read_register_(reg_addr, &reg_value);
144  }
145 
146  if (pin_value) {
147  reg_value |= 1 << bit;
148  } else {
149  reg_value &= ~(1 << bit);
150  }
151 
152  this->write_register_(reg_addr, reg_value);
153 
154  if (reg_addr == PCA6416A_OUTPUT0) {
155  this->output_0_ = reg_value;
156  } else if (reg_addr == PCA6416A_OUTPUT1) {
157  this->output_1_ = reg_value;
158  }
159 }
160 
162 
163 void PCA6416AGPIOPin::setup() { pin_mode(flags_); }
164 void PCA6416AGPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
165 bool PCA6416AGPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
166 void PCA6416AGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
167 std::string PCA6416AGPIOPin::dump_summary() const {
168  char buffer[32];
169  snprintf(buffer, sizeof(buffer), "%u via PCA6416A", pin_);
170  return buffer;
171 }
172 
173 } // namespace pca6416a
174 } // namespace esphome
bool digital_read(uint8_t pin)
Helper function to read the value of a pin.
Definition: pca6416a.cpp:67
void digital_write(bool value) override
Definition: pca6416a.cpp:166
ErrorCode read_register(uint8_t a_register, uint8_t *data, size_t len, bool stop=true)
reads an array of bytes from a specific register in the I²C device
Definition: i2c.cpp:10
void status_set_warning(const char *message="unspecified")
Definition: component.cpp:151
bool status_has_warning() const
Definition: component.cpp:149
bool write_register_(uint8_t reg, uint8_t value)
Definition: pca6416a.cpp:119
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
Definition: i2c.h:149
esphome::i2c::ErrorCode last_error_
Storage for last I2C error seen.
Definition: pca6416a.h:36
void digital_write(uint8_t pin, bool value)
Helper function to write the value of a pin.
Definition: pca6416a.cpp:75
bool has_pullup_
Only the PCAL6416A has pull-up resistors.
Definition: pca6416a.h:38
void pin_mode(gpio::Flags flags) override
Definition: pca6416a.cpp:164
void update_register_(uint8_t pin, bool pin_value, uint8_t reg_addr)
Definition: pca6416a.cpp:135
bool status_has_error() const
Definition: component.cpp:150
std::string dump_summary() const override
Definition: pca6416a.cpp:167
No error found during execution of method.
Definition: i2c_bus.h:13
void status_clear_warning()
Definition: component.cpp:166
void pin_mode(uint8_t pin, gpio::Flags flags)
Helper function to set the pin mode of a pin.
Definition: pca6416a.cpp:80
bool read_register_(uint8_t reg, uint8_t *value)
Definition: pca6416a.cpp:103
void setup() override
Check i2c availability and setup masks.
Definition: pca6416a.cpp:26
const uint32_t flags
Definition: stm32flash.h:85
uint8_t address_
store the address of the device on the bus
Definition: i2c.h:269
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:118
const float IO
For components that represent GPIO pins like PCF8573.
Definition: component.cpp:17
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
ErrorCode write_register(uint8_t a_register, const uint8_t *data, size_t len, bool stop=true)
writes an array of bytes to a specific register in the I²C device
Definition: i2c.cpp:25
float get_setup_priority() const override
Definition: pca6416a.cpp:161
uint8_t output_0_
The mask to write as output state - 1 means HIGH, 0 means LOW.
Definition: pca6416a.h:33