ESPHome  2022.5.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 
6 namespace esphome {
7 namespace waveshare_epaper {
8 
9 static const char *const TAG = "waveshare_epaper";
10 
11 static const uint8_t LUT_SIZE_WAVESHARE = 30;
12 
13 static const uint8_t FULL_UPDATE_LUT[LUT_SIZE_WAVESHARE] = {0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22, 0x66, 0x69,
14  0x69, 0x59, 0x58, 0x99, 0x99, 0x88, 0x00, 0x00, 0x00, 0x00,
15  0xF8, 0xB4, 0x13, 0x51, 0x35, 0x51, 0x51, 0x19, 0x01, 0x00};
16 
17 static const uint8_t PARTIAL_UPDATE_LUT[LUT_SIZE_WAVESHARE] = {
18  0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19  0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
20 
21 static const uint8_t LUT_SIZE_TTGO = 70;
22 
23 static const uint8_t FULL_UPDATE_LUT_TTGO[LUT_SIZE_TTGO] = {
24  0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, // LUT0: BB: VS 0 ~7
25  0x10, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, // LUT1: BW: VS 0 ~7
26  0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, // LUT2: WB: VS 0 ~7
27  0x10, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, // LUT3: WW: VS 0 ~7
28  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT4: VCOM: VS 0 ~7
29  0x03, 0x03, 0x00, 0x00, 0x02, // TP0 A~D RP0
30  0x09, 0x09, 0x00, 0x00, 0x02, // TP1 A~D RP1
31  0x03, 0x03, 0x00, 0x00, 0x02, // TP2 A~D RP2
32  0x00, 0x00, 0x00, 0x00, 0x00, // TP3 A~D RP3
33  0x00, 0x00, 0x00, 0x00, 0x00, // TP4 A~D RP4
34  0x00, 0x00, 0x00, 0x00, 0x00, // TP5 A~D RP5
35  0x00, 0x00, 0x00, 0x00, 0x00, // TP6 A~D RP6
36 };
37 
38 static const uint8_t PARTIAL_UPDATE_LUT_TTGO[LUT_SIZE_TTGO] = {
39  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT0: BB: VS 0 ~7
40  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT1: BW: VS 0 ~7
41  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT2: WB: VS 0 ~7
42  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT3: WW: VS 0 ~7
43  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // LUT4: VCOM: VS 0 ~7
44  0x0A, 0x00, 0x00, 0x00, 0x00, // TP0 A~D RP0
45  0x00, 0x00, 0x00, 0x00, 0x00, // TP1 A~D RP1
46  0x00, 0x00, 0x00, 0x00, 0x00, // TP2 A~D RP2
47  0x00, 0x00, 0x00, 0x00, 0x00, // TP3 A~D RP3
48  0x00, 0x00, 0x00, 0x00, 0x00, // TP4 A~D RP4
49  0x00, 0x00, 0x00, 0x00, 0x00, // TP5 A~D RP5
50  0x00, 0x00, 0x00, 0x00, 0x00, // TP6 A~D RP6
51 };
52 
53 static const uint8_t LUT_SIZE_TTGO_B73 = 100;
54 
55 static const uint8_t FULL_UPDATE_LUT_TTGO_B73[LUT_SIZE_TTGO_B73] = {
56  0xA0, 0x90, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x90, 0xA0, 0x00, 0x00, 0x00, 0x00,
57  0x00, 0x00, 0x00, 0xA0, 0x90, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x90, 0xA0, 0x00,
58  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 
60  0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x03, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
61  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 };
64 
65 static const uint8_t PARTIAL_UPDATE_LUT_TTGO_B73[LUT_SIZE_TTGO_B73] = {
66  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67  0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
68  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 
70  0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71  0x00, 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,
73 };
74 
75 static const uint8_t LUT_SIZE_TTGO_B1 = 29;
76 
77 static const uint8_t FULL_UPDATE_LUT_TTGO_B1[LUT_SIZE_TTGO_B1] = {
78  0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79  0x00, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x01, 0x00, 0x00, 0x00, 0x00};
80 
81 static const uint8_t PARTIAL_UPDATE_LUT_TTGO_B1[LUT_SIZE_TTGO_B1] = {
82  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83  0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
84 
86  this->init_internal_(this->get_buffer_length_());
87  this->dc_pin_->setup(); // OUTPUT
88  this->dc_pin_->digital_write(false);
89  if (this->reset_pin_ != nullptr) {
90  this->reset_pin_->setup(); // OUTPUT
91  this->reset_pin_->digital_write(true);
92  }
93  if (this->busy_pin_ != nullptr) {
94  this->busy_pin_->setup(); // INPUT
95  }
96  this->spi_setup();
97 
98  this->reset_();
99 }
101 void WaveshareEPaper::command(uint8_t value) {
102  this->start_command_();
103  this->write_byte(value);
104  this->end_command_();
105 }
106 void WaveshareEPaper::data(uint8_t value) {
107  this->start_data_();
108  this->write_byte(value);
109  this->end_data_();
110 }
112  if (this->busy_pin_ == nullptr) {
113  return true;
114  }
115 
116  const uint32_t start = millis();
117  while (this->busy_pin_->digital_read()) {
118  if (millis() - start > this->idle_timeout_()) {
119  ESP_LOGE(TAG, "Timeout while displaying image!");
120  return false;
121  }
122  delay(10);
123  }
124  return true;
125 }
127  this->do_update_();
128  this->display();
129 }
131  // flip logic
132  const uint8_t fill = color.is_on() ? 0x00 : 0xFF;
133  for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
134  this->buffer_[i] = fill;
135 }
137  if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
138  return;
139 
140  const uint32_t pos = (x + y * this->get_width_internal()) / 8u;
141  const uint8_t subpos = x & 0x07;
142  // flip logic
143  if (!color.is_on()) {
144  this->buffer_[pos] |= 0x80 >> subpos;
145  } else {
146  this->buffer_[pos] &= ~(0x80 >> subpos);
147  }
148 }
151  this->dc_pin_->digital_write(false);
152  this->enable();
153 }
156  this->dc_pin_->digital_write(true);
157  this->enable();
158 }
161 
162 // ========================================================
163 // Type A
164 // ========================================================
165 
167  if (this->model_ == TTGO_EPAPER_2_13_IN_B74) {
168  this->reset_pin_->digital_write(false);
169  delay(10);
170  this->reset_pin_->digital_write(true);
171  delay(10);
172  this->wait_until_idle_();
173 
174  this->command(0x12); // SWRESET
175  this->wait_until_idle_();
176  }
177 
178  // COMMAND DRIVER OUTPUT CONTROL
179  this->command(0x01);
180  this->data(this->get_height_internal() - 1);
181  this->data((this->get_height_internal() - 1) >> 8);
182  this->data(0x00); // ? GD = 0, SM = 0, TB = 0
183 
184  // COMMAND BOOSTER SOFT START CONTROL
185  this->command(0x0C);
186  this->data(0xD7);
187  this->data(0xD6);
188  this->data(0x9D);
189 
190  // COMMAND WRITE VCOM REGISTER
191  this->command(0x2C);
192  this->data(0xA8);
193 
194  // COMMAND SET DUMMY LINE PERIOD
195  this->command(0x3A);
196  this->data(0x1A);
197 
198  // COMMAND SET GATE TIME
199  this->command(0x3B);
200  this->data(0x08); // 2┬Ás per row
201 
202  // COMMAND DATA ENTRY MODE SETTING
203  this->command(0x11);
204  switch (this->model_) {
206  this->data(0x01); // x increase, y decrease : as in demo code
207  break;
210  this->data(0x03); // from top left to bottom right
211  // RAM content option for Display Update
212  this->command(0x21);
213  this->data(0x00);
214  this->data(0x80);
215  break;
216  default:
217  this->data(0x03); // from top left to bottom right
218  }
219 }
221  LOG_DISPLAY("", "Waveshare E-Paper", this);
222  switch (this->model_) {
224  ESP_LOGCONFIG(TAG, " Model: 1.54in");
225  break;
227  ESP_LOGCONFIG(TAG, " Model: 1.54inV2");
228  break;
230  ESP_LOGCONFIG(TAG, " Model: 2.13in");
231  break;
232  case TTGO_EPAPER_2_13_IN:
233  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO)");
234  break;
236  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B73)");
237  break;
239  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B74)");
240  break;
242  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B1)");
243  break;
245  ESP_LOGCONFIG(TAG, " Model: 2.9in");
246  break;
248  ESP_LOGCONFIG(TAG, " Model: 2.9inV2");
249  break;
250  }
251  ESP_LOGCONFIG(TAG, " Full Update Every: %u", this->full_update_every_);
252  LOG_PIN(" Reset Pin: ", this->reset_pin_);
253  LOG_PIN(" DC Pin: ", this->dc_pin_);
254  LOG_PIN(" Busy Pin: ", this->busy_pin_);
255  LOG_UPDATE_INTERVAL(this);
256 }
258  bool full_update = this->at_update_ == 0;
259  bool prev_full_update = this->at_update_ == 1;
260 
261  if (!this->wait_until_idle_()) {
262  this->status_set_warning();
263  return;
264  }
265 
266  if (this->full_update_every_ >= 1) {
267  if (full_update != prev_full_update) {
268  switch (this->model_) {
269  case TTGO_EPAPER_2_13_IN:
270  this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO : PARTIAL_UPDATE_LUT_TTGO, LUT_SIZE_TTGO);
271  break;
273  this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO_B73 : PARTIAL_UPDATE_LUT_TTGO_B73, LUT_SIZE_TTGO_B73);
274  break;
276  // there is no LUT
277  break;
279  this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO_B1 : PARTIAL_UPDATE_LUT_TTGO_B1, LUT_SIZE_TTGO_B1);
280  break;
281  default:
282  this->write_lut_(full_update ? FULL_UPDATE_LUT : PARTIAL_UPDATE_LUT, LUT_SIZE_WAVESHARE);
283  }
284  }
285  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
286  }
287 
288  // Set x & y regions we want to write to (full)
289  switch (this->model_) {
291  // COMMAND SET RAM X ADDRESS START END POSITION
292  this->command(0x44);
293  this->data(0x00);
294  this->data((this->get_width_internal() - 1) >> 3);
295  // COMMAND SET RAM Y ADDRESS START END POSITION
296  this->command(0x45);
297  this->data(this->get_height_internal() - 1);
298  this->data((this->get_height_internal() - 1) >> 8);
299  this->data(0x00);
300  this->data(0x00);
301 
302  // COMMAND SET RAM X ADDRESS COUNTER
303  this->command(0x4E);
304  this->data(0x00);
305  // COMMAND SET RAM Y ADDRESS COUNTER
306  this->command(0x4F);
307  this->data(this->get_height_internal() - 1);
308  this->data((this->get_height_internal() - 1) >> 8);
309 
310  break;
312  // BorderWaveform
313  this->command(0x3C);
314  this->data(full_update ? 0x05 : 0x80);
315 
316  // fall through
317  default:
318  // COMMAND SET RAM X ADDRESS START END POSITION
319  this->command(0x44);
320  this->data(0x00);
321  this->data((this->get_width_internal() - 1) >> 3);
322  // COMMAND SET RAM Y ADDRESS START END POSITION
323  this->command(0x45);
324  this->data(0x00);
325  this->data(0x00);
326  this->data(this->get_height_internal() - 1);
327  this->data((this->get_height_internal() - 1) >> 8);
328 
329  // COMMAND SET RAM X ADDRESS COUNTER
330  this->command(0x4E);
331  this->data(0x00);
332  // COMMAND SET RAM Y ADDRESS COUNTER
333  this->command(0x4F);
334  this->data(0x00);
335  this->data(0x00);
336  }
337 
338  if (!this->wait_until_idle_()) {
339  this->status_set_warning();
340  return;
341  }
342 
343  // COMMAND WRITE RAM
344  this->command(0x24);
345  this->start_data_();
346  switch (this->model_) {
347  case TTGO_EPAPER_2_13_IN_B1: { // block needed because of variable initializations
348  int16_t wb = ((this->get_width_internal()) >> 3);
349  for (int i = 0; i < this->get_height_internal(); i++) {
350  for (int j = 0; j < wb; j++) {
351  int idx = j + (this->get_height_internal() - 1 - i) * wb;
352  this->write_byte(this->buffer_[idx]);
353  }
354  }
355  break;
356  }
357  default:
358  this->write_array(this->buffer_, this->get_buffer_length_());
359  }
360  this->end_data_();
361 
362  // COMMAND DISPLAY UPDATE CONTROL 2
363  this->command(0x22);
364  switch (this->model_) {
368  this->data(full_update ? 0xF7 : 0xFF);
369  break;
371  this->data(0xC7);
372  break;
373  default:
374  this->data(0xC4);
375  break;
376  }
377 
378  // COMMAND MASTER ACTIVATION
379  this->command(0x20);
380  // COMMAND TERMINATE FRAME READ WRITE
381  this->command(0xFF);
382 
383  this->status_clear_warning();
384 }
386  switch (this->model_) {
389  return 200;
391  case TTGO_EPAPER_2_13_IN:
397  return 128;
398  }
399  return 0;
400 }
402  switch (this->model_) {
405  return 200;
407  case TTGO_EPAPER_2_13_IN:
411  return 250;
414  return 296;
415  }
416  return 0;
417 }
418 void WaveshareEPaperTypeA::write_lut_(const uint8_t *lut, const uint8_t size) {
419  // COMMAND WRITE LUT REGISTER
420  this->command(0x32);
421  for (uint8_t i = 0; i < size; i++)
422  this->data(lut[i]);
423 }
425 void WaveshareEPaperTypeA::set_full_update_every(uint32_t full_update_every) {
426  this->full_update_every_ = full_update_every;
427 }
428 
430  switch (this->model_) {
432  return 2500;
433  default:
435  }
436 }
437 
438 // ========================================================
439 // Type B
440 // ========================================================
441 // Datasheet:
442 // - https://www.waveshare.com/w/upload/7/7f/4.2inch-e-paper-b-specification.pdf
443 // - https://github.com/soonuse/epd-library-arduino/blob/master/4.2inch_e-paper/epd4in2/
444 
445 static const uint8_t LUT_VCOM_DC_2_7[44] = {
446  0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x00, 0x32, 0x32, 0x00, 0x00, 0x02, 0x00,
447  0x0F, 0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 };
450 
451 static const uint8_t LUT_WHITE_TO_WHITE_2_7[42] = {
452  0x50, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0xA0, 0x0F,
453  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455 };
456 
457 static const uint8_t LUT_BLACK_TO_WHITE_2_7[42] = {
458  0x50, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0xA0, 0x0F,
459  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
461 };
462 
463 static const uint8_t LUT_WHITE_TO_BLACK_2_7[] = {
464  0xA0, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0x50, 0x0F,
465  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467 };
468 
469 static const uint8_t LUT_BLACK_TO_BLACK_2_7[42] = {
470  0xA0, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0x50, 0x0F,
471  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 };
474 
476  // command power setting
477  this->command(0x01);
478  this->data(0x03); // VDS_EN, VDG_EN
479  this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
480  this->data(0x2B); // VDH
481  this->data(0x2B); // VDL
482  this->data(0x09); // VDHR
483 
484  // command booster soft start
485  this->command(0x06);
486  this->data(0x07);
487  this->data(0x07);
488  this->data(0x17);
489 
490  // Power optimization - ???
491  this->command(0xF8);
492  this->data(0x60);
493  this->data(0xA5);
494  this->command(0xF8);
495  this->data(0x89);
496  this->data(0xA5);
497  this->command(0xF8);
498  this->data(0x90);
499  this->data(0x00);
500  this->command(0xF8);
501  this->data(0x93);
502  this->data(0x2A);
503  this->command(0xF8);
504  this->data(0xA0);
505  this->data(0xA5);
506  this->command(0xF8);
507  this->data(0xA1);
508  this->data(0x00);
509  this->command(0xF8);
510  this->data(0x73);
511  this->data(0x41);
512 
513  // command partial display refresh
514  this->command(0x16);
515  this->data(0x00);
516 
517  // command power on
518  this->command(0x04);
519  this->wait_until_idle_();
520  delay(10);
521 
522  // Command panel setting
523  this->command(0x00);
524  this->data(0xAF); // KW-BF KWR-AF BWROTP 0f
525  // command pll control
526  this->command(0x30);
527  this->data(0x3A); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
528  // COMMAND VCM DC SETTING
529  this->command(0x82);
530  this->data(0x12);
531 
532  delay(2);
533  // COMMAND LUT FOR VCOM
534  this->command(0x20);
535  for (uint8_t i : LUT_VCOM_DC_2_7)
536  this->data(i);
537 
538  // COMMAND LUT WHITE TO WHITE
539  this->command(0x21);
540  for (uint8_t i : LUT_WHITE_TO_WHITE_2_7)
541  this->data(i);
542  // COMMAND LUT BLACK TO WHITE
543  this->command(0x22);
544  for (uint8_t i : LUT_BLACK_TO_WHITE_2_7)
545  this->data(i);
546  // COMMAND LUT WHITE TO BLACK
547  this->command(0x23);
548  for (uint8_t i : LUT_WHITE_TO_BLACK_2_7)
549  this->data(i);
550  // COMMAND LUT BLACK TO BLACK
551  this->command(0x24);
552  for (uint8_t i : LUT_BLACK_TO_BLACK_2_7)
553  this->data(i);
554 }
556  uint32_t buf_len = this->get_buffer_length_();
557 
558  // COMMAND DATA START TRANSMISSION 1
559  this->command(0x10);
560  delay(2);
561  for (uint32_t i = 0; i < buf_len; i++) {
562  this->data(this->buffer_[i]);
563  }
564  delay(2);
565 
566  // COMMAND DATA START TRANSMISSION 2
567  this->command(0x13);
568  delay(2);
569  for (uint32_t i = 0; i < buf_len; i++) {
570  this->data(this->buffer_[i]);
571  }
572 
573  // COMMAND DISPLAY REFRESH
574  this->command(0x12);
575 }
579  LOG_DISPLAY("", "Waveshare E-Paper", this);
580  ESP_LOGCONFIG(TAG, " Model: 2.7in");
581  LOG_PIN(" Reset Pin: ", this->reset_pin_);
582  LOG_PIN(" DC Pin: ", this->dc_pin_);
583  LOG_PIN(" Busy Pin: ", this->busy_pin_);
584  LOG_UPDATE_INTERVAL(this);
585 }
586 
587 // ========================================================
588 // 2.90in Type B (LUT from OTP)
589 // Datasheet:
590 // - https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf
591 // - https://github.com/soonuse/epd-library-arduino/blob/master/2.9inch_e-paper_b/epd2in9b/epd2in9b.cpp
592 // ========================================================
593 
595  // from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37
596  // EPD hardware init start
597  this->reset_();
598 
599  // COMMAND BOOSTER SOFT START
600  this->command(0x06);
601  this->data(0x17);
602  this->data(0x17);
603  this->data(0x17);
604 
605  // COMMAND POWER ON
606  this->command(0x04);
607  this->wait_until_idle_();
608 
609  // COMMAND PANEL SETTING
610  this->command(0x00);
611  // 128x296 resolution: 10
612  // LUT from OTP: 0
613  // B/W mode (doesn't work): 1
614  // scan-up: 1
615  // shift-right: 1
616  // booster ON: 1
617  // no soft reset: 1
618  this->data(0x9F);
619 
620  // COMMAND RESOLUTION SETTING
621  // set to 128x296 by COMMAND PANEL SETTING
622 
623  // COMMAND VCOM AND DATA INTERVAL SETTING
624  // use defaults for white border and ESPHome image polarity
625 
626  // EPD hardware init end
627 }
629  // COMMAND DATA START TRANSMISSION 1 (B/W data)
630  this->command(0x10);
631  delay(2);
632  this->start_data_();
633  this->write_array(this->buffer_, this->get_buffer_length_());
634  this->end_data_();
635  delay(2);
636 
637  // COMMAND DATA START TRANSMISSION 2 (RED data)
638  this->command(0x13);
639  delay(2);
640  this->start_data_();
641  for (size_t i = 0; i < this->get_buffer_length_(); i++)
642  this->write_byte(0x00);
643  this->end_data_();
644  delay(2);
645 
646  // COMMAND DISPLAY REFRESH
647  this->command(0x12);
648  delay(2);
649  this->wait_until_idle_();
650 
651  // COMMAND POWER OFF
652  // NOTE: power off < deep sleep
653  this->command(0x02);
654 }
658  LOG_DISPLAY("", "Waveshare E-Paper", this);
659  ESP_LOGCONFIG(TAG, " Model: 2.9in (B)");
660  LOG_PIN(" Reset Pin: ", this->reset_pin_);
661  LOG_PIN(" DC Pin: ", this->dc_pin_);
662  LOG_PIN(" Busy Pin: ", this->busy_pin_);
663  LOG_UPDATE_INTERVAL(this);
664 }
665 
666 static const uint8_t LUT_VCOM_DC_4_2[] = {
667  0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x17, 0x17, 0x00, 0x00, 0x02, 0x00, 0x0A, 0x01,
668  0x00, 0x00, 0x01, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670 };
671 static const uint8_t LUT_WHITE_TO_WHITE_4_2[] = {
672  0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A,
673  0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
674  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675 };
676 static const uint8_t LUT_BLACK_TO_WHITE_4_2[] = {
677  0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A,
678  0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
679  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680 };
681 
682 static const uint8_t LUT_BLACK_TO_BLACK_4_2[] = {
683  0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A,
684  0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
685  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686 };
687 
688 static const uint8_t LUT_WHITE_TO_BLACK_4_2[] = {
689  0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A,
690  0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
691  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
692 };
693 
695  // https://www.waveshare.com/w/upload/7/7f/4.2inch-e-paper-b-specification.pdf - page 8
696 
697  // COMMAND POWER SETTING
698  this->command(0x01);
699  this->data(0x03); // VDS_EN, VDG_EN
700  this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
701  this->data(0x2B); // VDH
702  this->data(0x2B); // VDL
703  this->data(0xFF); // VDHR
704 
705  // COMMAND BOOSTER SOFT START
706  this->command(0x06);
707  this->data(0x17); // PHA
708  this->data(0x17); // PHB
709  this->data(0x17); // PHC
710 
711  // COMMAND POWER ON
712  this->command(0x04);
713  this->wait_until_idle_();
714  delay(10);
715  // COMMAND PANEL SETTING
716  this->command(0x00);
717  this->data(0xBF); // KW-BF KWR-AF BWROTP 0f
718  this->data(0x0B);
719  // COMMAND PLL CONTROL
720  this->command(0x30);
721  this->data(0x3C); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
722 
723  delay(2);
724  // COMMAND LUT FOR VCOM
725  this->command(0x20);
726  for (uint8_t i : LUT_VCOM_DC_4_2)
727  this->data(i);
728  // COMMAND LUT WHITE TO WHITE
729  this->command(0x21);
730  for (uint8_t i : LUT_WHITE_TO_WHITE_4_2)
731  this->data(i);
732  // COMMAND LUT BLACK TO WHITE
733  this->command(0x22);
734  for (uint8_t i : LUT_BLACK_TO_WHITE_4_2)
735  this->data(i);
736  // COMMAND LUT WHITE TO BLACK
737  this->command(0x23);
738  for (uint8_t i : LUT_WHITE_TO_BLACK_4_2)
739  this->data(i);
740  // COMMAND LUT BLACK TO BLACK
741  this->command(0x24);
742  for (uint8_t i : LUT_BLACK_TO_BLACK_4_2)
743  this->data(i);
744 }
746  // COMMAND RESOLUTION SETTING
747  this->command(0x61);
748  this->data(0x01);
749  this->data(0x90);
750  this->data(0x01);
751  this->data(0x2C);
752 
753  // COMMAND VCM DC SETTING REGISTER
754  this->command(0x82);
755  this->data(0x12);
756 
757  // COMMAND VCOM AND DATA INTERVAL SETTING
758  this->command(0x50);
759  this->data(0x97);
760 
761  // COMMAND DATA START TRANSMISSION 1
762  this->command(0x10);
763  delay(2);
764  this->start_data_();
765  this->write_array(this->buffer_, this->get_buffer_length_());
766  this->end_data_();
767  delay(2);
768  // COMMAND DATA START TRANSMISSION 2
769  this->command(0x13);
770  delay(2);
771  this->start_data_();
772  this->write_array(this->buffer_, this->get_buffer_length_());
773  this->end_data_();
774  // COMMAND DISPLAY REFRESH
775  this->command(0x12);
776 }
780  LOG_DISPLAY("", "Waveshare E-Paper", this);
781  ESP_LOGCONFIG(TAG, " Model: 4.2in");
782  LOG_PIN(" Reset Pin: ", this->reset_pin_);
783  LOG_PIN(" DC Pin: ", this->dc_pin_);
784  LOG_PIN(" Busy Pin: ", this->busy_pin_);
785  LOG_UPDATE_INTERVAL(this);
786 }
787 
788 // ========================================================
789 // 4.20in Type B (LUT from OTP)
790 // Datasheet:
791 // - https://www.waveshare.com/w/upload/2/20/4.2inch-e-paper-module-user-manual-en.pdf
792 // - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_4in2b_V2.c
793 // ========================================================
795  // these exact timings are required for a proper reset/init
796  this->reset_pin_->digital_write(false);
797  delay(2);
798  this->reset_pin_->digital_write(true);
799  delay(200); // NOLINT
800 
801  // COMMAND POWER ON
802  this->command(0x04);
803  this->wait_until_idle_();
804 
805  // COMMAND PANEL SETTING
806  this->command(0x00);
807  this->data(0x0f); // LUT from OTP
808 }
809 
811  // COMMAND DATA START TRANSMISSION 1 (B/W data)
812  this->command(0x10);
813  this->start_data_();
814  this->write_array(this->buffer_, this->get_buffer_length_());
815  this->end_data_();
816 
817  // COMMAND DATA START TRANSMISSION 2 (RED data)
818  this->command(0x13);
819  this->start_data_();
820  for (size_t i = 0; i < this->get_buffer_length_(); i++)
821  this->write_byte(0xFF);
822  this->end_data_();
823  delay(2);
824 
825  // COMMAND DISPLAY REFRESH
826  this->command(0x12);
827  this->wait_until_idle_();
828 
829  // COMMAND POWER OFF
830  // NOTE: power off < deep sleep
831  this->command(0x02);
832 }
836  LOG_DISPLAY("", "Waveshare E-Paper", this);
837  ESP_LOGCONFIG(TAG, " Model: 4.2in (B V2)");
838  LOG_PIN(" Reset Pin: ", this->reset_pin_);
839  LOG_PIN(" DC Pin: ", this->dc_pin_);
840  LOG_PIN(" Busy Pin: ", this->busy_pin_);
841  LOG_UPDATE_INTERVAL(this);
842 }
843 
845  // COMMAND POWER SETTING
846  this->command(0x01);
847  this->data(0x37);
848  this->data(0x00);
849 
850  // COMMAND PANEL SETTING
851  this->command(0x00);
852  this->data(0xCF);
853  this->data(0x0B);
854 
855  // COMMAND BOOSTER SOFT START
856  this->command(0x06);
857  this->data(0xC7);
858  this->data(0xCC);
859  this->data(0x28);
860 
861  // COMMAND POWER ON
862  this->command(0x04);
863  this->wait_until_idle_();
864  delay(10);
865 
866  // COMMAND PLL CONTROL
867  this->command(0x30);
868  this->data(0x3C);
869 
870  // COMMAND TEMPERATURE SENSOR CALIBRATION
871  this->command(0x41);
872  this->data(0x00);
873 
874  // COMMAND VCOM AND DATA INTERVAL SETTING
875  this->command(0x50);
876  this->data(0x77);
877 
878  // COMMAND TCON SETTING
879  this->command(0x60);
880  this->data(0x22);
881 
882  // COMMAND RESOLUTION SETTING
883  this->command(0x61);
884  this->data(0x02);
885  this->data(0x58);
886  this->data(0x01);
887  this->data(0xC0);
888 
889  // COMMAND VCM DC SETTING REGISTER
890  this->command(0x82);
891  this->data(0x1E);
892 
893  this->command(0xE5);
894  this->data(0x03);
895 }
897  // COMMAND DATA START TRANSMISSION 1
898  this->command(0x10);
899 
900  this->start_data_();
901  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
902  uint8_t temp1 = this->buffer_[i];
903  for (uint8_t j = 0; j < 8; j++) {
904  uint8_t temp2;
905  if (temp1 & 0x80) {
906  temp2 = 0x03;
907  } else {
908  temp2 = 0x00;
909  }
910 
911  temp2 <<= 4;
912  temp1 <<= 1;
913  j++;
914  if (temp1 & 0x80) {
915  temp2 |= 0x03;
916  } else {
917  temp2 |= 0x00;
918  }
919  temp1 <<= 1;
920  this->write_byte(temp2);
921  }
922 
923  App.feed_wdt();
924  }
925  this->end_data_();
926 
927  // COMMAND DISPLAY REFRESH
928  this->command(0x12);
929 }
933  LOG_DISPLAY("", "Waveshare E-Paper", this);
934  ESP_LOGCONFIG(TAG, " Model: 5.83in");
935  LOG_PIN(" Reset Pin: ", this->reset_pin_);
936  LOG_PIN(" DC Pin: ", this->dc_pin_);
937  LOG_PIN(" Busy Pin: ", this->busy_pin_);
938  LOG_UPDATE_INTERVAL(this);
939 }
941  // COMMAND POWER SETTING
942  this->command(0x01);
943  this->data(0x07);
944  this->data(0x07); // VGH=20V,VGL=-20V
945  this->data(0x3f); // VDH=15V
946  this->data(0x3f); // VDL=-15V
947  // COMMAND POWER ON
948  this->command(0x04);
949  delay(100); // NOLINT
950  this->wait_until_idle_();
951  // COMMAND PANEL SETTING
952  this->command(0x00);
953  this->data(0x0F); // KW3f, KWR-2F, BWROTP 0f, BWOTP 1f
954  this->command(0x61); // tres
955  this->data(0x03); // 800px
956  this->data(0x20);
957  this->data(0x01); // 400px
958  this->data(0xE0);
959  this->command(0x15);
960  this->data(0x00);
961  // COMMAND VCOM AND DATA INTERVAL SETTING
962  this->command(0x50);
963  this->data(0x11);
964  this->data(0x07);
965  // COMMAND TCON SETTING
966  this->command(0x60);
967  this->data(0x22);
968  // COMMAND RESOLUTION SETTING
969  this->command(0x65);
970  this->data(0x00);
971  this->data(0x00); // 800*480
972  this->data(0x00);
973  this->data(0x00);
974 }
976  // COMMAND DATA START TRANSMISSION 1 (B/W data)
977  this->command(0x10);
978  delay(2);
979  this->start_data_();
980  this->write_array(this->buffer_, this->get_buffer_length_());
981  this->end_data_();
982  delay(2);
983 
984  // COMMAND DATA START TRANSMISSION 2 (RED data)
985  this->command(0x13);
986  delay(2);
987  this->start_data_();
988  for (size_t i = 0; i < this->get_buffer_length_(); i++)
989  this->write_byte(0x00);
990  this->end_data_();
991  delay(2);
992 
993  // COMMAND DISPLAY REFRESH
994  this->command(0x12);
995  delay(100); // NOLINT
996  this->wait_until_idle_();
997 }
1001  LOG_DISPLAY("", "Waveshare E-Paper", this);
1002  ESP_LOGCONFIG(TAG, " Model: 7.5in-bv2");
1003  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1004  LOG_PIN(" DC Pin: ", this->dc_pin_);
1005  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1006  LOG_UPDATE_INTERVAL(this);
1007 }
1009  // COMMAND POWER SETTING
1010  this->command(0x01);
1011  this->data(0x37);
1012  this->data(0x00);
1013  // COMMAND PANEL SETTING
1014  this->command(0x00);
1015  this->data(0xCF);
1016  this->data(0x0B);
1017  // COMMAND BOOSTER SOFT START
1018  this->command(0x06);
1019  this->data(0xC7);
1020  this->data(0xCC);
1021  this->data(0x28);
1022  // COMMAND POWER ON
1023  this->command(0x04);
1024  this->wait_until_idle_();
1025  delay(10);
1026  // COMMAND PLL CONTROL
1027  this->command(0x30);
1028  this->data(0x3C);
1029  // COMMAND TEMPERATURE SENSOR CALIBRATION
1030  this->command(0x41);
1031  this->data(0x00);
1032  // COMMAND VCOM AND DATA INTERVAL SETTING
1033  this->command(0x50);
1034  this->data(0x77);
1035  // COMMAND TCON SETTING
1036  this->command(0x60);
1037  this->data(0x22);
1038  // COMMAND RESOLUTION SETTING
1039  this->command(0x61);
1040  this->data(0x02);
1041  this->data(0x80);
1042  this->data(0x01);
1043  this->data(0x80);
1044  // COMMAND VCM DC SETTING REGISTER
1045  this->command(0x82);
1046  this->data(0x1E);
1047  this->command(0xE5);
1048  this->data(0x03);
1049 }
1051  // COMMAND DATA START TRANSMISSION 1
1052  this->command(0x10);
1053  this->start_data_();
1054  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
1055  uint8_t temp1 = this->buffer_[i];
1056  for (uint8_t j = 0; j < 8; j++) {
1057  uint8_t temp2;
1058  if (temp1 & 0x80) {
1059  temp2 = 0x03;
1060  } else {
1061  temp2 = 0x00;
1062  }
1063  temp2 <<= 4;
1064  temp1 <<= 1;
1065  j++;
1066  if (temp1 & 0x80) {
1067  temp2 |= 0x03;
1068  } else {
1069  temp2 |= 0x00;
1070  }
1071  temp1 <<= 1;
1072  this->write_byte(temp2);
1073  }
1074  App.feed_wdt();
1075  }
1076  this->end_data_();
1077  // COMMAND DISPLAY REFRESH
1078  this->command(0x12);
1079 }
1083  LOG_DISPLAY("", "Waveshare E-Paper", this);
1084  ESP_LOGCONFIG(TAG, " Model: 7.5in");
1085  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1086  LOG_PIN(" DC Pin: ", this->dc_pin_);
1087  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1088  LOG_UPDATE_INTERVAL(this);
1089 }
1091  // COMMAND POWER SETTING
1092  this->command(0x01);
1093  this->data(0x07);
1094  this->data(0x07);
1095  this->data(0x3f);
1096  this->data(0x3f);
1097  this->command(0x04);
1098 
1099  delay(100); // NOLINT
1100  this->wait_until_idle_();
1101  // COMMAND PANEL SETTING
1102  this->command(0x00);
1103  this->data(0x1F);
1104 
1105  // COMMAND RESOLUTION SETTING
1106  this->command(0x61);
1107  this->data(0x03);
1108  this->data(0x20);
1109  this->data(0x01);
1110  this->data(0xE0);
1111  // COMMAND ...?
1112  this->command(0x15);
1113  this->data(0x00);
1114  // COMMAND VCOM AND DATA INTERVAL SETTING
1115  this->command(0x50);
1116  this->data(0x10);
1117  this->data(0x07);
1118  // COMMAND TCON SETTING
1119  this->command(0x60);
1120  this->data(0x22);
1121 }
1123  uint32_t buf_len = this->get_buffer_length_();
1124  // COMMAND DATA START TRANSMISSION NEW DATA
1125  this->command(0x13);
1126  delay(2);
1127  for (uint32_t i = 0; i < buf_len; i++) {
1128  this->data(~(this->buffer_[i]));
1129  }
1130 
1131  // COMMAND DISPLAY REFRESH
1132  this->command(0x12);
1133  delay(100); // NOLINT
1134  this->wait_until_idle_();
1135 }
1136 
1140  LOG_DISPLAY("", "Waveshare E-Paper", this);
1141  ESP_LOGCONFIG(TAG, " Model: 7.5inV2rev2");
1142  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1143  LOG_PIN(" DC Pin: ", this->dc_pin_);
1144  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1145  LOG_UPDATE_INTERVAL(this);
1146 }
1147 
1148 /* 7.50inV2alt */
1150  if (this->busy_pin_ == nullptr) {
1151  return true;
1152  }
1153 
1154  const uint32_t start = millis();
1155  while (this->busy_pin_->digital_read()) {
1156  this->command(0x71);
1157  if (millis() - start > this->idle_timeout_()) {
1158  ESP_LOGI(TAG, "Timeout while displaying image!");
1159  return false;
1160  }
1161  delay(10);
1162  }
1163  return true;
1164 }
1165 
1167  this->reset_();
1168 
1169  // COMMAND POWER SETTING
1170  this->command(0x01);
1171 
1172  // 1-0=11: internal power
1173  this->data(0x17);
1174 
1175  this->data(0x17); // VGH&VGL
1176  this->data(0x3F); // VSH
1177  this->data(0x3F); // VSL
1178  this->data(0x11); // VSHR
1179 
1180  // VCOM DC Setting
1181  this->command(0x82);
1182  this->data(0x24); // VCOM
1183 
1184  // Booster Setting
1185  this->command(0x06);
1186  this->data(0x27);
1187  this->data(0x27);
1188  this->data(0x2F);
1189  this->data(0x17);
1190 
1191  // OSC Setting
1192  this->command(0x30);
1193  this->data(0x06); // 2-0=100: N=4 ; 5-3=111: M=7 ; 3C=50Hz 3A=100HZ
1194 
1195  // POWER ON
1196  this->command(0x04);
1197 
1198  delay(100); // NOLINT
1199  this->wait_until_idle_();
1200  // COMMAND PANEL SETTING
1201  this->command(0x00);
1202  this->data(0x3F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
1203 
1204  // COMMAND RESOLUTION SETTING
1205  this->command(0x61);
1206  this->data(0x03); // source 800
1207  this->data(0x20);
1208  this->data(0x01); // gate 480
1209  this->data(0xE0);
1210  // COMMAND ...?
1211  this->command(0x15);
1212  this->data(0x00);
1213  // COMMAND VCOM AND DATA INTERVAL SETTING
1214  this->command(0x50);
1215  this->data(0x10);
1216  this->data(0x07);
1217  // COMMAND TCON SETTING
1218  this->command(0x60);
1219  this->data(0x22);
1220  // Resolution setting
1221  this->command(0x65);
1222  this->data(0x00);
1223  this->data(0x00); // 800*480
1224  this->data(0x00);
1225  this->data(0x00);
1226 
1227  this->wait_until_idle_();
1228 
1229  uint8_t lut_vcom_7_i_n5_v2[] = {
1230  0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0xF, 0x1, 0xF, 0x1, 0x2, 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
1231  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1232  };
1233 
1234  uint8_t lut_ww_7_i_n5_v2[] = {
1235  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
1236  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1237  };
1238 
1239  uint8_t lut_bw_7_i_n5_v2[] = {
1240  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
1241  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1242  };
1243 
1244  uint8_t lut_wb_7_i_n5_v2[] = {
1245  0x80, 0xF, 0xF, 0x0, 0x0, 0x3, 0x84, 0xF, 0x1, 0xF, 0x1, 0x4, 0x40, 0xF, 0xF, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
1246  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1247  };
1248 
1249  uint8_t lut_bb_7_i_n5_v2[] = {
1250  0x80, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x40, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
1251  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1252  };
1253 
1254  uint8_t count;
1255  this->command(0x20); // VCOM
1256  for (count = 0; count < 42; count++)
1257  this->data(lut_vcom_7_i_n5_v2[count]);
1258 
1259  this->command(0x21); // LUTBW
1260  for (count = 0; count < 42; count++)
1261  this->data(lut_ww_7_i_n5_v2[count]);
1262 
1263  this->command(0x22); // LUTBW
1264  for (count = 0; count < 42; count++)
1265  this->data(lut_bw_7_i_n5_v2[count]);
1266 
1267  this->command(0x23); // LUTWB
1268  for (count = 0; count < 42; count++)
1269  this->data(lut_wb_7_i_n5_v2[count]);
1270 
1271  this->command(0x24); // LUTBB
1272  for (count = 0; count < 42; count++)
1273  this->data(lut_bb_7_i_n5_v2[count]);
1274 }
1275 
1277  LOG_DISPLAY("", "Waveshare E-Paper", this);
1278  ESP_LOGCONFIG(TAG, " Model: 7.5inV2");
1279  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1280  LOG_PIN(" DC Pin: ", this->dc_pin_);
1281  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1282  LOG_UPDATE_INTERVAL(this);
1283 }
1284 
1285 /* 7.50in-bc */
1287  /* The command sequence is similar to the 7P5In display but differs in subtle ways
1288  to allow for faster updates. */
1289  // COMMAND POWER SETTING
1290  this->command(0x01);
1291  this->data(0x37);
1292  this->data(0x00);
1293 
1294  // COMMAND PANEL SETTING
1295  this->command(0x00);
1296  this->data(0xCF);
1297  this->data(0x08);
1298 
1299  // COMMAND PLL CONTROL
1300  this->command(0x30);
1301  this->data(0x3A);
1302 
1303  // COMMAND VCM_DC_SETTING: all temperature range
1304  this->command(0x82);
1305  this->data(0x28);
1306 
1307  // COMMAND BOOSTER SOFT START
1308  this->command(0x06);
1309  this->data(0xC7);
1310  this->data(0xCC);
1311  this->data(0x15);
1312 
1313  // COMMAND VCOM AND DATA INTERVAL SETTING
1314  this->command(0x50);
1315  this->data(0x77);
1316 
1317  // COMMAND TCON SETTING
1318  this->command(0x60);
1319  this->data(0x22);
1320 
1321  // COMMAND FLASH CONTROL
1322  this->command(0x65);
1323  this->data(0x00);
1324 
1325  // COMMAND RESOLUTION SETTING
1326  this->command(0x61);
1327  this->data(0x02); // 640 >> 8
1328  this->data(0x80);
1329  this->data(0x01); // 384 >> 8
1330  this->data(0x80);
1331 
1332  // COMMAND FLASH MODE
1333  this->command(0xE5);
1334  this->data(0x03);
1335 }
1336 
1338  // COMMAND DATA START TRANSMISSION 1
1339  this->command(0x10);
1340  this->start_data_();
1341 
1342  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
1343  // A line of eight source pixels (each a bit in this byte)
1344  uint8_t eight_pixels = this->buffer_[i];
1345 
1346  for (uint8_t j = 0; j < 8; j += 2) {
1347  /* For bichromatic displays, each byte represents two pixels. Each nibble encodes a pixel: 0=white, 3=black,
1348  4=color. Therefore, e.g. 0x44 = two adjacent color pixels, 0x33 is two adjacent black pixels, etc. If you want
1349  to draw using the color pixels, change '0x30' with '0x40' and '0x03' with '0x04' below. */
1350  uint8_t left_nibble = (eight_pixels & 0x80) ? 0x30 : 0x00;
1351  eight_pixels <<= 1;
1352  uint8_t right_nibble = (eight_pixels & 0x80) ? 0x03 : 0x00;
1353  eight_pixels <<= 1;
1354  this->write_byte(left_nibble | right_nibble);
1355  }
1356  App.feed_wdt();
1357  }
1358  this->end_data_();
1359 
1360  // Unlike the 7P5In display, we send the "power on" command here rather than during initialization
1361  // COMMAND POWER ON
1362  this->command(0x04);
1363 
1364  // COMMAND DISPLAY REFRESH
1365  this->command(0x12);
1366 }
1367 
1369 
1371 
1373  LOG_DISPLAY("", "Waveshare E-Paper", this);
1374  ESP_LOGCONFIG(TAG, " Model: 7.5in-bc");
1375  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1376  LOG_PIN(" DC Pin: ", this->dc_pin_);
1377  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1378  LOG_UPDATE_INTERVAL(this);
1379 }
1380 
1382  this->command(0x12); // SWRESET
1383 
1384  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
1385 
1386  this->command(0x46); // Auto Write RAM
1387  this->data(0xF7);
1388 
1389  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
1390 
1391  this->command(0x47); // Auto Write RAM
1392  this->data(0xF7);
1393 
1394  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
1395 
1396  this->command(0x0C); // Soft start setting
1397  this->data(0xAE);
1398  this->data(0xC7);
1399  this->data(0xC3);
1400  this->data(0xC0);
1401  this->data(0x40);
1402 
1403  this->command(0x01); // Set MUX as 527
1404  this->data(0xAF);
1405  this->data(0x02);
1406  this->data(0x01);
1407 
1408  this->command(0x11); // Data entry mode
1409  this->data(0x01);
1410 
1411  this->command(0x44);
1412  this->data(0x00); // RAM x address start at 0
1413  this->data(0x00);
1414  this->data(0x6F); // RAM x address end at 36Fh -> 879
1415  this->data(0x03);
1416 
1417  this->command(0x45);
1418  this->data(0xAF); // RAM y address start at 20Fh;
1419  this->data(0x02);
1420  this->data(0x00); // RAM y address end at 00h;
1421  this->data(0x00);
1422 
1423  this->command(0x3C); // VBD
1424  this->data(0x01); // LUT1, for white
1425 
1426  this->command(0x18);
1427  this->data(0X80);
1428 
1429  this->command(0x22);
1430  this->data(0XB1); // Load Temperature and waveform setting.
1431 
1432  this->command(0x20);
1433 
1434  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
1435 
1436  this->command(0x4E);
1437  this->data(0x00);
1438  this->data(0x00);
1439 
1440  this->command(0x4F);
1441  this->data(0xAF);
1442  this->data(0x02);
1443 }
1444 
1446  this->command(0x4F);
1447  this->data(0xAf);
1448  this->data(0x02);
1449 
1450  // BLACK
1451  this->command(0x24);
1452  this->start_data_();
1453  this->write_array(this->buffer_, this->get_buffer_length_());
1454  this->end_data_();
1455 
1456  // RED
1457  this->command(0x26);
1458  this->start_data_();
1459  for (size_t i = 0; i < this->get_buffer_length_(); i++)
1460  this->write_byte(0x00);
1461  this->end_data_();
1462 
1463  this->command(0x22);
1464  this->data(0xC7);
1465  this->command(0x20);
1466  delay(100); // NOLINT
1467 }
1468 
1470 
1472 
1474  LOG_DISPLAY("", "Waveshare E-Paper", this);
1475  ESP_LOGCONFIG(TAG, " Model: 7.5in-HD-b");
1476  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1477  LOG_PIN(" DC Pin: ", this->dc_pin_);
1478  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1479  LOG_UPDATE_INTERVAL(this);
1480 }
1481 
1482 static const uint8_t LUT_SIZE_TTGO_DKE_PART = 153;
1483 
1484 static const uint8_t PART_UPDATE_LUT_TTGO_DKE[LUT_SIZE_TTGO_DKE_PART] = {
1485  0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1486  0x0, 0x0, 0x0, 0x0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0,
1487  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1488  0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1489  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1490  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1491  0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1492  0x0, 0x0, 0x0, 0x0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
1493  // 0x22, 0x17, 0x41, 0x0, 0x32, 0x32
1494 };
1495 
1498  bool partial = this->at_update_ != 0;
1499  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
1500 
1501  if (partial) {
1502  ESP_LOGI(TAG, "Performing partial e-paper update.");
1503  } else {
1504  ESP_LOGI(TAG, "Performing full e-paper update.");
1505  }
1506 
1507  // start and set up data format
1508  this->command(0x12);
1509  this->wait_until_idle_();
1510 
1511  this->command(0x11);
1512  this->data(0x03);
1513  this->command(0x44);
1514  this->data(1);
1515  this->data(this->get_width_internal() / 8);
1516  this->command(0x45);
1517  this->data(0);
1518  this->data(0);
1519  this->data(this->get_height_internal());
1520  this->data(0);
1521  this->command(0x4e);
1522  this->data(1);
1523  this->command(0x4f);
1524  this->data(0);
1525  this->data(0);
1526 
1527  if (!partial) {
1528  // send data
1529  this->command(0x24);
1530  this->start_data_();
1531  this->write_array(this->buffer_, this->get_buffer_length_());
1532  this->end_data_();
1533 
1534  // commit
1535  this->command(0x20);
1536  this->wait_until_idle_();
1537  } else {
1538  // set up partial update
1539  this->command(0x32);
1540  for (uint8_t v : PART_UPDATE_LUT_TTGO_DKE)
1541  this->data(v);
1542  this->command(0x3F);
1543  this->data(0x22);
1544 
1545  this->command(0x03);
1546  this->data(0x17);
1547  this->command(0x04);
1548  this->data(0x41);
1549  this->data(0x00);
1550  this->data(0x32);
1551  this->command(0x2C);
1552  this->data(0x32);
1553 
1554  this->command(0x37);
1555  this->data(0x00);
1556  this->data(0x00);
1557  this->data(0x00);
1558  this->data(0x00);
1559  this->data(0x00);
1560  this->data(0x40);
1561  this->data(0x00);
1562  this->data(0x00);
1563  this->data(0x00);
1564  this->data(0x00);
1565 
1566  this->command(0x3C);
1567  this->data(0x80);
1568  this->command(0x22);
1569  this->data(0xC0);
1570  this->command(0x20);
1571  this->wait_until_idle_();
1572 
1573  // send data
1574  this->command(0x24);
1575  this->start_data_();
1576  this->write_array(this->buffer_, this->get_buffer_length_());
1577  this->end_data_();
1578 
1579  // commit as partial
1580  this->command(0x22);
1581  this->data(0xCF);
1582  this->command(0x20);
1583  this->wait_until_idle_();
1584 
1585  // data must be sent again on partial update
1586  delay(300); // NOLINT
1587  this->command(0x24);
1588  this->start_data_();
1589  this->write_array(this->buffer_, this->get_buffer_length_());
1590  this->end_data_();
1591  delay(300); // NOLINT
1592  }
1593 
1594  ESP_LOGI(TAG, "Completed e-paper update.");
1595 }
1596 
1599 uint32_t WaveshareEPaper2P13InDKE::idle_timeout_() { return 5000; }
1601  LOG_DISPLAY("", "Waveshare E-Paper", this);
1602  ESP_LOGCONFIG(TAG, " Model: 2.13inDKE");
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 void WaveshareEPaper2P13InDKE::set_full_update_every(uint32_t full_update_every) {
1610  this->full_update_every_ = full_update_every;
1611 }
1612 
1613 } // namespace waveshare_epaper
1614 } // namespace esphome
virtual void digital_write(bool value)=0
void write_lut_(const uint8_t *lut, uint8_t size)
void draw_absolute_pixel_internal(int x, int y, Color color) override
void set_full_update_every(uint32_t full_update_every)
virtual int get_width_internal()=0
WaveshareEPaperTypeA(WaveshareEPaperTypeAModel model)
virtual void setup()=0
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:26
void init_internal_(uint32_t buffer_length)
void status_clear_warning()
Definition: component.cpp:148
const float PROCESSOR
For components that use data from sensors like displays.
Definition: component.cpp:19
Application App
Global storage of Application pointer - only one Application can exist.
void status_set_warning()
Definition: component.cpp:140
virtual bool digital_read()=0
virtual int get_height_internal()=0
Definition: a4988.cpp:4
bool is_on() ALWAYS_INLINE
Definition: color.h:46
void set_full_update_every(uint32_t full_update_every)
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:27