ESPHome  2025.2.0
waveshare_epaper.cpp
Go to the documentation of this file.
1 #include "waveshare_epaper.h"
2 #include "esphome/core/log.h"
4 #include "esphome/core/helpers.h"
5 #include <cinttypes>
6 #include <bitset>
7 
8 namespace esphome {
9 namespace waveshare_epaper {
10 
11 static const char *const TAG = "waveshare_epaper";
12 
13 static const uint8_t LUT_SIZE_WAVESHARE = 30;
14 
15 static const uint8_t FULL_UPDATE_LUT[LUT_SIZE_WAVESHARE] = {0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22, 0x66, 0x69,
16  0x69, 0x59, 0x58, 0x99, 0x99, 0x88, 0x00, 0x00, 0x00, 0x00,
17  0xF8, 0xB4, 0x13, 0x51, 0x35, 0x51, 0x51, 0x19, 0x01, 0x00};
18 
19 static const uint8_t PARTIAL_UPDATE_LUT[LUT_SIZE_WAVESHARE] = {
20  0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21  0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
22 
23 static const uint8_t LUT_SIZE_TTGO = 70;
24 
25 static const uint8_t FULL_UPDATE_LUT_TTGO[LUT_SIZE_TTGO] = {
26  0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, // LUT0: BB: VS 0 ~7
27  0x10, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, // LUT1: BW: VS 0 ~7
28  0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, // LUT2: WB: VS 0 ~7
29  0x10, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, // LUT3: WW: VS 0 ~7
30  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT4: VCOM: VS 0 ~7
31  0x03, 0x03, 0x00, 0x00, 0x02, // TP0 A~D RP0
32  0x09, 0x09, 0x00, 0x00, 0x02, // TP1 A~D RP1
33  0x03, 0x03, 0x00, 0x00, 0x02, // TP2 A~D RP2
34  0x00, 0x00, 0x00, 0x00, 0x00, // TP3 A~D RP3
35  0x00, 0x00, 0x00, 0x00, 0x00, // TP4 A~D RP4
36  0x00, 0x00, 0x00, 0x00, 0x00, // TP5 A~D RP5
37  0x00, 0x00, 0x00, 0x00, 0x00, // TP6 A~D RP6
38 };
39 
40 static const uint8_t PARTIAL_UPDATE_LUT_TTGO[LUT_SIZE_TTGO] = {
41  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT0: BB: VS 0 ~7
42  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT1: BW: VS 0 ~7
43  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT2: WB: VS 0 ~7
44  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT3: WW: VS 0 ~7
45  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT4: VCOM: VS 0 ~7
46  0x0A, 0x00, 0x00, 0x00, 0x00, // TP0 A~D RP0
47  0x00, 0x00, 0x00, 0x00, 0x00, // TP1 A~D RP1
48  0x00, 0x00, 0x00, 0x00, 0x00, // TP2 A~D RP2
49  0x00, 0x00, 0x00, 0x00, 0x00, // TP3 A~D RP3
50  0x00, 0x00, 0x00, 0x00, 0x00, // TP4 A~D RP4
51  0x00, 0x00, 0x00, 0x00, 0x00, // TP5 A~D RP5
52  0x00, 0x00, 0x00, 0x00, 0x00, // TP6 A~D RP6
53 };
54 
55 static const uint8_t LUT_SIZE_TTGO_B73 = 100;
56 
57 static const uint8_t FULL_UPDATE_LUT_TTGO_B73[LUT_SIZE_TTGO_B73] = {
58  0xA0, 0x90, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x90, 0xA0, 0x00, 0x00, 0x00, 0x00,
59  0x00, 0x00, 0x00, 0xA0, 0x90, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x90, 0xA0, 0x00,
60  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 
62  0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x03, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
63  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 };
66 
67 static const uint8_t PARTIAL_UPDATE_LUT_TTGO_B73[LUT_SIZE_TTGO_B73] = {
68  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69  0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
70  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 
72  0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 };
76 
77 static const uint8_t LUT_SIZE_TTGO_B1 = 29;
78 
79 static const uint8_t FULL_UPDATE_LUT_TTGO_B1[LUT_SIZE_TTGO_B1] = {
80  0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81  0x00, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x01, 0x00, 0x00, 0x00, 0x00};
82 
83 static const uint8_t PARTIAL_UPDATE_LUT_TTGO_B1[LUT_SIZE_TTGO_B1] = {
84  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85  0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
86 
87 // clang-format off
88 // Disable formatting to preserve the same look as in Waveshare examples
89 static const uint8_t PARTIAL_UPD_2IN9_LUT_SIZE = 159;
90 static const uint8_t PARTIAL_UPD_2IN9_LUT[PARTIAL_UPD_2IN9_LUT_SIZE] =
91 {
92  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93  0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94  0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97  0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
98  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00,
110  0x22, 0x17, 0x41, 0xB0, 0x32, 0x36,
111 };
112 // clang-format on
113 
115  this->init_internal_(this->get_buffer_length_());
116  this->setup_pins_();
117  this->spi_setup();
118  this->reset_();
119  this->initialize();
120 }
122  this->dc_pin_->setup(); // OUTPUT
123  this->dc_pin_->digital_write(false);
124  if (this->reset_pin_ != nullptr) {
125  this->reset_pin_->setup(); // OUTPUT
126  this->reset_pin_->digital_write(true);
127  }
128  if (this->busy_pin_ != nullptr) {
129  this->busy_pin_->setup(); // INPUT
130  }
131 }
133 void WaveshareEPaperBase::command(uint8_t value) {
134  this->start_command_();
135  this->write_byte(value);
136  this->end_command_();
137 }
138 void WaveshareEPaperBase::data(uint8_t value) {
139  this->start_data_();
140  this->write_byte(value);
141  this->end_data_();
142 }
143 
144 // write a command followed by one or more bytes of data.
145 // The command is the first byte, length is the total including cmd.
146 void WaveshareEPaperBase::cmd_data(const uint8_t *c_data, size_t length) {
147  this->dc_pin_->digital_write(false);
148  this->enable();
149  this->write_byte(c_data[0]);
150  this->dc_pin_->digital_write(true);
151  this->write_array(c_data + 1, length - 1);
152  this->disable();
153 }
154 
156  if (this->busy_pin_ == nullptr || !this->busy_pin_->digital_read()) {
157  return true;
158  }
159 
160  const uint32_t start = millis();
161  while (this->busy_pin_->digital_read()) {
162  if (millis() - start > this->idle_timeout_()) {
163  ESP_LOGE(TAG, "Timeout while displaying image!");
164  return false;
165  }
166  delay(1);
167  }
168  return true;
169 }
171  this->do_update_();
172  this->display();
173 }
175  // flip logic
176  const uint8_t fill = color.is_on() ? 0x00 : 0xFF;
177  for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
178  this->buffer_[i] = fill;
179 }
181  this->init_internal_7c_(this->get_buffer_length_());
182  this->setup_pins_();
183  this->spi_setup();
184  this->reset_();
185  this->initialize();
186 }
187 void WaveshareEPaper7C::init_internal_7c_(uint32_t buffer_length) {
189  uint32_t small_buffer_length = buffer_length / NUM_BUFFERS;
190 
191  for (int i = 0; i < NUM_BUFFERS; i++) {
192  this->buffers_[i] = allocator.allocate(small_buffer_length);
193  if (this->buffers_[i] == nullptr) {
194  ESP_LOGE(TAG, "Could not allocate buffer %d for display!", i);
195  for (auto &buffer : this->buffers_) {
196  allocator.deallocate(buffer, small_buffer_length);
197  buffer = nullptr;
198  }
199  return;
200  }
201  }
202  this->clear();
203 }
205  uint8_t hex_code;
206  if (color.red > 127) {
207  if (color.green > 170) {
208  if (color.blue > 127) {
209  hex_code = 0x1; // White
210  } else {
211  hex_code = 0x5; // Yellow
212  }
213  } else if (color.green > 85) {
214  hex_code = 0x6; // Orange
215  } else {
216  hex_code = 0x4; // Red (or Magenta)
217  }
218  } else {
219  if (color.green > 127) {
220  if (color.blue > 127) {
221  hex_code = 0x3; // Cyan -> Blue
222  } else {
223  hex_code = 0x2; // Green
224  }
225  } else {
226  if (color.blue > 127) {
227  hex_code = 0x3; // Blue
228  } else {
229  hex_code = 0x0; // Black
230  }
231  }
232  }
233 
234  return hex_code;
235 }
237  uint8_t pixel_color;
238  if (color.is_on()) {
239  pixel_color = this->color_to_hex(color);
240  } else {
241  pixel_color = 0x1;
242  }
243 
244  if (this->buffers_[0] == nullptr) {
245  ESP_LOGE(TAG, "Buffer unavailable!");
246  } else {
247  uint32_t small_buffer_length = this->get_buffer_length_() / NUM_BUFFERS;
248  for (auto &buffer : this->buffers_) {
249  for (uint32_t buffer_pos = 0; buffer_pos < small_buffer_length; buffer_pos += 3) {
250  // We store 8 bitset<3> in 3 bytes
251  // | byte 1 | byte 2 | byte 3 |
252  // |aaabbbaa|abbbaaab|bbaaabbb|
253  buffer[buffer_pos + 0] = pixel_color << 5 | pixel_color << 2 | pixel_color >> 1;
254  buffer[buffer_pos + 1] = pixel_color << 7 | pixel_color << 4 | pixel_color << 1 | pixel_color >> 2;
255  buffer[buffer_pos + 2] = pixel_color << 6 | pixel_color << 3 | pixel_color << 0;
256  }
257  App.feed_wdt();
258  }
259  }
260 }
262  if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
263  return;
264 
265  const uint32_t pos = (x + y * this->get_width_controller()) / 8u;
266  const uint8_t subpos = x & 0x07;
267  // flip logic
268  if (!color.is_on()) {
269  this->buffer_[pos] |= 0x80 >> subpos;
270  } else {
271  this->buffer_[pos] &= ~(0x80 >> subpos);
272  }
273 }
274 
276  return this->get_width_controller() * this->get_height_internal() / 8u;
277 } // just a black buffer
279  return this->get_width_controller() * this->get_height_internal() / 4u;
280 } // black and red buffer
282  return this->get_width_controller() * this->get_height_internal() / 8u * 3u;
283 } // 7 colors buffer, 1 pixel = 3 bits, we will store 8 pixels in 24 bits = 3 bytes
284 
286  this->filled_rectangle(0, 0, this->get_width(), this->get_height(), color);
287 }
289  if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
290  return;
291 
292  const uint32_t buf_half_len = this->get_buffer_length_() / 2u;
293 
294  const uint32_t pos = (x + y * this->get_width_internal()) / 8u;
295  const uint8_t subpos = x & 0x07;
296  // flip logic
297  if (color.is_on()) {
298  this->buffer_[pos] |= 0x80 >> subpos;
299  } else {
300  this->buffer_[pos] &= ~(0x80 >> subpos);
301  }
302 
303  // draw red pixels only, if the color contains red only
304  if (((color.red > 0) && (color.green == 0) && (color.blue == 0))) {
305  this->buffer_[pos + buf_half_len] |= 0x80 >> subpos;
306  } else {
307  this->buffer_[pos + buf_half_len] &= ~(0x80 >> subpos);
308  }
309 }
311  if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
312  return;
313 
314  uint8_t pixel_bits = this->color_to_hex(color);
315  uint32_t small_buffer_length = this->get_buffer_length_() / NUM_BUFFERS;
316  uint32_t pixel_position = x + y * this->get_width_controller();
317  uint32_t first_bit_position = pixel_position * 3;
318  uint32_t byte_position = first_bit_position / 8u;
319  uint32_t byte_subposition = first_bit_position % 8u;
320  uint32_t buffer_position = byte_position / small_buffer_length;
321  uint32_t buffer_subposition = byte_position % small_buffer_length;
322 
323  if (byte_subposition <= 5) {
324  this->buffers_[buffer_position][buffer_subposition] =
325  (this->buffers_[buffer_position][buffer_subposition] & (0xFF ^ (0b111 << (5 - byte_subposition)))) |
326  (pixel_bits << (5 - byte_subposition));
327  } else {
328  this->buffers_[buffer_position][buffer_subposition + 0] =
329  (this->buffers_[buffer_position][buffer_subposition + 0] & (0xFF ^ (0b111 >> (byte_subposition - 5)))) |
330  (pixel_bits >> (byte_subposition - 5));
331 
332  this->buffers_[buffer_position][buffer_subposition + 1] = (this->buffers_[buffer_position][buffer_subposition + 1] &
333  (0xFF ^ (0xFF & (0b111 << (13 - byte_subposition))))) |
334  (pixel_bits << (13 - byte_subposition));
335  }
336 }
338  this->dc_pin_->digital_write(false);
339  this->enable();
340 }
343  this->dc_pin_->digital_write(true);
344  this->enable();
345 }
348 
349 // ========================================================
350 // Type A
351 // ========================================================
352 
354  // Achieve display intialization
355  this->init_display_();
356  // If a reset pin is configured, eligible displays can be set to deep sleep
357  // between updates, as recommended by the hardware provider
358  if (this->reset_pin_ != nullptr) {
359  switch (this->model_) {
360  // More models can be added here to enable deep sleep if eligible
363  this->deep_sleep_between_updates_ = true;
364  ESP_LOGI(TAG, "Set the display to deep sleep");
365  this->deep_sleep();
366  break;
367  default:
368  break;
369  }
370  }
371 }
373  if (this->model_ == TTGO_EPAPER_2_13_IN_B74 || this->model_ == WAVESHARE_EPAPER_2_13_IN_V2) {
374  if (this->reset_pin_ != nullptr) {
375  this->reset_pin_->digital_write(false);
376  delay(10);
377  this->reset_pin_->digital_write(true);
378  delay(10);
379  this->wait_until_idle_();
380  }
381 
382  this->command(0x12); // SWRESET
383  this->wait_until_idle_();
384  }
385 
386  // COMMAND DRIVER OUTPUT CONTROL
387  this->command(0x01);
388  this->data(this->get_height_internal() - 1);
389  this->data((this->get_height_internal() - 1) >> 8);
390  this->data(0x00); // ? GD = 0, SM = 0, TB = 0
391 
392  // COMMAND BOOSTER SOFT START CONTROL
393  this->command(0x0C);
394  this->data(0xD7);
395  this->data(0xD6);
396  this->data(0x9D);
397 
398  // COMMAND WRITE VCOM REGISTER
399  this->command(0x2C);
400  this->data(0xA8);
401 
402  // COMMAND SET DUMMY LINE PERIOD
403  this->command(0x3A);
404  this->data(0x1A);
405 
406  // COMMAND SET GATE TIME
407  this->command(0x3B);
408  this->data(0x08); // 2µs per row
409 
410  // COMMAND DATA ENTRY MODE SETTING
411  this->command(0x11);
412  switch (this->model_) {
414  this->data(0x01); // x increase, y decrease : as in demo code
415  break;
418  this->data(0x03); // from top left to bottom right
419  // RAM content option for Display Update
420  this->command(0x21);
421  this->data(0x00);
422  this->data(0x80);
423  break;
424  default:
425  this->data(0x03); // from top left to bottom right
426  }
427 }
429  LOG_DISPLAY("", "Waveshare E-Paper", this);
430  switch (this->model_) {
432  ESP_LOGCONFIG(TAG, " Model: 1.54in");
433  break;
435  ESP_LOGCONFIG(TAG, " Model: 1.54inV2");
436  break;
438  ESP_LOGCONFIG(TAG, " Model: 2.13in");
439  break;
441  ESP_LOGCONFIG(TAG, " Model: 2.13inV2");
442  break;
443  case TTGO_EPAPER_2_13_IN:
444  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO)");
445  break;
447  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B73)");
448  break;
450  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B74)");
451  break;
453  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B1)");
454  break;
456  ESP_LOGCONFIG(TAG, " Model: 2.9in");
457  break;
459  ESP_LOGCONFIG(TAG, " Model: 2.9inV2");
460  break;
461  }
462  ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
463  LOG_PIN(" Reset Pin: ", this->reset_pin_);
464  LOG_PIN(" DC Pin: ", this->dc_pin_);
465  LOG_PIN(" Busy Pin: ", this->busy_pin_);
466  LOG_UPDATE_INTERVAL(this);
467 }
469  bool full_update = this->at_update_ == 0;
470  bool prev_full_update = this->at_update_ == 1;
471 
472  if (this->deep_sleep_between_updates_) {
473  ESP_LOGI(TAG, "Wake up the display");
474  this->reset_();
475  this->wait_until_idle_();
476  this->init_display_();
477  }
478 
479  if (!this->wait_until_idle_()) {
480  this->status_set_warning();
481  return;
482  }
483 
484  if (this->full_update_every_ >= 1) {
485  if (full_update != prev_full_update) {
486  switch (this->model_) {
487  case TTGO_EPAPER_2_13_IN:
489  // Waveshare 2.13" V2 uses the same LUTs as TTGO
490  this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO : PARTIAL_UPDATE_LUT_TTGO, LUT_SIZE_TTGO);
491  break;
493  this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO_B73 : PARTIAL_UPDATE_LUT_TTGO_B73, LUT_SIZE_TTGO_B73);
494  break;
496  // there is no LUT
497  break;
499  this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO_B1 : PARTIAL_UPDATE_LUT_TTGO_B1, LUT_SIZE_TTGO_B1);
500  break;
501  default:
502  this->write_lut_(full_update ? FULL_UPDATE_LUT : PARTIAL_UPDATE_LUT, LUT_SIZE_WAVESHARE);
503  }
504  }
505  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
506  }
507 
508  if (this->model_ == WAVESHARE_EPAPER_2_13_IN_V2) {
509  // Set VCOM for full or partial update
510  this->command(0x2C);
511  this->data(full_update ? 0x55 : 0x26);
512 
513  if (!full_update) {
514  // Enable "ping-pong"
515  this->command(0x37);
516  this->data(0x00);
517  this->data(0x00);
518  this->data(0x00);
519  this->data(0x00);
520  this->data(0x40);
521  this->data(0x00);
522  this->data(0x00);
523  this->command(0x22);
524  this->data(0xc0);
525  this->command(0x20);
526  }
527  }
528 
529  // Border waveform
530  switch (this->model_) {
532  this->command(0x3C);
533  this->data(full_update ? 0x05 : 0x80);
534  break;
536  this->command(0x3C);
537  this->data(full_update ? 0x03 : 0x01);
538  break;
539  default:
540  break;
541  }
542 
543  // Set x & y regions we want to write to (full)
544  switch (this->model_) {
546  // COMMAND SET RAM X ADDRESS START END POSITION
547  this->command(0x44);
548  this->data(0x00);
549  this->data((this->get_width_controller() - 1) >> 3);
550  // COMMAND SET RAM Y ADDRESS START END POSITION
551  this->command(0x45);
552  this->data(this->get_height_internal() - 1);
553  this->data((this->get_height_internal() - 1) >> 8);
554  this->data(0x00);
555  this->data(0x00);
556 
557  // COMMAND SET RAM X ADDRESS COUNTER
558  this->command(0x4E);
559  this->data(0x00);
560  // COMMAND SET RAM Y ADDRESS COUNTER
561  this->command(0x4F);
562  this->data(this->get_height_internal() - 1);
563  this->data((this->get_height_internal() - 1) >> 8);
564 
565  break;
566  default:
567  // COMMAND SET RAM X ADDRESS START END POSITION
568  this->command(0x44);
569  this->data(0x00);
570  this->data((this->get_width_internal() - 1) >> 3);
571  // COMMAND SET RAM Y ADDRESS START END POSITION
572  this->command(0x45);
573  this->data(0x00);
574  this->data(0x00);
575  this->data(this->get_height_internal() - 1);
576  this->data((this->get_height_internal() - 1) >> 8);
577 
578  // COMMAND SET RAM X ADDRESS COUNTER
579  this->command(0x4E);
580  this->data(0x00);
581  // COMMAND SET RAM Y ADDRESS COUNTER
582  this->command(0x4F);
583  this->data(0x00);
584  this->data(0x00);
585  }
586 
587  if (!this->wait_until_idle_()) {
588  this->status_set_warning();
589  return;
590  }
591 
592  // COMMAND WRITE RAM
593  this->command(0x24);
594  this->start_data_();
595  switch (this->model_) {
596  case TTGO_EPAPER_2_13_IN_B1: { // block needed because of variable initializations
597  int16_t wb = ((this->get_width_controller()) >> 3);
598  for (int i = 0; i < this->get_height_internal(); i++) {
599  for (int j = 0; j < wb; j++) {
600  int idx = j + (this->get_height_internal() - 1 - i) * wb;
601  this->write_byte(this->buffer_[idx]);
602  }
603  }
604  break;
605  }
606  default:
607  this->write_array(this->buffer_, this->get_buffer_length_());
608  }
609  this->end_data_();
610 
611  if (this->model_ == WAVESHARE_EPAPER_2_13_IN_V2 && full_update) {
612  // Write base image again on full refresh
613  this->command(0x26);
614  this->start_data_();
615  this->write_array(this->buffer_, this->get_buffer_length_());
616  this->end_data_();
617  }
618 
619  // COMMAND DISPLAY UPDATE CONTROL 2
620  this->command(0x22);
621  switch (this->model_) {
625  this->data(full_update ? 0xF7 : 0xFF);
626  break;
628  this->data(0xC7);
629  break;
631  this->data(full_update ? 0xC7 : 0x0C);
632  break;
633  default:
634  this->data(0xC4);
635  break;
636  }
637 
638  // COMMAND MASTER ACTIVATION
639  this->command(0x20);
640  // COMMAND TERMINATE FRAME READ WRITE
641  this->command(0xFF);
642 
643  this->status_clear_warning();
644 
645  if (this->deep_sleep_between_updates_) {
646  ESP_LOGI(TAG, "Set the display back to deep sleep");
647  this->deep_sleep();
648  }
649 }
651  switch (this->model_) {
654  return 200;
657  case TTGO_EPAPER_2_13_IN:
661  return 122;
664  return 128;
665  }
666  return 0;
667 }
668 // The controller of the 2.13" displays has a buffer larger than screen size
670  switch (this->model_) {
673  case TTGO_EPAPER_2_13_IN:
677  return 128;
678  default:
679  return this->get_width_internal();
680  }
681 }
683  switch (this->model_) {
686  return 200;
689  case TTGO_EPAPER_2_13_IN:
693  return 250;
696  return 296;
697  }
698  return 0;
699 }
700 void WaveshareEPaperTypeA::write_lut_(const uint8_t *lut, const uint8_t size) {
701  // COMMAND WRITE LUT REGISTER
702  this->command(0x32);
703  for (uint8_t i = 0; i < size; i++)
704  this->data(lut[i]);
705 }
707 void WaveshareEPaperTypeA::set_full_update_every(uint32_t full_update_every) {
708  this->full_update_every_ = full_update_every;
709 }
710 
712  switch (this->model_) {
717  return 2500;
718  default:
720  }
721 }
722 
723 // ========================================================
724 // Type B
725 // ========================================================
726 // Datasheet:
727 // - https://www.waveshare.com/w/upload/7/7f/4.2inch-e-paper-b-specification.pdf
728 // - https://github.com/soonuse/epd-library-arduino/blob/master/4.2inch_e-paper/epd4in2/
729 
730 static const uint8_t LUT_VCOM_DC_2_7[44] = {
731  0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x00, 0x32, 0x32, 0x00, 0x00, 0x02, 0x00,
732  0x0F, 0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
733  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
734 };
735 
736 static const uint8_t LUT_WHITE_TO_WHITE_2_7[42] = {
737  0x50, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0xA0, 0x0F,
738  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
739  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
740 };
741 
742 static const uint8_t LUT_BLACK_TO_WHITE_2_7[42] = {
743  0x50, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0xA0, 0x0F,
744  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
745  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
746 };
747 
748 static const uint8_t LUT_WHITE_TO_BLACK_2_7[] = {
749  0xA0, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0x50, 0x0F,
750  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
751  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
752 };
753 
754 static const uint8_t LUT_BLACK_TO_BLACK_2_7[42] = {
755  0xA0, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0x50, 0x0F,
756  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
757  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
758 };
759 
761  // command power setting
762  this->command(0x01);
763  this->data(0x03); // VDS_EN, VDG_EN
764  this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
765  this->data(0x2B); // VDH
766  this->data(0x2B); // VDL
767  this->data(0x09); // VDHR
768 
769  // command booster soft start
770  this->command(0x06);
771  this->data(0x07);
772  this->data(0x07);
773  this->data(0x17);
774 
775  // Power optimization - ???
776  this->command(0xF8);
777  this->data(0x60);
778  this->data(0xA5);
779  this->command(0xF8);
780  this->data(0x89);
781  this->data(0xA5);
782  this->command(0xF8);
783  this->data(0x90);
784  this->data(0x00);
785  this->command(0xF8);
786  this->data(0x93);
787  this->data(0x2A);
788  this->command(0xF8);
789  this->data(0xA0);
790  this->data(0xA5);
791  this->command(0xF8);
792  this->data(0xA1);
793  this->data(0x00);
794  this->command(0xF8);
795  this->data(0x73);
796  this->data(0x41);
797 
798  // command partial display refresh
799  this->command(0x16);
800  this->data(0x00);
801 
802  // command power on
803  this->command(0x04);
804  this->wait_until_idle_();
805  delay(10);
806 
807  // Command panel setting
808  this->command(0x00);
809  this->data(0xAF); // KW-BF KWR-AF BWROTP 0f
810  // command pll control
811  this->command(0x30);
812  this->data(0x3A); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
813  // COMMAND VCM DC SETTING
814  this->command(0x82);
815  this->data(0x12);
816 
817  delay(2);
818  // COMMAND LUT FOR VCOM
819  this->command(0x20);
820  for (uint8_t i : LUT_VCOM_DC_2_7)
821  this->data(i);
822 
823  // COMMAND LUT WHITE TO WHITE
824  this->command(0x21);
825  for (uint8_t i : LUT_WHITE_TO_WHITE_2_7)
826  this->data(i);
827  // COMMAND LUT BLACK TO WHITE
828  this->command(0x22);
829  for (uint8_t i : LUT_BLACK_TO_WHITE_2_7)
830  this->data(i);
831  // COMMAND LUT WHITE TO BLACK
832  this->command(0x23);
833  for (uint8_t i : LUT_WHITE_TO_BLACK_2_7)
834  this->data(i);
835  // COMMAND LUT BLACK TO BLACK
836  this->command(0x24);
837  for (uint8_t i : LUT_BLACK_TO_BLACK_2_7)
838  this->data(i);
839 }
841  uint32_t buf_len = this->get_buffer_length_();
842 
843  // COMMAND DATA START TRANSMISSION 1
844  this->command(0x10);
845  delay(2);
846  for (uint32_t i = 0; i < buf_len; i++) {
847  this->data(this->buffer_[i]);
848  }
849  delay(2);
850 
851  // COMMAND DATA START TRANSMISSION 2
852  this->command(0x13);
853  delay(2);
854  for (uint32_t i = 0; i < buf_len; i++) {
855  this->data(this->buffer_[i]);
856  }
857 
858  // COMMAND DISPLAY REFRESH
859  this->command(0x12);
860 }
864  LOG_DISPLAY("", "Waveshare E-Paper", this);
865  ESP_LOGCONFIG(TAG, " Model: 2.7in");
866  LOG_PIN(" Reset Pin: ", this->reset_pin_);
867  LOG_PIN(" DC Pin: ", this->dc_pin_);
868  LOG_PIN(" Busy Pin: ", this->busy_pin_);
869  LOG_UPDATE_INTERVAL(this);
870 }
871 
873  this->reset_();
874  this->wait_until_idle_();
875 
876  this->command(0x12); // SWRESET
877  this->wait_until_idle_();
878 
879  // SET WINDOWS
880  // XRAM_START_AND_END_POSITION
881  this->command(0x44);
882  this->data(0x00);
883  this->data(((this->get_width_controller() - 1) >> 3) & 0xFF);
884  // YRAM_START_AND_END_POSITION
885  this->command(0x45);
886  this->data(0x00);
887  this->data(0x00);
888  this->data((get_height_internal() - 1) & 0xFF);
889  this->data(((get_height_internal() - 1) >> 8) & 0xFF);
890 
891  // SET CURSOR
892  // XRAM_ADDRESS
893  this->command(0x4E);
894  this->data(0x00);
895  // YRAM_ADDRESS
896  this->command(0x4F);
897  this->data(0x00);
898  this->data(0x00);
899 
900  this->command(0x11); // data entry mode
901  this->data(0x03);
902 }
904  this->command(0x24);
905  this->start_data_();
906  this->write_array(this->buffer_, this->get_buffer_length_());
907  this->end_data_();
908 
909  // COMMAND DISPLAY REFRESH
910  this->command(0x22);
911  this->data(0xF7);
912  this->command(0x20);
913 }
917  LOG_DISPLAY("", "Waveshare E-Paper", this);
918  ESP_LOGCONFIG(TAG, " Model: 2.7in V2");
919  LOG_PIN(" Reset Pin: ", this->reset_pin_);
920  LOG_PIN(" DC Pin: ", this->dc_pin_);
921  LOG_PIN(" Busy Pin: ", this->busy_pin_);
922  LOG_UPDATE_INTERVAL(this);
923 }
924 
925 // ========================================================
926 // 1.54inch_v2_e-paper_b
927 // ========================================================
928 // Datasheet:
929 // - https://files.waveshare.com/upload/9/9e/1.54inch-e-paper-b-v2-specification.pdf
930 // - https://www.waveshare.com/wiki/1.54inch_e-Paper_Module_(B)_Manual
931 
933  this->reset_();
934 
935  this->wait_until_idle_();
936 
937  this->command(0x12);
938  this->wait_until_idle_();
939 
940  this->command(0x01);
941  this->data(0xC7);
942  this->data(0x00);
943  this->data(0x01);
944 
945  this->command(0x11); // data entry mode
946  this->data(0x01);
947 
948  this->command(0x44); // set Ram-X address start/end position
949  this->data(0x00);
950  this->data(0x18); // 0x18-->(24+1)*8=200
951 
952  this->command(0x45); // set Ram-Y address start/end position
953  this->data(0xC7); // 0xC7-->(199+1)=200
954  this->data(0x00);
955  this->data(0x00);
956  this->data(0x00);
957 
958  this->command(0x3C); // BorderWavefrom
959  this->data(0x05);
960 
961  this->command(0x18); // Read built-in temperature sensor
962  this->data(0x80);
963 
964  this->command(0x4E); // set RAM x address count to 0;
965  this->data(0x00);
966  this->command(0x4F); // set RAM y address count to 0X199;
967  this->data(0xC7);
968  this->data(0x00);
969 
970  this->wait_until_idle_();
971 }
972 
974  uint32_t buf_len_half = this->get_buffer_length_() >> 1;
975  this->initialize();
976 
977  // COMMAND DATA START TRANSMISSION 1 (BLACK)
978  this->command(0x24);
979  delay(2);
980  for (uint32_t i = 0; i < buf_len_half; i++) {
981  this->data(~this->buffer_[i]);
982  }
983  delay(2);
984 
985  // COMMAND DATA START TRANSMISSION 2 (RED)
986  this->command(0x26);
987  delay(2);
988  for (uint32_t i = buf_len_half; i < buf_len_half * 2u; i++) {
989  this->data(this->buffer_[i]);
990  }
991  this->command(0x22);
992  this->data(0xf7);
993  this->command(0x20);
994  this->wait_until_idle_();
995 
996  this->deep_sleep();
997 }
1001  LOG_DISPLAY("", "Waveshare E-Paper", this);
1002  ESP_LOGCONFIG(TAG, " Model: 1.54in V2 B");
1003  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1004  LOG_PIN(" DC Pin: ", this->dc_pin_);
1005  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1006  LOG_UPDATE_INTERVAL(this);
1007 }
1008 
1009 // ========================================================
1010 // 2.7inch_e-paper_b
1011 // ========================================================
1012 // Datasheet:
1013 // - https://www.waveshare.com/w/upload/d/d8/2.7inch-e-paper-b-specification.pdf
1014 // - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_2in7b.c
1015 
1016 static const uint8_t LUT_VCOM_DC_2_7B[44] = {0x00, 0x00, 0x00, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x0A,
1017  0x00, 0x00, 0x08, 0x00, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x00, 0x0A,
1018  0x0A, 0x00, 0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x00, 0x05, 0x00,
1019  0x03, 0x0E, 0x00, 0x00, 0x0A, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01};
1020 
1021 static const uint8_t LUT_WHITE_TO_WHITE_2_7B[42] = {0x90, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x40, 0x0A, 0x0A, 0x00, 0x00,
1022  0x08, 0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x80, 0x0A, 0x0A, 0x00,
1023  0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x00, 0x05, 0x00, 0x03, 0x0E,
1024  0x00, 0x00, 0x0A, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01};
1025 
1026 static const uint8_t LUT_BLACK_TO_WHITE_2_7B[42] = {0xA0, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x0A, 0x00, 0x00,
1027  0x08, 0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x90, 0x0A, 0x0A, 0x00,
1028  0x00, 0x08, 0xB0, 0x04, 0x10, 0x00, 0x00, 0x05, 0xB0, 0x03, 0x0E,
1029  0x00, 0x00, 0x0A, 0xC0, 0x23, 0x00, 0x00, 0x00, 0x01};
1030 
1031 static const uint8_t LUT_WHITE_TO_BLACK_2_7B[] = {0x90, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x20, 0x0A, 0x0A, 0x00, 0x00,
1032  0x08, 0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x10, 0x0A, 0x0A, 0x00,
1033  0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x00, 0x05, 0x00, 0x03, 0x0E,
1034  0x00, 0x00, 0x0A, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01};
1035 
1036 static const uint8_t LUT_BLACK_TO_BLACK_2_7B[42] = {0x90, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x40, 0x0A, 0x0A, 0x00, 0x00,
1037  0x08, 0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x80, 0x0A, 0x0A, 0x00,
1038  0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x00, 0x05, 0x00, 0x03, 0x0E,
1039  0x00, 0x00, 0x0A, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01};
1040 
1042  this->reset_();
1043 
1044  // command power on
1045  this->command(0x04);
1046  this->wait_until_idle_();
1047  delay(10);
1048 
1049  // Command panel setting
1050  this->command(0x00);
1051  this->data(0xAF); // KW-BF KWR-AF BWROTP 0f
1052  // command pll control
1053  this->command(0x30);
1054  this->data(0x3A); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
1055 
1056  // command power setting
1057  this->command(0x01);
1058  this->data(0x03); // VDS_EN, VDG_EN
1059  this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
1060  this->data(0x2B); // VDH
1061  this->data(0x2B); // VDL
1062  this->data(0x09); // VDHR
1063 
1064  // command booster soft start
1065  this->command(0x06);
1066  this->data(0x07);
1067  this->data(0x07);
1068  this->data(0x17);
1069 
1070  // Power optimization - ???
1071  this->command(0xF8);
1072  this->data(0x60);
1073  this->data(0xA5);
1074  this->command(0xF8);
1075  this->data(0x89);
1076  this->data(0xA5);
1077  this->command(0xF8);
1078  this->data(0x90);
1079  this->data(0x00);
1080  this->command(0xF8);
1081  this->data(0x93);
1082  this->data(0x2A);
1083  this->command(0xF8);
1084  this->data(0x73);
1085  this->data(0x41);
1086 
1087  // COMMAND VCM DC SETTING
1088  this->command(0x82);
1089  this->data(0x12);
1090 
1091  // VCOM_AND_DATA_INTERVAL_SETTING
1092  this->command(0x50);
1093  this->data(0x87); // define by OTP
1094 
1095  delay(2);
1096  // COMMAND LUT FOR VCOM
1097  this->command(0x20);
1098  for (uint8_t i : LUT_VCOM_DC_2_7B)
1099  this->data(i);
1100  // COMMAND LUT WHITE TO WHITE
1101  this->command(0x21);
1102  for (uint8_t i : LUT_WHITE_TO_WHITE_2_7B)
1103  this->data(i);
1104  // COMMAND LUT BLACK TO WHITE
1105  this->command(0x22);
1106  for (uint8_t i : LUT_BLACK_TO_WHITE_2_7B)
1107  this->data(i);
1108  // COMMAND LUT WHITE TO BLACK
1109  this->command(0x23);
1110  for (uint8_t i : LUT_WHITE_TO_BLACK_2_7B) {
1111  this->data(i);
1112  }
1113  // COMMAND LUT BLACK TO BLACK
1114  this->command(0x24);
1115 
1116  for (uint8_t i : LUT_BLACK_TO_BLACK_2_7B) {
1117  this->data(i);
1118  }
1119 
1120  delay(2);
1121 }
1122 
1124  uint32_t buf_len_half = this->get_buffer_length_() >> 1;
1125  this->initialize();
1126 
1127  // TCON_RESOLUTION
1128  this->command(0x61);
1129  this->data(this->get_width_controller() >> 8);
1130  this->data(this->get_width_controller() & 0xff); // 176
1131  this->data(this->get_height_internal() >> 8);
1132  this->data(this->get_height_internal() & 0xff); // 264
1133 
1134  // COMMAND DATA START TRANSMISSION 1 (BLACK)
1135  this->command(0x10);
1136  delay(2);
1137  for (uint32_t i = 0; i < buf_len_half; i++) {
1138  this->data(this->buffer_[i]);
1139  }
1140  this->command(0x11);
1141  delay(2);
1142 
1143  // COMMAND DATA START TRANSMISSION 2 (RED)
1144  this->command(0x13);
1145  delay(2);
1146  for (uint32_t i = buf_len_half; i < buf_len_half * 2u; i++) {
1147  this->data(this->buffer_[i]);
1148  }
1149  this->command(0x11);
1150 
1151  delay(2);
1152 
1153  // COMMAND DISPLAY REFRESH
1154  this->command(0x12);
1155  this->wait_until_idle_();
1156 
1157  this->deep_sleep();
1158 }
1162  LOG_DISPLAY("", "Waveshare E-Paper", this);
1163  ESP_LOGCONFIG(TAG, " Model: 2.7in B");
1164  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1165  LOG_PIN(" DC Pin: ", this->dc_pin_);
1166  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1167  LOG_UPDATE_INTERVAL(this);
1168 }
1169 
1170 // ========================================================
1171 // 2.7inch_e-paper_b_v2
1172 // ========================================================
1173 // Datasheet:
1174 // - https://www.waveshare.com/w/upload/7/7b/2.7inch-e-paper-b-v2-specification.pdf
1175 // - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_2in7b_V2.c
1176 
1178  this->reset_();
1179 
1180  this->wait_until_idle_();
1181  this->command(0x12);
1182  this->wait_until_idle_();
1183 
1184  this->command(0x00);
1185  this->data(0x27);
1186  this->data(0x01);
1187  this->data(0x00);
1188 
1189  this->command(0x11);
1190  this->data(0x03);
1191 
1192  // self.SetWindows(0, 0, self.width-1, self.height-1)
1193  // SetWindows(self, Xstart, Ystart, Xend, Yend):
1194 
1195  uint32_t xend = this->get_width_controller() - 1;
1196  uint32_t yend = this->get_height_internal() - 1;
1197  this->command(0x44);
1198  this->data(0x00);
1199  this->data((xend >> 3) & 0xff);
1200 
1201  this->command(0x45);
1202  this->data(0x00);
1203  this->data(0x00);
1204  this->data(yend & 0xff);
1205  this->data((yend >> 8) & 0xff);
1206 
1207  // SetCursor(self, Xstart, Ystart):
1208  this->command(0x4E);
1209  this->data(0x00);
1210  this->command(0x4F);
1211  this->data(0x00);
1212  this->data(0x00);
1213 }
1214 
1216  uint32_t buf_len = this->get_buffer_length_();
1217  // COMMAND DATA START TRANSMISSION 1 (BLACK)
1218  this->command(0x24);
1219  delay(2);
1220  for (uint32_t i = 0; i < buf_len; i++) {
1221  this->data(this->buffer_[i]);
1222  }
1223  delay(2);
1224 
1225  // COMMAND DATA START TRANSMISSION 2 (RED)
1226  this->command(0x26);
1227  delay(2);
1228  for (uint32_t i = 0; i < buf_len; i++) {
1229  this->data(this->buffer_[i]);
1230  }
1231 
1232  delay(2);
1233 
1234  this->command(0x20);
1235 
1236  this->wait_until_idle_();
1237 }
1241  LOG_DISPLAY("", "Waveshare E-Paper", this);
1242  ESP_LOGCONFIG(TAG, " Model: 2.7in B V2");
1243  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1244  LOG_PIN(" DC Pin: ", this->dc_pin_);
1245  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1246  LOG_UPDATE_INTERVAL(this);
1247 }
1248 
1249 // ========================================================
1250 // 2.90in Type B (LUT from OTP)
1251 // Datasheet:
1252 // - https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf
1253 // - https://github.com/soonuse/epd-library-arduino/blob/master/2.9inch_e-paper_b/epd2in9b/epd2in9b.cpp
1254 // ========================================================
1255 
1257  // from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37
1258  // EPD hardware init start
1259  this->reset_();
1260 
1261  // COMMAND BOOSTER SOFT START
1262  this->command(0x06);
1263  this->data(0x17);
1264  this->data(0x17);
1265  this->data(0x17);
1266 
1267  // COMMAND POWER ON
1268  this->command(0x04);
1269  this->wait_until_idle_();
1270 
1271  // COMMAND PANEL SETTING
1272  this->command(0x00);
1273  // 128x296 resolution: 10
1274  // LUT from OTP: 0
1275  // B/W mode (doesn't work): 1
1276  // scan-up: 1
1277  // shift-right: 1
1278  // booster ON: 1
1279  // no soft reset: 1
1280  this->data(0x9F);
1281 
1282  // COMMAND RESOLUTION SETTING
1283  // set to 128x296 by COMMAND PANEL SETTING
1284 
1285  // COMMAND VCOM AND DATA INTERVAL SETTING
1286  // use defaults for white border and ESPHome image polarity
1287 
1288  // EPD hardware init end
1289 }
1291  // COMMAND DATA START TRANSMISSION 1 (B/W data)
1292  this->command(0x10);
1293  delay(2);
1294  this->start_data_();
1295  this->write_array(this->buffer_, this->get_buffer_length_());
1296  this->end_data_();
1297  delay(2);
1298 
1299  // COMMAND DATA START TRANSMISSION 2 (RED data)
1300  this->command(0x13);
1301  delay(2);
1302  this->start_data_();
1303  for (size_t i = 0; i < this->get_buffer_length_(); i++)
1304  this->write_byte(0x00);
1305  this->end_data_();
1306  delay(2);
1307 
1308  // COMMAND DISPLAY REFRESH
1309  this->command(0x12);
1310  delay(2);
1311  this->wait_until_idle_();
1312 
1313  // COMMAND POWER OFF
1314  // NOTE: power off < deep sleep
1315  this->command(0x02);
1316 }
1320  LOG_DISPLAY("", "Waveshare E-Paper", this);
1321  ESP_LOGCONFIG(TAG, " Model: 2.9in (B)");
1322  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1323  LOG_PIN(" DC Pin: ", this->dc_pin_);
1324  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1325  LOG_UPDATE_INTERVAL(this);
1326 }
1327 
1328 // ========================================================
1329 // Waveshare 2.9-inch E-Paper (Type D)
1330 // Waveshare WIKI: https://www.waveshare.com/wiki/Pico-ePaper-2.9-D
1331 // Datasheet: https://www.waveshare.com/w/upload/b/b5/2.9inch_e-Paper_(D)_Specification.pdf
1332 // ========================================================
1333 
1335  // EPD hardware init start
1336  this->reset_();
1337 
1338  // Booster Soft Start
1339  this->command(0x06); // Command: BTST
1340  this->data(0x17); // Soft start configuration Phase A
1341  this->data(0x17); // Soft start configuration Phase B
1342  this->data(0x17); // Soft start configuration Phase C
1343 
1344  // Power Setting
1345  this->command(0x01); // Command: PWR
1346  this->data(0x03); // Intern DC/DC for VDH/VDL and VGH/VGL
1347  this->data(0x00); // Default configuration VCOM_HV and VGHL_LV
1348  this->data(0x2b); // VDH = 10.8 V
1349  this->data(0x2b); // VDL = -10.8 V
1350 
1351  // Power ON
1352  this->command(0x04); // Command: PON
1353  this->wait_until_idle_();
1354 
1355  // Panel settings
1356  this->command(0x00); // Command: PSR
1357  this->data(0x1F); // LUT from OTP, black and white mode, default scan
1358 
1359  // PLL Control
1360  this->command(0x30); // Command: PLL
1361  this->data(0x3A); // Default PLL frequency
1362 
1363  // Resolution settings
1364  this->command(0x61); // Command: TRES
1365  this->data(0x80); // Width: 128
1366  this->data(0x01); // Height MSB: 296
1367  this->data(0x28); // Height LSB: 296
1368 
1369  // VCOM and data interval settings
1370  this->command(0x50); // Command: CDI
1371  this->data(0x77);
1372 
1373  // VCOM_DC settings
1374  this->command(0x82); // Command: VDCS
1375  this->data(0x12); // Dafault VCOM_DC
1376 }
1377 
1379  // Start transmitting old data (clearing buffer)
1380  this->command(0x10); // Command: DTM1 (OLD frame data)
1381  this->start_data_();
1382  this->write_array(this->buffer_, this->get_buffer_length_());
1383  this->end_data_();
1384 
1385  // Start transmitting new data (updated content)
1386  this->command(0x13); // Command: DTM2 (NEW frame data)
1387  this->start_data_();
1388  this->write_array(this->buffer_, this->get_buffer_length_());
1389  this->end_data_();
1390 
1391  // Refresh Display
1392  this->command(0x12); // Command: DRF
1393  this->wait_until_idle_();
1394 
1395  // Enter Power Off
1396  this->command(0x02); // Command: POF
1397  this->wait_until_idle_();
1398 
1399  // Enter Deep Sleep
1400  this->command(0x07); // Command: DSLP
1401  this->data(0xA5);
1402 }
1403 
1407  LOG_DISPLAY("", "Waveshare E-Paper", this);
1408  ESP_LOGCONFIG(TAG, " Model: 2.9in (D)");
1409  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1410  LOG_PIN(" DC Pin: ", this->dc_pin_);
1411  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1412  LOG_UPDATE_INTERVAL(this);
1413 }
1414 
1415 // DKE 2.9
1416 // https://www.badge.team/docs/badges/sha2017/hardware/#e-ink-display-the-dke-group-depg0290b1
1417 // https://www.badge.team/docs/badges/sha2017/hardware/DEPG0290B01V3.0.pdf
1418 static const uint8_t LUT_SIZE_DKE = 70;
1419 static const uint8_t UPDATE_LUT_DKE[LUT_SIZE_DKE] = {
1420  0xA0, 0x90, 0x50, 0x0, 0x0, 0x0, 0x0, 0x50, 0x90, 0xA0, 0x0, 0x0, 0x0, 0x0, 0xA0, 0x90, 0x50, 0x0,
1421  0x0, 0x0, 0x0, 0x50, 0x90, 0xA0, 0x0, 0x0, 0x0, 0x0, 0x00, 0x00, 0x00, 0x0, 0x0, 0x0, 0x0, 0xF,
1422  0xF, 0x0, 0x0, 0x0, 0xF, 0xF, 0x0, 0x0, 0x02, 0xF, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1423  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1424 };
1425 static const uint8_t PART_UPDATE_LUT_DKE[LUT_SIZE_DKE] = {
1426  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xa0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x50, 0x10, 0x00, 0x00,
1427  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
1428  0x05, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1429  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1430 static const uint8_t FULL_UPDATE_LUT_DKE[LUT_SIZE_DKE] = {
1431  0x90, 0x50, 0xa0, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x10, 0xa0, 0xa0, 0x80, 0x00, 0x90, 0x50, 0xa0, 0x50,
1432  0x50, 0x00, 0x00, 0x00, 0x00, 0x10, 0xa0, 0xa0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
1433  0x04, 0x00, 0x00, 0x00, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00,
1434  0x00, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1435 
1437  // Hardware reset
1438  delay(10);
1439  this->reset_pin_->digital_write(false);
1440  delayMicroseconds(200);
1441  this->reset_pin_->digital_write(true);
1442  delayMicroseconds(200);
1443  // Wait for busy low
1444  this->wait_until_idle_();
1445  // Software reset
1446  this->command(0x12);
1447  // Wait for busy low
1448  this->wait_until_idle_();
1449  // Set Analog Block Control
1450  this->command(0x74);
1451  this->data(0x54);
1452  // Set Digital Block Control
1453  this->command(0x7E);
1454  this->data(0x3B);
1455  // Set display size and driver output control
1456  this->command(0x01);
1457  // this->data(0x27);
1458  // this->data(0x01);
1459  // this->data(0x00);
1460  this->data(this->get_height_internal() - 1);
1461  this->data((this->get_height_internal() - 1) >> 8);
1462  this->data(0x00); // ? GD = 0, SM = 0, TB = 0
1463  // Ram data entry mode
1464  this->command(0x11);
1465  this->data(0x03);
1466  // Set Ram X address
1467  this->command(0x44);
1468  this->data(0x00);
1469  this->data(0x0F);
1470  // Set Ram Y address
1471  this->command(0x45);
1472  this->data(0x00);
1473  this->data(0x00);
1474  this->data(0x27);
1475  this->data(0x01);
1476  // Set border
1477  this->command(0x3C);
1478  // this->data(0x80);
1479  this->data(0x01);
1480  // Set VCOM value
1481  this->command(0x2C);
1482  this->data(0x26);
1483  // Gate voltage setting
1484  this->command(0x03);
1485  this->data(0x17);
1486  // Source voltage setting
1487  this->command(0x04);
1488  this->data(0x41);
1489  this->data(0x00);
1490  this->data(0x32);
1491  // Frame setting 50hz
1492  this->command(0x3A);
1493  this->data(0x30);
1494  this->command(0x3B);
1495  this->data(0x0A);
1496  // Load LUT
1497  this->command(0x32);
1498  for (uint8_t v : FULL_UPDATE_LUT_DKE)
1499  this->data(v);
1500 }
1501 
1503  ESP_LOGI(TAG, "Performing e-paper update.");
1504  // Set Ram X address counter
1505  this->command(0x4e);
1506  this->data(0);
1507  // Set Ram Y address counter
1508  this->command(0x4f);
1509  this->data(0);
1510  this->data(0);
1511  // Load image (128/8*296)
1512  this->command(0x24);
1513  this->start_data_();
1514  this->write_array(this->buffer_, this->get_buffer_length_());
1515  this->end_data_();
1516  // Image update
1517  this->command(0x22);
1518  this->data(0xC7);
1519  this->command(0x20);
1520  // Wait for busy low
1521  this->wait_until_idle_();
1522  // Enter deep sleep mode
1523  this->command(0x10);
1524  this->data(0x01);
1525 }
1529  LOG_DISPLAY("", "Waveshare E-Paper", this);
1530  ESP_LOGCONFIG(TAG, " Model: 2.9in DKE");
1531  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1532  LOG_PIN(" DC Pin: ", this->dc_pin_);
1533  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1534  LOG_UPDATE_INTERVAL(this);
1535 }
1536 void WaveshareEPaper2P9InDKE::set_full_update_every(uint32_t full_update_every) {
1537  this->full_update_every_ = full_update_every;
1538 }
1539 
1540 // ========================================================
1541 // 2.90in Type B (LUT from OTP)
1542 // Datasheet:
1543 // - https://files.waveshare.com/upload/a/af/2.9inch-e-paper-b-v3-specification.pdf
1544 // ========================================================
1545 
1547  // from https://github.com/waveshareteam/e-Paper/blob/master/Arduino/epd2in9b_V3/epd2in9b_V3.cpp
1548  this->reset_();
1549 
1550  // COMMAND POWER ON
1551  this->command(0x04);
1552  this->wait_until_idle_();
1553 
1554  // COMMAND PANEL SETTING
1555  this->command(0x00);
1556  this->data(0x0F);
1557  this->data(0x89);
1558 
1559  // COMMAND RESOLUTION SETTING
1560  this->command(0x61);
1561  this->data(0x80);
1562  this->data(0x01);
1563  this->data(0x28);
1564 
1565  // COMMAND VCOM AND DATA INTERVAL SETTING
1566  this->command(0x50);
1567  this->data(0x77);
1568 }
1570  // COMMAND DATA START TRANSMISSION 1 (B/W data)
1571  this->command(0x10);
1572  delay(2);
1573  this->start_data_();
1574  this->write_array(this->buffer_, this->get_buffer_length_());
1575  this->end_data_();
1576  this->command(0x92);
1577  delay(2);
1578 
1579  // COMMAND DATA START TRANSMISSION 2 (RED data)
1580  this->command(0x13);
1581  delay(2);
1582  this->start_data_();
1583  for (size_t i = 0; i < this->get_buffer_length_(); i++)
1584  this->write_byte(0xFF);
1585  this->end_data_();
1586  this->command(0x92);
1587  delay(2);
1588 
1589  // COMMAND DISPLAY REFRESH
1590  this->command(0x12);
1591  delay(2);
1592  this->wait_until_idle_();
1593 
1594  // COMMAND POWER OFF
1595  // NOTE: power off < deep sleep
1596  this->command(0x02);
1597 }
1601  LOG_DISPLAY("", "Waveshare E-Paper", this);
1602  ESP_LOGCONFIG(TAG, " Model: 2.9in (B) V3");
1603  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1604  LOG_PIN(" DC Pin: ", this->dc_pin_);
1605  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1606  LOG_UPDATE_INTERVAL(this);
1607 }
1608 
1609 // ========================================================
1610 // 2.90in v2 rev2
1611 // based on SDK and examples in ZIP file from:
1612 // https://www.waveshare.com/pico-epaper-2.9.htm
1613 // ========================================================
1614 
1616  this->reset_();
1617  this->wait_until_idle_();
1618 
1619  this->command(0x12); // SWRESET
1620  this->wait_until_idle_();
1621 
1622  this->command(0x01);
1623  this->data(0x27);
1624  this->data(0x01);
1625  this->data(0x00);
1626 
1627  this->command(0x11);
1628  this->data(0x03);
1629 
1630  // SetWindows(0, 0, w, h)
1631  this->command(0x44);
1632  this->data(0x00);
1633  this->data(((this->get_width_controller() - 1) >> 3) & 0xFF);
1634 
1635  this->command(0x45);
1636  this->data(0x00);
1637  this->data(0x00);
1638  this->data((this->get_height_internal() - 1) & 0xFF);
1639  this->data(((this->get_height_internal() - 1) >> 8) & 0xFF);
1640 
1641  this->command(0x21);
1642  this->data(0x00);
1643  this->data(0x80);
1644 
1645  // SetCursor(0, 0)
1646  this->command(0x4E);
1647  this->data(0x00);
1648  this->command(0x4f);
1649  this->data(0x00);
1650  this->data(0x00);
1651 
1652  this->wait_until_idle_();
1653 }
1654 
1656 
1657 void WaveshareEPaper2P9InV2R2::reset_() {
1658  if (this->reset_pin_ != nullptr) {
1659  this->reset_pin_->digital_write(false);
1660  delay(reset_duration_); // NOLINT
1661  this->reset_pin_->digital_write(true);
1662  delay(reset_duration_); // NOLINT
1663  }
1664 }
1665 
1667  if (!this->wait_until_idle_()) {
1668  this->status_set_warning();
1669  ESP_LOGE(TAG, "fail idle 1");
1670  return;
1671  }
1672 
1673  if (this->full_update_every_ == 1) {
1674  // do single full update
1675  this->command(0x24);
1676  this->start_data_();
1677  this->write_array(this->buffer_, this->get_buffer_length_());
1678  this->end_data_();
1679 
1680  // TurnOnDisplay
1681  this->command(0x22);
1682  this->data(0xF7);
1683  this->command(0x20);
1684  return;
1685  }
1686 
1687  // if (this->full_update_every_ == 1 ||
1688  if (this->at_update_ == 0) {
1689  // do base update
1690  this->command(0x24);
1691  this->start_data_();
1692  this->write_array(this->buffer_, this->get_buffer_length_());
1693  this->end_data_();
1694 
1695  this->command(0x26);
1696  this->start_data_();
1697  this->write_array(this->buffer_, this->get_buffer_length_());
1698  this->end_data_();
1699 
1700  // TurnOnDisplay
1701  this->command(0x22);
1702  this->data(0xF7);
1703  this->command(0x20);
1704  } else {
1705  // do partial update
1706  this->reset_();
1707 
1708  this->write_lut_(PARTIAL_UPD_2IN9_LUT, PARTIAL_UPD_2IN9_LUT_SIZE);
1709 
1710  this->command(0x37);
1711  this->data(0x00);
1712  this->data(0x00);
1713  this->data(0x00);
1714  this->data(0x00);
1715  this->data(0x00);
1716  this->data(0x40);
1717  this->data(0x00);
1718  this->data(0x00);
1719  this->data(0x00);
1720  this->data(0x00);
1721 
1722  this->command(0x3C);
1723  this->data(0x80);
1724 
1725  this->command(0x22);
1726  this->data(0xC0);
1727  this->command(0x20);
1728 
1729  if (!this->wait_until_idle_()) {
1730  ESP_LOGE(TAG, "fail idle 2");
1731  }
1732 
1733  // SetWindows(0, 0, w, h)
1734  this->command(0x44);
1735  this->data(0x00);
1736  this->data(((this->get_width_controller() - 1) >> 3) & 0xFF);
1737 
1738  this->command(0x45);
1739  this->data(0x00);
1740  this->data(0x00);
1741  this->data((this->get_height_internal() - 1) & 0xFF);
1742  this->data(((this->get_height_internal() - 1) >> 8) & 0xFF);
1743 
1744  // SetCursor(0, 0)
1745  this->command(0x4E);
1746  this->data(0x00);
1747  this->command(0x4f);
1748  this->data(0x00);
1749  this->data(0x00);
1750 
1751  // write b/w
1752  this->command(0x24);
1753  this->start_data_();
1754  this->write_array(this->buffer_, this->get_buffer_length_());
1755  this->end_data_();
1756 
1757  // TurnOnDisplayPartial
1758  this->command(0x22);
1759  this->data(0x0F);
1760  this->command(0x20);
1761  }
1762 
1763  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
1764 }
1765 
1766 void WaveshareEPaper2P9InV2R2::write_lut_(const uint8_t *lut, const uint8_t size) {
1767  // COMMAND WRITE LUT REGISTER
1768  this->command(0x32);
1769  for (uint8_t i = 0; i < size; i++)
1770  this->data(lut[i]);
1771 }
1772 
1774  LOG_DISPLAY("", "Waveshare E-Paper", this);
1775  ESP_LOGCONFIG(TAG, " Model: 2.9inV2R2");
1776  ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
1777  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1778  LOG_PIN(" DC Pin: ", this->dc_pin_);
1779  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1780  LOG_UPDATE_INTERVAL(this);
1781 }
1782 
1784  this->command(0x10);
1785  this->data(0x01);
1786 }
1787 
1791 void WaveshareEPaper2P9InV2R2::set_full_update_every(uint32_t full_update_every) {
1792  this->full_update_every_ = full_update_every;
1793 }
1794 // ========================================================
1795 // Good Display 2.9in black/white
1796 // Datasheet:
1797 // - https://files.seeedstudio.com/wiki/Other_Display/29-epaper/GDEY029T94.pdf
1798 // -
1799 // https://github.com/Allen-Kuang/e-ink_Demo/blob/main/2.9%20inch%20E-paper%20-%20monocolor%20128x296/example/Display_EPD_W21.cpp
1800 // ========================================================
1801 
1803  // EPD hardware init start
1804  this->reset_();
1805 
1806  this->wait_until_idle_();
1807  this->command(0x12); // SWRESET
1808  this->wait_until_idle_();
1809 
1810  this->command(0x01); // Driver output control
1811  this->data((this->get_height_internal() - 1) % 256);
1812  this->data((this->get_height_internal() - 1) / 256);
1813  this->data(0x00);
1814 
1815  this->command(0x11); // data entry mode
1816  this->data(0x03);
1817 
1818  this->command(0x44); // set Ram-X address start/end position
1819  this->data(0x00);
1820  this->data(this->get_width_internal() / 8 - 1);
1821 
1822  this->command(0x45); // set Ram-Y address start/end position
1823  this->data(0x00);
1824  this->data(0x00);
1825  this->data((this->get_height_internal() - 1) % 256);
1826  this->data((this->get_height_internal() - 1) / 256);
1827 
1828  this->command(0x3C); // BorderWavefrom
1829  this->data(0x05);
1830 
1831  this->command(0x21); // Display update control
1832  this->data(0x00);
1833  this->data(0x80);
1834 
1835  this->command(0x18); // Read built-in temperature sensor
1836  this->data(0x80);
1837 
1838  this->command(0x4E); // set RAM x address count to 0;
1839  this->data(0x00);
1840  this->command(0x4F); // set RAM y address count to 0X199;
1841  this->command(0x00);
1842  this->command(0x00);
1843  this->wait_until_idle_();
1844 }
1846  this->command(0x24); // write RAM for black(0)/white (1)
1847  this->start_data_();
1848  for (uint32_t i = 0; i < this->get_buffer_length_(); i++) {
1849  this->write_byte(this->buffer_[i]);
1850  }
1851  this->end_data_();
1852  this->command(0x22); // Display Update Control
1853  this->data(0xF7);
1854  this->command(0x20); // Activate Display Update Sequence
1855  this->wait_until_idle_();
1856 }
1857 int GDEY029T94::get_width_internal() { return 128; }
1858 int GDEY029T94::get_height_internal() { return 296; }
1860  LOG_DISPLAY("", "E-Paper (Good Display)", this);
1861  ESP_LOGCONFIG(TAG, " Model: 2.9in GDEY029T94");
1862  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1863  LOG_PIN(" DC Pin: ", this->dc_pin_);
1864  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1865  LOG_UPDATE_INTERVAL(this);
1866 }
1867 
1868 // ========================================================
1869 // Good Display 2.9in black/white
1870 // Datasheet:
1871 // - https://v4.cecdn.yun300.cn/100001_1909185148/SSD1680.pdf
1872 // - https://github.com/adafruit/Adafruit_EPD/blob/master/src/panels/ThinkInk_290_Grayscale4_T5.h
1873 // - https://github.com/ZinggJM/GxEPD2/blob/master/src/epd/GxEPD2_290_T5.cpp
1874 // - http://www.e-paper-display.com/GDEW029T5%20V3.1%20Specification5c22.pdf?
1875 // ========================================================
1876 
1877 // full screen update LUT
1878 static const uint8_t LUT_20_VCOMDC_29_5[] = {
1879  0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x60, 0x28, 0x28, 0x00, 0x00, 0x01, 0x00, 0x14, 0x00,
1880  0x00, 0x00, 0x01, 0x00, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1881  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1882 };
1883 
1884 static const uint8_t LUT_21_WW_29_5[] = {
1885  0x40, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x40, 0x14,
1886  0x00, 0x00, 0x00, 0x01, 0xA0, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1887  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1888 };
1889 
1890 static const uint8_t LUT_22_BW_29_5[] = {
1891  0x40, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x40, 0x14,
1892  0x00, 0x00, 0x00, 0x01, 0xA0, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1893  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1894 };
1895 
1896 static const uint8_t LUT_23_WB_29_5[] = {
1897  0x80, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x80, 0x14,
1898  0x00, 0x00, 0x00, 0x01, 0x50, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1899  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1900 };
1901 
1902 static const uint8_t LUT_24_BB_29_5[] = {
1903  0x80, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x80, 0x14,
1904  0x00, 0x00, 0x00, 0x01, 0x50, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1905  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1906 };
1907 
1908 // partial screen update LUT
1909 static const uint8_t LUT_20_VCOMDC_PARTIAL_29_5[] = {
1910  0x00, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1911  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1912  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1913 };
1914 
1915 static const uint8_t LUT_21_WW_PARTIAL_29_5[] = {
1916  0x00, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1917  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1918  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1919 };
1920 
1921 static const uint8_t LUT_22_BW_PARTIAL_29_5[] = {
1922  0x80, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1923  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1924  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1925 };
1926 
1927 static const uint8_t LUT_23_WB_PARTIAL_29_5[] = {
1928  0x40, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1929  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1930  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1931 };
1932 
1933 static const uint8_t LUT_24_BB_PARTIAL_29_5[] = {
1934  0x00, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1935  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1936  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1937 };
1938 
1940  if (!this->power_is_on_) {
1941  this->command(0x04);
1942  this->wait_until_idle_();
1943  }
1944  this->power_is_on_ = true;
1945 }
1946 
1948  this->command(0x02);
1949  this->wait_until_idle_();
1950  this->power_is_on_ = false;
1951 }
1952 
1954  this->power_off_();
1955  if (this->deep_sleep_between_updates_) {
1956  this->command(0x07); // deep sleep
1957  this->data(0xA5); // check code
1958  ESP_LOGD(TAG, "go to deep sleep");
1959  this->is_deep_sleep_ = true;
1960  }
1961 }
1962 
1964  // from https://github.com/ZinggJM/GxEPD2/blob/master/src/epd/GxEPD2_290_T5.cpp
1965 
1966  // Hardware Initialization
1967  if (this->deep_sleep_between_updates_ && this->is_deep_sleep_) {
1968  ESP_LOGI(TAG, "wake up from deep sleep");
1969  this->reset_();
1970  this->is_deep_sleep_ = false;
1971  }
1972 
1973  // COMMAND POWER SETTINGS
1974  this->command(0x01);
1975  this->data(0x03);
1976  this->data(0x00);
1977  this->data(0x2b);
1978  this->data(0x2b);
1979  this->data(0x03); /* for b/w */
1980 
1981  // COMMAND BOOSTER SOFT START
1982  this->command(0x06);
1983  this->data(0x17);
1984  this->data(0x17);
1985  this->data(0x17);
1986 
1987  this->power_on_();
1988 
1989  // COMMAND PANEL SETTING
1990  this->command(0x00);
1991  // 128x296 resolution: 10
1992  // LUT from register: 1
1993  // B/W mode (doesn't work): 1
1994  // scan-up: 1
1995  // shift-right: 1
1996  // booster ON: 1
1997  // no soft reset: 1
1998  this->data(0b10111111);
1999  this->data(0x0d); // VCOM to 0V fast
2000  this->command(0x30); // PLL setting
2001  this->data(0x3a); // 3a 100HZ 29 150Hz 39 200HZ 31 171HZ
2002  this->command(0x61); // resolution setting
2003  this->data(this->get_width_internal());
2004  this->data(this->get_height_internal() >> 8);
2005  this->data(this->get_height_internal() & 0xFF);
2006 
2007  ESP_LOGD(TAG, "panel setting done");
2008 }
2009 
2011  // from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37
2012  if (this->reset_pin_ != nullptr)
2013  this->deep_sleep_between_updates_ = true;
2014 
2015  // old buffer for partial update
2017  this->old_buffer_ = allocator.allocate(this->get_buffer_length_());
2018  if (this->old_buffer_ == nullptr) {
2019  ESP_LOGE(TAG, "Could not allocate old buffer for display!");
2020  return;
2021  }
2022  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
2023  this->old_buffer_[i] = 0xFF;
2024  }
2025 }
2026 
2027 // initialize for full(normal) update
2029  this->init_display_();
2030  this->command(0x82); // vcom_DC setting
2031  this->data(0x08);
2032  this->command(0X50); // VCOM AND DATA INTERVAL SETTING
2033  this->data(0x97); // WBmode:VBDF 17|D7 VBDW 97 VBDB 57 WBRmode:VBDF F7 VBDW 77 VBDB 37 VBDR B7
2034  this->command(0x20);
2035  this->write_lut_(LUT_20_VCOMDC_29_5, sizeof(LUT_20_VCOMDC_29_5));
2036  this->command(0x21);
2037  this->write_lut_(LUT_21_WW_29_5, sizeof(LUT_21_WW_29_5));
2038  this->command(0x22);
2039  this->write_lut_(LUT_22_BW_29_5, sizeof(LUT_22_BW_29_5));
2040  this->command(0x23);
2041  this->write_lut_(LUT_23_WB_29_5, sizeof(LUT_23_WB_29_5));
2042  this->command(0x24);
2043  this->write_lut_(LUT_24_BB_29_5, sizeof(LUT_24_BB_29_5));
2044  ESP_LOGD(TAG, "initialized full update");
2045 }
2046 
2047 // initialzie for partial update
2049  this->init_display_();
2050  this->command(0x82); // vcom_DC setting
2051  this->data(0x08);
2052  this->command(0X50); // VCOM AND DATA INTERVAL SETTING
2053  this->data(0x17); // WBmode:VBDF 17|D7 VBDW 97 VBDB 57 WBRmode:VBDF F7 VBDW 77 VBDB 37 VBDR B7
2054  this->command(0x20);
2055  this->write_lut_(LUT_20_VCOMDC_PARTIAL_29_5, sizeof(LUT_20_VCOMDC_PARTIAL_29_5));
2056  this->command(0x21);
2057  this->write_lut_(LUT_21_WW_PARTIAL_29_5, sizeof(LUT_21_WW_PARTIAL_29_5));
2058  this->command(0x22);
2059  this->write_lut_(LUT_22_BW_PARTIAL_29_5, sizeof(LUT_22_BW_PARTIAL_29_5));
2060  this->command(0x23);
2061  this->write_lut_(LUT_23_WB_PARTIAL_29_5, sizeof(LUT_23_WB_PARTIAL_29_5));
2062  this->command(0x24);
2063  this->write_lut_(LUT_24_BB_PARTIAL_29_5, sizeof(LUT_24_BB_PARTIAL_29_5));
2064  ESP_LOGD(TAG, "initialized partial update");
2065 }
2066 
2068  bool full_update = this->at_update_ == 0;
2069  if (full_update) {
2070  this->init_full_();
2071  } else {
2072  this->init_partial_();
2073  this->command(0x91); // partial in
2074  // set partial window
2075  this->command(0x90);
2076  // this->data(0);
2077  this->data(0);
2078  // this->data(0);
2079  this->data((this->get_width_internal() - 1) % 256);
2080  this->data(0);
2081  this->data(0);
2082  this->data(((this->get_height_internal() - 1)) / 256);
2083  this->data(((this->get_height_internal() - 1)) % 256);
2084  this->data(0x01);
2085  }
2086  // input old buffer data
2087  this->command(0x10);
2088  delay(2);
2089  this->start_data_();
2090  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
2091  this->write_byte(this->old_buffer_[i]);
2092  }
2093  this->end_data_();
2094  delay(2);
2095 
2096  // COMMAND DATA START TRANSMISSION 2 (B/W only)
2097  this->command(0x13);
2098  delay(2);
2099  this->start_data_();
2100  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
2101  this->write_byte(this->buffer_[i]);
2102  this->old_buffer_[i] = this->buffer_[i];
2103  }
2104  this->end_data_();
2105  delay(2);
2106 
2107  // COMMAND DISPLAY REFRESH
2108  this->command(0x12);
2109  delay(2);
2110  this->wait_until_idle_();
2111 
2112  if (full_update) {
2113  ESP_LOGD(TAG, "full update done");
2114  } else {
2115  this->command(0x92); // partial out
2116  ESP_LOGD(TAG, "partial update done");
2117  }
2118 
2119  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
2120  // COMMAND deep sleep
2121  this->deep_sleep();
2122 }
2123 
2124 void GDEW029T5::write_lut_(const uint8_t *lut, const uint8_t size) {
2125  // COMMAND WRITE LUT REGISTER
2126  this->start_data_();
2127  for (uint8_t i = 0; i < size; i++)
2128  this->write_byte(lut[i]);
2129  this->end_data_();
2130 }
2131 
2132 void GDEW029T5::set_full_update_every(uint32_t full_update_every) { this->full_update_every_ = full_update_every; }
2133 
2134 int GDEW029T5::get_width_internal() { return 128; }
2135 int GDEW029T5::get_height_internal() { return 296; }
2137  LOG_DISPLAY("", "Waveshare E-Paper (Good Display)", this);
2138  ESP_LOGCONFIG(TAG, " Model: 2.9in Greyscale GDEW029T5");
2139  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2140  LOG_PIN(" DC Pin: ", this->dc_pin_);
2141  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2142  ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
2143  LOG_UPDATE_INTERVAL(this);
2144 }
2145 
2146 // ========================================================
2147 // Good Display 1.54in black/white/grey GDEW0154M09
2148 // As used in M5Stack Core Ink
2149 // Datasheet:
2150 // - https://v4.cecdn.yun300.cn/100001_1909185148/GDEW0154M09-200709.pdf
2151 // - https://github.com/m5stack/M5Core-Ink
2152 // Reference code from GoodDisplay:
2153 // - https://github.com/GoodDisplay/E-paper-Display-Library-of-GoodDisplay/
2154 // -> /Monochrome_E-paper-Display/1.54inch_JD79653_GDEW0154M09_200x200/ESP32-Arduino%20IDE/GDEW0154M09_Arduino.ino
2155 // M5Stack Core Ink spec:
2156 // - https://docs.m5stack.com/en/core/coreink
2157 // ========================================================
2158 
2160  this->init_internal_();
2162  this->lastbuff_ = allocator.allocate(this->get_buffer_length_());
2163  if (this->lastbuff_ != nullptr) {
2164  memset(this->lastbuff_, 0xff, sizeof(uint8_t) * this->get_buffer_length_());
2165  }
2166  this->clear_();
2167 }
2168 
2169 void GDEW0154M09::reset_() {
2170  // RST is inverse from other einks in this project
2171  if (this->reset_pin_ != nullptr) {
2172  this->reset_pin_->digital_write(false);
2173  delay(10);
2174  this->reset_pin_->digital_write(true);
2175  delay(10);
2176  }
2177 }
2178 
2179 void GDEW0154M09::init_internal_() {
2180  this->reset_();
2181 
2182  // clang-format off
2183  // 200x200 resolution: 11
2184  // LUT from OTP: 0
2185  // B/W mode (doesn't work): 1
2186  // scan-up: 1
2187  // shift-right: 1
2188  // booster ON: 1
2189  // no soft reset: 1
2190  const uint8_t panel_setting_1 = 0b11011111;
2191 
2192  // VCOM status off 0
2193  // Temp sensing default 1
2194  // VGL Power Off Floating 1
2195  // NORG expect refresh 1
2196  // VCOM Off on displ off 0
2197  const uint8_t panel_setting_2 = 0b01110;
2198 
2199  const uint8_t wf_t0154_cz_b3_list[] = {
2200  11, // 11 commands in list
2201  CMD_PSR_PANEL_SETTING, 2, panel_setting_1, panel_setting_2,
2202  CMD_UNDOCUMENTED_0x4D, 1, 0x55,
2203  CMD_UNDOCUMENTED_0xAA, 1, 0x0f,
2204  CMD_UNDOCUMENTED_0xE9, 1, 0x02,
2205  CMD_UNDOCUMENTED_0xB6, 1, 0x11,
2206  CMD_UNDOCUMENTED_0xF3, 1, 0x0a,
2207  CMD_TRES_RESOLUTION_SETTING, 3, 0xc8, 0x00, 0xc8,
2208  CMD_TCON_TCONSETTING, 1, 0x00,
2209  CMD_CDI_VCOM_DATA_INTERVAL, 1, 0xd7,
2210  CMD_PWS_POWER_SAVING, 1, 0x00,
2211  CMD_PON_POWER_ON, 0
2212  };
2213  // clang-format on
2214 
2215  this->write_init_list_(wf_t0154_cz_b3_list);
2216  delay(100); // NOLINT
2217  this->wait_until_idle_();
2218 }
2219 
2220 void GDEW0154M09::write_init_list_(const uint8_t *list) {
2221  uint8_t list_limit = list[0];
2222  uint8_t *start_ptr = ((uint8_t *) list + 1);
2223  for (uint8_t i = 0; i < list_limit; i++) {
2224  this->command(*(start_ptr + 0));
2225  for (uint8_t dnum = 0; dnum < *(start_ptr + 1); dnum++) {
2226  this->data(*(start_ptr + 2 + dnum));
2227  }
2228  start_ptr += (*(start_ptr + 1) + 2);
2229  }
2230 }
2231 
2232 void GDEW0154M09::clear_() {
2233  uint32_t pixsize = this->get_buffer_length_();
2234  for (uint8_t j = 0; j < 2; j++) {
2235  this->command(CMD_DTM1_DATA_START_TRANS);
2236  for (int count = 0; count < pixsize; count++) {
2237  this->data(0x00);
2238  }
2239  this->command(CMD_DTM2_DATA_START_TRANS2);
2240  for (int count = 0; count < pixsize; count++) {
2241  this->data(0xff);
2242  }
2243  this->command(CMD_DISPLAY_REFRESH);
2244  delay(10);
2245  this->wait_until_idle_();
2246  }
2247 }
2248 
2250  this->init_internal_();
2251  // "Mode 0 display" for now
2252  this->command(CMD_DTM1_DATA_START_TRANS);
2253  for (int i = 0; i < this->get_buffer_length_(); i++) {
2254  this->data(0xff);
2255  }
2256  this->command(CMD_DTM2_DATA_START_TRANS2); // write 'new' data to SRAM
2257  for (int i = 0; i < this->get_buffer_length_(); i++) {
2258  this->data(this->buffer_[i]);
2259  }
2260  this->command(CMD_DISPLAY_REFRESH);
2261  delay(10);
2262  this->wait_until_idle_();
2263  this->deep_sleep();
2264 }
2265 
2267  // COMMAND DEEP SLEEP
2268  this->command(CMD_POF_POWER_OFF);
2269  this->wait_until_idle_();
2270  delay(1000); // NOLINT
2271  this->command(CMD_DSLP_DEEP_SLEEP);
2272  this->data(DATA_DSLP_DEEP_SLEEP);
2273 }
2274 
2275 int GDEW0154M09::get_width_internal() { return 200; }
2278  LOG_DISPLAY("", "M5Stack CoreInk E-Paper (Good Display)", this);
2279  ESP_LOGCONFIG(TAG, " Model: 1.54in Greyscale GDEW0154M09");
2280  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2281  LOG_PIN(" DC Pin: ", this->dc_pin_);
2282  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2283  LOG_UPDATE_INTERVAL(this);
2284 }
2285 
2286 // ========================================================
2287 // Good Display 4.2in black/white GDEY042T81 (SSD1683)
2288 // Product page:
2289 // - https://www.good-display.com/product/386.html
2290 // Datasheet:
2291 // - https://v4.cecdn.yun300.cn/100001_1909185148/GDEY042T81.pdf
2292 // - https://v4.cecdn.yun300.cn/100001_1909185148/SSD1683.PDF
2293 // Reference code from GoodDisplay:
2294 // - https://www.good-display.com/companyfile/1572.html (2024-08-01 15:40:41)
2295 // Other reference code:
2296 // - https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp
2297 // ========================================================
2298 
2300  this->init_display_();
2301  ESP_LOGD(TAG, "Initialization complete, set the display to deep sleep");
2302  this->deep_sleep();
2303 }
2304 
2305 // conflicting documentation / examples regarding reset timings
2306 // https://v4.cecdn.yun300.cn/100001_1909185148/SSD1683.PDF -> 10ms
2307 // GD sample code (Display_EPD_W21.cpp, see above) -> 10 ms
2308 // https://v4.cecdn.yun300.cn/100001_1909185148/GDEY042T81.pdf (section 14.2) -> 0.2ms (200us)
2309 // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L351
2310 // -> 10ms
2311 // 10 ms seems to work, so we use this
2313 
2314 void GDEY042T81::reset_() {
2315  if (this->reset_pin_ != nullptr) {
2316  this->reset_pin_->digital_write(false);
2317  delay(reset_duration_); // NOLINT
2318  this->reset_pin_->digital_write(true);
2319  delay(reset_duration_); // NOLINT
2320  }
2321 }
2322 
2323 void GDEY042T81::init_display_() {
2324  this->reset_();
2325 
2326  this->wait_until_idle_();
2327  this->command(0x12); // SWRESET
2328  this->wait_until_idle_();
2329 
2330  // Specify number of lines for the driver: 300 (MUX 300)
2331  // https://v4.cecdn.yun300.cn/100001_1909185148/SSD1683.PDF (section 8.1)
2332  // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L354
2333  this->command(0x01); // driver output control
2334  this->data(0x2B); // (height - 1) % 256
2335  this->data(0x01); // (height - 1) / 256
2336  this->data(0x00);
2337 
2338  // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L360
2339  this->command(0x3C); // BorderWaveform
2340  this->data(0x01);
2341  this->command(0x18); // Read built-in temperature sensor
2342  this->data(0x80);
2343 
2344  // GD sample code (Display_EPD_W21.cpp@90ff)
2345  this->command(0x11); // data entry mode
2346  this->data(0x03);
2347  // set windows (0,0,400,300)
2348  this->command(0x44); // set Ram-X address start/end position
2349  this->data(0);
2350  this->data(0x31); // (width / 8 -1)
2351 
2352  this->command(0x45); // set Ram-y address start/end position
2353  this->data(0);
2354  this->data(0);
2355  this->data(0x2B); // (height - 1) % 256
2356  this->data(0x01); // (height - 1) / 256
2357 
2358  // set cursor (0,0)
2359  this->command(0x4E); // set RAM x address count to 0;
2360  this->data(0);
2361  this->command(0x4F); // set RAM y address count to 0;
2362  this->data(0);
2363  this->data(0);
2364 
2365  this->wait_until_idle_();
2366 }
2367 
2368 // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L366
2369 void GDEY042T81::update_full_() {
2370  this->command(0x21); // display update control
2371  this->data(0x40); // bypass RED as 0
2372  this->data(0x00); // single chip application
2373 
2374  // only ever do a fast update because slow updates are only relevant
2375  // for lower operating temperatures
2376  // see
2377  // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_290_GDEY029T94.h#L30
2378  //
2379  // Should slow/fast updates be made configurable similar to how GxEPD2 does it? No idea if anyone would need it...
2380  this->command(0x1A); // Write to temperature register
2381  this->data(0x6E);
2382  this->command(0x22);
2383  this->data(0xd7);
2384 
2385  this->command(0x20);
2386  this->wait_until_idle_();
2387 }
2388 
2389 // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L389
2390 void GDEY042T81::update_part_() {
2391  this->command(0x21); // display update control
2392  this->data(0x00); // RED normal
2393  this->data(0x00); // single chip application
2394 
2395  this->command(0x22);
2396  this->data(0xfc);
2397 
2398  this->command(0x20);
2399  this->wait_until_idle_();
2400 }
2401 
2403  ESP_LOGD(TAG, "Wake up the display");
2404  this->init_display_();
2405 
2406  if (!this->wait_until_idle_()) {
2407  this->status_set_warning();
2408  ESP_LOGE(TAG, "Failed to perform update, display is busy");
2409  return;
2410  }
2411 
2412  // basic code structure copied from WaveshareEPaper2P9InV2R2
2413  if (this->full_update_every_ == 1) {
2414  ESP_LOGD(TAG, "Full update");
2415  // do single full update
2416  this->command(0x24);
2417  this->start_data_();
2418  this->write_array(this->buffer_, this->get_buffer_length_());
2419  this->end_data_();
2420 
2421  // TurnOnDisplay
2422  this->update_full_();
2423  return;
2424  }
2425 
2426  // if (this->full_update_every_ == 1 ||
2427  if (this->at_update_ == 0) {
2428  ESP_LOGD(TAG, "Update");
2429  // do base update
2430  this->command(0x24);
2431  this->start_data_();
2432  this->write_array(this->buffer_, this->get_buffer_length_());
2433  this->end_data_();
2434 
2435  this->command(0x26);
2436  this->start_data_();
2437  this->write_array(this->buffer_, this->get_buffer_length_());
2438  this->end_data_();
2439 
2440  // TurnOnDisplay;
2441  this->update_full_();
2442  } else {
2443  // do partial update (full screen)
2444  // no need to load a LUT for GoodDisplays as they seem to have the LUT onboard
2445  // GD example code (Display_EPD_W21.cpp@283ff)
2446  //
2447  // not setting the BorderWaveform here again (contrary to the GD example) because according to
2448  // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L358
2449  // it seems to be enough to set it during display initialization
2450  ESP_LOGD(TAG, "Partial update");
2451  this->reset_();
2452  if (!this->wait_until_idle_()) {
2453  this->status_set_warning();
2454  ESP_LOGE(TAG, "Failed to perform partial update, display is busy");
2455  return;
2456  }
2457 
2458  this->command(0x24);
2459  this->start_data_();
2460  this->write_array(this->buffer_, this->get_buffer_length_());
2461  this->end_data_();
2462 
2463  // TurnOnDisplay
2464  this->update_part_();
2465  }
2466 
2467  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
2468  this->wait_until_idle_();
2469  ESP_LOGD(TAG, "Set the display back to deep sleep");
2470  this->deep_sleep();
2471 }
2472 void GDEY042T81::set_full_update_every(uint32_t full_update_every) { this->full_update_every_ = full_update_every; }
2473 int GDEY042T81::get_width_internal() { return 400; }
2474 int GDEY042T81::get_height_internal() { return 300; }
2475 uint32_t GDEY042T81::idle_timeout_() { return 5000; }
2477  LOG_DISPLAY("", "GoodDisplay E-Paper", this);
2478  ESP_LOGCONFIG(TAG, " Model: 4.2in B/W GDEY042T81");
2479  ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
2480  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2481  LOG_PIN(" DC Pin: ", this->dc_pin_);
2482  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2483  LOG_UPDATE_INTERVAL(this);
2484 }
2485 
2486 static const uint8_t LUT_VCOM_DC_4_2[] = {
2487  0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x17, 0x17, 0x00, 0x00, 0x02, 0x00, 0x0A, 0x01,
2488  0x00, 0x00, 0x01, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2489  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2490 };
2491 static const uint8_t LUT_WHITE_TO_WHITE_4_2[] = {
2492  0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A,
2493  0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
2494  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2495 };
2496 static const uint8_t LUT_BLACK_TO_WHITE_4_2[] = {
2497  0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A,
2498  0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
2499  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2500 };
2501 
2502 static const uint8_t LUT_BLACK_TO_BLACK_4_2[] = {
2503  0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A,
2504  0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
2505  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2506 };
2507 
2508 static const uint8_t LUT_WHITE_TO_BLACK_4_2[] = {
2509  0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A,
2510  0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
2511  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2512 };
2513 
2515  // https://www.waveshare.com/w/upload/7/7f/4.2inch-e-paper-b-specification.pdf - page 8
2516 
2517  // COMMAND POWER SETTING
2518  this->command(0x01);
2519  this->data(0x03); // VDS_EN, VDG_EN
2520  this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
2521  this->data(0x2B); // VDH
2522  this->data(0x2B); // VDL
2523  this->data(0xFF); // VDHR
2524 
2525  // COMMAND BOOSTER SOFT START
2526  this->command(0x06);
2527  this->data(0x17); // PHA
2528  this->data(0x17); // PHB
2529  this->data(0x17); // PHC
2530 
2531  // COMMAND POWER ON
2532  this->command(0x04);
2533  this->wait_until_idle_();
2534  delay(10);
2535  // COMMAND PANEL SETTING
2536  this->command(0x00);
2537  this->data(0xBF); // KW-BF KWR-AF BWROTP 0f
2538  this->data(0x0B);
2539  // COMMAND PLL CONTROL
2540  this->command(0x30);
2541  this->data(0x3C); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
2542 
2543  delay(2);
2544  // COMMAND LUT FOR VCOM
2545  this->command(0x20);
2546  for (uint8_t i : LUT_VCOM_DC_4_2)
2547  this->data(i);
2548  // COMMAND LUT WHITE TO WHITE
2549  this->command(0x21);
2550  for (uint8_t i : LUT_WHITE_TO_WHITE_4_2)
2551  this->data(i);
2552  // COMMAND LUT BLACK TO WHITE
2553  this->command(0x22);
2554  for (uint8_t i : LUT_BLACK_TO_WHITE_4_2)
2555  this->data(i);
2556  // COMMAND LUT WHITE TO BLACK
2557  this->command(0x23);
2558  for (uint8_t i : LUT_WHITE_TO_BLACK_4_2)
2559  this->data(i);
2560  // COMMAND LUT BLACK TO BLACK
2561  this->command(0x24);
2562  for (uint8_t i : LUT_BLACK_TO_BLACK_4_2)
2563  this->data(i);
2564 }
2566  // COMMAND RESOLUTION SETTING
2567  this->command(0x61);
2568  this->data(0x01);
2569  this->data(0x90);
2570  this->data(0x01);
2571  this->data(0x2C);
2572 
2573  // COMMAND VCM DC SETTING REGISTER
2574  this->command(0x82);
2575  this->data(0x12);
2576 
2577  // COMMAND VCOM AND DATA INTERVAL SETTING
2578  this->command(0x50);
2579  this->data(0x97);
2580 
2581  // COMMAND DATA START TRANSMISSION 1
2582  this->command(0x10);
2583  delay(2);
2584  this->start_data_();
2585  this->write_array(this->buffer_, this->get_buffer_length_());
2586  this->end_data_();
2587  delay(2);
2588  // COMMAND DATA START TRANSMISSION 2
2589  this->command(0x13);
2590  delay(2);
2591  this->start_data_();
2592  this->write_array(this->buffer_, this->get_buffer_length_());
2593  this->end_data_();
2594  // COMMAND DISPLAY REFRESH
2595  this->command(0x12);
2596 }
2600  LOG_DISPLAY("", "Waveshare E-Paper", this);
2601  ESP_LOGCONFIG(TAG, " Model: 4.2in");
2602  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2603  LOG_PIN(" DC Pin: ", this->dc_pin_);
2604  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2605  LOG_UPDATE_INTERVAL(this);
2606 }
2607 
2608 // ========================================================
2609 // 4.20in Type B (LUT from OTP)
2610 // Datasheet:
2611 // - https://www.waveshare.com/w/upload/2/20/4.2inch-e-paper-module-user-manual-en.pdf
2612 // - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_4in2b_V2.c
2613 // ========================================================
2615  // these exact timings are required for a proper reset/init
2616  this->reset_pin_->digital_write(false);
2617  delay(2);
2618  this->reset_pin_->digital_write(true);
2619  delay(200); // NOLINT
2620 
2621  // COMMAND POWER ON
2622  this->command(0x04);
2623  this->wait_until_idle_();
2624 
2625  // COMMAND PANEL SETTING
2626  this->command(0x00);
2627  this->data(0x0f); // LUT from OTP
2628 }
2629 
2631  // COMMAND DATA START TRANSMISSION 1 (B/W data)
2632  this->command(0x10);
2633  this->start_data_();
2634  this->write_array(this->buffer_, this->get_buffer_length_());
2635  this->end_data_();
2636 
2637  // COMMAND DATA START TRANSMISSION 2 (RED data)
2638  this->command(0x13);
2639  this->start_data_();
2640  for (size_t i = 0; i < this->get_buffer_length_(); i++)
2641  this->write_byte(0xFF);
2642  this->end_data_();
2643  delay(2);
2644 
2645  // COMMAND DISPLAY REFRESH
2646  this->command(0x12);
2647  this->wait_until_idle_();
2648 
2649  // COMMAND POWER OFF
2650  // NOTE: power off < deep sleep
2651  this->command(0x02);
2652 }
2656  LOG_DISPLAY("", "Waveshare E-Paper", this);
2657  ESP_LOGCONFIG(TAG, " Model: 4.2in (B V2)");
2658  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2659  LOG_PIN(" DC Pin: ", this->dc_pin_);
2660  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2661  LOG_UPDATE_INTERVAL(this);
2662 }
2663 
2664 // ========================================================
2665 // 4.20in Type B With Red colour support (LUT from OTP)
2666 // Datasheet:
2667 // - https://www.waveshare.com/w/upload/2/20/4.2inch-e-paper-module-user-manual-en.pdf
2668 // - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_4in2b_V2.c
2669 // The implementation is an adaptation of WaveshareEPaper4P2InBV2 class
2670 // ========================================================
2672  // these exact timings are required for a proper reset/init
2673  this->reset_pin_->digital_write(false);
2674  delay(2);
2675  this->reset_pin_->digital_write(true);
2676  delay(200); // NOLINT
2677 
2678  // COMMAND POWER ON
2679  this->command(0x04);
2680  this->wait_until_idle_();
2681 
2682  // COMMAND PANEL SETTING
2683  this->command(0x00);
2684  this->data(0x0f); // LUT from OTP
2685 }
2686 
2688  const uint32_t buf_len = this->get_buffer_length_() / 2u;
2689 
2690  this->command(0x10); // Send BW data Transmission
2691  delay(2); // Delay to prevent Watchdog error
2692  for (uint32_t i = 0; i < buf_len; ++i) {
2693  this->data(this->buffer_[i]);
2694  }
2695 
2696  this->command(0x13); // Send red data Transmission
2697  delay(2); // Delay to prevent Watchdog error
2698  for (uint32_t i = 0; i < buf_len; ++i) {
2699  // Red color need to flip bit from the buffer. Otherwise, red will conqure the screen!
2700  this->data(~this->buffer_[buf_len + i]);
2701  }
2702 
2703  // COMMAND DISPLAY REFRESH
2704  this->command(0x12);
2705  this->wait_until_idle_();
2706 
2707  // COMMAND POWER OFF
2708  // NOTE: power off < deep sleep
2709  this->command(0x02);
2710 }
2714  LOG_DISPLAY("", "Waveshare E-Paper", this);
2715  ESP_LOGCONFIG(TAG, " Model: 4.2in (B V2) BWR-Mode");
2716  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2717  LOG_PIN(" DC Pin: ", this->dc_pin_);
2718  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2719  LOG_UPDATE_INTERVAL(this);
2720 }
2721 
2723  // COMMAND POWER SETTING
2724  this->command(0x01);
2725  this->data(0x37);
2726  this->data(0x00);
2727 
2728  // COMMAND PANEL SETTING
2729  this->command(0x00);
2730  this->data(0xCF);
2731  this->data(0x0B);
2732 
2733  // COMMAND BOOSTER SOFT START
2734  this->command(0x06);
2735  this->data(0xC7);
2736  this->data(0xCC);
2737  this->data(0x28);
2738 
2739  // COMMAND POWER ON
2740  this->command(0x04);
2741  this->wait_until_idle_();
2742  delay(10);
2743 
2744  // COMMAND PLL CONTROL
2745  this->command(0x30);
2746  this->data(0x3C);
2747 
2748  // COMMAND TEMPERATURE SENSOR CALIBRATION
2749  this->command(0x41);
2750  this->data(0x00);
2751 
2752  // COMMAND VCOM AND DATA INTERVAL SETTING
2753  this->command(0x50);
2754  this->data(0x77);
2755 
2756  // COMMAND TCON SETTING
2757  this->command(0x60);
2758  this->data(0x22);
2759 
2760  // COMMAND RESOLUTION SETTING
2761  this->command(0x61);
2762  this->data(0x02);
2763  this->data(0x58);
2764  this->data(0x01);
2765  this->data(0xC0);
2766 
2767  // COMMAND VCM DC SETTING REGISTER
2768  this->command(0x82);
2769  this->data(0x1E);
2770 
2771  this->command(0xE5);
2772  this->data(0x03);
2773 }
2775  // COMMAND DATA START TRANSMISSION 1
2776  this->command(0x10);
2777 
2778  this->start_data_();
2779  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
2780  uint8_t temp1 = this->buffer_[i];
2781  for (uint8_t j = 0; j < 8; j++) {
2782  uint8_t temp2;
2783  if (temp1 & 0x80) {
2784  temp2 = 0x03;
2785  } else {
2786  temp2 = 0x00;
2787  }
2788 
2789  temp2 <<= 4;
2790  temp1 <<= 1;
2791  j++;
2792  if (temp1 & 0x80) {
2793  temp2 |= 0x03;
2794  } else {
2795  temp2 |= 0x00;
2796  }
2797  temp1 <<= 1;
2798  this->write_byte(temp2);
2799  }
2800 
2801  App.feed_wdt();
2802  }
2803  this->end_data_();
2804 
2805  // COMMAND DISPLAY REFRESH
2806  this->command(0x12);
2807 }
2811  LOG_DISPLAY("", "Waveshare E-Paper", this);
2812  ESP_LOGCONFIG(TAG, " Model: 5.83in");
2813  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2814  LOG_PIN(" DC Pin: ", this->dc_pin_);
2815  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2816  LOG_UPDATE_INTERVAL(this);
2817 }
2818 
2819 // ========================================================
2820 // 5.83in V2
2821 // Datasheet/Specification/Reference:
2822 // - https://www.waveshare.com/w/upload/3/37/5.83inch_e-Paper_V2_Specification.pdf
2823 // - https://github.com/waveshare/e-Paper/blob/master/Arduino/epd5in83_V2/epd5in83_V2.cpp
2824 // ========================================================
2826  // COMMAND POWER SETTING
2827  this->command(0x01);
2828  this->data(0x07);
2829  this->data(0x07);
2830  this->data(0x3f);
2831  this->data(0x3f);
2832 
2833  // COMMAND POWER ON
2834  this->command(0x04);
2835  delay(10);
2836  this->wait_until_idle_();
2837 
2838  // PANNEL SETTING
2839  this->command(0x00);
2840  this->data(0x1F);
2841 
2842  // COMMAND RESOLUTION SETTING
2843  this->command(0x61);
2844  this->data(0x02);
2845  this->data(0x88);
2846  this->data(0x01);
2847  this->data(0xE0);
2848 
2849  this->command(0x15);
2850  this->data(0x00);
2851 
2852  // COMMAND TCON SETTING
2853  this->command(0x60);
2854  this->data(0x22);
2855 
2856  // Do we need this?
2857  // COMMAND PLL CONTROL
2858  this->command(0x30);
2859  this->data(0x3C); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
2860 }
2862  // Reuse the code from WaveshareEPaper4P2In::display()
2863  // COMMAND VCM DC SETTING REGISTER
2864  this->command(0x82);
2865  this->data(0x12);
2866 
2867  // COMMAND VCOM AND DATA INTERVAL SETTING
2868  this->command(0x50);
2869  this->data(0x97);
2870 
2871  // COMMAND DATA START TRANSMISSION 1
2872  this->command(0x10);
2873  delay(2);
2874  this->start_data_();
2875  this->write_array(this->buffer_, this->get_buffer_length_());
2876  this->end_data_();
2877  delay(2);
2878 
2879  // COMMAND DATA START TRANSMISSION 2
2880  this->command(0x13);
2881  delay(2);
2882  this->start_data_();
2883  this->write_array(this->buffer_, this->get_buffer_length_());
2884  this->end_data_();
2885 
2886  // COMMAND DISPLAY REFRESH
2887  this->command(0x12);
2888 }
2892  LOG_DISPLAY("", "Waveshare E-Paper", this);
2893  ESP_LOGCONFIG(TAG, " Model: 5.83inv2");
2894  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2895  LOG_PIN(" DC Pin: ", this->dc_pin_);
2896  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2897  LOG_UPDATE_INTERVAL(this);
2898 }
2899 
2901  // COMMAND POWER SETTING
2902  this->command(0x01);
2903  this->data(0x07);
2904  this->data(0x07); // VGH=20V,VGL=-20V
2905  this->data(0x3f); // VDH=15V
2906  this->data(0x3f); // VDL=-15V
2907  // COMMAND POWER ON
2908  this->command(0x04);
2909  delay(100); // NOLINT
2910  this->wait_until_idle_();
2911  // COMMAND PANEL SETTING
2912  this->command(0x00);
2913  this->data(0x0F); // KW3f, KWR-2F, BWROTP 0f, BWOTP 1f
2914  this->command(0x61); // tres
2915  this->data(0x03); // 800px
2916  this->data(0x20);
2917  this->data(0x01); // 400px
2918  this->data(0xE0);
2919  this->command(0x15);
2920  this->data(0x00);
2921  // COMMAND VCOM AND DATA INTERVAL SETTING
2922  this->command(0x50);
2923  this->data(0x11);
2924  this->data(0x07);
2925  // COMMAND TCON SETTING
2926  this->command(0x60);
2927  this->data(0x22);
2928 
2929  this->command(0x82);
2930  this->data(0x08);
2931  this->command(0x30);
2932  this->data(0x06);
2933 
2934  // COMMAND RESOLUTION SETTING
2935  this->command(0x65);
2936  this->data(0x00);
2937  this->data(0x00); // 800*480
2938  this->data(0x00);
2939  this->data(0x00);
2940 }
2942  // COMMAND DATA START TRANSMISSION 1 (B/W data)
2943  this->command(0x10);
2944  delay(2);
2945  this->start_data_();
2946  this->write_array(this->buffer_, this->get_buffer_length_());
2947  this->end_data_();
2948  delay(2);
2949 
2950  // COMMAND DATA START TRANSMISSION 2 (RED data)
2951  this->command(0x13);
2952  delay(2);
2953  this->start_data_();
2954  for (size_t i = 0; i < this->get_buffer_length_(); i++)
2955  this->write_byte(0x00);
2956  this->end_data_();
2957  delay(2);
2958 
2959  // COMMAND DISPLAY REFRESH
2960  this->command(0x12);
2961  delay(100); // NOLINT
2962  this->wait_until_idle_();
2963  this->deep_sleep();
2964 }
2968  LOG_DISPLAY("", "Waveshare E-Paper", this);
2969  ESP_LOGCONFIG(TAG, " Model: 7.5in-bv2");
2970  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2971  LOG_PIN(" DC Pin: ", this->dc_pin_);
2972  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2973  LOG_UPDATE_INTERVAL(this);
2974 }
2975 
2978  if (this->busy_pin_ == nullptr) {
2979  return true;
2980  }
2981 
2982  const uint32_t start = millis();
2983  while (this->busy_pin_->digital_read()) {
2984  this->command(0x71);
2985  if (millis() - start > this->idle_timeout_()) {
2986  ESP_LOGI(TAG, "Timeout while displaying image!");
2987  return false;
2988  }
2989  App.feed_wdt();
2990  delay(10);
2991  }
2992  delay(200); // NOLINT
2993  return true;
2994 };
2996  this->reset_();
2997 
2998  // COMMAND POWER SETTING
2999  this->command(0x01);
3000 
3001  // 1-0=11: internal power
3002  this->data(0x07);
3003  this->data(0x17); // VGH&VGL
3004  this->data(0x3F); // VSH
3005  this->data(0x26); // VSL
3006  this->data(0x11); // VSHR
3007 
3008  // VCOM DC Setting
3009  this->command(0x82);
3010  this->data(0x24); // VCOM
3011 
3012  // Booster Setting
3013  this->command(0x06);
3014  this->data(0x27);
3015  this->data(0x27);
3016  this->data(0x2F);
3017  this->data(0x17);
3018 
3019  // POWER ON
3020  this->command(0x04);
3021 
3022  delay(100); // NOLINT
3023  this->wait_until_idle_();
3024  // COMMAND PANEL SETTING
3025  this->command(0x00);
3026  this->data(0x3F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
3027 
3028  // COMMAND RESOLUTION SETTING
3029  this->command(0x61);
3030  this->data(0x03); // source 800
3031  this->data(0x20);
3032  this->data(0x01); // gate 480
3033  this->data(0xE0);
3034  // COMMAND ...?
3035  this->command(0x15);
3036  this->data(0x00);
3037  // COMMAND VCOM AND DATA INTERVAL SETTING
3038  this->command(0x50);
3039  this->data(0x10);
3040  this->data(0x00);
3041  // COMMAND TCON SETTING
3042  this->command(0x60);
3043  this->data(0x22);
3044  // Resolution setting
3045  this->command(0x65);
3046  this->data(0x00);
3047  this->data(0x00); // 800*480
3048  this->data(0x00);
3049  this->data(0x00);
3050 
3051  uint8_t lut_vcom_7_i_n5_v2[] = {
3052  0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0xF, 0x1, 0xF, 0x1, 0x2, 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
3053  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3054  };
3055 
3056  uint8_t lut_ww_7_i_n5_v2[] = {
3057  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
3058  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3059  };
3060 
3061  uint8_t lut_bw_7_i_n5_v2[] = {
3062  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
3063  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3064  };
3065 
3066  uint8_t lut_wb_7_i_n5_v2[] = {
3067  0x80, 0xF, 0xF, 0x0, 0x0, 0x3, 0x84, 0xF, 0x1, 0xF, 0x1, 0x4, 0x40, 0xF, 0xF, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
3068  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3069  };
3070 
3071  uint8_t lut_bb_7_i_n5_v2[] = {
3072  0x80, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x40, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
3073  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3074  };
3075 
3076  uint8_t count;
3077  this->command(0x20); // VCOM
3078  for (count = 0; count < 42; count++)
3079  this->data(lut_vcom_7_i_n5_v2[count]);
3080 
3081  this->command(0x21); // LUTBW
3082  for (count = 0; count < 42; count++)
3083  this->data(lut_ww_7_i_n5_v2[count]);
3084 
3085  this->command(0x22); // LUTBW
3086  for (count = 0; count < 42; count++)
3087  this->data(lut_bw_7_i_n5_v2[count]);
3088 
3089  this->command(0x23); // LUTWB
3090  for (count = 0; count < 42; count++)
3091  this->data(lut_wb_7_i_n5_v2[count]);
3092 
3093  this->command(0x24); // LUTBB
3094  for (count = 0; count < 42; count++)
3095  this->data(lut_bb_7_i_n5_v2[count]);
3096 };
3098  this->init_display_();
3099  uint32_t buf_len = this->get_buffer_length_();
3100 
3101  this->command(0x10);
3102  for (uint32_t i = 0; i < buf_len; i++) {
3103  this->data(0xFF);
3104  }
3105 
3106  this->command(0x13); // Start Transmission
3107  delay(2);
3108  for (uint32_t i = 0; i < buf_len; i++) {
3109  this->data(~this->buffer_[i]);
3110  }
3111 
3112  this->command(0x12); // Display Refresh
3113  delay(100); // NOLINT
3114  this->wait_until_idle_();
3115  this->deep_sleep();
3116 }
3120  LOG_DISPLAY("", "Waveshare E-Paper", this);
3121  ESP_LOGCONFIG(TAG, " Model: 7.5in-bv3");
3122  LOG_PIN(" Reset Pin: ", this->reset_pin_);
3123  LOG_PIN(" DC Pin: ", this->dc_pin_);
3124  LOG_PIN(" Busy Pin: ", this->busy_pin_);
3125  LOG_UPDATE_INTERVAL(this);
3126 }
3127 
3130  if (this->busy_pin_ == nullptr) {
3131  return true;
3132  }
3133 
3134  const uint32_t start = millis();
3135  while (this->busy_pin_->digital_read()) {
3136  this->command(0x71);
3137  if (millis() - start > this->idle_timeout_()) {
3138  ESP_LOGI(TAG, "Timeout while displaying image!");
3139  return false;
3140  }
3141  App.feed_wdt();
3142  delay(10);
3143  }
3144  delay(200); // NOLINT
3145  return true;
3146 };
3148  this->reset_();
3149 
3150  // COMMAND POWER SETTING
3151  this->command(0x01);
3152 
3153  // 1-0=11: internal power
3154  this->data(0x07); // VRS_EN=1, VS_EN=1, VG_EN=1
3155  this->data(0x17); // VGH&VGL ??? VCOM_SLEW=1 but this is fixed, VG_LVL[2:0]=111 => VGH=20V VGL=-20V, it could be 0x07
3156  this->data(0x3F); // VSH=15V?
3157  this->data(0x26); // VSL=-9.4V?
3158  this->data(0x11); // VSHR=5.8V?
3159 
3160  // VCOM DC Setting
3161  this->command(0x82);
3162  this->data(0x24); // VCOM=-1.9V
3163 
3164  // POWER ON
3165  this->command(0x04);
3166  delay(100); // NOLINT
3167  this->wait_until_idle_();
3168 
3169  // COMMAND PANEL SETTING
3170  this->command(0x00);
3171  this->data(0x0F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
3172 
3173  // COMMAND RESOLUTION SETTING
3174  this->command(0x61);
3175  this->data(0x03); // source 800
3176  this->data(0x20);
3177  this->data(0x01); // gate 480
3178  this->data(0xE0);
3179 
3180  // COMMAND VCOM AND DATA INTERVAL SETTING
3181  this->command(0x50);
3182  this->data(0x20);
3183  this->data(0x00);
3184 
3185  // COMMAND TCON SETTING
3186  this->command(0x60);
3187  this->data(0x22);
3188 
3189  // Resolution setting
3190  this->command(0x65);
3191  this->data(0x00);
3192  this->data(0x00); // 800*480
3193  this->data(0x00);
3194  this->data(0x00);
3195 };
3197  this->init_display_();
3198  const uint32_t buf_len = this->get_buffer_length_() / 2u;
3199 
3200  this->command(0x10); // Send BW data Transmission
3201  delay(2);
3202  for (uint32_t i = 0; i < buf_len; i++) {
3203  this->data(this->buffer_[i]);
3204  }
3205 
3206  this->command(0x13); // Send red data Transmission
3207  delay(2);
3208  for (uint32_t i = 0; i < buf_len; i++) {
3209  this->data(this->buffer_[i + buf_len]);
3210  }
3211 
3212  this->command(0x12); // Display Refresh
3213  delay(100); // NOLINT
3214  this->wait_until_idle_();
3215  this->deep_sleep();
3216 }
3220  LOG_DISPLAY("", "Waveshare E-Paper", this);
3221  ESP_LOGCONFIG(TAG, " Model: 7.5in-bv3 BWR-Mode");
3222  LOG_PIN(" Reset Pin: ", this->reset_pin_);
3223  LOG_PIN(" DC Pin: ", this->dc_pin_);
3224  LOG_PIN(" Busy Pin: ", this->busy_pin_);
3225  LOG_UPDATE_INTERVAL(this);
3226 }
3227 
3229  // COMMAND POWER SETTING
3230  this->command(0x01);
3231  this->data(0x37);
3232  this->data(0x00);
3233  // COMMAND PANEL SETTING
3234  this->command(0x00);
3235  this->data(0xCF);
3236  this->data(0x0B);
3237  // COMMAND BOOSTER SOFT START
3238  this->command(0x06);
3239  this->data(0xC7);
3240  this->data(0xCC);
3241  this->data(0x28);
3242  // COMMAND POWER ON
3243  this->command(0x04);
3244  this->wait_until_idle_();
3245  delay(10);
3246  // COMMAND PLL CONTROL
3247  this->command(0x30);
3248  this->data(0x3C);
3249  // COMMAND TEMPERATURE SENSOR CALIBRATION
3250  this->command(0x41);
3251  this->data(0x00);
3252  // COMMAND VCOM AND DATA INTERVAL SETTING
3253  this->command(0x50);
3254  this->data(0x77);
3255  // COMMAND TCON SETTING
3256  this->command(0x60);
3257  this->data(0x22);
3258  // COMMAND RESOLUTION SETTING
3259  this->command(0x61);
3260  this->data(0x02);
3261  this->data(0x80);
3262  this->data(0x01);
3263  this->data(0x80);
3264  // COMMAND VCM DC SETTING REGISTER
3265  this->command(0x82);
3266  this->data(0x1E);
3267  this->command(0xE5);
3268  this->data(0x03);
3269 }
3271  // COMMAND DATA START TRANSMISSION 1
3272  this->command(0x10);
3273  this->start_data_();
3274  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
3275  uint8_t temp1 = this->buffer_[i];
3276  for (uint8_t j = 0; j < 8; j++) {
3277  uint8_t temp2;
3278  if (temp1 & 0x80) {
3279  temp2 = 0x03;
3280  } else {
3281  temp2 = 0x00;
3282  }
3283  temp2 <<= 4;
3284  temp1 <<= 1;
3285  j++;
3286  if (temp1 & 0x80) {
3287  temp2 |= 0x03;
3288  } else {
3289  temp2 |= 0x00;
3290  }
3291  temp1 <<= 1;
3292  this->write_byte(temp2);
3293  }
3294  App.feed_wdt();
3295  }
3296  this->end_data_();
3297  // COMMAND DISPLAY REFRESH
3298  this->command(0x12);
3299 }
3303  LOG_DISPLAY("", "Waveshare E-Paper", this);
3304  ESP_LOGCONFIG(TAG, " Model: 7.5in");
3305  LOG_PIN(" Reset Pin: ", this->reset_pin_);
3306  LOG_PIN(" DC Pin: ", this->dc_pin_);
3307  LOG_PIN(" Busy Pin: ", this->busy_pin_);
3308  LOG_UPDATE_INTERVAL(this);
3309 }
3311  if (this->buffers_[0] == nullptr) {
3312  ESP_LOGE(TAG, "Buffer unavailable!");
3313  return;
3314  }
3315 
3316  this->reset_();
3317  delay(20);
3318  this->wait_until_idle_();
3319 
3320  // COMMAND CMDH
3321  this->command(0xAA);
3322  this->data(0x49);
3323  this->data(0x55);
3324  this->data(0x20);
3325  this->data(0x08);
3326  this->data(0x09);
3327  this->data(0x18);
3328 
3329  this->command(0x01);
3330  this->data(0x3F);
3331  this->data(0x00);
3332  this->data(0x32);
3333  this->data(0x2A);
3334  this->data(0x0E);
3335  this->data(0x2A);
3336 
3337  this->command(0x00);
3338  this->data(0x5F);
3339  this->data(0x69);
3340 
3341  this->command(0x03);
3342  this->data(0x00);
3343  this->data(0x54);
3344  this->data(0x00);
3345  this->data(0x44);
3346 
3347  this->command(0x05);
3348  this->data(0x40);
3349  this->data(0x1F);
3350  this->data(0x1F);
3351  this->data(0x2C);
3352 
3353  this->command(0x06);
3354  this->data(0x6F);
3355  this->data(0x1F);
3356  this->data(0x1F);
3357  this->data(0x22);
3358 
3359  this->command(0x08);
3360  this->data(0x6F);
3361  this->data(0x1F);
3362  this->data(0x1F);
3363  this->data(0x22);
3364 
3365  // COMMAND IPC
3366  this->command(0x13);
3367  this->data(0x00);
3368  this->data(0x04);
3369 
3370  this->command(0x30);
3371  this->data(0x3C);
3372 
3373  // COMMAND TSE
3374  this->command(0x41);
3375  this->data(0x00);
3376 
3377  this->command(0x50);
3378  this->data(0x3F);
3379 
3380  this->command(0x60);
3381  this->data(0x02);
3382  this->data(0x00);
3383 
3384  this->command(0x61);
3385  this->data(0x03);
3386  this->data(0x20);
3387  this->data(0x01);
3388  this->data(0xE0);
3389 
3390  this->command(0x82);
3391  this->data(0x1E);
3392 
3393  this->command(0x84);
3394  this->data(0x00);
3395 
3396  // COMMAND AGID
3397  this->command(0x86);
3398  this->data(0x00);
3399 
3400  this->command(0xE3);
3401  this->data(0x2F);
3402 
3403  // COMMAND CCSET
3404  this->command(0xE0);
3405  this->data(0x00);
3406 
3407  // COMMAND TSSET
3408  this->command(0xE6);
3409  this->data(0x00);
3410 
3411  ESP_LOGI(TAG, "Display initialized successfully");
3412 }
3414  if (this->buffers_[0] == nullptr) {
3415  ESP_LOGE(TAG, "Buffer unavailable!");
3416  return;
3417  }
3418 
3419  // INITIALIZATION
3420  ESP_LOGI(TAG, "Initialise the display");
3421  this->initialize();
3422 
3423  // COMMAND DATA START TRANSMISSION
3424  ESP_LOGI(TAG, "Sending data to the display");
3425  this->command(0x10);
3426  uint32_t small_buffer_length = this->get_buffer_length_() / NUM_BUFFERS;
3427  uint8_t byte_to_send;
3428  for (auto &buffer : this->buffers_) {
3429  for (uint32_t buffer_pos = 0; buffer_pos < small_buffer_length; buffer_pos += 3) {
3430  std::bitset<24> triplet =
3431  buffer[buffer_pos + 0] << 16 | buffer[buffer_pos + 1] << 8 | buffer[buffer_pos + 2] << 0;
3432  // 8 bitset<3> are stored in 3 bytes
3433  // |aaabbbaa|abbbaaab|bbaaabbb|
3434  // | byte 1 | byte 2 | byte 3 |
3435  byte_to_send = ((triplet >> 17).to_ulong() & 0b01110000) | ((triplet >> 18).to_ulong() & 0b00000111);
3436  this->data(byte_to_send);
3437 
3438  byte_to_send = ((triplet >> 11).to_ulong() & 0b01110000) | ((triplet >> 12).to_ulong() & 0b00000111);
3439  this->data(byte_to_send);
3440 
3441  byte_to_send = ((triplet >> 5).to_ulong() & 0b01110000) | ((triplet >> 6).to_ulong() & 0b00000111);
3442  this->data(byte_to_send);
3443 
3444  byte_to_send = ((triplet << 1).to_ulong() & 0b01110000) | ((triplet << 0).to_ulong() & 0b00000111);
3445  this->data(byte_to_send);
3446  }
3447  App.feed_wdt();
3448  }
3449 
3450  // COMMAND POWER ON
3451  ESP_LOGI(TAG, "Power on the display");
3452  this->command(0x04);
3453  this->wait_until_idle_();
3454 
3455  // COMMAND REFRESH SCREEN
3456  ESP_LOGI(TAG, "Refresh the display");
3457  this->command(0x12);
3458  this->data(0x00);
3459  this->wait_until_idle_();
3460 
3461  // COMMAND POWER OFF
3462  ESP_LOGI(TAG, "Power off the display");
3463  this->command(0x02);
3464  this->data(0x00);
3465  this->wait_until_idle_();
3466 
3467  ESP_LOGI(TAG, "Set the display to deep sleep");
3468  this->command(0x07);
3469  this->data(0xA5);
3470 }
3473 uint32_t WaveshareEPaper7P3InF::idle_timeout_() { return 35000; }
3475  LOG_DISPLAY("", "Waveshare E-Paper", this);
3476  ESP_LOGCONFIG(TAG, " Model: 7.3in-F");
3477  LOG_PIN(" Reset Pin: ", this->reset_pin_);
3478  LOG_PIN(" DC Pin: ", this->dc_pin_);
3479  LOG_PIN(" Busy Pin: ", this->busy_pin_);
3480  LOG_UPDATE_INTERVAL(this);
3481 }
3482 
3484  if (this->busy_pin_ == nullptr) {
3485  return true;
3486  }
3487  const uint32_t start = millis();
3488  while (this->busy_pin_->digital_read()) {
3489  if (millis() - start > this->idle_timeout_()) {
3490  ESP_LOGE(TAG, "Timeout while displaying image!");
3491  return false;
3492  }
3493  App.feed_wdt();
3494  delay(10);
3495  }
3496  delay(200); // NOLINT
3497  return true;
3498 }
3500  if (this->busy_pin_ == nullptr) {
3501  return true;
3502  }
3503 
3504  const uint32_t start = millis();
3505  while (this->busy_pin_->digital_read()) {
3506  this->command(0x71);
3507  if (millis() - start > this->idle_timeout_()) {
3508  ESP_LOGE(TAG, "Timeout while displaying image!");
3509  return false;
3510  }
3511  App.feed_wdt();
3512  delay(10);
3513  }
3514  return true;
3515 }
3517  // COMMAND POWER SETTING
3518  this->command(0x01);
3519  this->data(0x07);
3520  this->data(0x07);
3521  this->data(0x3f);
3522  this->data(0x3f);
3523 
3524  // We don't want the display to be powered at this point
3525 
3526  delay(100); // NOLINT
3527  this->wait_until_idle_();
3528 
3529  // COMMAND VCOM AND DATA INTERVAL SETTING
3530  this->command(0x50);
3531  this->data(0x10);
3532  this->data(0x07);
3533 
3534  // COMMAND TCON SETTING
3535  this->command(0x60);
3536  this->data(0x22);
3537 
3538  // COMMAND PANEL SETTING
3539  this->command(0x00);
3540  this->data(0x1F);
3541 
3542  // COMMAND RESOLUTION SETTING
3543  this->command(0x61);
3544  this->data(0x03);
3545  this->data(0x20);
3546  this->data(0x01);
3547  this->data(0xE0);
3548 
3549  // COMMAND DUAL SPI MM_EN, DUSPI_EN
3550  this->command(0x15);
3551  this->data(0x00);
3552 
3553  // COMMAND POWER DRIVER HAT DOWN
3554  // This command will turn off booster, controller, source driver, gate driver, VCOM, and
3555  // temperature sensor, but register data will be kept until VDD turned OFF or Deep Sleep Mode.
3556  // Source/Gate/Border/VCOM will be released to floating.
3557  this->command(0x02);
3558 }
3560  uint32_t buf_len = this->get_buffer_length_();
3561 
3562  // COMMAND POWER ON
3563  ESP_LOGI(TAG, "Power on the display and hat");
3564 
3565  // This command will turn on booster, controller, regulators, and temperature sensor will be
3566  // activated for one-time sensing before enabling booster. When all voltages are ready, the
3567  // BUSY_N signal will return to high.
3568  this->command(0x04);
3569  delay(200); // NOLINT
3570  this->wait_until_idle_();
3571 
3572  // COMMAND DATA START TRANSMISSION NEW DATA
3573  this->command(0x13);
3574  delay(2);
3575  for (uint32_t i = 0; i < buf_len; i++) {
3576  this->data(~(this->buffer_[i]));
3577  }
3578 
3579  delay(100); // NOLINT
3580  this->wait_until_idle_();
3581 
3582  // COMMAND DISPLAY REFRESH
3583  this->command(0x12);
3584  delay(100); // NOLINT
3585  this->wait_until_idle_();
3586 
3587  ESP_LOGV(TAG, "Before command(0x02) (>> power off)");
3588  this->command(0x02);
3589  this->wait_until_idle_();
3590  ESP_LOGV(TAG, "After command(0x02) (>> power off)");
3591 }
3592 
3595 uint32_t WaveshareEPaper7P5InV2::idle_timeout_() { return 10000; }
3597  LOG_DISPLAY("", "Waveshare E-Paper", this);
3598  ESP_LOGCONFIG(TAG, " Model: 7.5inV2rev2");
3599  LOG_PIN(" Reset Pin: ", this->reset_pin_);
3600  LOG_PIN(" DC Pin: ", this->dc_pin_);
3601  LOG_PIN(" Busy Pin: ", this->busy_pin_);
3602  LOG_UPDATE_INTERVAL(this);
3603 }
3604 
3605 /* 7.50inV2alt */
3607  if (this->busy_pin_ == nullptr) {
3608  return true;
3609  }
3610 
3611  const uint32_t start = millis();
3612  while (this->busy_pin_->digital_read()) {
3613  this->command(0x71);
3614  if (millis() - start > this->idle_timeout_()) {
3615  ESP_LOGI(TAG, "Timeout while displaying image!");
3616  return false;
3617  }
3618  delay(10);
3619  }
3620  return true;
3621 }
3622 
3624  this->reset_();
3625 
3626  // COMMAND POWER SETTING
3627  this->command(0x01);
3628 
3629  // 1-0=11: internal power
3630  this->data(0x07);
3631  this->data(0x17); // VGH&VGL
3632  this->data(0x3F); // VSH
3633  this->data(0x26); // VSL
3634  this->data(0x11); // VSHR
3635 
3636  // VCOM DC Setting
3637  this->command(0x82);
3638  this->data(0x24); // VCOM
3639 
3640  // Booster Setting
3641  this->command(0x06);
3642  this->data(0x27);
3643  this->data(0x27);
3644  this->data(0x2F);
3645  this->data(0x17);
3646 
3647  // POWER ON
3648  this->command(0x04);
3649 
3650  delay(100); // NOLINT
3651  this->wait_until_idle_();
3652  // COMMAND PANEL SETTING
3653  this->command(0x00);
3654  this->data(0x3F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
3655 
3656  // COMMAND RESOLUTION SETTING
3657  this->command(0x61);
3658  this->data(0x03); // source 800
3659  this->data(0x20);
3660  this->data(0x01); // gate 480
3661  this->data(0xE0);
3662  // COMMAND ...?
3663  this->command(0x15);
3664  this->data(0x00);
3665  // COMMAND VCOM AND DATA INTERVAL SETTING
3666  this->command(0x50);
3667  this->data(0x10);
3668  this->data(0x00);
3669  // COMMAND TCON SETTING
3670  this->command(0x60);
3671  this->data(0x22);
3672  // Resolution setting
3673  this->command(0x65);
3674  this->data(0x00);
3675  this->data(0x00); // 800*480
3676  this->data(0x00);
3677  this->data(0x00);
3678 
3679  this->wait_until_idle_();
3680 
3681  uint8_t lut_vcom_7_i_n5_v2[] = {
3682  0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0xF, 0x1, 0xF, 0x1, 0x2, 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
3683  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3684  };
3685 
3686  uint8_t lut_ww_7_i_n5_v2[] = {
3687  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
3688  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3689  };
3690 
3691  uint8_t lut_bw_7_i_n5_v2[] = {
3692  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
3693  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3694  };
3695 
3696  uint8_t lut_wb_7_i_n5_v2[] = {
3697  0x80, 0xF, 0xF, 0x0, 0x0, 0x3, 0x84, 0xF, 0x1, 0xF, 0x1, 0x4, 0x40, 0xF, 0xF, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
3698  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3699  };
3700 
3701  uint8_t lut_bb_7_i_n5_v2[] = {
3702  0x80, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x40, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
3703  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3704  };
3705 
3706  uint8_t count;
3707  this->command(0x20); // VCOM
3708  for (count = 0; count < 42; count++)
3709  this->data(lut_vcom_7_i_n5_v2[count]);
3710 
3711  this->command(0x21); // LUTBW
3712  for (count = 0; count < 42; count++)
3713  this->data(lut_ww_7_i_n5_v2[count]);
3714 
3715  this->command(0x22); // LUTBW
3716  for (count = 0; count < 42; count++)
3717  this->data(lut_bw_7_i_n5_v2[count]);
3718 
3719  this->command(0x23); // LUTWB
3720  for (count = 0; count < 42; count++)
3721  this->data(lut_wb_7_i_n5_v2[count]);
3722 
3723  this->command(0x24); // LUTBB
3724  for (count = 0; count < 42; count++)
3725  this->data(lut_bb_7_i_n5_v2[count]);
3726 }
3727 
3729  LOG_DISPLAY("", "Waveshare E-Paper", this);
3730  ESP_LOGCONFIG(TAG, " Model: 7.5inV2");
3731  LOG_PIN(" Reset Pin: ", this->reset_pin_);
3732  LOG_PIN(" DC Pin: ", this->dc_pin_);
3733  LOG_PIN(" Busy Pin: ", this->busy_pin_);
3734  LOG_UPDATE_INTERVAL(this);
3735 }
3736 
3737 /* 7.50inV2 with partial and fast refresh */
3739  if (this->busy_pin_ == nullptr) {
3740  return true;
3741  }
3742 
3743  const uint32_t start = millis();
3744  while (this->busy_pin_->digital_read()) {
3745  this->command(0x71);
3746  if (millis() - start > this->idle_timeout_()) {
3747  ESP_LOGE(TAG, "Timeout while displaying image!");
3748  return false;
3749  }
3750  App.feed_wdt();
3751  delay(10);
3752  }
3753  return true;
3754 }
3755 
3756 void WaveshareEPaper7P5InV2P::reset_() {
3757  if (this->reset_pin_ != nullptr) {
3758  this->reset_pin_->digital_write(true);
3759  delay(20);
3760  this->reset_pin_->digital_write(false);
3761  delay(2);
3762  this->reset_pin_->digital_write(true);
3763  delay(20);
3764  }
3765 }
3766 
3767 void WaveshareEPaper7P5InV2P::turn_on_display_() {
3768  this->command(0x12);
3769  delay(100); // NOLINT
3770  this->wait_until_idle_();
3771 }
3772 
3774  this->reset_();
3775 
3776  // COMMAND POWER SETTING
3777  this->command(0x01);
3778  this->data(0x07);
3779  this->data(0x07);
3780  this->data(0x3f);
3781  this->data(0x3f);
3782 
3783  // COMMAND BOOSTER SOFT START
3784  this->command(0x06);
3785  this->data(0x17);
3786  this->data(0x17);
3787  this->data(0x28);
3788  this->data(0x17);
3789 
3790  // COMMAND POWER DRIVER HAT UP
3791  this->command(0x04);
3792  delay(100); // NOLINT
3793  this->wait_until_idle_();
3794 
3795  // COMMAND PANEL SETTING
3796  this->command(0x00);
3797  this->data(0x1F);
3798 
3799  // COMMAND RESOLUTION SETTING
3800  this->command(0x61);
3801  this->data(0x03);
3802  this->data(0x20);
3803  this->data(0x01);
3804  this->data(0xE0);
3805 
3806  // COMMAND DUAL SPI MM_EN, DUSPI_EN
3807  this->command(0x15);
3808  this->data(0x00);
3809 
3810  // COMMAND VCOM AND DATA INTERVAL SETTING
3811  this->command(0x50);
3812  this->data(0x10);
3813  this->data(0x07);
3814 
3815  // COMMAND TCON SETTING
3816  this->command(0x60);
3817  this->data(0x22);
3818 
3819  // COMMAND ENABLE FAST UPDATE
3820  this->command(0xE0);
3821  this->data(0x02);
3822  this->command(0xE5);
3823  this->data(0x5A);
3824 
3825  // COMMAND POWER DRIVER HAT DOWN
3826  this->command(0x02);
3827 }
3828 
3830  uint32_t buf_len = this->get_buffer_length_();
3831 
3832  // COMMAND POWER ON
3833  ESP_LOGI(TAG, "Power on the display and hat");
3834 
3835  this->command(0x04);
3836  delay(200); // NOLINT
3837  this->wait_until_idle_();
3838 
3839  if (this->full_update_every_ == 1) {
3840  this->command(0x13);
3841  for (uint32_t i = 0; i < buf_len; i++) {
3842  this->data(~(this->buffer_[i]));
3843  }
3844 
3845  this->turn_on_display_();
3846 
3847  this->command(0x02);
3848  this->wait_until_idle_();
3849  return;
3850  }
3851 
3852  this->command(0x50);
3853  this->data(0xA9);
3854  this->data(0x07);
3855 
3856  if (this->at_update_ == 0) {
3857  // Enable fast refresh
3858  this->command(0xE5);
3859  this->data(0x5A);
3860 
3861  this->command(0x92);
3862 
3863  this->command(0x10);
3864  delay(2);
3865  for (uint32_t i = 0; i < buf_len; i++) {
3866  this->data(~(this->buffer_[i]));
3867  }
3868 
3869  delay(100); // NOLINT
3870  this->wait_until_idle_();
3871 
3872  this->command(0x13);
3873  delay(2);
3874  for (uint32_t i = 0; i < buf_len; i++) {
3875  this->data(this->buffer_[i]);
3876  }
3877 
3878  delay(100); // NOLINT
3879  this->wait_until_idle_();
3880 
3881  this->turn_on_display_();
3882 
3883  } else {
3884  // Enable partial refresh
3885  this->command(0xE5);
3886  this->data(0x6E);
3887 
3888  // Activate partial refresh and set window bounds
3889  this->command(0x91);
3890  this->command(0x90);
3891 
3892  this->data(0x00);
3893  this->data(0x00);
3894  this->data((get_width_internal() - 1) >> 8 & 0xFF);
3895  this->data((get_width_internal() - 1) & 0xFF);
3896 
3897  this->data(0x00);
3898  this->data(0x00);
3899  this->data((get_height_internal() - 1) >> 8 & 0xFF);
3900  this->data((get_height_internal() - 1) & 0xFF);
3901 
3902  this->data(0x01);
3903 
3904  this->command(0x13);
3905  delay(2);
3906  for (uint32_t i = 0; i < buf_len; i++) {
3907  this->data(this->buffer_[i]);
3908  }
3909 
3910  delay(100); // NOLINT
3911  this->wait_until_idle_();
3912 
3913  this->turn_on_display_();
3914  }
3915 
3916  ESP_LOGV(TAG, "Before command(0x02) (>> power off)");
3917  this->command(0x02);
3918  this->wait_until_idle_();
3919  ESP_LOGV(TAG, "After command(0x02) (>> power off)");
3920 
3921  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
3922 }
3923 
3926 uint32_t WaveshareEPaper7P5InV2P::idle_timeout_() { return 10000; }
3928  LOG_DISPLAY("", "Waveshare E-Paper", this);
3929  ESP_LOGCONFIG(TAG, " Model: 7.50inv2p");
3930  ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
3931  LOG_PIN(" Reset Pin: ", this->reset_pin_);
3932  LOG_PIN(" DC Pin: ", this->dc_pin_);
3933  LOG_PIN(" Busy Pin: ", this->busy_pin_);
3934  LOG_UPDATE_INTERVAL(this);
3935 }
3936 void WaveshareEPaper7P5InV2P::set_full_update_every(uint32_t full_update_every) {
3937  this->full_update_every_ = full_update_every;
3938 }
3939 
3940 /* 7.50in-bc */
3942  /* The command sequence is similar to the 7P5In display but differs in subtle ways
3943  to allow for faster updates. */
3944  // COMMAND POWER SETTING
3945  this->command(0x01);
3946  this->data(0x37);
3947  this->data(0x00);
3948 
3949  // COMMAND PANEL SETTING
3950  this->command(0x00);
3951  this->data(0xCF);
3952  this->data(0x08);
3953 
3954  // COMMAND PLL CONTROL
3955  this->command(0x30);
3956  this->data(0x3A);
3957 
3958  // COMMAND VCM_DC_SETTING: all temperature range
3959  this->command(0x82);
3960  this->data(0x28);
3961 
3962  // COMMAND BOOSTER SOFT START
3963  this->command(0x06);
3964  this->data(0xC7);
3965  this->data(0xCC);
3966  this->data(0x15);
3967 
3968  // COMMAND VCOM AND DATA INTERVAL SETTING
3969  this->command(0x50);
3970  this->data(0x77);
3971 
3972  // COMMAND TCON SETTING
3973  this->command(0x60);
3974  this->data(0x22);
3975 
3976  // COMMAND FLASH CONTROL
3977  this->command(0x65);
3978  this->data(0x00);
3979 
3980  // COMMAND RESOLUTION SETTING
3981  this->command(0x61);
3982  this->data(0x02); // 640 >> 8
3983  this->data(0x80);
3984  this->data(0x01); // 384 >> 8
3985  this->data(0x80);
3986 
3987  // COMMAND FLASH MODE
3988  this->command(0xE5);
3989  this->data(0x03);
3990 }
3991 
3993  // COMMAND DATA START TRANSMISSION 1
3994  this->command(0x10);
3995  this->start_data_();
3996 
3997  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
3998  // A line of eight source pixels (each a bit in this byte)
3999  uint8_t eight_pixels = this->buffer_[i];
4000 
4001  for (uint8_t j = 0; j < 8; j += 2) {
4002  /* For bichromatic displays, each byte represents two pixels. Each nibble encodes a pixel: 0=white, 3=black,
4003  4=color. Therefore, e.g. 0x44 = two adjacent color pixels, 0x33 is two adjacent black pixels, etc. If you want
4004  to draw using the color pixels, change '0x30' with '0x40' and '0x03' with '0x04' below. */
4005  uint8_t left_nibble = (eight_pixels & 0x80) ? 0x30 : 0x00;
4006  eight_pixels <<= 1;
4007  uint8_t right_nibble = (eight_pixels & 0x80) ? 0x03 : 0x00;
4008  eight_pixels <<= 1;
4009  this->write_byte(left_nibble | right_nibble);
4010  }
4011  App.feed_wdt();
4012  }
4013  this->end_data_();
4014 
4015  // Unlike the 7P5In display, we send the "power on" command here rather than during initialization
4016  // COMMAND POWER ON
4017  this->command(0x04);
4018 
4019  // COMMAND DISPLAY REFRESH
4020  this->command(0x12);
4021 }
4022 
4024 
4026 
4028  LOG_DISPLAY("", "Waveshare E-Paper", this);
4029  ESP_LOGCONFIG(TAG, " Model: 7.5in-bc");
4030  LOG_PIN(" Reset Pin: ", this->reset_pin_);
4031  LOG_PIN(" DC Pin: ", this->dc_pin_);
4032  LOG_PIN(" Busy Pin: ", this->busy_pin_);
4033  LOG_UPDATE_INTERVAL(this);
4034 }
4035 
4037  this->command(0x12); // SWRESET
4038 
4039  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
4040 
4041  this->command(0x46); // Auto Write RAM
4042  this->data(0xF7);
4043 
4044  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
4045 
4046  this->command(0x47); // Auto Write RAM
4047  this->data(0xF7);
4048 
4049  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
4050 
4051  this->command(0x0C); // Soft start setting
4052  this->data(0xAE);
4053  this->data(0xC7);
4054  this->data(0xC3);
4055  this->data(0xC0);
4056  this->data(0x40);
4057 
4058  this->command(0x01); // Set MUX as 527
4059  this->data(0xAF);
4060  this->data(0x02);
4061  this->data(0x01);
4062 
4063  this->command(0x11); // Data entry mode
4064  this->data(0x01);
4065 
4066  this->command(0x44);
4067  this->data(0x00); // RAM x address start at 0
4068  this->data(0x00);
4069  this->data(0x6F); // RAM x address end at 36Fh -> 879
4070  this->data(0x03);
4071 
4072  this->command(0x45);
4073  this->data(0xAF); // RAM y address start at 20Fh;
4074  this->data(0x02);
4075  this->data(0x00); // RAM y address end at 00h;
4076  this->data(0x00);
4077 
4078  this->command(0x3C); // VBD
4079  this->data(0x01); // LUT1, for white
4080 
4081  this->command(0x18);
4082  this->data(0X80);
4083 
4084  this->command(0x22);
4085  this->data(0XB1); // Load Temperature and waveform setting.
4086 
4087  this->command(0x20);
4088 
4089  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
4090 
4091  this->command(0x4E);
4092  this->data(0x00);
4093  this->data(0x00);
4094 
4095  this->command(0x4F);
4096  this->data(0xAF);
4097  this->data(0x02);
4098 }
4099 
4101  this->command(0x4F);
4102  this->data(0xAf);
4103  this->data(0x02);
4104 
4105  // BLACK
4106  this->command(0x24);
4107  this->start_data_();
4108  this->write_array(this->buffer_, this->get_buffer_length_());
4109  this->end_data_();
4110 
4111  // RED
4112  this->command(0x26);
4113  this->start_data_();
4114  for (size_t i = 0; i < this->get_buffer_length_(); i++)
4115  this->write_byte(0x00);
4116  this->end_data_();
4117 
4118  this->command(0x22);
4119  this->data(0xC7);
4120  this->command(0x20);
4121  delay(100); // NOLINT
4122 }
4123 
4125 
4127 
4129  LOG_DISPLAY("", "Waveshare E-Paper", this);
4130  ESP_LOGCONFIG(TAG, " Model: 7.5in-HD-b");
4131  LOG_PIN(" Reset Pin: ", this->reset_pin_);
4132  LOG_PIN(" DC Pin: ", this->dc_pin_);
4133  LOG_PIN(" Busy Pin: ", this->busy_pin_);
4134  LOG_UPDATE_INTERVAL(this);
4135 }
4136 
4137 static const uint8_t LUT_SIZE_TTGO_DKE_PART = 153;
4138 
4139 static const uint8_t PART_UPDATE_LUT_TTGO_DKE[LUT_SIZE_TTGO_DKE_PART] = {
4140  0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4141  0x0, 0x0, 0x0, 0x0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0,
4142  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4143  0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4144  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4145  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4146  0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4147  0x0, 0x0, 0x0, 0x0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
4148  // 0x22, 0x17, 0x41, 0x0, 0x32, 0x32
4149 };
4150 
4153  bool partial = this->at_update_ != 0;
4154  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
4155 
4156  if (partial) {
4157  ESP_LOGI(TAG, "Performing partial e-paper update.");
4158  } else {
4159  ESP_LOGI(TAG, "Performing full e-paper update.");
4160  }
4161 
4162  // start and set up data format
4163  this->command(0x12);
4164  this->wait_until_idle_();
4165 
4166  this->command(0x11);
4167  this->data(0x03);
4168  this->command(0x44);
4169  this->data(1);
4170  this->data(this->get_width_internal() / 8);
4171  this->command(0x45);
4172  this->data(0);
4173  this->data(0);
4174  this->data(this->get_height_internal());
4175  this->data(0);
4176  this->command(0x4e);
4177  this->data(1);
4178  this->command(0x4f);
4179  this->data(0);
4180  this->data(0);
4181 
4182  if (!partial) {
4183  // send data
4184  this->command(0x24);
4185  this->start_data_();
4186  this->write_array(this->buffer_, this->get_buffer_length_());
4187  this->end_data_();
4188 
4189  // commit
4190  this->command(0x20);
4191  this->wait_until_idle_();
4192  } else {
4193  // set up partial update
4194  this->command(0x32);
4195  this->start_data_();
4196  this->write_array(PART_UPDATE_LUT_TTGO_DKE, sizeof(PART_UPDATE_LUT_TTGO_DKE));
4197  this->end_data_();
4198  this->command(0x3F);
4199  this->data(0x22);
4200 
4201  this->command(0x03);
4202  this->data(0x17);
4203  this->command(0x04);
4204  this->data(0x41);
4205  this->data(0x00);
4206  this->data(0x32);
4207  this->command(0x2C);
4208  this->data(0x32);
4209 
4210  this->command(0x37);
4211  this->data(0x00);
4212  this->data(0x00);
4213  this->data(0x00);
4214  this->data(0x00);
4215  this->data(0x00);
4216  this->data(0x40);
4217  this->data(0x00);
4218  this->data(0x00);
4219  this->data(0x00);
4220  this->data(0x00);
4221 
4222  this->command(0x3C);
4223  this->data(0x80);
4224  this->command(0x22);
4225  this->data(0xC0);
4226  this->command(0x20);
4227  this->wait_until_idle_();
4228 
4229  // send data
4230  this->command(0x24);
4231  this->start_data_();
4232  this->write_array(this->buffer_, this->get_buffer_length_());
4233  this->end_data_();
4234 
4235  // commit as partial
4236  this->command(0x22);
4237  this->data(0xCF);
4238  this->command(0x20);
4239  this->wait_until_idle_();
4240 
4241  // data must be sent again on partial update
4242  this->command(0x24);
4243  this->start_data_();
4244  this->write_array(this->buffer_, this->get_buffer_length_());
4245  this->end_data_();
4246  }
4247 
4248  ESP_LOGI(TAG, "Completed e-paper update.");
4249 }
4250 
4253 uint32_t WaveshareEPaper2P13InDKE::idle_timeout_() { return 5000; }
4255  LOG_DISPLAY("", "Waveshare E-Paper", this);
4256  ESP_LOGCONFIG(TAG, " Model: 2.13inDKE");
4257  LOG_PIN(" CS Pin: ", this->cs_);
4258  LOG_PIN(" Reset Pin: ", this->reset_pin_);
4259  LOG_PIN(" DC Pin: ", this->dc_pin_);
4260  LOG_PIN(" Busy Pin: ", this->busy_pin_);
4261  LOG_UPDATE_INTERVAL(this);
4262 }
4263 
4264 void WaveshareEPaper2P13InDKE::set_full_update_every(uint32_t full_update_every) {
4265  this->full_update_every_ = full_update_every;
4266 }
4267 
4268 // ========================================================
4269 // 13.3in (K version)
4270 // Datasheet/Specification/Reference:
4271 // - https://files.waveshare.com/wiki/13.3inch-e-Paper-HAT-(K)/13.3-inch-e-Paper-(K)-user-manual.pdf
4272 // - https://github.com/waveshareteam/e-Paper/tree/master/Arduino/epd13in3k
4273 // ========================================================
4274 
4275 // using default wait_until_idle_() function
4277  this->wait_until_idle_();
4278  this->command(0x12); // SWRESET
4279  this->wait_until_idle_();
4280 
4281  this->command(0x0c); // set soft start
4282  this->data(0xae);
4283  this->data(0xc7);
4284  this->data(0xc3);
4285  this->data(0xc0);
4286  this->data(0x80);
4287 
4288  this->command(0x01); // driver output control
4289  this->data((get_height_internal() - 1) % 256); // Y
4290  this->data((get_height_internal() - 1) / 256); // Y
4291  this->data(0x00);
4292 
4293  this->command(0x11); // data entry mode
4294  this->data(0x03);
4295 
4296  // SET WINDOWS
4297  // XRAM_START_AND_END_POSITION
4298  this->command(0x44);
4299  this->data(0 & 0xFF);
4300  this->data((0 >> 8) & 0x03);
4301  this->data((get_width_internal() - 1) & 0xFF);
4302  this->data(((get_width_internal() - 1) >> 8) & 0x03);
4303  // YRAM_START_AND_END_POSITION
4304  this->command(0x45);
4305  this->data(0 & 0xFF);
4306  this->data((0 >> 8) & 0x03);
4307  this->data((get_height_internal() - 1) & 0xFF);
4308  this->data(((get_height_internal() - 1) >> 8) & 0x03);
4309 
4310  this->command(0x3C); // Border setting
4311  this->data(0x01);
4312 
4313  this->command(0x18); // use the internal temperature sensor
4314  this->data(0x80);
4315 
4316  // SET CURSOR
4317  // XRAM_ADDRESS
4318  this->command(0x4E);
4319  this->data(0 & 0xFF);
4320  this->data((0 >> 8) & 0x03);
4321  // YRAM_ADDRESS
4322  this->command(0x4F);
4323  this->data(0 & 0xFF);
4324  this->data((0 >> 8) & 0x03);
4325 }
4327  // do single full update
4328  this->command(0x24);
4329  this->start_data_();
4330  this->write_array(this->buffer_, this->get_buffer_length_());
4331  this->end_data_();
4332 
4333  // COMMAND DISPLAY REFRESH
4334  this->command(0x22);
4335  this->data(0xF7);
4336  this->command(0x20);
4337 }
4338 
4341 uint32_t WaveshareEPaper13P3InK::idle_timeout_() { return 10000; }
4343  LOG_DISPLAY("", "Waveshare E-Paper", this);
4344  ESP_LOGCONFIG(TAG, " Model: 13.3inK");
4345  LOG_PIN(" Reset Pin: ", this->reset_pin_);
4346  LOG_PIN(" DC Pin: ", this->dc_pin_);
4347  LOG_PIN(" Busy Pin: ", this->busy_pin_);
4348  LOG_UPDATE_INTERVAL(this);
4349 }
4350 
4351 } // namespace waveshare_epaper
4352 } // namespace esphome
virtual void digital_write(bool value)=0
void set_full_update_every(uint32_t full_update_every)
int get_width() override
Get the width of the image in pixels with rotation applied.
void status_set_warning(const char *message="unspecified")
Definition: component.cpp:151
void draw_absolute_pixel_internal(int x, int y, Color color) override
void write_lut_(const uint8_t *lut, uint8_t size)
uint16_t x
Definition: tt21100.cpp:17
void draw_absolute_pixel_internal(int x, int y, Color color) override
T * allocate(size_t n)
Definition: helpers.h:703
void set_full_update_every(uint32_t full_update_every)
void filled_rectangle(int x1, int y1, int width, int height, Color color=COLOR_ON)
Fill a rectangle with the top left point at [x1,y1] and the bottom right point at [x1+width...
Definition: display.cpp:104
void set_full_update_every(uint32_t full_update_every)
GPIOPin * cs_
Definition: spi.h:397
void set_full_update_every(uint32_t full_update_every)
WaveshareEPaperTypeA(WaveshareEPaperTypeAModel model)
virtual void fill(Color color)
Fill the entire screen with the given color.
Definition: display.cpp:15
virtual void setup()=0
bool is_on() ESPHOME_ALWAYS_INLINE
Definition: color.h:46
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
uint16_t y
Definition: tt21100.cpp:18
void init_internal_(uint32_t buffer_length)
virtual int get_height_internal()=0
const char *const TAG
Definition: spi.cpp:8
int get_height() override
Get the height of the image in pixels with rotation applied.
void status_clear_warning()
Definition: component.cpp:166
virtual int get_width_internal()=0
void clear()
Clear the entire screen by filling it with OFF pixels.
Definition: display.cpp:16
uint8_t green
Definition: color.h:19
const float PROCESSOR
For components that use data from sensors like displays.
Definition: component.cpp:20
Application App
Global storage of Application pointer - only one Application can exist.
void init_internal_7c_(uint32_t buffer_length)
void set_full_update_every(uint32_t full_update_every)
virtual bool digital_read()=0
void deallocate(T *p, size_t n)
Definition: helpers.h:720
void write_lut_(const uint8_t *lut, uint8_t size)
void write_lut_(const uint8_t *lut, uint8_t size)
uint8_t blue
Definition: color.h:23
uint16_t length
Definition: tt21100.cpp:12
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
Definition: core.cpp:28
void set_full_update_every(uint32_t full_update_every)
An STL allocator that uses SPI or internal RAM.
Definition: helpers.h:683
void draw_absolute_pixel_internal(int x, int y, Color color) override
void set_full_update_every(uint32_t full_update_every)
void cmd_data(const uint8_t *data, size_t length)
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:26
uint8_t red
Definition: color.h:15