ESPHome  2024.3.1
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_internal()) >> 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(((get_width_internal() - 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 // 2.7inch_e-paper_b
813 // ========================================================
814 // Datasheet:
815 // - https://www.waveshare.com/w/upload/d/d8/2.7inch-e-paper-b-specification.pdf
816 // - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_2in7b.c
817 
818 static const uint8_t LUT_VCOM_DC_2_7B[44] = {0x00, 0x00, 0x00, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x0A,
819  0x00, 0x00, 0x08, 0x00, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x00, 0x0A,
820  0x0A, 0x00, 0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x00, 0x05, 0x00,
821  0x03, 0x0E, 0x00, 0x00, 0x0A, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01};
822 
823 static const uint8_t LUT_WHITE_TO_WHITE_2_7B[42] = {0x90, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x40, 0x0A, 0x0A, 0x00, 0x00,
824  0x08, 0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x80, 0x0A, 0x0A, 0x00,
825  0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x00, 0x05, 0x00, 0x03, 0x0E,
826  0x00, 0x00, 0x0A, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01};
827 
828 static const uint8_t LUT_BLACK_TO_WHITE_2_7B[42] = {0xA0, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x0A, 0x00, 0x00,
829  0x08, 0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x90, 0x0A, 0x0A, 0x00,
830  0x00, 0x08, 0xB0, 0x04, 0x10, 0x00, 0x00, 0x05, 0xB0, 0x03, 0x0E,
831  0x00, 0x00, 0x0A, 0xC0, 0x23, 0x00, 0x00, 0x00, 0x01};
832 
833 static const uint8_t LUT_WHITE_TO_BLACK_2_7B[] = {0x90, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x20, 0x0A, 0x0A, 0x00, 0x00,
834  0x08, 0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x10, 0x0A, 0x0A, 0x00,
835  0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x00, 0x05, 0x00, 0x03, 0x0E,
836  0x00, 0x00, 0x0A, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01};
837 
838 static const uint8_t LUT_BLACK_TO_BLACK_2_7B[42] = {0x90, 0x1A, 0x1A, 0x00, 0x00, 0x01, 0x40, 0x0A, 0x0A, 0x00, 0x00,
839  0x08, 0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, 0x80, 0x0A, 0x0A, 0x00,
840  0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x00, 0x05, 0x00, 0x03, 0x0E,
841  0x00, 0x00, 0x0A, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01};
842 
844  this->reset_();
845 
846  // command power on
847  this->command(0x04);
848  this->wait_until_idle_();
849  delay(10);
850 
851  // Command panel setting
852  this->command(0x00);
853  this->data(0xAF); // KW-BF KWR-AF BWROTP 0f
854  // command pll control
855  this->command(0x30);
856  this->data(0x3A); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
857 
858  // command power setting
859  this->command(0x01);
860  this->data(0x03); // VDS_EN, VDG_EN
861  this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
862  this->data(0x2B); // VDH
863  this->data(0x2B); // VDL
864  this->data(0x09); // VDHR
865 
866  // command booster soft start
867  this->command(0x06);
868  this->data(0x07);
869  this->data(0x07);
870  this->data(0x17);
871 
872  // Power optimization - ???
873  this->command(0xF8);
874  this->data(0x60);
875  this->data(0xA5);
876  this->command(0xF8);
877  this->data(0x89);
878  this->data(0xA5);
879  this->command(0xF8);
880  this->data(0x90);
881  this->data(0x00);
882  this->command(0xF8);
883  this->data(0x93);
884  this->data(0x2A);
885  this->command(0xF8);
886  this->data(0x73);
887  this->data(0x41);
888 
889  // COMMAND VCM DC SETTING
890  this->command(0x82);
891  this->data(0x12);
892 
893  // VCOM_AND_DATA_INTERVAL_SETTING
894  this->command(0x50);
895  this->data(0x87); // define by OTP
896 
897  delay(2);
898  // COMMAND LUT FOR VCOM
899  this->command(0x20);
900  for (uint8_t i : LUT_VCOM_DC_2_7B)
901  this->data(i);
902  // COMMAND LUT WHITE TO WHITE
903  this->command(0x21);
904  for (uint8_t i : LUT_WHITE_TO_WHITE_2_7B)
905  this->data(i);
906  // COMMAND LUT BLACK TO WHITE
907  this->command(0x22);
908  for (uint8_t i : LUT_BLACK_TO_WHITE_2_7B)
909  this->data(i);
910  // COMMAND LUT WHITE TO BLACK
911  this->command(0x23);
912  for (uint8_t i : LUT_WHITE_TO_BLACK_2_7B) {
913  this->data(i);
914  }
915  // COMMAND LUT BLACK TO BLACK
916  this->command(0x24);
917 
918  for (uint8_t i : LUT_BLACK_TO_BLACK_2_7B) {
919  this->data(i);
920  }
921 
922  delay(2);
923 }
924 
926  uint32_t buf_len_half = this->get_buffer_length_() >> 1;
927  this->initialize();
928 
929  // TCON_RESOLUTION
930  this->command(0x61);
931  this->data(this->get_width_internal() >> 8);
932  this->data(this->get_width_internal() & 0xff); // 176
933  this->data(this->get_height_internal() >> 8);
934  this->data(this->get_height_internal() & 0xff); // 264
935 
936  // COMMAND DATA START TRANSMISSION 1 (BLACK)
937  this->command(0x10);
938  delay(2);
939  for (uint32_t i = 0; i < buf_len_half; i++) {
940  this->data(this->buffer_[i]);
941  }
942  this->command(0x11);
943  delay(2);
944 
945  // COMMAND DATA START TRANSMISSION 2 (RED)
946  this->command(0x13);
947  delay(2);
948  for (uint32_t i = buf_len_half; i < buf_len_half * 2u; i++) {
949  this->data(this->buffer_[i]);
950  }
951  this->command(0x11);
952 
953  delay(2);
954 
955  // COMMAND DISPLAY REFRESH
956  this->command(0x12);
957  this->wait_until_idle_();
958 
959  this->deep_sleep();
960 }
964  LOG_DISPLAY("", "Waveshare E-Paper", this);
965  ESP_LOGCONFIG(TAG, " Model: 2.7in B");
966  LOG_PIN(" Reset Pin: ", this->reset_pin_);
967  LOG_PIN(" DC Pin: ", this->dc_pin_);
968  LOG_PIN(" Busy Pin: ", this->busy_pin_);
969  LOG_UPDATE_INTERVAL(this);
970 }
971 
972 // ========================================================
973 // 2.7inch_e-paper_b_v2
974 // ========================================================
975 // Datasheet:
976 // - https://www.waveshare.com/w/upload/7/7b/2.7inch-e-paper-b-v2-specification.pdf
977 // - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_2in7b_V2.c
978 
980  this->reset_();
981 
982  this->wait_until_idle_();
983  this->command(0x12);
984  this->wait_until_idle_();
985 
986  this->command(0x00);
987  this->data(0x27);
988  this->data(0x01);
989  this->data(0x00);
990 
991  this->command(0x11);
992  this->data(0x03);
993 
994  // self.SetWindows(0, 0, self.width-1, self.height-1)
995  // SetWindows(self, Xstart, Ystart, Xend, Yend):
996 
997  uint32_t xend = this->get_width_internal() - 1;
998  uint32_t yend = this->get_height_internal() - 1;
999  this->command(0x44);
1000  this->data(0x00);
1001  this->data((xend >> 3) & 0xff);
1002 
1003  this->command(0x45);
1004  this->data(0x00);
1005  this->data(0x00);
1006  this->data(yend & 0xff);
1007  this->data((yend >> 8) & 0xff);
1008 
1009  // SetCursor(self, Xstart, Ystart):
1010  this->command(0x4E);
1011  this->data(0x00);
1012  this->command(0x4F);
1013  this->data(0x00);
1014  this->data(0x00);
1015 }
1016 
1018  uint32_t buf_len = this->get_buffer_length_();
1019  // COMMAND DATA START TRANSMISSION 1 (BLACK)
1020  this->command(0x24);
1021  delay(2);
1022  for (uint32_t i = 0; i < buf_len; i++) {
1023  this->data(this->buffer_[i]);
1024  }
1025  delay(2);
1026 
1027  // COMMAND DATA START TRANSMISSION 2 (RED)
1028  this->command(0x26);
1029  delay(2);
1030  for (uint32_t i = 0; i < buf_len; i++) {
1031  this->data(this->buffer_[i]);
1032  }
1033 
1034  delay(2);
1035 
1036  this->command(0x20);
1037 
1038  this->wait_until_idle_();
1039 }
1043  LOG_DISPLAY("", "Waveshare E-Paper", this);
1044  ESP_LOGCONFIG(TAG, " Model: 2.7in B V2");
1045  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1046  LOG_PIN(" DC Pin: ", this->dc_pin_);
1047  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1048  LOG_UPDATE_INTERVAL(this);
1049 }
1050 
1051 // ========================================================
1052 // 2.90in Type B (LUT from OTP)
1053 // Datasheet:
1054 // - https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf
1055 // - https://github.com/soonuse/epd-library-arduino/blob/master/2.9inch_e-paper_b/epd2in9b/epd2in9b.cpp
1056 // ========================================================
1057 
1059  // from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37
1060  // EPD hardware init start
1061  this->reset_();
1062 
1063  // COMMAND BOOSTER SOFT START
1064  this->command(0x06);
1065  this->data(0x17);
1066  this->data(0x17);
1067  this->data(0x17);
1068 
1069  // COMMAND POWER ON
1070  this->command(0x04);
1071  this->wait_until_idle_();
1072 
1073  // COMMAND PANEL SETTING
1074  this->command(0x00);
1075  // 128x296 resolution: 10
1076  // LUT from OTP: 0
1077  // B/W mode (doesn't work): 1
1078  // scan-up: 1
1079  // shift-right: 1
1080  // booster ON: 1
1081  // no soft reset: 1
1082  this->data(0x9F);
1083 
1084  // COMMAND RESOLUTION SETTING
1085  // set to 128x296 by COMMAND PANEL SETTING
1086 
1087  // COMMAND VCOM AND DATA INTERVAL SETTING
1088  // use defaults for white border and ESPHome image polarity
1089 
1090  // EPD hardware init end
1091 }
1093  // COMMAND DATA START TRANSMISSION 1 (B/W data)
1094  this->command(0x10);
1095  delay(2);
1096  this->start_data_();
1097  this->write_array(this->buffer_, this->get_buffer_length_());
1098  this->end_data_();
1099  delay(2);
1100 
1101  // COMMAND DATA START TRANSMISSION 2 (RED data)
1102  this->command(0x13);
1103  delay(2);
1104  this->start_data_();
1105  for (size_t i = 0; i < this->get_buffer_length_(); i++)
1106  this->write_byte(0x00);
1107  this->end_data_();
1108  delay(2);
1109 
1110  // COMMAND DISPLAY REFRESH
1111  this->command(0x12);
1112  delay(2);
1113  this->wait_until_idle_();
1114 
1115  // COMMAND POWER OFF
1116  // NOTE: power off < deep sleep
1117  this->command(0x02);
1118 }
1122  LOG_DISPLAY("", "Waveshare E-Paper", this);
1123  ESP_LOGCONFIG(TAG, " Model: 2.9in (B)");
1124  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1125  LOG_PIN(" DC Pin: ", this->dc_pin_);
1126  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1127  LOG_UPDATE_INTERVAL(this);
1128 }
1129 
1130 // ========================================================
1131 // 2.90in Type B (LUT from OTP)
1132 // Datasheet:
1133 // - https://files.waveshare.com/upload/a/af/2.9inch-e-paper-b-v3-specification.pdf
1134 // ========================================================
1135 
1137  // from https://github.com/waveshareteam/e-Paper/blob/master/Arduino/epd2in9b_V3/epd2in9b_V3.cpp
1138  this->reset_();
1139 
1140  // COMMAND POWER ON
1141  this->command(0x04);
1142  this->wait_until_idle_();
1143 
1144  // COMMAND PANEL SETTING
1145  this->command(0x00);
1146  this->data(0x0F);
1147  this->data(0x89);
1148 
1149  // COMMAND RESOLUTION SETTING
1150  this->command(0x61);
1151  this->data(0x80);
1152  this->data(0x01);
1153  this->data(0x28);
1154 
1155  // COMMAND VCOM AND DATA INTERVAL SETTING
1156  this->command(0x50);
1157  this->data(0x77);
1158 }
1160  // COMMAND DATA START TRANSMISSION 1 (B/W data)
1161  this->command(0x10);
1162  delay(2);
1163  this->start_data_();
1164  this->write_array(this->buffer_, this->get_buffer_length_());
1165  this->end_data_();
1166  this->command(0x92);
1167  delay(2);
1168 
1169  // COMMAND DATA START TRANSMISSION 2 (RED data)
1170  this->command(0x13);
1171  delay(2);
1172  this->start_data_();
1173  for (size_t i = 0; i < this->get_buffer_length_(); i++)
1174  this->write_byte(0xFF);
1175  this->end_data_();
1176  this->command(0x92);
1177  delay(2);
1178 
1179  // COMMAND DISPLAY REFRESH
1180  this->command(0x12);
1181  delay(2);
1182  this->wait_until_idle_();
1183 
1184  // COMMAND POWER OFF
1185  // NOTE: power off < deep sleep
1186  this->command(0x02);
1187 }
1191  LOG_DISPLAY("", "Waveshare E-Paper", this);
1192  ESP_LOGCONFIG(TAG, " Model: 2.9in (B) V3");
1193  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1194  LOG_PIN(" DC Pin: ", this->dc_pin_);
1195  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1196  LOG_UPDATE_INTERVAL(this);
1197 }
1198 
1199 // ========================================================
1200 // 2.90in v2 rev2
1201 // based on SDK and examples in ZIP file from:
1202 // https://www.waveshare.com/pico-epaper-2.9.htm
1203 // ========================================================
1204 
1206  this->reset_();
1207  this->wait_until_idle_();
1208 
1209  this->command(0x12); // SWRESET
1210  this->wait_until_idle_();
1211 
1212  this->command(0x01);
1213  this->data(0x27);
1214  this->data(0x01);
1215  this->data(0x00);
1216 
1217  this->command(0x11);
1218  this->data(0x03);
1219 
1220  // SetWindows(0, 0, w, h)
1221  this->command(0x44);
1222  this->data(0x00);
1223  this->data(((this->get_width_controller() - 1) >> 3) & 0xFF);
1224 
1225  this->command(0x45);
1226  this->data(0x00);
1227  this->data(0x00);
1228  this->data((this->get_height_internal() - 1) & 0xFF);
1229  this->data(((this->get_height_internal() - 1) >> 8) & 0xFF);
1230 
1231  this->command(0x21);
1232  this->data(0x00);
1233  this->data(0x80);
1234 
1235  // SetCursor(0, 0)
1236  this->command(0x4E);
1237  this->data(0x00);
1238  this->command(0x4f);
1239  this->data(0x00);
1240  this->data(0x00);
1241 
1242  this->wait_until_idle_();
1243 }
1244 
1246 
1247 void WaveshareEPaper2P9InV2R2::reset_() {
1248  if (this->reset_pin_ != nullptr) {
1249  this->reset_pin_->digital_write(false);
1250  delay(reset_duration_); // NOLINT
1251  this->reset_pin_->digital_write(true);
1252  delay(reset_duration_); // NOLINT
1253  }
1254 }
1255 
1257  if (!this->wait_until_idle_()) {
1258  this->status_set_warning();
1259  ESP_LOGE(TAG, "fail idle 1");
1260  return;
1261  }
1262 
1263  if (this->full_update_every_ == 1) {
1264  // do single full update
1265  this->command(0x24);
1266  this->start_data_();
1267  this->write_array(this->buffer_, this->get_buffer_length_());
1268  this->end_data_();
1269 
1270  // TurnOnDisplay
1271  this->command(0x22);
1272  this->data(0xF7);
1273  this->command(0x20);
1274  return;
1275  }
1276 
1277  // if (this->full_update_every_ == 1 ||
1278  if (this->at_update_ == 0) {
1279  // do base update
1280  this->command(0x24);
1281  this->start_data_();
1282  this->write_array(this->buffer_, this->get_buffer_length_());
1283  this->end_data_();
1284 
1285  this->command(0x26);
1286  this->start_data_();
1287  this->write_array(this->buffer_, this->get_buffer_length_());
1288  this->end_data_();
1289 
1290  // TurnOnDisplay
1291  this->command(0x22);
1292  this->data(0xF7);
1293  this->command(0x20);
1294  } else {
1295  // do partial update
1296  this->reset_();
1297 
1298  this->write_lut_(PARTIAL_UPD_2IN9_LUT, PARTIAL_UPD_2IN9_LUT_SIZE);
1299 
1300  this->command(0x37);
1301  this->data(0x00);
1302  this->data(0x00);
1303  this->data(0x00);
1304  this->data(0x00);
1305  this->data(0x00);
1306  this->data(0x40);
1307  this->data(0x00);
1308  this->data(0x00);
1309  this->data(0x00);
1310  this->data(0x00);
1311 
1312  this->command(0x3C);
1313  this->data(0x80);
1314 
1315  this->command(0x22);
1316  this->data(0xC0);
1317  this->command(0x20);
1318 
1319  if (!this->wait_until_idle_()) {
1320  ESP_LOGE(TAG, "fail idle 2");
1321  }
1322 
1323  // SetWindows(0, 0, w, h)
1324  this->command(0x44);
1325  this->data(0x00);
1326  this->data(((this->get_width_controller() - 1) >> 3) & 0xFF);
1327 
1328  this->command(0x45);
1329  this->data(0x00);
1330  this->data(0x00);
1331  this->data((this->get_height_internal() - 1) & 0xFF);
1332  this->data(((this->get_height_internal() - 1) >> 8) & 0xFF);
1333 
1334  // SetCursor(0, 0)
1335  this->command(0x4E);
1336  this->data(0x00);
1337  this->command(0x4f);
1338  this->data(0x00);
1339  this->data(0x00);
1340 
1341  // write b/w
1342  this->command(0x24);
1343  this->start_data_();
1344  this->write_array(this->buffer_, this->get_buffer_length_());
1345  this->end_data_();
1346 
1347  // TurnOnDisplayPartial
1348  this->command(0x22);
1349  this->data(0x0F);
1350  this->command(0x20);
1351  }
1352 
1353  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
1354 }
1355 
1356 void WaveshareEPaper2P9InV2R2::write_lut_(const uint8_t *lut, const uint8_t size) {
1357  // COMMAND WRITE LUT REGISTER
1358  this->command(0x32);
1359  for (uint8_t i = 0; i < size; i++)
1360  this->data(lut[i]);
1361 }
1362 
1364  LOG_DISPLAY("", "Waveshare E-Paper", this);
1365  ESP_LOGCONFIG(TAG, " Model: 2.9inV2R2");
1366  ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
1367  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1368  LOG_PIN(" DC Pin: ", this->dc_pin_);
1369  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1370  LOG_UPDATE_INTERVAL(this);
1371 }
1372 
1374  this->command(0x10);
1375  this->data(0x01);
1376 }
1377 
1381 void WaveshareEPaper2P9InV2R2::set_full_update_every(uint32_t full_update_every) {
1382  this->full_update_every_ = full_update_every;
1383 }
1384 
1385 // ========================================================
1386 // Good Display 2.9in black/white/grey
1387 // Datasheet:
1388 // - https://v4.cecdn.yun300.cn/100001_1909185148/SSD1680.pdf
1389 // - https://github.com/adafruit/Adafruit_EPD/blob/master/src/panels/ThinkInk_290_Grayscale4_T5.h
1390 // ========================================================
1391 
1393  // from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37
1394  // EPD hardware init start
1395  this->reset_();
1396 
1397  // COMMAND POWER SETTINGS
1398  this->command(0x00);
1399  this->data(0x03);
1400  this->data(0x00);
1401  this->data(0x2b);
1402  this->data(0x2b);
1403  this->data(0x03); /* for b/w */
1404 
1405  // COMMAND BOOSTER SOFT START
1406  this->command(0x06);
1407  this->data(0x17);
1408  this->data(0x17);
1409  this->data(0x17);
1410 
1411  // COMMAND POWER ON
1412  this->command(0x04);
1413  this->wait_until_idle_();
1414 
1415  // Not sure what this does but it's in the Adafruit EPD library
1416  this->command(0xFF);
1417  this->wait_until_idle_();
1418 
1419  // COMMAND PANEL SETTING
1420  this->command(0x00);
1421  // 128x296 resolution: 10
1422  // LUT from OTP: 0
1423  // B/W mode (doesn't work): 1
1424  // scan-up: 1
1425  // shift-right: 1
1426  // booster ON: 1
1427  // no soft reset: 1
1428  this->data(0b10011111);
1429 
1430  // COMMAND RESOLUTION SETTING
1431  // set to 128x296 by COMMAND PANEL SETTING
1432 
1433  // COMMAND VCOM AND DATA INTERVAL SETTING
1434  // use defaults for white border and ESPHome image polarity
1435 
1436  // EPD hardware init end
1437 }
1439  // COMMAND DATA START TRANSMISSION 2 (B/W only)
1440  this->command(0x13);
1441  delay(2);
1442  this->start_data_();
1443  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
1444  this->write_byte(this->buffer_[i]);
1445  }
1446  this->end_data_();
1447  delay(2);
1448 
1449  // COMMAND DISPLAY REFRESH
1450  this->command(0x12);
1451  delay(2);
1452  this->wait_until_idle_();
1453 
1454  // COMMAND POWER OFF
1455  // NOTE: power off < deep sleep
1456  this->command(0x02);
1457 }
1458 int GDEY029T94::get_width_internal() { return 128; }
1459 int GDEY029T94::get_height_internal() { return 296; }
1461  LOG_DISPLAY("", "Waveshare E-Paper (Good Display)", this);
1462  ESP_LOGCONFIG(TAG, " Model: 2.9in Greyscale GDEY029T94");
1463  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1464  LOG_PIN(" DC Pin: ", this->dc_pin_);
1465  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1466  LOG_UPDATE_INTERVAL(this);
1467 }
1468 
1469 // ========================================================
1470 // Good Display 1.54in black/white/grey GDEW0154M09
1471 // As used in M5Stack Core Ink
1472 // Datasheet:
1473 // - https://v4.cecdn.yun300.cn/100001_1909185148/GDEW0154M09-200709.pdf
1474 // - https://github.com/m5stack/M5Core-Ink
1475 // Reference code from GoodDisplay:
1476 // - https://github.com/GoodDisplay/E-paper-Display-Library-of-GoodDisplay/
1477 // -> /Monochrome_E-paper-Display/1.54inch_JD79653_GDEW0154M09_200x200/ESP32-Arduino%20IDE/GDEW0154M09_Arduino.ino
1478 // M5Stack Core Ink spec:
1479 // - https://docs.m5stack.com/en/core/coreink
1480 // ========================================================
1481 
1483  this->init_internal_();
1485  this->lastbuff_ = allocator.allocate(this->get_buffer_length_());
1486  if (this->lastbuff_ != nullptr) {
1487  memset(this->lastbuff_, 0xff, sizeof(uint8_t) * this->get_buffer_length_());
1488  }
1489  this->clear_();
1490 }
1491 
1492 void GDEW0154M09::reset_() {
1493  // RST is inverse from other einks in this project
1494  if (this->reset_pin_ != nullptr) {
1495  this->reset_pin_->digital_write(false);
1496  delay(10);
1497  this->reset_pin_->digital_write(true);
1498  delay(10);
1499  }
1500 }
1501 
1502 void GDEW0154M09::init_internal_() {
1503  this->reset_();
1504 
1505  // clang-format off
1506  // 200x200 resolution: 11
1507  // LUT from OTP: 0
1508  // B/W mode (doesn't work): 1
1509  // scan-up: 1
1510  // shift-right: 1
1511  // booster ON: 1
1512  // no soft reset: 1
1513  const uint8_t panel_setting_1 = 0b11011111;
1514 
1515  // VCOM status off 0
1516  // Temp sensing default 1
1517  // VGL Power Off Floating 1
1518  // NORG expect refresh 1
1519  // VCOM Off on displ off 0
1520  const uint8_t panel_setting_2 = 0b01110;
1521 
1522  const uint8_t wf_t0154_cz_b3_list[] = {
1523  11, // 11 commands in list
1524  CMD_PSR_PANEL_SETTING, 2, panel_setting_1, panel_setting_2,
1525  CMD_UNDOCUMENTED_0x4D, 1, 0x55,
1526  CMD_UNDOCUMENTED_0xAA, 1, 0x0f,
1527  CMD_UNDOCUMENTED_0xE9, 1, 0x02,
1528  CMD_UNDOCUMENTED_0xB6, 1, 0x11,
1529  CMD_UNDOCUMENTED_0xF3, 1, 0x0a,
1530  CMD_TRES_RESOLUTION_SETTING, 3, 0xc8, 0x00, 0xc8,
1531  CMD_TCON_TCONSETTING, 1, 0x00,
1532  CMD_CDI_VCOM_DATA_INTERVAL, 1, 0xd7,
1533  CMD_PWS_POWER_SAVING, 1, 0x00,
1534  CMD_PON_POWER_ON, 0
1535  };
1536  // clang-format on
1537 
1538  this->write_init_list_(wf_t0154_cz_b3_list);
1539  delay(100); // NOLINT
1540  this->wait_until_idle_();
1541 }
1542 
1543 void GDEW0154M09::write_init_list_(const uint8_t *list) {
1544  uint8_t list_limit = list[0];
1545  uint8_t *start_ptr = ((uint8_t *) list + 1);
1546  for (uint8_t i = 0; i < list_limit; i++) {
1547  this->command(*(start_ptr + 0));
1548  for (uint8_t dnum = 0; dnum < *(start_ptr + 1); dnum++) {
1549  this->data(*(start_ptr + 2 + dnum));
1550  }
1551  start_ptr += (*(start_ptr + 1) + 2);
1552  }
1553 }
1554 
1555 void GDEW0154M09::clear_() {
1556  uint32_t pixsize = this->get_buffer_length_();
1557  for (uint8_t j = 0; j < 2; j++) {
1558  this->command(CMD_DTM1_DATA_START_TRANS);
1559  for (int count = 0; count < pixsize; count++) {
1560  this->data(0x00);
1561  }
1562  this->command(CMD_DTM2_DATA_START_TRANS2);
1563  for (int count = 0; count < pixsize; count++) {
1564  this->data(0xff);
1565  }
1566  this->command(CMD_DISPLAY_REFRESH);
1567  delay(10);
1568  this->wait_until_idle_();
1569  }
1570 }
1571 
1573  this->init_internal_();
1574  // "Mode 0 display" for now
1575  this->command(CMD_DTM1_DATA_START_TRANS);
1576  for (int i = 0; i < this->get_buffer_length_(); i++) {
1577  this->data(0xff);
1578  }
1579  this->command(CMD_DTM2_DATA_START_TRANS2); // write 'new' data to SRAM
1580  for (int i = 0; i < this->get_buffer_length_(); i++) {
1581  this->data(this->buffer_[i]);
1582  }
1583  this->command(CMD_DISPLAY_REFRESH);
1584  delay(10);
1585  this->wait_until_idle_();
1586  this->deep_sleep();
1587 }
1588 
1590  // COMMAND DEEP SLEEP
1591  this->command(CMD_POF_POWER_OFF);
1592  this->wait_until_idle_();
1593  delay(1000); // NOLINT
1594  this->command(CMD_DSLP_DEEP_SLEEP);
1595  this->data(DATA_DSLP_DEEP_SLEEP);
1596 }
1597 
1598 int GDEW0154M09::get_width_internal() { return 200; }
1601  LOG_DISPLAY("", "M5Stack CoreInk E-Paper (Good Display)", this);
1602  ESP_LOGCONFIG(TAG, " Model: 1.54in Greyscale GDEW0154M09");
1603  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1604  LOG_PIN(" DC Pin: ", this->dc_pin_);
1605  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1606  LOG_UPDATE_INTERVAL(this);
1607 }
1608 
1609 static const uint8_t LUT_VCOM_DC_4_2[] = {
1610  0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x17, 0x17, 0x00, 0x00, 0x02, 0x00, 0x0A, 0x01,
1611  0x00, 0x00, 0x01, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1612  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1613 };
1614 static const uint8_t LUT_WHITE_TO_WHITE_4_2[] = {
1615  0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A,
1616  0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1617  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1618 };
1619 static const uint8_t LUT_BLACK_TO_WHITE_4_2[] = {
1620  0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A,
1621  0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1622  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1623 };
1624 
1625 static const uint8_t LUT_BLACK_TO_BLACK_4_2[] = {
1626  0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A,
1627  0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1628  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1629 };
1630 
1631 static const uint8_t LUT_WHITE_TO_BLACK_4_2[] = {
1632  0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A,
1633  0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1634  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1635 };
1636 
1638  // https://www.waveshare.com/w/upload/7/7f/4.2inch-e-paper-b-specification.pdf - page 8
1639 
1640  // COMMAND POWER SETTING
1641  this->command(0x01);
1642  this->data(0x03); // VDS_EN, VDG_EN
1643  this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
1644  this->data(0x2B); // VDH
1645  this->data(0x2B); // VDL
1646  this->data(0xFF); // VDHR
1647 
1648  // COMMAND BOOSTER SOFT START
1649  this->command(0x06);
1650  this->data(0x17); // PHA
1651  this->data(0x17); // PHB
1652  this->data(0x17); // PHC
1653 
1654  // COMMAND POWER ON
1655  this->command(0x04);
1656  this->wait_until_idle_();
1657  delay(10);
1658  // COMMAND PANEL SETTING
1659  this->command(0x00);
1660  this->data(0xBF); // KW-BF KWR-AF BWROTP 0f
1661  this->data(0x0B);
1662  // COMMAND PLL CONTROL
1663  this->command(0x30);
1664  this->data(0x3C); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
1665 
1666  delay(2);
1667  // COMMAND LUT FOR VCOM
1668  this->command(0x20);
1669  for (uint8_t i : LUT_VCOM_DC_4_2)
1670  this->data(i);
1671  // COMMAND LUT WHITE TO WHITE
1672  this->command(0x21);
1673  for (uint8_t i : LUT_WHITE_TO_WHITE_4_2)
1674  this->data(i);
1675  // COMMAND LUT BLACK TO WHITE
1676  this->command(0x22);
1677  for (uint8_t i : LUT_BLACK_TO_WHITE_4_2)
1678  this->data(i);
1679  // COMMAND LUT WHITE TO BLACK
1680  this->command(0x23);
1681  for (uint8_t i : LUT_WHITE_TO_BLACK_4_2)
1682  this->data(i);
1683  // COMMAND LUT BLACK TO BLACK
1684  this->command(0x24);
1685  for (uint8_t i : LUT_BLACK_TO_BLACK_4_2)
1686  this->data(i);
1687 }
1689  // COMMAND RESOLUTION SETTING
1690  this->command(0x61);
1691  this->data(0x01);
1692  this->data(0x90);
1693  this->data(0x01);
1694  this->data(0x2C);
1695 
1696  // COMMAND VCM DC SETTING REGISTER
1697  this->command(0x82);
1698  this->data(0x12);
1699 
1700  // COMMAND VCOM AND DATA INTERVAL SETTING
1701  this->command(0x50);
1702  this->data(0x97);
1703 
1704  // COMMAND DATA START TRANSMISSION 1
1705  this->command(0x10);
1706  delay(2);
1707  this->start_data_();
1708  this->write_array(this->buffer_, this->get_buffer_length_());
1709  this->end_data_();
1710  delay(2);
1711  // COMMAND DATA START TRANSMISSION 2
1712  this->command(0x13);
1713  delay(2);
1714  this->start_data_();
1715  this->write_array(this->buffer_, this->get_buffer_length_());
1716  this->end_data_();
1717  // COMMAND DISPLAY REFRESH
1718  this->command(0x12);
1719 }
1723  LOG_DISPLAY("", "Waveshare E-Paper", this);
1724  ESP_LOGCONFIG(TAG, " Model: 4.2in");
1725  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1726  LOG_PIN(" DC Pin: ", this->dc_pin_);
1727  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1728  LOG_UPDATE_INTERVAL(this);
1729 }
1730 
1731 // ========================================================
1732 // 4.20in Type B (LUT from OTP)
1733 // Datasheet:
1734 // - https://www.waveshare.com/w/upload/2/20/4.2inch-e-paper-module-user-manual-en.pdf
1735 // - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_4in2b_V2.c
1736 // ========================================================
1738  // these exact timings are required for a proper reset/init
1739  this->reset_pin_->digital_write(false);
1740  delay(2);
1741  this->reset_pin_->digital_write(true);
1742  delay(200); // NOLINT
1743 
1744  // COMMAND POWER ON
1745  this->command(0x04);
1746  this->wait_until_idle_();
1747 
1748  // COMMAND PANEL SETTING
1749  this->command(0x00);
1750  this->data(0x0f); // LUT from OTP
1751 }
1752 
1754  // COMMAND DATA START TRANSMISSION 1 (B/W data)
1755  this->command(0x10);
1756  this->start_data_();
1757  this->write_array(this->buffer_, this->get_buffer_length_());
1758  this->end_data_();
1759 
1760  // COMMAND DATA START TRANSMISSION 2 (RED data)
1761  this->command(0x13);
1762  this->start_data_();
1763  for (size_t i = 0; i < this->get_buffer_length_(); i++)
1764  this->write_byte(0xFF);
1765  this->end_data_();
1766  delay(2);
1767 
1768  // COMMAND DISPLAY REFRESH
1769  this->command(0x12);
1770  this->wait_until_idle_();
1771 
1772  // COMMAND POWER OFF
1773  // NOTE: power off < deep sleep
1774  this->command(0x02);
1775 }
1779  LOG_DISPLAY("", "Waveshare E-Paper", this);
1780  ESP_LOGCONFIG(TAG, " Model: 4.2in (B V2)");
1781  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1782  LOG_PIN(" DC Pin: ", this->dc_pin_);
1783  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1784  LOG_UPDATE_INTERVAL(this);
1785 }
1786 
1788  // COMMAND POWER SETTING
1789  this->command(0x01);
1790  this->data(0x37);
1791  this->data(0x00);
1792 
1793  // COMMAND PANEL SETTING
1794  this->command(0x00);
1795  this->data(0xCF);
1796  this->data(0x0B);
1797 
1798  // COMMAND BOOSTER SOFT START
1799  this->command(0x06);
1800  this->data(0xC7);
1801  this->data(0xCC);
1802  this->data(0x28);
1803 
1804  // COMMAND POWER ON
1805  this->command(0x04);
1806  this->wait_until_idle_();
1807  delay(10);
1808 
1809  // COMMAND PLL CONTROL
1810  this->command(0x30);
1811  this->data(0x3C);
1812 
1813  // COMMAND TEMPERATURE SENSOR CALIBRATION
1814  this->command(0x41);
1815  this->data(0x00);
1816 
1817  // COMMAND VCOM AND DATA INTERVAL SETTING
1818  this->command(0x50);
1819  this->data(0x77);
1820 
1821  // COMMAND TCON SETTING
1822  this->command(0x60);
1823  this->data(0x22);
1824 
1825  // COMMAND RESOLUTION SETTING
1826  this->command(0x61);
1827  this->data(0x02);
1828  this->data(0x58);
1829  this->data(0x01);
1830  this->data(0xC0);
1831 
1832  // COMMAND VCM DC SETTING REGISTER
1833  this->command(0x82);
1834  this->data(0x1E);
1835 
1836  this->command(0xE5);
1837  this->data(0x03);
1838 }
1840  // COMMAND DATA START TRANSMISSION 1
1841  this->command(0x10);
1842 
1843  this->start_data_();
1844  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
1845  uint8_t temp1 = this->buffer_[i];
1846  for (uint8_t j = 0; j < 8; j++) {
1847  uint8_t temp2;
1848  if (temp1 & 0x80) {
1849  temp2 = 0x03;
1850  } else {
1851  temp2 = 0x00;
1852  }
1853 
1854  temp2 <<= 4;
1855  temp1 <<= 1;
1856  j++;
1857  if (temp1 & 0x80) {
1858  temp2 |= 0x03;
1859  } else {
1860  temp2 |= 0x00;
1861  }
1862  temp1 <<= 1;
1863  this->write_byte(temp2);
1864  }
1865 
1866  App.feed_wdt();
1867  }
1868  this->end_data_();
1869 
1870  // COMMAND DISPLAY REFRESH
1871  this->command(0x12);
1872 }
1876  LOG_DISPLAY("", "Waveshare E-Paper", this);
1877  ESP_LOGCONFIG(TAG, " Model: 5.83in");
1878  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1879  LOG_PIN(" DC Pin: ", this->dc_pin_);
1880  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1881  LOG_UPDATE_INTERVAL(this);
1882 }
1883 
1884 // ========================================================
1885 // 5.83in V2
1886 // Datasheet/Specification/Reference:
1887 // - https://www.waveshare.com/w/upload/3/37/5.83inch_e-Paper_V2_Specification.pdf
1888 // - https://github.com/waveshare/e-Paper/blob/master/Arduino/epd5in83_V2/epd5in83_V2.cpp
1889 // ========================================================
1891  // COMMAND POWER SETTING
1892  this->command(0x01);
1893  this->data(0x07);
1894  this->data(0x07);
1895  this->data(0x3f);
1896  this->data(0x3f);
1897 
1898  // COMMAND POWER ON
1899  this->command(0x04);
1900  delay(10);
1901  this->wait_until_idle_();
1902 
1903  // PANNEL SETTING
1904  this->command(0x00);
1905  this->data(0x1F);
1906 
1907  // COMMAND RESOLUTION SETTING
1908  this->command(0x61);
1909  this->data(0x02);
1910  this->data(0x88);
1911  this->data(0x01);
1912  this->data(0xE0);
1913 
1914  this->command(0x15);
1915  this->data(0x00);
1916 
1917  // COMMAND TCON SETTING
1918  this->command(0x60);
1919  this->data(0x22);
1920 
1921  // Do we need this?
1922  // COMMAND PLL CONTROL
1923  this->command(0x30);
1924  this->data(0x3C); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
1925 }
1927  // Reuse the code from WaveshareEPaper4P2In::display()
1928  // COMMAND VCM DC SETTING REGISTER
1929  this->command(0x82);
1930  this->data(0x12);
1931 
1932  // COMMAND VCOM AND DATA INTERVAL SETTING
1933  this->command(0x50);
1934  this->data(0x97);
1935 
1936  // COMMAND DATA START TRANSMISSION 1
1937  this->command(0x10);
1938  delay(2);
1939  this->start_data_();
1940  this->write_array(this->buffer_, this->get_buffer_length_());
1941  this->end_data_();
1942  delay(2);
1943 
1944  // COMMAND DATA START TRANSMISSION 2
1945  this->command(0x13);
1946  delay(2);
1947  this->start_data_();
1948  this->write_array(this->buffer_, this->get_buffer_length_());
1949  this->end_data_();
1950 
1951  // COMMAND DISPLAY REFRESH
1952  this->command(0x12);
1953 }
1957  LOG_DISPLAY("", "Waveshare E-Paper", this);
1958  ESP_LOGCONFIG(TAG, " Model: 5.83inv2");
1959  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1960  LOG_PIN(" DC Pin: ", this->dc_pin_);
1961  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1962  LOG_UPDATE_INTERVAL(this);
1963 }
1964 
1966  // COMMAND POWER SETTING
1967  this->command(0x01);
1968  this->data(0x07);
1969  this->data(0x07); // VGH=20V,VGL=-20V
1970  this->data(0x3f); // VDH=15V
1971  this->data(0x3f); // VDL=-15V
1972  // COMMAND POWER ON
1973  this->command(0x04);
1974  delay(100); // NOLINT
1975  this->wait_until_idle_();
1976  // COMMAND PANEL SETTING
1977  this->command(0x00);
1978  this->data(0x0F); // KW3f, KWR-2F, BWROTP 0f, BWOTP 1f
1979  this->command(0x61); // tres
1980  this->data(0x03); // 800px
1981  this->data(0x20);
1982  this->data(0x01); // 400px
1983  this->data(0xE0);
1984  this->command(0x15);
1985  this->data(0x00);
1986  // COMMAND VCOM AND DATA INTERVAL SETTING
1987  this->command(0x50);
1988  this->data(0x11);
1989  this->data(0x07);
1990  // COMMAND TCON SETTING
1991  this->command(0x60);
1992  this->data(0x22);
1993 
1994  this->command(0x82);
1995  this->data(0x08);
1996  this->command(0x30);
1997  this->data(0x06);
1998 
1999  // COMMAND RESOLUTION SETTING
2000  this->command(0x65);
2001  this->data(0x00);
2002  this->data(0x00); // 800*480
2003  this->data(0x00);
2004  this->data(0x00);
2005 }
2007  // COMMAND DATA START TRANSMISSION 1 (B/W data)
2008  this->command(0x10);
2009  delay(2);
2010  this->start_data_();
2011  this->write_array(this->buffer_, this->get_buffer_length_());
2012  this->end_data_();
2013  delay(2);
2014 
2015  // COMMAND DATA START TRANSMISSION 2 (RED data)
2016  this->command(0x13);
2017  delay(2);
2018  this->start_data_();
2019  for (size_t i = 0; i < this->get_buffer_length_(); i++)
2020  this->write_byte(0x00);
2021  this->end_data_();
2022  delay(2);
2023 
2024  // COMMAND DISPLAY REFRESH
2025  this->command(0x12);
2026  delay(100); // NOLINT
2027  this->wait_until_idle_();
2028  this->deep_sleep();
2029 }
2033  LOG_DISPLAY("", "Waveshare E-Paper", this);
2034  ESP_LOGCONFIG(TAG, " Model: 7.5in-bv2");
2035  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2036  LOG_PIN(" DC Pin: ", this->dc_pin_);
2037  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2038  LOG_UPDATE_INTERVAL(this);
2039 }
2040 
2043  if (this->busy_pin_ == nullptr) {
2044  return true;
2045  }
2046 
2047  const uint32_t start = millis();
2048  while (this->busy_pin_->digital_read()) {
2049  this->command(0x71);
2050  if (millis() - start > this->idle_timeout_()) {
2051  ESP_LOGI(TAG, "Timeout while displaying image!");
2052  return false;
2053  }
2054  App.feed_wdt();
2055  delay(10);
2056  }
2057  delay(200); // NOLINT
2058  return true;
2059 };
2061  this->reset_();
2062 
2063  // COMMAND POWER SETTING
2064  this->command(0x01);
2065 
2066  // 1-0=11: internal power
2067  this->data(0x07);
2068  this->data(0x17); // VGH&VGL
2069  this->data(0x3F); // VSH
2070  this->data(0x26); // VSL
2071  this->data(0x11); // VSHR
2072 
2073  // VCOM DC Setting
2074  this->command(0x82);
2075  this->data(0x24); // VCOM
2076 
2077  // Booster Setting
2078  this->command(0x06);
2079  this->data(0x27);
2080  this->data(0x27);
2081  this->data(0x2F);
2082  this->data(0x17);
2083 
2084  // POWER ON
2085  this->command(0x04);
2086 
2087  delay(100); // NOLINT
2088  this->wait_until_idle_();
2089  // COMMAND PANEL SETTING
2090  this->command(0x00);
2091  this->data(0x3F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
2092 
2093  // COMMAND RESOLUTION SETTING
2094  this->command(0x61);
2095  this->data(0x03); // source 800
2096  this->data(0x20);
2097  this->data(0x01); // gate 480
2098  this->data(0xE0);
2099  // COMMAND ...?
2100  this->command(0x15);
2101  this->data(0x00);
2102  // COMMAND VCOM AND DATA INTERVAL SETTING
2103  this->command(0x50);
2104  this->data(0x10);
2105  this->data(0x00);
2106  // COMMAND TCON SETTING
2107  this->command(0x60);
2108  this->data(0x22);
2109  // Resolution setting
2110  this->command(0x65);
2111  this->data(0x00);
2112  this->data(0x00); // 800*480
2113  this->data(0x00);
2114  this->data(0x00);
2115 
2116  uint8_t lut_vcom_7_i_n5_v2[] = {
2117  0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0xF, 0x1, 0xF, 0x1, 0x2, 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2118  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2119  };
2120 
2121  uint8_t lut_ww_7_i_n5_v2[] = {
2122  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2123  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2124  };
2125 
2126  uint8_t lut_bw_7_i_n5_v2[] = {
2127  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2128  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2129  };
2130 
2131  uint8_t lut_wb_7_i_n5_v2[] = {
2132  0x80, 0xF, 0xF, 0x0, 0x0, 0x3, 0x84, 0xF, 0x1, 0xF, 0x1, 0x4, 0x40, 0xF, 0xF, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
2133  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2134  };
2135 
2136  uint8_t lut_bb_7_i_n5_v2[] = {
2137  0x80, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x40, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2138  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2139  };
2140 
2141  uint8_t count;
2142  this->command(0x20); // VCOM
2143  for (count = 0; count < 42; count++)
2144  this->data(lut_vcom_7_i_n5_v2[count]);
2145 
2146  this->command(0x21); // LUTBW
2147  for (count = 0; count < 42; count++)
2148  this->data(lut_ww_7_i_n5_v2[count]);
2149 
2150  this->command(0x22); // LUTBW
2151  for (count = 0; count < 42; count++)
2152  this->data(lut_bw_7_i_n5_v2[count]);
2153 
2154  this->command(0x23); // LUTWB
2155  for (count = 0; count < 42; count++)
2156  this->data(lut_wb_7_i_n5_v2[count]);
2157 
2158  this->command(0x24); // LUTBB
2159  for (count = 0; count < 42; count++)
2160  this->data(lut_bb_7_i_n5_v2[count]);
2161 };
2163  this->init_display_();
2164  uint32_t buf_len = this->get_buffer_length_();
2165 
2166  this->command(0x10);
2167  for (uint32_t i = 0; i < buf_len; i++) {
2168  this->data(0xFF);
2169  }
2170 
2171  this->command(0x13); // Start Transmission
2172  delay(2);
2173  for (uint32_t i = 0; i < buf_len; i++) {
2174  this->data(~this->buffer_[i]);
2175  }
2176 
2177  this->command(0x12); // Display Refresh
2178  delay(100); // NOLINT
2179  this->wait_until_idle_();
2180  this->deep_sleep();
2181 }
2185  LOG_DISPLAY("", "Waveshare E-Paper", this);
2186  ESP_LOGCONFIG(TAG, " Model: 7.5in-bv3");
2187  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2188  LOG_PIN(" DC Pin: ", this->dc_pin_);
2189  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2190  LOG_UPDATE_INTERVAL(this);
2191 }
2192 
2194  // COMMAND POWER SETTING
2195  this->command(0x01);
2196  this->data(0x37);
2197  this->data(0x00);
2198  // COMMAND PANEL SETTING
2199  this->command(0x00);
2200  this->data(0xCF);
2201  this->data(0x0B);
2202  // COMMAND BOOSTER SOFT START
2203  this->command(0x06);
2204  this->data(0xC7);
2205  this->data(0xCC);
2206  this->data(0x28);
2207  // COMMAND POWER ON
2208  this->command(0x04);
2209  this->wait_until_idle_();
2210  delay(10);
2211  // COMMAND PLL CONTROL
2212  this->command(0x30);
2213  this->data(0x3C);
2214  // COMMAND TEMPERATURE SENSOR CALIBRATION
2215  this->command(0x41);
2216  this->data(0x00);
2217  // COMMAND VCOM AND DATA INTERVAL SETTING
2218  this->command(0x50);
2219  this->data(0x77);
2220  // COMMAND TCON SETTING
2221  this->command(0x60);
2222  this->data(0x22);
2223  // COMMAND RESOLUTION SETTING
2224  this->command(0x61);
2225  this->data(0x02);
2226  this->data(0x80);
2227  this->data(0x01);
2228  this->data(0x80);
2229  // COMMAND VCM DC SETTING REGISTER
2230  this->command(0x82);
2231  this->data(0x1E);
2232  this->command(0xE5);
2233  this->data(0x03);
2234 }
2236  // COMMAND DATA START TRANSMISSION 1
2237  this->command(0x10);
2238  this->start_data_();
2239  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
2240  uint8_t temp1 = this->buffer_[i];
2241  for (uint8_t j = 0; j < 8; j++) {
2242  uint8_t temp2;
2243  if (temp1 & 0x80) {
2244  temp2 = 0x03;
2245  } else {
2246  temp2 = 0x00;
2247  }
2248  temp2 <<= 4;
2249  temp1 <<= 1;
2250  j++;
2251  if (temp1 & 0x80) {
2252  temp2 |= 0x03;
2253  } else {
2254  temp2 |= 0x00;
2255  }
2256  temp1 <<= 1;
2257  this->write_byte(temp2);
2258  }
2259  App.feed_wdt();
2260  }
2261  this->end_data_();
2262  // COMMAND DISPLAY REFRESH
2263  this->command(0x12);
2264 }
2268  LOG_DISPLAY("", "Waveshare E-Paper", this);
2269  ESP_LOGCONFIG(TAG, " Model: 7.5in");
2270  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2271  LOG_PIN(" DC Pin: ", this->dc_pin_);
2272  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2273  LOG_UPDATE_INTERVAL(this);
2274 }
2276  if (this->busy_pin_ == nullptr) {
2277  return true;
2278  }
2279 
2280  const uint32_t start = millis();
2281  while (this->busy_pin_->digital_read()) {
2282  this->command(0x71);
2283  if (millis() - start > this->idle_timeout_()) {
2284  ESP_LOGE(TAG, "Timeout while displaying image!");
2285  return false;
2286  }
2287  App.feed_wdt();
2288  delay(10);
2289  }
2290  return true;
2291 }
2293  // COMMAND POWER SETTING
2294  this->command(0x01);
2295  this->data(0x07);
2296  this->data(0x07);
2297  this->data(0x3f);
2298  this->data(0x3f);
2299 
2300  // We don't want the display to be powered at this point
2301 
2302  delay(100); // NOLINT
2303  this->wait_until_idle_();
2304 
2305  // COMMAND VCOM AND DATA INTERVAL SETTING
2306  this->command(0x50);
2307  this->data(0x10);
2308  this->data(0x07);
2309 
2310  // COMMAND TCON SETTING
2311  this->command(0x60);
2312  this->data(0x22);
2313 
2314  // COMMAND PANEL SETTING
2315  this->command(0x00);
2316  this->data(0x1F);
2317 
2318  // COMMAND RESOLUTION SETTING
2319  this->command(0x61);
2320  this->data(0x03);
2321  this->data(0x20);
2322  this->data(0x01);
2323  this->data(0xE0);
2324 
2325  // COMMAND DUAL SPI MM_EN, DUSPI_EN
2326  this->command(0x15);
2327  this->data(0x00);
2328 
2329  // COMMAND POWER DRIVER HAT DOWN
2330  // This command will turn off booster, controller, source driver, gate driver, VCOM, and
2331  // temperature sensor, but register data will be kept until VDD turned OFF or Deep Sleep Mode.
2332  // Source/Gate/Border/VCOM will be released to floating.
2333  this->command(0x02);
2334 }
2336  uint32_t buf_len = this->get_buffer_length_();
2337 
2338  // COMMAND POWER ON
2339  ESP_LOGI(TAG, "Power on the display and hat");
2340 
2341  // This command will turn on booster, controller, regulators, and temperature sensor will be
2342  // activated for one-time sensing before enabling booster. When all voltages are ready, the
2343  // BUSY_N signal will return to high.
2344  this->command(0x04);
2345  delay(200); // NOLINT
2346  this->wait_until_idle_();
2347 
2348  // COMMAND DATA START TRANSMISSION NEW DATA
2349  this->command(0x13);
2350  delay(2);
2351  for (uint32_t i = 0; i < buf_len; i++) {
2352  this->data(~(this->buffer_[i]));
2353  }
2354 
2355  delay(100); // NOLINT
2356  this->wait_until_idle_();
2357 
2358  // COMMAND DISPLAY REFRESH
2359  this->command(0x12);
2360  delay(100); // NOLINT
2361  this->wait_until_idle_();
2362 
2363  ESP_LOGV(TAG, "Before command(0x02) (>> power off)");
2364  this->command(0x02);
2365  this->wait_until_idle_();
2366  ESP_LOGV(TAG, "After command(0x02) (>> power off)");
2367 }
2368 
2371 uint32_t WaveshareEPaper7P5InV2::idle_timeout_() { return 10000; }
2373  LOG_DISPLAY("", "Waveshare E-Paper", this);
2374  ESP_LOGCONFIG(TAG, " Model: 7.5inV2rev2");
2375  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2376  LOG_PIN(" DC Pin: ", this->dc_pin_);
2377  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2378  LOG_UPDATE_INTERVAL(this);
2379 }
2380 
2381 /* 7.50inV2alt */
2383  if (this->busy_pin_ == nullptr) {
2384  return true;
2385  }
2386 
2387  const uint32_t start = millis();
2388  while (this->busy_pin_->digital_read()) {
2389  this->command(0x71);
2390  if (millis() - start > this->idle_timeout_()) {
2391  ESP_LOGI(TAG, "Timeout while displaying image!");
2392  return false;
2393  }
2394  delay(10);
2395  }
2396  return true;
2397 }
2398 
2400  this->reset_();
2401 
2402  // COMMAND POWER SETTING
2403  this->command(0x01);
2404 
2405  // 1-0=11: internal power
2406  this->data(0x07);
2407  this->data(0x17); // VGH&VGL
2408  this->data(0x3F); // VSH
2409  this->data(0x26); // VSL
2410  this->data(0x11); // VSHR
2411 
2412  // VCOM DC Setting
2413  this->command(0x82);
2414  this->data(0x24); // VCOM
2415 
2416  // Booster Setting
2417  this->command(0x06);
2418  this->data(0x27);
2419  this->data(0x27);
2420  this->data(0x2F);
2421  this->data(0x17);
2422 
2423  // POWER ON
2424  this->command(0x04);
2425 
2426  delay(100); // NOLINT
2427  this->wait_until_idle_();
2428  // COMMAND PANEL SETTING
2429  this->command(0x00);
2430  this->data(0x3F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
2431 
2432  // COMMAND RESOLUTION SETTING
2433  this->command(0x61);
2434  this->data(0x03); // source 800
2435  this->data(0x20);
2436  this->data(0x01); // gate 480
2437  this->data(0xE0);
2438  // COMMAND ...?
2439  this->command(0x15);
2440  this->data(0x00);
2441  // COMMAND VCOM AND DATA INTERVAL SETTING
2442  this->command(0x50);
2443  this->data(0x10);
2444  this->data(0x00);
2445  // COMMAND TCON SETTING
2446  this->command(0x60);
2447  this->data(0x22);
2448  // Resolution setting
2449  this->command(0x65);
2450  this->data(0x00);
2451  this->data(0x00); // 800*480
2452  this->data(0x00);
2453  this->data(0x00);
2454 
2455  this->wait_until_idle_();
2456 
2457  uint8_t lut_vcom_7_i_n5_v2[] = {
2458  0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0xF, 0x1, 0xF, 0x1, 0x2, 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2459  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2460  };
2461 
2462  uint8_t lut_ww_7_i_n5_v2[] = {
2463  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2464  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2465  };
2466 
2467  uint8_t lut_bw_7_i_n5_v2[] = {
2468  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2469  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2470  };
2471 
2472  uint8_t lut_wb_7_i_n5_v2[] = {
2473  0x80, 0xF, 0xF, 0x0, 0x0, 0x3, 0x84, 0xF, 0x1, 0xF, 0x1, 0x4, 0x40, 0xF, 0xF, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
2474  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2475  };
2476 
2477  uint8_t lut_bb_7_i_n5_v2[] = {
2478  0x80, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x40, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
2479  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2480  };
2481 
2482  uint8_t count;
2483  this->command(0x20); // VCOM
2484  for (count = 0; count < 42; count++)
2485  this->data(lut_vcom_7_i_n5_v2[count]);
2486 
2487  this->command(0x21); // LUTBW
2488  for (count = 0; count < 42; count++)
2489  this->data(lut_ww_7_i_n5_v2[count]);
2490 
2491  this->command(0x22); // LUTBW
2492  for (count = 0; count < 42; count++)
2493  this->data(lut_bw_7_i_n5_v2[count]);
2494 
2495  this->command(0x23); // LUTWB
2496  for (count = 0; count < 42; count++)
2497  this->data(lut_wb_7_i_n5_v2[count]);
2498 
2499  this->command(0x24); // LUTBB
2500  for (count = 0; count < 42; count++)
2501  this->data(lut_bb_7_i_n5_v2[count]);
2502 }
2503 
2505  LOG_DISPLAY("", "Waveshare E-Paper", this);
2506  ESP_LOGCONFIG(TAG, " Model: 7.5inV2");
2507  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2508  LOG_PIN(" DC Pin: ", this->dc_pin_);
2509  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2510  LOG_UPDATE_INTERVAL(this);
2511 }
2512 
2513 /* 7.50in-bc */
2515  /* The command sequence is similar to the 7P5In display but differs in subtle ways
2516  to allow for faster updates. */
2517  // COMMAND POWER SETTING
2518  this->command(0x01);
2519  this->data(0x37);
2520  this->data(0x00);
2521 
2522  // COMMAND PANEL SETTING
2523  this->command(0x00);
2524  this->data(0xCF);
2525  this->data(0x08);
2526 
2527  // COMMAND PLL CONTROL
2528  this->command(0x30);
2529  this->data(0x3A);
2530 
2531  // COMMAND VCM_DC_SETTING: all temperature range
2532  this->command(0x82);
2533  this->data(0x28);
2534 
2535  // COMMAND BOOSTER SOFT START
2536  this->command(0x06);
2537  this->data(0xC7);
2538  this->data(0xCC);
2539  this->data(0x15);
2540 
2541  // COMMAND VCOM AND DATA INTERVAL SETTING
2542  this->command(0x50);
2543  this->data(0x77);
2544 
2545  // COMMAND TCON SETTING
2546  this->command(0x60);
2547  this->data(0x22);
2548 
2549  // COMMAND FLASH CONTROL
2550  this->command(0x65);
2551  this->data(0x00);
2552 
2553  // COMMAND RESOLUTION SETTING
2554  this->command(0x61);
2555  this->data(0x02); // 640 >> 8
2556  this->data(0x80);
2557  this->data(0x01); // 384 >> 8
2558  this->data(0x80);
2559 
2560  // COMMAND FLASH MODE
2561  this->command(0xE5);
2562  this->data(0x03);
2563 }
2564 
2566  // COMMAND DATA START TRANSMISSION 1
2567  this->command(0x10);
2568  this->start_data_();
2569 
2570  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
2571  // A line of eight source pixels (each a bit in this byte)
2572  uint8_t eight_pixels = this->buffer_[i];
2573 
2574  for (uint8_t j = 0; j < 8; j += 2) {
2575  /* For bichromatic displays, each byte represents two pixels. Each nibble encodes a pixel: 0=white, 3=black,
2576  4=color. Therefore, e.g. 0x44 = two adjacent color pixels, 0x33 is two adjacent black pixels, etc. If you want
2577  to draw using the color pixels, change '0x30' with '0x40' and '0x03' with '0x04' below. */
2578  uint8_t left_nibble = (eight_pixels & 0x80) ? 0x30 : 0x00;
2579  eight_pixels <<= 1;
2580  uint8_t right_nibble = (eight_pixels & 0x80) ? 0x03 : 0x00;
2581  eight_pixels <<= 1;
2582  this->write_byte(left_nibble | right_nibble);
2583  }
2584  App.feed_wdt();
2585  }
2586  this->end_data_();
2587 
2588  // Unlike the 7P5In display, we send the "power on" command here rather than during initialization
2589  // COMMAND POWER ON
2590  this->command(0x04);
2591 
2592  // COMMAND DISPLAY REFRESH
2593  this->command(0x12);
2594 }
2595 
2597 
2599 
2601  LOG_DISPLAY("", "Waveshare E-Paper", this);
2602  ESP_LOGCONFIG(TAG, " Model: 7.5in-bc");
2603  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2604  LOG_PIN(" DC Pin: ", this->dc_pin_);
2605  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2606  LOG_UPDATE_INTERVAL(this);
2607 }
2608 
2610  this->command(0x12); // SWRESET
2611 
2612  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
2613 
2614  this->command(0x46); // Auto Write RAM
2615  this->data(0xF7);
2616 
2617  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
2618 
2619  this->command(0x47); // Auto Write RAM
2620  this->data(0xF7);
2621 
2622  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
2623 
2624  this->command(0x0C); // Soft start setting
2625  this->data(0xAE);
2626  this->data(0xC7);
2627  this->data(0xC3);
2628  this->data(0xC0);
2629  this->data(0x40);
2630 
2631  this->command(0x01); // Set MUX as 527
2632  this->data(0xAF);
2633  this->data(0x02);
2634  this->data(0x01);
2635 
2636  this->command(0x11); // Data entry mode
2637  this->data(0x01);
2638 
2639  this->command(0x44);
2640  this->data(0x00); // RAM x address start at 0
2641  this->data(0x00);
2642  this->data(0x6F); // RAM x address end at 36Fh -> 879
2643  this->data(0x03);
2644 
2645  this->command(0x45);
2646  this->data(0xAF); // RAM y address start at 20Fh;
2647  this->data(0x02);
2648  this->data(0x00); // RAM y address end at 00h;
2649  this->data(0x00);
2650 
2651  this->command(0x3C); // VBD
2652  this->data(0x01); // LUT1, for white
2653 
2654  this->command(0x18);
2655  this->data(0X80);
2656 
2657  this->command(0x22);
2658  this->data(0XB1); // Load Temperature and waveform setting.
2659 
2660  this->command(0x20);
2661 
2662  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
2663 
2664  this->command(0x4E);
2665  this->data(0x00);
2666  this->data(0x00);
2667 
2668  this->command(0x4F);
2669  this->data(0xAF);
2670  this->data(0x02);
2671 }
2672 
2674  this->command(0x4F);
2675  this->data(0xAf);
2676  this->data(0x02);
2677 
2678  // BLACK
2679  this->command(0x24);
2680  this->start_data_();
2681  this->write_array(this->buffer_, this->get_buffer_length_());
2682  this->end_data_();
2683 
2684  // RED
2685  this->command(0x26);
2686  this->start_data_();
2687  for (size_t i = 0; i < this->get_buffer_length_(); i++)
2688  this->write_byte(0x00);
2689  this->end_data_();
2690 
2691  this->command(0x22);
2692  this->data(0xC7);
2693  this->command(0x20);
2694  delay(100); // NOLINT
2695 }
2696 
2698 
2700 
2702  LOG_DISPLAY("", "Waveshare E-Paper", this);
2703  ESP_LOGCONFIG(TAG, " Model: 7.5in-HD-b");
2704  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2705  LOG_PIN(" DC Pin: ", this->dc_pin_);
2706  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2707  LOG_UPDATE_INTERVAL(this);
2708 }
2709 
2710 static const uint8_t LUT_SIZE_TTGO_DKE_PART = 153;
2711 
2712 static const uint8_t PART_UPDATE_LUT_TTGO_DKE[LUT_SIZE_TTGO_DKE_PART] = {
2713  0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2714  0x0, 0x0, 0x0, 0x0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0,
2715  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2716  0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2717  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2718  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2719  0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2720  0x0, 0x0, 0x0, 0x0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
2721  // 0x22, 0x17, 0x41, 0x0, 0x32, 0x32
2722 };
2723 
2726  bool partial = this->at_update_ != 0;
2727  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
2728 
2729  if (partial) {
2730  ESP_LOGI(TAG, "Performing partial e-paper update.");
2731  } else {
2732  ESP_LOGI(TAG, "Performing full e-paper update.");
2733  }
2734 
2735  // start and set up data format
2736  this->command(0x12);
2737  this->wait_until_idle_();
2738 
2739  this->command(0x11);
2740  this->data(0x03);
2741  this->command(0x44);
2742  this->data(1);
2743  this->data(this->get_width_internal() / 8);
2744  this->command(0x45);
2745  this->data(0);
2746  this->data(0);
2747  this->data(this->get_height_internal());
2748  this->data(0);
2749  this->command(0x4e);
2750  this->data(1);
2751  this->command(0x4f);
2752  this->data(0);
2753  this->data(0);
2754 
2755  if (!partial) {
2756  // send data
2757  this->command(0x24);
2758  this->start_data_();
2759  this->write_array(this->buffer_, this->get_buffer_length_());
2760  this->end_data_();
2761 
2762  // commit
2763  this->command(0x20);
2764  this->wait_until_idle_();
2765  } else {
2766  // set up partial update
2767  this->command(0x32);
2768  this->start_data_();
2769  this->write_array(PART_UPDATE_LUT_TTGO_DKE, sizeof(PART_UPDATE_LUT_TTGO_DKE));
2770  this->end_data_();
2771  this->command(0x3F);
2772  this->data(0x22);
2773 
2774  this->command(0x03);
2775  this->data(0x17);
2776  this->command(0x04);
2777  this->data(0x41);
2778  this->data(0x00);
2779  this->data(0x32);
2780  this->command(0x2C);
2781  this->data(0x32);
2782 
2783  this->command(0x37);
2784  this->data(0x00);
2785  this->data(0x00);
2786  this->data(0x00);
2787  this->data(0x00);
2788  this->data(0x00);
2789  this->data(0x40);
2790  this->data(0x00);
2791  this->data(0x00);
2792  this->data(0x00);
2793  this->data(0x00);
2794 
2795  this->command(0x3C);
2796  this->data(0x80);
2797  this->command(0x22);
2798  this->data(0xC0);
2799  this->command(0x20);
2800  this->wait_until_idle_();
2801 
2802  // send data
2803  this->command(0x24);
2804  this->start_data_();
2805  this->write_array(this->buffer_, this->get_buffer_length_());
2806  this->end_data_();
2807 
2808  // commit as partial
2809  this->command(0x22);
2810  this->data(0xCF);
2811  this->command(0x20);
2812  this->wait_until_idle_();
2813 
2814  // data must be sent again on partial update
2815  this->command(0x24);
2816  this->start_data_();
2817  this->write_array(this->buffer_, this->get_buffer_length_());
2818  this->end_data_();
2819  }
2820 
2821  ESP_LOGI(TAG, "Completed e-paper update.");
2822 }
2823 
2826 uint32_t WaveshareEPaper2P13InDKE::idle_timeout_() { return 5000; }
2828  LOG_DISPLAY("", "Waveshare E-Paper", this);
2829  ESP_LOGCONFIG(TAG, " Model: 2.13inDKE");
2830  LOG_PIN(" CS Pin: ", this->cs_);
2831  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2832  LOG_PIN(" DC Pin: ", this->dc_pin_);
2833  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2834  LOG_UPDATE_INTERVAL(this);
2835 }
2836 
2837 void WaveshareEPaper2P13InDKE::set_full_update_every(uint32_t full_update_every) {
2838  this->full_update_every_ = full_update_every;
2839 }
2840 
2841 } // namespace waveshare_epaper
2842 } // namespace esphome
virtual void digital_write(bool value)=0
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:146
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
An STL allocator that uses SPI RAM.
Definition: helpers.h:645
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:89
GPIOPin * cs_
Definition: spi.h:395
WaveshareEPaperTypeA(WaveshareEPaperTypeAModel model)
virtual void fill(Color color)
Fill the entire screen with the given color.
Definition: display.cpp:15
virtual void setup()=0
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:161
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
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
bool is_on() ALWAYS_INLINE
Definition: color.h:46
void set_full_update_every(uint32_t full_update_every)
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