Update devices.yaml and state.json with new device configurations and states

- Refactored friendly names in devices.yaml for consistency and clarity.
- Added new devices and updated existing ones in devices.yaml.
- Populated state.json with detailed state information for various devices, including brightness, power, and link quality.
- Included update information for devices where applicable.
This commit is contained in:
2026-04-03 00:39:43 +02:00
parent 17883d85d9
commit bdbeec27aa
28 changed files with 6459 additions and 89839 deletions

View File

@@ -0,0 +1 @@
CODEOWNERS = ["@clydebarrow"]

View File

@@ -0,0 +1,229 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import core, pins
from esphome.components import display, spi
from esphome.const import (
CONF_BUSY_PIN,
CONF_DC_PIN,
CONF_FULL_UPDATE_EVERY,
CONF_ID,
CONF_LAMBDA,
CONF_MODEL,
CONF_PAGES,
CONF_RESET_DURATION,
CONF_RESET_PIN,
)
DEPENDENCIES = ["spi"]
waveshare_epaper_ns = cg.esphome_ns.namespace("waveshare_epaper")
WaveshareEPaperBase = waveshare_epaper_ns.class_(
"WaveshareEPaperBase", cg.PollingComponent, spi.SPIDevice, display.DisplayBuffer
)
WaveshareEPaper = waveshare_epaper_ns.class_("WaveshareEPaper", WaveshareEPaperBase)
WaveshareEPaperBWR = waveshare_epaper_ns.class_(
"WaveshareEPaperBWR", WaveshareEPaperBase
)
WaveshareEPaperPolled = waveshare_epaper_ns.class_(
"WaveshareEPaperPolled", WaveshareEPaper
)
WaveshareEPaperTypeA = waveshare_epaper_ns.class_(
"WaveshareEPaperTypeA", WaveshareEPaper
)
WaveshareEPaper2P7In = waveshare_epaper_ns.class_(
"WaveshareEPaper2P7In", WaveshareEPaper
)
WaveshareEPaper2P7InB = waveshare_epaper_ns.class_(
"WaveshareEPaper2P7InB", WaveshareEPaperBWR
)
WaveshareEPaper2P7InBV2 = waveshare_epaper_ns.class_(
"WaveshareEPaper2P7InBV2", WaveshareEPaperBWR
)
WaveshareEPaper2P7InV2 = waveshare_epaper_ns.class_(
"WaveshareEPaper2P7InV2", WaveshareEPaper
)
WaveshareEPaper2P9InB = waveshare_epaper_ns.class_(
"WaveshareEPaper2P9InB", WaveshareEPaper
)
WaveshareEPaper2P9InBV3 = waveshare_epaper_ns.class_(
"WaveshareEPaper2P9InBV3", WaveshareEPaper
)
WaveshareEPaper2P9InV2R2 = waveshare_epaper_ns.class_(
"WaveshareEPaper2P9InV2R2", WaveshareEPaper
)
GDEW029T5 = waveshare_epaper_ns.class_("GDEW029T5", WaveshareEPaper)
WaveshareEPaper2P9InDKE = waveshare_epaper_ns.class_(
"WaveshareEPaper2P9InDKE", WaveshareEPaper
)
WaveshareEPaper4P2In = waveshare_epaper_ns.class_(
"WaveshareEPaper4P2In", WaveshareEPaper
)
WaveshareEPaper4P2InBV2 = waveshare_epaper_ns.class_(
"WaveshareEPaper4P2InBV2", WaveshareEPaper
)
WaveshareEPaper5P8In = waveshare_epaper_ns.class_(
"WaveshareEPaper5P8In", WaveshareEPaper
)
WaveshareEPaper5P8InV2 = waveshare_epaper_ns.class_(
"WaveshareEPaper5P8InV2", WaveshareEPaper
)
WaveshareEPaper7P5In = waveshare_epaper_ns.class_(
"WaveshareEPaper7P5In", WaveshareEPaper
)
WaveshareEPaper7P5InBC = waveshare_epaper_ns.class_(
"WaveshareEPaper7P5InBC", WaveshareEPaper
)
WaveshareEPaper7P5InBV2 = waveshare_epaper_ns.class_(
"WaveshareEPaper7P5InBV2", WaveshareEPaper
)
WaveshareEPaper7P5InBV3 = waveshare_epaper_ns.class_(
"WaveshareEPaper7P5InBV3", WaveshareEPaper
)
WaveshareEPaper7P5InV2 = waveshare_epaper_ns.class_(
"WaveshareEPaper7P5InV2", WaveshareEPaper
)
WaveshareEPaper7P5InV2alt = waveshare_epaper_ns.class_(
"WaveshareEPaper7P5InV2alt", WaveshareEPaper
)
WaveshareEPaper7P5InHDB = waveshare_epaper_ns.class_(
"WaveshareEPaper7P5InHDB", WaveshareEPaper
)
WaveshareEPaper2P13InDKE = waveshare_epaper_ns.class_(
"WaveshareEPaper2P13InDKE", WaveshareEPaper
)
WaveshareEPaper2P13InV2 = waveshare_epaper_ns.class_(
"WaveshareEPaper2P13InV2", WaveshareEPaper
)
WaveshareEPaper2P13InV3 = waveshare_epaper_ns.class_(
"WaveshareEPaper2P13InV3", WaveshareEPaper
)
WaveshareEPaper13P3InK = waveshare_epaper_ns.class_(
"WaveshareEPaper13P3InK", WaveshareEPaper
)
GDEW0154M09 = waveshare_epaper_ns.class_("GDEW0154M09", WaveshareEPaper)
WaveshareEPaper7In5BV2 = waveshare_epaper_ns.class_(
"WaveshareEPaper7In5BV2", WaveshareEPaperPolled
)
WaveshareEPaperTypeAModel = waveshare_epaper_ns.enum("WaveshareEPaperTypeAModel")
WaveshareEPaperTypeBModel = waveshare_epaper_ns.enum("WaveshareEPaperTypeBModel")
MODELS = {
"1.54in": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_1_54_IN),
"1.54inv2": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_1_54_IN_V2),
"2.13in": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_13_IN),
"2.13inv2": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_13_IN_V2),
"2.13in-ttgo": ("a", WaveshareEPaperTypeAModel.TTGO_EPAPER_2_13_IN),
"2.13in-ttgo-b1": ("a", WaveshareEPaperTypeAModel.TTGO_EPAPER_2_13_IN_B1),
"2.13in-ttgo-b73": ("a", WaveshareEPaperTypeAModel.TTGO_EPAPER_2_13_IN_B73),
"2.13in-ttgo-b74": ("a", WaveshareEPaperTypeAModel.TTGO_EPAPER_2_13_IN_B74),
"2.90in": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_9_IN),
"2.90inv2": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_9_IN_V2),
"gdew029t5": ("c", GDEW029T5),
"2.70in": ("b", WaveshareEPaper2P7In),
"2.70in-b": ("b", WaveshareEPaper2P7InB),
"2.70in-bv2": ("b", WaveshareEPaper2P7InBV2),
"2.70inv2": ("b", WaveshareEPaper2P7InV2),
"2.90in-b": ("b", WaveshareEPaper2P9InB),
"2.90in-bv3": ("b", WaveshareEPaper2P9InBV3),
"2.90inv2-r2": ("c", WaveshareEPaper2P9InV2R2),
"2.90in-dke": ("c", WaveshareEPaper2P9InDKE),
"4.20in": ("b", WaveshareEPaper4P2In),
"4.20in-bv2": ("b", WaveshareEPaper4P2InBV2),
"5.83in": ("b", WaveshareEPaper5P8In),
"5.83inv2": ("b", WaveshareEPaper5P8InV2),
"7.50in": ("b", WaveshareEPaper7P5In),
"7.50in-bv2": ("b", WaveshareEPaper7P5InBV2),
"7.50in-bv2-rb": ("b", WaveshareEPaper7In5BV2),
"7.50in-bv3": ("b", WaveshareEPaper7P5InBV3),
"7.50in-bc": ("b", WaveshareEPaper7P5InBC),
"7.50inv2": ("b", WaveshareEPaper7P5InV2),
"7.50inv2alt": ("b", WaveshareEPaper7P5InV2alt),
"7.50in-hd-b": ("b", WaveshareEPaper7P5InHDB),
"2.13in-ttgo-dke": ("c", WaveshareEPaper2P13InDKE),
"2.13inv3": ("c", WaveshareEPaper2P13InV3),
"1.54in-m5coreink-m09": ("c", GDEW0154M09),
"13.3in-k": ("b", WaveshareEPaper13P3InK),
}
RESET_PIN_REQUIRED_MODELS = ("2.13inv2", "2.13in-ttgo-b74")
def validate_full_update_every_only_types_ac(value):
if CONF_FULL_UPDATE_EVERY not in value:
return value
if MODELS[value[CONF_MODEL]][0] == "b":
full_models = []
for key, val in sorted(MODELS.items()):
if val[0] != "b":
full_models.append(key)
raise cv.Invalid(
"The 'full_update_every' option is only available for models "
+ ", ".join(full_models)
)
return value
def validate_reset_pin_required(config):
if config[CONF_MODEL] in RESET_PIN_REQUIRED_MODELS and CONF_RESET_PIN not in config:
raise cv.Invalid(
f"'{CONF_RESET_PIN}' is required for model {config[CONF_MODEL]}"
)
return config
CONFIG_SCHEMA = cv.All(
display.FULL_DISPLAY_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(WaveshareEPaperBase),
cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema,
cv.Required(CONF_MODEL): cv.one_of(*MODELS, lower=True),
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
cv.Optional(CONF_BUSY_PIN): pins.gpio_input_pin_schema,
cv.Optional(CONF_FULL_UPDATE_EVERY): cv.int_range(min=1, max=4294967295),
cv.Optional(CONF_RESET_DURATION): cv.All(
cv.positive_time_period_milliseconds,
cv.Range(max=core.TimePeriod(milliseconds=500)),
),
}
)
.extend(cv.polling_component_schema("1s"))
.extend(spi.spi_device_schema()),
validate_full_update_every_only_types_ac,
validate_reset_pin_required,
cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA),
)
async def to_code(config):
model_type, model = MODELS[config[CONF_MODEL]]
if model_type == "a":
rhs = WaveshareEPaperTypeA.new(model)
var = cg.Pvariable(config[CONF_ID], rhs, WaveshareEPaperTypeA)
elif model_type in ("b", "c"):
rhs = model.new()
var = cg.Pvariable(config[CONF_ID], rhs, model)
else:
raise NotImplementedError()
await display.register_display(var, config)
await spi.register_spi_device(var, config)
dc = await cg.gpio_pin_expression(config[CONF_DC_PIN])
cg.add(var.set_dc_pin(dc))
if CONF_LAMBDA in config:
lambda_ = await cg.process_lambda(
config[CONF_LAMBDA], [(display.DisplayRef, "it")], return_type=cg.void
)
cg.add(var.set_writer(lambda_))
if CONF_RESET_PIN in config:
reset = await cg.gpio_pin_expression(config[CONF_RESET_PIN])
cg.add(var.set_reset_pin(reset))
if CONF_BUSY_PIN in config:
reset = await cg.gpio_pin_expression(config[CONF_BUSY_PIN])
cg.add(var.set_busy_pin(reset))
if CONF_FULL_UPDATE_EVERY in config:
cg.add(var.set_full_update_every(config[CONF_FULL_UPDATE_EVERY]))
if CONF_RESET_DURATION in config:
cg.add(var.set_reset_duration(config[CONF_RESET_DURATION]))

View File

@@ -0,0 +1,186 @@
#include "waveshare_epaper.h"
#include "esphome/core/log.h"
#include "esphome/core/application.h"
namespace esphome {
namespace waveshare_epaper {
static const char *const TAG = "waveshare_2.13v3";
static const uint8_t PARTIAL_LUT[] = {
0x32, // cmd
0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
};
static const uint8_t FULL_LUT[] = {
0x32, // CMD
0x80, 0x4A, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x4A, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x80, 0x4A, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x4A, 0x80, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0x0, 0x0, 0xF, 0x0, 0x0, 0x2, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
};
static const uint8_t SW_RESET = 0x12;
static const uint8_t ACTIVATE = 0x20;
static const uint8_t WRITE_BUFFER = 0x24;
static const uint8_t WRITE_BASE = 0x26;
static const uint8_t DRV_OUT_CTL[] = {0x01, 0x27, 0x01, 0x00}; // driver output control
static const uint8_t GATEV[] = {0x03, 0x17};
static const uint8_t SRCV[] = {0x04, 0x41, 0x0C, 0x32};
static const uint8_t SLEEP[] = {0x10, 0x01};
static const uint8_t DATA_ENTRY[] = {0x11, 0x03}; // data entry mode
static const uint8_t TEMP_SENS[] = {0x18, 0x80}; // Temp sensor
static const uint8_t DISPLAY_UPDATE[] = {0x21, 0x00, 0x80}; // Display update control
static const uint8_t UPSEQ[] = {0x22, 0xC0};
static const uint8_t ON_FULL[] = {0x22, 0xC7};
static const uint8_t ON_PARTIAL[] = {0x22, 0x0F};
static const uint8_t VCOM[] = {0x2C, 0x36};
static const uint8_t CMD5[] = {0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00};
static const uint8_t BORDER_PART[] = {0x3C, 0x80}; // border waveform
static const uint8_t BORDER_FULL[] = {0x3C, 0x05}; // border waveform
static const uint8_t CMD1[] = {0x3F, 0x22};
static const uint8_t RAM_X_START[] = {0x44, 0x00, 121 / 8}; // set ram_x_address_start_end
static const uint8_t RAM_Y_START[] = {0x45, 0x00, 0x00, 250 - 1, 0}; // set ram_y_address_start_end
static const uint8_t RAM_X_POS[] = {0x4E, 0x00}; // set ram_x_address_counter
// static const uint8_t RAM_Y_POS[] = {0x4F, 0x00, 0x00}; // set ram_y_address_counter
#define SEND(x) this->cmd_data(x, sizeof(x))
void WaveshareEPaper2P13InV3::write_lut_(const uint8_t *lut) {
this->wait_until_idle_();
this->cmd_data(lut, sizeof(PARTIAL_LUT));
SEND(CMD1);
SEND(GATEV);
SEND(SRCV);
SEND(VCOM);
}
// write the buffer starting on line top, up to line bottom.
void WaveshareEPaper2P13InV3::write_buffer_(uint8_t cmd, int top, int bottom) {
this->wait_until_idle_();
this->set_window_(top, bottom);
this->command(cmd);
this->start_data_();
auto width_bytes = this->get_width_internal() / 8;
this->write_array(this->buffer_ + top * width_bytes, (bottom - top) * width_bytes);
this->end_data_();
}
void WaveshareEPaper2P13InV3::send_reset_() {
if (this->reset_pin_ != nullptr) {
this->reset_pin_->digital_write(false);
delay(2);
this->reset_pin_->digital_write(true);
}
}
void WaveshareEPaper2P13InV3::setup() {
setup_pins_();
delay(20);
this->send_reset_();
// as a one-off delay this is not worth working around.
delay(100); // NOLINT
this->wait_until_idle_();
this->command(SW_RESET);
this->wait_until_idle_();
SEND(DRV_OUT_CTL);
SEND(DATA_ENTRY);
SEND(CMD5);
this->set_window_(0, this->get_height_internal());
SEND(BORDER_FULL);
SEND(DISPLAY_UPDATE);
SEND(TEMP_SENS);
this->wait_until_idle_();
this->write_lut_(FULL_LUT);
}
// t and b are y positions, i.e. line numbers.
void WaveshareEPaper2P13InV3::set_window_(int t, int b) {
uint8_t buffer[3];
SEND(RAM_X_START);
SEND(RAM_Y_START);
SEND(RAM_X_POS);
buffer[0] = 0x4F;
buffer[1] = (uint8_t) t;
buffer[2] = (uint8_t) (t >> 8);
SEND(buffer);
}
// must implement, but we override setup to have more control
void WaveshareEPaper2P13InV3::initialize() {}
void WaveshareEPaper2P13InV3::partial_update_() {
this->send_reset_();
this->set_timeout(100, [this] {
this->write_lut_(PARTIAL_LUT);
SEND(BORDER_PART);
SEND(UPSEQ);
this->command(ACTIVATE);
this->set_timeout(100, [this] {
this->wait_until_idle_();
this->write_buffer_(WRITE_BUFFER, 0, this->get_height_internal());
SEND(ON_PARTIAL);
this->command(ACTIVATE); // Activate Display Update Sequence
this->is_busy_ = false;
});
});
}
void WaveshareEPaper2P13InV3::full_update_() {
ESP_LOGI(TAG, "Performing full e-paper update.");
this->write_lut_(FULL_LUT);
this->write_buffer_(WRITE_BUFFER, 0, this->get_height_internal());
this->write_buffer_(WRITE_BASE, 0, this->get_height_internal());
SEND(ON_FULL);
this->command(ACTIVATE); // don't wait here
this->is_busy_ = false;
}
void WaveshareEPaper2P13InV3::display() {
if (this->is_busy_ || (this->busy_pin_ != nullptr && this->busy_pin_->digital_read()))
return;
this->is_busy_ = true;
const bool partial = this->at_update_ != 0;
this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
if (partial) {
this->partial_update_();
} else {
this->full_update_();
}
}
int WaveshareEPaper2P13InV3::get_width_internal() { return 128; }
int WaveshareEPaper2P13InV3::get_height_internal() { return 250; }
uint32_t WaveshareEPaper2P13InV3::idle_timeout_() { return 5000; }
void WaveshareEPaper2P13InV3::dump_config() {
LOG_DISPLAY("", "Waveshare E-Paper", this);
ESP_LOGCONFIG(TAG, " Model: 2.13inV3");
LOG_PIN(" CS Pin: ", this->cs_);
LOG_PIN(" Reset Pin: ", this->reset_pin_);
LOG_PIN(" DC Pin: ", this->dc_pin_);
LOG_PIN(" Busy Pin: ", this->busy_pin_);
LOG_UPDATE_INTERVAL(this);
}
void WaveshareEPaper2P13InV3::set_full_update_every(uint32_t full_update_every) {
this->full_update_every_ = full_update_every;
}
} // namespace waveshare_epaper
} // namespace esphome

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,864 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/spi/spi.h"
#include "esphome/components/display/display_buffer.h"
namespace esphome {
namespace waveshare_epaper {
class WaveshareEPaper : public display::DisplayBuffer,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW,
spi::CLOCK_PHASE_LEADING, spi::DATA_RATE_2MHZ> {
public:
void set_dc_pin(GPIOPin *dc_pin) { dc_pin_ = dc_pin; }
float get_setup_priority() const override;
void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; }
void set_busy_pin(GPIOPin *busy) { this->busy_pin_ = busy; }
void set_reset_duration(uint32_t reset_duration) { this->reset_duration_ = reset_duration; }
void command(uint8_t value);
void data(uint8_t value);
void cmd_data(const uint8_t *data, size_t length);
virtual void display() = 0;
virtual void initialize() = 0;
virtual void deep_sleep() = 0;
void update() override;
void setup() override {
this->setup_pins_();
this->initialize();
}
void on_safe_shutdown() override;
display::DisplayType get_display_type() override;
void fill(Color color) override;
protected:
bool wait_until_idle_();
void setup_pins_();
void reset_() {
if (this->reset_pin_ != nullptr) {
this->reset_pin_->digital_write(false);
delay(reset_duration_); // NOLINT
this->reset_pin_->digital_write(true);
delay(20);
}
}
virtual int get_width_controller() { return this->get_width_internal(); };
uint32_t get_buffer_length_();
uint32_t reset_duration_{200};
// Return the list of colors supported by the device
virtual std::vector<Color> get_supported_colors() { return {display::COLOR_ON}; }
void draw_absolute_pixel_internal(int x, int y, Color color) override;
void start_command_();
void end_command_();
void start_data_();
void end_data_();
GPIOPin *reset_pin_{nullptr};
GPIOPin *dc_pin_;
GPIOPin *busy_pin_{nullptr};
virtual uint32_t idle_timeout_() { return 1000u; } // NOLINT(readability-identifier-naming)
};
class WaveshareEPaperBWR : public WaveshareEPaper {
public:
std::vector<Color> get_supported_colors() override { return {display::COLOR_ON, Color(255, 0, 0, 0)}; }
};
enum WaveshareEPaperTypeAModel {
WAVESHARE_EPAPER_1_54_IN = 0,
WAVESHARE_EPAPER_1_54_IN_V2,
WAVESHARE_EPAPER_2_13_IN,
WAVESHARE_EPAPER_2_13_IN_V2,
WAVESHARE_EPAPER_2_9_IN,
WAVESHARE_EPAPER_2_9_IN_V2,
TTGO_EPAPER_2_13_IN,
TTGO_EPAPER_2_13_IN_B73,
TTGO_EPAPER_2_13_IN_B1,
TTGO_EPAPER_2_13_IN_B74,
};
class WaveshareEPaperTypeA : public WaveshareEPaper {
public:
WaveshareEPaperTypeA(WaveshareEPaperTypeAModel model);
void initialize() override;
void dump_config() override;
void display() override;
void deep_sleep() override {
switch (this->model_) {
// Models with specific deep sleep command and data
case WAVESHARE_EPAPER_1_54_IN:
case WAVESHARE_EPAPER_1_54_IN_V2:
case WAVESHARE_EPAPER_2_9_IN_V2:
case WAVESHARE_EPAPER_2_13_IN_V2:
// COMMAND DEEP SLEEP MODE
this->command(0x10);
this->data(0x01);
break;
// Other models default to simple deep sleep command
default:
// COMMAND DEEP SLEEP
this->command(0x10);
break;
}
if (this->model_ != WAVESHARE_EPAPER_2_13_IN_V2) {
// From panel specification:
// "After this command initiated, the chip will enter Deep Sleep Mode, BUSY pad will keep output high."
this->wait_until_idle_();
}
}
void set_full_update_every(uint32_t full_update_every);
protected:
void write_lut_(const uint8_t *lut, uint8_t size);
void init_display_();
int get_width_internal() override;
int get_height_internal() override;
int get_width_controller() override;
uint32_t full_update_every_{30};
uint32_t at_update_{0};
WaveshareEPaperTypeAModel model_;
uint32_t idle_timeout_() override;
bool deep_sleep_between_updates_{false};
};
enum WaveshareEPaperTypeBModel {
WAVESHARE_EPAPER_2_7_IN = 0,
WAVESHARE_EPAPER_2_7_IN_B,
WAVESHARE_EPAPER_2_7_IN_B_V2,
WAVESHARE_EPAPER_4_2_IN,
WAVESHARE_EPAPER_4_2_IN_B_V2,
WAVESHARE_EPAPER_7_5_IN,
WAVESHARE_EPAPER_7_5_INV2,
WAVESHARE_EPAPER_7_5_IN_B_V2,
WAVESHARE_EPAPER_13_3_IN_K,
};
class WaveshareEPaper2P7In : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND DEEP SLEEP
this->command(0x07);
this->data(0xA5); // check byte
}
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class WaveshareEPaper2P7InB : public WaveshareEPaperBWR {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND VCOM_AND_DATA_INTERVAL_SETTING
this->command(0x50);
// COMMAND POWER OFF
this->command(0x02);
this->wait_until_idle_();
// COMMAND DEEP SLEEP
this->command(0x07); // deep sleep
this->data(0xA5); // check byte
}
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class WaveshareEPaper2P7InBV2 : public WaveshareEPaperBWR {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND DEEP SLEEP
this->command(0x10);
this->data(0x01);
}
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class GDEW029T5 : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND DEEP SLEEP
this->command(0x07);
this->data(0xA5); // check byte
}
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class WaveshareEPaper2P7InV2 : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override { ; }
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class GDEW0154M09 : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override;
protected:
int get_width_internal() override;
int get_height_internal() override;
private:
static const uint8_t CMD_DTM1_DATA_START_TRANS = 0x10;
static const uint8_t CMD_DTM2_DATA_START_TRANS2 = 0x13;
static const uint8_t CMD_DISPLAY_REFRESH = 0x12;
static const uint8_t CMD_AUTO_SEQ = 0x17;
static const uint8_t DATA_AUTO_PON_DSR_POF_DSLP = 0xA7;
static const uint8_t CMD_PSR_PANEL_SETTING = 0x00;
static const uint8_t CMD_UNDOCUMENTED_0x4D = 0x4D; // NOLINT
static const uint8_t CMD_UNDOCUMENTED_0xAA = 0xaa; // NOLINT
static const uint8_t CMD_UNDOCUMENTED_0xE9 = 0xe9; // NOLINT
static const uint8_t CMD_UNDOCUMENTED_0xB6 = 0xb6; // NOLINT
static const uint8_t CMD_UNDOCUMENTED_0xF3 = 0xf3; // NOLINT
static const uint8_t CMD_TRES_RESOLUTION_SETTING = 0x61;
static const uint8_t CMD_TCON_TCONSETTING = 0x60;
static const uint8_t CMD_CDI_VCOM_DATA_INTERVAL = 0x50;
static const uint8_t CMD_POF_POWER_OFF = 0x02;
static const uint8_t CMD_DSLP_DEEP_SLEEP = 0x07;
static const uint8_t DATA_DSLP_DEEP_SLEEP = 0xA5;
static const uint8_t CMD_PWS_POWER_SAVING = 0xe3;
static const uint8_t CMD_PON_POWER_ON = 0x04;
static const uint8_t CMD_PTL_PARTIAL_WINDOW = 0x90;
uint8_t *lastbuff_ = nullptr;
void reset_();
void clear_();
void write_init_list_(const uint8_t *list);
void init_internal_();
};
class WaveshareEPaper2P9InB : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND DEEP SLEEP
this->command(0x07);
this->data(0xA5); // check byte
}
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class WaveshareEPaper2P9InBV3 : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND DEEP SLEEP
this->command(0x07);
this->data(0xA5); // check byte
}
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class WaveshareEPaper2P9InV2R2 : public WaveshareEPaper {
public:
WaveshareEPaper2P9InV2R2();
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override;
void set_full_update_every(uint32_t full_update_every);
protected:
void write_lut_(const uint8_t *lut, uint8_t size);
int get_width_internal() override;
int get_height_internal() override;
int get_width_controller() override;
uint32_t full_update_every_{30};
uint32_t at_update_{0};
private:
void reset_();
};
class WaveshareEPaper2P9InDKE : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND DEEP SLEEP
this->command(0x10);
this->data(0x01);
}
void set_full_update_every(uint32_t full_update_every);
protected:
uint32_t full_update_every_{30};
uint32_t at_update_{0};
int get_width_internal() override;
int get_height_internal() override;
};
class WaveshareEPaper4P2In : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND VCOM AND DATA INTERVAL SETTING
this->command(0x50);
this->data(0x17); // border floating
// COMMAND VCM DC SETTING
this->command(0x82);
// COMMAND PANEL SETTING
this->command(0x00);
delay(100); // NOLINT
// COMMAND POWER SETTING
this->command(0x01);
this->data(0x00);
this->data(0x00);
this->data(0x00);
this->data(0x00);
this->data(0x00);
delay(100); // NOLINT
// COMMAND POWER OFF
this->command(0x02);
this->wait_until_idle_();
// COMMAND DEEP SLEEP
this->command(0x07);
this->data(0xA5); // check byte
}
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class WaveshareEPaper4P2InBV2 : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND VCOM AND DATA INTERVAL SETTING
this->command(0x50);
this->data(0xF7); // border floating
// COMMAND POWER OFF
this->command(0x02);
this->wait_until_idle_();
// COMMAND DEEP SLEEP
this->command(0x07);
this->data(0xA5); // check code
}
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class WaveshareEPaper5P8In : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND POWER OFF
this->command(0x02);
this->wait_until_idle_();
// COMMAND DEEP SLEEP
this->command(0x07);
this->data(0xA5); // check byte
}
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class WaveshareEPaper5P8InV2 : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND VCOM AND DATA INTERVAL SETTING
this->command(0x50);
this->data(0x17); // border floating
// COMMAND VCM DC SETTING
this->command(0x82);
// COMMAND PANEL SETTING
this->command(0x00);
delay(100); // NOLINT
// COMMAND POWER SETTING
this->command(0x01);
this->data(0x00);
this->data(0x00);
this->data(0x00);
this->data(0x00);
this->data(0x00);
delay(100); // NOLINT
// COMMAND POWER OFF
this->command(0x02);
this->wait_until_idle_();
// COMMAND DEEP SLEEP
this->command(0x07);
this->data(0xA5); // check byte
}
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class WaveshareEPaper7P5In : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND POWER OFF
this->command(0x02);
this->wait_until_idle_();
// COMMAND DEEP SLEEP
this->command(0x07);
this->data(0xA5); // check byte
}
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class WaveshareEPaper7P5InBV2 : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND POWER OFF
this->command(0x02);
this->wait_until_idle_();
// COMMAND DEEP SLEEP
this->command(0x07); // deep sleep
this->data(0xA5); // check byte
}
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class WaveshareEPaper7P5InBV3 : public WaveshareEPaper {
public:
bool wait_until_idle_();
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
this->command(0x02); // Power off
this->wait_until_idle_();
this->command(0x07); // Deep sleep
this->data(0xA5);
}
void clear_screen();
protected:
int get_width_internal() override;
int get_height_internal() override;
void reset_() {
if (this->reset_pin_ != nullptr) {
this->reset_pin_->digital_write(true);
delay(200); // NOLINT
this->reset_pin_->digital_write(false);
delay(5);
this->reset_pin_->digital_write(true);
delay(200); // NOLINT
}
};
void init_display_();
};
class WaveshareEPaper7P5InBC : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND POWER OFF
this->command(0x02);
this->wait_until_idle_();
// COMMAND DEEP SLEEP
this->command(0x07);
this->data(0xA5); // check byte
}
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class WaveshareEPaper7P5InV2 : public WaveshareEPaper {
public:
bool wait_until_idle_();
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND POWER OFF
this->command(0x02);
this->wait_until_idle_();
// COMMAND DEEP SLEEP
this->command(0x07);
this->data(0xA5); // check byte
}
protected:
int get_width_internal() override;
int get_height_internal() override;
uint32_t idle_timeout_() override;
};
class WaveshareEPaper7P5InV2alt : public WaveshareEPaper7P5InV2 {
public:
bool wait_until_idle_();
void initialize() override;
void dump_config() override;
protected:
void reset_() {
if (this->reset_pin_ != nullptr) {
this->reset_pin_->digital_write(true);
delay(200); // NOLINT
this->reset_pin_->digital_write(false);
delay(2);
this->reset_pin_->digital_write(true);
delay(20);
}
};
};
class WaveshareEPaper7P5InHDB : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// deep sleep
this->command(0x10);
this->data(0x01);
}
protected:
int get_width_internal() override;
int get_height_internal() override;
};
class WaveshareEPaper2P13InDKE : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND POWER DOWN
this->command(0x10);
this->data(0x01);
// cannot wait until idle here, the device no longer responds
}
void set_full_update_every(uint32_t full_update_every);
protected:
int get_width_internal() override;
int get_height_internal() override;
uint32_t idle_timeout_() override;
uint32_t full_update_every_{30};
uint32_t at_update_{0};
};
class WaveshareEPaper2P13InV3 : public WaveshareEPaper {
public:
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND POWER DOWN
this->command(0x10);
this->data(0x01);
// cannot wait until idle here, the device no longer responds
}
void set_full_update_every(uint32_t full_update_every);
void setup() override;
void initialize() override;
protected:
int get_width_internal() override;
int get_height_internal() override;
uint32_t idle_timeout_() override;
void write_buffer_(uint8_t cmd, int top, int bottom);
void set_window_(int t, int b);
void send_reset_();
void partial_update_();
void full_update_();
uint32_t full_update_every_{30};
uint32_t at_update_{0};
bool is_busy_{false};
void write_lut_(const uint8_t *lut);
};
class WaveshareEPaper13P3InK : public WaveshareEPaper {
public:
void initialize() override;
void display() override;
void dump_config() override;
void deep_sleep() override {
// COMMAND DEEP SLEEP
this->command(0x10);
this->data(0x01);
}
protected:
int get_width_internal() override;
int get_height_internal() override;
uint32_t idle_timeout_() override;
};
// Generic Waveshare e-paper component that
// avoids using any blocking wait to be able to support
// big screens that are slow to update
class WaveshareEPaperPolled : public WaveshareEPaper {
// Will request a display refresh
void update() override;
// Will move the state machine one state at a time
// to refresh the display when requested by display()
void loop() override;
// Unused method from parent
void initialize() override {}
protected:
// Below are display steps, called one after the other by loop()
// Just implement these to support a new device.
// Never sleep or wait in a step, the state machine will
// handle it.
// Just after reset, set the power mode and power the driver on
virtual void power_on() = 0;
// Send all the configuration required to display
virtual void configure() = 0;
// Send image data and refresh the display
void display() override = 0;
// Power off the driver
virtual void power_off() = 0;
// Set the screen to deep sleep
void deep_sleep() override = 0;
private:
enum class State : uint8_t {
SLEEPING,
UPDATE_REQUESTED,
RESETTING,
INITIALIZING,
POWERING_ON,
CONFIGURING,
DISPLAYING,
POWERING_OFF,
};
// Set the current state of the display
void set_state_(State state);
// Current state of the display
State state_{State::SLEEPING};
// Timestamp of last state changed, used to wait between states
uint32_t last_state_change_{0};
};
// 7.5 inches screen supporting black and red color with
// a v3 label on the back. Called EDP_7in5b_V2 in WaveShare examples.
class WaveshareEPaper7In5BV2 : public WaveshareEPaperPolled {
public:
void dump_config() override;
void power_on() override;
void configure() override;
void display() override;
void power_off() override;
void deep_sleep() override;
std::vector<Color> get_supported_colors() override { return {display::COLOR_ON, Color(255, 0, 0, 0)}; }
protected:
int get_width_internal() override { return 800; }
int get_height_internal() override { return 480; }
};
} // namespace waveshare_epaper
} // namespace esphome