ESPHome  2024.12.2
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) == 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  this->last_error_ = this->read_register(reg, value, 1, true);
110  if (this->last_error_ != i2c::ERROR_OK) {
111  this->status_set_warning();
112  ESP_LOGE(TAG, "read_register_(): I2C I/O error: %d", (int) this->last_error_);
113  return false;
114  }
115 
116  this->status_clear_warning();
117  return true;
118 }
119 
120 bool PCA6416AComponent::write_register_(uint8_t reg, uint8_t value) {
121  if (this->is_failed()) {
122  ESP_LOGD(TAG, "Device marked failed");
123  return false;
124  }
125 
126  this->last_error_ = this->write_register(reg, &value, 1, true);
127  if (this->last_error_ != i2c::ERROR_OK) {
128  this->status_set_warning();
129  ESP_LOGE(TAG, "write_register_(): I2C I/O error: %d", (int) this->last_error_);
130  return false;
131  }
132 
133  this->status_clear_warning();
134  return true;
135 }
136 
137 void PCA6416AComponent::update_register_(uint8_t pin, bool pin_value, uint8_t reg_addr) {
138  uint8_t bit = pin % 8;
139  uint8_t reg_value = 0;
140  if (reg_addr == PCA6416A_OUTPUT0) {
141  reg_value = this->output_0_;
142  } else if (reg_addr == PCA6416A_OUTPUT1) {
143  reg_value = this->output_1_;
144  } else {
145  this->read_register_(reg_addr, &reg_value);
146  }
147 
148  if (pin_value) {
149  reg_value |= 1 << bit;
150  } else {
151  reg_value &= ~(1 << bit);
152  }
153 
154  this->write_register_(reg_addr, reg_value);
155 
156  if (reg_addr == PCA6416A_OUTPUT0) {
157  this->output_0_ = reg_value;
158  } else if (reg_addr == PCA6416A_OUTPUT1) {
159  this->output_1_ = reg_value;
160  }
161 }
162 
164 
165 void PCA6416AGPIOPin::setup() { pin_mode(flags_); }
166 void PCA6416AGPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
167 bool PCA6416AGPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
168 void PCA6416AGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
169 std::string PCA6416AGPIOPin::dump_summary() const {
170  char buffer[32];
171  snprintf(buffer, sizeof(buffer), "%u via PCA6416A", pin_);
172  return buffer;
173 }
174 
175 } // namespace pca6416a
176 } // 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:168
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:120
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
Definition: i2c.h:149
bool is_failed() const
Definition: component.cpp:143
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:166
void update_register_(uint8_t pin, bool pin_value, uint8_t reg_addr)
Definition: pca6416a.cpp:137
bool status_has_error() const
Definition: component.cpp:150
std::string dump_summary() const override
Definition: pca6416a.cpp:169
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
Implementation of SPI Controller mode.
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:163
uint8_t output_0_
The mask to write as output state - 1 means HIGH, 0 means LOW.
Definition: pca6416a.h:33