ESPHome  2024.12.2
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 
7 namespace esphome {
8 namespace waveshare_epaper {
9 
10 static const char *const TAG = "waveshare_epaper";
11 
12 static const uint8_t LUT_SIZE_WAVESHARE = 30;
13 
14 static const uint8_t FULL_UPDATE_LUT[LUT_SIZE_WAVESHARE] = {0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22, 0x66, 0x69,
15  0x69, 0x59, 0x58, 0x99, 0x99, 0x88, 0x00, 0x00, 0x00, 0x00,
16  0xF8, 0xB4, 0x13, 0x51, 0x35, 0x51, 0x51, 0x19, 0x01, 0x00};
17 
18 static const uint8_t PARTIAL_UPDATE_LUT[LUT_SIZE_WAVESHARE] = {
19  0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20  0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
21 
22 static const uint8_t LUT_SIZE_TTGO = 70;
23 
24 static const uint8_t FULL_UPDATE_LUT_TTGO[LUT_SIZE_TTGO] = {
25  0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, // LUT0: BB: VS 0 ~7
26  0x10, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, // LUT1: BW: VS 0 ~7
27  0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, // LUT2: WB: VS 0 ~7
28  0x10, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, // LUT3: WW: VS 0 ~7
29  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT4: VCOM: VS 0 ~7
30  0x03, 0x03, 0x00, 0x00, 0x02, // TP0 A~D RP0
31  0x09, 0x09, 0x00, 0x00, 0x02, // TP1 A~D RP1
32  0x03, 0x03, 0x00, 0x00, 0x02, // TP2 A~D RP2
33  0x00, 0x00, 0x00, 0x00, 0x00, // TP3 A~D RP3
34  0x00, 0x00, 0x00, 0x00, 0x00, // TP4 A~D RP4
35  0x00, 0x00, 0x00, 0x00, 0x00, // TP5 A~D RP5
36  0x00, 0x00, 0x00, 0x00, 0x00, // TP6 A~D RP6
37 };
38 
39 static const uint8_t PARTIAL_UPDATE_LUT_TTGO[LUT_SIZE_TTGO] = {
40  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT0: BB: VS 0 ~7
41  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT1: BW: VS 0 ~7
42  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT2: WB: VS 0 ~7
43  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT3: WW: VS 0 ~7
44  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT4: VCOM: VS 0 ~7
45  0x0A, 0x00, 0x00, 0x00, 0x00, // TP0 A~D RP0
46  0x00, 0x00, 0x00, 0x00, 0x00, // TP1 A~D RP1
47  0x00, 0x00, 0x00, 0x00, 0x00, // TP2 A~D RP2
48  0x00, 0x00, 0x00, 0x00, 0x00, // TP3 A~D RP3
49  0x00, 0x00, 0x00, 0x00, 0x00, // TP4 A~D RP4
50  0x00, 0x00, 0x00, 0x00, 0x00, // TP5 A~D RP5
51  0x00, 0x00, 0x00, 0x00, 0x00, // TP6 A~D RP6
52 };
53 
54 static const uint8_t LUT_SIZE_TTGO_B73 = 100;
55 
56 static const uint8_t FULL_UPDATE_LUT_TTGO_B73[LUT_SIZE_TTGO_B73] = {
57  0xA0, 0x90, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x90, 0xA0, 0x00, 0x00, 0x00, 0x00,
58  0x00, 0x00, 0x00, 0xA0, 0x90, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x90, 0xA0, 0x00,
59  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 
61  0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x03, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
62  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 };
65 
66 static const uint8_t PARTIAL_UPDATE_LUT_TTGO_B73[LUT_SIZE_TTGO_B73] = {
67  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68  0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
69  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 
71  0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72  0x00, 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,
74 };
75 
76 static const uint8_t LUT_SIZE_TTGO_B1 = 29;
77 
78 static const uint8_t FULL_UPDATE_LUT_TTGO_B1[LUT_SIZE_TTGO_B1] = {
79  0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80  0x00, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x01, 0x00, 0x00, 0x00, 0x00};
81 
82 static const uint8_t PARTIAL_UPDATE_LUT_TTGO_B1[LUT_SIZE_TTGO_B1] = {
83  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84  0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
85 
86 // clang-format off
87 // Disable formatting to preserve the same look as in Waveshare examples
88 static const uint8_t PARTIAL_UPD_2IN9_LUT_SIZE = 159;
89 static const uint8_t PARTIAL_UPD_2IN9_LUT[PARTIAL_UPD_2IN9_LUT_SIZE] =
90 {
91  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92  0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93  0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96  0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
97  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99  0x00, 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  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00,
109  0x22, 0x17, 0x41, 0xB0, 0x32, 0x36,
110 };
111 // clang-format on
112 
114  this->init_internal_(this->get_buffer_length_());
115  this->dc_pin_->setup(); // OUTPUT
116  this->dc_pin_->digital_write(false);
117  if (this->reset_pin_ != nullptr) {
118  this->reset_pin_->setup(); // OUTPUT
119  this->reset_pin_->digital_write(true);
120  }
121  if (this->busy_pin_ != nullptr) {
122  this->busy_pin_->setup(); // INPUT
123  }
124  this->spi_setup();
125 
126  this->reset_();
127 }
129 void WaveshareEPaperBase::command(uint8_t value) {
130  this->start_command_();
131  this->write_byte(value);
132  this->end_command_();
133 }
134 void WaveshareEPaperBase::data(uint8_t value) {
135  this->start_data_();
136  this->write_byte(value);
137  this->end_data_();
138 }
139 
140 // write a command followed by one or more bytes of data.
141 // The command is the first byte, length is the total including cmd.
142 void WaveshareEPaperBase::cmd_data(const uint8_t *c_data, size_t length) {
143  this->dc_pin_->digital_write(false);
144  this->enable();
145  this->write_byte(c_data[0]);
146  this->dc_pin_->digital_write(true);
147  this->write_array(c_data + 1, length - 1);
148  this->disable();
149 }
150 
152  if (this->busy_pin_ == nullptr || !this->busy_pin_->digital_read()) {
153  return true;
154  }
155 
156  const uint32_t start = millis();
157  while (this->busy_pin_->digital_read()) {
158  if (millis() - start > this->idle_timeout_()) {
159  ESP_LOGE(TAG, "Timeout while displaying image!");
160  return false;
161  }
162  delay(1);
163  }
164  return true;
165 }
167  this->do_update_();
168  this->display();
169 }
171  // flip logic
172  const uint8_t fill = color.is_on() ? 0x00 : 0xFF;
173  for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
174  this->buffer_[i] = fill;
175 }
177  if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
178  return;
179 
180  const uint32_t pos = (x + y * this->get_width_controller()) / 8u;
181  const uint8_t subpos = x & 0x07;
182  // flip logic
183  if (!color.is_on()) {
184  this->buffer_[pos] |= 0x80 >> subpos;
185  } else {
186  this->buffer_[pos] &= ~(0x80 >> subpos);
187  }
188 }
189 
191  return this->get_width_controller() * this->get_height_internal() / 8u;
192 } // just a black buffer
194  return this->get_width_controller() * this->get_height_internal() / 4u;
195 } // black and red buffer
196 
198  this->filled_rectangle(0, 0, this->get_width(), this->get_height(), color);
199 }
201  if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
202  return;
203 
204  const uint32_t buf_half_len = this->get_buffer_length_() / 2u;
205 
206  const uint32_t pos = (x + y * this->get_width_internal()) / 8u;
207  const uint8_t subpos = x & 0x07;
208  // flip logic
209  if (color.is_on()) {
210  this->buffer_[pos] |= 0x80 >> subpos;
211  } else {
212  this->buffer_[pos] &= ~(0x80 >> subpos);
213  }
214 
215  // draw red pixels only, if the color contains red only
216  if (((color.red > 0) && (color.green == 0) && (color.blue == 0))) {
217  this->buffer_[pos + buf_half_len] |= 0x80 >> subpos;
218  } else {
219  this->buffer_[pos + buf_half_len] &= ~(0x80 >> subpos);
220  }
221 }
222 
224  this->dc_pin_->digital_write(false);
225  this->enable();
226 }
229  this->dc_pin_->digital_write(true);
230  this->enable();
231 }
234 
235 // ========================================================
236 // Type A
237 // ========================================================
238 
240  // Achieve display intialization
241  this->init_display_();
242  // If a reset pin is configured, eligible displays can be set to deep sleep
243  // between updates, as recommended by the hardware provider
244  if (this->reset_pin_ != nullptr) {
245  switch (this->model_) {
246  // More models can be added here to enable deep sleep if eligible
249  this->deep_sleep_between_updates_ = true;
250  ESP_LOGI(TAG, "Set the display to deep sleep");
251  this->deep_sleep();
252  break;
253  default:
254  break;
255  }
256  }
257 }
259  if (this->model_ == TTGO_EPAPER_2_13_IN_B74 || this->model_ == WAVESHARE_EPAPER_2_13_IN_V2) {
260  if (this->reset_pin_ != nullptr) {
261  this->reset_pin_->digital_write(false);
262  delay(10);
263  this->reset_pin_->digital_write(true);
264  delay(10);
265  this->wait_until_idle_();
266  }
267 
268  this->command(0x12); // SWRESET
269  this->wait_until_idle_();
270  }
271 
272  // COMMAND DRIVER OUTPUT CONTROL
273  this->command(0x01);
274  this->data(this->get_height_internal() - 1);
275  this->data((this->get_height_internal() - 1) >> 8);
276  this->data(0x00); // ? GD = 0, SM = 0, TB = 0
277 
278  // COMMAND BOOSTER SOFT START CONTROL
279  this->command(0x0C);
280  this->data(0xD7);
281  this->data(0xD6);
282  this->data(0x9D);
283 
284  // COMMAND WRITE VCOM REGISTER
285  this->command(0x2C);
286  this->data(0xA8);
287 
288  // COMMAND SET DUMMY LINE PERIOD
289  this->command(0x3A);
290  this->data(0x1A);
291 
292  // COMMAND SET GATE TIME
293  this->command(0x3B);
294  this->data(0x08); // 2µs per row
295 
296  // COMMAND DATA ENTRY MODE SETTING
297  this->command(0x11);
298  switch (this->model_) {
300  this->data(0x01); // x increase, y decrease : as in demo code
301  break;
304  this->data(0x03); // from top left to bottom right
305  // RAM content option for Display Update
306  this->command(0x21);
307  this->data(0x00);
308  this->data(0x80);
309  break;
310  default:
311  this->data(0x03); // from top left to bottom right
312  }
313 }
315  LOG_DISPLAY("", "Waveshare E-Paper", this);
316  switch (this->model_) {
318  ESP_LOGCONFIG(TAG, " Model: 1.54in");
319  break;
321  ESP_LOGCONFIG(TAG, " Model: 1.54inV2");
322  break;
324  ESP_LOGCONFIG(TAG, " Model: 2.13in");
325  break;
327  ESP_LOGCONFIG(TAG, " Model: 2.13inV2");
328  break;
329  case TTGO_EPAPER_2_13_IN:
330  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO)");
331  break;
333  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B73)");
334  break;
336  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B74)");
337  break;
339  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B1)");
340  break;
342  ESP_LOGCONFIG(TAG, " Model: 2.9in");
343  break;
345  ESP_LOGCONFIG(TAG, " Model: 2.9inV2");
346  break;
347  }
348  ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
349  LOG_PIN(" Reset Pin: ", this->reset_pin_);
350  LOG_PIN(" DC Pin: ", this->dc_pin_);
351  LOG_PIN(" Busy Pin: ", this->busy_pin_);
352  LOG_UPDATE_INTERVAL(this);
353 }
355  bool full_update = this->at_update_ == 0;
356  bool prev_full_update = this->at_update_ == 1;
357 
358  if (this->deep_sleep_between_updates_) {
359  ESP_LOGI(TAG, "Wake up the display");
360  this->reset_();
361  this->wait_until_idle_();
362  this->init_display_();
363  }
364 
365  if (!this->wait_until_idle_()) {
366  this->status_set_warning();
367  return;
368  }
369 
370  if (this->full_update_every_ >= 1) {
371  if (full_update != prev_full_update) {
372  switch (this->model_) {
373  case TTGO_EPAPER_2_13_IN:
375  // Waveshare 2.13" V2 uses the same LUTs as TTGO
376  this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO : PARTIAL_UPDATE_LUT_TTGO, LUT_SIZE_TTGO);
377  break;
379  this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO_B73 : PARTIAL_UPDATE_LUT_TTGO_B73, LUT_SIZE_TTGO_B73);
380  break;
382  // there is no LUT
383  break;
385  this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO_B1 : PARTIAL_UPDATE_LUT_TTGO_B1, LUT_SIZE_TTGO_B1);
386  break;
387  default:
388  this->write_lut_(full_update ? FULL_UPDATE_LUT : PARTIAL_UPDATE_LUT, LUT_SIZE_WAVESHARE);
389  }
390  }
391  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
392  }
393 
394  if (this->model_ == WAVESHARE_EPAPER_2_13_IN_V2) {
395  // Set VCOM for full or partial update
396  this->command(0x2C);
397  this->data(full_update ? 0x55 : 0x26);
398 
399  if (!full_update) {
400  // Enable "ping-pong"
401  this->command(0x37);
402  this->data(0x00);
403  this->data(0x00);
404  this->data(0x00);
405  this->data(0x00);
406  this->data(0x40);
407  this->data(0x00);
408  this->data(0x00);
409  this->command(0x22);
410  this->data(0xc0);
411  this->command(0x20);
412  }
413  }
414 
415  // Border waveform
416  switch (this->model_) {
418  this->command(0x3C);
419  this->data(full_update ? 0x05 : 0x80);
420  break;
422  this->command(0x3C);
423  this->data(full_update ? 0x03 : 0x01);
424  break;
425  default:
426  break;
427  }
428 
429  // Set x & y regions we want to write to (full)
430  switch (this->model_) {
432  // COMMAND SET RAM X ADDRESS START END POSITION
433  this->command(0x44);
434  this->data(0x00);
435  this->data((this->get_width_controller() - 1) >> 3);
436  // COMMAND SET RAM Y ADDRESS START END POSITION
437  this->command(0x45);
438  this->data(this->get_height_internal() - 1);
439  this->data((this->get_height_internal() - 1) >> 8);
440  this->data(0x00);
441  this->data(0x00);
442 
443  // COMMAND SET RAM X ADDRESS COUNTER
444  this->command(0x4E);
445  this->data(0x00);
446  // COMMAND SET RAM Y ADDRESS COUNTER
447  this->command(0x4F);
448  this->data(this->get_height_internal() - 1);
449  this->data((this->get_height_internal() - 1) >> 8);
450 
451  break;
452  default:
453  // COMMAND SET RAM X ADDRESS START END POSITION
454  this->command(0x44);
455  this->data(0x00);
456  this->data((this->get_width_internal() - 1) >> 3);
457  // COMMAND SET RAM Y ADDRESS START END POSITION
458  this->command(0x45);
459  this->data(0x00);
460  this->data(0x00);
461  this->data(this->get_height_internal() - 1);
462  this->data((this->get_height_internal() - 1) >> 8);
463 
464  // COMMAND SET RAM X ADDRESS COUNTER
465  this->command(0x4E);
466  this->data(0x00);
467  // COMMAND SET RAM Y ADDRESS COUNTER
468  this->command(0x4F);
469  this->data(0x00);
470  this->data(0x00);
471  }
472 
473  if (!this->wait_until_idle_()) {
474  this->status_set_warning();
475  return;
476  }
477 
478  // COMMAND WRITE RAM
479  this->command(0x24);
480  this->start_data_();
481  switch (this->model_) {
482  case TTGO_EPAPER_2_13_IN_B1: { // block needed because of variable initializations
483  int16_t wb = ((this->get_width_controller()) >> 3);
484  for (int i = 0; i < this->get_height_internal(); i++) {
485  for (int j = 0; j < wb; j++) {
486  int idx = j + (this->get_height_internal() - 1 - i) * wb;
487  this->write_byte(this->buffer_[idx]);
488  }
489  }
490  break;
491  }
492  default:
493  this->write_array(this->buffer_, this->get_buffer_length_());
494  }
495  this->end_data_();
496 
497  if (this->model_ == WAVESHARE_EPAPER_2_13_IN_V2 && full_update) {
498  // Write base image again on full refresh
499  this->command(0x26);
500  this->start_data_();
501  this->write_array(this->buffer_, this->get_buffer_length_());
502  this->end_data_();
503  }
504 
505  // COMMAND DISPLAY UPDATE CONTROL 2
506  this->command(0x22);
507  switch (this->model_) {
511  this->data(full_update ? 0xF7 : 0xFF);
512  break;
514  this->data(0xC7);
515  break;
517  this->data(full_update ? 0xC7 : 0x0C);
518  break;
519  default:
520  this->data(0xC4);
521  break;
522  }
523 
524  // COMMAND MASTER ACTIVATION
525  this->command(0x20);
526  // COMMAND TERMINATE FRAME READ WRITE
527  this->command(0xFF);
528 
529  this->status_clear_warning();
530 
531  if (this->deep_sleep_between_updates_) {
532  ESP_LOGI(TAG, "Set the display back to deep sleep");
533  this->deep_sleep();
534  }
535 }
537  switch (this->model_) {
540  return 200;
543  case TTGO_EPAPER_2_13_IN:
547  return 122;
550  return 128;
551  }
552  return 0;
553 }
554 // The controller of the 2.13" displays has a buffer larger than screen size
556  switch (this->model_) {
559  case TTGO_EPAPER_2_13_IN:
563  return 128;
564  default:
565  return this->get_width_internal();
566  }
567 }
569  switch (this->model_) {
572  return 200;
575  case TTGO_EPAPER_2_13_IN:
579  return 250;
582  return 296;
583  }
584  return 0;
585 }
586 void WaveshareEPaperTypeA::write_lut_(const uint8_t *lut, const uint8_t size) {
587  // COMMAND WRITE LUT REGISTER
588  this->command(0x32);
589  for (uint8_t i = 0; i < size; i++)
590  this->data(lut[i]);
591 }
593 void WaveshareEPaperTypeA::set_full_update_every(uint32_t full_update_every) {
594  this->full_update_every_ = full_update_every;
595 }
596 
598  switch (this->model_) {
603  return 2500;
604  default:
606  }
607 }
608 
609 // ========================================================
610 // Type B
611 // ========================================================
612 // Datasheet:
613 // - https://www.waveshare.com/w/upload/7/7f/4.2inch-e-paper-b-specification.pdf
614 // - https://github.com/soonuse/epd-library-arduino/blob/master/4.2inch_e-paper/epd4in2/
615 
616 static const uint8_t LUT_VCOM_DC_2_7[44] = {
617  0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x00, 0x32, 0x32, 0x00, 0x00, 0x02, 0x00,
618  0x0F, 0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 };
621 
622 static const uint8_t LUT_WHITE_TO_WHITE_2_7[42] = {
623  0x50, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0xA0, 0x0F,
624  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626 };
627 
628 static const uint8_t LUT_BLACK_TO_WHITE_2_7[42] = {
629  0x50, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0xA0, 0x0F,
630  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 };
633 
634 static const uint8_t LUT_WHITE_TO_BLACK_2_7[] = {
635  0xA0, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0x50, 0x0F,
636  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 };
639 
640 static const uint8_t LUT_BLACK_TO_BLACK_2_7[42] = {
641  0xA0, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0x50, 0x0F,
642  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 };
645 
647  // command power setting
648  this->command(0x01);
649  this->data(0x03); // VDS_EN, VDG_EN
650  this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
651  this->data(0x2B); // VDH
652  this->data(0x2B); // VDL
653  this->data(0x09); // VDHR
654 
655  // command booster soft start
656  this->command(0x06);
657  this->data(0x07);
658  this->data(0x07);
659  this->data(0x17);
660 
661  // Power optimization - ???
662  this->command(0xF8);
663  this->data(0x60);
664  this->data(0xA5);
665  this->command(0xF8);
666  this->data(0x89);
667  this->data(0xA5);
668  this->command(0xF8);
669  this->data(0x90);
670  this->data(0x00);
671  this->command(0xF8);
672  this->data(0x93);
673  this->data(0x2A);
674  this->command(0xF8);
675  this->data(0xA0);
676  this->data(0xA5);
677  this->command(0xF8);
678  this->data(0xA1);
679  this->data(0x00);
680  this->command(0xF8);
681  this->data(0x73);
682  this->data(0x41);
683 
684  // command partial display refresh
685  this->command(0x16);
686  this->data(0x00);
687 
688  // command power on
689  this->command(0x04);
690  this->wait_until_idle_();
691  delay(10);
692 
693  // Command panel setting
694  this->command(0x00);
695  this->data(0xAF); // KW-BF KWR-AF BWROTP 0f
696  // command pll control
697  this->command(0x30);
698  this->data(0x3A); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
699  // COMMAND VCM DC SETTING
700  this->command(0x82);
701  this->data(0x12);
702 
703  delay(2);
704  // COMMAND LUT FOR VCOM
705  this->command(0x20);
706  for (uint8_t i : LUT_VCOM_DC_2_7)
707  this->data(i);
708 
709  // COMMAND LUT WHITE TO WHITE
710  this->command(0x21);
711  for (uint8_t i : LUT_WHITE_TO_WHITE_2_7)
712  this->data(i);
713  // COMMAND LUT BLACK TO WHITE
714  this->command(0x22);
715  for (uint8_t i : LUT_BLACK_TO_WHITE_2_7)
716  this->data(i);
717  // COMMAND LUT WHITE TO BLACK
718  this->command(0x23);
719  for (uint8_t i : LUT_WHITE_TO_BLACK_2_7)
720  this->data(i);
721  // COMMAND LUT BLACK TO BLACK
722  this->command(0x24);
723  for (uint8_t i : LUT_BLACK_TO_BLACK_2_7)
724  this->data(i);
725 }
727  uint32_t buf_len = this->get_buffer_length_();
728 
729  // COMMAND DATA START TRANSMISSION 1
730  this->command(0x10);
731  delay(2);
732  for (uint32_t i = 0; i < buf_len; i++) {
733  this->data(this->buffer_[i]);
734  }
735  delay(2);
736 
737  // COMMAND DATA START TRANSMISSION 2
738  this->command(0x13);
739  delay(2);
740  for (uint32_t i = 0; i < buf_len; i++) {
741  this->data(this->buffer_[i]);
742  }
743 
744  // COMMAND DISPLAY REFRESH
745  this->command(0x12);
746 }
750  LOG_DISPLAY("", "Waveshare E-Paper", this);
751  ESP_LOGCONFIG(TAG, " Model: 2.7in");
752  LOG_PIN(" Reset Pin: ", this->reset_pin_);
753  LOG_PIN(" DC Pin: ", this->dc_pin_);
754  LOG_PIN(" Busy Pin: ", this->busy_pin_);
755  LOG_UPDATE_INTERVAL(this);
756 }
757 
759  this->reset_();
760  this->wait_until_idle_();
761 
762  this->command(0x12); // SWRESET
763  this->wait_until_idle_();
764 
765  // SET WINDOWS
766  // XRAM_START_AND_END_POSITION
767  this->command(0x44);
768  this->data(0x00);
769  this->data(((this->get_width_controller() - 1) >> 3) & 0xFF);
770  // YRAM_START_AND_END_POSITION
771  this->command(0x45);
772  this->data(0x00);
773  this->data(0x00);
774  this->data((get_height_internal() - 1) & 0xFF);
775  this->data(((get_height_internal() - 1) >> 8) & 0xFF);
776 
777  // SET CURSOR
778  // XRAM_ADDRESS
779  this->command(0x4E);
780  this->data(0x00);
781  // YRAM_ADDRESS
782  this->command(0x4F);
783  this->data(0x00);
784  this->data(0x00);
785 
786  this->command(0x11); // data entry mode
787  this->data(0x03);
788 }
790  this->command(0x24);
791  this->start_data_();
792  this->write_array(this->buffer_, this->get_buffer_length_());
793  this->end_data_();
794 
795  // COMMAND DISPLAY REFRESH
796  this->command(0x22);
797  this->data(0xF7);
798  this->command(0x20);
799 }
803  LOG_DISPLAY("", "Waveshare E-Paper", this);
804  ESP_LOGCONFIG(TAG, " Model: 2.7in V2");
805  LOG_PIN(" Reset Pin: ", this->reset_pin_);
806  LOG_PIN(" DC Pin: ", this->dc_pin_);
807  LOG_PIN(" Busy Pin: ", this->busy_pin_);
808  LOG_UPDATE_INTERVAL(this);
809 }
810 
811 // ========================================================
812 // 1.54inch_v2_e-paper_b
813 // ========================================================
814 // Datasheet:
815 // - https://files.waveshare.com/upload/9/9e/1.54inch-e-paper-b-v2-specification.pdf
816 // - https://www.waveshare.com/wiki/1.54inch_e-Paper_Module_(B)_Manual
817 
819  this->reset_();
820 
821  this->wait_until_idle_();
822 
823  this->command(0x12);
824  this->wait_until_idle_();
825 
826  this->command(0x01);
827  this->data(0xC7);
828  this->data(0x00);
829  this->data(0x01);
830 
831  this->command(0x11); // data entry mode
832  this->data(0x01);
833 
834  this->command(0x44); // set Ram-X address start/end position
835  this->data(0x00);
836  this->data(0x18); // 0x18-->(24+1)*8=200
837 
838  this->command(0x45); // set Ram-Y address start/end position
839  this->data(0xC7); // 0xC7-->(199+1)=200
840  this->data(0x00);
841  this->data(0x00);
842  this->data(0x00);
843 
844  this->command(0x3C); // BorderWavefrom
845  this->data(0x05);
846 
847  this->command(0x18); // Read built-in temperature sensor
848  this->data(0x80);
849 
850  this->command(0x4E); // set RAM x address count to 0;
851  this->data(0x00);
852  this->command(0x4F); // set RAM y address count to 0X199;
853  this->data(0xC7);
854  this->data(0x00);
855 
856  this->wait_until_idle_();
857 }
858 
860  uint32_t buf_len_half = this->get_buffer_length_() >> 1;
861  this->initialize();
862 
863  // COMMAND DATA START TRANSMISSION 1 (BLACK)
864  this->command(0x24);
865  delay(2);
866  for (uint32_t i = 0; i < buf_len_half; i++) {
867  this->data(~this->buffer_[i]);
868  }
869  delay(2);
870 
871  // COMMAND DATA START TRANSMISSION 2 (RED)
872  this->command(0x26);
873  delay(2);
874  for (uint32_t i = buf_len_half; i < buf_len_half * 2u; i++) {
875  this->data(this->buffer_[i]);
876  }
877  this->command(0x22);
878  this->data(0xf7);
879  this->command(0x20);
880  this->wait_until_idle_();
881 
882  this->deep_sleep();
883 }
887  LOG_DISPLAY("", "Waveshare E-Paper", this);
888  ESP_LOGCONFIG(TAG, " Model: 1.54in V2 B");
889  LOG_PIN(" Reset Pin: ", this->reset_pin_);
890  LOG_PIN(" DC Pin: ", this->dc_pin_);
891  LOG_PIN(" Busy Pin: ", this->busy_pin_);
892  LOG_UPDATE_INTERVAL(this);
893 }
894 
895 // ========================================================
896 // 2.7inch_e-paper_b
897 // ========================================================
898 // Datasheet:
899 // - https://www.waveshare.com/w/upload/d/d8/2.7inch-e-paper-b-specification.pdf
900 // - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_2in7b.c
901 
902 static const uint8_t LUT_VCOM_DC_2_7B[44] = {0x00, 0x00, 0x00, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x0A,
903  0x00, 0x00, 0x08, 0x00, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x00, 0x0A,
904  0x0A, 0x00, 0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x00, 0x05, 0x00,
905  0x03, 0x0E, 0x00, 0x00, 0x0A, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01};
906 
907 static const uint8_t LUT_WHITE_TO_WHITE_2_7B[42] = {0x90, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x40, 0x0A, 0x0A, 0x00, 0x00,
908  0x08, 0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x80, 0x0A, 0x0A, 0x00,
909  0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x00, 0x05, 0x00, 0x03, 0x0E,
910  0x00, 0x00, 0x0A, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01};
911 
912 static const uint8_t LUT_BLACK_TO_WHITE_2_7B[42] = {0xA0, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x0A, 0x00, 0x00,
913  0x08, 0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x90, 0x0A, 0x0A, 0x00,
914  0x00, 0x08, 0xB0, 0x04, 0x10, 0x00, 0x00, 0x05, 0xB0, 0x03, 0x0E,
915  0x00, 0x00, 0x0A, 0xC0, 0x23, 0x00, 0x00, 0x00, 0x01};
916 
917 static const uint8_t LUT_WHITE_TO_BLACK_2_7B[] = {0x90, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x20, 0x0A, 0x0A, 0x00, 0x00,
918  0x08, 0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x10, 0x0A, 0x0A, 0x00,
919  0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x00, 0x05, 0x00, 0x03, 0x0E,
920  0x00, 0x00, 0x0A, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01};
921 
922 static const uint8_t LUT_BLACK_TO_BLACK_2_7B[42] = {0x90, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x40, 0x0A, 0x0A, 0x00, 0x00,
923  0x08, 0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x80, 0x0A, 0x0A, 0x00,
924  0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x00, 0x05, 0x00, 0x03, 0x0E,
925  0x00, 0x00, 0x0A, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01};
926 
928  this->reset_();
929 
930  // command power on
931  this->command(0x04);
932  this->wait_until_idle_();
933  delay(10);
934 
935  // Command panel setting
936  this->command(0x00);
937  this->data(0xAF); // KW-BF KWR-AF BWROTP 0f
938  // command pll control
939  this->command(0x30);
940  this->data(0x3A); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
941 
942  // command power setting
943  this->command(0x01);
944  this->data(0x03); // VDS_EN, VDG_EN
945  this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
946  this->data(0x2B); // VDH
947  this->data(0x2B); // VDL
948  this->data(0x09); // VDHR
949 
950  // command booster soft start
951  this->command(0x06);
952  this->data(0x07);
953  this->data(0x07);
954  this->data(0x17);
955 
956  // Power optimization - ???
957  this->command(0xF8);
958  this->data(0x60);
959  this->data(0xA5);
960  this->command(0xF8);
961  this->data(0x89);
962  this->data(0xA5);
963  this->command(0xF8);
964  this->data(0x90);
965  this->data(0x00);
966  this->command(0xF8);
967  this->data(0x93);
968  this->data(0x2A);
969  this->command(0xF8);
970  this->data(0x73);
971  this->data(0x41);
972 
973  // COMMAND VCM DC SETTING
974  this->command(0x82);
975  this->data(0x12);
976 
977  // VCOM_AND_DATA_INTERVAL_SETTING
978  this->command(0x50);
979  this->data(0x87); // define by OTP
980 
981  delay(2);
982  // COMMAND LUT FOR VCOM
983  this->command(0x20);
984  for (uint8_t i : LUT_VCOM_DC_2_7B)
985  this->data(i);
986  // COMMAND LUT WHITE TO WHITE
987  this->command(0x21);
988  for (uint8_t i : LUT_WHITE_TO_WHITE_2_7B)
989  this->data(i);
990  // COMMAND LUT BLACK TO WHITE
991  this->command(0x22);
992  for (uint8_t i : LUT_BLACK_TO_WHITE_2_7B)
993  this->data(i);
994  // COMMAND LUT WHITE TO BLACK
995  this->command(0x23);
996  for (uint8_t i : LUT_WHITE_TO_BLACK_2_7B) {
997  this->data(i);
998  }
999  // COMMAND LUT BLACK TO BLACK
1000  this->command(0x24);
1001 
1002  for (uint8_t i : LUT_BLACK_TO_BLACK_2_7B) {
1003  this->data(i);
1004  }
1005 
1006  delay(2);
1007 }
1008 
1010  uint32_t buf_len_half = this->get_buffer_length_() >> 1;
1011  this->initialize();
1012 
1013  // TCON_RESOLUTION
1014  this->command(0x61);
1015  this->data(this->get_width_controller() >> 8);
1016  this->data(this->get_width_controller() & 0xff); // 176
1017  this->data(this->get_height_internal() >> 8);
1018  this->data(this->get_height_internal() & 0xff); // 264
1019 
1020  // COMMAND DATA START TRANSMISSION 1 (BLACK)
1021  this->command(0x10);
1022  delay(2);
1023  for (uint32_t i = 0; i < buf_len_half; i++) {
1024  this->data(this->buffer_[i]);
1025  }
1026  this->command(0x11);
1027  delay(2);
1028 
1029  // COMMAND DATA START TRANSMISSION 2 (RED)
1030  this->command(0x13);
1031  delay(2);
1032  for (uint32_t i = buf_len_half; i < buf_len_half * 2u; i++) {
1033  this->data(this->buffer_[i]);
1034  }
1035  this->command(0x11);
1036 
1037  delay(2);
1038 
1039  // COMMAND DISPLAY REFRESH
1040  this->command(0x12);
1041  this->wait_until_idle_();
1042 
1043  this->deep_sleep();
1044 }
1048  LOG_DISPLAY("", "Waveshare E-Paper", this);
1049  ESP_LOGCONFIG(TAG, " Model: 2.7in B");
1050  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1051  LOG_PIN(" DC Pin: ", this->dc_pin_);
1052  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1053  LOG_UPDATE_INTERVAL(this);
1054 }
1055 
1056 // ========================================================
1057 // 2.7inch_e-paper_b_v2
1058 // ========================================================
1059 // Datasheet:
1060 // - https://www.waveshare.com/w/upload/7/7b/2.7inch-e-paper-b-v2-specification.pdf
1061 // - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_2in7b_V2.c
1062 
1064  this->reset_();
1065 
1066  this->wait_until_idle_();
1067  this->command(0x12);
1068  this->wait_until_idle_();
1069 
1070  this->command(0x00);
1071  this->data(0x27);
1072  this->data(0x01);
1073  this->data(0x00);
1074 
1075  this->command(0x11);
1076  this->data(0x03);
1077 
1078  // self.SetWindows(0, 0, self.width-1, self.height-1)
1079  // SetWindows(self, Xstart, Ystart, Xend, Yend):
1080 
1081  uint32_t xend = this->get_width_controller() - 1;
1082  uint32_t yend = this->get_height_internal() - 1;
1083  this->command(0x44);
1084  this->data(0x00);
1085  this->data((xend >> 3) & 0xff);
1086 
1087  this->command(0x45);
1088  this->data(0x00);
1089  this->data(0x00);
1090  this->data(yend & 0xff);
1091  this->data((yend >> 8) & 0xff);
1092 
1093  // SetCursor(self, Xstart, Ystart):
1094  this->command(0x4E);
1095  this->data(0x00);
1096  this->command(0x4F);
1097  this->data(0x00);
1098  this->data(0x00);
1099 }
1100 
1102  uint32_t buf_len = this->get_buffer_length_();
1103  // COMMAND DATA START TRANSMISSION 1 (BLACK)
1104  this->command(0x24);
1105  delay(2);
1106  for (uint32_t i = 0; i < buf_len; i++) {
1107  this->data(this->buffer_[i]);
1108  }
1109  delay(2);
1110 
1111  // COMMAND DATA START TRANSMISSION 2 (RED)
1112  this->command(0x26);
1113  delay(2);
1114  for (uint32_t i = 0; i < buf_len; i++) {
1115  this->data(this->buffer_[i]);
1116  }
1117 
1118  delay(2);
1119 
1120  this->command(0x20);
1121 
1122  this->wait_until_idle_();
1123 }
1127  LOG_DISPLAY("", "Waveshare E-Paper", this);
1128  ESP_LOGCONFIG(TAG, " Model: 2.7in B V2");
1129  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1130  LOG_PIN(" DC Pin: ", this->dc_pin_);
1131  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1132  LOG_UPDATE_INTERVAL(this);
1133 }
1134 
1135 // ========================================================
1136 // 2.90in Type B (LUT from OTP)
1137 // Datasheet:
1138 // - https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf
1139 // - https://github.com/soonuse/epd-library-arduino/blob/master/2.9inch_e-paper_b/epd2in9b/epd2in9b.cpp
1140 // ========================================================
1141 
1143  // from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37
1144  // EPD hardware init start
1145  this->reset_();
1146 
1147  // COMMAND BOOSTER SOFT START
1148  this->command(0x06);
1149  this->data(0x17);
1150  this->data(0x17);
1151  this->data(0x17);
1152 
1153  // COMMAND POWER ON
1154  this->command(0x04);
1155  this->wait_until_idle_();
1156 
1157  // COMMAND PANEL SETTING
1158  this->command(0x00);
1159  // 128x296 resolution: 10
1160  // LUT from OTP: 0
1161  // B/W mode (doesn't work): 1
1162  // scan-up: 1
1163  // shift-right: 1
1164  // booster ON: 1
1165  // no soft reset: 1
1166  this->data(0x9F);
1167 
1168  // COMMAND RESOLUTION SETTING
1169  // set to 128x296 by COMMAND PANEL SETTING
1170 
1171  // COMMAND VCOM AND DATA INTERVAL SETTING
1172  // use defaults for white border and ESPHome image polarity
1173 
1174  // EPD hardware init end
1175 }
1177  // COMMAND DATA START TRANSMISSION 1 (B/W data)
1178  this->command(0x10);
1179  delay(2);
1180  this->start_data_();
1181  this->write_array(this->buffer_, this->get_buffer_length_());
1182  this->end_data_();
1183  delay(2);
1184 
1185  // COMMAND DATA START TRANSMISSION 2 (RED data)
1186  this->command(0x13);
1187  delay(2);
1188  this->start_data_();
1189  for (size_t i = 0; i < this->get_buffer_length_(); i++)
1190  this->write_byte(0x00);
1191  this->end_data_();
1192  delay(2);
1193 
1194  // COMMAND DISPLAY REFRESH
1195  this->command(0x12);
1196  delay(2);
1197  this->wait_until_idle_();
1198 
1199  // COMMAND POWER OFF
1200  // NOTE: power off < deep sleep
1201  this->command(0x02);
1202 }
1206  LOG_DISPLAY("", "Waveshare E-Paper", this);
1207  ESP_LOGCONFIG(TAG, " Model: 2.9in (B)");
1208  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1209  LOG_PIN(" DC Pin: ", this->dc_pin_);
1210  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1211  LOG_UPDATE_INTERVAL(this);
1212 }
1213 
1214 // DKE 2.9
1215 // https://www.badge.team/docs/badges/sha2017/hardware/#e-ink-display-the-dke-group-depg0290b1
1216 // https://www.badge.team/docs/badges/sha2017/hardware/DEPG0290B01V3.0.pdf
1217 static const uint8_t LUT_SIZE_DKE = 70;
1218 static const uint8_t UPDATE_LUT_DKE[LUT_SIZE_DKE] = {
1219  0xA0, 0x90, 0x50, 0x0, 0x0, 0x0, 0x0, 0x50, 0x90, 0xA0, 0x0, 0x0, 0x0, 0x0, 0xA0, 0x90, 0x50, 0x0,
1220  0x0, 0x0, 0x0, 0x50, 0x90, 0xA0, 0x0, 0x0, 0x0, 0x0, 0x00, 0x00, 0x00, 0x0, 0x0, 0x0, 0x0, 0xF,
1221  0xF, 0x0, 0x0, 0x0, 0xF, 0xF, 0x0, 0x0, 0x02, 0xF, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1222  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1223 };
1224 static const uint8_t PART_UPDATE_LUT_DKE[LUT_SIZE_DKE] = {
1225  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xa0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x50, 0x10, 0x00, 0x00,
1226  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
1227  0x05, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1228  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1229 static const uint8_t FULL_UPDATE_LUT_DKE[LUT_SIZE_DKE] = {
1230  0x90, 0x50, 0xa0, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x10, 0xa0, 0xa0, 0x80, 0x00, 0x90, 0x50, 0xa0, 0x50,
1231  0x50, 0x00, 0x00, 0x00, 0x00, 0x10, 0xa0, 0xa0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
1232  0x04, 0x00, 0x00, 0x00, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00,
1233  0x00, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1234 
1236  // Hardware reset
1237  delay(10);
1238  this->reset_pin_->digital_write(false);
1239  delayMicroseconds(200);
1240  this->reset_pin_->digital_write(true);
1241  delayMicroseconds(200);
1242  // Wait for busy low
1243  this->wait_until_idle_();
1244  // Software reset
1245  this->command(0x12);
1246  // Wait for busy low
1247  this->wait_until_idle_();
1248  // Set Analog Block Control
1249  this->command(0x74);
1250  this->data(0x54);
1251  // Set Digital Block Control
1252  this->command(0x7E);
1253  this->data(0x3B);
1254  // Set display size and driver output control
1255  this->command(0x01);
1256  // this->data(0x27);
1257  // this->data(0x01);
1258  // this->data(0x00);
1259  this->data(this->get_height_internal() - 1);
1260  this->data((this->get_height_internal() - 1) >> 8);
1261  this->data(0x00); // ? GD = 0, SM = 0, TB = 0
1262  // Ram data entry mode
1263  this->command(0x11);
1264  this->data(0x03);
1265  // Set Ram X address
1266  this->command(0x44);
1267  this->data(0x00);
1268  this->data(0x0F);
1269  // Set Ram Y address
1270  this->command(0x45);
1271  this->data(0x00);
1272  this->data(0x00);
1273  this->data(0x27);
1274  this->data(0x01);
1275  // Set border
1276  this->command(0x3C);
1277  // this->data(0x80);
1278  this->data(0x01);
1279  // Set VCOM value
1280  this->command(0x2C);
1281  this->data(0x26);
1282  // Gate voltage setting
1283  this->command(0x03);
1284  this->data(0x17);
1285  // Source voltage setting
1286  this->command(0x04);
1287  this->data(0x41);
1288  this->data(0x00);
1289  this->data(0x32);
1290  // Frame setting 50hz
1291  this->command(0x3A);
1292  this->data(0x30);
1293  this->command(0x3B);
1294  this->data(0x0A);
1295  // Load LUT
1296  this->command(0x32);
1297  for (uint8_t v : FULL_UPDATE_LUT_DKE)
1298  this->data(v);
1299 }
1300 
1302  ESP_LOGI(TAG, "Performing e-paper update.");
1303  // Set Ram X address counter
1304  this->command(0x4e);
1305  this->data(0);
1306  // Set Ram Y address counter
1307  this->command(0x4f);
1308  this->data(0);
1309  this->data(0);
1310  // Load image (128/8*296)
1311  this->command(0x24);
1312  this->start_data_();
1313  this->write_array(this->buffer_, this->get_buffer_length_());
1314  this->end_data_();
1315  // Image update
1316  this->command(0x22);
1317  this->data(0xC7);
1318  this->command(0x20);
1319  // Wait for busy low
1320  this->wait_until_idle_();
1321  // Enter deep sleep mode
1322  this->command(0x10);
1323  this->data(0x01);
1324 }
1328  LOG_DISPLAY("", "Waveshare E-Paper", this);
1329  ESP_LOGCONFIG(TAG, " Model: 2.9in DKE");
1330  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1331  LOG_PIN(" DC Pin: ", this->dc_pin_);
1332  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1333  LOG_UPDATE_INTERVAL(this);
1334 }
1335 void WaveshareEPaper2P9InDKE::set_full_update_every(uint32_t full_update_every) {
1336  this->full_update_every_ = full_update_every;
1337 }
1338 
1339 // ========================================================
1340 // 2.90in Type B (LUT from OTP)
1341 // Datasheet:
1342 // - https://files.waveshare.com/upload/a/af/2.9inch-e-paper-b-v3-specification.pdf
1343 // ========================================================
1344 
1346  // from https://github.com/waveshareteam/e-Paper/blob/master/Arduino/epd2in9b_V3/epd2in9b_V3.cpp
1347  this->reset_();
1348 
1349  // COMMAND POWER ON
1350  this->command(0x04);
1351  this->wait_until_idle_();
1352 
1353  // COMMAND PANEL SETTING
1354  this->command(0x00);
1355  this->data(0x0F);
1356  this->data(0x89);
1357 
1358  // COMMAND RESOLUTION SETTING
1359  this->command(0x61);
1360  this->data(0x80);
1361  this->data(0x01);
1362  this->data(0x28);
1363 
1364  // COMMAND VCOM AND DATA INTERVAL SETTING
1365  this->command(0x50);
1366  this->data(0x77);
1367 }
1369  // COMMAND DATA START TRANSMISSION 1 (B/W data)
1370  this->command(0x10);
1371  delay(2);
1372  this->start_data_();
1373  this->write_array(this->buffer_, this->get_buffer_length_());
1374  this->end_data_();
1375  this->command(0x92);
1376  delay(2);
1377 
1378  // COMMAND DATA START TRANSMISSION 2 (RED data)
1379  this->command(0x13);
1380  delay(2);
1381  this->start_data_();
1382  for (size_t i = 0; i < this->get_buffer_length_(); i++)
1383  this->write_byte(0xFF);
1384  this->end_data_();
1385  this->command(0x92);
1386  delay(2);
1387 
1388  // COMMAND DISPLAY REFRESH
1389  this->command(0x12);
1390  delay(2);
1391  this->wait_until_idle_();
1392 
1393  // COMMAND POWER OFF
1394  // NOTE: power off < deep sleep
1395  this->command(0x02);
1396 }
1400  LOG_DISPLAY("", "Waveshare E-Paper", this);
1401  ESP_LOGCONFIG(TAG, " Model: 2.9in (B) V3");
1402  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1403  LOG_PIN(" DC Pin: ", this->dc_pin_);
1404  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1405  LOG_UPDATE_INTERVAL(this);
1406 }
1407 
1408 // ========================================================
1409 // 2.90in v2 rev2
1410 // based on SDK and examples in ZIP file from:
1411 // https://www.waveshare.com/pico-epaper-2.9.htm
1412 // ========================================================
1413 
1415  this->reset_();
1416  this->wait_until_idle_();
1417 
1418  this->command(0x12); // SWRESET
1419  this->wait_until_idle_();
1420 
1421  this->command(0x01);
1422  this->data(0x27);
1423  this->data(0x01);
1424  this->data(0x00);
1425 
1426  this->command(0x11);
1427  this->data(0x03);
1428 
1429  // SetWindows(0, 0, w, h)
1430  this->command(0x44);
1431  this->data(0x00);
1432  this->data(((this->get_width_controller() - 1) >> 3) & 0xFF);
1433 
1434  this->command(0x45);
1435  this->data(0x00);
1436  this->data(0x00);
1437  this->data((this->get_height_internal() - 1) & 0xFF);
1438  this->data(((this->get_height_internal() - 1) >> 8) & 0xFF);
1439 
1440  this->command(0x21);
1441  this->data(0x00);
1442  this->data(0x80);
1443 
1444  // SetCursor(0, 0)
1445  this->command(0x4E);
1446  this->data(0x00);
1447  this->command(0x4f);
1448  this->data(0x00);
1449  this->data(0x00);
1450 
1451  this->wait_until_idle_();
1452 }
1453 
1455 
1456 void WaveshareEPaper2P9InV2R2::reset_() {
1457  if (this->reset_pin_ != nullptr) {
1458  this->reset_pin_->digital_write(false);
1459  delay(reset_duration_); // NOLINT
1460  this->reset_pin_->digital_write(true);
1461  delay(reset_duration_); // NOLINT
1462  }
1463 }
1464 
1466  if (!this->wait_until_idle_()) {
1467  this->status_set_warning();
1468  ESP_LOGE(TAG, "fail idle 1");
1469  return;
1470  }
1471 
1472  if (this->full_update_every_ == 1) {
1473  // do single full update
1474  this->command(0x24);
1475  this->start_data_();
1476  this->write_array(this->buffer_, this->get_buffer_length_());
1477  this->end_data_();
1478 
1479  // TurnOnDisplay
1480  this->command(0x22);
1481  this->data(0xF7);
1482  this->command(0x20);
1483  return;
1484  }
1485 
1486  // if (this->full_update_every_ == 1 ||
1487  if (this->at_update_ == 0) {
1488  // do base update
1489  this->command(0x24);
1490  this->start_data_();
1491  this->write_array(this->buffer_, this->get_buffer_length_());
1492  this->end_data_();
1493 
1494  this->command(0x26);
1495  this->start_data_();
1496  this->write_array(this->buffer_, this->get_buffer_length_());
1497  this->end_data_();
1498 
1499  // TurnOnDisplay
1500  this->command(0x22);
1501  this->data(0xF7);
1502  this->command(0x20);
1503  } else {
1504  // do partial update
1505  this->reset_();
1506 
1507  this->write_lut_(PARTIAL_UPD_2IN9_LUT, PARTIAL_UPD_2IN9_LUT_SIZE);
1508 
1509  this->command(0x37);
1510  this->data(0x00);
1511  this->data(0x00);
1512  this->data(0x00);
1513  this->data(0x00);
1514  this->data(0x00);
1515  this->data(0x40);
1516  this->data(0x00);
1517  this->data(0x00);
1518  this->data(0x00);
1519  this->data(0x00);
1520 
1521  this->command(0x3C);
1522  this->data(0x80);
1523 
1524  this->command(0x22);
1525  this->data(0xC0);
1526  this->command(0x20);
1527 
1528  if (!this->wait_until_idle_()) {
1529  ESP_LOGE(TAG, "fail idle 2");
1530  }
1531 
1532  // SetWindows(0, 0, w, h)
1533  this->command(0x44);
1534  this->data(0x00);
1535  this->data(((this->get_width_controller() - 1) >> 3) & 0xFF);
1536 
1537  this->command(0x45);
1538  this->data(0x00);
1539  this->data(0x00);
1540  this->data((this->get_height_internal() - 1) & 0xFF);
1541  this->data(((this->get_height_internal() - 1) >> 8) & 0xFF);
1542 
1543  // SetCursor(0, 0)
1544  this->command(0x4E);
1545  this->data(0x00);
1546  this->command(0x4f);
1547  this->data(0x00);
1548  this->data(0x00);
1549 
1550  // write b/w
1551  this->command(0x24);
1552  this->start_data_();
1553  this->write_array(this->buffer_, this->get_buffer_length_());
1554  this->end_data_();
1555 
1556  // TurnOnDisplayPartial
1557  this->command(0x22);
1558  this->data(0x0F);
1559  this->command(0x20);
1560  }
1561 
1562  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
1563 }
1564 
1565 void WaveshareEPaper2P9InV2R2::write_lut_(const uint8_t *lut, const uint8_t size) {
1566  // COMMAND WRITE LUT REGISTER
1567  this->command(0x32);
1568  for (uint8_t i = 0; i < size; i++)
1569  this->data(lut[i]);
1570 }
1571 
1573  LOG_DISPLAY("", "Waveshare E-Paper", this);
1574  ESP_LOGCONFIG(TAG, " Model: 2.9inV2R2");
1575  ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
1576  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1577  LOG_PIN(" DC Pin: ", this->dc_pin_);
1578  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1579  LOG_UPDATE_INTERVAL(this);
1580 }
1581 
1583  this->command(0x10);
1584  this->data(0x01);
1585 }
1586 
1590 void WaveshareEPaper2P9InV2R2::set_full_update_every(uint32_t full_update_every) {
1591  this->full_update_every_ = full_update_every;
1592 }
1593 
1594 // ========================================================
1595 // Good Display 2.9in black/white/grey
1596 // Datasheet:
1597 // - https://v4.cecdn.yun300.cn/100001_1909185148/SSD1680.pdf
1598 // - https://github.com/adafruit/Adafruit_EPD/blob/master/src/panels/ThinkInk_290_Grayscale4_T5.h
1599 // ========================================================
1600 
1602  // from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37
1603  // EPD hardware init start
1604  this->reset_();
1605 
1606  // COMMAND POWER SETTINGS
1607  this->command(0x00);
1608  this->data(0x03);
1609  this->data(0x00);
1610  this->data(0x2b);
1611  this->data(0x2b);
1612  this->data(0x03); /* for b/w */
1613 
1614  // COMMAND BOOSTER SOFT START
1615  this->command(0x06);
1616  this->data(0x17);
1617  this->data(0x17);
1618  this->data(0x17);
1619 
1620  // COMMAND POWER ON
1621  this->command(0x04);
1622  this->wait_until_idle_();
1623 
1624  // Not sure what this does but it's in the Adafruit EPD library
1625  this->command(0xFF);
1626  this->wait_until_idle_();
1627 
1628  // COMMAND PANEL SETTING
1629  this->command(0x00);
1630  // 128x296 resolution: 10
1631  // LUT from OTP: 0
1632  // B/W mode (doesn't work): 1
1633  // scan-up: 1
1634  // shift-right: 1
1635  // booster ON: 1
1636  // no soft reset: 1
1637  this->data(0b10011111);
1638 
1639  // COMMAND RESOLUTION SETTING
1640  // set to 128x296 by COMMAND PANEL SETTING
1641 
1642  // COMMAND VCOM AND DATA INTERVAL SETTING
1643  // use defaults for white border and ESPHome image polarity
1644 
1645  // EPD hardware init end
1646 }
1648  // COMMAND DATA START TRANSMISSION 2 (B/W only)
1649  this->command(0x13);
1650  delay(2);
1651  this->start_data_();
1652  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
1653  this->write_byte(this->buffer_[i]);
1654  }
1655  this->end_data_();
1656  delay(2);
1657 
1658  // COMMAND DISPLAY REFRESH
1659  this->command(0x12);
1660  delay(2);
1661  this->wait_until_idle_();
1662 
1663  // COMMAND POWER OFF
1664  // NOTE: power off < deep sleep
1665  this->command(0x02);
1666 }
1667 int GDEW029T5::get_width_internal() { return 128; }
1668 int GDEW029T5::get_height_internal() { return 296; }
1670  LOG_DISPLAY("", "Waveshare E-Paper (Good Display)", this);
1671  ESP_LOGCONFIG(TAG, " Model: 2.9in Greyscale GDEW029T5");
1672  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1673  LOG_PIN(" DC Pin: ", this->dc_pin_);
1674  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1675  LOG_UPDATE_INTERVAL(this);
1676 }
1677 
1678 // ========================================================
1679 // Good Display 1.54in black/white/grey GDEW0154M09
1680 // As used in M5Stack Core Ink
1681 // Datasheet:
1682 // - https://v4.cecdn.yun300.cn/100001_1909185148/GDEW0154M09-200709.pdf
1683 // - https://github.com/m5stack/M5Core-Ink
1684 // Reference code from GoodDisplay:
1685 // - https://github.com/GoodDisplay/E-paper-Display-Library-of-GoodDisplay/
1686 // -> /Monochrome_E-paper-Display/1.54inch_JD79653_GDEW0154M09_200x200/ESP32-Arduino%20IDE/GDEW0154M09_Arduino.ino
1687 // M5Stack Core Ink spec:
1688 // - https://docs.m5stack.com/en/core/coreink
1689 // ========================================================
1690 
1692  this->init_internal_();
1694  this->lastbuff_ = allocator.allocate(this->get_buffer_length_());
1695  if (this->lastbuff_ != nullptr) {
1696  memset(this->lastbuff_, 0xff, sizeof(uint8_t) * this->get_buffer_length_());
1697  }
1698  this->clear_();
1699 }
1700 
1701 void GDEW0154M09::reset_() {
1702  // RST is inverse from other einks in this project
1703  if (this->reset_pin_ != nullptr) {
1704  this->reset_pin_->digital_write(false);
1705  delay(10);
1706  this->reset_pin_->digital_write(true);
1707  delay(10);
1708  }
1709 }
1710 
1711 void GDEW0154M09::init_internal_() {
1712  this->reset_();
1713 
1714  // clang-format off
1715  // 200x200 resolution: 11
1716  // LUT from OTP: 0
1717  // B/W mode (doesn't work): 1
1718  // scan-up: 1
1719  // shift-right: 1
1720  // booster ON: 1
1721  // no soft reset: 1
1722  const uint8_t panel_setting_1 = 0b11011111;
1723 
1724  // VCOM status off 0
1725  // Temp sensing default 1
1726  // VGL Power Off Floating 1
1727  // NORG expect refresh 1
1728  // VCOM Off on displ off 0
1729  const uint8_t panel_setting_2 = 0b01110;
1730 
1731  const uint8_t wf_t0154_cz_b3_list[] = {
1732  11, // 11 commands in list
1733  CMD_PSR_PANEL_SETTING, 2, panel_setting_1, panel_setting_2,
1734  CMD_UNDOCUMENTED_0x4D, 1, 0x55,
1735  CMD_UNDOCUMENTED_0xAA, 1, 0x0f,
1736  CMD_UNDOCUMENTED_0xE9, 1, 0x02,
1737  CMD_UNDOCUMENTED_0xB6, 1, 0x11,
1738  CMD_UNDOCUMENTED_0xF3, 1, 0x0a,
1739  CMD_TRES_RESOLUTION_SETTING, 3, 0xc8, 0x00, 0xc8,
1740  CMD_TCON_TCONSETTING, 1, 0x00,
1741  CMD_CDI_VCOM_DATA_INTERVAL, 1, 0xd7,
1742  CMD_PWS_POWER_SAVING, 1, 0x00,
1743  CMD_PON_POWER_ON, 0
1744  };
1745  // clang-format on
1746 
1747  this->write_init_list_(wf_t0154_cz_b3_list);
1748  delay(100); // NOLINT
1749  this->wait_until_idle_();
1750 }
1751 
1752 void GDEW0154M09::write_init_list_(const uint8_t *list) {
1753  uint8_t list_limit = list[0];
1754  uint8_t *start_ptr = ((uint8_t *) list + 1);
1755  for (uint8_t i = 0; i < list_limit; i++) {
1756  this->command(*(start_ptr + 0));
1757  for (uint8_t dnum = 0; dnum < *(start_ptr + 1); dnum++) {
1758  this->data(*(start_ptr + 2 + dnum));
1759  }
1760  start_ptr += (*(start_ptr + 1) + 2);
1761  }
1762 }
1763 
1764 void GDEW0154M09::clear_() {
1765  uint32_t pixsize = this->get_buffer_length_();
1766  for (uint8_t j = 0; j < 2; j++) {
1767  this->command(CMD_DTM1_DATA_START_TRANS);
1768  for (int count = 0; count < pixsize; count++) {
1769  this->data(0x00);
1770  }
1771  this->command(CMD_DTM2_DATA_START_TRANS2);
1772  for (int count = 0; count < pixsize; count++) {
1773  this->data(0xff);
1774  }
1775  this->command(CMD_DISPLAY_REFRESH);
1776  delay(10);
1777  this->wait_until_idle_();
1778  }
1779 }
1780 
1782  this->init_internal_();
1783  // "Mode 0 display" for now
1784  this->command(CMD_DTM1_DATA_START_TRANS);
1785  for (int i = 0; i < this->get_buffer_length_(); i++) {
1786  this->data(0xff);
1787  }
1788  this->command(CMD_DTM2_DATA_START_TRANS2); // write 'new' data to SRAM
1789  for (int i = 0; i < this->get_buffer_length_(); i++) {
1790  this->data(this->buffer_[i]);
1791  }
1792  this->command(CMD_DISPLAY_REFRESH);
1793  delay(10);
1794  this->wait_until_idle_();
1795  this->deep_sleep();
1796 }
1797 
1799  // COMMAND DEEP SLEEP
1800  this->command(CMD_POF_POWER_OFF);
1801  this->wait_until_idle_();
1802  delay(1000); // NOLINT
1803  this->command(CMD_DSLP_DEEP_SLEEP);
1804  this->data(DATA_DSLP_DEEP_SLEEP);
1805 }
1806 
1807 int GDEW0154M09::get_width_internal() { return 200; }
1810  LOG_DISPLAY("", "M5Stack CoreInk E-Paper (Good Display)", this);
1811  ESP_LOGCONFIG(TAG, " Model: 1.54in Greyscale GDEW0154M09");
1812  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1813  LOG_PIN(" DC Pin: ", this->dc_pin_);
1814  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1815  LOG_UPDATE_INTERVAL(this);
1816 }
1817 
1818 static const uint8_t LUT_VCOM_DC_4_2[] = {
1819  0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x17, 0x17, 0x00, 0x00, 0x02, 0x00, 0x0A, 0x01,
1820  0x00, 0x00, 0x01, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1821  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1822 };
1823 static const uint8_t LUT_WHITE_TO_WHITE_4_2[] = {
1824  0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A,
1825  0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1826  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1827 };
1828 static const uint8_t LUT_BLACK_TO_WHITE_4_2[] = {
1829  0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A,
1830  0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1831  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1832 };
1833 
1834 static const uint8_t LUT_BLACK_TO_BLACK_4_2[] = {
1835  0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A,
1836  0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1837  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1838 };
1839 
1840 static const uint8_t LUT_WHITE_TO_BLACK_4_2[] = {
1841  0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A,
1842  0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1843  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1844 };
1845 
1847  // https://www.waveshare.com/w/upload/7/7f/4.2inch-e-paper-b-specification.pdf - page 8
1848 
1849  // COMMAND POWER SETTING
1850  this->command(0x01);
1851  this->data(0x03); // VDS_EN, VDG_EN
1852  this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
1853  this->data(0x2B); // VDH
1854  this->data(0x2B); // VDL
1855  this->data(0xFF); // VDHR
1856 
1857  // COMMAND BOOSTER SOFT START
1858  this->command(0x06);
1859  this->data(0x17); // PHA
1860  this->data(0x17); // PHB
1861  this->data(0x17); // PHC
1862 
1863  // COMMAND POWER ON
1864  this->command(0x04);
1865  this->wait_until_idle_();
1866  delay(10);
1867  // COMMAND PANEL SETTING
1868  this->command(0x00);
1869  this->data(0xBF); // KW-BF KWR-AF BWROTP 0f
1870  this->data(0x0B);
1871  // COMMAND PLL CONTROL
1872  this->command(0x30);
1873  this->data(0x3C); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
1874 
1875  delay(2);
1876  // COMMAND LUT FOR VCOM
1877  this->command(0x20);
1878  for (uint8_t i : LUT_VCOM_DC_4_2)
1879  this->data(i);
1880  // COMMAND LUT WHITE TO WHITE
1881  this->command(0x21);
1882  for (uint8_t i : LUT_WHITE_TO_WHITE_4_2)
1883  this->data(i);
1884  // COMMAND LUT BLACK TO WHITE
1885  this->command(0x22);
1886  for (uint8_t i : LUT_BLACK_TO_WHITE_4_2)
1887  this->data(i);
1888  // COMMAND LUT WHITE TO BLACK
1889  this->command(0x23);
1890  for (uint8_t i : LUT_WHITE_TO_BLACK_4_2)
1891  this->data(i);
1892  // COMMAND LUT BLACK TO BLACK
1893  this->command(0x24);
1894  for (uint8_t i : LUT_BLACK_TO_BLACK_4_2)
1895  this->data(i);
1896 }
1898  // COMMAND RESOLUTION SETTING
1899  this->command(0x61);
1900  this->data(0x01);
1901  this->data(0x90);
1902  this->data(0x01);
1903  this->data(0x2C);
1904 
1905  // COMMAND VCM DC SETTING REGISTER
1906  this->command(0x82);
1907  this->data(0x12);
1908 
1909  // COMMAND VCOM AND DATA INTERVAL SETTING
1910  this->command(0x50);
1911  this->data(0x97);
1912 
1913  // COMMAND DATA START TRANSMISSION 1
1914  this->command(0x10);
1915  delay(2);
1916  this->start_data_();
1917  this->write_array(this->buffer_, this->get_buffer_length_());
1918  this->end_data_();
1919  delay(2);
1920  // COMMAND DATA START TRANSMISSION 2
1921  this->command(0x13);
1922  delay(2);
1923  this->start_data_();
1924  this->write_array(this->buffer_, this->get_buffer_length_());
1925  this->end_data_();
1926  // COMMAND DISPLAY REFRESH
1927  this->command(0x12);
1928 }
1932  LOG_DISPLAY("", "Waveshare E-Paper", this);
1933  ESP_LOGCONFIG(TAG, " Model: 4.2in");
1934  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1935  LOG_PIN(" DC Pin: ", this->dc_pin_);
1936  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1937  LOG_UPDATE_INTERVAL(this);
1938 }
1939 
1940 // ========================================================
1941 // 4.20in Type B (LUT from OTP)
1942 // Datasheet:
1943 // - https://www.waveshare.com/w/upload/2/20/4.2inch-e-paper-module-user-manual-en.pdf
1944 // - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_4in2b_V2.c
1945 // ========================================================
1947  // these exact timings are required for a proper reset/init
1948  this->reset_pin_->digital_write(false);
1949  delay(2);
1950  this->reset_pin_->digital_write(true);
1951  delay(200); // NOLINT
1952 
1953  // COMMAND POWER ON
1954  this->command(0x04);
1955  this->wait_until_idle_();
1956 
1957  // COMMAND PANEL SETTING
1958  this->command(0x00);
1959  this->data(0x0f); // LUT from OTP
1960 }
1961 
1963  // COMMAND DATA START TRANSMISSION 1 (B/W data)
1964  this->command(0x10);
1965  this->start_data_();
1966  this->write_array(this->buffer_, this->get_buffer_length_());
1967  this->end_data_();
1968 
1969  // COMMAND DATA START TRANSMISSION 2 (RED data)
1970  this->command(0x13);
1971  this->start_data_();
1972  for (size_t i = 0; i < this->get_buffer_length_(); i++)
1973  this->write_byte(0xFF);
1974  this->end_data_();
1975  delay(2);
1976 
1977  // COMMAND DISPLAY REFRESH
1978  this->command(0x12);
1979  this->wait_until_idle_();
1980 
1981  // COMMAND POWER OFF
1982  // NOTE: power off < deep sleep
1983  this->command(0x02);
1984 }
1988  LOG_DISPLAY("", "Waveshare E-Paper", this);
1989  ESP_LOGCONFIG(TAG, " Model: 4.2in (B V2)");
1990  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1991  LOG_PIN(" DC Pin: ", this->dc_pin_);
1992  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1993  LOG_UPDATE_INTERVAL(this);
1994 }
1995 
1997  // COMMAND POWER SETTING
1998  this->command(0x01);
1999  this->data(0x37);
2000  this->data(0x00);
2001 
2002  // COMMAND PANEL SETTING
2003  this->command(0x00);
2004  this->data(0xCF);
2005  this->data(0x0B);
2006 
2007  // COMMAND BOOSTER SOFT START
2008  this->command(0x06);
2009  this->data(0xC7);
2010  this->data(0xCC);
2011  this->data(0x28);
2012 
2013  // COMMAND POWER ON
2014  this->command(0x04);
2015  this->wait_until_idle_();
2016  delay(10);
2017 
2018  // COMMAND PLL CONTROL
2019  this->command(0x30);
2020  this->data(0x3C);
2021 
2022  // COMMAND TEMPERATURE SENSOR CALIBRATION
2023  this->command(0x41);
2024  this->data(0x00);
2025 
2026  // COMMAND VCOM AND DATA INTERVAL SETTING
2027  this->command(0x50);
2028  this->data(0x77);
2029 
2030  // COMMAND TCON SETTING
2031  this->command(0x60);
2032  this->data(0x22);
2033 
2034  // COMMAND RESOLUTION SETTING
2035  this->command(0x61);
2036  this->data(0x02);
2037  this->data(0x58);
2038  this->data(0x01);
2039  this->data(0xC0);
2040 
2041  // COMMAND VCM DC SETTING REGISTER
2042  this->command(0x82);
2043  this->data(0x1E);
2044 
2045  this->command(0xE5);
2046  this->data(0x03);
2047 }
2049  // COMMAND DATA START TRANSMISSION 1
2050  this->command(0x10);
2051 
2052  this->start_data_();
2053  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
2054  uint8_t temp1 = this->buffer_[i];
2055  for (uint8_t j = 0; j < 8; j++) {
2056  uint8_t temp2;
2057  if (temp1 & 0x80) {
2058  temp2 = 0x03;
2059  } else {
2060  temp2 = 0x00;
2061  }
2062 
2063  temp2 <<= 4;
2064  temp1 <<= 1;
2065  j++;
2066  if (temp1 & 0x80) {
2067  temp2 |= 0x03;
2068  } else {
2069  temp2 |= 0x00;
2070  }
2071  temp1 <<= 1;
2072  this->write_byte(temp2);
2073  }
2074 
2075  App.feed_wdt();
2076  }
2077  this->end_data_();
2078 
2079  // COMMAND DISPLAY REFRESH
2080  this->command(0x12);
2081 }
2085  LOG_DISPLAY("", "Waveshare E-Paper", this);
2086  ESP_LOGCONFIG(TAG, " Model: 5.83in");
2087  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2088  LOG_PIN(" DC Pin: ", this->dc_pin_);
2089  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2090  LOG_UPDATE_INTERVAL(this);
2091 }
2092 
2093 // ========================================================
2094 // 5.83in V2
2095 // Datasheet/Specification/Reference:
2096 // - https://www.waveshare.com/w/upload/3/37/5.83inch_e-Paper_V2_Specification.pdf
2097 // - https://github.com/waveshare/e-Paper/blob/master/Arduino/epd5in83_V2/epd5in83_V2.cpp
2098 // ========================================================
2100  // COMMAND POWER SETTING
2101  this->command(0x01);
2102  this->data(0x07);
2103  this->data(0x07);
2104  this->data(0x3f);
2105  this->data(0x3f);
2106 
2107  // COMMAND POWER ON
2108  this->command(0x04);
2109  delay(10);
2110  this->wait_until_idle_();
2111 
2112  // PANNEL SETTING
2113  this->command(0x00);
2114  this->data(0x1F);
2115 
2116  // COMMAND RESOLUTION SETTING
2117  this->command(0x61);
2118  this->data(0x02);
2119  this->data(0x88);
2120  this->data(0x01);
2121  this->data(0xE0);
2122 
2123  this->command(0x15);
2124  this->data(0x00);
2125 
2126  // COMMAND TCON SETTING
2127  this->command(0x60);
2128  this->data(0x22);
2129 
2130  // Do we need this?
2131  // COMMAND PLL CONTROL
2132  this->command(0x30);
2133  this->data(0x3C); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
2134 }
2136  // Reuse the code from WaveshareEPaper4P2In::display()
2137  // COMMAND VCM DC SETTING REGISTER
2138  this->command(0x82);
2139  this->data(0x12);
2140 
2141  // COMMAND VCOM AND DATA INTERVAL SETTING
2142  this->command(0x50);
2143  this->data(0x97);
2144 
2145  // COMMAND DATA START TRANSMISSION 1
2146  this->command(0x10);
2147  delay(2);
2148  this->start_data_();
2149  this->write_array(this->buffer_, this->get_buffer_length_());
2150  this->end_data_();
2151  delay(2);
2152 
2153  // COMMAND DATA START TRANSMISSION 2
2154  this->command(0x13);
2155  delay(2);
2156  this->start_data_();
2157  this->write_array(this->buffer_, this->get_buffer_length_());
2158  this->end_data_();
2159 
2160  // COMMAND DISPLAY REFRESH
2161  this->command(0x12);
2162 }
2166  LOG_DISPLAY("", "Waveshare E-Paper", this);
2167  ESP_LOGCONFIG(TAG, " Model: 5.83inv2");
2168  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2169  LOG_PIN(" DC Pin: ", this->dc_pin_);
2170  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2171  LOG_UPDATE_INTERVAL(this);
2172 }
2173 
2175  // COMMAND POWER SETTING
2176  this->command(0x01);
2177  this->data(0x07);
2178  this->data(0x07); // VGH=20V,VGL=-20V
2179  this->data(0x3f); // VDH=15V
2180  this->data(0x3f); // VDL=-15V
2181  // COMMAND POWER ON
2182  this->command(0x04);
2183  delay(100); // NOLINT
2184  this->wait_until_idle_();
2185  // COMMAND PANEL SETTING
2186  this->command(0x00);
2187  this->data(0x0F); // KW3f, KWR-2F, BWROTP 0f, BWOTP 1f
2188  this->command(0x61); // tres
2189  this->data(0x03); // 800px
2190  this->data(0x20);
2191  this->data(0x01); // 400px
2192  this->data(0xE0);
2193  this->command(0x15);
2194  this->data(0x00);
2195  // COMMAND VCOM AND DATA INTERVAL SETTING
2196  this->command(0x50);
2197  this->data(0x11);
2198  this->data(0x07);
2199  // COMMAND TCON SETTING
2200  this->command(0x60);
2201  this->data(0x22);
2202 
2203  this->command(0x82);
2204  this->data(0x08);
2205  this->command(0x30);
2206  this->data(0x06);
2207 
2208  // COMMAND RESOLUTION SETTING
2209  this->command(0x65);
2210  this->data(0x00);
2211  this->data(0x00); // 800*480
2212  this->data(0x00);
2213  this->data(0x00);
2214 }
2216  // COMMAND DATA START TRANSMISSION 1 (B/W data)
2217  this->command(0x10);
2218  delay(2);
2219  this->start_data_();
2220  this->write_array(this->buffer_, this->get_buffer_length_());
2221  this->end_data_();
2222  delay(2);
2223 
2224  // COMMAND DATA START TRANSMISSION 2 (RED data)
2225  this->command(0x13);
2226  delay(2);
2227  this->start_data_();
2228  for (size_t i = 0; i < this->get_buffer_length_(); i++)
2229  this->write_byte(0x00);
2230  this->end_data_();
2231  delay(2);
2232 
2233  // COMMAND DISPLAY REFRESH
2234  this->command(0x12);
2235  delay(100); // NOLINT
2236  this->wait_until_idle_();
2237  this->deep_sleep();
2238 }
2242  LOG_DISPLAY("", "Waveshare E-Paper", this);
2243  ESP_LOGCONFIG(TAG, " Model: 7.5in-bv2");
2244  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2245  LOG_PIN(" DC Pin: ", this->dc_pin_);
2246  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2247  LOG_UPDATE_INTERVAL(this);
2248 }
2249 
2252  if (this->busy_pin_ == nullptr) {
2253  return true;
2254  }
2255 
2256  const uint32_t start = millis();
2257  while (this->busy_pin_->digital_read()) {
2258  this->command(0x71);
2259  if (millis() - start > this->idle_timeout_()) {
2260  ESP_LOGI(TAG, "Timeout while displaying image!");
2261  return false;
2262  }
2263  App.feed_wdt();
2264  delay(10);
2265  }
2266  delay(200); // NOLINT
2267  return true;
2268 };
2270  this->reset_();
2271 
2272  // COMMAND POWER SETTING
2273  this->command(0x01);
2274 
2275  // 1-0=11: internal power
2276  this->data(0x07);
2277  this->data(0x17); // VGH&VGL
2278  this->data(0x3F); // VSH
2279  this->data(0x26); // VSL
2280  this->data(0x11); // VSHR
2281 
2282  // VCOM DC Setting
2283  this->command(0x82);
2284  this->data(0x24); // VCOM
2285 
2286  // Booster Setting
2287  this->command(0x06);
2288  this->data(0x27);
2289  this->data(0x27);
2290  this->data(0x2F);
2291  this->data(0x17);
2292 
2293  // POWER ON
2294  this->command(0x04);
2295 
2296  delay(100); // NOLINT
2297  this->wait_until_idle_();
2298  // COMMAND PANEL SETTING
2299  this->command(0x00);
2300  this->data(0x3F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
2301 
2302  // COMMAND RESOLUTION SETTING
2303  this->command(0x61);
2304  this->data(0x03); // source 800
2305  this->data(0x20);
2306  this->data(0x01); // gate 480
2307  this->data(0xE0);
2308  // COMMAND ...?
2309  this->command(0x15);
2310  this->data(0x00);
2311  // COMMAND VCOM AND DATA INTERVAL SETTING
2312  this->command(0x50);
2313  this->data(0x10);
2314  this->data(0x00);
2315  // COMMAND TCON SETTING
2316  this->command(0x60);
2317  this->data(0x22);
2318  // Resolution setting
2319  this->command(0x65);
2320  this->data(0x00);
2321  this->data(0x00); // 800*480
2322  this->data(0x00);
2323  this->data(0x00);
2324 
2325  uint8_t lut_vcom_7_i_n5_v2[] = {
2326  0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0xF, 0x1, 0xF, 0x1, 0x2, 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2327  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2328  };
2329 
2330  uint8_t lut_ww_7_i_n5_v2[] = {
2331  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2332  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2333  };
2334 
2335  uint8_t lut_bw_7_i_n5_v2[] = {
2336  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2337  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2338  };
2339 
2340  uint8_t lut_wb_7_i_n5_v2[] = {
2341  0x80, 0xF, 0xF, 0x0, 0x0, 0x3, 0x84, 0xF, 0x1, 0xF, 0x1, 0x4, 0x40, 0xF, 0xF, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
2342  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2343  };
2344 
2345  uint8_t lut_bb_7_i_n5_v2[] = {
2346  0x80, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x40, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2347  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2348  };
2349 
2350  uint8_t count;
2351  this->command(0x20); // VCOM
2352  for (count = 0; count < 42; count++)
2353  this->data(lut_vcom_7_i_n5_v2[count]);
2354 
2355  this->command(0x21); // LUTBW
2356  for (count = 0; count < 42; count++)
2357  this->data(lut_ww_7_i_n5_v2[count]);
2358 
2359  this->command(0x22); // LUTBW
2360  for (count = 0; count < 42; count++)
2361  this->data(lut_bw_7_i_n5_v2[count]);
2362 
2363  this->command(0x23); // LUTWB
2364  for (count = 0; count < 42; count++)
2365  this->data(lut_wb_7_i_n5_v2[count]);
2366 
2367  this->command(0x24); // LUTBB
2368  for (count = 0; count < 42; count++)
2369  this->data(lut_bb_7_i_n5_v2[count]);
2370 };
2372  this->init_display_();
2373  uint32_t buf_len = this->get_buffer_length_();
2374 
2375  this->command(0x10);
2376  for (uint32_t i = 0; i < buf_len; i++) {
2377  this->data(0xFF);
2378  }
2379 
2380  this->command(0x13); // Start Transmission
2381  delay(2);
2382  for (uint32_t i = 0; i < buf_len; i++) {
2383  this->data(~this->buffer_[i]);
2384  }
2385 
2386  this->command(0x12); // Display Refresh
2387  delay(100); // NOLINT
2388  this->wait_until_idle_();
2389  this->deep_sleep();
2390 }
2394  LOG_DISPLAY("", "Waveshare E-Paper", this);
2395  ESP_LOGCONFIG(TAG, " Model: 7.5in-bv3");
2396  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2397  LOG_PIN(" DC Pin: ", this->dc_pin_);
2398  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2399  LOG_UPDATE_INTERVAL(this);
2400 }
2401 
2404  if (this->busy_pin_ == nullptr) {
2405  return true;
2406  }
2407 
2408  const uint32_t start = millis();
2409  while (this->busy_pin_->digital_read()) {
2410  this->command(0x71);
2411  if (millis() - start > this->idle_timeout_()) {
2412  ESP_LOGI(TAG, "Timeout while displaying image!");
2413  return false;
2414  }
2415  App.feed_wdt();
2416  delay(10);
2417  }
2418  delay(200); // NOLINT
2419  return true;
2420 };
2422  this->reset_();
2423 
2424  // COMMAND POWER SETTING
2425  this->command(0x01);
2426 
2427  // 1-0=11: internal power
2428  this->data(0x07);
2429  this->data(0x17); // VGH&VGL
2430  this->data(0x3F); // VSH
2431  this->data(0x26); // VSL
2432  this->data(0x11); // VSHR
2433 
2434  // VCOM DC Setting
2435  this->command(0x82);
2436  this->data(0x24); // VCOM
2437 
2438  // Booster Setting
2439  this->command(0x06);
2440  this->data(0x27);
2441  this->data(0x27);
2442  this->data(0x2F);
2443  this->data(0x17);
2444 
2445  // POWER ON
2446  this->command(0x04);
2447 
2448  delay(100); // NOLINT
2449  this->wait_until_idle_();
2450  // COMMAND PANEL SETTING
2451  this->command(0x00);
2452  this->data(0x0F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
2453 
2454  // COMMAND RESOLUTION SETTING
2455  this->command(0x61);
2456  this->data(0x03); // source 800
2457  this->data(0x20);
2458  this->data(0x01); // gate 480
2459  this->data(0xE0);
2460  // COMMAND ...?
2461  this->command(0x15);
2462  this->data(0x00);
2463  // COMMAND VCOM AND DATA INTERVAL SETTING
2464  this->command(0x50);
2465  this->data(0x20);
2466  this->data(0x00);
2467  // COMMAND TCON SETTING
2468  this->command(0x60);
2469  this->data(0x22);
2470  // Resolution setting
2471  this->command(0x65);
2472  this->data(0x00);
2473  this->data(0x00); // 800*480
2474  this->data(0x00);
2475  this->data(0x00);
2476 };
2478  this->init_display_();
2479  const uint32_t buf_len = this->get_buffer_length_() / 2u;
2480 
2481  this->command(0x10); // Send BW data Transmission
2482  delay(2);
2483  for (uint32_t i = 0; i < buf_len; i++) {
2484  this->data(this->buffer_[i]);
2485  }
2486 
2487  this->command(0x13); // Send red data Transmission
2488  delay(2);
2489  for (uint32_t i = 0; i < buf_len; i++) {
2490  this->data(this->buffer_[i + buf_len]);
2491  }
2492 
2493  this->command(0x12); // Display Refresh
2494  delay(100); // NOLINT
2495  this->wait_until_idle_();
2496  this->deep_sleep();
2497 }
2501  LOG_DISPLAY("", "Waveshare E-Paper", this);
2502  ESP_LOGCONFIG(TAG, " Model: 7.5in-bv3 BWR-Mode");
2503  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2504  LOG_PIN(" DC Pin: ", this->dc_pin_);
2505  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2506  LOG_UPDATE_INTERVAL(this);
2507 }
2508 
2510  // COMMAND POWER SETTING
2511  this->command(0x01);
2512  this->data(0x37);
2513  this->data(0x00);
2514  // COMMAND PANEL SETTING
2515  this->command(0x00);
2516  this->data(0xCF);
2517  this->data(0x0B);
2518  // COMMAND BOOSTER SOFT START
2519  this->command(0x06);
2520  this->data(0xC7);
2521  this->data(0xCC);
2522  this->data(0x28);
2523  // COMMAND POWER ON
2524  this->command(0x04);
2525  this->wait_until_idle_();
2526  delay(10);
2527  // COMMAND PLL CONTROL
2528  this->command(0x30);
2529  this->data(0x3C);
2530  // COMMAND TEMPERATURE SENSOR CALIBRATION
2531  this->command(0x41);
2532  this->data(0x00);
2533  // COMMAND VCOM AND DATA INTERVAL SETTING
2534  this->command(0x50);
2535  this->data(0x77);
2536  // COMMAND TCON SETTING
2537  this->command(0x60);
2538  this->data(0x22);
2539  // COMMAND RESOLUTION SETTING
2540  this->command(0x61);
2541  this->data(0x02);
2542  this->data(0x80);
2543  this->data(0x01);
2544  this->data(0x80);
2545  // COMMAND VCM DC SETTING REGISTER
2546  this->command(0x82);
2547  this->data(0x1E);
2548  this->command(0xE5);
2549  this->data(0x03);
2550 }
2552  // COMMAND DATA START TRANSMISSION 1
2553  this->command(0x10);
2554  this->start_data_();
2555  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
2556  uint8_t temp1 = this->buffer_[i];
2557  for (uint8_t j = 0; j < 8; j++) {
2558  uint8_t temp2;
2559  if (temp1 & 0x80) {
2560  temp2 = 0x03;
2561  } else {
2562  temp2 = 0x00;
2563  }
2564  temp2 <<= 4;
2565  temp1 <<= 1;
2566  j++;
2567  if (temp1 & 0x80) {
2568  temp2 |= 0x03;
2569  } else {
2570  temp2 |= 0x00;
2571  }
2572  temp1 <<= 1;
2573  this->write_byte(temp2);
2574  }
2575  App.feed_wdt();
2576  }
2577  this->end_data_();
2578  // COMMAND DISPLAY REFRESH
2579  this->command(0x12);
2580 }
2584  LOG_DISPLAY("", "Waveshare E-Paper", this);
2585  ESP_LOGCONFIG(TAG, " Model: 7.5in");
2586  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2587  LOG_PIN(" DC Pin: ", this->dc_pin_);
2588  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2589  LOG_UPDATE_INTERVAL(this);
2590 }
2592  if (this->busy_pin_ == nullptr) {
2593  return true;
2594  }
2595 
2596  const uint32_t start = millis();
2597  while (this->busy_pin_->digital_read()) {
2598  this->command(0x71);
2599  if (millis() - start > this->idle_timeout_()) {
2600  ESP_LOGE(TAG, "Timeout while displaying image!");
2601  return false;
2602  }
2603  App.feed_wdt();
2604  delay(10);
2605  }
2606  return true;
2607 }
2609  // COMMAND POWER SETTING
2610  this->command(0x01);
2611  this->data(0x07);
2612  this->data(0x07);
2613  this->data(0x3f);
2614  this->data(0x3f);
2615 
2616  // We don't want the display to be powered at this point
2617 
2618  delay(100); // NOLINT
2619  this->wait_until_idle_();
2620 
2621  // COMMAND VCOM AND DATA INTERVAL SETTING
2622  this->command(0x50);
2623  this->data(0x10);
2624  this->data(0x07);
2625 
2626  // COMMAND TCON SETTING
2627  this->command(0x60);
2628  this->data(0x22);
2629 
2630  // COMMAND PANEL SETTING
2631  this->command(0x00);
2632  this->data(0x1F);
2633 
2634  // COMMAND RESOLUTION SETTING
2635  this->command(0x61);
2636  this->data(0x03);
2637  this->data(0x20);
2638  this->data(0x01);
2639  this->data(0xE0);
2640 
2641  // COMMAND DUAL SPI MM_EN, DUSPI_EN
2642  this->command(0x15);
2643  this->data(0x00);
2644 
2645  // COMMAND POWER DRIVER HAT DOWN
2646  // This command will turn off booster, controller, source driver, gate driver, VCOM, and
2647  // temperature sensor, but register data will be kept until VDD turned OFF or Deep Sleep Mode.
2648  // Source/Gate/Border/VCOM will be released to floating.
2649  this->command(0x02);
2650 }
2652  uint32_t buf_len = this->get_buffer_length_();
2653 
2654  // COMMAND POWER ON
2655  ESP_LOGI(TAG, "Power on the display and hat");
2656 
2657  // This command will turn on booster, controller, regulators, and temperature sensor will be
2658  // activated for one-time sensing before enabling booster. When all voltages are ready, the
2659  // BUSY_N signal will return to high.
2660  this->command(0x04);
2661  delay(200); // NOLINT
2662  this->wait_until_idle_();
2663 
2664  // COMMAND DATA START TRANSMISSION NEW DATA
2665  this->command(0x13);
2666  delay(2);
2667  for (uint32_t i = 0; i < buf_len; i++) {
2668  this->data(~(this->buffer_[i]));
2669  }
2670 
2671  delay(100); // NOLINT
2672  this->wait_until_idle_();
2673 
2674  // COMMAND DISPLAY REFRESH
2675  this->command(0x12);
2676  delay(100); // NOLINT
2677  this->wait_until_idle_();
2678 
2679  ESP_LOGV(TAG, "Before command(0x02) (>> power off)");
2680  this->command(0x02);
2681  this->wait_until_idle_();
2682  ESP_LOGV(TAG, "After command(0x02) (>> power off)");
2683 }
2684 
2687 uint32_t WaveshareEPaper7P5InV2::idle_timeout_() { return 10000; }
2689  LOG_DISPLAY("", "Waveshare E-Paper", this);
2690  ESP_LOGCONFIG(TAG, " Model: 7.5inV2rev2");
2691  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2692  LOG_PIN(" DC Pin: ", this->dc_pin_);
2693  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2694  LOG_UPDATE_INTERVAL(this);
2695 }
2696 
2697 /* 7.50inV2alt */
2699  if (this->busy_pin_ == nullptr) {
2700  return true;
2701  }
2702 
2703  const uint32_t start = millis();
2704  while (this->busy_pin_->digital_read()) {
2705  this->command(0x71);
2706  if (millis() - start > this->idle_timeout_()) {
2707  ESP_LOGI(TAG, "Timeout while displaying image!");
2708  return false;
2709  }
2710  delay(10);
2711  }
2712  return true;
2713 }
2714 
2716  this->reset_();
2717 
2718  // COMMAND POWER SETTING
2719  this->command(0x01);
2720 
2721  // 1-0=11: internal power
2722  this->data(0x07);
2723  this->data(0x17); // VGH&VGL
2724  this->data(0x3F); // VSH
2725  this->data(0x26); // VSL
2726  this->data(0x11); // VSHR
2727 
2728  // VCOM DC Setting
2729  this->command(0x82);
2730  this->data(0x24); // VCOM
2731 
2732  // Booster Setting
2733  this->command(0x06);
2734  this->data(0x27);
2735  this->data(0x27);
2736  this->data(0x2F);
2737  this->data(0x17);
2738 
2739  // POWER ON
2740  this->command(0x04);
2741 
2742  delay(100); // NOLINT
2743  this->wait_until_idle_();
2744  // COMMAND PANEL SETTING
2745  this->command(0x00);
2746  this->data(0x3F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
2747 
2748  // COMMAND RESOLUTION SETTING
2749  this->command(0x61);
2750  this->data(0x03); // source 800
2751  this->data(0x20);
2752  this->data(0x01); // gate 480
2753  this->data(0xE0);
2754  // COMMAND ...?
2755  this->command(0x15);
2756  this->data(0x00);
2757  // COMMAND VCOM AND DATA INTERVAL SETTING
2758  this->command(0x50);
2759  this->data(0x10);
2760  this->data(0x00);
2761  // COMMAND TCON SETTING
2762  this->command(0x60);
2763  this->data(0x22);
2764  // Resolution setting
2765  this->command(0x65);
2766  this->data(0x00);
2767  this->data(0x00); // 800*480
2768  this->data(0x00);
2769  this->data(0x00);
2770 
2771  this->wait_until_idle_();
2772 
2773  uint8_t lut_vcom_7_i_n5_v2[] = {
2774  0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0xF, 0x1, 0xF, 0x1, 0x2, 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2775  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2776  };
2777 
2778  uint8_t lut_ww_7_i_n5_v2[] = {
2779  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2780  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2781  };
2782 
2783  uint8_t lut_bw_7_i_n5_v2[] = {
2784  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2785  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2786  };
2787 
2788  uint8_t lut_wb_7_i_n5_v2[] = {
2789  0x80, 0xF, 0xF, 0x0, 0x0, 0x3, 0x84, 0xF, 0x1, 0xF, 0x1, 0x4, 0x40, 0xF, 0xF, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
2790  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2791  };
2792 
2793  uint8_t lut_bb_7_i_n5_v2[] = {
2794  0x80, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x40, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2795  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2796  };
2797 
2798  uint8_t count;
2799  this->command(0x20); // VCOM
2800  for (count = 0; count < 42; count++)
2801  this->data(lut_vcom_7_i_n5_v2[count]);
2802 
2803  this->command(0x21); // LUTBW
2804  for (count = 0; count < 42; count++)
2805  this->data(lut_ww_7_i_n5_v2[count]);
2806 
2807  this->command(0x22); // LUTBW
2808  for (count = 0; count < 42; count++)
2809  this->data(lut_bw_7_i_n5_v2[count]);
2810 
2811  this->command(0x23); // LUTWB
2812  for (count = 0; count < 42; count++)
2813  this->data(lut_wb_7_i_n5_v2[count]);
2814 
2815  this->command(0x24); // LUTBB
2816  for (count = 0; count < 42; count++)
2817  this->data(lut_bb_7_i_n5_v2[count]);
2818 }
2819 
2821  LOG_DISPLAY("", "Waveshare E-Paper", this);
2822  ESP_LOGCONFIG(TAG, " Model: 7.5inV2");
2823  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2824  LOG_PIN(" DC Pin: ", this->dc_pin_);
2825  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2826  LOG_UPDATE_INTERVAL(this);
2827 }
2828 
2829 /* 7.50in-bc */
2831  /* The command sequence is similar to the 7P5In display but differs in subtle ways
2832  to allow for faster updates. */
2833  // COMMAND POWER SETTING
2834  this->command(0x01);
2835  this->data(0x37);
2836  this->data(0x00);
2837 
2838  // COMMAND PANEL SETTING
2839  this->command(0x00);
2840  this->data(0xCF);
2841  this->data(0x08);
2842 
2843  // COMMAND PLL CONTROL
2844  this->command(0x30);
2845  this->data(0x3A);
2846 
2847  // COMMAND VCM_DC_SETTING: all temperature range
2848  this->command(0x82);
2849  this->data(0x28);
2850 
2851  // COMMAND BOOSTER SOFT START
2852  this->command(0x06);
2853  this->data(0xC7);
2854  this->data(0xCC);
2855  this->data(0x15);
2856 
2857  // COMMAND VCOM AND DATA INTERVAL SETTING
2858  this->command(0x50);
2859  this->data(0x77);
2860 
2861  // COMMAND TCON SETTING
2862  this->command(0x60);
2863  this->data(0x22);
2864 
2865  // COMMAND FLASH CONTROL
2866  this->command(0x65);
2867  this->data(0x00);
2868 
2869  // COMMAND RESOLUTION SETTING
2870  this->command(0x61);
2871  this->data(0x02); // 640 >> 8
2872  this->data(0x80);
2873  this->data(0x01); // 384 >> 8
2874  this->data(0x80);
2875 
2876  // COMMAND FLASH MODE
2877  this->command(0xE5);
2878  this->data(0x03);
2879 }
2880 
2882  // COMMAND DATA START TRANSMISSION 1
2883  this->command(0x10);
2884  this->start_data_();
2885 
2886  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
2887  // A line of eight source pixels (each a bit in this byte)
2888  uint8_t eight_pixels = this->buffer_[i];
2889 
2890  for (uint8_t j = 0; j < 8; j += 2) {
2891  /* For bichromatic displays, each byte represents two pixels. Each nibble encodes a pixel: 0=white, 3=black,
2892  4=color. Therefore, e.g. 0x44 = two adjacent color pixels, 0x33 is two adjacent black pixels, etc. If you want
2893  to draw using the color pixels, change '0x30' with '0x40' and '0x03' with '0x04' below. */
2894  uint8_t left_nibble = (eight_pixels & 0x80) ? 0x30 : 0x00;
2895  eight_pixels <<= 1;
2896  uint8_t right_nibble = (eight_pixels & 0x80) ? 0x03 : 0x00;
2897  eight_pixels <<= 1;
2898  this->write_byte(left_nibble | right_nibble);
2899  }
2900  App.feed_wdt();
2901  }
2902  this->end_data_();
2903 
2904  // Unlike the 7P5In display, we send the "power on" command here rather than during initialization
2905  // COMMAND POWER ON
2906  this->command(0x04);
2907 
2908  // COMMAND DISPLAY REFRESH
2909  this->command(0x12);
2910 }
2911 
2913 
2915 
2917  LOG_DISPLAY("", "Waveshare E-Paper", this);
2918  ESP_LOGCONFIG(TAG, " Model: 7.5in-bc");
2919  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2920  LOG_PIN(" DC Pin: ", this->dc_pin_);
2921  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2922  LOG_UPDATE_INTERVAL(this);
2923 }
2924 
2926  this->command(0x12); // SWRESET
2927 
2928  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
2929 
2930  this->command(0x46); // Auto Write RAM
2931  this->data(0xF7);
2932 
2933  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
2934 
2935  this->command(0x47); // Auto Write RAM
2936  this->data(0xF7);
2937 
2938  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
2939 
2940  this->command(0x0C); // Soft start setting
2941  this->data(0xAE);
2942  this->data(0xC7);
2943  this->data(0xC3);
2944  this->data(0xC0);
2945  this->data(0x40);
2946 
2947  this->command(0x01); // Set MUX as 527
2948  this->data(0xAF);
2949  this->data(0x02);
2950  this->data(0x01);
2951 
2952  this->command(0x11); // Data entry mode
2953  this->data(0x01);
2954 
2955  this->command(0x44);
2956  this->data(0x00); // RAM x address start at 0
2957  this->data(0x00);
2958  this->data(0x6F); // RAM x address end at 36Fh -> 879
2959  this->data(0x03);
2960 
2961  this->command(0x45);
2962  this->data(0xAF); // RAM y address start at 20Fh;
2963  this->data(0x02);
2964  this->data(0x00); // RAM y address end at 00h;
2965  this->data(0x00);
2966 
2967  this->command(0x3C); // VBD
2968  this->data(0x01); // LUT1, for white
2969 
2970  this->command(0x18);
2971  this->data(0X80);
2972 
2973  this->command(0x22);
2974  this->data(0XB1); // Load Temperature and waveform setting.
2975 
2976  this->command(0x20);
2977 
2978  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
2979 
2980  this->command(0x4E);
2981  this->data(0x00);
2982  this->data(0x00);
2983 
2984  this->command(0x4F);
2985  this->data(0xAF);
2986  this->data(0x02);
2987 }
2988 
2990  this->command(0x4F);
2991  this->data(0xAf);
2992  this->data(0x02);
2993 
2994  // BLACK
2995  this->command(0x24);
2996  this->start_data_();
2997  this->write_array(this->buffer_, this->get_buffer_length_());
2998  this->end_data_();
2999 
3000  // RED
3001  this->command(0x26);
3002  this->start_data_();
3003  for (size_t i = 0; i < this->get_buffer_length_(); i++)
3004  this->write_byte(0x00);
3005  this->end_data_();
3006 
3007  this->command(0x22);
3008  this->data(0xC7);
3009  this->command(0x20);
3010  delay(100); // NOLINT
3011 }
3012 
3014 
3016 
3018  LOG_DISPLAY("", "Waveshare E-Paper", this);
3019  ESP_LOGCONFIG(TAG, " Model: 7.5in-HD-b");
3020  LOG_PIN(" Reset Pin: ", this->reset_pin_);
3021  LOG_PIN(" DC Pin: ", this->dc_pin_);
3022  LOG_PIN(" Busy Pin: ", this->busy_pin_);
3023  LOG_UPDATE_INTERVAL(this);
3024 }
3025 
3026 static const uint8_t LUT_SIZE_TTGO_DKE_PART = 153;
3027 
3028 static const uint8_t PART_UPDATE_LUT_TTGO_DKE[LUT_SIZE_TTGO_DKE_PART] = {
3029  0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3030  0x0, 0x0, 0x0, 0x0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0,
3031  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3032  0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3033  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3034  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3035  0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3036  0x0, 0x0, 0x0, 0x0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
3037  // 0x22, 0x17, 0x41, 0x0, 0x32, 0x32
3038 };
3039 
3042  bool partial = this->at_update_ != 0;
3043  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
3044 
3045  if (partial) {
3046  ESP_LOGI(TAG, "Performing partial e-paper update.");
3047  } else {
3048  ESP_LOGI(TAG, "Performing full e-paper update.");
3049  }
3050 
3051  // start and set up data format
3052  this->command(0x12);
3053  this->wait_until_idle_();
3054 
3055  this->command(0x11);
3056  this->data(0x03);
3057  this->command(0x44);
3058  this->data(1);
3059  this->data(this->get_width_internal() / 8);
3060  this->command(0x45);
3061  this->data(0);
3062  this->data(0);
3063  this->data(this->get_height_internal());
3064  this->data(0);
3065  this->command(0x4e);
3066  this->data(1);
3067  this->command(0x4f);
3068  this->data(0);
3069  this->data(0);
3070 
3071  if (!partial) {
3072  // send data
3073  this->command(0x24);
3074  this->start_data_();
3075  this->write_array(this->buffer_, this->get_buffer_length_());
3076  this->end_data_();
3077 
3078  // commit
3079  this->command(0x20);
3080  this->wait_until_idle_();
3081  } else {
3082  // set up partial update
3083  this->command(0x32);
3084  this->start_data_();
3085  this->write_array(PART_UPDATE_LUT_TTGO_DKE, sizeof(PART_UPDATE_LUT_TTGO_DKE));
3086  this->end_data_();
3087  this->command(0x3F);
3088  this->data(0x22);
3089 
3090  this->command(0x03);
3091  this->data(0x17);
3092  this->command(0x04);
3093  this->data(0x41);
3094  this->data(0x00);
3095  this->data(0x32);
3096  this->command(0x2C);
3097  this->data(0x32);
3098 
3099  this->command(0x37);
3100  this->data(0x00);
3101  this->data(0x00);
3102  this->data(0x00);
3103  this->data(0x00);
3104  this->data(0x00);
3105  this->data(0x40);
3106  this->data(0x00);
3107  this->data(0x00);
3108  this->data(0x00);
3109  this->data(0x00);
3110 
3111  this->command(0x3C);
3112  this->data(0x80);
3113  this->command(0x22);
3114  this->data(0xC0);
3115  this->command(0x20);
3116  this->wait_until_idle_();
3117 
3118  // send data
3119  this->command(0x24);
3120  this->start_data_();
3121  this->write_array(this->buffer_, this->get_buffer_length_());
3122  this->end_data_();
3123 
3124  // commit as partial
3125  this->command(0x22);
3126  this->data(0xCF);
3127  this->command(0x20);
3128  this->wait_until_idle_();
3129 
3130  // data must be sent again on partial update
3131  this->command(0x24);
3132  this->start_data_();
3133  this->write_array(this->buffer_, this->get_buffer_length_());
3134  this->end_data_();
3135  }
3136 
3137  ESP_LOGI(TAG, "Completed e-paper update.");
3138 }
3139 
3142 uint32_t WaveshareEPaper2P13InDKE::idle_timeout_() { return 5000; }
3144  LOG_DISPLAY("", "Waveshare E-Paper", this);
3145  ESP_LOGCONFIG(TAG, " Model: 2.13inDKE");
3146  LOG_PIN(" CS Pin: ", this->cs_);
3147  LOG_PIN(" Reset Pin: ", this->reset_pin_);
3148  LOG_PIN(" DC Pin: ", this->dc_pin_);
3149  LOG_PIN(" Busy Pin: ", this->busy_pin_);
3150  LOG_UPDATE_INTERVAL(this);
3151 }
3152 
3153 void WaveshareEPaper2P13InDKE::set_full_update_every(uint32_t full_update_every) {
3154  this->full_update_every_ = full_update_every;
3155 }
3156 
3157 // ========================================================
3158 // 13.3in (K version)
3159 // Datasheet/Specification/Reference:
3160 // - https://files.waveshare.com/wiki/13.3inch-e-Paper-HAT-(K)/13.3-inch-e-Paper-(K)-user-manual.pdf
3161 // - https://github.com/waveshareteam/e-Paper/tree/master/Arduino/epd13in3k
3162 // ========================================================
3163 
3164 // using default wait_until_idle_() function
3166  this->wait_until_idle_();
3167  this->command(0x12); // SWRESET
3168  this->wait_until_idle_();
3169 
3170  this->command(0x0c); // set soft start
3171  this->data(0xae);
3172  this->data(0xc7);
3173  this->data(0xc3);
3174  this->data(0xc0);
3175  this->data(0x80);
3176 
3177  this->command(0x01); // driver output control
3178  this->data((get_height_internal() - 1) % 256); // Y
3179  this->data((get_height_internal() - 1) / 256); // Y
3180  this->data(0x00);
3181 
3182  this->command(0x11); // data entry mode
3183  this->data(0x03);
3184 
3185  // SET WINDOWS
3186  // XRAM_START_AND_END_POSITION
3187  this->command(0x44);
3188  this->data(0 & 0xFF);
3189  this->data((0 >> 8) & 0x03);
3190  this->data((get_width_internal() - 1) & 0xFF);
3191  this->data(((get_width_internal() - 1) >> 8) & 0x03);
3192  // YRAM_START_AND_END_POSITION
3193  this->command(0x45);
3194  this->data(0 & 0xFF);
3195  this->data((0 >> 8) & 0x03);
3196  this->data((get_height_internal() - 1) & 0xFF);
3197  this->data(((get_height_internal() - 1) >> 8) & 0x03);
3198 
3199  this->command(0x3C); // Border setting
3200  this->data(0x01);
3201 
3202  this->command(0x18); // use the internal temperature sensor
3203  this->data(0x80);
3204 
3205  // SET CURSOR
3206  // XRAM_ADDRESS
3207  this->command(0x4E);
3208  this->data(0 & 0xFF);
3209  this->data((0 >> 8) & 0x03);
3210  // YRAM_ADDRESS
3211  this->command(0x4F);
3212  this->data(0 & 0xFF);
3213  this->data((0 >> 8) & 0x03);
3214 }
3216  // do single full update
3217  this->command(0x24);
3218  this->start_data_();
3219  this->write_array(this->buffer_, this->get_buffer_length_());
3220  this->end_data_();
3221 
3222  // COMMAND DISPLAY REFRESH
3223  this->command(0x22);
3224  this->data(0xF7);
3225  this->command(0x20);
3226 }
3227 
3230 uint32_t WaveshareEPaper13P3InK::idle_timeout_() { return 10000; }
3232  LOG_DISPLAY("", "Waveshare E-Paper", this);
3233  ESP_LOGCONFIG(TAG, " Model: 13.3inK");
3234  LOG_PIN(" Reset Pin: ", this->reset_pin_);
3235  LOG_PIN(" DC Pin: ", this->dc_pin_);
3236  LOG_PIN(" Busy Pin: ", this->busy_pin_);
3237  LOG_UPDATE_INTERVAL(this);
3238 }
3239 
3240 } // namespace waveshare_epaper
3241 } // 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:690
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
GPIOPin * cs_
Definition: spi.h:378
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
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.
virtual bool digital_read()=0
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:675
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