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