mirror of
https://github.com/Threnklyn/esphome-dev.git
synced 2026-05-19 20:53:26 +02:00
bab0ba9c0f
* Change buffer sending process for waveshare_epaper (2.70in) The current way ESPhome sending buffer to WaveshareEPaper2P7In does not show the expected content on the display, this commit is changing the data transferring process so the content is showing as expected. The process is adapted from the demo code provided by Waveshare, manufacturer of the E-paper display. * Fix linting eror
757 lines
24 KiB
C++
757 lines
24 KiB
C++
#include "waveshare_epaper.h"
|
|
#include "esphome/core/log.h"
|
|
#include "esphome/core/application.h"
|
|
#include "esphome/core/helpers.h"
|
|
|
|
namespace esphome {
|
|
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};
|
|
|
|
static const uint8_t PARTIAL_UPDATE_LUT[LUT_SIZE_WAVESHARE] = {
|
|
0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
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
|
|
0x10, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, // LUT1: BW: VS 0 ~7
|
|
0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, // LUT2: WB: VS 0 ~7
|
|
0x10, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, // LUT3: WW: VS 0 ~7
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT4: VCOM: VS 0 ~7
|
|
0x03, 0x03, 0x00, 0x00, 0x02, // TP0 A~D RP0
|
|
0x09, 0x09, 0x00, 0x00, 0x02, // TP1 A~D RP1
|
|
0x03, 0x03, 0x00, 0x00, 0x02, // 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 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,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x03, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
|
|
static const uint8_t PARTIAL_UPDATE_LUT_TTGO_B73[LUT_SIZE_TTGO_B73] = {
|
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
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
|
|
};
|
|
|
|
void WaveshareEPaper::setup_pins_() {
|
|
this->init_internal_(this->get_buffer_length_());
|
|
this->dc_pin_->setup(); // OUTPUT
|
|
this->dc_pin_->digital_write(false);
|
|
if (this->reset_pin_ != nullptr) {
|
|
this->reset_pin_->setup(); // OUTPUT
|
|
this->reset_pin_->digital_write(true);
|
|
}
|
|
if (this->busy_pin_ != nullptr) {
|
|
this->busy_pin_->setup(); // INPUT
|
|
}
|
|
this->spi_setup();
|
|
|
|
this->reset_();
|
|
}
|
|
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 WaveshareEPaper::data(uint8_t value) {
|
|
this->start_data_();
|
|
this->write_byte(value);
|
|
this->end_data_();
|
|
}
|
|
bool WaveshareEPaper::wait_until_idle_() {
|
|
if (this->busy_pin_ == nullptr) {
|
|
return true;
|
|
}
|
|
|
|
const uint32_t start = millis();
|
|
while (this->busy_pin_->digital_read()) {
|
|
if (millis() - start > 1000) {
|
|
ESP_LOGE(TAG, "Timeout while displaying image!");
|
|
return false;
|
|
}
|
|
delay(10);
|
|
}
|
|
return true;
|
|
}
|
|
void WaveshareEPaper::update() {
|
|
this->do_update_();
|
|
this->display();
|
|
}
|
|
void WaveshareEPaper::fill(int color) {
|
|
// flip logic
|
|
const uint8_t fill = color ? 0x00 : 0xFF;
|
|
for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
|
|
this->buffer_[i] = fill;
|
|
}
|
|
void HOT WaveshareEPaper::draw_absolute_pixel_internal(int x, int y, int color) {
|
|
if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
|
|
return;
|
|
|
|
const uint32_t pos = (x + y * this->get_width_internal()) / 8u;
|
|
const uint8_t subpos = x & 0x07;
|
|
// flip logic
|
|
if (!color)
|
|
this->buffer_[pos] |= 0x80 >> subpos;
|
|
else
|
|
this->buffer_[pos] &= ~(0x80 >> subpos);
|
|
}
|
|
uint32_t WaveshareEPaper::get_buffer_length_() { return this->get_width_internal() * this->get_height_internal() / 8u; }
|
|
void WaveshareEPaper::start_command_() {
|
|
this->dc_pin_->digital_write(false);
|
|
this->enable();
|
|
}
|
|
void WaveshareEPaper::end_command_() { this->disable(); }
|
|
void WaveshareEPaper::start_data_() {
|
|
this->dc_pin_->digital_write(true);
|
|
this->enable();
|
|
}
|
|
void WaveshareEPaper::end_data_() { this->disable(); }
|
|
void WaveshareEPaper::on_safe_shutdown() { this->deep_sleep(); }
|
|
|
|
// ========================================================
|
|
// Type A
|
|
// ========================================================
|
|
|
|
void WaveshareEPaperTypeA::initialize() {
|
|
// COMMAND DRIVER OUTPUT CONTROL
|
|
this->command(0x01);
|
|
this->data(this->get_height_internal() - 1);
|
|
this->data((this->get_height_internal() - 1) >> 8);
|
|
this->data(0x00); // ? GD = 0, SM = 0, TB = 0
|
|
|
|
// COMMAND BOOSTER SOFT START CONTROL
|
|
this->command(0x0C);
|
|
this->data(0xD7);
|
|
this->data(0xD6);
|
|
this->data(0x9D);
|
|
|
|
// COMMAND WRITE VCOM REGISTER
|
|
this->command(0x2C);
|
|
this->data(0xA8);
|
|
|
|
// COMMAND SET DUMMY LINE PERIOD
|
|
this->command(0x3A);
|
|
this->data(0x1A);
|
|
|
|
// COMMAND SET GATE TIME
|
|
this->command(0x3B);
|
|
this->data(0x08); // 2µs per row
|
|
|
|
// COMMAND DATA ENTRY MODE SETTING
|
|
this->command(0x11);
|
|
this->data(0x03); // from top left to bottom right
|
|
}
|
|
void WaveshareEPaperTypeA::dump_config() {
|
|
LOG_DISPLAY("", "Waveshare E-Paper", this);
|
|
switch (this->model_) {
|
|
case WAVESHARE_EPAPER_1_54_IN:
|
|
ESP_LOGCONFIG(TAG, " Model: 1.54in");
|
|
break;
|
|
case WAVESHARE_EPAPER_2_13_IN:
|
|
ESP_LOGCONFIG(TAG, " Model: 2.13in");
|
|
break;
|
|
case TTGO_EPAPER_2_13_IN:
|
|
ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO)");
|
|
break;
|
|
case TTGO_EPAPER_2_13_IN_B73:
|
|
ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B73)");
|
|
break;
|
|
case WAVESHARE_EPAPER_2_9_IN:
|
|
ESP_LOGCONFIG(TAG, " Model: 2.9in");
|
|
break;
|
|
}
|
|
ESP_LOGCONFIG(TAG, " Full Update Every: %u", this->full_update_every_);
|
|
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 HOT WaveshareEPaperTypeA::display() {
|
|
if (!this->wait_until_idle_()) {
|
|
this->status_set_warning();
|
|
return;
|
|
}
|
|
|
|
if (this->full_update_every_ >= 2) {
|
|
bool prev_full_update = this->at_update_ == 1;
|
|
bool full_update = this->at_update_ == 0;
|
|
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);
|
|
}
|
|
}
|
|
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);
|
|
|
|
// 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();
|
|
return;
|
|
}
|
|
|
|
// COMMAND WRITE RAM
|
|
this->command(0x24);
|
|
this->start_data_();
|
|
this->write_array(this->buffer_, this->get_buffer_length_());
|
|
this->end_data_();
|
|
|
|
// COMMAND DISPLAY UPDATE CONTROL 2
|
|
this->command(0x22);
|
|
this->data(0xC4);
|
|
// COMMAND MASTER ACTIVATION
|
|
this->command(0x20);
|
|
// COMMAND TERMINATE FRAME READ WRITE
|
|
this->command(0xFF);
|
|
|
|
this->status_clear_warning();
|
|
}
|
|
int WaveshareEPaperTypeA::get_width_internal() {
|
|
switch (this->model_) {
|
|
case WAVESHARE_EPAPER_1_54_IN:
|
|
return 200;
|
|
case WAVESHARE_EPAPER_2_13_IN:
|
|
return 128;
|
|
case TTGO_EPAPER_2_13_IN:
|
|
return 128;
|
|
case TTGO_EPAPER_2_13_IN_B73:
|
|
return 128;
|
|
case WAVESHARE_EPAPER_2_9_IN:
|
|
return 128;
|
|
}
|
|
return 0;
|
|
}
|
|
int WaveshareEPaperTypeA::get_height_internal() {
|
|
switch (this->model_) {
|
|
case WAVESHARE_EPAPER_1_54_IN:
|
|
return 200;
|
|
case WAVESHARE_EPAPER_2_13_IN:
|
|
return 250;
|
|
case TTGO_EPAPER_2_13_IN:
|
|
return 250;
|
|
case TTGO_EPAPER_2_13_IN_B73:
|
|
return 250;
|
|
case WAVESHARE_EPAPER_2_9_IN:
|
|
return 296;
|
|
}
|
|
return 0;
|
|
}
|
|
void WaveshareEPaperTypeA::write_lut_(const uint8_t *lut, const uint8_t size) {
|
|
// COMMAND WRITE LUT REGISTER
|
|
this->command(0x32);
|
|
for (uint8_t i = 0; i < size; i++)
|
|
this->data(lut[i]);
|
|
}
|
|
WaveshareEPaperTypeA::WaveshareEPaperTypeA(WaveshareEPaperTypeAModel model) : model_(model) {}
|
|
void WaveshareEPaperTypeA::set_full_update_every(uint32_t full_update_every) {
|
|
this->full_update_every_ = full_update_every;
|
|
}
|
|
|
|
// ========================================================
|
|
// Type B
|
|
// ========================================================
|
|
// Datasheet:
|
|
// - https://www.waveshare.com/w/upload/7/7f/4.2inch-e-paper-b-specification.pdf
|
|
// - https://github.com/soonuse/epd-library-arduino/blob/master/4.2inch_e-paper/epd4in2/
|
|
|
|
static const uint8_t LUT_VCOM_DC_2_7[44] = {
|
|
0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x00, 0x32, 0x32, 0x00, 0x00, 0x02, 0x00,
|
|
0x0F, 0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
|
|
static const uint8_t LUT_WHITE_TO_WHITE_2_7[42] = {
|
|
0x50, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0xA0, 0x0F,
|
|
0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
|
|
static const uint8_t LUT_BLACK_TO_WHITE_2_7[42] = {
|
|
0x50, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0xA0, 0x0F,
|
|
0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
|
|
static const uint8_t LUT_WHITE_TO_BLACK_2_7[] = {
|
|
0xA0, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0x50, 0x0F,
|
|
0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
|
|
static const uint8_t LUT_BLACK_TO_BLACK_2_7[42] = {
|
|
0xA0, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0x50, 0x0F,
|
|
0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
|
|
void WaveshareEPaper2P7In::initialize() {
|
|
// command power setting
|
|
this->command(0x01);
|
|
this->data(0x03); // VDS_EN, VDG_EN
|
|
this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
|
|
this->data(0x2B); // VDH
|
|
this->data(0x2B); // VDL
|
|
this->data(0x09); // VDHR
|
|
|
|
// command booster soft start
|
|
this->command(0x06);
|
|
this->data(0x07);
|
|
this->data(0x07);
|
|
this->data(0x17);
|
|
|
|
// Power optimization - ???
|
|
this->command(0xF8);
|
|
this->data(0x60);
|
|
this->data(0xA5);
|
|
this->command(0xF8);
|
|
this->data(0x89);
|
|
this->data(0xA5);
|
|
this->command(0xF8);
|
|
this->data(0x90);
|
|
this->data(0x00);
|
|
this->command(0xF8);
|
|
this->data(0x93);
|
|
this->data(0x2A);
|
|
this->command(0xF8);
|
|
this->data(0xA0);
|
|
this->data(0xA5);
|
|
this->command(0xF8);
|
|
this->data(0xA1);
|
|
this->data(0x00);
|
|
this->command(0xF8);
|
|
this->data(0x73);
|
|
this->data(0x41);
|
|
|
|
// command partial display refresh
|
|
this->command(0x16);
|
|
this->data(0x00);
|
|
|
|
// command power on
|
|
this->command(0x04);
|
|
this->wait_until_idle_();
|
|
delay(10);
|
|
|
|
// Command panel setting
|
|
this->command(0x00);
|
|
this->data(0xAF); // KW-BF KWR-AF BWROTP 0f
|
|
// command pll control
|
|
this->command(0x30);
|
|
this->data(0x3A); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
|
|
// COMMAND VCM DC SETTING
|
|
this->command(0x82);
|
|
this->data(0x12);
|
|
|
|
delay(2);
|
|
// COMMAND LUT FOR VCOM
|
|
this->command(0x20);
|
|
for (uint8_t i : LUT_VCOM_DC_2_7)
|
|
this->data(i);
|
|
|
|
// COMMAND LUT WHITE TO WHITE
|
|
this->command(0x21);
|
|
for (uint8_t i : LUT_WHITE_TO_WHITE_2_7)
|
|
this->data(i);
|
|
// COMMAND LUT BLACK TO WHITE
|
|
this->command(0x22);
|
|
for (uint8_t i : LUT_BLACK_TO_WHITE_2_7)
|
|
this->data(i);
|
|
// COMMAND LUT WHITE TO BLACK
|
|
this->command(0x23);
|
|
for (uint8_t i : LUT_WHITE_TO_BLACK_2_7)
|
|
this->data(i);
|
|
// COMMAND LUT BLACK TO BLACK
|
|
this->command(0x24);
|
|
for (uint8_t i : LUT_BLACK_TO_BLACK_2_7)
|
|
this->data(i);
|
|
}
|
|
void HOT WaveshareEPaper2P7In::display() {
|
|
uint32_t buf_len = this->get_buffer_length_();
|
|
|
|
// COMMAND DATA START TRANSMISSION 1
|
|
this->command(0x10);
|
|
delay(2);
|
|
for (uint32_t i = 0; i < buf_len; i++) {
|
|
this->data(this->buffer_[i]);
|
|
}
|
|
delay(2);
|
|
|
|
// COMMAND DATA START TRANSMISSION 2
|
|
this->command(0x13);
|
|
delay(2);
|
|
for (uint32_t i = 0; i < buf_len; i++) {
|
|
this->data(this->buffer_[i]);
|
|
}
|
|
|
|
// COMMAND DISPLAY REFRESH
|
|
this->command(0x12);
|
|
}
|
|
int WaveshareEPaper2P7In::get_width_internal() { return 176; }
|
|
int WaveshareEPaper2P7In::get_height_internal() { return 264; }
|
|
void WaveshareEPaper2P7In::dump_config() {
|
|
LOG_DISPLAY("", "Waveshare E-Paper", this);
|
|
ESP_LOGCONFIG(TAG, " Model: 2.7in");
|
|
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);
|
|
}
|
|
|
|
// ========================================================
|
|
// 2.90in Type B (LUT from OTP)
|
|
// Datasheet:
|
|
// - https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf
|
|
// - https://github.com/soonuse/epd-library-arduino/blob/master/2.9inch_e-paper_b/epd2in9b/epd2in9b.cpp
|
|
// ========================================================
|
|
|
|
void WaveshareEPaper2P9InB::initialize() {
|
|
// from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37
|
|
// EPD hardware init start
|
|
this->reset_();
|
|
|
|
// COMMAND BOOSTER SOFT START
|
|
this->command(0x06);
|
|
this->data(0x17);
|
|
this->data(0x17);
|
|
this->data(0x17);
|
|
|
|
// COMMAND POWER ON
|
|
this->command(0x04);
|
|
this->wait_until_idle_();
|
|
|
|
// COMMAND PANEL SETTING
|
|
this->command(0x00);
|
|
// 128x296 resolution: 10
|
|
// LUT from OTP: 0
|
|
// B/W mode (doesn't work): 1
|
|
// scan-up: 1
|
|
// shift-right: 1
|
|
// booster ON: 1
|
|
// no soft reset: 1
|
|
this->data(0x9F);
|
|
|
|
// COMMAND RESOLUTION SETTING
|
|
// set to 128x296 by COMMAND PANNEL SETTING
|
|
|
|
// COMMAND VCOM AND DATA INTERVAL SETTING
|
|
// use defaults for white border and ESPHome image polarity
|
|
|
|
// EPD hardware init end
|
|
}
|
|
void HOT WaveshareEPaper2P9InB::display() {
|
|
// COMMAND DATA START TRANSMISSION 1 (B/W data)
|
|
this->command(0x10);
|
|
delay(2);
|
|
this->start_data_();
|
|
this->write_array(this->buffer_, this->get_buffer_length_());
|
|
this->end_data_();
|
|
delay(2);
|
|
|
|
// COMMAND DATA START TRANSMISSION 2 (RED data)
|
|
this->command(0x13);
|
|
delay(2);
|
|
this->start_data_();
|
|
for (int i = 0; i < this->get_buffer_length_(); i++)
|
|
this->write_byte(0x00);
|
|
this->end_data_();
|
|
delay(2);
|
|
|
|
// COMMAND DISPLAY REFRESH
|
|
this->command(0x12);
|
|
delay(2);
|
|
this->wait_until_idle_();
|
|
|
|
// COMMAND POWER OFF
|
|
// NOTE: power off < deep sleep
|
|
this->command(0x02);
|
|
}
|
|
int WaveshareEPaper2P9InB::get_width_internal() { return 128; }
|
|
int WaveshareEPaper2P9InB::get_height_internal() { return 296; }
|
|
void WaveshareEPaper2P9InB::dump_config() {
|
|
LOG_DISPLAY("", "Waveshare E-Paper", this);
|
|
ESP_LOGCONFIG(TAG, " Model: 2.9in (B)");
|
|
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);
|
|
}
|
|
|
|
static const uint8_t LUT_VCOM_DC_4_2[] = {
|
|
0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x17, 0x17, 0x00, 0x00, 0x02, 0x00, 0x0A, 0x01,
|
|
0x00, 0x00, 0x01, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
static const uint8_t LUT_WHITE_TO_WHITE_4_2[] = {
|
|
0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A,
|
|
0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
static const uint8_t LUT_BLACK_TO_WHITE_4_2[] = {
|
|
0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A,
|
|
0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
|
|
static const uint8_t LUT_BLACK_TO_BLACK_4_2[] = {
|
|
0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A,
|
|
0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
|
|
static const uint8_t LUT_WHITE_TO_BLACK_4_2[] = {
|
|
0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A,
|
|
0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
|
|
void WaveshareEPaper4P2In::initialize() {
|
|
// https://www.waveshare.com/w/upload/7/7f/4.2inch-e-paper-b-specification.pdf - page 8
|
|
|
|
// COMMAND POWER SETTING
|
|
this->command(0x01);
|
|
this->data(0x03); // VDS_EN, VDG_EN
|
|
this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
|
|
this->data(0x2B); // VDH
|
|
this->data(0x2B); // VDL
|
|
this->data(0xFF); // VDHR
|
|
|
|
// COMMAND BOOSTER SOFT START
|
|
this->command(0x06);
|
|
this->data(0x17); // PHA
|
|
this->data(0x17); // PHB
|
|
this->data(0x17); // PHC
|
|
|
|
// COMMAND POWER ON
|
|
this->command(0x04);
|
|
this->wait_until_idle_();
|
|
delay(10);
|
|
// COMMAND PANEL SETTING
|
|
this->command(0x00);
|
|
this->data(0xBF); // KW-BF KWR-AF BWROTP 0f
|
|
this->data(0x0B);
|
|
// COMMAND PLL CONTROL
|
|
this->command(0x30);
|
|
this->data(0x3C); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
|
|
|
|
delay(2);
|
|
// COMMAND LUT FOR VCOM
|
|
this->command(0x20);
|
|
for (uint8_t i : LUT_VCOM_DC_4_2)
|
|
this->data(i);
|
|
// COMMAND LUT WHITE TO WHITE
|
|
this->command(0x21);
|
|
for (uint8_t i : LUT_WHITE_TO_WHITE_4_2)
|
|
this->data(i);
|
|
// COMMAND LUT BLACK TO WHITE
|
|
this->command(0x22);
|
|
for (uint8_t i : LUT_BLACK_TO_WHITE_4_2)
|
|
this->data(i);
|
|
// COMMAND LUT WHITE TO BLACK
|
|
this->command(0x23);
|
|
for (uint8_t i : LUT_WHITE_TO_BLACK_4_2)
|
|
this->data(i);
|
|
// COMMAND LUT BLACK TO BLACK
|
|
this->command(0x24);
|
|
for (uint8_t i : LUT_BLACK_TO_BLACK_4_2)
|
|
this->data(i);
|
|
}
|
|
void HOT WaveshareEPaper4P2In::display() {
|
|
// COMMAND RESOLUTION SETTING
|
|
this->command(0x61);
|
|
this->data(0x01);
|
|
this->data(0x90);
|
|
this->data(0x01);
|
|
this->data(0x2C);
|
|
|
|
// COMMAND VCM DC SETTING REGISTER
|
|
this->command(0x82);
|
|
this->data(0x12);
|
|
|
|
// COMMAND VCOM AND DATA INTERVAL SETTING
|
|
this->command(0x50);
|
|
this->data(0x97);
|
|
|
|
// COMMAND DATA START TRANSMISSION 1
|
|
this->command(0x10);
|
|
delay(2);
|
|
this->start_data_();
|
|
this->write_array(this->buffer_, this->get_buffer_length_());
|
|
this->end_data_();
|
|
delay(2);
|
|
// COMMAND DATA START TRANSMISSION 2
|
|
this->command(0x13);
|
|
delay(2);
|
|
this->start_data_();
|
|
this->write_array(this->buffer_, this->get_buffer_length_());
|
|
this->end_data_();
|
|
// COMMAND DISPLAY REFRESH
|
|
this->command(0x12);
|
|
}
|
|
int WaveshareEPaper4P2In::get_width_internal() { return 400; }
|
|
int WaveshareEPaper4P2In::get_height_internal() { return 300; }
|
|
void WaveshareEPaper4P2In::dump_config() {
|
|
LOG_DISPLAY("", "Waveshare E-Paper", this);
|
|
ESP_LOGCONFIG(TAG, " Model: 4.2in");
|
|
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 WaveshareEPaper7P5In::initialize() {
|
|
// COMMAND POWER SETTING
|
|
this->command(0x01);
|
|
this->data(0x37);
|
|
this->data(0x00);
|
|
|
|
// COMMAND PANEL SETTING
|
|
this->command(0x00);
|
|
this->data(0xCF);
|
|
this->data(0x0B);
|
|
|
|
// COMMAND BOOSTER SOFT START
|
|
this->command(0x06);
|
|
this->data(0xC7);
|
|
this->data(0xCC);
|
|
this->data(0x28);
|
|
|
|
// COMMAND POWER ON
|
|
this->command(0x04);
|
|
this->wait_until_idle_();
|
|
delay(10);
|
|
|
|
// COMMAND PLL CONTROL
|
|
this->command(0x30);
|
|
this->data(0x3C);
|
|
|
|
// COMMAND TEMPERATURE SENSOR CALIBRATION
|
|
this->command(0x41);
|
|
this->data(0x00);
|
|
|
|
// COMMAND VCOM AND DATA INTERVAL SETTING
|
|
this->command(0x50);
|
|
this->data(0x77);
|
|
|
|
// COMMAND TCON SETTING
|
|
this->command(0x60);
|
|
this->data(0x22);
|
|
|
|
// COMMAND RESOLUTION SETTING
|
|
this->command(0x61);
|
|
this->data(0x02);
|
|
this->data(0x80);
|
|
this->data(0x01);
|
|
this->data(0x80);
|
|
|
|
// COMMAND VCM DC SETTING REGISTER
|
|
this->command(0x82);
|
|
this->data(0x1E);
|
|
|
|
this->command(0xE5);
|
|
this->data(0x03);
|
|
}
|
|
void HOT WaveshareEPaper7P5In::display() {
|
|
// COMMAND DATA START TRANSMISSION 1
|
|
this->command(0x10);
|
|
|
|
this->start_data_();
|
|
for (size_t i = 0; i < this->get_buffer_length_(); i++) {
|
|
uint8_t temp1 = this->buffer_[i];
|
|
for (uint8_t j = 0; j < 8; j++) {
|
|
uint8_t temp2;
|
|
if (temp1 & 0x80)
|
|
temp2 = 0x03;
|
|
else
|
|
temp2 = 0x00;
|
|
|
|
temp2 <<= 4;
|
|
temp1 <<= 1;
|
|
j++;
|
|
if (temp1 & 0x80)
|
|
temp2 |= 0x03;
|
|
else
|
|
temp2 |= 0x00;
|
|
temp1 <<= 1;
|
|
this->write_byte(temp2);
|
|
}
|
|
|
|
App.feed_wdt();
|
|
}
|
|
this->end_data_();
|
|
|
|
// COMMAND DISPLAY REFRESH
|
|
this->command(0x12);
|
|
}
|
|
int WaveshareEPaper7P5In::get_width_internal() { return 640; }
|
|
int WaveshareEPaper7P5In::get_height_internal() { return 384; }
|
|
void WaveshareEPaper7P5In::dump_config() {
|
|
LOG_DISPLAY("", "Waveshare E-Paper", this);
|
|
ESP_LOGCONFIG(TAG, " Model: 7.5in");
|
|
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);
|
|
}
|
|
|
|
} // namespace waveshare_epaper
|
|
} // namespace esphome
|