From c6ce6ce0164628f54cbdfb205d94342766496ae2 Mon Sep 17 00:00:00 2001 From: Michael Davidson Date: Sun, 11 Feb 2024 09:57:34 +1100 Subject: [PATCH 1/3] Support for 4.2in v2 display. Board is marked as Rev 2.2 --- esphome/components/waveshare_epaper/display.py | 4 ++++ .../components/waveshare_epaper/waveshare_epaper.cpp | 10 ++++++++++ esphome/components/waveshare_epaper/waveshare_epaper.h | 2 ++ 3 files changed, 16 insertions(+) diff --git a/esphome/components/waveshare_epaper/display.py b/esphome/components/waveshare_epaper/display.py index fa7c104951..240f61dcf1 100644 --- a/esphome/components/waveshare_epaper/display.py +++ b/esphome/components/waveshare_epaper/display.py @@ -52,6 +52,9 @@ WaveshareEPaper4P2In = waveshare_epaper_ns.class_( WaveshareEPaper4P2InBV2 = waveshare_epaper_ns.class_( "WaveshareEPaper4P2InBV2", WaveshareEPaper ) +WaveshareEPaper4P2InV2 = waveshare_epaper_ns.class_( + "WaveshareEPaper4P2InV2", WaveshareEPaper +) WaveshareEPaper5P8In = waveshare_epaper_ns.class_( "WaveshareEPaper5P8In", WaveshareEPaper ) @@ -109,6 +112,7 @@ MODELS = { "2.90in-bv3": ("b", WaveshareEPaper2P9InBV3), "4.20in": ("b", WaveshareEPaper4P2In), "4.20in-bv2": ("b", WaveshareEPaper4P2InBV2), + "4.20in-v2": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_4_2_IN_V2), "5.83in": ("b", WaveshareEPaper5P8In), "5.83inv2": ("b", WaveshareEPaper5P8InV2), "7.50in": ("b", WaveshareEPaper7P5In), diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.cpp b/esphome/components/waveshare_epaper/waveshare_epaper.cpp index 9118475c36..ff5f9feaf1 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.cpp +++ b/esphome/components/waveshare_epaper/waveshare_epaper.cpp @@ -219,6 +219,7 @@ void WaveshareEPaperTypeA::initialize() { // More models can be added here to enable deep sleep if eligible case WAVESHARE_EPAPER_1_54_IN: case WAVESHARE_EPAPER_1_54_IN_V2: + case WAVESHARE_EPAPER_4_2_IN_V2: this->deep_sleep_between_updates_ = true; ESP_LOGI(TAG, "Set the display to deep sleep"); this->deep_sleep(); @@ -272,6 +273,7 @@ void WaveshareEPaperTypeA::init_display_() { break; case TTGO_EPAPER_2_13_IN_B74: case WAVESHARE_EPAPER_2_9_IN_V2: + case WAVESHARE_EPAPER_4_2_IN_V2: this->data(0x03); // from top left to bottom right // RAM content option for Display Update this->command(0x21); @@ -312,6 +314,9 @@ void WaveshareEPaperTypeA::dump_config() { case WAVESHARE_EPAPER_2_9_IN_V2: ESP_LOGCONFIG(TAG, " Model: 2.9inV2"); break; + case WAVESHARE_EPAPER_4_2_IN_V2: + ESP_LOGCONFIG(TAG, " Model: 4.2inV2"); + break; } ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_); LOG_PIN(" Reset Pin: ", this->reset_pin_); @@ -435,6 +440,7 @@ void HOT WaveshareEPaperTypeA::display() { this->command(0x22); switch (this->model_) { case WAVESHARE_EPAPER_2_9_IN_V2: + case WAVESHARE_EPAPER_4_2_IN_V2: case WAVESHARE_EPAPER_1_54_IN_V2: case TTGO_EPAPER_2_13_IN_B74: this->data(full_update ? 0xF7 : 0xFF); @@ -473,6 +479,8 @@ int WaveshareEPaperTypeA::get_width_internal() { case WAVESHARE_EPAPER_2_9_IN: case WAVESHARE_EPAPER_2_9_IN_V2: return 128; + case WAVESHARE_EPAPER_4_2_IN_V2: + return 400; } return 0; } @@ -503,6 +511,8 @@ int WaveshareEPaperTypeA::get_height_internal() { case WAVESHARE_EPAPER_2_9_IN: case WAVESHARE_EPAPER_2_9_IN_V2: return 296; + case WAVESHARE_EPAPER_4_2_IN_V2: + return 300; } return 0; } diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.h b/esphome/components/waveshare_epaper/waveshare_epaper.h index 47f0cb27b6..d12ceb9cdc 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.h +++ b/esphome/components/waveshare_epaper/waveshare_epaper.h @@ -92,6 +92,7 @@ enum WaveshareEPaperTypeAModel { WAVESHARE_EPAPER_2_13_IN, WAVESHARE_EPAPER_2_9_IN, WAVESHARE_EPAPER_2_9_IN_V2, + WAVESHARE_EPAPER_4_2_IN_V2, TTGO_EPAPER_2_13_IN, TTGO_EPAPER_2_13_IN_B73, TTGO_EPAPER_2_13_IN_B1, @@ -114,6 +115,7 @@ class WaveshareEPaperTypeA : public WaveshareEPaper { case WAVESHARE_EPAPER_1_54_IN: case WAVESHARE_EPAPER_1_54_IN_V2: case WAVESHARE_EPAPER_2_9_IN_V2: + case WAVESHARE_EPAPER_4_2_IN_V2: // COMMAND DEEP SLEEP MODE this->command(0x10); this->data(0x01); From b4b3d5efadc4b6f971626313afd774a860493b2a Mon Sep 17 00:00:00 2001 From: Michael Davidson Date: Tue, 5 Mar 2024 20:44:15 +1100 Subject: [PATCH 2/3] Rollbck changes to WaveshareEPaperTypeA --- .../components/waveshare_epaper/waveshare_epaper.cpp | 10 ---------- esphome/components/waveshare_epaper/waveshare_epaper.h | 2 -- 2 files changed, 12 deletions(-) diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.cpp b/esphome/components/waveshare_epaper/waveshare_epaper.cpp index ff5f9feaf1..9118475c36 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.cpp +++ b/esphome/components/waveshare_epaper/waveshare_epaper.cpp @@ -219,7 +219,6 @@ void WaveshareEPaperTypeA::initialize() { // More models can be added here to enable deep sleep if eligible case WAVESHARE_EPAPER_1_54_IN: case WAVESHARE_EPAPER_1_54_IN_V2: - case WAVESHARE_EPAPER_4_2_IN_V2: this->deep_sleep_between_updates_ = true; ESP_LOGI(TAG, "Set the display to deep sleep"); this->deep_sleep(); @@ -273,7 +272,6 @@ void WaveshareEPaperTypeA::init_display_() { break; case TTGO_EPAPER_2_13_IN_B74: case WAVESHARE_EPAPER_2_9_IN_V2: - case WAVESHARE_EPAPER_4_2_IN_V2: this->data(0x03); // from top left to bottom right // RAM content option for Display Update this->command(0x21); @@ -314,9 +312,6 @@ void WaveshareEPaperTypeA::dump_config() { case WAVESHARE_EPAPER_2_9_IN_V2: ESP_LOGCONFIG(TAG, " Model: 2.9inV2"); break; - case WAVESHARE_EPAPER_4_2_IN_V2: - ESP_LOGCONFIG(TAG, " Model: 4.2inV2"); - break; } ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_); LOG_PIN(" Reset Pin: ", this->reset_pin_); @@ -440,7 +435,6 @@ void HOT WaveshareEPaperTypeA::display() { this->command(0x22); switch (this->model_) { case WAVESHARE_EPAPER_2_9_IN_V2: - case WAVESHARE_EPAPER_4_2_IN_V2: case WAVESHARE_EPAPER_1_54_IN_V2: case TTGO_EPAPER_2_13_IN_B74: this->data(full_update ? 0xF7 : 0xFF); @@ -479,8 +473,6 @@ int WaveshareEPaperTypeA::get_width_internal() { case WAVESHARE_EPAPER_2_9_IN: case WAVESHARE_EPAPER_2_9_IN_V2: return 128; - case WAVESHARE_EPAPER_4_2_IN_V2: - return 400; } return 0; } @@ -511,8 +503,6 @@ int WaveshareEPaperTypeA::get_height_internal() { case WAVESHARE_EPAPER_2_9_IN: case WAVESHARE_EPAPER_2_9_IN_V2: return 296; - case WAVESHARE_EPAPER_4_2_IN_V2: - return 300; } return 0; } diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.h b/esphome/components/waveshare_epaper/waveshare_epaper.h index d12ceb9cdc..47f0cb27b6 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.h +++ b/esphome/components/waveshare_epaper/waveshare_epaper.h @@ -92,7 +92,6 @@ enum WaveshareEPaperTypeAModel { WAVESHARE_EPAPER_2_13_IN, WAVESHARE_EPAPER_2_9_IN, WAVESHARE_EPAPER_2_9_IN_V2, - WAVESHARE_EPAPER_4_2_IN_V2, TTGO_EPAPER_2_13_IN, TTGO_EPAPER_2_13_IN_B73, TTGO_EPAPER_2_13_IN_B1, @@ -115,7 +114,6 @@ class WaveshareEPaperTypeA : public WaveshareEPaper { case WAVESHARE_EPAPER_1_54_IN: case WAVESHARE_EPAPER_1_54_IN_V2: case WAVESHARE_EPAPER_2_9_IN_V2: - case WAVESHARE_EPAPER_4_2_IN_V2: // COMMAND DEEP SLEEP MODE this->command(0x10); this->data(0x01); From 0d040b46b7ff23735faeb29806ab5a84cbd03a4e Mon Sep 17 00:00:00 2001 From: Michael Davidson Date: Tue, 5 Mar 2024 23:03:50 +1100 Subject: [PATCH 3/3] Split support for Waveshare 4.2 v2 devices into their own class Tagged as "a-alt". It's a Type A device but implemented in its own class to reduce conditionals throughout the Type A implementation --- .../components/waveshare_epaper/display.py | 4 +- .../waveshare_epaper/waveshare_42v2.cpp | 158 ++++++++++++++++++ .../waveshare_epaper/waveshare_42v2.h | 32 ++++ 3 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 esphome/components/waveshare_epaper/waveshare_42v2.cpp create mode 100644 esphome/components/waveshare_epaper/waveshare_42v2.h diff --git a/esphome/components/waveshare_epaper/display.py b/esphome/components/waveshare_epaper/display.py index 240f61dcf1..66e7a16b35 100644 --- a/esphome/components/waveshare_epaper/display.py +++ b/esphome/components/waveshare_epaper/display.py @@ -112,7 +112,7 @@ MODELS = { "2.90in-bv3": ("b", WaveshareEPaper2P9InBV3), "4.20in": ("b", WaveshareEPaper4P2In), "4.20in-bv2": ("b", WaveshareEPaper4P2InBV2), - "4.20in-v2": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_4_2_IN_V2), + "4.20in-v2": ("a-alt", WaveshareEPaper4P2InV2), "5.83in": ("b", WaveshareEPaper5P8In), "5.83inv2": ("b", WaveshareEPaper5P8InV2), "7.50in": ("b", WaveshareEPaper7P5In), @@ -170,7 +170,7 @@ async def to_code(config): if model_type == "a": rhs = WaveshareEPaperTypeA.new(model) var = cg.Pvariable(config[CONF_ID], rhs, WaveshareEPaperTypeA) - elif model_type in ("b", "c"): + elif model_type in ("a-alt", "b", "c"): rhs = model.new() var = cg.Pvariable(config[CONF_ID], rhs, model) else: diff --git a/esphome/components/waveshare_epaper/waveshare_42v2.cpp b/esphome/components/waveshare_epaper/waveshare_42v2.cpp new file mode 100644 index 0000000000..fc97581c3c --- /dev/null +++ b/esphome/components/waveshare_epaper/waveshare_42v2.cpp @@ -0,0 +1,158 @@ +#include "waveshare_42v2.h" +#include +#include "esphome/core/log.h" + +namespace esphome { +namespace waveshare_epaper { + +static const char *const TAG = "waveshare_4.2v2"; + +void WaveshareEPaper4P2InV2::display() { + ESP_LOGD(TAG, "Performing full update"); + this->full_update_(); +} + +void WaveshareEPaper4P2InV2::full_update_() { + this->reset_(); + this->wait_until_idle_(); + + this->command(0x24); + this->start_data_(); + this->write_array(this->buffer_, this->get_buffer_length_()); + this->end_data_(); + + this->command(0x26); + this->start_data_(); + this->write_array(this->buffer_, this->get_buffer_length_()); + this->end_data_(); + + this->turn_on_display_full_(); + + this->deep_sleep(); +} + +void WaveshareEPaper4P2InV2::turn_on_display_full_() { + this->command(0x22); + this->data(0xc7); + this->command(0x20); + + this->wait_until_idle_(); +} + +void WaveshareEPaper4P2InV2::set_window_(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2) { + this->command(0x44); // SET_RAM_X_ADDRESS_START_END_POSITION + this->data((x >> 3) & 0xFF); + this->data((x2 >> 3) & 0xFF); + + this->command(0x45); // SET_RAM_Y_ADDRESS_START_END_POSITION + this->data(y & 0xFF); + this->data((y >> 8) & 0xFF); + this->data(62 & 0xFF); + this->data((y2 >> 8) & 0xFF); +} + +void WaveshareEPaper4P2InV2::clear_() { + uint8_t *buffer = (uint8_t *) calloc(this->get_buffer_length_(), sizeof(uint8_t)); + memset(buffer, 0xff, this->get_buffer_length_()); + + this->command(0x24); + this->start_data_(); + this->write_array(buffer, this->get_buffer_length_()); + this->end_data_(); + + this->command(0x26); + this->start_data_(); + this->write_array(buffer, this->get_buffer_length_()); + this->end_data_(); + + free(buffer); +} + +void WaveshareEPaper4P2InV2::set_cursor_(uint16_t x, uint16_t y) { + this->command(0x4E); // SET_RAM_X_ADDRESS_COUNTER + this->data(x & 0xFF); + + this->command(0x4F); // SET_RAM_Y_ADDRESS_COUNTER + this->data(y & 0xFF); + this->data((y >> 8) & 0xFF); +} + +void WaveshareEPaper4P2InV2::fast_initialize_() { +#define MODE_1_SECOND 1 +#define MODE_1_5_SECOND 0 + + this->reset_(); + if (!this->wait_until_idle_()) { + ESP_LOGW(TAG, "wait_until_idle_ returned FALSE. Is your busy pin set?"); + } + this->command(0x12); // soft reset + if (!this->wait_until_idle_()) { + ESP_LOGW(TAG, "wait_until_idle_ returned FALSE. Is your busy pin set?"); + } + this->command(0x21); + this->data(0x40); + this->data(0x00); + + this->command(0x3C); + this->data(0x05); + +#if MODE_1_5_SECOND + // 1.5s + this->command(0x1A); // Write to temperature register + this->data(0x6E); +#endif +#if MODE_1_SECOND + // 1s + this->command(0x1A); // Write to temperature register + this->data(0x5A); +#endif + + this->command(0x22); // Load temperature value + this->data(0x91); + this->command(0x20); + if (!this->wait_until_idle_()) { + ESP_LOGW(TAG, "wait_until_idle_ returned FALSE. Is your busy pin set?"); + } + this->command(0x11); // data entry mode + this->data(0x03); // X-mode + + this->set_window_(0, 0, this->get_width_internal() - 1, this->get_height_internal() - 1); + this->set_cursor_(0, 0); + + if (!this->wait_until_idle_()) { + ESP_LOGW(TAG, "wait_until_idle_ returned FALSE. Is your busy pin set?"); + } + + this->clear_(); + this->turn_on_display_full_(); +} + +void WaveshareEPaper4P2InV2::initialize() { + this->fast_initialize_(); +} + +void WaveshareEPaper4P2InV2::deep_sleep() { + this->command(0x10); + this->data(0x01); + delay(200); +} + +void WaveshareEPaper4P2InV2::set_full_update_every(uint32_t full_update_every) { + this->full_update_every_ = full_update_every; +} + +int WaveshareEPaper4P2InV2::get_width_internal() { return 400; } + +int WaveshareEPaper4P2InV2::get_height_internal() { return 300; } + +void WaveshareEPaper4P2InV2::reset_() { + this->reset_pin_->digital_write(true); // Note: Should be inverted logic + delay(100); + this->reset_pin_->digital_write(false); // Note: Should be inverted logic according to the docs + delay(this->reset_duration_); + this->reset_pin_->digital_write(true); // Note: Should be inverted logic + delay(100); +} + +} // namespace waveshare_epaper +} // namespace esphome \ No newline at end of file diff --git a/esphome/components/waveshare_epaper/waveshare_42v2.h b/esphome/components/waveshare_epaper/waveshare_42v2.h new file mode 100644 index 0000000000..96661562b7 --- /dev/null +++ b/esphome/components/waveshare_epaper/waveshare_42v2.h @@ -0,0 +1,32 @@ +#include "waveshare_epaper.h" + +namespace esphome { +namespace waveshare_epaper { + +class WaveshareEPaper4P2InV2 : public WaveshareEPaper { + public: + void display() override; + void initialize() override; + void deep_sleep() override; + + void set_full_update_every(uint32_t full_update_every); + + protected: + void fast_initialize_(); + void full_update_(); + + void reset_(); + void set_window_(uint16_t x, uint16_t y, uint16_t x1, uint16_t y2); + void set_cursor_(uint16_t x, uint16_t y); + void turn_on_display_full_(); + void clear_(); + + int get_width_internal() override; + int get_height_internal() override; + + uint32_t full_update_every_{30}; + uint32_t at_update_{0}; +}; + +} // namespace waveshare_epaper +} // namespace esphome \ No newline at end of file