ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
ch422g.cpp
Go to the documentation of this file.
1#include "ch422g.h"
3#include "esphome/core/log.h"
4
5namespace esphome::ch422g {
6
7static const uint8_t CH422G_REG_MODE = 0x24;
8static const uint8_t CH422G_MODE_OUTPUT = 0x01; // enables output mode on 0-7
9static const uint8_t CH422G_MODE_OPEN_DRAIN = 0x04; // enables open drain mode on 8-11
10static const uint8_t CH422G_REG_IN = 0x26; // read reg for input bits
11static const uint8_t CH422G_REG_OUT = 0x38; // write reg for output bits 0-7
12static const uint8_t CH422G_REG_OUT_UPPER = 0x23; // write reg for output bits 8-11
13
14ESPHOME_LOG_TAG(TAG, "ch422g");
15
17 // set outputs before mode
18 this->write_outputs_();
19 // Set mode and check for errors
20 if (!this->set_mode_(this->mode_value_) || !this->read_inputs_()) {
21 ESP_LOGE(TAG, "CH422G not detected at 0x%02X", this->address_);
22 this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
23 return;
24 }
25
26 ESP_LOGCONFIG(TAG, "Initialization complete. Warning: %d, Error: %d", this->status_has_warning(),
27 this->status_has_error());
28}
29
31 // Clear all the previously read flags.
32 this->pin_read_flags_ = 0x00;
33}
34
36 ESP_LOGCONFIG(TAG, "CH422G:");
37 LOG_I2C_DEVICE(this)
38}
39
41 if (pin < 8) {
43 this->mode_value_ |= CH422G_MODE_OUTPUT;
44 }
45 } else {
47 this->mode_value_ |= CH422G_MODE_OPEN_DRAIN;
48 }
49 }
50}
51
53 if (this->pin_read_flags_ == 0 || this->pin_read_flags_ & (1 << pin)) {
54 // Read values on first access or in case it's being read again in the same loop
55 this->read_inputs_();
56 }
57
58 this->pin_read_flags_ |= (1 << pin);
59 return (this->input_bits_ & (1 << pin)) != 0;
60}
61
62void CH422GComponent::digital_write(uint8_t pin, bool value) {
63 assign_bits(this->output_bits_, 1 << pin, value);
64 this->write_outputs_();
65}
66
68 if (this->is_failed()) {
69 return false;
70 }
71 uint8_t result;
72 // reading inputs requires the chip to be in input mode, possibly temporarily.
73 if (this->mode_value_ & CH422G_MODE_OUTPUT) {
74 this->set_mode_(this->mode_value_ & ~CH422G_MODE_OUTPUT);
75 result = this->read_reg_(CH422G_REG_IN);
76 this->set_mode_(this->mode_value_);
77 } else {
78 result = this->read_reg_(CH422G_REG_IN);
79 }
80 this->input_bits_ = result;
82 return true;
83}
84
85// Write a register. Can't use the standard write_byte() method because there is no single pre-configured i2c address.
86bool CH422GComponent::write_reg_(uint8_t reg, uint8_t value) {
87 auto err = this->bus_->write_readv(reg, &value, 1, nullptr, 0);
88 if (err != i2c::ERROR_OK) {
89 char buf[64];
90 snprintf(buf, sizeof(buf), "write failed for register 0x%X, error %d", reg, err);
91 this->status_set_warning(buf);
92 return false;
93 }
95 return true;
96}
97
98uint8_t CH422GComponent::read_reg_(uint8_t reg) {
99 uint8_t value;
100 auto err = this->bus_->write_readv(reg, nullptr, 0, &value, 1);
101 if (err != i2c::ERROR_OK) {
102 char buf[64];
103 snprintf(buf, sizeof(buf), "read failed for register 0x%X, error %d", reg, err);
104 this->status_set_warning(buf);
105 return 0;
106 }
107 this->status_clear_warning();
108 return value;
109}
110
111bool CH422GComponent::set_mode_(uint8_t mode) { return this->write_reg_(CH422G_REG_MODE, mode); }
112
114 return this->write_reg_(CH422G_REG_OUT, static_cast<uint8_t>(this->output_bits_)) &&
115 this->write_reg_(CH422G_REG_OUT_UPPER, static_cast<uint8_t>(this->output_bits_ >> 8));
116}
117
119
120} // namespace esphome::ch422g
121
122ESPHOME_EXPANDER_PIN_SUMMARY(esphome::ch422g::CH422GComponent, "EXIO%u via CH422G")
BedjetMode mode
BedJet operating mode.
void mark_failed()
Mark this component as failed.
bool is_failed() const
Definition component.h:274
bool status_has_warning() const
Definition component.h:280
bool status_has_error() const
Definition component.h:282
void status_clear_warning()
Definition component.h:296
uint16_t output_bits_
The mask to write as output state - 1 means HIGH, 0 means LOW.
Definition ch422g.h:36
void setup() override
Check i2c availability and setup masks.
Definition ch422g.cpp:16
float get_setup_priority() const override
Definition ch422g.cpp:118
bool set_mode_(uint8_t mode)
Definition ch422g.cpp:111
void pin_mode(uint8_t pin, gpio::Flags flags)
Helper function to set the pin mode of a pin.
Definition ch422g.cpp:40
uint8_t pin_read_flags_
Flags to check if read previously during this loop.
Definition ch422g.h:38
void loop() override
Poll for input changes periodically.
Definition ch422g.cpp:30
uint8_t read_reg_(uint8_t reg)
Definition ch422g.cpp:98
uint8_t mode_value_
Copy of the mode value.
Definition ch422g.h:42
bool write_reg_(uint8_t reg, uint8_t value)
Definition ch422g.cpp:86
uint8_t input_bits_
Copy of last read values.
Definition ch422g.h:40
bool digital_read(uint8_t pin)
Helper function to read the value of a pin.
Definition ch422g.cpp:52
void digital_write(uint8_t pin, bool value)
Helper function to write the value of a pin.
Definition ch422g.cpp:62
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:325
uint8_t address_
store the address of the device on the bus
Definition i2c.h:327
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
Definition i2c.h:164
uint16_t flags
ESPHOME_LOG_TAG(TAG, "ch422g")
@ ERROR_OK
No error found during execution of method.
Definition i2c_bus.h:15
constexpr float IO
For components that represent GPIO pins like PCF8573.
Definition component.h:41
ESPHOME_ALWAYS_INLINE constexpr void assign_bits(T &value, std::type_identity_t< T > mask, bool on)
Set the bits of mask in value when on is true, clear them otherwise.
Definition helpers.h:1072