ESPHome 2026.11.0-dev
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
10ESPHOME_LOG_TAG(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
2189 LOG_DISPLAY("", "Waveshare E-Paper (Good Display)", this);
2190 ESP_LOGCONFIG(TAG, " Model: 2.9in Greyscale GDEW029T5");
2191 LOG_PIN(" Reset Pin: ", this->reset_pin_);
2192 LOG_PIN(" DC Pin: ", this->dc_pin_);
2193 LOG_PIN(" Busy Pin: ", this->busy_pin_);
2194 ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
2195 LOG_UPDATE_INTERVAL(this);
2196}
2197
2198// ========================================================
2199// Good Display 1.54in black/white/grey GDEW0154M09
2200// As used in M5Stack Core Ink
2201// Datasheet:
2202// - https://v4.cecdn.yun300.cn/100001_1909185148/GDEW0154M09-200709.pdf
2203// - https://github.com/m5stack/M5Core-Ink
2204// Reference code from GoodDisplay:
2205// - https://github.com/GoodDisplay/E-paper-Display-Library-of-GoodDisplay/
2206// -> /Monochrome_E-paper-Display/1.54inch_JD79653_GDEW0154M09_200x200/ESP32-Arduino%20IDE/GDEW0154M09_Arduino.ino
2207// M5Stack Core Ink spec:
2208// - https://docs.m5stack.com/en/core/coreink
2209// ========================================================
2210
2212 this->init_internal_();
2213 RAMAllocator<uint8_t> allocator;
2214 this->lastbuff_ = allocator.allocate(this->get_buffer_length_());
2215 if (this->lastbuff_ != nullptr) {
2216 memset(this->lastbuff_, 0xff, sizeof(uint8_t) * this->get_buffer_length_());
2217 }
2218 this->clear_();
2219}
2220
2221void GDEW0154M09::reset_() {
2222 // RST is inverse from other einks in this project
2223 if (this->reset_pin_ != nullptr) {
2224 this->reset_pin_->digital_write(false);
2225 delay(10);
2226 this->reset_pin_->digital_write(true);
2227 delay(10);
2228 }
2229}
2230
2231void GDEW0154M09::init_internal_() {
2232 this->reset_();
2233
2234 // clang-format off
2235 // 200x200 resolution: 11
2236 // LUT from OTP: 0
2237 // B/W mode (doesn't work): 1
2238 // scan-up: 1
2239 // shift-right: 1
2240 // booster ON: 1
2241 // no soft reset: 1
2242 const uint8_t panel_setting_1 = 0b11011111;
2243
2244 // VCOM status off 0
2245 // Temp sensing default 1
2246 // VGL Power Off Floating 1
2247 // NORG expect refresh 1
2248 // VCOM Off on displ off 0
2249 const uint8_t panel_setting_2 = 0b01110;
2250
2251 const uint8_t wf_t0154_cz_b3_list[] = {
2252 11, // 11 commands in list
2253 CMD_PSR_PANEL_SETTING, 2, panel_setting_1, panel_setting_2,
2254 CMD_UNDOCUMENTED_0x4D, 1, 0x55,
2255 CMD_UNDOCUMENTED_0xAA, 1, 0x0f,
2256 CMD_UNDOCUMENTED_0xE9, 1, 0x02,
2257 CMD_UNDOCUMENTED_0xB6, 1, 0x11,
2258 CMD_UNDOCUMENTED_0xF3, 1, 0x0a,
2259 CMD_TRES_RESOLUTION_SETTING, 3, 0xc8, 0x00, 0xc8,
2260 CMD_TCON_TCONSETTING, 1, 0x00,
2261 CMD_CDI_VCOM_DATA_INTERVAL, 1, 0xd7,
2262 CMD_PWS_POWER_SAVING, 1, 0x00,
2263 CMD_PON_POWER_ON, 0
2264 };
2265 // clang-format on
2266
2267 this->write_init_list_(wf_t0154_cz_b3_list);
2268 delay(100); // NOLINT
2269 this->wait_until_idle_();
2270}
2271
2272void GDEW0154M09::write_init_list_(const uint8_t *list) {
2273 uint8_t list_limit = list[0];
2274 uint8_t *start_ptr = ((uint8_t *) list + 1);
2275 for (uint8_t i = 0; i < list_limit; i++) {
2276 this->command(*(start_ptr + 0));
2277 for (uint8_t dnum = 0; dnum < *(start_ptr + 1); dnum++) {
2278 this->data(*(start_ptr + 2 + dnum));
2279 }
2280 start_ptr += (*(start_ptr + 1) + 2);
2281 }
2282}
2283
2284void GDEW0154M09::clear_() {
2285 uint32_t pixsize = this->get_buffer_length_();
2286 for (uint8_t j = 0; j < 2; j++) {
2287 this->command(CMD_DTM1_DATA_START_TRANS);
2288 for (uint32_t count = 0; count < pixsize; count++) {
2289 this->data(0x00);
2290 }
2291 this->command(CMD_DTM2_DATA_START_TRANS2);
2292 for (uint32_t count = 0; count < pixsize; count++) {
2293 this->data(0xff);
2294 }
2295 this->command(CMD_DISPLAY_REFRESH);
2296 delay(10);
2297 this->wait_until_idle_();
2298 }
2299}
2300
2302 this->init_internal_();
2303 // "Mode 0 display" for now
2304 this->command(CMD_DTM1_DATA_START_TRANS);
2305 for (uint32_t i = 0; i < this->get_buffer_length_(); i++) {
2306 this->data(0xff);
2307 }
2308 this->command(CMD_DTM2_DATA_START_TRANS2); // write 'new' data to SRAM
2309 for (uint32_t i = 0; i < this->get_buffer_length_(); i++) {
2310 this->data(this->buffer_[i]);
2311 }
2312 this->command(CMD_DISPLAY_REFRESH);
2313 delay(10);
2314 this->wait_until_idle_();
2315 this->deep_sleep();
2316}
2317
2319 // COMMAND DEEP SLEEP
2320 this->command(CMD_POF_POWER_OFF);
2321 this->wait_until_idle_();
2322 delay(1000); // NOLINT
2323 this->command(CMD_DSLP_DEEP_SLEEP);
2324 this->data(DATA_DSLP_DEEP_SLEEP);
2325}
2326
2330 LOG_DISPLAY("", "M5Stack CoreInk E-Paper (Good Display)", this);
2331 ESP_LOGCONFIG(TAG, " Model: 1.54in Greyscale GDEW0154M09");
2332 LOG_PIN(" Reset Pin: ", this->reset_pin_);
2333 LOG_PIN(" DC Pin: ", this->dc_pin_);
2334 LOG_PIN(" Busy Pin: ", this->busy_pin_);
2335 LOG_UPDATE_INTERVAL(this);
2336}
2337
2338// ========================================================
2339// Good Display 4.2in black/white GDEY042T81 (SSD1683)
2340// Product page:
2341// - https://www.good-display.com/product/386.html
2342// Datasheet:
2343// - https://v4.cecdn.yun300.cn/100001_1909185148/GDEY042T81.pdf
2344// - https://v4.cecdn.yun300.cn/100001_1909185148/SSD1683.PDF
2345// Reference code from GoodDisplay:
2346// - https://www.good-display.com/companyfile/1572.html (2024-08-01 15:40:41)
2347// Other reference code:
2348// - https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp
2349// ========================================================
2350
2352 this->init_display_();
2353 ESP_LOGD(TAG, "Initialization complete, set the display to deep sleep");
2354 this->deep_sleep();
2355}
2356
2357// conflicting documentation / examples regarding reset timings
2358// https://v4.cecdn.yun300.cn/100001_1909185148/SSD1683.PDF -> 10ms
2359// GD sample code (Display_EPD_W21.cpp, see above) -> 10 ms
2360// https://v4.cecdn.yun300.cn/100001_1909185148/GDEY042T81.pdf (section 14.2) -> 0.2ms (200us)
2361// https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L351
2362// -> 10ms
2363// 10 ms seems to work, so we use this
2365
2366void GDEY042T81::reset_() {
2367 if (this->reset_pin_ != nullptr) {
2368 this->reset_pin_->digital_write(false);
2369 delay(reset_duration_); // NOLINT
2370 this->reset_pin_->digital_write(true);
2371 delay(reset_duration_); // NOLINT
2372 }
2373}
2374
2375void GDEY042T81::init_display_() {
2376 this->reset_();
2377
2378 this->wait_until_idle_();
2379 this->command(0x12); // SWRESET
2380 this->wait_until_idle_();
2381
2382 // Specify number of lines for the driver: 300 (MUX 300)
2383 // https://v4.cecdn.yun300.cn/100001_1909185148/SSD1683.PDF (section 8.1)
2384 // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L354
2385 this->command(0x01); // driver output control
2386 this->data(0x2B); // (height - 1) % 256
2387 this->data(0x01); // (height - 1) / 256
2388 this->data(0x00);
2389
2390 // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L360
2391 this->command(0x3C); // BorderWaveform
2392 this->data(0x01);
2393 this->command(0x18); // Read built-in temperature sensor
2394 this->data(0x80);
2395
2396 // GD sample code (Display_EPD_W21.cpp@90ff)
2397 this->command(0x11); // data entry mode
2398 this->data(0x03);
2399 // set windows (0,0,400,300)
2400 this->command(0x44); // set Ram-X address start/end position
2401 this->data(0);
2402 this->data(0x31); // (width / 8 -1)
2403
2404 this->command(0x45); // set Ram-y address start/end position
2405 this->data(0);
2406 this->data(0);
2407 this->data(0x2B); // (height - 1) % 256
2408 this->data(0x01); // (height - 1) / 256
2409
2410 // set cursor (0,0)
2411 this->command(0x4E); // set RAM x address count to 0;
2412 this->data(0);
2413 this->command(0x4F); // set RAM y address count to 0;
2414 this->data(0);
2415 this->data(0);
2416
2417 this->wait_until_idle_();
2418}
2419
2420// https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L366
2421void GDEY042T81::update_full_() {
2422 this->command(0x21); // display update control
2423 this->data(0x40); // bypass RED as 0
2424 this->data(0x00); // single chip application
2425
2426 // only ever do a fast update because slow updates are only relevant
2427 // for lower operating temperatures
2428 // see
2429 // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_290_GDEY029T94.h#L30
2430 //
2431 // Should slow/fast updates be made configurable similar to how GxEPD2 does it? No idea if anyone would need it...
2432 this->command(0x1A); // Write to temperature register
2433 this->data(0x6E);
2434 this->command(0x22);
2435 this->data(0xd7);
2436
2437 this->command(0x20);
2438 this->wait_until_idle_();
2439}
2440
2441// https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L389
2442void GDEY042T81::update_part_() {
2443 this->command(0x21); // display update control
2444 this->data(0x00); // RED normal
2445 this->data(0x00); // single chip application
2446
2447 this->command(0x22);
2448 this->data(0xfc);
2449
2450 this->command(0x20);
2451 this->wait_until_idle_();
2452}
2453
2455 ESP_LOGD(TAG, "Wake up the display");
2456 this->init_display_();
2457
2458 if (!this->wait_until_idle_()) {
2459 this->status_set_warning();
2460 ESP_LOGE(TAG, "Failed to perform update, display is busy");
2461 return;
2462 }
2463
2464 // basic code structure copied from WaveshareEPaper2P9InV2R2
2465 if (this->full_update_every_ == 1) {
2466 ESP_LOGD(TAG, "Full update");
2467 // do single full update
2468 this->command(0x24);
2469 this->start_data_();
2470 this->write_array(this->buffer_, this->get_buffer_length_());
2471 this->end_data_();
2472
2473 // TurnOnDisplay
2474 this->update_full_();
2475 return;
2476 }
2477
2478 // if (this->full_update_every_ == 1 ||
2479 if (this->at_update_ == 0) {
2480 ESP_LOGD(TAG, "Update");
2481 // do base update
2482 this->command(0x24);
2483 this->start_data_();
2484 this->write_array(this->buffer_, this->get_buffer_length_());
2485 this->end_data_();
2486
2487 this->command(0x26);
2488 this->start_data_();
2489 this->write_array(this->buffer_, this->get_buffer_length_());
2490 this->end_data_();
2491
2492 // TurnOnDisplay;
2493 this->update_full_();
2494 } else {
2495 // do partial update (full screen)
2496 // no need to load a LUT for GoodDisplays as they seem to have the LUT onboard
2497 // GD example code (Display_EPD_W21.cpp@283ff)
2498 //
2499 // not setting the BorderWaveform here again (contrary to the GD example) because according to
2500 // https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L358
2501 // it seems to be enough to set it during display initialization
2502 ESP_LOGD(TAG, "Partial update");
2503 this->reset_();
2504 if (!this->wait_until_idle_()) {
2505 this->status_set_warning();
2506 ESP_LOGE(TAG, "Failed to perform partial update, display is busy");
2507 return;
2508 }
2509
2510 this->command(0x24);
2511 this->start_data_();
2512 this->write_array(this->buffer_, this->get_buffer_length_());
2513 this->end_data_();
2514
2515 // TurnOnDisplay
2516 this->update_part_();
2517 }
2518
2519 this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
2520 this->wait_until_idle_();
2521 ESP_LOGD(TAG, "Set the display back to deep sleep");
2522 this->deep_sleep();
2523}
2528 LOG_DISPLAY("", "GoodDisplay E-Paper", this);
2529 ESP_LOGCONFIG(TAG,
2530 " Model: 4.2in B/W GDEY042T81\n"
2531 " Full Update Every: %" PRIu32,
2532 this->full_update_every_);
2533 LOG_PIN(" Reset Pin: ", this->reset_pin_);
2534 LOG_PIN(" DC Pin: ", this->dc_pin_);
2535 LOG_PIN(" Busy Pin: ", this->busy_pin_);
2536 LOG_UPDATE_INTERVAL(this);
2537}
2538
2539static const uint8_t LUT_VCOM_DC_4_2[] = {
2540 0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x17, 0x17, 0x00, 0x00, 0x02, 0x00, 0x0A, 0x01,
2541 0x00, 0x00, 0x01, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2543};
2544static const uint8_t LUT_WHITE_TO_WHITE_4_2[] = {
2545 0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A,
2546 0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
2547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2548};
2549static const uint8_t LUT_BLACK_TO_WHITE_4_2[] = {
2550 0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A,
2551 0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
2552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2553};
2554
2555static const uint8_t LUT_BLACK_TO_BLACK_4_2[] = {
2556 0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A,
2557 0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
2558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2559};
2560
2561static const uint8_t LUT_WHITE_TO_BLACK_4_2[] = {
2562 0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A,
2563 0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
2564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2565};
2566
2568 // https://www.waveshare.com/w/upload/7/7f/4.2inch-e-paper-b-specification.pdf - page 8
2569
2570 // COMMAND POWER SETTING
2571 this->command(0x01);
2572 this->data(0x03); // VDS_EN, VDG_EN
2573 this->data(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
2574 this->data(0x2B); // VDH
2575 this->data(0x2B); // VDL
2576 this->data(0xFF); // VDHR
2577
2578 // COMMAND BOOSTER SOFT START
2579 this->command(0x06);
2580 this->data(0x17); // PHA
2581 this->data(0x17); // PHB
2582 this->data(0x17); // PHC
2583
2584 // COMMAND POWER ON
2585 this->command(0x04);
2586 this->wait_until_idle_();
2587 delay(10);
2588 // COMMAND PANEL SETTING
2589 this->command(0x00);
2590 this->data(0xBF); // KW-BF KWR-AF BWROTP 0f
2591 this->data(0x0B);
2592 // COMMAND PLL CONTROL
2593 this->command(0x30);
2594 this->data(0x3C); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
2595
2596 delay(2);
2597 // COMMAND LUT FOR VCOM
2598 this->command(0x20);
2599 for (uint8_t i : LUT_VCOM_DC_4_2)
2600 this->data(i);
2601 // COMMAND LUT WHITE TO WHITE
2602 this->command(0x21);
2603 for (uint8_t i : LUT_WHITE_TO_WHITE_4_2)
2604 this->data(i);
2605 // COMMAND LUT BLACK TO WHITE
2606 this->command(0x22);
2607 for (uint8_t i : LUT_BLACK_TO_WHITE_4_2)
2608 this->data(i);
2609 // COMMAND LUT WHITE TO BLACK
2610 this->command(0x23);
2611 for (uint8_t i : LUT_WHITE_TO_BLACK_4_2)
2612 this->data(i);
2613 // COMMAND LUT BLACK TO BLACK
2614 this->command(0x24);
2615 for (uint8_t i : LUT_BLACK_TO_BLACK_4_2)
2616 this->data(i);
2617}
2619 // COMMAND RESOLUTION SETTING
2620 this->command(0x61);
2621 this->data(0x01);
2622 this->data(0x90);
2623 this->data(0x01);
2624 this->data(0x2C);
2625
2626 // COMMAND VCM DC SETTING REGISTER
2627 this->command(0x82);
2628 this->data(0x12);
2629
2630 // COMMAND VCOM AND DATA INTERVAL SETTING
2631 this->command(0x50);
2632 this->data(0x97);
2633
2634 // COMMAND DATA START TRANSMISSION 1
2635 this->command(0x10);
2636 delay(2);
2637 this->start_data_();
2638 this->write_array(this->buffer_, this->get_buffer_length_());
2639 this->end_data_();
2640 delay(2);
2641 // COMMAND DATA START TRANSMISSION 2
2642 this->command(0x13);
2643 delay(2);
2644 this->start_data_();
2645 this->write_array(this->buffer_, this->get_buffer_length_());
2646 this->end_data_();
2647 // COMMAND DISPLAY REFRESH
2648 this->command(0x12);
2649}
2653 LOG_DISPLAY("", "Waveshare E-Paper", this);
2654 ESP_LOGCONFIG(TAG, " Model: 4.2in");
2655 LOG_PIN(" Reset Pin: ", this->reset_pin_);
2656 LOG_PIN(" DC Pin: ", this->dc_pin_);
2657 LOG_PIN(" Busy Pin: ", this->busy_pin_);
2658 LOG_UPDATE_INTERVAL(this);
2659}
2660
2661// ========================================================
2662// 4.20in Type B (LUT from OTP)
2663// Datasheet:
2664// - https://www.waveshare.com/w/upload/2/20/4.2inch-e-paper-module-user-manual-en.pdf
2665// - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_4in2b_V2.c
2666// ========================================================
2668 // these exact timings are required for a proper reset/init
2669 this->reset_pin_->digital_write(false);
2670 delay(2);
2671 this->reset_pin_->digital_write(true);
2672 delay(200); // NOLINT
2673
2674 // COMMAND POWER ON
2675 this->command(0x04);
2676 this->wait_until_idle_();
2677
2678 // COMMAND PANEL SETTING
2679 this->command(0x00);
2680 this->data(0x0f); // LUT from OTP
2681}
2682
2684 // COMMAND DATA START TRANSMISSION 1 (B/W data)
2685 this->command(0x10);
2686 this->start_data_();
2687 this->write_array(this->buffer_, this->get_buffer_length_());
2688 this->end_data_();
2689
2690 // COMMAND DATA START TRANSMISSION 2 (RED data)
2691 this->command(0x13);
2692 this->start_data_();
2693 for (size_t i = 0; i < this->get_buffer_length_(); i++)
2694 this->write_byte(0xFF);
2695 this->end_data_();
2696 delay(2);
2697
2698 // COMMAND DISPLAY REFRESH
2699 this->command(0x12);
2700 this->wait_until_idle_();
2701
2702 // COMMAND POWER OFF
2703 // NOTE: power off < deep sleep
2704 this->command(0x02);
2705}
2709 LOG_DISPLAY("", "Waveshare E-Paper", this);
2710 ESP_LOGCONFIG(TAG, " Model: 4.2in (B V2)");
2711 LOG_PIN(" Reset Pin: ", this->reset_pin_);
2712 LOG_PIN(" DC Pin: ", this->dc_pin_);
2713 LOG_PIN(" Busy Pin: ", this->busy_pin_);
2714 LOG_UPDATE_INTERVAL(this);
2715}
2716
2717// ========================================================
2718// 4.20in Type B With Red colour support (LUT from OTP)
2719// Datasheet:
2720// - https://www.waveshare.com/w/upload/2/20/4.2inch-e-paper-module-user-manual-en.pdf
2721// - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_4in2b_V2.c
2722// The implementation is an adaptation of WaveshareEPaper4P2InBV2 class
2723// ========================================================
2725 // these exact timings are required for a proper reset/init
2726 this->reset_pin_->digital_write(false);
2727 delay(2);
2728 this->reset_pin_->digital_write(true);
2729 delay(200); // NOLINT
2730
2731 // COMMAND POWER ON
2732 this->command(0x04);
2733 this->wait_until_idle_();
2734
2735 // COMMAND PANEL SETTING
2736 this->command(0x00);
2737 this->data(0x0f); // LUT from OTP
2738}
2739
2741 const uint32_t buf_len = this->get_buffer_length_() / 2u;
2742
2743 this->command(0x10); // Send BW data Transmission
2744 delay(2); // Delay to prevent Watchdog error
2745 for (uint32_t i = 0; i < buf_len; ++i) {
2746 this->data(this->buffer_[i]);
2747 }
2748
2749 this->command(0x13); // Send red data Transmission
2750 delay(2); // Delay to prevent Watchdog error
2751 for (uint32_t i = 0; i < buf_len; ++i) {
2752 // Red color need to flip bit from the buffer. Otherwise, red will conqure the screen!
2753 this->data(~this->buffer_[buf_len + i]);
2754 }
2755
2756 // COMMAND DISPLAY REFRESH
2757 this->command(0x12);
2758 this->wait_until_idle_();
2759
2760 // COMMAND POWER OFF
2761 // NOTE: power off < deep sleep
2762 this->command(0x02);
2763}
2767 LOG_DISPLAY("", "Waveshare E-Paper", this);
2768 ESP_LOGCONFIG(TAG, " Model: 4.2in (B V2) BWR-Mode");
2769 LOG_PIN(" Reset Pin: ", this->reset_pin_);
2770 LOG_PIN(" DC Pin: ", this->dc_pin_);
2771 LOG_PIN(" Busy Pin: ", this->busy_pin_);
2772 LOG_UPDATE_INTERVAL(this);
2773}
2774
2776 // COMMAND POWER SETTING
2777 this->command(0x01);
2778 this->data(0x37);
2779 this->data(0x00);
2780
2781 // COMMAND PANEL SETTING
2782 this->command(0x00);
2783 this->data(0xCF);
2784 this->data(0x0B);
2785
2786 // COMMAND BOOSTER SOFT START
2787 this->command(0x06);
2788 this->data(0xC7);
2789 this->data(0xCC);
2790 this->data(0x28);
2791
2792 // COMMAND POWER ON
2793 this->command(0x04);
2794 this->wait_until_idle_();
2795 delay(10);
2796
2797 // COMMAND PLL CONTROL
2798 this->command(0x30);
2799 this->data(0x3C);
2800
2801 // COMMAND TEMPERATURE SENSOR CALIBRATION
2802 this->command(0x41);
2803 this->data(0x00);
2804
2805 // COMMAND VCOM AND DATA INTERVAL SETTING
2806 this->command(0x50);
2807 this->data(0x77);
2808
2809 // COMMAND TCON SETTING
2810 this->command(0x60);
2811 this->data(0x22);
2812
2813 // COMMAND RESOLUTION SETTING
2814 this->command(0x61);
2815 this->data(0x02);
2816 this->data(0x58);
2817 this->data(0x01);
2818 this->data(0xC0);
2819
2820 // COMMAND VCM DC SETTING REGISTER
2821 this->command(0x82);
2822 this->data(0x1E);
2823
2824 this->command(0xE5);
2825 this->data(0x03);
2826}
2828 // COMMAND DATA START TRANSMISSION 1
2829 this->command(0x10);
2830
2831 this->start_data_();
2832 for (size_t i = 0; i < this->get_buffer_length_(); i++) {
2833 uint8_t temp1 = this->buffer_[i];
2834 for (uint8_t j = 0; j < 8; j++) {
2835 uint8_t temp2;
2836 if (temp1 & 0x80) {
2837 temp2 = 0x03;
2838 } else {
2839 temp2 = 0x00;
2840 }
2841
2842 temp2 <<= 4;
2843 temp1 <<= 1;
2844 j++;
2845 if (temp1 & 0x80) {
2846 temp2 |= 0x03;
2847 } else {
2848 temp2 |= 0x00;
2849 }
2850 temp1 <<= 1;
2851 this->write_byte(temp2);
2852 }
2853
2854 App.feed_wdt();
2855 }
2856 this->end_data_();
2857
2858 // COMMAND DISPLAY REFRESH
2859 this->command(0x12);
2860}
2864 LOG_DISPLAY("", "Waveshare E-Paper", this);
2865 ESP_LOGCONFIG(TAG, " Model: 5.83in");
2866 LOG_PIN(" Reset Pin: ", this->reset_pin_);
2867 LOG_PIN(" DC Pin: ", this->dc_pin_);
2868 LOG_PIN(" Busy Pin: ", this->busy_pin_);
2869 LOG_UPDATE_INTERVAL(this);
2870}
2871
2872// ========================================================
2873// 5.83in V2
2874// Datasheet/Specification/Reference:
2875// - https://www.waveshare.com/w/upload/3/37/5.83inch_e-Paper_V2_Specification.pdf
2876// - https://github.com/waveshare/e-Paper/blob/master/Arduino/epd5in83_V2/epd5in83_V2.cpp
2877// ========================================================
2879 // COMMAND POWER SETTING
2880 this->command(0x01);
2881 this->data(0x07);
2882 this->data(0x07);
2883 this->data(0x3f);
2884 this->data(0x3f);
2885
2886 // COMMAND POWER ON
2887 this->command(0x04);
2888 delay(10);
2889 this->wait_until_idle_();
2890
2891 // PANNEL SETTING
2892 this->command(0x00);
2893 this->data(0x1F);
2894
2895 // COMMAND RESOLUTION SETTING
2896 this->command(0x61);
2897 this->data(0x02);
2898 this->data(0x88);
2899 this->data(0x01);
2900 this->data(0xE0);
2901
2902 this->command(0x15);
2903 this->data(0x00);
2904
2905 // COMMAND TCON SETTING
2906 this->command(0x60);
2907 this->data(0x22);
2908
2909 // Do we need this?
2910 // COMMAND PLL CONTROL
2911 this->command(0x30);
2912 this->data(0x3C); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
2913}
2915 // Reuse the code from WaveshareEPaper4P2In::display()
2916 // COMMAND VCM DC SETTING REGISTER
2917 this->command(0x82);
2918 this->data(0x12);
2919
2920 // COMMAND VCOM AND DATA INTERVAL SETTING
2921 this->command(0x50);
2922 this->data(0x97);
2923
2924 // COMMAND DATA START TRANSMISSION 1
2925 this->command(0x10);
2926 delay(2);
2927 this->start_data_();
2928 this->write_array(this->buffer_, this->get_buffer_length_());
2929 this->end_data_();
2930 delay(2);
2931
2932 // COMMAND DATA START TRANSMISSION 2
2933 this->command(0x13);
2934 delay(2);
2935 this->start_data_();
2936 this->write_array(this->buffer_, this->get_buffer_length_());
2937 this->end_data_();
2938
2939 // COMMAND DISPLAY REFRESH
2940 this->command(0x12);
2941}
2945 LOG_DISPLAY("", "Waveshare E-Paper", this);
2946 ESP_LOGCONFIG(TAG, " Model: 5.83inv2");
2947 LOG_PIN(" Reset Pin: ", this->reset_pin_);
2948 LOG_PIN(" DC Pin: ", this->dc_pin_);
2949 LOG_PIN(" Busy Pin: ", this->busy_pin_);
2950 LOG_UPDATE_INTERVAL(this);
2951}
2952
2953// ========================================================
2954// Good Display 5.83in black/white GDEY0583T81
2955// Product page:
2956// - https://www.good-display.com/product/440.html
2957// - https://www.seeedstudio.com/5-83-Monochrome-ePaper-Display-with-648x480-Pixels-p-5785.html
2958// Datasheet:
2959// -
2960// https://www.good-display.com/public/html/pdfjs/viewer/viewernew.html?file=https://v4.cecdn.yun300.cn/100001_1909185148/GDEY0583T81-new.pdf
2961// - https://v4.cecdn.yun300.cn/100001_1909185148/GDEY0583T81-new.pdf
2962// Reference code from GoodDisplay:
2963// - https://www.good-display.com/companyfile/903.html
2964// ========================================================
2965
2967 // Allocate buffer for old data for partial updates
2968 RAMAllocator<uint8_t> allocator{};
2969 this->old_buffer_ = allocator.allocate(this->get_buffer_length_());
2970 if (this->old_buffer_ == nullptr) {
2971 ESP_LOGE(TAG, "Could not allocate old buffer for display!");
2972 return;
2973 }
2974 memset(this->old_buffer_, 0xFF, this->get_buffer_length_());
2975
2976 this->init_full_();
2977
2978 this->wait_until_idle_();
2979
2980 this->deep_sleep();
2981}
2982
2983void GDEY0583T81::power_on_() {
2984 if (!this->power_is_on_) {
2985 this->command(0x04);
2986 this->wait_until_idle_();
2987 }
2988 this->power_is_on_ = true;
2989 this->is_deep_sleep_ = false;
2990}
2991
2992void GDEY0583T81::power_off_() {
2993 this->command(0x02);
2994 this->wait_until_idle_();
2995 this->power_is_on_ = false;
2996}
2997
2999 if (this->is_deep_sleep_) {
3000 return;
3001 }
3002
3003 // VCOM and data interval setting (CDI)
3004 this->command(0x50);
3005 this->data(0xf7);
3006
3007 this->power_off_();
3008 delay(10);
3009
3010 // Deep sleep (DSLP)
3011 this->command(0x07);
3012 this->data(0xA5);
3013 this->is_deep_sleep_ = true;
3014}
3015
3016void GDEY0583T81::reset_() {
3017 if (this->reset_pin_ != nullptr) {
3018 this->reset_pin_->digital_write(false);
3019 delay(10);
3020 this->reset_pin_->digital_write(true);
3021 delay(10);
3022 }
3023}
3024
3025// Initialize for full screen update in fast mode
3026void GDEY0583T81::init_full_() {
3027 this->init_display_();
3028
3029 // Based on the GD sample code
3030 // VCOM and data interval setting (CDI)
3031 this->command(0x50);
3032 this->data(0x29);
3033 this->data(0x07);
3034
3035 // Cascade Setting (CCSET)
3036 this->command(0xE0);
3037 this->data(0x02);
3038
3039 // Force Temperature (TSSET)
3040 this->command(0xE5);
3041 this->data(0x5A);
3042}
3043
3044// Initialize for a partial update of the full screen
3045void GDEY0583T81::init_partial_() {
3046 this->init_display_();
3047
3048 // Cascade Setting (CCSET)
3049 this->command(0xE0);
3050 this->data(0x02);
3051
3052 // Force Temperature (TSSET)
3053 this->command(0xE5);
3054 this->data(0x6E);
3055}
3056
3057void GDEY0583T81::init_display_() {
3058 this->reset_();
3059
3060 // Panel Setting (PSR)
3061 this->command(0x00);
3062 // Sets: REG=0, LUT from OTP (set by CDI)
3063 // KW/R=1, Sets KW mode (Black/White)
3064 // as opposed to the default KWR mode (Black/White/Red)
3065 // UD=1, Gate Scan Direction, 1 = up (default)
3066 // SHL=1, Source Shift Direction, 1 = right (default)
3067 // SHD_N=1, Booster Switch, 1 = ON (default)
3068 // RST_N=1, Soft reset, 1 = No effect (default)
3069 this->data(0x1F);
3070
3071 // Resolution setting (TRES)
3072 this->command(0x61);
3073
3074 // Horizontal display resolution (HRES)
3075 this->data(get_width_internal() / 256);
3076 this->data(get_width_internal() % 256);
3077
3078 // Vertical display resolution (VRES)
3079 this->data(get_height_internal() / 256);
3080 this->data(get_height_internal() % 256);
3081
3082 this->power_on_();
3083}
3084
3086 bool full_update = this->at_update_ == 0;
3087 if (full_update) {
3088 this->init_full_();
3089 } else {
3090 this->init_partial_();
3091
3092 // VCOM and data interval setting (CDI)
3093 this->command(0x50);
3094 this->data(0xA9);
3095 this->data(0x07);
3096
3097 // Partial In (PTIN), makes the display enter partial mode
3098 this->command(0x91);
3099
3100 // Partial Window (PTL)
3101 // We use the full screen as the window
3102 this->command(0x90);
3103
3104 // Horizontal start/end channel bank (HRST/HRED)
3105 this->data(0);
3106 this->data(0);
3107 this->data((get_width_internal() - 1) / 256);
3108 this->data((get_width_internal() - 1) % 256);
3109
3110 // Vertical start/end line (VRST/VRED)
3111 this->data(0);
3112 this->data(0);
3113 this->data((get_height_internal() - 1) / 256);
3114 this->data((get_height_internal() - 1) % 256);
3115
3116 this->data(0x01);
3117
3118 // Display Start Transmission 1 (DTM1)
3119 // in KW mode this writes "OLD" data to SRAM
3120 this->command(0x10);
3121 this->start_data_();
3122 this->write_array(this->old_buffer_, this->get_buffer_length_());
3123 this->end_data_();
3124 }
3125
3126 // Display Start Transmission 2 (DTM2)
3127 // in KW mode this writes "NEW" data to SRAM
3128 this->command(0x13);
3129 this->start_data_();
3130 this->write_array(this->buffer_, this->get_buffer_length_());
3131 this->end_data_();
3132
3133 for (size_t i = 0; i < this->get_buffer_length_(); i++) {
3134 this->old_buffer_[i] = this->buffer_[i];
3135 }
3136
3137 // Display Refresh (DRF)
3138 this->command(0x12);
3139 delay(10);
3140 this->wait_until_idle_();
3141
3142 if (full_update) {
3143 ESP_LOGD(TAG, "Full update done");
3144 } else {
3145 // Partial out (PTOUT), makes the display exit partial mode
3146 this->command(0x92);
3147 ESP_LOGD(TAG, "Partial update done, next full update after %" PRIu32 " cycles",
3148 this->full_update_every_ - this->at_update_ - 1);
3149 }
3150
3151 this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
3152
3153 this->deep_sleep();
3154}
3155
3160 LOG_DISPLAY("", "GoodDisplay E-Paper", this);
3161 ESP_LOGCONFIG(TAG,
3162 " Model: 5.83in B/W GDEY0583T81\n"
3163 " Full Update Every: %" PRIu32,
3164 this->full_update_every_);
3165 LOG_PIN(" Reset Pin: ", this->reset_pin_);
3166 LOG_PIN(" DC Pin: ", this->dc_pin_);
3167 LOG_PIN(" Busy Pin: ", this->busy_pin_);
3168 LOG_UPDATE_INTERVAL(this);
3169}
3170
3172 // COMMAND POWER SETTING
3173 this->command(0x01);
3174 this->data(0x07);
3175 this->data(0x07); // VGH=20V,VGL=-20V
3176 this->data(0x3f); // VDH=15V
3177 this->data(0x3f); // VDL=-15V
3178 // COMMAND POWER ON
3179 this->command(0x04);
3180 delay(100); // NOLINT
3181 this->wait_until_idle_();
3182 // COMMAND PANEL SETTING
3183 this->command(0x00);
3184 this->data(0x0F); // KW3f, KWR-2F, BWROTP 0f, BWOTP 1f
3185 this->command(0x61); // tres
3186 this->data(0x03); // 800px
3187 this->data(0x20);
3188 this->data(0x01); // 400px
3189 this->data(0xE0);
3190 this->command(0x15);
3191 this->data(0x00);
3192 // COMMAND VCOM AND DATA INTERVAL SETTING
3193 this->command(0x50);
3194 this->data(0x11);
3195 this->data(0x07);
3196 // COMMAND TCON SETTING
3197 this->command(0x60);
3198 this->data(0x22);
3199
3200 this->command(0x82);
3201 this->data(0x08);
3202 this->command(0x30);
3203 this->data(0x06);
3204
3205 // COMMAND RESOLUTION SETTING
3206 this->command(0x65);
3207 this->data(0x00);
3208 this->data(0x00); // 800*480
3209 this->data(0x00);
3210 this->data(0x00);
3211}
3213 // COMMAND DATA START TRANSMISSION 1 (B/W data)
3214 this->command(0x10);
3215 delay(2);
3216 this->start_data_();
3217 this->write_array(this->buffer_, this->get_buffer_length_());
3218 this->end_data_();
3219 delay(2);
3220
3221 // COMMAND DATA START TRANSMISSION 2 (RED data)
3222 this->command(0x13);
3223 delay(2);
3224 this->start_data_();
3225 for (size_t i = 0; i < this->get_buffer_length_(); i++)
3226 this->write_byte(0x00);
3227 this->end_data_();
3228 delay(2);
3229
3230 // COMMAND DISPLAY REFRESH
3231 this->command(0x12);
3232 delay(100); // NOLINT
3233 this->wait_until_idle_();
3234 this->deep_sleep();
3235}
3239 LOG_DISPLAY("", "Waveshare E-Paper", this);
3240 ESP_LOGCONFIG(TAG, " Model: 7.5in-bv2");
3241 LOG_PIN(" Reset Pin: ", this->reset_pin_);
3242 LOG_PIN(" DC Pin: ", this->dc_pin_);
3243 LOG_PIN(" Busy Pin: ", this->busy_pin_);
3244 LOG_UPDATE_INTERVAL(this);
3245}
3246
3249 if (this->busy_pin_ == nullptr) {
3250 return true;
3251 }
3252
3253 const uint32_t start = millis();
3254 while (this->busy_pin_->digital_read()) {
3255 this->command(0x71);
3256 if (millis() - start > this->idle_timeout_()) {
3257 ESP_LOGI(TAG, "Timeout while displaying image!");
3258 return false;
3259 }
3260 App.feed_wdt();
3261 delay(10);
3262 }
3263 delay(200); // NOLINT
3264 return true;
3265};
3267 this->reset_();
3268
3269 // COMMAND POWER SETTING
3270 this->command(0x01);
3271
3272 // 1-0=11: internal power
3273 this->data(0x07);
3274 this->data(0x17); // VGH&VGL
3275 this->data(0x3F); // VSH
3276 this->data(0x26); // VSL
3277 this->data(0x11); // VSHR
3278
3279 // VCOM DC Setting
3280 this->command(0x82);
3281 this->data(0x24); // VCOM
3282
3283 // Booster Setting
3284 this->command(0x06);
3285 this->data(0x27);
3286 this->data(0x27);
3287 this->data(0x2F);
3288 this->data(0x17);
3289
3290 // POWER ON
3291 this->command(0x04);
3292
3293 delay(100); // NOLINT
3294 this->wait_until_idle_();
3295 // COMMAND PANEL SETTING
3296 this->command(0x00);
3297 this->data(0x3F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
3298
3299 // COMMAND RESOLUTION SETTING
3300 this->command(0x61);
3301 this->data(0x03); // source 800
3302 this->data(0x20);
3303 this->data(0x01); // gate 480
3304 this->data(0xE0);
3305 // COMMAND ...?
3306 this->command(0x15);
3307 this->data(0x00);
3308 // COMMAND VCOM AND DATA INTERVAL SETTING
3309 this->command(0x50);
3310 this->data(0x10);
3311 this->data(0x00);
3312 // COMMAND TCON SETTING
3313 this->command(0x60);
3314 this->data(0x22);
3315 // Resolution setting
3316 this->command(0x65);
3317 this->data(0x00);
3318 this->data(0x00); // 800*480
3319 this->data(0x00);
3320 this->data(0x00);
3321
3322 uint8_t lut_vcom_7_i_n5_v2[] = {
3323 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0xF, 0x1, 0xF, 0x1, 0x2, 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
3324 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3325 };
3326
3327 uint8_t lut_ww_7_i_n5_v2[] = {
3328 0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
3329 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3330 };
3331
3332 uint8_t lut_bw_7_i_n5_v2[] = {
3333 0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
3334 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3335 };
3336
3337 uint8_t lut_wb_7_i_n5_v2[] = {
3338 0x80, 0xF, 0xF, 0x0, 0x0, 0x3, 0x84, 0xF, 0x1, 0xF, 0x1, 0x4, 0x40, 0xF, 0xF, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
3339 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3340 };
3341
3342 uint8_t lut_bb_7_i_n5_v2[] = {
3343 0x80, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x40, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
3344 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3345 };
3346
3347 uint8_t count;
3348 this->command(0x20); // VCOM
3349 for (count = 0; count < 42; count++)
3350 this->data(lut_vcom_7_i_n5_v2[count]);
3351
3352 this->command(0x21); // LUTBW
3353 for (count = 0; count < 42; count++)
3354 this->data(lut_ww_7_i_n5_v2[count]);
3355
3356 this->command(0x22); // LUTBW
3357 for (count = 0; count < 42; count++)
3358 this->data(lut_bw_7_i_n5_v2[count]);
3359
3360 this->command(0x23); // LUTWB
3361 for (count = 0; count < 42; count++)
3362 this->data(lut_wb_7_i_n5_v2[count]);
3363
3364 this->command(0x24); // LUTBB
3365 for (count = 0; count < 42; count++)
3366 this->data(lut_bb_7_i_n5_v2[count]);
3367};
3369 this->init_display_();
3370 uint32_t buf_len = this->get_buffer_length_();
3371
3372 this->command(0x10);
3373 for (uint32_t i = 0; i < buf_len; i++) {
3374 this->data(0xFF);
3375 }
3376
3377 this->command(0x13); // Start Transmission
3378 delay(2);
3379 for (uint32_t i = 0; i < buf_len; i++) {
3380 this->data(~this->buffer_[i]);
3381 }
3382
3383 this->command(0x12); // Display Refresh
3384 delay(100); // NOLINT
3385 this->wait_until_idle_();
3386 this->deep_sleep();
3387}
3391 LOG_DISPLAY("", "Waveshare E-Paper", this);
3392 ESP_LOGCONFIG(TAG, " Model: 7.5in-bv3");
3393 LOG_PIN(" Reset Pin: ", this->reset_pin_);
3394 LOG_PIN(" DC Pin: ", this->dc_pin_);
3395 LOG_PIN(" Busy Pin: ", this->busy_pin_);
3396 LOG_UPDATE_INTERVAL(this);
3397}
3398
3401 if (this->busy_pin_ == nullptr) {
3402 return true;
3403 }
3404
3405 const uint32_t start = millis();
3406 while (this->busy_pin_->digital_read()) {
3407 this->command(0x71);
3408 if (millis() - start > this->idle_timeout_()) {
3409 ESP_LOGI(TAG, "Timeout while displaying image!");
3410 return false;
3411 }
3412 App.feed_wdt();
3413 delay(10);
3414 }
3415 delay(200); // NOLINT
3416 return true;
3417};
3419 this->reset_();
3420
3421 // COMMAND POWER SETTING
3422 this->command(0x01);
3423
3424 // 1-0=11: internal power
3425 this->data(0x07); // VRS_EN=1, VS_EN=1, VG_EN=1
3426 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
3427 this->data(0x3F); // VSH=15V?
3428 this->data(0x26); // VSL=-9.4V?
3429 this->data(0x11); // VSHR=5.8V?
3430
3431 // VCOM DC Setting
3432 this->command(0x82);
3433 this->data(0x24); // VCOM=-1.9V
3434
3435 // POWER ON
3436 this->command(0x04);
3437 delay(100); // NOLINT
3438 this->wait_until_idle_();
3439
3440 // COMMAND PANEL SETTING
3441 this->command(0x00);
3442 this->data(0x0F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
3443
3444 // COMMAND RESOLUTION SETTING
3445 this->command(0x61);
3446 this->data(0x03); // source 800
3447 this->data(0x20);
3448 this->data(0x01); // gate 480
3449 this->data(0xE0);
3450
3451 // COMMAND VCOM AND DATA INTERVAL SETTING
3452 this->command(0x50);
3453 this->data(0x20);
3454 this->data(0x00);
3455
3456 // COMMAND TCON SETTING
3457 this->command(0x60);
3458 this->data(0x22);
3459
3460 // Resolution setting
3461 this->command(0x65);
3462 this->data(0x00);
3463 this->data(0x00); // 800*480
3464 this->data(0x00);
3465 this->data(0x00);
3466};
3468 this->init_display_();
3469 const uint32_t buf_len = this->get_buffer_length_() / 2u;
3470
3471 this->command(0x10); // Send BW data Transmission
3472 delay(2);
3473 for (uint32_t i = 0; i < buf_len; i++) {
3474 this->data(this->buffer_[i]);
3475 }
3476
3477 this->command(0x13); // Send red data Transmission
3478 delay(2);
3479 for (uint32_t i = 0; i < buf_len; i++) {
3480 this->data(this->buffer_[i + buf_len]);
3481 }
3482
3483 this->command(0x12); // Display Refresh
3484 delay(100); // NOLINT
3485 this->wait_until_idle_();
3486 this->deep_sleep();
3487}
3491 LOG_DISPLAY("", "Waveshare E-Paper", this);
3492 ESP_LOGCONFIG(TAG, " Model: 7.5in-bv3 BWR-Mode");
3493 LOG_PIN(" Reset Pin: ", this->reset_pin_);
3494 LOG_PIN(" DC Pin: ", this->dc_pin_);
3495 LOG_PIN(" Busy Pin: ", this->busy_pin_);
3496 LOG_UPDATE_INTERVAL(this);
3497}
3498
3500 // COMMAND POWER SETTING
3501 this->command(0x01);
3502 this->data(0x37);
3503 this->data(0x00);
3504 // COMMAND PANEL SETTING
3505 this->command(0x00);
3506 this->data(0xCF);
3507 this->data(0x0B);
3508 // COMMAND BOOSTER SOFT START
3509 this->command(0x06);
3510 this->data(0xC7);
3511 this->data(0xCC);
3512 this->data(0x28);
3513 // COMMAND POWER ON
3514 this->command(0x04);
3515 this->wait_until_idle_();
3516 delay(10);
3517 // COMMAND PLL CONTROL
3518 this->command(0x30);
3519 this->data(0x3C);
3520 // COMMAND TEMPERATURE SENSOR CALIBRATION
3521 this->command(0x41);
3522 this->data(0x00);
3523 // COMMAND VCOM AND DATA INTERVAL SETTING
3524 this->command(0x50);
3525 this->data(0x77);
3526 // COMMAND TCON SETTING
3527 this->command(0x60);
3528 this->data(0x22);
3529 // COMMAND RESOLUTION SETTING
3530 this->command(0x61);
3531 this->data(0x02);
3532 this->data(0x80);
3533 this->data(0x01);
3534 this->data(0x80);
3535 // COMMAND VCM DC SETTING REGISTER
3536 this->command(0x82);
3537 this->data(0x1E);
3538 this->command(0xE5);
3539 this->data(0x03);
3540}
3542 // COMMAND DATA START TRANSMISSION 1
3543 this->command(0x10);
3544 this->start_data_();
3545 for (size_t i = 0; i < this->get_buffer_length_(); i++) {
3546 uint8_t temp1 = this->buffer_[i];
3547 for (uint8_t j = 0; j < 8; j++) {
3548 uint8_t temp2;
3549 if (temp1 & 0x80) {
3550 temp2 = 0x03;
3551 } else {
3552 temp2 = 0x00;
3553 }
3554 temp2 <<= 4;
3555 temp1 <<= 1;
3556 j++;
3557 if (temp1 & 0x80) {
3558 temp2 |= 0x03;
3559 } else {
3560 temp2 |= 0x00;
3561 }
3562 temp1 <<= 1;
3563 this->write_byte(temp2);
3564 }
3565 App.feed_wdt();
3566 }
3567 this->end_data_();
3568 // COMMAND DISPLAY REFRESH
3569 this->command(0x12);
3570}
3574 LOG_DISPLAY("", "Waveshare E-Paper", this);
3575 ESP_LOGCONFIG(TAG, " Model: 7.5in");
3576 LOG_PIN(" Reset Pin: ", this->reset_pin_);
3577 LOG_PIN(" DC Pin: ", this->dc_pin_);
3578 LOG_PIN(" Busy Pin: ", this->busy_pin_);
3579 LOG_UPDATE_INTERVAL(this);
3580}
3581
3582// Waveshare 5.65F ========================================================
3583
3584namespace cmddata_5P65InF {
3585// WaveshareEPaper5P65InF commands
3586// https://www.waveshare.com/wiki/5.65inch_e-Paper_Module_(F)
3587
3588// R00H (PSR): Panel setting Register
3589// UD(1): scan up
3590// SHL(1) shift right
3591// SHD_N(1) DC-DC on
3592// RST_N(1) no reset
3593static const uint8_t R00_CMD_PSR[] = {0x00, 0xEF, 0x08};
3594
3595// R01H (PWR): Power setting Register
3596// internal DC-DC power generation
3597static const uint8_t R01_CMD_PWR[] = {0x01, 0x07, 0x00, 0x00, 0x00};
3598
3599// R02H (POF): Power OFF Command
3600static const uint8_t R02_CMD_POF[] = {0x02};
3601
3602// R03H (PFS): Power off sequence setting Register
3603// T_VDS_OFF (00) = 1 frame
3604static const uint8_t R03_CMD_PFS[] = {0x03, 0x00};
3605
3606// R04H (PON): Power ON Command
3607static const uint8_t R04_CMD_PON[] = {0x04};
3608
3609// R06h (BTST): Booster Soft Start
3610static const uint8_t R06_CMD_BTST[] = {0x06, 0xC7, 0xC7, 0x1D};
3611
3612// R07H (DSLP): Deep sleep#
3613// Note Documentation @ Waveshare shows cmd code as 0x10 in table, but
3614// 0x10 is DTM1.
3615static const uint8_t R07_CMD_DSLP[] = {0x07, 0xA5};
3616
3617// R10H (DTM1): Data Start Transmission 1
3618
3619static const uint8_t R10_CMD_DTM1[] = {0x10};
3620
3621// R11H (DSP): Data Stop
3622static const uint8_t R11_CMD_DSP[] = {0x11};
3623
3624// R12H (DRF): Display Refresh
3625static const uint8_t R12_CMD_DRF[] = {0x12};
3626
3627// R13H (IPC): Image Process Command
3628static const uint8_t R13_CMD_IPC[] = {0x13, 0x00};
3629
3630// R30H (PLL): PLL Control
3631// 0x3C = 50Hz
3632static const uint8_t R30_CMD_PLL[] = {0x30, 0x3C};
3633
3634// R41H (TSE): Temperature Sensor Enable
3635// TSE(0) enable, TO(0000) +0 degree offset
3636static const uint8_t R41_CMD_TSE[] = {0x41, 0x00};
3637
3638// R50H (CDI) VCOM and Data interval setting
3639// CDI(0111) 10
3640// DDX(1), VBD(001) Border output "White"
3641static const uint8_t R50_CMD_CDI[] = {0x50, 0x37};
3642
3643// R60H (TCON) Gate and Source non overlap period command
3644// S2G(10) 12 units
3645// G2S(10) 12 units
3646static const uint8_t R60_CMD_TCON[] = {0x60, 0x22};
3647
3648// R61H (TRES) Resolution Setting
3649// 0x258 = 600
3650// 0x1C0 = 448
3651static const uint8_t R61_CMD_TRES[] = {0x61, 0x02, 0x58, 0x01, 0xC0};
3652
3653// RE3H (PWS) Power Savings
3654static const uint8_t RE3_CMD_PWS[] = {0xE3, 0xAA};
3655} // namespace cmddata_5P65InF
3656
3658 if (this->buffers_[0] == nullptr) {
3659 ESP_LOGE(TAG, "Buffer unavailable!");
3660 return;
3661 }
3662
3663 this->reset_();
3664 delay(20);
3665 this->wait_until_(IDLE);
3666
3667 using namespace cmddata_5P65InF;
3668
3669 this->cmd_data(R00_CMD_PSR, sizeof(R00_CMD_PSR));
3670 this->cmd_data(R01_CMD_PWR, sizeof(R01_CMD_PWR));
3671 this->cmd_data(R03_CMD_PFS, sizeof(R03_CMD_PFS));
3672 this->cmd_data(R06_CMD_BTST, sizeof(R06_CMD_BTST));
3673 this->cmd_data(R30_CMD_PLL, sizeof(R30_CMD_PLL));
3674 this->cmd_data(R41_CMD_TSE, sizeof(R41_CMD_TSE));
3675 this->cmd_data(R50_CMD_CDI, sizeof(R50_CMD_CDI));
3676 this->cmd_data(R60_CMD_TCON, sizeof(R60_CMD_TCON));
3677 this->cmd_data(R61_CMD_TRES, sizeof(R61_CMD_TRES));
3678 this->cmd_data(RE3_CMD_PWS, sizeof(RE3_CMD_PWS));
3679
3680 delay(100); // NOLINT
3681 this->cmd_data(R50_CMD_CDI, sizeof(R50_CMD_CDI));
3682
3683 ESP_LOGI(TAG, "Display initialized successfully");
3684}
3685
3687 // INITIALIZATION
3688 ESP_LOGI(TAG, "Initialise the display");
3689 this->initialize();
3690
3691 using namespace cmddata_5P65InF;
3692
3693 // COMMAND DATA START TRANSMISSION
3694 ESP_LOGI(TAG, "Sending data to the display");
3695 this->cmd_data(R61_CMD_TRES, sizeof(R61_CMD_TRES));
3696 this->cmd_data(R10_CMD_DTM1, sizeof(R10_CMD_DTM1));
3697 this->send_buffers_();
3698
3699 // COMMAND POWER ON
3700 ESP_LOGI(TAG, "Power on the display");
3701 this->cmd_data(R04_CMD_PON, sizeof(R04_CMD_PON));
3702 this->wait_until_(IDLE);
3703
3704 // COMMAND REFRESH SCREEN
3705 ESP_LOGI(TAG, "Refresh the display");
3706 this->cmd_data(R12_CMD_DRF, sizeof(R12_CMD_DRF));
3707 this->wait_until_(IDLE);
3708
3709 // COMMAND POWER OFF
3710 ESP_LOGI(TAG, "Power off the display");
3711 this->cmd_data(R02_CMD_POF, sizeof(R02_CMD_POF));
3712 this->wait_until_(BUSY);
3713
3714 if (this->deep_sleep_between_updates_) {
3715 ESP_LOGI(TAG, "Set the display to deep sleep");
3716 this->cmd_data(R07_CMD_DSLP, sizeof(R07_CMD_DSLP));
3717 }
3718}
3719
3723
3725 LOG_DISPLAY("", "Waveshare E-Paper", this);
3726 ESP_LOGCONFIG(TAG, " Model: 5.65in-F");
3727 LOG_PIN(" Reset Pin: ", this->reset_pin_);
3728 LOG_PIN(" DC Pin: ", this->dc_pin_);
3729 LOG_PIN(" Busy Pin: ", this->busy_pin_);
3730 LOG_UPDATE_INTERVAL(this);
3731}
3732
3734 if (this->busy_pin_ == nullptr) {
3735 return true;
3736 }
3737
3738 const uint32_t start = millis();
3739 while (busy_state != this->busy_pin_->digital_read()) {
3740 if (millis() - start > this->idle_timeout_()) {
3741 ESP_LOGE(TAG, "Timeout while displaying image!");
3742 return false;
3743 }
3744 App.feed_wdt();
3745 delay(10);
3746 }
3747 return true;
3748}
3749
3751 if (this->buffers_[0] == nullptr) {
3752 ESP_LOGE(TAG, "Buffer unavailable!");
3753 return;
3754 }
3755
3756 this->reset_();
3757 delay(20);
3758 this->wait_until_idle_();
3759
3760 // COMMAND CMDH
3761 this->command(0xAA);
3762 this->data(0x49);
3763 this->data(0x55);
3764 this->data(0x20);
3765 this->data(0x08);
3766 this->data(0x09);
3767 this->data(0x18);
3768
3769 this->command(0x01);
3770 this->data(0x3F);
3771 this->data(0x00);
3772 this->data(0x32);
3773 this->data(0x2A);
3774 this->data(0x0E);
3775 this->data(0x2A);
3776
3777 this->command(0x00);
3778 this->data(0x5F);
3779 this->data(0x69);
3780
3781 this->command(0x03);
3782 this->data(0x00);
3783 this->data(0x54);
3784 this->data(0x00);
3785 this->data(0x44);
3786
3787 this->command(0x05);
3788 this->data(0x40);
3789 this->data(0x1F);
3790 this->data(0x1F);
3791 this->data(0x2C);
3792
3793 this->command(0x06);
3794 this->data(0x6F);
3795 this->data(0x1F);
3796 this->data(0x1F);
3797 this->data(0x22);
3798
3799 this->command(0x08);
3800 this->data(0x6F);
3801 this->data(0x1F);
3802 this->data(0x1F);
3803 this->data(0x22);
3804
3805 // COMMAND IPC
3806 this->command(0x13);
3807 this->data(0x00);
3808 this->data(0x04);
3809
3810 this->command(0x30);
3811 this->data(0x3C);
3812
3813 // COMMAND TSE
3814 this->command(0x41);
3815 this->data(0x00);
3816
3817 this->command(0x50);
3818 this->data(0x3F);
3819
3820 this->command(0x60);
3821 this->data(0x02);
3822 this->data(0x00);
3823
3824 this->command(0x61);
3825 this->data(0x03);
3826 this->data(0x20);
3827 this->data(0x01);
3828 this->data(0xE0);
3829
3830 this->command(0x82);
3831 this->data(0x1E);
3832
3833 this->command(0x84);
3834 this->data(0x00);
3835
3836 // COMMAND AGID
3837 this->command(0x86);
3838 this->data(0x00);
3839
3840 this->command(0xE3);
3841 this->data(0x2F);
3842
3843 // COMMAND CCSET
3844 this->command(0xE0);
3845 this->data(0x00);
3846
3847 // COMMAND TSSET
3848 this->command(0xE6);
3849 this->data(0x00);
3850
3851 ESP_LOGI(TAG, "Display initialized successfully");
3852}
3854 // INITIALIZATION
3855 ESP_LOGI(TAG, "Initialise the display");
3856 this->initialize();
3857
3858 // COMMAND DATA START TRANSMISSION
3859 ESP_LOGI(TAG, "Sending data to the display");
3860 this->command(0x10);
3861 this->send_buffers_();
3862
3863 // COMMAND POWER ON
3864 ESP_LOGI(TAG, "Power on the display");
3865 this->command(0x04);
3866 this->wait_until_idle_();
3867
3868 // COMMAND REFRESH SCREEN
3869 ESP_LOGI(TAG, "Refresh the display");
3870 this->command(0x12);
3871 this->data(0x00);
3872 this->wait_until_idle_();
3873
3874 // COMMAND POWER OFF
3875 ESP_LOGI(TAG, "Power off the display");
3876 this->command(0x02);
3877 this->data(0x00);
3878 this->wait_until_idle_();
3879
3880 if (this->deep_sleep_between_updates_) {
3881 ESP_LOGI(TAG, "Set the display to deep sleep");
3882 this->command(0x07);
3883 this->data(0xA5);
3884 }
3885}
3890 LOG_DISPLAY("", "Waveshare E-Paper", this);
3891 ESP_LOGCONFIG(TAG, " Model: 7.3in-F");
3892 LOG_PIN(" Reset Pin: ", this->reset_pin_);
3893 LOG_PIN(" DC Pin: ", this->dc_pin_);
3894 LOG_PIN(" Busy Pin: ", this->busy_pin_);
3895 LOG_UPDATE_INTERVAL(this);
3896}
3897
3899 if (this->busy_pin_ == nullptr) {
3900 return true;
3901 }
3902 const uint32_t start = millis();
3903 while (this->busy_pin_->digital_read()) {
3904 if (millis() - start > this->idle_timeout_()) {
3905 ESP_LOGE(TAG, "Timeout while displaying image!");
3906 return false;
3907 }
3908 App.feed_wdt();
3909 delay(10);
3910 }
3911 delay(200); // NOLINT
3912 return true;
3913}
3915 if (this->busy_pin_ == nullptr) {
3916 return true;
3917 }
3918
3919 const uint32_t start = millis();
3920 while (this->busy_pin_->digital_read()) {
3921 this->command(0x71);
3922 if (millis() - start > this->idle_timeout_()) {
3923 ESP_LOGE(TAG, "Timeout while displaying image!");
3924 return false;
3925 }
3926 App.feed_wdt();
3927 delay(10);
3928 }
3929 return true;
3930}
3932 // COMMAND POWER SETTING
3933 this->command(0x01);
3934 this->data(0x07);
3935 this->data(0x07);
3936 this->data(0x3f);
3937 this->data(0x3f);
3938
3939 // We don't want the display to be powered at this point
3940
3941 delay(100); // NOLINT
3942 this->wait_until_idle_();
3943
3944 // COMMAND VCOM AND DATA INTERVAL SETTING
3945 this->command(0x50);
3946 this->data(0x10);
3947 this->data(0x07);
3948
3949 // COMMAND TCON SETTING
3950 this->command(0x60);
3951 this->data(0x22);
3952
3953 // COMMAND PANEL SETTING
3954 this->command(0x00);
3955 this->data(0x1F);
3956
3957 // COMMAND RESOLUTION SETTING
3958 this->command(0x61);
3959 this->data(0x03);
3960 this->data(0x20);
3961 this->data(0x01);
3962 this->data(0xE0);
3963
3964 // COMMAND DUAL SPI MM_EN, DUSPI_EN
3965 this->command(0x15);
3966 this->data(0x00);
3967
3968 // COMMAND POWER DRIVER HAT DOWN
3969 // This command will turn off booster, controller, source driver, gate driver, VCOM, and
3970 // temperature sensor, but register data will be kept until VDD turned OFF or Deep Sleep Mode.
3971 // Source/Gate/Border/VCOM will be released to floating.
3972 this->command(0x02);
3973}
3975 uint32_t buf_len = this->get_buffer_length_();
3976
3977 // COMMAND POWER ON
3978 ESP_LOGI(TAG, "Power on the display and hat");
3979
3980 // This command will turn on booster, controller, regulators, and temperature sensor will be
3981 // activated for one-time sensing before enabling booster. When all voltages are ready, the
3982 // BUSY_N signal will return to high.
3983 this->command(0x04);
3984 delay(200); // NOLINT
3985 this->wait_until_idle_();
3986
3987 // COMMAND DATA START TRANSMISSION NEW DATA
3988 this->command(0x13);
3989 delay(2);
3990 for (uint32_t i = 0; i < buf_len; i++) {
3991 this->data(~(this->buffer_[i]));
3992 }
3993
3994 delay(100); // NOLINT
3995 this->wait_until_idle_();
3996
3997 // COMMAND DISPLAY REFRESH
3998 this->command(0x12);
3999 delay(100); // NOLINT
4000 this->wait_until_idle_();
4001
4002 ESP_LOGV(TAG, "Before command(0x02) (>> power off)");
4003 this->command(0x02);
4004 this->wait_until_idle_();
4005 ESP_LOGV(TAG, "After command(0x02) (>> power off)");
4006}
4007
4012 LOG_DISPLAY("", "Waveshare E-Paper", this);
4013 ESP_LOGCONFIG(TAG, " Model: 7.5inV2rev2");
4014 LOG_PIN(" Reset Pin: ", this->reset_pin_);
4015 LOG_PIN(" DC Pin: ", this->dc_pin_);
4016 LOG_PIN(" Busy Pin: ", this->busy_pin_);
4017 LOG_UPDATE_INTERVAL(this);
4018}
4019
4020/* 7.50inV2alt */
4022 if (this->busy_pin_ == nullptr) {
4023 return true;
4024 }
4025
4026 const uint32_t start = millis();
4027 while (this->busy_pin_->digital_read()) {
4028 this->command(0x71);
4029 if (millis() - start > this->idle_timeout_()) {
4030 ESP_LOGI(TAG, "Timeout while displaying image!");
4031 return false;
4032 }
4033 delay(10);
4034 }
4035 return true;
4036}
4037
4039 this->reset_();
4040
4041 // COMMAND POWER SETTING
4042 this->command(0x01);
4043
4044 // 1-0=11: internal power
4045 this->data(0x07);
4046 this->data(0x17); // VGH&VGL
4047 this->data(0x3F); // VSH
4048 this->data(0x26); // VSL
4049 this->data(0x11); // VSHR
4050
4051 // VCOM DC Setting
4052 this->command(0x82);
4053 this->data(0x24); // VCOM
4054
4055 // Booster Setting
4056 this->command(0x06);
4057 this->data(0x27);
4058 this->data(0x27);
4059 this->data(0x2F);
4060 this->data(0x17);
4061
4062 // POWER ON
4063 this->command(0x04);
4064
4065 delay(100); // NOLINT
4066 this->wait_until_idle_();
4067 // COMMAND PANEL SETTING
4068 this->command(0x00);
4069 this->data(0x3F); // KW-3f KWR-2F BWROTP 0f BWOTP 1f
4070
4071 // COMMAND RESOLUTION SETTING
4072 this->command(0x61);
4073 this->data(0x03); // source 800
4074 this->data(0x20);
4075 this->data(0x01); // gate 480
4076 this->data(0xE0);
4077 // COMMAND ...?
4078 this->command(0x15);
4079 this->data(0x00);
4080 // COMMAND VCOM AND DATA INTERVAL SETTING
4081 this->command(0x50);
4082 this->data(0x10);
4083 this->data(0x00);
4084 // COMMAND TCON SETTING
4085 this->command(0x60);
4086 this->data(0x22);
4087 // Resolution setting
4088 this->command(0x65);
4089 this->data(0x00);
4090 this->data(0x00); // 800*480
4091 this->data(0x00);
4092 this->data(0x00);
4093
4094 this->wait_until_idle_();
4095
4096 uint8_t lut_vcom_7_i_n5_v2[] = {
4097 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0xF, 0x1, 0xF, 0x1, 0x2, 0x0, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
4098 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4099 };
4100
4101 uint8_t lut_ww_7_i_n5_v2[] = {
4102 0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
4103 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4104 };
4105
4106 uint8_t lut_bw_7_i_n5_v2[] = {
4107 0x10, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x20, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
4108 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4109 };
4110
4111 uint8_t lut_wb_7_i_n5_v2[] = {
4112 0x80, 0xF, 0xF, 0x0, 0x0, 0x3, 0x84, 0xF, 0x1, 0xF, 0x1, 0x4, 0x40, 0xF, 0xF, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
4113 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4114 };
4115
4116 uint8_t lut_bb_7_i_n5_v2[] = {
4117 0x80, 0xF, 0xF, 0x0, 0x0, 0x1, 0x84, 0xF, 0x1, 0xF, 0x1, 0x2, 0x40, 0xF, 0xF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
4118 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4119 };
4120
4121 uint8_t count;
4122 this->command(0x20); // VCOM
4123 for (count = 0; count < 42; count++)
4124 this->data(lut_vcom_7_i_n5_v2[count]);
4125
4126 this->command(0x21); // LUTBW
4127 for (count = 0; count < 42; count++)
4128 this->data(lut_ww_7_i_n5_v2[count]);
4129
4130 this->command(0x22); // LUTBW
4131 for (count = 0; count < 42; count++)
4132 this->data(lut_bw_7_i_n5_v2[count]);
4133
4134 this->command(0x23); // LUTWB
4135 for (count = 0; count < 42; count++)
4136 this->data(lut_wb_7_i_n5_v2[count]);
4137
4138 this->command(0x24); // LUTBB
4139 for (count = 0; count < 42; count++)
4140 this->data(lut_bb_7_i_n5_v2[count]);
4141}
4142
4144 LOG_DISPLAY("", "Waveshare E-Paper", this);
4145 ESP_LOGCONFIG(TAG, " Model: 7.5inV2");
4146 LOG_PIN(" Reset Pin: ", this->reset_pin_);
4147 LOG_PIN(" DC Pin: ", this->dc_pin_);
4148 LOG_PIN(" Busy Pin: ", this->busy_pin_);
4149 LOG_UPDATE_INTERVAL(this);
4150}
4151
4152/* 7.50inV2 with partial and fast refresh */
4154 if (this->busy_pin_ == nullptr) {
4155 return true;
4156 }
4157
4158 const uint32_t start = millis();
4159 while (this->busy_pin_->digital_read()) {
4160 this->command(0x71);
4161 if (millis() - start > this->idle_timeout_()) {
4162 ESP_LOGE(TAG, "Timeout while displaying image!");
4163 return false;
4164 }
4165 App.feed_wdt();
4166 delay(10);
4167 }
4168 return true;
4169}
4170
4171void WaveshareEPaper7P5InV2P::reset_() {
4172 if (this->reset_pin_ != nullptr) {
4173 this->reset_pin_->digital_write(true);
4174 delay(20);
4175 this->reset_pin_->digital_write(false);
4176 delay(2);
4177 this->reset_pin_->digital_write(true);
4178 delay(20);
4179 }
4180}
4181
4182void WaveshareEPaper7P5InV2P::turn_on_display_() {
4183 this->command(0x12);
4184 delay(100); // NOLINT
4185 this->wait_until_idle_();
4186}
4187
4189 this->reset_();
4190
4191 // COMMAND POWER SETTING
4192 this->command(0x01);
4193 this->data(0x07);
4194 this->data(0x07);
4195 this->data(0x3f);
4196 this->data(0x3f);
4197
4198 // COMMAND BOOSTER SOFT START
4199 this->command(0x06);
4200 this->data(0x17);
4201 this->data(0x17);
4202 this->data(0x28);
4203 this->data(0x17);
4204
4205 // COMMAND POWER DRIVER HAT UP
4206 this->command(0x04);
4207 delay(100); // NOLINT
4208 this->wait_until_idle_();
4209
4210 // COMMAND PANEL SETTING
4211 this->command(0x00);
4212 this->data(0x1F);
4213
4214 // COMMAND RESOLUTION SETTING
4215 this->command(0x61);
4216 this->data(0x03);
4217 this->data(0x20);
4218 this->data(0x01);
4219 this->data(0xE0);
4220
4221 // COMMAND DUAL SPI MM_EN, DUSPI_EN
4222 this->command(0x15);
4223 this->data(0x00);
4224
4225 // COMMAND VCOM AND DATA INTERVAL SETTING
4226 this->command(0x50);
4227 this->data(0x10);
4228 this->data(0x07);
4229
4230 // COMMAND TCON SETTING
4231 this->command(0x60);
4232 this->data(0x22);
4233
4234 // COMMAND ENABLE FAST UPDATE
4235 this->command(0xE0);
4236 this->data(0x02);
4237 this->command(0xE5);
4238 this->data(0x5A);
4239
4240 // COMMAND POWER DRIVER HAT DOWN
4241 this->command(0x02);
4242}
4243
4245 uint32_t buf_len = this->get_buffer_length_();
4246
4247 // COMMAND POWER ON
4248 ESP_LOGI(TAG, "Power on the display and hat");
4249
4250 this->command(0x04);
4251 delay(200); // NOLINT
4252 this->wait_until_idle_();
4253
4254 if (this->full_update_every_ == 1) {
4255 this->command(0x13);
4256 for (uint32_t i = 0; i < buf_len; i++) {
4257 this->data(~(this->buffer_[i]));
4258 }
4259
4260 this->turn_on_display_();
4261
4262 this->command(0x02);
4263 this->wait_until_idle_();
4264 return;
4265 }
4266
4267 this->command(0x50);
4268 this->data(0xA9);
4269 this->data(0x07);
4270
4271 if (this->at_update_ == 0) {
4272 // Enable fast refresh
4273 this->command(0xE5);
4274 this->data(0x5A);
4275
4276 this->command(0x92);
4277
4278 this->command(0x10);
4279 delay(2);
4280 for (uint32_t i = 0; i < buf_len; i++) {
4281 this->data(~(this->buffer_[i]));
4282 }
4283
4284 delay(100); // NOLINT
4285 this->wait_until_idle_();
4286
4287 this->command(0x13);
4288 delay(2);
4289 for (uint32_t i = 0; i < buf_len; i++) {
4290 this->data(this->buffer_[i]);
4291 }
4292
4293 delay(100); // NOLINT
4294 this->wait_until_idle_();
4295
4296 this->turn_on_display_();
4297
4298 } else {
4299 // Enable partial refresh
4300 this->command(0xE5);
4301 this->data(0x6E);
4302
4303 // Activate partial refresh and set window bounds
4304 this->command(0x91);
4305 this->command(0x90);
4306
4307 this->data(0x00);
4308 this->data(0x00);
4309 this->data((get_width_internal() - 1) >> 8 & 0xFF);
4310 this->data((get_width_internal() - 1) & 0xFF);
4311
4312 this->data(0x00);
4313 this->data(0x00);
4314 this->data((get_height_internal() - 1) >> 8 & 0xFF);
4315 this->data((get_height_internal() - 1) & 0xFF);
4316
4317 this->data(0x01);
4318
4319 this->command(0x13);
4320 delay(2);
4321 for (uint32_t i = 0; i < buf_len; i++) {
4322 this->data(this->buffer_[i]);
4323 }
4324
4325 delay(100); // NOLINT
4326 this->wait_until_idle_();
4327
4328 this->turn_on_display_();
4329 }
4330
4331 ESP_LOGV(TAG, "Before command(0x02) (>> power off)");
4332 this->command(0x02);
4333 this->wait_until_idle_();
4334 ESP_LOGV(TAG, "After command(0x02) (>> power off)");
4335
4336 this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
4337}
4338
4343 LOG_DISPLAY("", "Waveshare E-Paper", this);
4344 ESP_LOGCONFIG(TAG,
4345 " Model: 7.50inv2p\n"
4346 " Full Update Every: %" PRIu32,
4347 this->full_update_every_);
4348 LOG_PIN(" Reset Pin: ", this->reset_pin_);
4349 LOG_PIN(" DC Pin: ", this->dc_pin_);
4350 LOG_PIN(" Busy Pin: ", this->busy_pin_);
4351 LOG_UPDATE_INTERVAL(this);
4352}
4354 this->full_update_every_ = full_update_every;
4355}
4356
4357/* 7.50in-bc */
4359 /* The command sequence is similar to the 7P5In display but differs in subtle ways
4360 to allow for faster updates. */
4361 // COMMAND POWER SETTING
4362 this->command(0x01);
4363 this->data(0x37);
4364 this->data(0x00);
4365
4366 // COMMAND PANEL SETTING
4367 this->command(0x00);
4368 this->data(0xCF);
4369 this->data(0x08);
4370
4371 // COMMAND PLL CONTROL
4372 this->command(0x30);
4373 this->data(0x3A);
4374
4375 // COMMAND VCM_DC_SETTING: all temperature range
4376 this->command(0x82);
4377 this->data(0x28);
4378
4379 // COMMAND BOOSTER SOFT START
4380 this->command(0x06);
4381 this->data(0xC7);
4382 this->data(0xCC);
4383 this->data(0x15);
4384
4385 // COMMAND VCOM AND DATA INTERVAL SETTING
4386 this->command(0x50);
4387 this->data(0x77);
4388
4389 // COMMAND TCON SETTING
4390 this->command(0x60);
4391 this->data(0x22);
4392
4393 // COMMAND FLASH CONTROL
4394 this->command(0x65);
4395 this->data(0x00);
4396
4397 // COMMAND RESOLUTION SETTING
4398 this->command(0x61);
4399 this->data(0x02); // 640 >> 8
4400 this->data(0x80);
4401 this->data(0x01); // 384 >> 8
4402 this->data(0x80);
4403
4404 // COMMAND FLASH MODE
4405 this->command(0xE5);
4406 this->data(0x03);
4407}
4408
4410 // COMMAND DATA START TRANSMISSION 1
4411 this->command(0x10);
4412 this->start_data_();
4413
4414 for (size_t i = 0; i < this->get_buffer_length_(); i++) {
4415 // A line of eight source pixels (each a bit in this byte)
4416 uint8_t eight_pixels = this->buffer_[i];
4417
4418 for (uint8_t j = 0; j < 8; j += 2) {
4419 /* For bichromatic displays, each byte represents two pixels. Each nibble encodes a pixel: 0=white, 3=black,
4420 4=color. Therefore, e.g. 0x44 = two adjacent color pixels, 0x33 is two adjacent black pixels, etc. If you want
4421 to draw using the color pixels, change '0x30' with '0x40' and '0x03' with '0x04' below. */
4422 uint8_t left_nibble = (eight_pixels & 0x80) ? 0x30 : 0x00;
4423 eight_pixels <<= 1;
4424 uint8_t right_nibble = (eight_pixels & 0x80) ? 0x03 : 0x00;
4425 eight_pixels <<= 1;
4426 this->write_byte(left_nibble | right_nibble);
4427 }
4428 App.feed_wdt();
4429 }
4430 this->end_data_();
4431
4432 // Unlike the 7P5In display, we send the "power on" command here rather than during initialization
4433 // COMMAND POWER ON
4434 this->command(0x04);
4435
4436 // COMMAND DISPLAY REFRESH
4437 this->command(0x12);
4438}
4439
4441
4443
4445 LOG_DISPLAY("", "Waveshare E-Paper", this);
4446 ESP_LOGCONFIG(TAG, " Model: 7.5in-bc");
4447 LOG_PIN(" Reset Pin: ", this->reset_pin_);
4448 LOG_PIN(" DC Pin: ", this->dc_pin_);
4449 LOG_PIN(" Busy Pin: ", this->busy_pin_);
4450 LOG_UPDATE_INTERVAL(this);
4451}
4452
4454 this->command(0x12); // SWRESET
4455
4456 this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
4457
4458 this->command(0x46); // Auto Write RAM
4459 this->data(0xF7);
4460
4461 this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
4462
4463 this->command(0x47); // Auto Write RAM
4464 this->data(0xF7);
4465
4466 this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
4467
4468 this->command(0x0C); // Soft start setting
4469 this->data(0xAE);
4470 this->data(0xC7);
4471 this->data(0xC3);
4472 this->data(0xC0);
4473 this->data(0x40);
4474
4475 this->command(0x01); // Set MUX as 527
4476 this->data(0xAF);
4477 this->data(0x02);
4478 this->data(0x01);
4479
4480 this->command(0x11); // Data entry mode
4481 this->data(0x01);
4482
4483 this->command(0x44);
4484 this->data(0x00); // RAM x address start at 0
4485 this->data(0x00);
4486 this->data(0x6F); // RAM x address end at 36Fh -> 879
4487 this->data(0x03);
4488
4489 this->command(0x45);
4490 this->data(0xAF); // RAM y address start at 20Fh;
4491 this->data(0x02);
4492 this->data(0x00); // RAM y address end at 00h;
4493 this->data(0x00);
4494
4495 this->command(0x3C); // VBD
4496 this->data(0x01); // LUT1, for white
4497
4498 this->command(0x18);
4499 this->data(0x80);
4500
4501 this->command(0x22);
4502 this->data(0xB1); // Load Temperature and waveform setting.
4503
4504 this->command(0x20);
4505
4506 this->wait_until_idle_(); // waiting for the electronic paper IC to release the idle signal
4507
4508 this->command(0x4E);
4509 this->data(0x00);
4510 this->data(0x00);
4511
4512 this->command(0x4F);
4513 this->data(0xAF);
4514 this->data(0x02);
4515}
4516
4518 this->command(0x4F);
4519 this->data(0xAf);
4520 this->data(0x02);
4521
4522 // BLACK
4523 this->command(0x24);
4524 this->start_data_();
4525 this->write_array(this->buffer_, this->get_buffer_length_());
4526 this->end_data_();
4527
4528 // RED
4529 this->command(0x26);
4530 this->start_data_();
4531 for (size_t i = 0; i < this->get_buffer_length_(); i++)
4532 this->write_byte(0x00);
4533 this->end_data_();
4534
4535 this->command(0x22);
4536 this->data(0xC7);
4537 this->command(0x20);
4538 delay(100); // NOLINT
4539}
4540
4542
4544
4546 LOG_DISPLAY("", "Waveshare E-Paper", this);
4547 ESP_LOGCONFIG(TAG, " Model: 7.5in-HD-b");
4548 LOG_PIN(" Reset Pin: ", this->reset_pin_);
4549 LOG_PIN(" DC Pin: ", this->dc_pin_);
4550 LOG_PIN(" Busy Pin: ", this->busy_pin_);
4551 LOG_UPDATE_INTERVAL(this);
4552}
4553
4554static const uint8_t LUT_SIZE_TTGO_DKE_PART = 153;
4555
4556static const uint8_t PART_UPDATE_LUT_TTGO_DKE[LUT_SIZE_TTGO_DKE_PART] = {
4557 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4558 0x0, 0x0, 0x0, 0x0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0,
4559 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4560 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4561 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4562 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4563 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
4564 0x0, 0x0, 0x0, 0x0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
4565 // 0x22, 0x17, 0x41, 0x0, 0x32, 0x32
4566};
4567
4570 bool partial = this->at_update_ != 0;
4571 this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
4572
4573 if (partial) {
4574 ESP_LOGI(TAG, "Performing partial e-paper update.");
4575 } else {
4576 ESP_LOGI(TAG, "Performing full e-paper update.");
4577 }
4578
4579 // start and set up data format
4580 this->command(0x12);
4581 this->wait_until_idle_();
4582
4583 this->command(0x11);
4584 this->data(0x03);
4585 this->command(0x44);
4586 this->data(1);
4587 this->data(this->get_width_internal() / 8);
4588 this->command(0x45);
4589 this->data(0);
4590 this->data(0);
4591 this->data(this->get_height_internal());
4592 this->data(0);
4593 this->command(0x4e);
4594 this->data(1);
4595 this->command(0x4f);
4596 this->data(0);
4597 this->data(0);
4598
4599 if (!partial) {
4600 // send data
4601 this->command(0x24);
4602 this->start_data_();
4603 this->write_array(this->buffer_, this->get_buffer_length_());
4604 this->end_data_();
4605
4606 // commit
4607 this->command(0x20);
4608 this->wait_until_idle_();
4609 } else {
4610 // set up partial update
4611 this->command(0x32);
4612 this->start_data_();
4613 this->write_array(PART_UPDATE_LUT_TTGO_DKE, sizeof(PART_UPDATE_LUT_TTGO_DKE));
4614 this->end_data_();
4615 this->command(0x3F);
4616 this->data(0x22);
4617
4618 this->command(0x03);
4619 this->data(0x17);
4620 this->command(0x04);
4621 this->data(0x41);
4622 this->data(0x00);
4623 this->data(0x32);
4624 this->command(0x2C);
4625 this->data(0x32);
4626
4627 this->command(0x37);
4628 this->data(0x00);
4629 this->data(0x00);
4630 this->data(0x00);
4631 this->data(0x00);
4632 this->data(0x00);
4633 this->data(0x40);
4634 this->data(0x00);
4635 this->data(0x00);
4636 this->data(0x00);
4637 this->data(0x00);
4638
4639 this->command(0x3C);
4640 this->data(0x80);
4641 this->command(0x22);
4642 this->data(0xC0);
4643 this->command(0x20);
4644 this->wait_until_idle_();
4645
4646 // send data
4647 this->command(0x24);
4648 this->start_data_();
4649 this->write_array(this->buffer_, this->get_buffer_length_());
4650 this->end_data_();
4651
4652 // commit as partial
4653 this->command(0x22);
4654 this->data(0xCF);
4655 this->command(0x20);
4656 this->wait_until_idle_();
4657
4658 // data must be sent again on partial update
4659 this->command(0x24);
4660 this->start_data_();
4661 this->write_array(this->buffer_, this->get_buffer_length_());
4662 this->end_data_();
4663 }
4664
4665 ESP_LOGI(TAG, "Completed e-paper update.");
4666}
4667
4672 LOG_DISPLAY("", "Waveshare E-Paper", this);
4673 ESP_LOGCONFIG(TAG, " Model: 2.13inDKE");
4674 LOG_PIN(" CS Pin: ", this->cs_);
4675 LOG_PIN(" Reset Pin: ", this->reset_pin_);
4676 LOG_PIN(" DC Pin: ", this->dc_pin_);
4677 LOG_PIN(" Busy Pin: ", this->busy_pin_);
4678 LOG_UPDATE_INTERVAL(this);
4679}
4680
4682 this->full_update_every_ = full_update_every;
4683}
4684
4685// ========================================================
4686// 13.3in (K version)
4687// Datasheet/Specification/Reference:
4688// - https://files.waveshare.com/wiki/13.3inch-e-Paper-HAT-(K)/13.3-inch-e-Paper-(K)-user-manual.pdf
4689// - https://github.com/waveshareteam/e-Paper/tree/master/Arduino/epd13in3k
4690// ========================================================
4691
4692// using default wait_until_idle_() function
4694 this->wait_until_idle_();
4695 this->command(0x12); // SWRESET
4696 this->wait_until_idle_();
4697
4698 this->command(0x0c); // set soft start
4699 this->data(0xae);
4700 this->data(0xc7);
4701 this->data(0xc3);
4702 this->data(0xc0);
4703 this->data(0x80);
4704
4705 this->command(0x01); // driver output control
4706 this->data((get_height_internal() - 1) % 256); // Y
4707 this->data((get_height_internal() - 1) / 256); // Y
4708 this->data(0x00);
4709
4710 this->command(0x11); // data entry mode
4711 this->data(0x03);
4712
4713 // SET WINDOWS
4714 // XRAM_START_AND_END_POSITION
4715 this->command(0x44);
4716 this->data(0 & 0xFF);
4717 this->data((0 >> 8) & 0x03);
4718 this->data((get_width_internal() - 1) & 0xFF);
4719 this->data(((get_width_internal() - 1) >> 8) & 0x03);
4720 // YRAM_START_AND_END_POSITION
4721 this->command(0x45);
4722 this->data(0 & 0xFF);
4723 this->data((0 >> 8) & 0x03);
4724 this->data((get_height_internal() - 1) & 0xFF);
4725 this->data(((get_height_internal() - 1) >> 8) & 0x03);
4726
4727 this->command(0x3C); // Border setting
4728 this->data(0x01);
4729
4730 this->command(0x18); // use the internal temperature sensor
4731 this->data(0x80);
4732
4733 // SET CURSOR
4734 // XRAM_ADDRESS
4735 this->command(0x4E);
4736 this->data(0 & 0xFF);
4737 this->data((0 >> 8) & 0x03);
4738 // YRAM_ADDRESS
4739 this->command(0x4F);
4740 this->data(0 & 0xFF);
4741 this->data((0 >> 8) & 0x03);
4742}
4744 // do single full update
4745 this->command(0x24);
4746 this->start_data_();
4747 this->write_array(this->buffer_, this->get_buffer_length_());
4748 this->end_data_();
4749
4750 // COMMAND DISPLAY REFRESH
4751 this->command(0x22);
4752 this->data(0xF7);
4753 this->command(0x20);
4754}
4755
4760 LOG_DISPLAY("", "Waveshare E-Paper", this);
4761 ESP_LOGCONFIG(TAG, " Model: 13.3inK");
4762 LOG_PIN(" Reset Pin: ", this->reset_pin_);
4763 LOG_PIN(" DC Pin: ", this->dc_pin_);
4764 LOG_PIN(" Busy Pin: ", this->busy_pin_);
4765 LOG_UPDATE_INTERVAL(this);
4766}
4767
4768} // namespace esphome::waveshare_epaper
void feed_wdt()
Feed the task watchdog.
void status_clear_warning()
Definition component.h:296
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:2298
void deallocate(T *p, size_t n)
Definition helpers.h:2355
T * allocate(size_t n)
Definition helpers.h:2325
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:17
virtual void fill(Color color)
Fill the entire screen with the given color.
Definition display.cpp:16
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:826
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:173
void write_lut_(const uint8_t *lut, uint8_t size)
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)
unsigned count
Definition gif.cpp:51
uint32_t buffer
Definition gif.cpp:50
constexpr float PROCESSOR
For components that use data from sensors like displays.
Definition component.h:47
ESPHOME_LOG_TAG(TAG, "waveshare_2.13v3")
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
Definition hal.cpp:48
uint16_t size
Definition helpers.cpp:34
size_t size_t pos
Definition helpers.h:1255
void HOT delay(uint32_t ms)
Definition hal.cpp:85
uint32_t IRAM_ATTR HOT millis()
Definition hal.cpp:25
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