ESPHome 2026.6.0-dev
Loading...
Searching...
No Matches
weikai_i2c.cpp
Go to the documentation of this file.
1
5
6#include "weikai_i2c.h"
7
9static const char *const TAG = "weikai_i2c";
10
12void print_buffer(const uint8_t *data, size_t length) {
13 char hex_buffer[100];
14 hex_buffer[(3 * 32) + 1] = 0;
15 for (size_t i = 0; i < length; i++) {
16 snprintf(&hex_buffer[3 * (i % 32)], sizeof(hex_buffer), "%02X ", data[i]);
17 if (i % 32 == 31) {
18 ESP_LOGVV(TAG, " %s", hex_buffer);
19 }
20 }
21 if (length % 32) {
22 // null terminate if incomplete line
23 hex_buffer[3 * (length % 32) + 2] = 0;
24 ESP_LOGVV(TAG, " %s", hex_buffer);
25 }
26}
27
28static const char *const REG_TO_STR_P0[16] = {"GENA", "GRST", "GMUT", "SPAGE", "SCR", "LCR", "FCR", "SIER",
29 "SIFR", "TFCNT", "RFCNT", "FSR", "LSR", "FDAT", "FWCR", "RS485"};
30static const char *const REG_TO_STR_P1[16] = {"GENA", "GRST", "GMUT", "SPAGE", "BAUD1", "BAUD0", "PRES", "RFTL",
31 "TFTL", "FWTH", "FWTL", "XON1", "XOFF1", "SADR", "SAEN", "RTSDLY"};
32using namespace weikai;
33// method to print a register value as text: used in the log messages ...
34const char *reg_to_str(int reg, bool page1) {
35 if (reg == WKREG_GPDAT) {
36 return "GPDAT";
37 } else if (reg == WKREG_GPDIR) {
38 return "GPDIR";
39 } else {
40 return page1 ? REG_TO_STR_P1[reg & 0x0F] : REG_TO_STR_P0[reg & 0x0F];
41 }
42}
43enum RegType { REG = 0, FIFO = 1 };
44
50inline uint8_t i2c_address(uint8_t base_address, uint8_t channel, RegType fifo) {
51 // the address of the device is:
52 // +----+----+----+----+----+----+----+----+
53 // | 0 | A1 | A0 | 1 | 0 | C1 | C0 | F |
54 // +----+----+----+----+----+----+----+----+
55 // where:
56 // - A1,A0 is the address read from A1,A0 switch
57 // - C1,C0 is the channel number (in practice only 00 or 01)
58 // - F is: 0 when accessing register, one when accessing FIFO
59 uint8_t const addr = base_address | channel << 1 | fifo << 0;
60 return addr;
61}
62
64// The WeikaiRegisterI2C methods
67 uint8_t value = 0x00;
68 WeikaiComponentI2C *comp_i2c = static_cast<WeikaiComponentI2C *>(this->comp_);
69 uint8_t address = i2c_address(comp_i2c->base_address_, this->channel_, REG);
70 comp_i2c->set_i2c_address(address);
71 auto error = comp_i2c->read_register(this->register_, &value, 1);
72 if (error == i2c::NO_ERROR) {
74 ESP_LOGVV(TAG, "WeikaiRegisterI2C::read_reg() @%02X reg=%s ch=%u I2C_code:%d, buf=%02X", address,
75 reg_to_str(this->register_, comp_i2c->page1()), this->channel_, (int) error, value);
76 } else { // error
78 ESP_LOGE(TAG, "WeikaiRegisterI2C::read_reg() @%02X reg=%s ch=%u I2C_code:%d, buf=%02X", address,
79 reg_to_str(this->register_, comp_i2c->page1()), this->channel_, (int) error, value);
80 }
81 return value;
82}
83
84void WeikaiRegisterI2C::read_fifo(uint8_t *data, size_t length) const {
85 WeikaiComponentI2C *comp_i2c = static_cast<WeikaiComponentI2C *>(this->comp_);
86 uint8_t address = i2c_address(comp_i2c->base_address_, this->channel_, FIFO);
87 comp_i2c->set_i2c_address(address);
88 auto error = comp_i2c->read(data, length);
89 if (error == i2c::NO_ERROR) {
91#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
92 ESP_LOGVV(TAG, "WeikaiRegisterI2C::read_fifo() @%02X ch=%d I2C_code:%d len=%d buffer", address, this->channel_,
93 (int) error, length);
94 print_buffer(data, length);
95#endif
96 } else { // error
98 ESP_LOGE(TAG, "WeikaiRegisterI2C::read_fifo() @%02X reg=N/A ch=%d I2C_code:%d len=%d buf=%02X", address,
99 this->channel_, (int) error, length, data[0]);
100 }
101}
102
103void WeikaiRegisterI2C::write_reg(uint8_t value) {
104 WeikaiComponentI2C *comp_i2c = static_cast<WeikaiComponentI2C *>(this->comp_);
105 uint8_t address = i2c_address(comp_i2c->base_address_, this->channel_, REG); // update the i2c bus
106 comp_i2c->set_i2c_address(address);
107 auto error = comp_i2c->write_register(this->register_, &value, 1);
108 if (error == i2c::NO_ERROR) {
110 ESP_LOGVV(TAG, "WK2168Reg::write_reg() @%02X reg=%s ch=%d I2C_code:%d buf=%02X", address,
111 reg_to_str(this->register_, comp_i2c->page1()), this->channel_, (int) error, value);
112 } else { // error
113 this->comp_->status_set_warning();
114 ESP_LOGE(TAG, "WK2168Reg::write_reg() @%02X reg=%s ch=%d I2C_code:%d buf=%d", address,
115 reg_to_str(this->register_, comp_i2c->page1()), this->channel_, (int) error, value);
116 }
117}
118
119void WeikaiRegisterI2C::write_fifo(uint8_t *data, size_t length) {
120 WeikaiComponentI2C *comp_i2c = static_cast<WeikaiComponentI2C *>(this->comp_);
121 uint8_t address = i2c_address(comp_i2c->base_address_, this->channel_, FIFO); // set fifo flag
122 comp_i2c->set_i2c_address(address);
123 auto error = comp_i2c->write(data, length);
124 if (error == i2c::NO_ERROR) {
126#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
127 ESP_LOGVV(TAG, "WK2168Reg::write_fifo() @%02X ch=%d I2C_code:%d len=%d buffer", address, this->channel_,
128 (int) error, length);
129 print_buffer(data, length);
130#endif
131 } else { // error
132 this->comp_->status_set_warning();
133 ESP_LOGE(TAG, "WK2168Reg::write_fifo() @%02X reg=N/A, ch=%d I2C_code:%d len=%d, buf=%02X", address, this->channel_,
134 (int) error, length, data[0]);
135 }
136}
137
139// The WeikaiComponentI2C methods
142 // before any manipulation we store the address to base_address_ for future use
143 this->base_address_ = this->address_;
144 ESP_LOGCONFIG(TAG, "Setup %s (%d UARTs) @ 0x%02X", this->get_name(), this->children_.size(), this->base_address_);
145
146 // enable all channels
148 // reset all channels
150 // initialize the spage register to page 0
151 this->reg(WKREG_SPAGE, 0) = 0;
152 this->page1_ = false;
153
154 // we setup our children channels
155 for (auto *child : this->children_) {
156 child->setup_channel();
157 }
158}
159
161 ESP_LOGCONFIG(TAG,
162 "Initialization of %s with %d UARTs completed\n"
163 " Crystal: %" PRIu32,
164 this->get_name(), this->children_.size(), this->crystal_);
165 if (test_mode_) {
166 ESP_LOGCONFIG(TAG,
167 " Test mode: %d\n"
168 " Transfer buffer size: %d",
170 }
171 this->address_ = this->base_address_; // we restore the base_address before display (less confusing)
172 LOG_I2C_DEVICE(this);
173
174 for (auto *child : this->children_) {
175 child->dump_channel();
176 }
177}
178
179} // namespace esphome::weikai_i2c
uint8_t address
Definition bl0906.h:4
void status_clear_warning()
Definition component.h:289
ErrorCode write_register(uint8_t a_register, const uint8_t *data, size_t len) const
writes an array of bytes to a specific register in the I²C device
Definition i2c.cpp:34
ErrorCode write(const uint8_t *data, size_t len) const
writes an array of bytes to a device using an I2CBus
Definition i2c.h:183
ErrorCode read(uint8_t *data, size_t len) const
reads an array of bytes from the device using an I2CBus
Definition i2c.h:163
uint8_t address_
store the address of the device on the bus
Definition i2c.h:270
void set_i2c_address(uint8_t address)
We store the address of the device on the bus.
Definition i2c.h:139
ErrorCode read_register(uint8_t a_register, uint8_t *data, size_t len)
reads an array of bytes from a specific register in the I²C device
Definition i2c.cpp:25
int test_mode_
test mode value (0 -> no tests)
Definition weikai.h:260
bool page1_
set to true when in "page1 mode"
Definition weikai.h:261
std::vector< WeikaiChannel * > children_
the list of WeikaiChannel UART children
Definition weikai.h:262
const char * get_name()
Get the name of the component.
Definition weikai.h:214
uint8_t register_
address of the register
Definition weikai.h:184
uint8_t channel_
channel for this register
Definition weikai.h:185
WeikaiComponent *const comp_
pointer to our parent (aggregation)
Definition weikai.h:183
The WeikaiComponentI2C class stores the information to the WeiKai component connected through an I2C ...
Definition weikai_i2c.h:41
weikai::WeikaiRegister & reg(uint8_t reg, uint8_t channel) override
Definition weikai_i2c.h:43
uint8_t base_address_
base address of I2C device
Definition weikai_i2c.h:55
void write_fifo(uint8_t *data, size_t length) override
uint8_t read_reg() const override
void write_reg(uint8_t value) override
void read_fifo(uint8_t *data, size_t length) const override
constexpr uint8_t WKREG_SPAGE
Global Page register c0/c1 0011.
Definition wk_reg_def.h:126
constexpr uint8_t GRST_C4RST
Channel 4 soft reset (0: not reset, 1: reset)
Definition wk_reg_def.h:55
constexpr uint8_t WKREG_GPDIR
Global GPIO direction register - 10 0001.
Definition wk_reg_def.h:84
constexpr uint8_t WKREG_GPDAT
Global GPIO data register - 11 0001.
Definition wk_reg_def.h:98
constexpr uint8_t GRST_C2RST
Channel 2 soft reset (0: not reset, 1: reset)
Definition wk_reg_def.h:59
constexpr uint8_t WKREG_GRST
Global Reset Register - 00 0001.
Definition wk_reg_def.h:53
constexpr uint8_t GRST_C3RST
Channel 3 soft reset (0: not reset, 1: reset)
Definition wk_reg_def.h:57
constexpr uint8_t GENA_C2EN
Channel 2 enable clock (0: disable, 1: enable)
Definition wk_reg_def.h:37
constexpr uint8_t GRST_C1RST
Channel 1 soft reset (0: not reset, 1: reset)
Definition wk_reg_def.h:61
constexpr uint8_t GENA_C3EN
Channel 3 enable clock (0: disable, 1: enable)
Definition wk_reg_def.h:35
constexpr uint8_t GENA_C4EN
Channel 4 enable clock (0: disable, 1: enable)
Definition wk_reg_def.h:33
constexpr uint8_t WKREG_GENA
Global Control Register - 00 0000.
Definition wk_reg_def.h:31
constexpr uint8_t GENA_C1EN
Channel 1 enable clock (0: disable, 1: enable)
Definition wk_reg_def.h:39
@ NO_ERROR
No error found during execution of method.
Definition i2c_bus.h:13
uint8_t i2c_address(uint8_t base_address, uint8_t channel, RegType fifo)
Computes the I²C bus's address used to access the component.
constexpr size_t XFER_MAX_SIZE
XFER_MAX_SIZE defines the maximum number of bytes allowed during one transfer.
Definition weikai.h:32
const char * reg_to_str(int reg, bool page1)
Definition weikai.cpp:62
void print_buffer(const uint8_t *data, size_t length)
Display a buffer in hexadecimal format (32 hex values / line) for debug.
Definition weikai.cpp:40
uint16_t length
Definition tt21100.cpp:0
WeiKai component family - classes declaration.