mirror of
https://github.com/esphome/esphome.git
synced 2024-12-02 11:44:13 +01:00
162 lines
5.1 KiB
C++
162 lines
5.1 KiB
C++
#ifdef ARDUINO_ARCH_ESP32
|
||
#include "uart.h"
|
||
#include "esphome/core/log.h"
|
||
#include "esphome/core/helpers.h"
|
||
#include "esphome/core/application.h"
|
||
#include "esphome/core/defines.h"
|
||
|
||
namespace esphome {
|
||
namespace uart {
|
||
static const char *const TAG = "uart_esp32";
|
||
uint8_t next_uart_num = 1;
|
||
|
||
static const uint32_t UART_PARITY_EVEN = 0 << 0;
|
||
static const uint32_t UART_PARITY_ODD = 1 << 0;
|
||
static const uint32_t UART_PARITY_ENABLE = 1 << 1;
|
||
static const uint32_t UART_NB_BIT_5 = 0 << 2;
|
||
static const uint32_t UART_NB_BIT_6 = 1 << 2;
|
||
static const uint32_t UART_NB_BIT_7 = 2 << 2;
|
||
static const uint32_t UART_NB_BIT_8 = 3 << 2;
|
||
static const uint32_t UART_NB_STOP_BIT_1 = 1 << 4;
|
||
static const uint32_t UART_NB_STOP_BIT_2 = 3 << 4;
|
||
static const uint32_t UART_TICK_APB_CLOCK = 1 << 27;
|
||
|
||
uint32_t UARTComponent::get_config() {
|
||
uint32_t config = 0;
|
||
|
||
/*
|
||
* All bits numbers below come from
|
||
* framework-arduinoespressif32/cores/esp32/esp32-hal-uart.h
|
||
* And more specifically conf0 union in uart_dev_t.
|
||
*
|
||
* Below is bit used from conf0 union.
|
||
* <name>:<bits position> <values>
|
||
* parity:0 0:even 1:odd
|
||
* parity_en:1 Set this bit to enable uart parity check.
|
||
* bit_num:2-4 0:5bits 1:6bits 2:7bits 3:8bits
|
||
* stop_bit_num:4-6 stop bit. 1:1bit 2:1.5bits 3:2bits
|
||
* tick_ref_always_on:27 select the clock.1:apb clock:ref_tick
|
||
*/
|
||
|
||
if (this->parity_ == UART_CONFIG_PARITY_EVEN)
|
||
config |= UART_PARITY_EVEN | UART_PARITY_ENABLE;
|
||
else if (this->parity_ == UART_CONFIG_PARITY_ODD)
|
||
config |= UART_PARITY_ODD | UART_PARITY_ENABLE;
|
||
|
||
switch (this->data_bits_) {
|
||
case 5:
|
||
config |= UART_NB_BIT_5;
|
||
break;
|
||
case 6:
|
||
config |= UART_NB_BIT_6;
|
||
break;
|
||
case 7:
|
||
config |= UART_NB_BIT_7;
|
||
break;
|
||
case 8:
|
||
config |= UART_NB_BIT_8;
|
||
break;
|
||
}
|
||
|
||
if (this->stop_bits_ == 1)
|
||
config |= UART_NB_STOP_BIT_1;
|
||
else
|
||
config |= UART_NB_STOP_BIT_2;
|
||
|
||
config |= UART_TICK_APB_CLOCK;
|
||
|
||
return config;
|
||
}
|
||
|
||
void UARTComponent::setup() {
|
||
ESP_LOGCONFIG(TAG, "Setting up UART...");
|
||
// Use Arduino HardwareSerial UARTs if all used pins match the ones
|
||
// preconfigured by the platform. For example if RX disabled but TX pin
|
||
// is 1 we still want to use Serial.
|
||
if (this->tx_pin_.value_or(1) == 1 && this->rx_pin_.value_or(3) == 3) {
|
||
this->hw_serial_ = &Serial;
|
||
} else {
|
||
this->hw_serial_ = new HardwareSerial(next_uart_num++);
|
||
}
|
||
int8_t tx = this->tx_pin_.has_value() ? *this->tx_pin_ : -1;
|
||
int8_t rx = this->rx_pin_.has_value() ? *this->rx_pin_ : -1;
|
||
this->hw_serial_->begin(this->baud_rate_, get_config(), rx, tx, this->invert_);
|
||
this->hw_serial_->setRxBufferSize(this->rx_buffer_size_);
|
||
}
|
||
|
||
void UARTComponent::dump_config() {
|
||
ESP_LOGCONFIG(TAG, "UART Bus:");
|
||
if (this->tx_pin_.has_value()) {
|
||
ESP_LOGCONFIG(TAG, " TX Pin: GPIO%d", *this->tx_pin_);
|
||
}
|
||
if (this->rx_pin_.has_value()) {
|
||
ESP_LOGCONFIG(TAG, " RX Pin: GPIO%d", *this->rx_pin_);
|
||
ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_);
|
||
}
|
||
ESP_LOGCONFIG(TAG, " Baud Rate: %u baud", this->baud_rate_);
|
||
ESP_LOGCONFIG(TAG, " Data Bits: %u", this->data_bits_);
|
||
ESP_LOGCONFIG(TAG, " Parity: %s", parity_to_str(this->parity_));
|
||
ESP_LOGCONFIG(TAG, " Stop bits: %u", this->stop_bits_);
|
||
this->check_logger_conflict_();
|
||
}
|
||
|
||
void UARTComponent::write_byte(uint8_t data) {
|
||
this->hw_serial_->write(data);
|
||
ESP_LOGVV(TAG, " Wrote 0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(data), data);
|
||
}
|
||
void UARTComponent::write_array(const uint8_t *data, size_t len) {
|
||
this->hw_serial_->write(data, len);
|
||
for (size_t i = 0; i < len; i++) {
|
||
ESP_LOGVV(TAG, " Wrote 0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(data[i]), data[i]);
|
||
}
|
||
}
|
||
void UARTComponent::write_str(const char *str) {
|
||
this->hw_serial_->write(str);
|
||
ESP_LOGVV(TAG, " Wrote \"%s\"", str);
|
||
}
|
||
bool UARTComponent::read_byte(uint8_t *data) {
|
||
if (!this->check_read_timeout_())
|
||
return false;
|
||
*data = this->hw_serial_->read();
|
||
ESP_LOGVV(TAG, " Read 0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(*data), *data);
|
||
return true;
|
||
}
|
||
bool UARTComponent::peek_byte(uint8_t *data) {
|
||
if (!this->check_read_timeout_())
|
||
return false;
|
||
*data = this->hw_serial_->peek();
|
||
return true;
|
||
}
|
||
bool UARTComponent::read_array(uint8_t *data, size_t len) {
|
||
if (!this->check_read_timeout_(len))
|
||
return false;
|
||
this->hw_serial_->readBytes(data, len);
|
||
for (size_t i = 0; i < len; i++) {
|
||
ESP_LOGVV(TAG, " Read 0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(data[i]), data[i]);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
bool UARTComponent::check_read_timeout_(size_t len) {
|
||
if (this->available() >= len)
|
||
return true;
|
||
|
||
uint32_t start_time = millis();
|
||
while (this->available() < len) {
|
||
if (millis() - start_time > 1000) {
|
||
ESP_LOGE(TAG, "Reading from UART timed out at byte %u!", this->available());
|
||
return false;
|
||
}
|
||
yield();
|
||
}
|
||
return true;
|
||
}
|
||
int UARTComponent::available() { return this->hw_serial_->available(); }
|
||
void UARTComponent::flush() {
|
||
ESP_LOGVV(TAG, " Flushing...");
|
||
this->hw_serial_->flush();
|
||
}
|
||
|
||
} // namespace uart
|
||
} // namespace esphome
|
||
#endif // ARDUINO_ARCH_ESP32
|