63 static const char *
const TAG =
"weikai";
70 #define I2S2CS(val) (i2s(val).c_str()) 76 uint32_t e =
millis() - last_time;
100 char hex_buffer[100];
101 hex_buffer[(3 * 32) + 1] = 0;
102 for (
size_t i = 0; i <
length; i++) {
103 snprintf(&hex_buffer[3 * (i % 32)],
sizeof(hex_buffer),
"%02X ", data[i]);
105 ESP_LOGVV(TAG,
" %s", hex_buffer);
110 hex_buffer[3 * (length % 32) + 2] = 0;
111 ESP_LOGVV(TAG,
" %s", hex_buffer);
115 static const char *
const REG_TO_STR_P0[16] = {
"GENA",
"GRST",
"GMUT",
"SPAGE",
"SCR",
"LCR",
"FCR",
"SIER",
116 "SIFR",
"TFCNT",
"RFCNT",
"FSR",
"LSR",
"FDAT",
"FWCR",
"RS485"};
117 static const char *
const REG_TO_STR_P1[16] = {
"GENA",
"GRST",
"GMUT",
"SPAGE",
"BAUD1",
"BAUD0",
"PRES",
"RFTL",
118 "TFTL",
"FWTH",
"FWTL",
"XON1",
"XOFF1",
"SADR",
"SAEN",
"RTSDLY"};
127 return page1 ? REG_TO_STR_P1[reg & 0x0F] : REG_TO_STR_P0[reg & 0x0F];
161 size_t transferred = 0;
162 for (
auto *child : this->children_) {
164 transferred += child->xfer_fifo_to_buffer_();
166 if (transferred > 0) {
167 ESP_LOGV(TAG,
"we transferred %d bytes from fifo to buffer...", transferred);
170 #ifdef TEST_COMPONENT 171 static uint32_t loop_time = 0;
172 static uint32_t loop_count = 0;
175 if (test_mode_ == 1) {
176 ESP_LOGI(TAG,
"Component loop %" PRIu32
" for %s : %" PRIu32
" ms since last call ...", loop_count++,
177 this->get_name(),
millis() - loop_time);
181 for (
int i = 0; i < this->children_.size(); i++) {
182 if (i != ((loop_count - 1) % this->children_.size()))
184 snprintf(message,
sizeof(message),
"%s:%s", this->get_name(), children_[i]->get_channel_name());
185 children_[i]->uart_send_test_(message);
186 uint32_t
const start_time =
millis();
187 while (children_[i]->tx_fifo_is_not_empty_()) {
188 if (
millis() - start_time > 1500) {
189 ESP_LOGE(TAG,
"timeout while flushing - %d bytes left in buffer...", children_[i]->tx_in_fifo_());
194 bool status = children_[i]->uart_receive_test_(message);
195 ESP_LOGI(TAG,
"Test %s => send/received %u bytes %s - execution time %" PRIu32
" ms...", message,
200 if (this->test_mode_ == 2) {
201 for (
auto *child : this->children_) {
203 if (child->available()) {
204 child->read_byte(&data);
205 ESP_LOGI(TAG,
"echo mode: read -> send %02X", data);
206 child->write_byte(data);
210 if (test_mode_ == 3) {
214 if (test_mode_ == 4) {
220 #if defined(TEST_COMPONENT) 222 static bool init_input{
false};
223 static uint8_t
state{0};
229 ESP_LOGI(TAG,
"initializing all pins to input mode");
231 ESP_LOGI(TAG,
"initial input data state = %02X (%s)",
state, I2S2CS(
state));
234 if (value !=
state) {
235 ESP_LOGI(TAG,
"Input data changed from %02X to %02X (%s)",
state, value, I2S2CS(value));
241 static bool init_output{
false};
242 static uint8_t
state{0};
247 ESP_LOGI(TAG,
"initializing all pins to output mode");
249 ESP_LOGI(TAG,
"setting all outputs to 0");
253 ESP_LOGI(TAG,
"Flipping all outputs to %02X (%s)",
state, I2S2CS(
state));
263 ESP_LOGVV(TAG,
"reading input pin %u = %u in_state %s", pin, this->input_state_ & (1 << pin), I2S2CS(input_state_));
264 return this->input_state_ & (1 << pin);
269 this->output_state_ |= (1 << pin);
271 this->output_state_ &= ~(1 << pin);
273 ESP_LOGVV(TAG,
"writing output pin %d with %d out_state %s", pin, uint8_t(value), I2S2CS(this->output_state_));
279 this->pin_config_ &= ~(1 << pin);
282 this->pin_config_ |= 1 << pin;
284 ESP_LOGE(TAG,
"pin %d direction invalid", pin);
287 ESP_LOGVV(TAG,
"setting pin %d direction to %d pin_config=%s", pin, flags, I2S2CS(this->pin_config_));
292 ESP_LOGCONFIG(TAG,
"Setting GPIO pin %d mode to %s", this->pin_,
297 this->pin_mode(this->flags_);
302 snprintf(buffer,
sizeof(buffer),
"%u via WeiKai %s", this->pin_, this->parent_->get_name());
310 ESP_LOGCONFIG(TAG,
" Setting up UART %s:%s ...", this->parent_->get_name(), this->get_channel_name());
312 if (this->check_channel_down()) {
313 ESP_LOGCONFIG(TAG,
" Error channel %s not working...", this->get_channel_name());
316 this->receive_buffer_.clear();
317 this->set_line_param_();
318 this->set_baudrate_();
322 ESP_LOGCONFIG(TAG,
" UART %s ...", this->get_channel_name());
323 ESP_LOGCONFIG(TAG,
" Baud rate: %" PRIu32
" Bd", this->baud_rate_);
324 ESP_LOGCONFIG(TAG,
" Data bits: %u", this->data_bits_);
325 ESP_LOGCONFIG(TAG,
" Stop bits: %u", this->stop_bits_);
326 ESP_LOGCONFIG(TAG,
" Parity: %s",
p2s(this->parity_));
337 this->data_bits_ = 8;
339 if (this->stop_bits_ == 2)
341 switch (this->parity_) {
352 ESP_LOGV(TAG,
" line config: %d data_bits, %d stop_bits, parity %s register [%s]", this->data_bits_,
353 this->stop_bits_,
p2s(this->parity_), I2S2CS(lcr));
357 if (this->baud_rate_ > this->parent_->crystal_ / 16) {
358 baud_rate_ = this->parent_->crystal_ / 16;
359 ESP_LOGE(TAG,
" Requested baudrate too high for crystal=%" PRIu32
" Hz. Has been reduced to %" PRIu32
" Bd",
360 this->parent_->crystal_, this->baud_rate_);
362 uint16_t
const val_int = this->parent_->crystal_ / (this->baud_rate_ * 16) - 1;
363 uint16_t val_dec = (this->parent_->crystal_ % (this->baud_rate_ * 16)) / (this->baud_rate_ * 16);
364 uint8_t
const baud_high = (uint8_t) (val_int >> 8);
365 uint8_t
const baud_low = (uint8_t) (val_int & 0xFF);
366 while (val_dec > 0x0A)
368 uint8_t
const baud_dec = (uint8_t) (val_dec);
370 this->parent_->page1_ =
true;
375 this->parent_->page1_ =
false;
378 ESP_LOGV(TAG,
" Crystal=%" PRId32
" baudrate=%" PRId32
" => registers [%d %d %d]", this->parent_->crystal_,
379 this->baud_rate_, baud_high, baud_low, baud_dec);
387 uint8_t
const fsr = this->reg(
WKREG_FSR);
389 ESP_LOGVV(TAG,
"tx FIFO full FSR=%s", I2S2CS(fsr));
393 ESP_LOGVV(TAG,
"tx FIFO contains %d bytes", tfcnt);
399 uint8_t
const fsr = this->reg(
WKREG_FSR);
402 ESP_LOGE(TAG,
"Receive data overflow FSR=%s", I2S2CS(fsr));
404 ESP_LOGE(TAG,
"Receive line break FSR=%s", I2S2CS(fsr));
406 ESP_LOGE(TAG,
"Receive frame error FSR=%s", I2S2CS(fsr));
408 ESP_LOGE(TAG,
"Receive parity error FSR=%s", I2S2CS(fsr));
410 if ((available == 0) && (fsr &
FSR_RFDAT)) {
416 if (available == 0) {
417 ESP_LOGV(TAG,
"rx FIFO is full FSR=%s", I2S2CS(fsr));
421 ESP_LOGVV(TAG,
"rx FIFO contain %d bytes - FSR status=%s", available, I2S2CS(fsr));
432 ESP_LOGE(TAG,
"R/W of register failed expected 0x3F received 0x%02X", val);
438 ESP_LOGE(TAG,
"R/W of register failed expected 0x00 received 0x%02X", val);
445 auto available = this->receive_buffer_.count();
447 xfer_fifo_to_buffer_();
448 return this->receive_buffer_.peek(*buffer);
452 size_t available = this->receive_buffer_.count();
454 available = xfer_fifo_to_buffer_();
460 auto available = this->receive_buffer_.count();
461 if (length > available) {
462 ESP_LOGW(TAG,
"read_array: buffer underflow requested %d bytes only %d bytes available...", length, available);
467 for (
size_t i = 0; i <
length; i++) {
468 this->receive_buffer_.pop(buffer[i]);
470 ESP_LOGVV(TAG,
"read_array(ch=%d buffer[0]=%02X, length=%d): status %s", this->channel_, *buffer, length,
471 status ?
"OK" :
"ERROR");
477 ESP_LOGE(TAG,
"Write_array: invalid call - requested %d bytes but max size %d ...", length,
XFER_MAX_SIZE);
480 this->reg(0).write_fifo(const_cast<uint8_t *>(buffer), length);
484 uint32_t
const start_time =
millis();
485 while (this->tx_fifo_is_not_empty_()) {
486 if (
millis() - start_time > 200) {
487 ESP_LOGW(TAG,
"WARNING flush timeout - still %d bytes not sent after 200 ms...", this->tx_in_fifo_());
497 while ((to_transfer = this->rx_in_fifo_()) && (free = this->receive_buffer_.free())) {
501 if (to_transfer > free)
504 uint8_t data[to_transfer];
505 this->reg(0).read_fifo(data, to_transfer);
506 for (
size_t i = 0; i < to_transfer; i++)
507 this->receive_buffer_.push(data[i]);
516 #ifdef TEST_COMPONENT 526 Increment() : i_(0) {}
530 uint8_t operator()() {
return i_++; }
539 char hex_buffer[100];
540 hex_buffer[(3 * 32) + 1] = 0;
541 for (
size_t i = 0; i < buffer.size(); i++) {
542 snprintf(&hex_buffer[3 * (i % 32)],
sizeof(hex_buffer),
"%02X ", buffer[i]);
544 ESP_LOGI(TAG,
" %s", hex_buffer);
546 if (buffer.size() % 32) {
548 hex_buffer[3 * (buffer.size() % 32) + 1] = 0;
549 ESP_LOGI(TAG,
" %s", hex_buffer);
555 auto start_exec =
micros();
557 generate(output_buffer.begin(), output_buffer.end(), Increment());
564 ESP_LOGV(TAG,
"%s => sent %d bytes - exec time %d µs ...", message,
RING_BUFFER_SIZE,
micros() - start_exec);
569 auto start_exec =
micros();
575 uint32_t
const start_time =
millis();
579 this->xfer_fifo_to_buffer_();
580 if (
millis() - start_time > 1500) {
581 ESP_LOGE(TAG,
"uart_receive_test_() timeout: only %d bytes received...", this->available());
590 uint8_t peek_value = 0;
591 this->peek_byte(&peek_value);
592 if (peek_value != 0) {
593 ESP_LOGE(TAG,
"Peek first byte value error...");
599 ESP_LOGE(TAG,
"Read buffer contains error...b=%x i=%x", buffer[i], i % XFER_MAX_SIZE);
606 ESP_LOGV(TAG,
"%s => received %d bytes status %s - exec time %d µs ...", message, received, status ?
"OK" :
"ERROR",
constexpr uint8_t LCR_PAR_ODD
Parity odd.
const uint32_t COMPONENT_STATE_LOOP
constexpr uint8_t WKREG_SCR
Serial Control Register - c0/c1 0100.
int available() override
Returns the number of bytes in the receive buffer.
constexpr uint8_t FCR_TFRST
Transmitter FIFO reset.
const char * p2s(uart::UARTParityOptions parity)
Converts the parity enum value to a C string.
constexpr uint8_t WKREG_BRL
Baud rate configuration register: low byte - c0/c1 0101.
size_t tx_in_fifo_()
Returns the number of bytes in the transmit fifo.
void uart_send_test_(char *message)
Test the write_array() method.
void set_baudrate_()
set the baud rate
void loop() override
override the Component loop()
void write_pin_val_(uint8_t pin, bool value)
Helper method to write the value of a pin.
size_t rx_in_fifo_()
Returns the number of bytes in the receive fifo.
constexpr uint8_t FSR_RFDAT
Receiver FIFO count (0: empty, 1: not empty)
virtual void dump_channel()
dump channel information
constexpr uint8_t WKREG_BRH
Baud rate configuration register: high byte - c0/c1 0100.
void set_line_param_()
set the line parameters
constexpr uint8_t FSR_TFFULL
Transmitter FIFO full (0: not full, 1: full)
WeikaiRegister & operator &=(uint8_t value)
overloads the compound &= operator.
uint32_t elapsed_ms(uint32_t &last_time)
measure the time elapsed between two calls
const char * reg_to_str(int reg, bool page1)
constexpr uint8_t LCR_PAEN
Parity enable (0: no check, 1: check)
void reset_fifo_()
reset the weikai internal FIFO
uint32_t IRAM_ATTR HOT micros()
bool peek_byte(uint8_t *buffer) override
Reads the first byte in FIFO without removing it.
constexpr size_t XFER_MAX_SIZE
XFER_MAX_SIZE defines the maximum number of bytes allowed during one transfer.
constexpr uint8_t WKREG_FCR
FIFO Control Register - c0/c1 0110.
uint32_t IRAM_ATTR HOT millis()
constexpr uint8_t WKREG_FSR
FIFO Status Register - c0/c1 1011.
void set_pin_direction_(uint8_t pin, gpio::Flags flags)
Helper method to set the pin mode of a pin.
constexpr uint8_t SCR_TXEN
transmission control (0: enable, 1: disable)
constexpr uint8_t FSR_RFLB
Receiver FIFO Line Break (0: no LB, 1: LB)
constexpr uint8_t FSR_TFDAT
Transmitter FIFO count (0: empty, 1: not empty)
std::string i2s(uint8_t val)
convert an int to binary representation as C++ std::string
constexpr uint8_t FSR_RFPE
Receiver Parity Error (0: no PE, 1: PE)
constexpr uint8_t LCR_STPL
Stop length (0: 1 bit, 1: 2 bits)
void write_array(const uint8_t *buffer, size_t length) override
Writes a specified number of bytes to a serial port.
bool uart_receive_test_(char *message)
Test the read_array() method.
void flush() override
Flush the output fifo.
std::string dump_summary() const override
constexpr uint8_t WKREG_BRD
Baud rate configuration register decimal part - c0/c1 0110.
bool read_array(uint8_t *buffer, size_t length) override
Reads a specified number of bytes from a serial port.
constexpr uint8_t LCR_PAR_EVEN
Parity even.
constexpr uint8_t FCR_RFEN
Receiver FIFO enable.
constexpr uint8_t FSR_RFOE
Receiver FIFO Overflow Error (0: no OE, 1: OE)
WeikaiRegister & operator|=(uint8_t value)
overloads the compound |= operator.
WeiKai component family - classes declaration.
constexpr uint8_t WKREG_GPDAT
Global GPIO data register - 11 0001.
const uint32_t COMPONENT_STATE_MASK
size_t xfer_fifo_to_buffer_()
transfer bytes from the weikai internal FIFO to the buffer (if any)
constexpr uint8_t FCR_TFEN
Transmitter FIFO enable.
void print_buffer(const uint8_t *data, size_t length)
Display a buffer in hexadecimal format (32 hex values / line) for debug.
constexpr uint8_t WKREG_RFCNT
Receiver FIFO count - c0/c1 1010.
constexpr size_t RING_BUFFER_SIZE
size of the ring buffer set to size of the FIFO
virtual void setup_channel()
Setup the channel.
WeikaiRegister objects acts as proxies to access remote register independently of the bus type...
std::string to_string(int value)
void IRAM_ATTR HOT yield()
virtual bool check_channel_down()
check if channel is alive
constexpr uint8_t SCR_RXEN
receiving control (0: enable, 1: disable)
constexpr uint8_t WKREG_TFCNT
Transmitter FIFO Count - c0/c1 1001.
WeikaiRegister & operator=(uint8_t value)
overloads the = operator.
Implementation of SPI Controller mode.
constexpr size_t FIFO_SIZE
size of the internal WeiKai FIFO
constexpr uint8_t FCR_RFRST
Receiver FIFO reset.
constexpr uint8_t WKREG_SPAGE
Global Page register c0/c1 0011.
bool read_pin_val_(uint8_t pin)
Helper method to read the value of a pin.
bool tx_fifo_is_not_empty_()
test if transmit buffer is not empty in the status register (optimization)
constexpr uint8_t WKREG_GPDIR
Global GPIO direction register - 10 0001.
constexpr uint8_t FSR_RFFE
Receiver FIFO Frame Error (0: no FE, 1: FE)
void IRAM_ATTR HOT delay(uint32_t ms)
constexpr uint8_t WKREG_LCR
Line Configuration Register - c0/c1 0101.