ESPHome  2023.11.6
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 
87  this->init_internal_(this->get_buffer_length_());
88  this->dc_pin_->setup(); // OUTPUT
89  this->dc_pin_->digital_write(false);
90  if (this->reset_pin_ != nullptr) {
91  this->reset_pin_->setup(); // OUTPUT
92  this->reset_pin_->digital_write(true);
93  }
94  if (this->busy_pin_ != nullptr) {
95  this->busy_pin_->setup(); // INPUT
96  }
97  this->spi_setup();
98 
99  this->reset_();
100 }
102 void WaveshareEPaper::command(uint8_t value) {
103  this->start_command_();
104  this->write_byte(value);
105  this->end_command_();
106 }
107 void WaveshareEPaper::data(uint8_t value) {
108  this->start_data_();
109  this->write_byte(value);
110  this->end_data_();
111 }
113  if (this->busy_pin_ == nullptr) {
114  return true;
115  }
116 
117  const uint32_t start = millis();
118  while (this->busy_pin_->digital_read()) {
119  if (millis() - start > this->idle_timeout_()) {
120  ESP_LOGE(TAG, "Timeout while displaying image!");
121  return false;
122  }
123  delay(10);
124  }
125  return true;
126 }
128  this->do_update_();
129  this->display();
130 }
132  // flip logic
133  const uint8_t fill = color.is_on() ? 0x00 : 0xFF;
134  for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
135  this->buffer_[i] = fill;
136 }
138  if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
139  return;
140 
141  const uint32_t pos = (x + y * this->get_width_controller()) / 8u;
142  const uint8_t subpos = x & 0x07;
143  // flip logic
144  if (!color.is_on()) {
145  this->buffer_[pos] |= 0x80 >> subpos;
146  } else {
147  this->buffer_[pos] &= ~(0x80 >> subpos);
148  }
149 }
151  return this->get_width_controller() * this->get_height_internal() / 8u;
152 }
154  this->dc_pin_->digital_write(false);
155  this->enable();
156 }
159  this->dc_pin_->digital_write(true);
160  this->enable();
161 }
164 
165 // ========================================================
166 // Type A
167 // ========================================================
168 
170  if (this->model_ == TTGO_EPAPER_2_13_IN_B74) {
171  this->reset_pin_->digital_write(false);
172  delay(10);
173  this->reset_pin_->digital_write(true);
174  delay(10);
175  this->wait_until_idle_();
176 
177  this->command(0x12); // SWRESET
178  this->wait_until_idle_();
179  }
180 
181  // COMMAND DRIVER OUTPUT CONTROL
182  this->command(0x01);
183  this->data(this->get_height_internal() - 1);
184  this->data((this->get_height_internal() - 1) >> 8);
185  this->data(0x00); // ? GD = 0, SM = 0, TB = 0
186 
187  // COMMAND BOOSTER SOFT START CONTROL
188  this->command(0x0C);
189  this->data(0xD7);
190  this->data(0xD6);
191  this->data(0x9D);
192 
193  // COMMAND WRITE VCOM REGISTER
194  this->command(0x2C);
195  this->data(0xA8);
196 
197  // COMMAND SET DUMMY LINE PERIOD
198  this->command(0x3A);
199  this->data(0x1A);
200 
201  // COMMAND SET GATE TIME
202  this->command(0x3B);
203  this->data(0x08); // 2µs per row
204 
205  // COMMAND DATA ENTRY MODE SETTING
206  this->command(0x11);
207  switch (this->model_) {
209  this->data(0x01); // x increase, y decrease : as in demo code
210  break;
213  this->data(0x03); // from top left to bottom right
214  // RAM content option for Display Update
215  this->command(0x21);
216  this->data(0x00);
217  this->data(0x80);
218  break;
219  default:
220  this->data(0x03); // from top left to bottom right
221  }
222 }
224  LOG_DISPLAY("", "Waveshare E-Paper", this);
225  switch (this->model_) {
227  ESP_LOGCONFIG(TAG, " Model: 1.54in");
228  break;
230  ESP_LOGCONFIG(TAG, " Model: 1.54inV2");
231  break;
233  ESP_LOGCONFIG(TAG, " Model: 2.13in");
234  break;
235  case TTGO_EPAPER_2_13_IN:
236  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO)");
237  break;
239  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B73)");
240  break;
242  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B74)");
243  break;
245  ESP_LOGCONFIG(TAG, " Model: 2.13in (TTGO B1)");
246  break;
248  ESP_LOGCONFIG(TAG, " Model: 2.9in");
249  break;
251  ESP_LOGCONFIG(TAG, " Model: 2.9inV2");
252  break;
253  }
254  ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
255  LOG_PIN(" Reset Pin: ", this->reset_pin_);
256  LOG_PIN(" DC Pin: ", this->dc_pin_);
257  LOG_PIN(" Busy Pin: ", this->busy_pin_);
258  LOG_UPDATE_INTERVAL(this);
259 }
261  bool full_update = this->at_update_ == 0;
262  bool prev_full_update = this->at_update_ == 1;
263 
264  if (!this->wait_until_idle_()) {
265  this->status_set_warning();
266  return;
267  }
268 
269  if (this->full_update_every_ >= 1) {
270  if (full_update != prev_full_update) {
271  switch (this->model_) {
272  case TTGO_EPAPER_2_13_IN:
273  this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO : PARTIAL_UPDATE_LUT_TTGO, LUT_SIZE_TTGO);
274  break;
276  this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO_B73 : PARTIAL_UPDATE_LUT_TTGO_B73, LUT_SIZE_TTGO_B73);
277  break;
279  // there is no LUT
280  break;
282  this->write_lut_(full_update ? FULL_UPDATE_LUT_TTGO_B1 : PARTIAL_UPDATE_LUT_TTGO_B1, LUT_SIZE_TTGO_B1);
283  break;
284  default:
285  this->write_lut_(full_update ? FULL_UPDATE_LUT : PARTIAL_UPDATE_LUT, LUT_SIZE_WAVESHARE);
286  }
287  }
288  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
289  }
290 
291  // Set x & y regions we want to write to (full)
292  switch (this->model_) {
294  // COMMAND SET RAM X ADDRESS START END POSITION
295  this->command(0x44);
296  this->data(0x00);
297  this->data((this->get_width_controller() - 1) >> 3);
298  // COMMAND SET RAM Y ADDRESS START END POSITION
299  this->command(0x45);
300  this->data(this->get_height_internal() - 1);
301  this->data((this->get_height_internal() - 1) >> 8);
302  this->data(0x00);
303  this->data(0x00);
304 
305  // COMMAND SET RAM X ADDRESS COUNTER
306  this->command(0x4E);
307  this->data(0x00);
308  // COMMAND SET RAM Y ADDRESS COUNTER
309  this->command(0x4F);
310  this->data(this->get_height_internal() - 1);
311  this->data((this->get_height_internal() - 1) >> 8);
312 
313  break;
315  // BorderWaveform
316  this->command(0x3C);
317  this->data(full_update ? 0x05 : 0x80);
318 
319  // fall through
320  default:
321  // COMMAND SET RAM X ADDRESS START END POSITION
322  this->command(0x44);
323  this->data(0x00);
324  this->data((this->get_width_internal() - 1) >> 3);
325  // COMMAND SET RAM Y ADDRESS START END POSITION
326  this->command(0x45);
327  this->data(0x00);
328  this->data(0x00);
329  this->data(this->get_height_internal() - 1);
330  this->data((this->get_height_internal() - 1) >> 8);
331 
332  // COMMAND SET RAM X ADDRESS COUNTER
333  this->command(0x4E);
334  this->data(0x00);
335  // COMMAND SET RAM Y ADDRESS COUNTER
336  this->command(0x4F);
337  this->data(0x00);
338  this->data(0x00);
339  }
340 
341  if (!this->wait_until_idle_()) {
342  this->status_set_warning();
343  return;
344  }
345 
346  // COMMAND WRITE RAM
347  this->command(0x24);
348  this->start_data_();
349  switch (this->model_) {
350  case TTGO_EPAPER_2_13_IN_B1: { // block needed because of variable initializations
351  int16_t wb = ((this->get_width_internal()) >> 3);
352  for (int i = 0; i < this->get_height_internal(); i++) {
353  for (int j = 0; j < wb; j++) {
354  int idx = j + (this->get_height_internal() - 1 - i) * wb;
355  this->write_byte(this->buffer_[idx]);
356  }
357  }
358  break;
359  }
360  default:
361  this->write_array(this->buffer_, this->get_buffer_length_());
362  }
363  this->end_data_();
364 
365  // COMMAND DISPLAY UPDATE CONTROL 2
366  this->command(0x22);
367  switch (this->model_) {
371  this->data(full_update ? 0xF7 : 0xFF);
372  break;
374  this->data(0xC7);
375  break;
376  default:
377  this->data(0xC4);
378  break;
379  }
380 
381  // COMMAND MASTER ACTIVATION
382  this->command(0x20);
383  // COMMAND TERMINATE FRAME READ WRITE
384  this->command(0xFF);
385 
386  this->status_clear_warning();
387 }
389  switch (this->model_) {
392  return 200;
394  case TTGO_EPAPER_2_13_IN:
398  return 122;
401  return 128;
402  }
403  return 0;
404 }
405 // The controller of the 2.13" displays has a buffer larger than screen size
407  switch (this->model_) {
409  case TTGO_EPAPER_2_13_IN:
413  return 128;
414  default:
415  return this->get_width_internal();
416  }
417 }
419  switch (this->model_) {
422  return 200;
424  case TTGO_EPAPER_2_13_IN:
428  return 250;
431  return 296;
432  }
433  return 0;
434 }
435 void WaveshareEPaperTypeA::write_lut_(const uint8_t *lut, const uint8_t size) {
436  // COMMAND WRITE LUT REGISTER
437  this->command(0x32);
438  for (uint8_t i = 0; i < size; i++)
439  this->data(lut[i]);
440 }
442 void WaveshareEPaperTypeA::set_full_update_every(uint32_t full_update_every) {
443  this->full_update_every_ = full_update_every;
444 }
445 
447  switch (this->model_) {
449  return 2500;
450  default:
452  }
453 }
454 
455 // ========================================================
456 // Type B
457 // ========================================================
458 // Datasheet:
459 // - https://www.waveshare.com/w/upload/7/7f/4.2inch-e-paper-b-specification.pdf
460 // - https://github.com/soonuse/epd-library-arduino/blob/master/4.2inch_e-paper/epd4in2/
461 
462 static const uint8_t LUT_VCOM_DC_2_7[44] = {
463  0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x00, 0x32, 0x32, 0x00, 0x00, 0x02, 0x00,
464  0x0F, 0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
465  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 };
467 
468 static const uint8_t LUT_WHITE_TO_WHITE_2_7[42] = {
469  0x50, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0xA0, 0x0F,
470  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
471  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472 };
473 
474 static const uint8_t LUT_BLACK_TO_WHITE_2_7[42] = {
475  0x50, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0xA0, 0x0F,
476  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 };
479 
480 static const uint8_t LUT_WHITE_TO_BLACK_2_7[] = {
481  0xA0, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0x50, 0x0F,
482  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
484 };
485 
486 static const uint8_t LUT_BLACK_TO_BLACK_2_7[42] = {
487  0xA0, 0x0F, 0x0F, 0x00, 0x00, 0x05, 0x60, 0x32, 0x32, 0x00, 0x00, 0x02, 0x50, 0x0F,
488  0x0F, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 };
491 
493  // command power setting
494  this->command(0x01);
495  this->data(0x03); // VDS_EN, VDG_EN
496  this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
497  this->data(0x2B); // VDH
498  this->data(0x2B); // VDL
499  this->data(0x09); // VDHR
500 
501  // command booster soft start
502  this->command(0x06);
503  this->data(0x07);
504  this->data(0x07);
505  this->data(0x17);
506 
507  // Power optimization - ???
508  this->command(0xF8);
509  this->data(0x60);
510  this->data(0xA5);
511  this->command(0xF8);
512  this->data(0x89);
513  this->data(0xA5);
514  this->command(0xF8);
515  this->data(0x90);
516  this->data(0x00);
517  this->command(0xF8);
518  this->data(0x93);
519  this->data(0x2A);
520  this->command(0xF8);
521  this->data(0xA0);
522  this->data(0xA5);
523  this->command(0xF8);
524  this->data(0xA1);
525  this->data(0x00);
526  this->command(0xF8);
527  this->data(0x73);
528  this->data(0x41);
529 
530  // command partial display refresh
531  this->command(0x16);
532  this->data(0x00);
533 
534  // command power on
535  this->command(0x04);
536  this->wait_until_idle_();
537  delay(10);
538 
539  // Command panel setting
540  this->command(0x00);
541  this->data(0xAF); // KW-BF KWR-AF BWROTP 0f
542  // command pll control
543  this->command(0x30);
544  this->data(0x3A); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
545  // COMMAND VCM DC SETTING
546  this->command(0x82);
547  this->data(0x12);
548 
549  delay(2);
550  // COMMAND LUT FOR VCOM
551  this->command(0x20);
552  for (uint8_t i : LUT_VCOM_DC_2_7)
553  this->data(i);
554 
555  // COMMAND LUT WHITE TO WHITE
556  this->command(0x21);
557  for (uint8_t i : LUT_WHITE_TO_WHITE_2_7)
558  this->data(i);
559  // COMMAND LUT BLACK TO WHITE
560  this->command(0x22);
561  for (uint8_t i : LUT_BLACK_TO_WHITE_2_7)
562  this->data(i);
563  // COMMAND LUT WHITE TO BLACK
564  this->command(0x23);
565  for (uint8_t i : LUT_WHITE_TO_BLACK_2_7)
566  this->data(i);
567  // COMMAND LUT BLACK TO BLACK
568  this->command(0x24);
569  for (uint8_t i : LUT_BLACK_TO_BLACK_2_7)
570  this->data(i);
571 }
573  uint32_t buf_len = this->get_buffer_length_();
574 
575  // COMMAND DATA START TRANSMISSION 1
576  this->command(0x10);
577  delay(2);
578  for (uint32_t i = 0; i < buf_len; i++) {
579  this->data(this->buffer_[i]);
580  }
581  delay(2);
582 
583  // COMMAND DATA START TRANSMISSION 2
584  this->command(0x13);
585  delay(2);
586  for (uint32_t i = 0; i < buf_len; i++) {
587  this->data(this->buffer_[i]);
588  }
589 
590  // COMMAND DISPLAY REFRESH
591  this->command(0x12);
592 }
596  LOG_DISPLAY("", "Waveshare E-Paper", this);
597  ESP_LOGCONFIG(TAG, " Model: 2.7in");
598  LOG_PIN(" Reset Pin: ", this->reset_pin_);
599  LOG_PIN(" DC Pin: ", this->dc_pin_);
600  LOG_PIN(" Busy Pin: ", this->busy_pin_);
601  LOG_UPDATE_INTERVAL(this);
602 }
603 
604 // ========================================================
605 // 2.90in Type B (LUT from OTP)
606 // Datasheet:
607 // - https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf
608 // - https://github.com/soonuse/epd-library-arduino/blob/master/2.9inch_e-paper_b/epd2in9b/epd2in9b.cpp
609 // ========================================================
610 
612  // from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37
613  // EPD hardware init start
614  this->reset_();
615 
616  // COMMAND BOOSTER SOFT START
617  this->command(0x06);
618  this->data(0x17);
619  this->data(0x17);
620  this->data(0x17);
621 
622  // COMMAND POWER ON
623  this->command(0x04);
624  this->wait_until_idle_();
625 
626  // COMMAND PANEL SETTING
627  this->command(0x00);
628  // 128x296 resolution: 10
629  // LUT from OTP: 0
630  // B/W mode (doesn't work): 1
631  // scan-up: 1
632  // shift-right: 1
633  // booster ON: 1
634  // no soft reset: 1
635  this->data(0x9F);
636 
637  // COMMAND RESOLUTION SETTING
638  // set to 128x296 by COMMAND PANEL SETTING
639 
640  // COMMAND VCOM AND DATA INTERVAL SETTING
641  // use defaults for white border and ESPHome image polarity
642 
643  // EPD hardware init end
644 }
646  // COMMAND DATA START TRANSMISSION 1 (B/W data)
647  this->command(0x10);
648  delay(2);
649  this->start_data_();
650  this->write_array(this->buffer_, this->get_buffer_length_());
651  this->end_data_();
652  delay(2);
653 
654  // COMMAND DATA START TRANSMISSION 2 (RED data)
655  this->command(0x13);
656  delay(2);
657  this->start_data_();
658  for (size_t i = 0; i < this->get_buffer_length_(); i++)
659  this->write_byte(0x00);
660  this->end_data_();
661  delay(2);
662 
663  // COMMAND DISPLAY REFRESH
664  this->command(0x12);
665  delay(2);
666  this->wait_until_idle_();
667 
668  // COMMAND POWER OFF
669  // NOTE: power off < deep sleep
670  this->command(0x02);
671 }
675  LOG_DISPLAY("", "Waveshare E-Paper", this);
676  ESP_LOGCONFIG(TAG, " Model: 2.9in (B)");
677  LOG_PIN(" Reset Pin: ", this->reset_pin_);
678  LOG_PIN(" DC Pin: ", this->dc_pin_);
679  LOG_PIN(" Busy Pin: ", this->busy_pin_);
680  LOG_UPDATE_INTERVAL(this);
681 }
682 
683 // ========================================================
684 // Good Display 2.9in black/white/grey
685 // Datasheet:
686 // - https://v4.cecdn.yun300.cn/100001_1909185148/SSD1680.pdf
687 // - https://github.com/adafruit/Adafruit_EPD/blob/master/src/panels/ThinkInk_290_Grayscale4_T5.h
688 // ========================================================
689 
691  // from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37
692  // EPD hardware init start
693  this->reset_();
694 
695  // COMMAND POWER SETTINGS
696  this->command(0x00);
697  this->data(0x03);
698  this->data(0x00);
699  this->data(0x2b);
700  this->data(0x2b);
701  this->data(0x03); /* for b/w */
702 
703  // COMMAND BOOSTER SOFT START
704  this->command(0x06);
705  this->data(0x17);
706  this->data(0x17);
707  this->data(0x17);
708 
709  // COMMAND POWER ON
710  this->command(0x04);
711  this->wait_until_idle_();
712 
713  // Not sure what this does but it's in the Adafruit EPD library
714  this->command(0xFF);
715  this->wait_until_idle_();
716 
717  // COMMAND PANEL SETTING
718  this->command(0x00);
719  // 128x296 resolution: 10
720  // LUT from OTP: 0
721  // B/W mode (doesn't work): 1
722  // scan-up: 1
723  // shift-right: 1
724  // booster ON: 1
725  // no soft reset: 1
726  this->data(0b10011111);
727 
728  // COMMAND RESOLUTION SETTING
729  // set to 128x296 by COMMAND PANEL SETTING
730 
731  // COMMAND VCOM AND DATA INTERVAL SETTING
732  // use defaults for white border and ESPHome image polarity
733 
734  // EPD hardware init end
735 }
737  // COMMAND DATA START TRANSMISSION 2 (B/W only)
738  this->command(0x13);
739  delay(2);
740  this->start_data_();
741  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
742  this->write_byte(this->buffer_[i]);
743  }
744  this->end_data_();
745  delay(2);
746 
747  // COMMAND DISPLAY REFRESH
748  this->command(0x12);
749  delay(2);
750  this->wait_until_idle_();
751 
752  // COMMAND POWER OFF
753  // NOTE: power off < deep sleep
754  this->command(0x02);
755 }
756 int GDEY029T94::get_width_internal() { return 128; }
757 int GDEY029T94::get_height_internal() { return 296; }
759  LOG_DISPLAY("", "Waveshare E-Paper (Good Display)", this);
760  ESP_LOGCONFIG(TAG, " Model: 2.9in Greyscale GDEY029T94");
761  LOG_PIN(" Reset Pin: ", this->reset_pin_);
762  LOG_PIN(" DC Pin: ", this->dc_pin_);
763  LOG_PIN(" Busy Pin: ", this->busy_pin_);
764  LOG_UPDATE_INTERVAL(this);
765 }
766 
767 // ========================================================
768 // Good Display 1.54in black/white/grey GDEW0154M09
769 // As used in M5Stack Core Ink
770 // Datasheet:
771 // - https://v4.cecdn.yun300.cn/100001_1909185148/GDEW0154M09-200709.pdf
772 // - https://github.com/m5stack/M5Core-Ink
773 // Reference code from GoodDisplay:
774 // - https://github.com/GoodDisplay/E-paper-Display-Library-of-GoodDisplay/
775 // -> /Monochrome_E-paper-Display/1.54inch_JD79653_GDEW0154M09_200x200/ESP32-Arduino%20IDE/GDEW0154M09_Arduino.ino
776 // M5Stack Core Ink spec:
777 // - https://docs.m5stack.com/en/core/coreink
778 // ========================================================
779 
781  this->init_internal_();
783  this->lastbuff_ = allocator.allocate(this->get_buffer_length_());
784  if (this->lastbuff_ != nullptr) {
785  memset(this->lastbuff_, 0xff, sizeof(uint8_t) * this->get_buffer_length_());
786  }
787  this->clear_();
788 }
789 
790 void GDEW0154M09::reset_() {
791  // RST is inverse from other einks in this project
792  if (this->reset_pin_ != nullptr) {
793  this->reset_pin_->digital_write(false);
794  delay(10);
795  this->reset_pin_->digital_write(true);
796  delay(10);
797  }
798 }
799 
800 void GDEW0154M09::init_internal_() {
801  this->reset_();
802 
803  // clang-format off
804  // 200x200 resolution: 11
805  // LUT from OTP: 0
806  // B/W mode (doesn't work): 1
807  // scan-up: 1
808  // shift-right: 1
809  // booster ON: 1
810  // no soft reset: 1
811  const uint8_t panel_setting_1 = 0b11011111;
812 
813  // VCOM status off 0
814  // Temp sensing default 1
815  // VGL Power Off Floating 1
816  // NORG expect refresh 1
817  // VCOM Off on displ off 0
818  const uint8_t panel_setting_2 = 0b01110;
819 
820  const uint8_t wf_t0154_cz_b3_list[] = {
821  11, // 11 commands in list
822  CMD_PSR_PANEL_SETTING, 2, panel_setting_1, panel_setting_2,
823  CMD_UNDOCUMENTED_0x4D, 1, 0x55,
824  CMD_UNDOCUMENTED_0xAA, 1, 0x0f,
825  CMD_UNDOCUMENTED_0xE9, 1, 0x02,
826  CMD_UNDOCUMENTED_0xB6, 1, 0x11,
827  CMD_UNDOCUMENTED_0xF3, 1, 0x0a,
828  CMD_TRES_RESOLUTION_SETTING, 3, 0xc8, 0x00, 0xc8,
829  CMD_TCON_TCONSETTING, 1, 0x00,
830  CMD_CDI_VCOM_DATA_INTERVAL, 1, 0xd7,
831  CMD_PWS_POWER_SAVING, 1, 0x00,
832  CMD_PON_POWER_ON, 0
833  };
834  // clang-format on
835 
836  this->write_init_list_(wf_t0154_cz_b3_list);
837  delay(100); // NOLINT
838  this->wait_until_idle_();
839 }
840 
841 void GDEW0154M09::write_init_list_(const uint8_t *list) {
842  uint8_t list_limit = list[0];
843  uint8_t *start_ptr = ((uint8_t *) list + 1);
844  for (uint8_t i = 0; i < list_limit; i++) {
845  this->command(*(start_ptr + 0));
846  for (uint8_t dnum = 0; dnum < *(start_ptr + 1); dnum++) {
847  this->data(*(start_ptr + 2 + dnum));
848  }
849  start_ptr += (*(start_ptr + 1) + 2);
850  }
851 }
852 
853 void GDEW0154M09::clear_() {
854  uint32_t pixsize = this->get_buffer_length_();
855  for (uint8_t j = 0; j < 2; j++) {
856  this->command(CMD_DTM1_DATA_START_TRANS);
857  for (int count = 0; count < pixsize; count++) {
858  this->data(0x00);
859  }
860  this->command(CMD_DTM2_DATA_START_TRANS2);
861  for (int count = 0; count < pixsize; count++) {
862  this->data(0xff);
863  }
864  this->command(CMD_DISPLAY_REFRESH);
865  delay(10);
866  this->wait_until_idle_();
867  }
868 }
869 
871  this->init_internal_();
872  // "Mode 0 display" for now
873  this->command(CMD_DTM1_DATA_START_TRANS);
874  for (int i = 0; i < this->get_buffer_length_(); i++) {
875  this->data(0xff);
876  }
877  this->command(CMD_DTM2_DATA_START_TRANS2); // write 'new' data to SRAM
878  for (int i = 0; i < this->get_buffer_length_(); i++) {
879  this->data(this->buffer_[i]);
880  }
881  this->command(CMD_DISPLAY_REFRESH);
882  delay(10);
883  this->wait_until_idle_();
884  this->deep_sleep();
885 }
886 
888  // COMMAND DEEP SLEEP
889  this->command(CMD_POF_POWER_OFF);
890  this->wait_until_idle_();
891  delay(1000); // NOLINT
892  this->command(CMD_DSLP_DEEP_SLEEP);
893  this->data(DATA_DSLP_DEEP_SLEEP);
894 }
895 
896 int GDEW0154M09::get_width_internal() { return 200; }
897 int GDEW0154M09::get_height_internal() { return 200; }
899  LOG_DISPLAY("", "M5Stack CoreInk E-Paper (Good Display)", this);
900  ESP_LOGCONFIG(TAG, " Model: 1.54in Greyscale GDEW0154M09");
901  LOG_PIN(" Reset Pin: ", this->reset_pin_);
902  LOG_PIN(" DC Pin: ", this->dc_pin_);
903  LOG_PIN(" Busy Pin: ", this->busy_pin_);
904  LOG_UPDATE_INTERVAL(this);
905 }
906 
907 static const uint8_t LUT_VCOM_DC_4_2[] = {
908  0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x17, 0x17, 0x00, 0x00, 0x02, 0x00, 0x0A, 0x01,
909  0x00, 0x00, 0x01, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
910  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
911 };
912 static const uint8_t LUT_WHITE_TO_WHITE_4_2[] = {
913  0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A,
914  0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
915  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
916 };
917 static const uint8_t LUT_BLACK_TO_WHITE_4_2[] = {
918  0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A,
919  0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
920  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
921 };
922 
923 static const uint8_t LUT_BLACK_TO_BLACK_4_2[] = {
924  0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A,
925  0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
926  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
927 };
928 
929 static const uint8_t LUT_WHITE_TO_BLACK_4_2[] = {
930  0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A,
931  0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
932  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
933 };
934 
936  // https://www.waveshare.com/w/upload/7/7f/4.2inch-e-paper-b-specification.pdf - page 8
937 
938  // COMMAND POWER SETTING
939  this->command(0x01);
940  this->data(0x03); // VDS_EN, VDG_EN
941  this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
942  this->data(0x2B); // VDH
943  this->data(0x2B); // VDL
944  this->data(0xFF); // VDHR
945 
946  // COMMAND BOOSTER SOFT START
947  this->command(0x06);
948  this->data(0x17); // PHA
949  this->data(0x17); // PHB
950  this->data(0x17); // PHC
951 
952  // COMMAND POWER ON
953  this->command(0x04);
954  this->wait_until_idle_();
955  delay(10);
956  // COMMAND PANEL SETTING
957  this->command(0x00);
958  this->data(0xBF); // KW-BF KWR-AF BWROTP 0f
959  this->data(0x0B);
960  // COMMAND PLL CONTROL
961  this->command(0x30);
962  this->data(0x3C); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
963 
964  delay(2);
965  // COMMAND LUT FOR VCOM
966  this->command(0x20);
967  for (uint8_t i : LUT_VCOM_DC_4_2)
968  this->data(i);
969  // COMMAND LUT WHITE TO WHITE
970  this->command(0x21);
971  for (uint8_t i : LUT_WHITE_TO_WHITE_4_2)
972  this->data(i);
973  // COMMAND LUT BLACK TO WHITE
974  this->command(0x22);
975  for (uint8_t i : LUT_BLACK_TO_WHITE_4_2)
976  this->data(i);
977  // COMMAND LUT WHITE TO BLACK
978  this->command(0x23);
979  for (uint8_t i : LUT_WHITE_TO_BLACK_4_2)
980  this->data(i);
981  // COMMAND LUT BLACK TO BLACK
982  this->command(0x24);
983  for (uint8_t i : LUT_BLACK_TO_BLACK_4_2)
984  this->data(i);
985 }
987  // COMMAND RESOLUTION SETTING
988  this->command(0x61);
989  this->data(0x01);
990  this->data(0x90);
991  this->data(0x01);
992  this->data(0x2C);
993 
994  // COMMAND VCM DC SETTING REGISTER
995  this->command(0x82);
996  this->data(0x12);
997 
998  // COMMAND VCOM AND DATA INTERVAL SETTING
999  this->command(0x50);
1000  this->data(0x97);
1001 
1002  // COMMAND DATA START TRANSMISSION 1
1003  this->command(0x10);
1004  delay(2);
1005  this->start_data_();
1006  this->write_array(this->buffer_, this->get_buffer_length_());
1007  this->end_data_();
1008  delay(2);
1009  // COMMAND DATA START TRANSMISSION 2
1010  this->command(0x13);
1011  delay(2);
1012  this->start_data_();
1013  this->write_array(this->buffer_, this->get_buffer_length_());
1014  this->end_data_();
1015  // COMMAND DISPLAY REFRESH
1016  this->command(0x12);
1017 }
1021  LOG_DISPLAY("", "Waveshare E-Paper", this);
1022  ESP_LOGCONFIG(TAG, " Model: 4.2in");
1023  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1024  LOG_PIN(" DC Pin: ", this->dc_pin_);
1025  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1026  LOG_UPDATE_INTERVAL(this);
1027 }
1028 
1029 // ========================================================
1030 // 4.20in Type B (LUT from OTP)
1031 // Datasheet:
1032 // - https://www.waveshare.com/w/upload/2/20/4.2inch-e-paper-module-user-manual-en.pdf
1033 // - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_4in2b_V2.c
1034 // ========================================================
1036  // these exact timings are required for a proper reset/init
1037  this->reset_pin_->digital_write(false);
1038  delay(2);
1039  this->reset_pin_->digital_write(true);
1040  delay(200); // NOLINT
1041 
1042  // COMMAND POWER ON
1043  this->command(0x04);
1044  this->wait_until_idle_();
1045 
1046  // COMMAND PANEL SETTING
1047  this->command(0x00);
1048  this->data(0x0f); // LUT from OTP
1049 }
1050 
1052  // COMMAND DATA START TRANSMISSION 1 (B/W data)
1053  this->command(0x10);
1054  this->start_data_();
1055  this->write_array(this->buffer_, this->get_buffer_length_());
1056  this->end_data_();
1057 
1058  // COMMAND DATA START TRANSMISSION 2 (RED data)
1059  this->command(0x13);
1060  this->start_data_();
1061  for (size_t i = 0; i < this->get_buffer_length_(); i++)
1062  this->write_byte(0xFF);
1063  this->end_data_();
1064  delay(2);
1065 
1066  // COMMAND DISPLAY REFRESH
1067  this->command(0x12);
1068  this->wait_until_idle_();
1069 
1070  // COMMAND POWER OFF
1071  // NOTE: power off < deep sleep
1072  this->command(0x02);
1073 }
1077  LOG_DISPLAY("", "Waveshare E-Paper", this);
1078  ESP_LOGCONFIG(TAG, " Model: 4.2in (B V2)");
1079  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1080  LOG_PIN(" DC Pin: ", this->dc_pin_);
1081  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1082  LOG_UPDATE_INTERVAL(this);
1083 }
1084 
1086  // COMMAND POWER SETTING
1087  this->command(0x01);
1088  this->data(0x37);
1089  this->data(0x00);
1090 
1091  // COMMAND PANEL SETTING
1092  this->command(0x00);
1093  this->data(0xCF);
1094  this->data(0x0B);
1095 
1096  // COMMAND BOOSTER SOFT START
1097  this->command(0x06);
1098  this->data(0xC7);
1099  this->data(0xCC);
1100  this->data(0x28);
1101 
1102  // COMMAND POWER ON
1103  this->command(0x04);
1104  this->wait_until_idle_();
1105  delay(10);
1106 
1107  // COMMAND PLL CONTROL
1108  this->command(0x30);
1109  this->data(0x3C);
1110 
1111  // COMMAND TEMPERATURE SENSOR CALIBRATION
1112  this->command(0x41);
1113  this->data(0x00);
1114 
1115  // COMMAND VCOM AND DATA INTERVAL SETTING
1116  this->command(0x50);
1117  this->data(0x77);
1118 
1119  // COMMAND TCON SETTING
1120  this->command(0x60);
1121  this->data(0x22);
1122 
1123  // COMMAND RESOLUTION SETTING
1124  this->command(0x61);
1125  this->data(0x02);
1126  this->data(0x58);
1127  this->data(0x01);
1128  this->data(0xC0);
1129 
1130  // COMMAND VCM DC SETTING REGISTER
1131  this->command(0x82);
1132  this->data(0x1E);
1133 
1134  this->command(0xE5);
1135  this->data(0x03);
1136 }
1138  // COMMAND DATA START TRANSMISSION 1
1139  this->command(0x10);
1140 
1141  this->start_data_();
1142  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
1143  uint8_t temp1 = this->buffer_[i];
1144  for (uint8_t j = 0; j < 8; j++) {
1145  uint8_t temp2;
1146  if (temp1 & 0x80) {
1147  temp2 = 0x03;
1148  } else {
1149  temp2 = 0x00;
1150  }
1151 
1152  temp2 <<= 4;
1153  temp1 <<= 1;
1154  j++;
1155  if (temp1 & 0x80) {
1156  temp2 |= 0x03;
1157  } else {
1158  temp2 |= 0x00;
1159  }
1160  temp1 <<= 1;
1161  this->write_byte(temp2);
1162  }
1163 
1164  App.feed_wdt();
1165  }
1166  this->end_data_();
1167 
1168  // COMMAND DISPLAY REFRESH
1169  this->command(0x12);
1170 }
1174  LOG_DISPLAY("", "Waveshare E-Paper", this);
1175  ESP_LOGCONFIG(TAG, " Model: 5.83in");
1176  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1177  LOG_PIN(" DC Pin: ", this->dc_pin_);
1178  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1179  LOG_UPDATE_INTERVAL(this);
1180 }
1181 
1182 // ========================================================
1183 // 5.83in V2
1184 // Datasheet/Specification/Reference:
1185 // - https://www.waveshare.com/w/upload/3/37/5.83inch_e-Paper_V2_Specification.pdf
1186 // - https://github.com/waveshare/e-Paper/blob/master/Arduino/epd5in83_V2/epd5in83_V2.cpp
1187 // ========================================================
1189  // COMMAND POWER SETTING
1190  this->command(0x01);
1191  this->data(0x07);
1192  this->data(0x07);
1193  this->data(0x3f);
1194  this->data(0x3f);
1195 
1196  // COMMAND POWER ON
1197  this->command(0x04);
1198  delay(10);
1199  this->wait_until_idle_();
1200 
1201  // PANNEL SETTING
1202  this->command(0x00);
1203  this->data(0x1F);
1204 
1205  // COMMAND RESOLUTION SETTING
1206  this->command(0x61);
1207  this->data(0x02);
1208  this->data(0x88);
1209  this->data(0x01);
1210  this->data(0xE0);
1211 
1212  this->command(0x15);
1213  this->data(0x00);
1214 
1215  // COMMAND TCON SETTING
1216  this->command(0x60);
1217  this->data(0x22);
1218 
1219  // Do we need this?
1220  // COMMAND PLL CONTROL
1221  this->command(0x30);
1222  this->data(0x3C); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
1223 }
1225  // Reuse the code from WaveshareEPaper4P2In::display()
1226  // COMMAND VCM DC SETTING REGISTER
1227  this->command(0x82);
1228  this->data(0x12);
1229 
1230  // COMMAND VCOM AND DATA INTERVAL SETTING
1231  this->command(0x50);
1232  this->data(0x97);
1233 
1234  // COMMAND DATA START TRANSMISSION 1
1235  this->command(0x10);
1236  delay(2);
1237  this->start_data_();
1238  this->write_array(this->buffer_, this->get_buffer_length_());
1239  this->end_data_();
1240  delay(2);
1241 
1242  // COMMAND DATA START TRANSMISSION 2
1243  this->command(0x13);
1244  delay(2);
1245  this->start_data_();
1246  this->write_array(this->buffer_, this->get_buffer_length_());
1247  this->end_data_();
1248 
1249  // COMMAND DISPLAY REFRESH
1250  this->command(0x12);
1251 }
1255  LOG_DISPLAY("", "Waveshare E-Paper", this);
1256  ESP_LOGCONFIG(TAG, " Model: 5.83inv2");
1257  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1258  LOG_PIN(" DC Pin: ", this->dc_pin_);
1259  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1260  LOG_UPDATE_INTERVAL(this);
1261 }
1262 
1264  // COMMAND POWER SETTING
1265  this->command(0x01);
1266  this->data(0x07);
1267  this->data(0x07); // VGH=20V,VGL=-20V
1268  this->data(0x3f); // VDH=15V
1269  this->data(0x3f); // VDL=-15V
1270  // COMMAND POWER ON
1271  this->command(0x04);
1272  delay(100); // NOLINT
1273  this->wait_until_idle_();
1274  // COMMAND PANEL SETTING
1275  this->command(0x00);
1276  this->data(0x0F); // KW3f, KWR-2F, BWROTP 0f, BWOTP 1f
1277  this->command(0x61); // tres
1278  this->data(0x03); // 800px
1279  this->data(0x20);
1280  this->data(0x01); // 400px
1281  this->data(0xE0);
1282  this->command(0x15);
1283  this->data(0x00);
1284  // COMMAND VCOM AND DATA INTERVAL SETTING
1285  this->command(0x50);
1286  this->data(0x11);
1287  this->data(0x07);
1288  // COMMAND TCON SETTING
1289  this->command(0x60);
1290  this->data(0x22);
1291  // COMMAND RESOLUTION SETTING
1292  this->command(0x65);
1293  this->data(0x00);
1294  this->data(0x00); // 800*480
1295  this->data(0x00);
1296  this->data(0x00);
1297 }
1299  // COMMAND DATA START TRANSMISSION 1 (B/W data)
1300  this->command(0x10);
1301  delay(2);
1302  this->start_data_();
1303  this->write_array(this->buffer_, this->get_buffer_length_());
1304  this->end_data_();
1305  delay(2);
1306 
1307  // COMMAND DATA START TRANSMISSION 2 (RED data)
1308  this->command(0x13);
1309  delay(2);
1310  this->start_data_();
1311  for (size_t i = 0; i < this->get_buffer_length_(); i++)
1312  this->write_byte(0x00);
1313  this->end_data_();
1314  delay(2);
1315 
1316  // COMMAND DISPLAY REFRESH
1317  this->command(0x12);
1318  delay(100); // NOLINT
1319  this->wait_until_idle_();
1320 }
1324  LOG_DISPLAY("", "Waveshare E-Paper", this);
1325  ESP_LOGCONFIG(TAG, " Model: 7.5in-bv2");
1326  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1327  LOG_PIN(" DC Pin: ", this->dc_pin_);
1328  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1329  LOG_UPDATE_INTERVAL(this);
1330 }
1331 
1333  if (this->busy_pin_ == nullptr) {
1334  return true;
1335  }
1336 
1337  const uint32_t start = millis();
1338  while (this->busy_pin_->digital_read()) {
1339  this->command(0x71);
1340  if (millis() - start > this->idle_timeout_()) {
1341  ESP_LOGI(TAG, "Timeout while displaying image!");
1342  return false;
1343  }
1344  delay(10);
1345  }
1346  delay(200); // NOLINT
1347  return true;
1348 };
1350  this->reset_();
1351 
1352  // COMMAND POWER SETTING
1353  this->command(0x01);
1354 
1355  // 1-0=11: internal power
1356  this->data(0x07);
1357  this->data(0x17); // VGH&VGL
1358  this->data(0x3F); // VSH
1359  this->data(0x26); // VSL
1360  this->data(0x11); // VSHR
1361 
1362  // VCOM DC Setting
1363  this->command(0x82);
1364  this->data(0x24); // VCOM
1365 
1366  // Booster Setting
1367  this->command(0x06);
1368  this->data(0x27);
1369  this->data(0x27);
1370  this->data(0x2F);
1371  this->data(0x17);
1372 
1373  // POWER ON
1374  this->command(0x04);
1375 
1376  delay(100); // NOLINT
1377  this->wait_until_idle_();
1378  // COMMAND PANEL SETTING
1379  this->command(0x00);
1380  this->data(0x3F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
1381 
1382  // COMMAND RESOLUTION SETTING
1383  this->command(0x61);
1384  this->data(0x03); // source 800
1385  this->data(0x20);
1386  this->data(0x01); // gate 480
1387  this->data(0xE0);
1388  // COMMAND ...?
1389  this->command(0x15);
1390  this->data(0x00);
1391  // COMMAND VCOM AND DATA INTERVAL SETTING
1392  this->command(0x50);
1393  this->data(0x10);
1394  this->data(0x00);
1395  // COMMAND TCON SETTING
1396  this->command(0x60);
1397  this->data(0x22);
1398  // Resolution setting
1399  this->command(0x65);
1400  this->data(0x00);
1401  this->data(0x00); // 800*480
1402  this->data(0x00);
1403  this->data(0x00);
1404 
1405  this->wait_until_idle_();
1406 
1407  uint8_t lut_vcom_7_i_n5_v2[] = {
1408  0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0xF, 0x1, 0xF, 0x1, 0x2, 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
1409  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1410  };
1411 
1412  uint8_t lut_ww_7_i_n5_v2[] = {
1413  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
1414  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1415  };
1416 
1417  uint8_t lut_bw_7_i_n5_v2[] = {
1418  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
1419  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1420  };
1421 
1422  uint8_t lut_wb_7_i_n5_v2[] = {
1423  0x80, 0xF, 0xF, 0x0, 0x0, 0x3, 0x84, 0xF, 0x1, 0xF, 0x1, 0x4, 0x40, 0xF, 0xF, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
1424  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1425  };
1426 
1427  uint8_t lut_bb_7_i_n5_v2[] = {
1428  0x80, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x40, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
1429  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1430  };
1431 
1432  uint8_t count;
1433  this->command(0x20); // VCOM
1434  for (count = 0; count < 42; count++)
1435  this->data(lut_vcom_7_i_n5_v2[count]);
1436 
1437  this->command(0x21); // LUTBW
1438  for (count = 0; count < 42; count++)
1439  this->data(lut_ww_7_i_n5_v2[count]);
1440 
1441  this->command(0x22); // LUTBW
1442  for (count = 0; count < 42; count++)
1443  this->data(lut_bw_7_i_n5_v2[count]);
1444 
1445  this->command(0x23); // LUTWB
1446  for (count = 0; count < 42; count++)
1447  this->data(lut_wb_7_i_n5_v2[count]);
1448 
1449  this->command(0x24); // LUTBB
1450  for (count = 0; count < 42; count++)
1451  this->data(lut_bb_7_i_n5_v2[count]);
1452 
1453  this->command(0x10);
1454  for (uint32_t i = 0; i < 800 * 480 / 8; i++) {
1455  this->data(0xFF);
1456  }
1457 };
1459  uint32_t buf_len = this->get_buffer_length_();
1460 
1461  this->command(0x13); // Start Transmission
1462  delay(2);
1463  for (uint32_t i = 0; i < buf_len; i++) {
1464  this->data(~(this->buffer_[i]));
1465  }
1466 
1467  this->command(0x12); // Display Refresh
1468  delay(100); // NOLINT
1469  this->wait_until_idle_();
1470 }
1474  LOG_DISPLAY("", "Waveshare E-Paper", this);
1475  ESP_LOGCONFIG(TAG, " Model: 7.5in-bv3");
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 
1483  // COMMAND POWER SETTING
1484  this->command(0x01);
1485  this->data(0x37);
1486  this->data(0x00);
1487  // COMMAND PANEL SETTING
1488  this->command(0x00);
1489  this->data(0xCF);
1490  this->data(0x0B);
1491  // COMMAND BOOSTER SOFT START
1492  this->command(0x06);
1493  this->data(0xC7);
1494  this->data(0xCC);
1495  this->data(0x28);
1496  // COMMAND POWER ON
1497  this->command(0x04);
1498  this->wait_until_idle_();
1499  delay(10);
1500  // COMMAND PLL CONTROL
1501  this->command(0x30);
1502  this->data(0x3C);
1503  // COMMAND TEMPERATURE SENSOR CALIBRATION
1504  this->command(0x41);
1505  this->data(0x00);
1506  // COMMAND VCOM AND DATA INTERVAL SETTING
1507  this->command(0x50);
1508  this->data(0x77);
1509  // COMMAND TCON SETTING
1510  this->command(0x60);
1511  this->data(0x22);
1512  // COMMAND RESOLUTION SETTING
1513  this->command(0x61);
1514  this->data(0x02);
1515  this->data(0x80);
1516  this->data(0x01);
1517  this->data(0x80);
1518  // COMMAND VCM DC SETTING REGISTER
1519  this->command(0x82);
1520  this->data(0x1E);
1521  this->command(0xE5);
1522  this->data(0x03);
1523 }
1525  // COMMAND DATA START TRANSMISSION 1
1526  this->command(0x10);
1527  this->start_data_();
1528  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
1529  uint8_t temp1 = this->buffer_[i];
1530  for (uint8_t j = 0; j < 8; j++) {
1531  uint8_t temp2;
1532  if (temp1 & 0x80) {
1533  temp2 = 0x03;
1534  } else {
1535  temp2 = 0x00;
1536  }
1537  temp2 <<= 4;
1538  temp1 <<= 1;
1539  j++;
1540  if (temp1 & 0x80) {
1541  temp2 |= 0x03;
1542  } else {
1543  temp2 |= 0x00;
1544  }
1545  temp1 <<= 1;
1546  this->write_byte(temp2);
1547  }
1548  App.feed_wdt();
1549  }
1550  this->end_data_();
1551  // COMMAND DISPLAY REFRESH
1552  this->command(0x12);
1553 }
1557  LOG_DISPLAY("", "Waveshare E-Paper", this);
1558  ESP_LOGCONFIG(TAG, " Model: 7.5in");
1559  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1560  LOG_PIN(" DC Pin: ", this->dc_pin_);
1561  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1562  LOG_UPDATE_INTERVAL(this);
1563 }
1565  if (this->busy_pin_ == nullptr) {
1566  return true;
1567  }
1568 
1569  const uint32_t start = millis();
1570  while (this->busy_pin_->digital_read()) {
1571  this->command(0x71);
1572  if (millis() - start > this->idle_timeout_()) {
1573  ESP_LOGE(TAG, "Timeout while displaying image!");
1574  return false;
1575  }
1576  App.feed_wdt();
1577  delay(10);
1578  }
1579  return true;
1580 }
1582  // COMMAND POWER SETTING
1583  this->command(0x01);
1584  this->data(0x07);
1585  this->data(0x07);
1586  this->data(0x3f);
1587  this->data(0x3f);
1588 
1589  // We don't want the display to be powered at this point
1590 
1591  delay(100); // NOLINT
1592  this->wait_until_idle_();
1593 
1594  // COMMAND VCOM AND DATA INTERVAL SETTING
1595  this->command(0x50);
1596  this->data(0x10);
1597  this->data(0x07);
1598 
1599  // COMMAND TCON SETTING
1600  this->command(0x60);
1601  this->data(0x22);
1602 
1603  // COMMAND PANEL SETTING
1604  this->command(0x00);
1605  this->data(0x1F);
1606 
1607  // COMMAND RESOLUTION SETTING
1608  this->command(0x61);
1609  this->data(0x03);
1610  this->data(0x20);
1611  this->data(0x01);
1612  this->data(0xE0);
1613 
1614  // COMMAND DUAL SPI MM_EN, DUSPI_EN
1615  this->command(0x15);
1616  this->data(0x00);
1617 
1618  // COMMAND POWER DRIVER HAT DOWN
1619  // This command will turn off booster, controller, source driver, gate driver, VCOM, and
1620  // temperature sensor, but register data will be kept until VDD turned OFF or Deep Sleep Mode.
1621  // Source/Gate/Border/VCOM will be released to floating.
1622  this->command(0x02);
1623 }
1625  uint32_t buf_len = this->get_buffer_length_();
1626 
1627  // COMMAND POWER ON
1628  ESP_LOGI(TAG, "Power on the display and hat");
1629 
1630  // This command will turn on booster, controller, regulators, and temperature sensor will be
1631  // activated for one-time sensing before enabling booster. When all voltages are ready, the
1632  // BUSY_N signal will return to high.
1633  this->command(0x04);
1634  delay(200); // NOLINT
1635  this->wait_until_idle_();
1636 
1637  // COMMAND DATA START TRANSMISSION NEW DATA
1638  this->command(0x13);
1639  delay(2);
1640  for (uint32_t i = 0; i < buf_len; i++) {
1641  this->data(~(this->buffer_[i]));
1642  }
1643 
1644  delay(100); // NOLINT
1645  this->wait_until_idle_();
1646 
1647  // COMMAND DISPLAY REFRESH
1648  this->command(0x12);
1649  delay(100); // NOLINT
1650  this->wait_until_idle_();
1651 
1652  ESP_LOGV(TAG, "Before command(0x02) (>> power off)");
1653  this->command(0x02);
1654  this->wait_until_idle_();
1655  ESP_LOGV(TAG, "After command(0x02) (>> power off)");
1656 }
1657 
1660 uint32_t WaveshareEPaper7P5InV2::idle_timeout_() { return 10000; }
1662  LOG_DISPLAY("", "Waveshare E-Paper", this);
1663  ESP_LOGCONFIG(TAG, " Model: 7.5inV2rev2");
1664  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1665  LOG_PIN(" DC Pin: ", this->dc_pin_);
1666  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1667  LOG_UPDATE_INTERVAL(this);
1668 }
1669 
1670 /* 7.50inV2alt */
1672  if (this->busy_pin_ == nullptr) {
1673  return true;
1674  }
1675 
1676  const uint32_t start = millis();
1677  while (this->busy_pin_->digital_read()) {
1678  this->command(0x71);
1679  if (millis() - start > this->idle_timeout_()) {
1680  ESP_LOGI(TAG, "Timeout while displaying image!");
1681  return false;
1682  }
1683  delay(10);
1684  }
1685  return true;
1686 }
1687 
1689  this->reset_();
1690 
1691  // COMMAND POWER SETTING
1692  this->command(0x01);
1693 
1694  // 1-0=11: internal power
1695  this->data(0x07);
1696  this->data(0x17); // VGH&VGL
1697  this->data(0x3F); // VSH
1698  this->data(0x26); // VSL
1699  this->data(0x11); // VSHR
1700 
1701  // VCOM DC Setting
1702  this->command(0x82);
1703  this->data(0x24); // VCOM
1704 
1705  // Booster Setting
1706  this->command(0x06);
1707  this->data(0x27);
1708  this->data(0x27);
1709  this->data(0x2F);
1710  this->data(0x17);
1711 
1712  // POWER ON
1713  this->command(0x04);
1714 
1715  delay(100); // NOLINT
1716  this->wait_until_idle_();
1717  // COMMAND PANEL SETTING
1718  this->command(0x00);
1719  this->data(0x3F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
1720 
1721  // COMMAND RESOLUTION SETTING
1722  this->command(0x61);
1723  this->data(0x03); // source 800
1724  this->data(0x20);
1725  this->data(0x01); // gate 480
1726  this->data(0xE0);
1727  // COMMAND ...?
1728  this->command(0x15);
1729  this->data(0x00);
1730  // COMMAND VCOM AND DATA INTERVAL SETTING
1731  this->command(0x50);
1732  this->data(0x10);
1733  this->data(0x00);
1734  // COMMAND TCON SETTING
1735  this->command(0x60);
1736  this->data(0x22);
1737  // Resolution setting
1738  this->command(0x65);
1739  this->data(0x00);
1740  this->data(0x00); // 800*480
1741  this->data(0x00);
1742  this->data(0x00);
1743 
1744  this->wait_until_idle_();
1745 
1746  uint8_t lut_vcom_7_i_n5_v2[] = {
1747  0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0xF, 0x1, 0xF, 0x1, 0x2, 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
1748  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1749  };
1750 
1751  uint8_t lut_ww_7_i_n5_v2[] = {
1752  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
1753  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1754  };
1755 
1756  uint8_t lut_bw_7_i_n5_v2[] = {
1757  0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
1758  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1759  };
1760 
1761  uint8_t lut_wb_7_i_n5_v2[] = {
1762  0x80, 0xF, 0xF, 0x0, 0x0, 0x3, 0x84, 0xF, 0x1, 0xF, 0x1, 0x4, 0x40, 0xF, 0xF, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
1763  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1764  };
1765 
1766  uint8_t lut_bb_7_i_n5_v2[] = {
1767  0x80, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x40, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
1768  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1769  };
1770 
1771  uint8_t count;
1772  this->command(0x20); // VCOM
1773  for (count = 0; count < 42; count++)
1774  this->data(lut_vcom_7_i_n5_v2[count]);
1775 
1776  this->command(0x21); // LUTBW
1777  for (count = 0; count < 42; count++)
1778  this->data(lut_ww_7_i_n5_v2[count]);
1779 
1780  this->command(0x22); // LUTBW
1781  for (count = 0; count < 42; count++)
1782  this->data(lut_bw_7_i_n5_v2[count]);
1783 
1784  this->command(0x23); // LUTWB
1785  for (count = 0; count < 42; count++)
1786  this->data(lut_wb_7_i_n5_v2[count]);
1787 
1788  this->command(0x24); // LUTBB
1789  for (count = 0; count < 42; count++)
1790  this->data(lut_bb_7_i_n5_v2[count]);
1791 }
1792 
1794  LOG_DISPLAY("", "Waveshare E-Paper", this);
1795  ESP_LOGCONFIG(TAG, " Model: 7.5inV2");
1796  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1797  LOG_PIN(" DC Pin: ", this->dc_pin_);
1798  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1799  LOG_UPDATE_INTERVAL(this);
1800 }
1801 
1802 /* 7.50in-bc */
1804  /* The command sequence is similar to the 7P5In display but differs in subtle ways
1805  to allow for faster updates. */
1806  // COMMAND POWER SETTING
1807  this->command(0x01);
1808  this->data(0x37);
1809  this->data(0x00);
1810 
1811  // COMMAND PANEL SETTING
1812  this->command(0x00);
1813  this->data(0xCF);
1814  this->data(0x08);
1815 
1816  // COMMAND PLL CONTROL
1817  this->command(0x30);
1818  this->data(0x3A);
1819 
1820  // COMMAND VCM_DC_SETTING: all temperature range
1821  this->command(0x82);
1822  this->data(0x28);
1823 
1824  // COMMAND BOOSTER SOFT START
1825  this->command(0x06);
1826  this->data(0xC7);
1827  this->data(0xCC);
1828  this->data(0x15);
1829 
1830  // COMMAND VCOM AND DATA INTERVAL SETTING
1831  this->command(0x50);
1832  this->data(0x77);
1833 
1834  // COMMAND TCON SETTING
1835  this->command(0x60);
1836  this->data(0x22);
1837 
1838  // COMMAND FLASH CONTROL
1839  this->command(0x65);
1840  this->data(0x00);
1841 
1842  // COMMAND RESOLUTION SETTING
1843  this->command(0x61);
1844  this->data(0x02); // 640 >> 8
1845  this->data(0x80);
1846  this->data(0x01); // 384 >> 8
1847  this->data(0x80);
1848 
1849  // COMMAND FLASH MODE
1850  this->command(0xE5);
1851  this->data(0x03);
1852 }
1853 
1855  // COMMAND DATA START TRANSMISSION 1
1856  this->command(0x10);
1857  this->start_data_();
1858 
1859  for (size_t i = 0; i < this->get_buffer_length_(); i++) {
1860  // A line of eight source pixels (each a bit in this byte)
1861  uint8_t eight_pixels = this->buffer_[i];
1862 
1863  for (uint8_t j = 0; j < 8; j += 2) {
1864  /* For bichromatic displays, each byte represents two pixels. Each nibble encodes a pixel: 0=white, 3=black,
1865  4=color. Therefore, e.g. 0x44 = two adjacent color pixels, 0x33 is two adjacent black pixels, etc. If you want
1866  to draw using the color pixels, change '0x30' with '0x40' and '0x03' with '0x04' below. */
1867  uint8_t left_nibble = (eight_pixels & 0x80) ? 0x30 : 0x00;
1868  eight_pixels <<= 1;
1869  uint8_t right_nibble = (eight_pixels & 0x80) ? 0x03 : 0x00;
1870  eight_pixels <<= 1;
1871  this->write_byte(left_nibble | right_nibble);
1872  }
1873  App.feed_wdt();
1874  }
1875  this->end_data_();
1876 
1877  // Unlike the 7P5In display, we send the "power on" command here rather than during initialization
1878  // COMMAND POWER ON
1879  this->command(0x04);
1880 
1881  // COMMAND DISPLAY REFRESH
1882  this->command(0x12);
1883 }
1884 
1886 
1888 
1890  LOG_DISPLAY("", "Waveshare E-Paper", this);
1891  ESP_LOGCONFIG(TAG, " Model: 7.5in-bc");
1892  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1893  LOG_PIN(" DC Pin: ", this->dc_pin_);
1894  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1895  LOG_UPDATE_INTERVAL(this);
1896 }
1897 
1899  this->command(0x12); // SWRESET
1900 
1901  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
1902 
1903  this->command(0x46); // Auto Write RAM
1904  this->data(0xF7);
1905 
1906  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
1907 
1908  this->command(0x47); // Auto Write RAM
1909  this->data(0xF7);
1910 
1911  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
1912 
1913  this->command(0x0C); // Soft start setting
1914  this->data(0xAE);
1915  this->data(0xC7);
1916  this->data(0xC3);
1917  this->data(0xC0);
1918  this->data(0x40);
1919 
1920  this->command(0x01); // Set MUX as 527
1921  this->data(0xAF);
1922  this->data(0x02);
1923  this->data(0x01);
1924 
1925  this->command(0x11); // Data entry mode
1926  this->data(0x01);
1927 
1928  this->command(0x44);
1929  this->data(0x00); // RAM x address start at 0
1930  this->data(0x00);
1931  this->data(0x6F); // RAM x address end at 36Fh -> 879
1932  this->data(0x03);
1933 
1934  this->command(0x45);
1935  this->data(0xAF); // RAM y address start at 20Fh;
1936  this->data(0x02);
1937  this->data(0x00); // RAM y address end at 00h;
1938  this->data(0x00);
1939 
1940  this->command(0x3C); // VBD
1941  this->data(0x01); // LUT1, for white
1942 
1943  this->command(0x18);
1944  this->data(0X80);
1945 
1946  this->command(0x22);
1947  this->data(0XB1); // Load Temperature and waveform setting.
1948 
1949  this->command(0x20);
1950 
1951  this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
1952 
1953  this->command(0x4E);
1954  this->data(0x00);
1955  this->data(0x00);
1956 
1957  this->command(0x4F);
1958  this->data(0xAF);
1959  this->data(0x02);
1960 }
1961 
1963  this->command(0x4F);
1964  this->data(0xAf);
1965  this->data(0x02);
1966 
1967  // BLACK
1968  this->command(0x24);
1969  this->start_data_();
1970  this->write_array(this->buffer_, this->get_buffer_length_());
1971  this->end_data_();
1972 
1973  // RED
1974  this->command(0x26);
1975  this->start_data_();
1976  for (size_t i = 0; i < this->get_buffer_length_(); i++)
1977  this->write_byte(0x00);
1978  this->end_data_();
1979 
1980  this->command(0x22);
1981  this->data(0xC7);
1982  this->command(0x20);
1983  delay(100); // NOLINT
1984 }
1985 
1987 
1989 
1991  LOG_DISPLAY("", "Waveshare E-Paper", this);
1992  ESP_LOGCONFIG(TAG, " Model: 7.5in-HD-b");
1993  LOG_PIN(" Reset Pin: ", this->reset_pin_);
1994  LOG_PIN(" DC Pin: ", this->dc_pin_);
1995  LOG_PIN(" Busy Pin: ", this->busy_pin_);
1996  LOG_UPDATE_INTERVAL(this);
1997 }
1998 
1999 static const uint8_t LUT_SIZE_TTGO_DKE_PART = 153;
2000 
2001 static const uint8_t PART_UPDATE_LUT_TTGO_DKE[LUT_SIZE_TTGO_DKE_PART] = {
2002  0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2003  0x0, 0x0, 0x0, 0x0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0,
2004  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2005  0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2006  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2007  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2008  0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
2009  0x0, 0x0, 0x0, 0x0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
2010  // 0x22, 0x17, 0x41, 0x0, 0x32, 0x32
2011 };
2012 
2015  bool partial = this->at_update_ != 0;
2016  this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
2017 
2018  if (partial) {
2019  ESP_LOGI(TAG, "Performing partial e-paper update.");
2020  } else {
2021  ESP_LOGI(TAG, "Performing full e-paper update.");
2022  }
2023 
2024  // start and set up data format
2025  this->command(0x12);
2026  this->wait_until_idle_();
2027 
2028  this->command(0x11);
2029  this->data(0x03);
2030  this->command(0x44);
2031  this->data(1);
2032  this->data(this->get_width_internal() / 8);
2033  this->command(0x45);
2034  this->data(0);
2035  this->data(0);
2036  this->data(this->get_height_internal());
2037  this->data(0);
2038  this->command(0x4e);
2039  this->data(1);
2040  this->command(0x4f);
2041  this->data(0);
2042  this->data(0);
2043 
2044  if (!partial) {
2045  // send data
2046  this->command(0x24);
2047  this->start_data_();
2048  this->write_array(this->buffer_, this->get_buffer_length_());
2049  this->end_data_();
2050 
2051  // commit
2052  this->command(0x20);
2053  this->wait_until_idle_();
2054  } else {
2055  // set up partial update
2056  this->command(0x32);
2057  for (uint8_t v : PART_UPDATE_LUT_TTGO_DKE)
2058  this->data(v);
2059  this->command(0x3F);
2060  this->data(0x22);
2061 
2062  this->command(0x03);
2063  this->data(0x17);
2064  this->command(0x04);
2065  this->data(0x41);
2066  this->data(0x00);
2067  this->data(0x32);
2068  this->command(0x2C);
2069  this->data(0x32);
2070 
2071  this->command(0x37);
2072  this->data(0x00);
2073  this->data(0x00);
2074  this->data(0x00);
2075  this->data(0x00);
2076  this->data(0x00);
2077  this->data(0x40);
2078  this->data(0x00);
2079  this->data(0x00);
2080  this->data(0x00);
2081  this->data(0x00);
2082 
2083  this->command(0x3C);
2084  this->data(0x80);
2085  this->command(0x22);
2086  this->data(0xC0);
2087  this->command(0x20);
2088  this->wait_until_idle_();
2089 
2090  // send data
2091  this->command(0x24);
2092  this->start_data_();
2093  this->write_array(this->buffer_, this->get_buffer_length_());
2094  this->end_data_();
2095 
2096  // commit as partial
2097  this->command(0x22);
2098  this->data(0xCF);
2099  this->command(0x20);
2100  this->wait_until_idle_();
2101 
2102  // data must be sent again on partial update
2103  delay(300); // NOLINT
2104  this->command(0x24);
2105  this->start_data_();
2106  this->write_array(this->buffer_, this->get_buffer_length_());
2107  this->end_data_();
2108  delay(300); // NOLINT
2109  }
2110 
2111  ESP_LOGI(TAG, "Completed e-paper update.");
2112 }
2113 
2116 uint32_t WaveshareEPaper2P13InDKE::idle_timeout_() { return 5000; }
2118  LOG_DISPLAY("", "Waveshare E-Paper", this);
2119  ESP_LOGCONFIG(TAG, " Model: 2.13inDKE");
2120  LOG_PIN(" Reset Pin: ", this->reset_pin_);
2121  LOG_PIN(" DC Pin: ", this->dc_pin_);
2122  LOG_PIN(" Busy Pin: ", this->busy_pin_);
2123  LOG_UPDATE_INTERVAL(this);
2124 }
2125 
2126 void WaveshareEPaper2P13InDKE::set_full_update_every(uint32_t full_update_every) {
2127  this->full_update_every_ = full_update_every;
2128 }
2129 
2130 } // namespace waveshare_epaper
2131 } // namespace esphome
virtual void digital_write(bool value)=0
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)
virtual int get_width_internal()=0
WaveshareEPaperTypeA(WaveshareEPaperTypeAModel model)
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)
void status_clear_warning()
Definition: component.cpp:153
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:145
virtual bool digital_read()=0
virtual int get_height_internal()=0
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
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:26