mirror of
https://github.com/esphome/esphome.git
synced 2024-12-24 14:34:54 +01:00
Waveshare: support red and black on EDP_7in5b_V2
This commit is contained in:
parent
75899162b3
commit
481e7ee74b
3 changed files with 294 additions and 73 deletions
|
@ -24,6 +24,9 @@ WaveshareEPaper = waveshare_epaper_ns.class_("WaveshareEPaper", WaveshareEPaperB
|
|||
WaveshareEPaperBWR = waveshare_epaper_ns.class_(
|
||||
"WaveshareEPaperBWR", WaveshareEPaperBase
|
||||
)
|
||||
WaveshareEPaperPolled = waveshare_epaper_ns.class_(
|
||||
"WaveshareEPaperPolled", WaveshareEPaper
|
||||
)
|
||||
WaveshareEPaperTypeA = waveshare_epaper_ns.class_(
|
||||
"WaveshareEPaperTypeA", WaveshareEPaper
|
||||
)
|
||||
|
@ -98,6 +101,9 @@ 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")
|
||||
|
@ -128,6 +134,7 @@ MODELS = {
|
|||
"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),
|
||||
|
|
|
@ -110,7 +110,7 @@ static const uint8_t PARTIAL_UPD_2IN9_LUT[PARTIAL_UPD_2IN9_LUT_SIZE] =
|
|||
};
|
||||
// clang-format on
|
||||
|
||||
void WaveshareEPaperBase::setup_pins_() {
|
||||
void WaveshareEPaper::setup_pins_() {
|
||||
this->init_internal_(this->get_buffer_length_());
|
||||
this->dc_pin_->setup(); // OUTPUT
|
||||
this->dc_pin_->digital_write(false);
|
||||
|
@ -125,13 +125,13 @@ void WaveshareEPaperBase::setup_pins_() {
|
|||
|
||||
this->reset_();
|
||||
}
|
||||
float WaveshareEPaperBase::get_setup_priority() const { return setup_priority::PROCESSOR; }
|
||||
void WaveshareEPaperBase::command(uint8_t value) {
|
||||
float WaveshareEPaper::get_setup_priority() const { return setup_priority::PROCESSOR; }
|
||||
void WaveshareEPaper::command(uint8_t value) {
|
||||
this->start_command_();
|
||||
this->write_byte(value);
|
||||
this->end_command_();
|
||||
}
|
||||
void WaveshareEPaperBase::data(uint8_t value) {
|
||||
void WaveshareEPaper::data(uint8_t value) {
|
||||
this->start_data_();
|
||||
this->write_byte(value);
|
||||
this->end_data_();
|
||||
|
@ -139,7 +139,7 @@ void WaveshareEPaperBase::data(uint8_t value) {
|
|||
|
||||
// write a command followed by one or more bytes of data.
|
||||
// The command is the first byte, length is the total including cmd.
|
||||
void WaveshareEPaperBase::cmd_data(const uint8_t *c_data, size_t length) {
|
||||
void WaveshareEPaper::cmd_data(const uint8_t *c_data, size_t length) {
|
||||
this->dc_pin_->digital_write(false);
|
||||
this->enable();
|
||||
this->write_byte(c_data[0]);
|
||||
|
@ -148,7 +148,7 @@ void WaveshareEPaperBase::cmd_data(const uint8_t *c_data, size_t length) {
|
|||
this->disable();
|
||||
}
|
||||
|
||||
bool WaveshareEPaperBase::wait_until_idle_() {
|
||||
bool WaveshareEPaper::wait_until_idle_() {
|
||||
if (this->busy_pin_ == nullptr || !this->busy_pin_->digital_read()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -163,15 +163,23 @@ bool WaveshareEPaperBase::wait_until_idle_() {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
void WaveshareEPaperBase::update() {
|
||||
void WaveshareEPaper::update() {
|
||||
this->do_update_();
|
||||
this->display();
|
||||
}
|
||||
void WaveshareEPaper::fill(Color color) {
|
||||
// flip logic
|
||||
const uint8_t fill = color.is_on() ? 0x00 : 0xFF;
|
||||
for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
|
||||
this->buffer_[i] = fill;
|
||||
uint32_t offset = 0;
|
||||
for (const auto& buf_color: this->get_supported_colors()) {
|
||||
// A bit set to 1 means color is off
|
||||
uint8_t value = 0x00;
|
||||
if (color != buf_color) {
|
||||
value = 0xFF;
|
||||
}
|
||||
for (uint32_t i = 0; i < (this->get_width_internal() * this->get_height_internal()) / 8u; i++) {
|
||||
this->buffer_[offset+i] = value;
|
||||
}
|
||||
offset+= (this->get_width_internal() * this->get_height_internal()) / 8u;
|
||||
}
|
||||
}
|
||||
void HOT WaveshareEPaper::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||
if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
|
||||
|
@ -179,58 +187,40 @@ void HOT WaveshareEPaper::draw_absolute_pixel_internal(int x, int y, Color color
|
|||
|
||||
const uint32_t pos = (x + y * this->get_width_controller()) / 8u;
|
||||
const uint8_t subpos = x & 0x07;
|
||||
// flip logic
|
||||
if (!color.is_on()) {
|
||||
this->buffer_[pos] |= 0x80 >> subpos;
|
||||
} else {
|
||||
this->buffer_[pos] &= ~(0x80 >> subpos);
|
||||
uint32_t offset = 0;
|
||||
for (const auto& buf_color: this->get_supported_colors()) {
|
||||
// A bit set to 1 means color is off
|
||||
this->buffer_[offset+pos] &= ~(0x80 >> subpos);
|
||||
if (color != buf_color) {
|
||||
this->buffer_[offset+pos] |= 0x80 >> subpos;
|
||||
}
|
||||
offset+= (this->get_width_internal() * this->get_height_internal()) / 8u;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t WaveshareEPaper::get_buffer_length_() {
|
||||
return this->get_width_controller() * this->get_height_internal() / 8u;
|
||||
} // just a black buffer
|
||||
uint32_t WaveshareEPaperBWR::get_buffer_length_() {
|
||||
return this->get_width_controller() * this->get_height_internal() / 4u;
|
||||
} // black and red buffer
|
||||
|
||||
void WaveshareEPaperBWR::fill(Color color) {
|
||||
this->filled_rectangle(0, 0, this->get_width(), this->get_height(), color);
|
||||
}
|
||||
void HOT WaveshareEPaperBWR::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||
if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
|
||||
return;
|
||||
|
||||
const uint32_t buf_half_len = this->get_buffer_length_() / 2u;
|
||||
|
||||
const uint32_t pos = (x + y * this->get_width_internal()) / 8u;
|
||||
const uint8_t subpos = x & 0x07;
|
||||
// flip logic
|
||||
if (color.is_on()) {
|
||||
this->buffer_[pos] |= 0x80 >> subpos;
|
||||
} else {
|
||||
this->buffer_[pos] &= ~(0x80 >> subpos);
|
||||
}
|
||||
|
||||
// draw red pixels only, if the color contains red only
|
||||
if (((color.red > 0) && (color.green == 0) && (color.blue == 0))) {
|
||||
this->buffer_[pos + buf_half_len] |= 0x80 >> subpos;
|
||||
} else {
|
||||
this->buffer_[pos + buf_half_len] &= ~(0x80 >> subpos);
|
||||
}
|
||||
return (this->get_width_controller() * this->get_height_internal() * this->get_supported_colors().size()) / 8u;
|
||||
}
|
||||
|
||||
void WaveshareEPaperBase::start_command_() {
|
||||
void WaveshareEPaper::start_command_() {
|
||||
this->dc_pin_->digital_write(false);
|
||||
this->enable();
|
||||
}
|
||||
void WaveshareEPaperBase::end_command_() { this->disable(); }
|
||||
void WaveshareEPaperBase::start_data_() {
|
||||
void WaveshareEPaper::end_command_() { this->disable(); }
|
||||
void WaveshareEPaper::start_data_() {
|
||||
this->dc_pin_->digital_write(true);
|
||||
this->enable();
|
||||
}
|
||||
void WaveshareEPaperBase::end_data_() { this->disable(); }
|
||||
void WaveshareEPaperBase::on_safe_shutdown() { this->deep_sleep(); }
|
||||
void WaveshareEPaper::end_data_() { this->disable(); }
|
||||
void WaveshareEPaper::on_safe_shutdown() { this->deep_sleep(); }
|
||||
|
||||
display::DisplayType WaveshareEPaper::get_display_type() {
|
||||
if (this->get_supported_colors().size() == 1) {
|
||||
return display::DisplayType::DISPLAY_TYPE_BINARY;
|
||||
} else {
|
||||
return display::DisplayType::DISPLAY_TYPE_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================
|
||||
// Type A
|
||||
|
@ -602,7 +592,7 @@ uint32_t WaveshareEPaperTypeA::idle_timeout_() {
|
|||
case TTGO_EPAPER_2_13_IN_B1:
|
||||
return 2500;
|
||||
default:
|
||||
return WaveshareEPaperBase::idle_timeout_();
|
||||
return WaveshareEPaper::idle_timeout_();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3040,11 +3030,166 @@ uint32_t WaveshareEPaper13P3InK::idle_timeout_() { return 10000; }
|
|||
void WaveshareEPaper13P3InK::dump_config() {
|
||||
LOG_DISPLAY("", "Waveshare E-Paper", this);
|
||||
ESP_LOGCONFIG(TAG, " Model: 13.3inK");
|
||||
}
|
||||
|
||||
void WaveshareEPaperPolled::update() {
|
||||
this->do_update_();
|
||||
if (this->state_ == State::sleeping) {
|
||||
this->set_state_(State::update_requested);
|
||||
}
|
||||
}
|
||||
|
||||
void WaveshareEPaperPolled::loop() {
|
||||
switch (this->state_) {
|
||||
case State::sleeping:
|
||||
break;
|
||||
case State::update_requested:
|
||||
this->reset_pin_->digital_write(false);
|
||||
this->set_state_(State::resetting);
|
||||
break;
|
||||
case State::resetting:
|
||||
if (millis() - this->last_state_change_ >= this->reset_duration_) {
|
||||
this->reset_pin_->digital_write(true);
|
||||
this->set_state_(State::initializing);
|
||||
}
|
||||
break;
|
||||
case State::initializing:
|
||||
if (millis() - this->last_state_change_ >= 200) {
|
||||
this->power_on();
|
||||
this->set_state_(State::powering_on);
|
||||
}
|
||||
break;
|
||||
case State::powering_on:
|
||||
if (millis() - this->last_state_change_ >= 100 && (!this->busy_pin_ || !this->busy_pin_->digital_read())) {
|
||||
this->configure();
|
||||
this->set_state_(State::configuring);
|
||||
}
|
||||
break;
|
||||
case State::configuring:
|
||||
this->display();
|
||||
this->set_state_(State::displaying);
|
||||
break;
|
||||
case State::displaying:
|
||||
if (millis() - this->last_state_change_ >= 200 && (!this->busy_pin_ || !this->busy_pin_->digital_read())) {
|
||||
this->power_off();
|
||||
this->set_state_(State::powering_off);
|
||||
}
|
||||
break;
|
||||
case State::powering_off:
|
||||
if (!this->busy_pin_ || !this->busy_pin_->digital_read()) {
|
||||
this->deep_sleep();
|
||||
this->set_state_(State::sleeping);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WaveshareEPaperPolled::set_state_(State state) {
|
||||
this->state_ = state;
|
||||
this->last_state_change_ = millis();
|
||||
switch (this->state_) {
|
||||
case State::sleeping:
|
||||
ESP_LOGD(TAG, "sleeping");
|
||||
break;
|
||||
case State::update_requested:
|
||||
ESP_LOGD(TAG, "update_requested");
|
||||
break;
|
||||
case State::resetting:
|
||||
ESP_LOGD(TAG, "resetting");
|
||||
break;
|
||||
case State::initializing:
|
||||
ESP_LOGD(TAG, "initializing");
|
||||
break;
|
||||
case State::powering_on:
|
||||
ESP_LOGD(TAG, "powering_on");
|
||||
break;
|
||||
case State::configuring:
|
||||
ESP_LOGD(TAG, "configuring");
|
||||
break;
|
||||
case State::displaying:
|
||||
ESP_LOGD(TAG, "displaying");
|
||||
break;
|
||||
case State::powering_off:
|
||||
ESP_LOGD(TAG, "powering_off");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WaveshareEPaper7In5BV2::dump_config() {
|
||||
LOG_DISPLAY("", "Waveshare E-Paper", this);
|
||||
ESP_LOGCONFIG(TAG, " Model: 7.5in V3 Black/Red");
|
||||
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 WaveshareEPaper7In5BV2::power_on() {
|
||||
// COMMAND POWER SETTING
|
||||
this->command(0x01);
|
||||
this->data(0x07);
|
||||
this->data(0x17);
|
||||
this->data(0x3F);
|
||||
this->data(0x3F);
|
||||
// POWER ON
|
||||
this->command(0x04);
|
||||
}
|
||||
|
||||
void WaveshareEPaper7In5BV2::configure() {
|
||||
// COMMAND PANEL SETTING
|
||||
this->command(0x00);
|
||||
this->data(0x0F); // //KW-3f KWR-2F BWROTP 0f BWOTP 1f
|
||||
// COMMAND RESOLUTION SETTING
|
||||
this->command(0x61);
|
||||
this->data(0x03);
|
||||
this->data(0x20);
|
||||
this->data(0x01);
|
||||
this->data(0xE0);
|
||||
// COMMAND DUAL SPI MODE
|
||||
this->command(0x15);
|
||||
this->data(0x00);
|
||||
// COMMAND VCOM AND DATA INTERVAL SETTING
|
||||
this->command(0x50);
|
||||
this->data(0x11);
|
||||
this->data(0x07);
|
||||
// COMMAND TCON SETTING
|
||||
this->command(0x60);
|
||||
this->data(0x22);
|
||||
// COMMAND RESOLUTION GATE SETTING
|
||||
this->command(0x65);
|
||||
this->data(0x00);
|
||||
this->data(0x00);
|
||||
this->data(0x00);
|
||||
this->data(0x00);
|
||||
}
|
||||
|
||||
void HOT WaveshareEPaper7In5BV2::display() {
|
||||
uint32_t buf_len = this->get_buffer_length_();
|
||||
// COMMAND DATA START TRANSMISSION NEW DATA
|
||||
this->command(0x10);
|
||||
for (uint32_t i = 0; i < buf_len/2; i++) {
|
||||
this->data(this->buffer_[i]);
|
||||
}
|
||||
this->command(0x92);
|
||||
|
||||
// COMMAND DATA START TRANSMISSION NEW DATA
|
||||
this->command(0x13);
|
||||
for (uint32_t i = buf_len/2; i < buf_len; i++) {
|
||||
this->data(~this->buffer_[i]);
|
||||
}
|
||||
|
||||
// COMMAND DISPLAY REFRESH
|
||||
this->command(0x12);
|
||||
}
|
||||
|
||||
void WaveshareEPaper7In5BV2::power_off() {
|
||||
this->command(0x02); // POWER OFF
|
||||
}
|
||||
|
||||
void WaveshareEPaper7In5BV2::deep_sleep() {
|
||||
this->command(0x07); // SLEEP
|
||||
this->data(0xA5);
|
||||
}
|
||||
|
||||
} // namespace waveshare_epaper
|
||||
} // namespace esphome
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
namespace esphome {
|
||||
namespace waveshare_epaper {
|
||||
|
||||
class WaveshareEPaperBase : public display::DisplayBuffer,
|
||||
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:
|
||||
|
@ -34,6 +34,10 @@ class WaveshareEPaperBase : public display::DisplayBuffer,
|
|||
|
||||
void on_safe_shutdown() override;
|
||||
|
||||
display::DisplayType get_display_type() override;
|
||||
|
||||
void fill(Color color) override;
|
||||
|
||||
protected:
|
||||
bool wait_until_idle_();
|
||||
|
||||
|
@ -50,9 +54,14 @@ class WaveshareEPaperBase : public display::DisplayBuffer,
|
|||
|
||||
virtual int get_width_controller() { return this->get_width_internal(); };
|
||||
|
||||
virtual uint32_t get_buffer_length_() = 0; // NOLINT(readability-identifier-naming)
|
||||
virtual 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_();
|
||||
|
@ -64,26 +73,9 @@ class WaveshareEPaperBase : public display::DisplayBuffer,
|
|||
virtual uint32_t idle_timeout_() { return 1000u; } // NOLINT(readability-identifier-naming)
|
||||
};
|
||||
|
||||
class WaveshareEPaper : public WaveshareEPaperBase {
|
||||
class WaveshareEPaperBWR : public WaveshareEPaper {
|
||||
public:
|
||||
void fill(Color color) override;
|
||||
|
||||
display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_BINARY; }
|
||||
|
||||
protected:
|
||||
void draw_absolute_pixel_internal(int x, int y, Color color) override;
|
||||
uint32_t get_buffer_length_() override;
|
||||
};
|
||||
|
||||
class WaveshareEPaperBWR : public WaveshareEPaperBase {
|
||||
public:
|
||||
void fill(Color color) override;
|
||||
|
||||
display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; }
|
||||
|
||||
protected:
|
||||
void draw_absolute_pixel_internal(int x, int y, Color color) override;
|
||||
uint32_t get_buffer_length_() override;
|
||||
virtual std::vector<Color> get_supported_colors() override { return {display::COLOR_ON, Color(255, 0, 0, 0)}; }
|
||||
};
|
||||
|
||||
enum WaveshareEPaperTypeAModel {
|
||||
|
@ -791,6 +783,83 @@ class WaveshareEPaper13P3InK : public WaveshareEPaper {
|
|||
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
|
||||
virtual void display() = 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;
|
||||
|
||||
virtual 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
|
||||
|
|
Loading…
Reference in a new issue