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