ESPHome 2026.3.0-dev
Loading...
Searching...
No Matches
ch423.cpp
Go to the documentation of this file.
1#include "ch423.h"
2#include "esphome/core/log.h"
4
5namespace esphome::ch423 {
6
7static constexpr uint8_t CH423_REG_SYS = 0x24; // Set system parameters (0x48 >> 1)
8static constexpr uint8_t CH423_SYS_IO_OE = 0x01; // IO output enable
9static constexpr uint8_t CH423_SYS_OD_EN = 0x04; // Open drain enable for OC pins
10static constexpr uint8_t CH423_REG_IO = 0x30; // Write/read IO7-IO0 (0x60 >> 1)
11static constexpr uint8_t CH423_REG_IO_RD = 0x26; // Read IO7-IO0 (0x4D >> 1, rounded down)
12static constexpr uint8_t CH423_REG_OCL = 0x22; // Write OC7-OC0 (0x44 >> 1)
13static constexpr uint8_t CH423_REG_OCH = 0x23; // Write OC15-OC8 (0x46 >> 1)
14
15static const char *const TAG = "ch423";
16
18 // set outputs before mode
19 this->write_outputs_();
20 // Set system parameters and check for errors
21 bool success = this->write_reg_(CH423_REG_SYS, this->sys_params_);
22 // Only read inputs if pins are configured for input (IO_OE not set)
23 if (success && !(this->sys_params_ & CH423_SYS_IO_OE)) {
24 success = this->read_inputs_();
25 }
26 if (!success) {
27 ESP_LOGE(TAG, "CH423 not detected");
28 this->mark_failed();
29 return;
30 }
31
32 ESP_LOGCONFIG(TAG, "Initialization complete. Warning: %d, Error: %d", this->status_has_warning(),
33 this->status_has_error());
34}
35
37 // Clear all the previously read flags.
38 this->pin_read_flags_ = 0x00;
39}
40
42 ESP_LOGCONFIG(TAG, "CH423:");
43 if (this->is_failed()) {
44 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
45 }
46}
47
49 if (pin < 8) {
51 this->sys_params_ |= CH423_SYS_IO_OE;
52 }
53 } else if (pin >= 8 && pin < 24) {
55 this->sys_params_ |= CH423_SYS_OD_EN;
56 }
57 }
58}
59
61 if (this->pin_read_flags_ == 0 || this->pin_read_flags_ & (1 << pin)) {
62 // Read values on first access or in case it's being read again in the same loop
63 this->read_inputs_();
64 }
65
66 this->pin_read_flags_ |= (1 << pin);
67 return (this->input_bits_ & (1 << pin)) != 0;
68}
69
70void CH423Component::digital_write(uint8_t pin, bool value) {
71 if (value) {
72 this->output_bits_ |= (1 << pin);
73 } else {
74 this->output_bits_ &= ~(1 << pin);
75 }
76 this->write_outputs_();
77}
78
80 if (this->is_failed()) {
81 return false;
82 }
83 // reading inputs requires IO_OE to be 0
84 if (this->sys_params_ & CH423_SYS_IO_OE) {
85 return false;
86 }
87 uint8_t result = this->read_reg_(CH423_REG_IO_RD);
88 this->input_bits_ = result;
90 return true;
91}
92
93// Write a register. Can't use the standard write_byte() method because there is no single pre-configured i2c address.
94bool CH423Component::write_reg_(uint8_t reg, uint8_t value) {
95 auto err = this->bus_->write_readv(reg, &value, 1, nullptr, 0);
96 if (err != i2c::ERROR_OK) {
97 char buf[64];
98 ESPHOME_snprintf_P(buf, sizeof(buf), ESPHOME_PSTR("write failed for register 0x%X, error %d"), reg, err);
99 this->status_set_warning(buf);
100 return false;
101 }
102 this->status_clear_warning();
103 return true;
104}
105
106uint8_t CH423Component::read_reg_(uint8_t reg) {
107 uint8_t value;
108 auto err = this->bus_->write_readv(reg, nullptr, 0, &value, 1);
109 if (err != i2c::ERROR_OK) {
110 char buf[64];
111 ESPHOME_snprintf_P(buf, sizeof(buf), ESPHOME_PSTR("read failed for register 0x%X, error %d"), reg, err);
112 this->status_set_warning(buf);
113 return 0;
114 }
115 this->status_clear_warning();
116 return value;
117}
118
120 bool success = true;
121 // Write IO7-IO0
122 success &= this->write_reg_(CH423_REG_IO, static_cast<uint8_t>(this->output_bits_));
123 // Write OC7-OC0
124 success &= this->write_reg_(CH423_REG_OCL, static_cast<uint8_t>(this->output_bits_ >> 8));
125 // Write OC15-OC8
126 success &= this->write_reg_(CH423_REG_OCH, static_cast<uint8_t>(this->output_bits_ >> 16));
127 return success;
128}
129
131
132// Run our loop() method very early in the loop, so that we cache read values
133// before other components call our digital_read() method.
134float CH423Component::get_loop_priority() const { return 9.0f; } // Just after WIFI
135
137bool CH423GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) ^ this->inverted_; }
138
139void CH423GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value ^ this->inverted_); }
140size_t CH423GPIOPin::dump_summary(char *buffer, size_t len) const {
141 return snprintf(buffer, len, "EXIO%u via CH423", this->pin_);
142}
144 flags_ = flags;
145 this->parent_->pin_mode(this->pin_, flags);
146}
147
148} // namespace esphome::ch423
virtual void mark_failed()
Mark this component as failed.
bool is_failed() const
void status_set_warning(const char *message=nullptr)
bool status_has_warning() const
bool status_has_error() const
void status_clear_warning()
uint8_t read_reg_(uint8_t reg)
Definition ch423.cpp:106
void digital_write(uint8_t pin, bool value)
Helper function to write the value of a pin.
Definition ch423.cpp:70
bool write_reg_(uint8_t reg, uint8_t value)
Definition ch423.cpp:94
void setup() override
Check i2c availability and setup masks.
Definition ch423.cpp:17
uint8_t pin_read_flags_
Flags to check if read previously during this loop.
Definition ch423.h:37
uint8_t input_bits_
Copy of last read values.
Definition ch423.h:39
uint8_t sys_params_
System parameters.
Definition ch423.h:41
bool digital_read(uint8_t pin)
Helper function to read the value of a pin.
Definition ch423.cpp:60
float get_loop_priority() const override
Definition ch423.cpp:134
float get_setup_priority() const override
Definition ch423.cpp:130
void pin_mode(uint8_t pin, gpio::Flags flags)
Helper function to set the pin mode of a pin.
Definition ch423.cpp:48
void dump_config() override
Definition ch423.cpp:41
void loop() override
Poll for input changes periodically.
Definition ch423.cpp:36
uint32_t output_bits_
The mask to write as output state - 1 means HIGH, 0 means LOW.
Definition ch423.h:35
void digital_write(bool value) override
Definition ch423.cpp:139
void set_flags(gpio::Flags flags)
Definition ch423.cpp:143
CH423Component * parent_
Definition ch423.h:61
size_t dump_summary(char *buffer, size_t len) const override
Definition ch423.cpp:140
bool digital_read() override
Definition ch423.cpp:137
void pin_mode(gpio::Flags flags) override
Definition ch423.cpp:136
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...
I2CBus * bus_
pointer to I2CBus instance
Definition i2c.h:303
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
Definition i2c.h:153
uint16_t flags
@ FLAG_OUTPUT
Definition gpio.h:28
@ FLAG_OPEN_DRAIN
Definition gpio.h:29
@ ERROR_OK
No error found during execution of method.
Definition i2c_bus.h:17
const float IO
For components that represent GPIO pins like PCF8573.
Definition component.cpp:82
std::string size_t len
Definition helpers.h:692