ESPHome  2024.12.2
ch422g.cpp
Go to the documentation of this file.
1 #include "ch422g.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace ch422g {
6 
7 static const uint8_t CH422G_REG_MODE = 0x24;
8 static const uint8_t CH422G_MODE_OUTPUT = 0x01; // enables output mode on 0-7
9 static const uint8_t CH422G_MODE_OPEN_DRAIN = 0x04; // enables open drain mode on 8-11
10 static const uint8_t CH422G_REG_IN = 0x26; // read reg for input bits
11 static const uint8_t CH422G_REG_OUT = 0x38; // write reg for output bits 0-7
12 static const uint8_t CH422G_REG_OUT_UPPER = 0x23; // write reg for output bits 8-11
13 
14 static const char *const TAG = "ch422g";
15 
17  ESP_LOGCONFIG(TAG, "Setting up CH422G...");
18  // set outputs before mode
19  this->write_outputs_();
20  // Set mode and check for errors
21  if (!this->set_mode_(this->mode_value_) || !this->read_inputs_()) {
22  ESP_LOGE(TAG, "CH422G not detected at 0x%02X", this->address_);
23  this->mark_failed();
24  return;
25  }
26 
27  ESP_LOGCONFIG(TAG, "Initialization complete. Warning: %d, Error: %d", this->status_has_warning(),
28  this->status_has_error());
29 }
30 
32  // Clear all the previously read flags.
33  this->pin_read_flags_ = 0x00;
34 }
35 
37  ESP_LOGCONFIG(TAG, "CH422G:");
38  LOG_I2C_DEVICE(this)
39  if (this->is_failed()) {
40  ESP_LOGE(TAG, "Communication with CH422G failed!");
41  }
42 }
43 
45  if (pin < 8) {
46  if (flags & gpio::FLAG_OUTPUT) {
47  this->mode_value_ |= CH422G_MODE_OUTPUT;
48  }
49  } else {
50  if (flags & gpio::FLAG_OPEN_DRAIN) {
51  this->mode_value_ |= CH422G_MODE_OPEN_DRAIN;
52  }
53  }
54 }
55 
56 bool CH422GComponent::digital_read(uint8_t pin) {
57  if (this->pin_read_flags_ == 0 || this->pin_read_flags_ & (1 << pin)) {
58  // Read values on first access or in case it's being read again in the same loop
59  this->read_inputs_();
60  }
61 
62  this->pin_read_flags_ |= (1 << pin);
63  return (this->input_bits_ & (1 << pin)) != 0;
64 }
65 
66 void CH422GComponent::digital_write(uint8_t pin, bool value) {
67  if (value) {
68  this->output_bits_ |= (1 << pin);
69  } else {
70  this->output_bits_ &= ~(1 << pin);
71  }
72  this->write_outputs_();
73 }
74 
76  if (this->is_failed()) {
77  return false;
78  }
79  uint8_t result;
80  // reading inputs requires the chip to be in input mode, possibly temporarily.
81  if (this->mode_value_ & CH422G_MODE_OUTPUT) {
82  this->set_mode_(this->mode_value_ & ~CH422G_MODE_OUTPUT);
83  result = this->read_reg_(CH422G_REG_IN);
84  this->set_mode_(this->mode_value_);
85  } else {
86  result = this->read_reg_(CH422G_REG_IN);
87  }
88  this->input_bits_ = result;
89  this->status_clear_warning();
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.
94 bool CH422GComponent::write_reg_(uint8_t reg, uint8_t value) {
95  auto err = this->bus_->write(reg, &value, 1);
96  if (err != i2c::ERROR_OK) {
97  this->status_set_warning(str_sprintf("write failed for register 0x%X, error %d", reg, err).c_str());
98  return false;
99  }
100  this->status_clear_warning();
101  return true;
102 }
103 
104 uint8_t CH422GComponent::read_reg_(uint8_t reg) {
105  uint8_t value;
106  auto err = this->bus_->read(reg, &value, 1);
107  if (err != i2c::ERROR_OK) {
108  this->status_set_warning(str_sprintf("read failed for register 0x%X, error %d", reg, err).c_str());
109  return 0;
110  }
111  this->status_clear_warning();
112  return value;
113 }
114 
115 bool CH422GComponent::set_mode_(uint8_t mode) { return this->write_reg_(CH422G_REG_MODE, mode); }
116 
118  return this->write_reg_(CH422G_REG_OUT, static_cast<uint8_t>(this->output_bits_)) &&
119  this->write_reg_(CH422G_REG_OUT_UPPER, static_cast<uint8_t>(this->output_bits_ >> 8));
120 }
121 
123 
124 // Run our loop() method very early in the loop, so that we cache read values
125 // before other components call our digital_read() method.
126 float CH422GComponent::get_loop_priority() const { return 9.0f; } // Just after WIFI
127 
128 void CH422GGPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
129 bool CH422GGPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) ^ this->inverted_; }
130 
131 void CH422GGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value ^ this->inverted_); }
132 std::string CH422GGPIOPin::dump_summary() const { return str_sprintf("EXIO%u via CH422G", pin_); }
134  flags_ = flags;
135  this->parent_->pin_mode(this->pin_, flags);
136 }
137 
138 } // namespace ch422g
139 } // namespace esphome
float get_loop_priority() const override
Definition: ch422g.cpp:126
std::string dump_summary() const override
Definition: ch422g.cpp:132
void setup() override
Check i2c availability and setup masks.
Definition: ch422g.cpp:16
void status_set_warning(const char *message="unspecified")
Definition: component.cpp:151
bool status_has_warning() const
Definition: component.cpp:149
void loop() override
Poll for input changes periodically.
Definition: ch422g.cpp:31
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
Definition: i2c.h:149
void digital_write(uint8_t pin, bool value)
Helper function to write the value of a pin.
Definition: ch422g.cpp:66
uint16_t output_bits_
The mask to write as output state - 1 means HIGH, 0 means LOW.
Definition: ch422g.h:37
bool is_failed() const
Definition: component.cpp:143
bool write_reg_(uint8_t reg, uint8_t value)
Definition: ch422g.cpp:94
uint8_t mode_value_
Copy of the mode value.
Definition: ch422g.h:43
bool status_has_error() const
Definition: component.cpp:150
uint8_t pin_read_flags_
Flags to check if read previously during this loop.
Definition: ch422g.h:39
No error found during execution of method.
Definition: i2c_bus.h:13
void set_flags(gpio::Flags flags)
Definition: ch422g.cpp:133
std::string str_sprintf(const char *fmt,...)
Definition: helpers.cpp:320
void status_clear_warning()
Definition: component.cpp:166
BedjetMode mode
BedJet operating mode.
Definition: bedjet_codec.h:183
bool digital_read(uint8_t pin)
Helper function to read the value of a pin.
Definition: ch422g.cpp:56
void dump_config() override
Definition: ch422g.cpp:36
void pin_mode(uint8_t pin, gpio::Flags flags)
Helper function to set the pin mode of a pin.
Definition: ch422g.cpp:44
const uint32_t flags
Definition: stm32flash.h:85
float get_setup_priority() const override
Definition: ch422g.cpp:122
uint8_t address_
store the address of the device on the bus
Definition: i2c.h:269
I2CBus * bus_
pointer to I2CBus instance
Definition: i2c.h:270
virtual ErrorCode read(uint8_t address, uint8_t *buffer, size_t len)
Creates a ReadBuffer and calls the virtual readv() method to read bytes into this buffer...
Definition: i2c_bus.h:47
virtual ErrorCode write(uint8_t address, const uint8_t *buffer, size_t len)
Definition: i2c_bus.h:62
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
bool digital_read() override
Definition: ch422g.cpp:129
uint8_t input_bits_
Copy of last read values.
Definition: ch422g.h:41
void digital_write(bool value) override
Definition: ch422g.cpp:131
void pin_mode(gpio::Flags flags) override
Definition: ch422g.cpp:128
uint8_t read_reg_(uint8_t reg)
Definition: ch422g.cpp:104
bool set_mode_(uint8_t mode)
Definition: ch422g.cpp:115