diff --git a/esphome/components/waveshare_epaper/display.py b/esphome/components/waveshare_epaper/display.py index 430022e542..16f234563c 100644 --- a/esphome/components/waveshare_epaper/display.py +++ b/esphome/components/waveshare_epaper/display.py @@ -48,6 +48,7 @@ MODELS = { "1.54in": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_1_54_IN), "2.13in": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_13_IN), "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.90in": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_9_IN), "2.90inv2": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_9_IN_V2), diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.cpp b/esphome/components/waveshare_epaper/waveshare_epaper.cpp index adb748d308..0fb783107d 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.cpp +++ b/esphome/components/waveshare_epaper/waveshare_epaper.cpp @@ -9,6 +9,7 @@ namespace waveshare_epaper { static const char *TAG = "waveshare_epaper"; static const uint8_t LUT_SIZE_WAVESHARE = 30; + static const uint8_t FULL_UPDATE_LUT[LUT_SIZE_WAVESHARE] = {0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22, 0x66, 0x69, 0x69, 0x59, 0x58, 0x99, 0x99, 0x88, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB4, 0x13, 0x51, 0x35, 0x51, 0x51, 0x19, 0x01, 0x00}; @@ -18,7 +19,6 @@ static const uint8_t PARTIAL_UPDATE_LUT[LUT_SIZE_WAVESHARE] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static const uint8_t LUT_SIZE_TTGO = 70; -static const uint8_t LUT_SIZE_TTGO_B73 = 100; static const uint8_t FULL_UPDATE_LUT_TTGO[LUT_SIZE_TTGO] = { 0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, // LUT0: BB: VS 0 ~7 @@ -35,6 +35,23 @@ static const uint8_t FULL_UPDATE_LUT_TTGO[LUT_SIZE_TTGO] = { 0x00, 0x00, 0x00, 0x00, 0x00, // TP6 A~D RP6 }; +static const uint8_t PARTIAL_UPDATE_LUT_TTGO[LUT_SIZE_TTGO] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT0: BB: VS 0 ~7 + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT1: BW: VS 0 ~7 + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT2: WB: VS 0 ~7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT3: WW: VS 0 ~7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT4: VCOM: VS 0 ~7 + 0x0A, 0x00, 0x00, 0x00, 0x00, // TP0 A~D RP0 + 0x00, 0x00, 0x00, 0x00, 0x00, // TP1 A~D RP1 + 0x00, 0x00, 0x00, 0x00, 0x00, // TP2 A~D RP2 + 0x00, 0x00, 0x00, 0x00, 0x00, // TP3 A~D RP3 + 0x00, 0x00, 0x00, 0x00, 0x00, // TP4 A~D RP4 + 0x00, 0x00, 0x00, 0x00, 0x00, // TP5 A~D RP5 + 0x00, 0x00, 0x00, 0x00, 0x00, // TP6 A~D RP6 +}; + +static const uint8_t LUT_SIZE_TTGO_B73 = 100; + static const uint8_t FULL_UPDATE_LUT_TTGO_B73[LUT_SIZE_TTGO_B73] = { 0xA0, 0x90, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x90, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x90, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x90, 0xA0, 0x00, @@ -55,20 +72,15 @@ static const uint8_t PARTIAL_UPDATE_LUT_TTGO_B73[LUT_SIZE_TTGO_B73] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -static const uint8_t PARTIAL_UPDATE_LUT_TTGO[LUT_SIZE_TTGO] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT0: BB: VS 0 ~7 - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT1: BW: VS 0 ~7 - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT2: WB: VS 0 ~7 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT3: WW: VS 0 ~7 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT4: VCOM: VS 0 ~7 - 0x0A, 0x00, 0x00, 0x00, 0x00, // TP0 A~D RP0 - 0x00, 0x00, 0x00, 0x00, 0x00, // TP1 A~D RP1 - 0x00, 0x00, 0x00, 0x00, 0x00, // TP2 A~D RP2 - 0x00, 0x00, 0x00, 0x00, 0x00, // TP3 A~D RP3 - 0x00, 0x00, 0x00, 0x00, 0x00, // TP4 A~D RP4 - 0x00, 0x00, 0x00, 0x00, 0x00, // TP5 A~D RP5 - 0x00, 0x00, 0x00, 0x00, 0x00, // TP6 A~D RP6 -}; +static const uint8_t LUT_SIZE_TTGO_B1 = 29; + +static const uint8_t FULL_UPDATE_LUT_TTGO_B1[LUT_SIZE_TTGO_B1] = { + 0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x01, 0x00, 0x00, 0x00, 0x00}; + +static const uint8_t PARTIAL_UPDATE_LUT_TTGO_B1[LUT_SIZE_TTGO_B1] = { + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; void WaveshareEPaper::setup_pins_() { this->init_internal_(this->get_buffer_length_()); @@ -103,7 +115,7 @@ bool WaveshareEPaper::wait_until_idle_() { const uint32_t start = millis(); while (this->busy_pin_->digital_read()) { - if (millis() - start > 1000) { + if (millis() - start > this->idle_timeout_()) { ESP_LOGE(TAG, "Timeout while displaying image!"); return false; } @@ -177,13 +189,19 @@ void WaveshareEPaperTypeA::initialize() { // COMMAND DATA ENTRY MODE SETTING this->command(0x11); - this->data(0x03); // from top left to bottom right - - if (this->model_ == WAVESHARE_EPAPER_2_9_IN_V2) { - // RAM content option for Display Update - this->command(0x21); - this->data(0x00); - this->data(0x80); + switch (this->model_) { + case TTGO_EPAPER_2_13_IN_B1: + this->data(0x01); // x increase, y decrease : as in demo code + break; + case WAVESHARE_EPAPER_2_9_IN_V2: + this->data(0x03); // from top left to bottom right + // RAM content option for Display Update + this->command(0x21); + this->data(0x00); + this->data(0x80); + break; + default: + this->data(0x03); // from top left to bottom right } } void WaveshareEPaperTypeA::dump_config() { @@ -201,6 +219,9 @@ void WaveshareEPaperTypeA::dump_config() { case TTGO_EPAPER_2_13_IN_B73: ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B73)"); break; + case TTGO_EPAPER_2_13_IN_B1: + ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B1)"); + break; case WAVESHARE_EPAPER_2_9_IN: ESP_LOGCONFIG(TAG, " Model: 2.9in"); break; @@ -225,36 +246,67 @@ void HOT WaveshareEPaperTypeA::display() { if (this->full_update_every_ >= 1) { if (full_update != prev_full_update) { - if (this->model_ == TTGO_EPAPER_2_13_IN) { - this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO : PARTIAL_UPDATE_LUT_TTGO, LUT_SIZE_TTGO); - } else if (this->model_ == TTGO_EPAPER_2_13_IN_B73) { - this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO_B73 : PARTIAL_UPDATE_LUT_TTGO_B73, LUT_SIZE_TTGO_B73); - } else { - this->write_lut_(full_update ? FULL_UPDATE_LUT : PARTIAL_UPDATE_LUT, LUT_SIZE_WAVESHARE); + switch (this->model_) { + case TTGO_EPAPER_2_13_IN: + this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO : PARTIAL_UPDATE_LUT_TTGO, LUT_SIZE_TTGO); + break; + case TTGO_EPAPER_2_13_IN_B73: + this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO_B73 : PARTIAL_UPDATE_LUT_TTGO_B73, LUT_SIZE_TTGO_B73); + break; + case TTGO_EPAPER_2_13_IN_B1: + this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO_B1 : PARTIAL_UPDATE_LUT_TTGO_B1, LUT_SIZE_TTGO_B1); + break; + default: + this->write_lut_(full_update ? FULL_UPDATE_LUT : PARTIAL_UPDATE_LUT, LUT_SIZE_WAVESHARE); } } this->at_update_ = (this->at_update_ + 1) % this->full_update_every_; } // Set x & y regions we want to write to (full) - // COMMAND SET RAM X ADDRESS START END POSITION - this->command(0x44); - this->data(0x00); - this->data((this->get_width_internal() - 1) >> 3); - // COMMAND SET RAM Y ADDRESS START END POSITION - this->command(0x45); - this->data(0x00); - this->data(0x00); - this->data(this->get_height_internal() - 1); - this->data((this->get_height_internal() - 1) >> 8); + switch (this->model_) { + case TTGO_EPAPER_2_13_IN_B1: + // COMMAND SET RAM X ADDRESS START END POSITION + this->command(0x44); + this->data(0x00); + this->data((this->get_width_internal() - 1) >> 3); + // COMMAND SET RAM Y ADDRESS START END POSITION + this->command(0x45); + this->data(this->get_height_internal() - 1); + this->data((this->get_height_internal() - 1) >> 8); + this->data(0x00); + this->data(0x00); - // COMMAND SET RAM X ADDRESS COUNTER - this->command(0x4E); - this->data(0x00); - // COMMAND SET RAM Y ADDRESS COUNTER - this->command(0x4F); - this->data(0x00); - this->data(0x00); + // COMMAND SET RAM X ADDRESS COUNTER + this->command(0x4E); + this->data(0x00); + // COMMAND SET RAM Y ADDRESS COUNTER + this->command(0x4F); + this->data(this->get_height_internal() - 1); + this->data((this->get_height_internal() - 1) >> 8); + + break; + + default: + // COMMAND SET RAM X ADDRESS START END POSITION + this->command(0x44); + this->data(0x00); + this->data((this->get_width_internal() - 1) >> 3); + // COMMAND SET RAM Y ADDRESS START END POSITION + this->command(0x45); + this->data(0x00); + this->data(0x00); + this->data(this->get_height_internal() - 1); + this->data((this->get_height_internal() - 1) >> 8); + + // COMMAND SET RAM X ADDRESS COUNTER + this->command(0x4E); + this->data(0x00); + // COMMAND SET RAM Y ADDRESS COUNTER + this->command(0x4F); + this->data(0x00); + this->data(0x00); + } if (!this->wait_until_idle_()) { this->status_set_warning(); @@ -264,7 +316,20 @@ void HOT WaveshareEPaperTypeA::display() { // COMMAND WRITE RAM this->command(0x24); this->start_data_(); - this->write_array(this->buffer_, this->get_buffer_length_()); + switch (this->model_) { + case TTGO_EPAPER_2_13_IN_B1: { // block needed because of variable initializations + int16_t wb = ((this->get_width_internal()) >> 3); + for (int i = 0; i < this->get_height_internal(); i++) { + for (int j = 0; j < wb; j++) { + int idx = j + (this->get_height_internal() - 1 - i) * wb; + this->write_byte(this->buffer_[idx]); + } + } + break; + } + default: + this->write_array(this->buffer_, this->get_buffer_length_()); + } this->end_data_(); // COMMAND DISPLAY UPDATE CONTROL 2 @@ -294,6 +359,8 @@ int WaveshareEPaperTypeA::get_width_internal() { return 128; case TTGO_EPAPER_2_13_IN_B73: return 128; + case TTGO_EPAPER_2_13_IN_B1: + return 128; case WAVESHARE_EPAPER_2_9_IN: return 128; case WAVESHARE_EPAPER_2_9_IN_V2: @@ -311,6 +378,8 @@ int WaveshareEPaperTypeA::get_height_internal() { return 250; case TTGO_EPAPER_2_13_IN_B73: return 250; + case TTGO_EPAPER_2_13_IN_B1: + return 250; case WAVESHARE_EPAPER_2_9_IN: return 296; case WAVESHARE_EPAPER_2_9_IN_V2: @@ -329,6 +398,16 @@ void WaveshareEPaperTypeA::set_full_update_every(uint32_t full_update_every) { this->full_update_every_ = full_update_every; } +int WaveshareEPaperTypeA::idle_timeout_() { + switch (this->model_) { + case TTGO_EPAPER_2_13_IN_B1: + return 2500; + break; + default: + return WaveshareEPaper::idle_timeout_(); + } +} + // ======================================================== // Type B // ======================================================== diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.h b/esphome/components/waveshare_epaper/waveshare_epaper.h index 8ea73d053a..0b8958e7f0 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.h +++ b/esphome/components/waveshare_epaper/waveshare_epaper.h @@ -61,6 +61,7 @@ class WaveshareEPaper : public PollingComponent, GPIOPin *reset_pin_{nullptr}; GPIOPin *dc_pin_; GPIOPin *busy_pin_{nullptr}; + virtual int idle_timeout_() { return 1000; } // NOLINT(readability-identifier-naming) }; enum WaveshareEPaperTypeAModel { @@ -70,6 +71,7 @@ enum WaveshareEPaperTypeAModel { WAVESHARE_EPAPER_2_9_IN_V2, TTGO_EPAPER_2_13_IN, TTGO_EPAPER_2_13_IN_B73, + TTGO_EPAPER_2_13_IN_B1, }; class WaveshareEPaperTypeA : public WaveshareEPaper { @@ -106,6 +108,7 @@ class WaveshareEPaperTypeA : public WaveshareEPaper { uint32_t full_update_every_{30}; uint32_t at_update_{0}; WaveshareEPaperTypeAModel model_; + int idle_timeout_() override; }; enum WaveshareEPaperTypeBModel { diff --git a/tests/test1.yaml b/tests/test1.yaml index f5354231b4..f08cea7770 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -1887,24 +1887,6 @@ display: reset_pin: GPIO23 lambda: |- it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: waveshare_epaper - cs_pin: GPIO23 - dc_pin: GPIO23 - busy_pin: GPIO23 - reset_pin: GPIO23 - model: 2.90in - full_update_every: 30 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - - platform: waveshare_epaper - cs_pin: GPIO23 - dc_pin: GPIO23 - busy_pin: GPIO23 - reset_pin: GPIO23 - model: 2.90inv2 - full_update_every: 30 - lambda: |- - it.rectangle(0, 0, it.get_width(), it.get_height()); - platform: st7789v cs_pin: GPIO5 dc_pin: GPIO16 diff --git a/tests/test4.yaml b/tests/test4.yaml index 1f6eb5442b..ed63a1ac14 100644 --- a/tests/test4.yaml +++ b/tests/test4.yaml @@ -132,3 +132,31 @@ display: it.rectangle(3, 3, it.get_width()-6, it.get_height()-6, red); rotation: 0° update_interval: 16ms + - platform: waveshare_epaper + cs_pin: GPIO23 + dc_pin: GPIO23 + busy_pin: GPIO23 + reset_pin: GPIO23 + model: 2.13in-ttgo-b1 + full_update_every: 30 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: GPIO23 + dc_pin: GPIO23 + busy_pin: GPIO23 + reset_pin: GPIO23 + model: 2.90in + full_update_every: 30 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); + - platform: waveshare_epaper + cs_pin: GPIO23 + dc_pin: GPIO23 + busy_pin: GPIO23 + reset_pin: GPIO23 + model: 2.90inv2 + full_update_every: 30 + lambda: |- + it.rectangle(0, 0, it.get_width(), it.get_height()); +