ESPHome 2025.5.0
Loading...
Searching...
No Matches
inkplate.cpp
Go to the documentation of this file.
1#include "inkplate.h"
2#include "esphome/core/log.h"
5
6#ifdef USE_ESP32_FRAMEWORK_ARDUINO
7
8#include <esp32-hal-gpio.h>
9
10namespace esphome {
11namespace inkplate6 {
12
13static const char *const TAG = "inkplate";
14
16 for (uint32_t i = 0; i < 256; i++) {
17 this->pin_lut_[i] = ((i & 0b00000011) << 4) | (((i & 0b00001100) >> 2) << 18) | (((i & 0b00010000) >> 4) << 23) |
18 (((i & 0b11100000) >> 5) << 25);
19 }
20
21 this->initialize_();
22
23 this->vcom_pin_->setup();
24 this->powerup_pin_->setup();
25 this->wakeup_pin_->setup();
26 this->gpio0_enable_pin_->setup();
28
29 this->cl_pin_->setup();
30 this->le_pin_->setup();
31 this->ckv_pin_->setup();
32 this->gmod_pin_->setup();
33 this->oe_pin_->setup();
34 this->sph_pin_->setup();
35 this->spv_pin_->setup();
36
45
46 this->wakeup_pin_->digital_write(true);
47 delay(1);
48 this->write_bytes(0x09, {
49 0b00011011, // Power up seq.
50 0b00000000, // Power up delay (3mS per rail)
51 0b00011011, // Power down seq.
52 0b00000000, // Power down delay (6mS per rail)
53 });
54 delay(1);
55 this->wakeup_pin_->digital_write(false);
56}
57
64 uint32_t buffer_size = this->get_buffer_length_();
65 if (buffer_size == 0)
66 return;
67
68 if (this->partial_buffer_ != nullptr)
69 allocator.deallocate(this->partial_buffer_, buffer_size);
70 if (this->partial_buffer_2_ != nullptr)
71 allocator.deallocate(this->partial_buffer_2_, buffer_size * 2);
72 if (this->buffer_ != nullptr)
73 allocator.deallocate(this->buffer_, buffer_size);
74 if (this->glut_ != nullptr)
75 allocator32.deallocate(this->glut_, 256 * 9);
76 if (this->glut2_ != nullptr)
77 allocator32.deallocate(this->glut2_, 256 * 9);
78
79 this->buffer_ = allocator.allocate(buffer_size);
80 if (this->buffer_ == nullptr) {
81 ESP_LOGE(TAG, "Could not allocate buffer for display!");
82 this->mark_failed();
83 return;
84 }
85 if (this->greyscale_) {
86 uint8_t glut_size = 9;
87
88 this->glut_ = allocator32.allocate(256 * glut_size);
89 if (this->glut_ == nullptr) {
90 ESP_LOGE(TAG, "Could not allocate glut!");
91 this->mark_failed();
92 return;
93 }
94 this->glut2_ = allocator32.allocate(256 * glut_size);
95 if (this->glut2_ == nullptr) {
96 ESP_LOGE(TAG, "Could not allocate glut2!");
97 this->mark_failed();
98 return;
99 }
100
101 const auto *const waveform3_bit = waveform3BitAll[this->model_];
102
103 for (int i = 0; i < glut_size; i++) {
104 for (uint32_t j = 0; j < 256; j++) {
105 uint8_t z = (waveform3_bit[j & 0x07][i] << 2) | (waveform3_bit[(j >> 4) & 0x07][i]);
106 this->glut_[i * 256 + j] = ((z & 0b00000011) << 4) | (((z & 0b00001100) >> 2) << 18) |
107 (((z & 0b00010000) >> 4) << 23) | (((z & 0b11100000) >> 5) << 25);
108 z = ((waveform3_bit[j & 0x07][i] << 2) | (waveform3_bit[(j >> 4) & 0x07][i])) << 4;
109 this->glut2_[i * 256 + j] = ((z & 0b00000011) << 4) | (((z & 0b00001100) >> 2) << 18) |
110 (((z & 0b00010000) >> 4) << 23) | (((z & 0b11100000) >> 5) << 25);
111 }
112 }
113
114 } else {
115 this->partial_buffer_ = allocator.allocate(buffer_size);
116 if (this->partial_buffer_ == nullptr) {
117 ESP_LOGE(TAG, "Could not allocate partial buffer for display!");
118 this->mark_failed();
119 return;
120 }
121 this->partial_buffer_2_ = allocator.allocate(buffer_size * 2);
122 if (this->partial_buffer_2_ == nullptr) {
123 ESP_LOGE(TAG, "Could not allocate partial buffer 2 for display!");
124 this->mark_failed();
125 return;
126 }
127
128 memset(this->partial_buffer_, 0, buffer_size);
129 memset(this->partial_buffer_2_, 0, buffer_size * 2);
130 }
131
132 memset(this->buffer_, 0, buffer_size);
133}
134
136
138 if (this->greyscale_) {
139 return size_t(this->get_width_internal()) * size_t(this->get_height_internal()) / 2u;
140 } else {
141 return size_t(this->get_width_internal()) * size_t(this->get_height_internal()) / 8u;
142 }
143}
144
146 this->do_update_();
147
148 if (this->full_update_every_ > 0 && this->partial_updates_ >= this->full_update_every_) {
149 this->block_partial_ = true;
150 }
151
152 this->display();
153}
154
156 if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
157 return;
158
159 if (this->greyscale_) {
160 int x1 = x / 2;
161 int x_sub = x % 2;
162 uint32_t pos = (x1 + y * (this->get_width_internal() / 2));
163 uint8_t current = this->buffer_[pos];
164
165 // float px = (0.2126 * (color.red / 255.0)) + (0.7152 * (color.green / 255.0)) + (0.0722 * (color.blue / 255.0));
166 // px = pow(px, 1.5);
167 // uint8_t gs = (uint8_t)(px*7);
168
169 uint8_t gs = ((color.red * 2126 / 10000) + (color.green * 7152 / 10000) + (color.blue * 722 / 10000)) >> 5;
170 this->buffer_[pos] = (pixelMaskGLUT[x_sub] & current) | (x_sub ? gs : gs << 4);
171
172 } else {
173 int x1 = x / 8;
174 int x_sub = x % 8;
175 uint32_t pos = (x1 + y * (this->get_width_internal() / 8));
176 uint8_t current = this->partial_buffer_[pos];
177 this->partial_buffer_[pos] = (~pixelMaskLUT[x_sub] & current) | (color.is_on() ? 0 : pixelMaskLUT[x_sub]);
178 }
179}
180
182 LOG_DISPLAY("", "Inkplate", this);
183 ESP_LOGCONFIG(TAG, " Greyscale: %s", YESNO(this->greyscale_));
184 ESP_LOGCONFIG(TAG, " Partial Updating: %s", YESNO(this->partial_updating_));
185 ESP_LOGCONFIG(TAG, " Full Update Every: %d", this->full_update_every_);
186 // Log pins
187 LOG_PIN(" CKV Pin: ", this->ckv_pin_);
188 LOG_PIN(" CL Pin: ", this->cl_pin_);
189 LOG_PIN(" GPIO0 Enable Pin: ", this->gpio0_enable_pin_);
190 LOG_PIN(" GMOD Pin: ", this->gmod_pin_);
191 LOG_PIN(" LE Pin: ", this->le_pin_);
192 LOG_PIN(" OE Pin: ", this->oe_pin_);
193 LOG_PIN(" POWERUP Pin: ", this->powerup_pin_);
194 LOG_PIN(" SPH Pin: ", this->sph_pin_);
195 LOG_PIN(" SPV Pin: ", this->spv_pin_);
196 LOG_PIN(" VCOM Pin: ", this->vcom_pin_);
197 LOG_PIN(" WAKEUP Pin: ", this->wakeup_pin_);
198
199 LOG_PIN(" Data 0 Pin: ", this->display_data_0_pin_);
200 LOG_PIN(" Data 1 Pin: ", this->display_data_1_pin_);
201 LOG_PIN(" Data 2 Pin: ", this->display_data_2_pin_);
202 LOG_PIN(" Data 3 Pin: ", this->display_data_3_pin_);
203 LOG_PIN(" Data 4 Pin: ", this->display_data_4_pin_);
204 LOG_PIN(" Data 5 Pin: ", this->display_data_5_pin_);
205 LOG_PIN(" Data 6 Pin: ", this->display_data_6_pin_);
206 LOG_PIN(" Data 7 Pin: ", this->display_data_7_pin_);
207
208 LOG_UPDATE_INTERVAL(this);
209}
210
212 ESP_LOGV(TAG, "Eink off called");
213 if (!panel_on_)
214 return;
215 panel_on_ = false;
216
217 this->oe_pin_->digital_write(false);
218 this->gmod_pin_->digital_write(false);
219
220 GPIO.out &= ~(this->get_data_pin_mask_() | (1 << this->cl_pin_->get_pin()) | (1 << this->le_pin_->get_pin()));
221 this->ckv_pin_->digital_write(false);
222 this->sph_pin_->digital_write(false);
223 this->spv_pin_->digital_write(false);
224
225 this->vcom_pin_->digital_write(false);
226
227 this->write_byte(0x01, 0x6F); // Put TPS65186 into standby mode
228
229 delay(100); // NOLINT
230
231 this->write_byte(0x01, 0x4f); // Disable 3V3 to the panel
232
233 if (this->model_ != INKPLATE_6_PLUS)
234 this->wakeup_pin_->digital_write(false);
235
237}
238
240 ESP_LOGV(TAG, "Eink on called");
241 if (panel_on_)
242 return;
243 this->panel_on_ = true;
244
245 this->pins_as_outputs_();
246 this->wakeup_pin_->digital_write(true);
247 this->vcom_pin_->digital_write(true);
248 delay(2);
249
250 this->write_byte(0x01, 0b00101111); // Enable all rails
251
252 delay(1);
253
254 this->write_byte(0x01, 0b10101111); // Switch TPS65186 into active mode
255
256 this->le_pin_->digital_write(false);
257 this->oe_pin_->digital_write(false);
258 this->cl_pin_->digital_write(false);
259 this->sph_pin_->digital_write(true);
260 this->gmod_pin_->digital_write(true);
261 this->spv_pin_->digital_write(true);
262 this->ckv_pin_->digital_write(false);
263 this->oe_pin_->digital_write(false);
264
265 uint32_t timer = millis();
266 do {
267 delay(1);
268 } while (!this->read_power_status_() && ((millis() - timer) < 250));
269 if ((millis() - timer) >= 250) {
270 ESP_LOGW(TAG, "Power supply not detected");
271 this->wakeup_pin_->digital_write(false);
272 this->vcom_pin_->digital_write(false);
273 this->powerup_pin_->digital_write(false);
274 this->panel_on_ = false;
275 return;
276 }
277
278 this->oe_pin_->digital_write(true);
279}
280
282 uint8_t data;
283 auto err = this->read_register(0x0F, &data, 1);
284 if (err == i2c::ERROR_OK) {
285 return data == 0b11111010;
286 }
287 return false;
288}
289
291 ESP_LOGV(TAG, "Fill called");
292 uint32_t start_time = millis();
293
294 if (this->greyscale_) {
295 uint8_t fill = ((color.red * 2126 / 10000) + (color.green * 7152 / 10000) + (color.blue * 722 / 10000)) >> 5;
296 memset(this->buffer_, (fill << 4) | fill, this->get_buffer_length_());
297 } else {
298 uint8_t fill = color.is_on() ? 0x00 : 0xFF;
299 memset(this->partial_buffer_, fill, this->get_buffer_length_());
300 }
301
302 ESP_LOGV(TAG, "Fill finished (%ums)", millis() - start_time);
303}
304
306 ESP_LOGV(TAG, "Display called");
307 uint32_t start_time = millis();
308
309 if (this->greyscale_) {
310 this->display3b_();
311 } else {
312 if (this->partial_updating_ && this->partial_update_()) {
313 ESP_LOGV(TAG, "Display finished (partial) (%ums)", millis() - start_time);
314 return;
315 }
316 this->display1b_();
317 }
318 ESP_LOGV(TAG, "Display finished (full) (%ums)", millis() - start_time);
319}
320
322 ESP_LOGV(TAG, "Display1b called");
323 uint32_t start_time = millis();
324
325 memcpy(this->buffer_, this->partial_buffer_, this->get_buffer_length_());
326
327 uint8_t data;
328 uint8_t buffer_value;
329 const uint8_t *buffer_ptr;
330 eink_on_();
331 if (this->model_ == INKPLATE_6_PLUS) {
332 clean_fast_(0, 1);
333 clean_fast_(1, 15);
334 clean_fast_(2, 1);
335 clean_fast_(0, 5);
336 clean_fast_(2, 1);
337 clean_fast_(1, 15);
338 } else {
339 clean_fast_(0, 1);
340 clean_fast_(1, 21);
341 clean_fast_(2, 1);
342 clean_fast_(0, 12);
343 clean_fast_(2, 1);
344 clean_fast_(1, 21);
345 clean_fast_(2, 1);
346 clean_fast_(0, 12);
347 clean_fast_(2, 1);
348 }
349
350 uint32_t clock = (1 << this->cl_pin_->get_pin());
351 uint32_t data_mask = this->get_data_pin_mask_();
352 ESP_LOGV(TAG, "Display1b start loops (%ums)", millis() - start_time);
353
354 int rep = (this->model_ == INKPLATE_6_V2) ? 5 : 4;
355
356 for (int k = 0; k < rep; k++) {
357 buffer_ptr = &this->buffer_[this->get_buffer_length_() - 1];
358 vscan_start_();
359 for (int i = 0, im = this->get_height_internal(); i < im; i++) {
360 buffer_value = *(buffer_ptr--);
361 data = this->model_ == INKPLATE_6_PLUS ? LUTW[(~buffer_value >> 4) & 0x0F] : LUTB[(buffer_value >> 4) & 0x0F];
362 hscan_start_(this->pin_lut_[data]);
363 data = this->model_ == INKPLATE_6_PLUS ? LUTW[(~buffer_value) & 0x0F] : LUTB[buffer_value & 0x0F];
364 GPIO.out_w1ts = this->pin_lut_[data] | clock;
365 GPIO.out_w1tc = data_mask | clock;
366
367 for (int j = 0, jm = (this->get_width_internal() / 8) - 1; j < jm; j++) {
368 buffer_value = *(buffer_ptr--);
369 data = this->model_ == INKPLATE_6_PLUS ? LUTW[(~buffer_value >> 4) & 0x0F] : LUTB[(buffer_value >> 4) & 0x0F];
370 GPIO.out_w1ts = this->pin_lut_[data] | clock;
371 GPIO.out_w1tc = data_mask | clock;
372 data = this->model_ == INKPLATE_6_PLUS ? LUTW[(~buffer_value) & 0x0F] : LUTB[buffer_value & 0x0F];
373 GPIO.out_w1ts = this->pin_lut_[data] | clock;
374 GPIO.out_w1tc = data_mask | clock;
375 }
376 // New Inkplate6 panel doesn't need last clock
377 if (this->model_ != INKPLATE_6_V2) {
378 GPIO.out_w1ts = clock;
379 GPIO.out_w1tc = data_mask | clock;
380 }
381 vscan_end_();
382 }
384 }
385 ESP_LOGV(TAG, "Display1b first loop x %d (%ums)", 4, millis() - start_time);
386
387 buffer_ptr = &this->buffer_[this->get_buffer_length_() - 1];
388 vscan_start_();
389 for (int i = 0, im = this->get_height_internal(); i < im; i++) {
390 buffer_value = *(buffer_ptr--);
391 data = this->model_ == INKPLATE_6_PLUS ? LUTB[(buffer_value >> 4) & 0x0F] : LUT2[(buffer_value >> 4) & 0x0F];
392 hscan_start_(this->pin_lut_[data] | clock);
393 data = this->model_ == INKPLATE_6_PLUS ? LUTB[buffer_value & 0x0F] : LUT2[buffer_value & 0x0F];
394 GPIO.out_w1ts = this->pin_lut_[data] | clock;
395 GPIO.out_w1tc = data_mask | clock;
396
397 for (int j = 0, jm = (this->get_width_internal() / 8) - 1; j < jm; j++) {
398 buffer_value = *(buffer_ptr--);
399 data = this->model_ == INKPLATE_6_PLUS ? LUTB[(buffer_value >> 4) & 0x0F] : LUT2[(buffer_value >> 4) & 0x0F];
400 GPIO.out_w1ts = this->pin_lut_[data] | clock;
401 GPIO.out_w1tc = data_mask | clock;
402 data = this->model_ == INKPLATE_6_PLUS ? LUTB[buffer_value & 0x0F] : LUT2[buffer_value & 0x0F];
403 GPIO.out_w1ts = this->pin_lut_[data] | clock;
404 GPIO.out_w1tc = data_mask | clock;
405 }
406 // New Inkplate6 panel doesn't need last clock
407 if (this->model_ != INKPLATE_6_V2) {
408 GPIO.out_w1ts = clock;
409 GPIO.out_w1tc = data_mask | clock;
410 }
411 vscan_end_();
412 }
414 ESP_LOGV(TAG, "Display1b second loop (%ums)", millis() - start_time);
415
416 if (this->model_ == INKPLATE_6_PLUS) {
417 clean_fast_(2, 2);
418 clean_fast_(3, 1);
419 } else {
420 uint32_t send = this->pin_lut_[0];
421 vscan_start_();
422 for (int i = 0, im = this->get_height_internal(); i < im; i++) {
423 hscan_start_(send);
424 GPIO.out_w1ts = send | clock;
425 GPIO.out_w1tc = data_mask | clock;
426 for (int j = 0, jm = (this->get_width_internal() / 8) - 1; j < jm; j++) {
427 GPIO.out_w1ts = send | clock;
428 GPIO.out_w1tc = data_mask | clock;
429 GPIO.out_w1ts = send | clock;
430 GPIO.out_w1tc = data_mask | clock;
431 }
432 // New Inkplate6 panel doesn't need last clock
433 if (this->model_ != INKPLATE_6_V2) {
434 GPIO.out_w1ts = clock;
435 GPIO.out_w1tc = data_mask | clock;
436 }
437 vscan_end_();
438 }
440 ESP_LOGV(TAG, "Display1b third loop (%ums)", millis() - start_time);
441 }
442 vscan_start_();
443 eink_off_();
444 this->block_partial_ = false;
445 this->partial_updates_ = 0;
446 ESP_LOGV(TAG, "Display1b finished (%ums)", millis() - start_time);
447}
448
450 ESP_LOGV(TAG, "Display3b called");
451 uint32_t start_time = millis();
452
453 eink_on_();
454 if (this->model_ == INKPLATE_6_PLUS) {
455 clean_fast_(0, 1);
456 clean_fast_(1, 15);
457 clean_fast_(2, 1);
458 clean_fast_(0, 5);
459 clean_fast_(2, 1);
460 clean_fast_(1, 15);
461 } else {
462 clean_fast_(0, 1);
463 clean_fast_(1, 21);
464 clean_fast_(2, 1);
465 clean_fast_(0, 12);
466 clean_fast_(2, 1);
467 clean_fast_(1, 21);
468 clean_fast_(2, 1);
469 clean_fast_(0, 12);
470 clean_fast_(2, 1);
471 }
472
473 uint32_t clock = (1 << this->cl_pin_->get_pin());
474 uint32_t data_mask = this->get_data_pin_mask_();
475 uint32_t pos;
476 uint32_t data;
477 uint8_t glut_size = 9;
478 for (int k = 0; k < glut_size; k++) {
479 pos = this->get_buffer_length_();
480 vscan_start_();
481 for (int i = 0; i < this->get_height_internal(); i++) {
482 data = this->glut2_[k * 256 + this->buffer_[--pos]];
483 data |= this->glut_[k * 256 + this->buffer_[--pos]];
484 hscan_start_(data);
485 data = this->glut2_[k * 256 + this->buffer_[--pos]];
486 data |= this->glut_[k * 256 + this->buffer_[--pos]];
487 GPIO.out_w1ts = data | clock;
488 GPIO.out_w1tc = data_mask | clock;
489
490 for (int j = 0; j < (this->get_width_internal() / 8) - 1; j++) {
491 data = this->glut2_[k * 256 + this->buffer_[--pos]];
492 data |= this->glut_[k * 256 + this->buffer_[--pos]];
493 GPIO.out_w1ts = data | clock;
494 GPIO.out_w1tc = data_mask | clock;
495 data = this->glut2_[k * 256 + this->buffer_[--pos]];
496 data |= this->glut_[k * 256 + this->buffer_[--pos]];
497 GPIO.out_w1ts = data | clock;
498 GPIO.out_w1tc = data_mask | clock;
499 }
500 // New Inkplate6 panel doesn't need last clock
501 if (this->model_ != INKPLATE_6_V2) {
502 GPIO.out_w1ts = clock;
503 GPIO.out_w1tc = data_mask | clock;
504 }
505 vscan_end_();
506 }
508 }
509 clean_fast_(3, 1);
510 vscan_start_();
511 eink_off_();
512 ESP_LOGV(TAG, "Display3b finished (%ums)", millis() - start_time);
513}
514
516 ESP_LOGV(TAG, "Partial update called");
517 uint32_t start_time = millis();
518 if (this->greyscale_)
519 return false;
520 if (this->block_partial_)
521 return false;
522
523 this->partial_updates_++;
524
525 uint32_t pos = this->get_buffer_length_() - 1;
526 uint8_t data;
527 uint8_t diffw, diffb;
528 uint32_t n = (this->get_buffer_length_() * 2) - 1;
529
530 for (int i = 0, im = this->get_height_internal(); i < im; i++) {
531 for (int j = 0, jm = (this->get_width_internal() / 8); j < jm; j++) {
532 diffw = this->buffer_[pos] & ~(this->partial_buffer_[pos]);
533 diffb = ~(this->buffer_[pos]) & this->partial_buffer_[pos];
534 pos--;
535 this->partial_buffer_2_[n--] = LUTW[diffw >> 4] & LUTB[diffb >> 4];
536 this->partial_buffer_2_[n--] = LUTW[diffw & 0x0F] & LUTB[diffb & 0x0F];
537 }
538 }
539 ESP_LOGV(TAG, "Partial update buffer built after (%ums)", millis() - start_time);
540
541 int rep = (this->model_ == INKPLATE_6_V2) ? 6 : 5;
542
543 eink_on_();
544 uint32_t clock = (1 << this->cl_pin_->get_pin());
545 uint32_t data_mask = this->get_data_pin_mask_();
546 for (int k = 0; k < rep; k++) {
547 vscan_start_();
548 const uint8_t *data_ptr = &this->partial_buffer_2_[(this->get_buffer_length_() * 2) - 1];
549 for (int i = 0; i < this->get_height_internal(); i++) {
550 data = *(data_ptr--);
551 hscan_start_(this->pin_lut_[data]);
552 for (int j = 0, jm = (this->get_width_internal() / 4) - 1; j < jm; j++) {
553 data = *(data_ptr--);
554 GPIO.out_w1ts = this->pin_lut_[data] | clock;
555 GPIO.out_w1tc = data_mask | clock;
556 }
557 // New Inkplate6 panel doesn't need last clock
558 if (this->model_ != INKPLATE_6_V2) {
559 GPIO.out_w1ts = clock;
560 GPIO.out_w1tc = data_mask | clock;
561 }
562 vscan_end_();
563 }
565 ESP_LOGV(TAG, "Partial update loop k=%d (%ums)", k, millis() - start_time);
566 }
567 clean_fast_(2, 2);
568 clean_fast_(3, 1);
569 vscan_start_();
570 eink_off_();
571
572 memcpy(this->buffer_, this->partial_buffer_, this->get_buffer_length_());
573 ESP_LOGV(TAG, "Partial update finished (%ums)", millis() - start_time);
574 return true;
575}
576
578 this->ckv_pin_->digital_write(true);
580 this->spv_pin_->digital_write(false);
582 this->ckv_pin_->digital_write(false);
584 this->ckv_pin_->digital_write(true);
586 this->spv_pin_->digital_write(true);
588 this->ckv_pin_->digital_write(false);
590 this->ckv_pin_->digital_write(true);
592 this->ckv_pin_->digital_write(false);
594 this->ckv_pin_->digital_write(true);
596 this->ckv_pin_->digital_write(false);
598 this->ckv_pin_->digital_write(true);
599}
600
601void Inkplate6::hscan_start_(uint32_t d) {
602 uint8_t clock = (1 << this->cl_pin_->get_pin());
603 this->sph_pin_->digital_write(false);
604 GPIO.out_w1ts = d | clock;
605 GPIO.out_w1tc = this->get_data_pin_mask_() | clock;
606 this->sph_pin_->digital_write(true);
607 this->ckv_pin_->digital_write(true);
608}
609
611 this->ckv_pin_->digital_write(false);
612 this->le_pin_->digital_write(true);
613 this->le_pin_->digital_write(false);
615}
616
618 ESP_LOGV(TAG, "Clean called");
619 uint32_t start_time = millis();
620
621 eink_on_();
622 clean_fast_(0, 1); // White
623 clean_fast_(0, 8); // White to White
624 clean_fast_(0, 1); // White to Black
625 clean_fast_(0, 8); // Black to Black
626 clean_fast_(2, 1); // Black to White
627 clean_fast_(1, 10); // White to White
628 ESP_LOGV(TAG, "Clean finished (%ums)", millis() - start_time);
629}
630
631void Inkplate6::clean_fast_(uint8_t c, uint8_t rep) {
632 ESP_LOGV(TAG, "Clean fast called with: (%d, %d)", c, rep);
633 uint32_t start_time = millis();
634
635 eink_on_();
636 uint8_t data = 0;
637 if (c == 0) { // White
638 data = 0b10101010;
639 } else if (c == 1) { // Black
640 data = 0b01010101;
641 } else if (c == 2) { // Discharge
642 data = 0b00000000;
643 } else if (c == 3) { // Skip
644 data = 0b11111111;
645 }
646
647 uint32_t send = ((data & 0b00000011) << 4) | (((data & 0b00001100) >> 2) << 18) | (((data & 0b00010000) >> 4) << 23) |
648 (((data & 0b11100000) >> 5) << 25);
649 uint32_t clock = (1 << this->cl_pin_->get_pin());
650
651 for (int k = 0; k < rep; k++) {
652 vscan_start_();
653 for (int i = 0; i < this->get_height_internal(); i++) {
654 hscan_start_(send);
655 GPIO.out_w1ts = send | clock;
656 GPIO.out_w1tc = clock;
657 for (int j = 0; j < (this->get_width_internal() / 8) - 1; j++) {
658 GPIO.out_w1ts = clock;
659 GPIO.out_w1tc = clock;
660 GPIO.out_w1ts = clock;
661 GPIO.out_w1tc = clock;
662 }
663 // New Inkplate6 panel doesn't need last clock
664 if (this->model_ != INKPLATE_6_V2) {
665 GPIO.out_w1ts = send | clock;
666 GPIO.out_w1tc = clock;
667 }
668 vscan_end_();
669 }
671 ESP_LOGV(TAG, "Clean fast rep loop %d finished (%ums)", k, millis() - start_time);
672 }
673 ESP_LOGV(TAG, "Clean fast finished (%ums)", millis() - start_time);
674}
675
695
715
716} // namespace inkplate6
717} // namespace esphome
718
719#endif // USE_ESP32_FRAMEWORK_ARDUINO
virtual void mark_failed()
Mark this component as failed.
virtual void pin_mode(gpio::Flags flags)=0
virtual void setup()=0
virtual void digital_write(bool value)=0
virtual uint8_t get_pin() const =0
An STL allocator that uses SPI or internal RAM.
Definition helpers.h:683
void deallocate(T *p, size_t n)
Definition helpers.h:741
T * allocate(size_t n)
Definition helpers.h:703
bool write_bytes(uint8_t a_register, const uint8_t *data, uint8_t len, bool stop=true)
Definition i2c.h:252
bool write_byte(uint8_t a_register, uint8_t data, bool stop=true)
Definition i2c.h:266
ErrorCode read_register(uint8_t a_register, uint8_t *data, size_t len, bool stop=true)
reads an array of bytes from a specific register in the I²C device
Definition i2c.cpp:10
InternalGPIOPin * display_data_4_pin_
Definition inkplate.h:232
InternalGPIOPin * le_pin_
Definition inkplate.h:241
InternalGPIOPin * display_data_5_pin_
Definition inkplate.h:233
InternalGPIOPin * display_data_3_pin_
Definition inkplate.h:231
InternalGPIOPin * display_data_0_pin_
Definition inkplate.h:228
const uint8_t pixelMaskLUT[8]
Definition inkplate.h:31
InternalGPIOPin * display_data_2_pin_
Definition inkplate.h:230
const uint8_t pixelMaskGLUT[2]
Definition inkplate.h:32
InternalGPIOPin * display_data_1_pin_
Definition inkplate.h:229
void draw_absolute_pixel_internal(int x, int y, Color color) override
Definition inkplate.cpp:155
const uint8_t LUT2[16]
Definition inkplate.h:24
int get_height_internal() override
Definition inkplate.h:179
InternalGPIOPin * display_data_6_pin_
Definition inkplate.h:234
float get_setup_priority() const override
Definition inkplate.cpp:135
InternalGPIOPin * cl_pin_
Definition inkplate.h:238
void clean_fast_(uint8_t c, uint8_t rep)
Definition inkplate.cpp:631
const uint8_t LUTB[16]
Definition inkplate.h:28
void hscan_start_(uint32_t d)
Definition inkplate.cpp:601
int get_width_internal() override
Definition inkplate.h:164
const uint8_t LUTW[16]
Definition inkplate.h:26
const uint8_t waveform3BitAll[6][8][9]
Definition inkplate.h:34
InternalGPIOPin * display_data_7_pin_
Definition inkplate.h:235
void fill(Color color) override
Definition inkplate.cpp:290
void initialize_()
Allocate buffers.
Definition inkplate.cpp:61
bool z
Definition msa3xx.h:1
@ FLAG_OUTPUT
Definition gpio.h:19
@ FLAG_INPUT
Definition gpio.h:18
@ ERROR_OK
No error found during execution of method.
Definition i2c_bus.h:13
const float PROCESSOR
For components that use data from sensors like displays.
Definition component.cpp:20
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
Definition core.cpp:30
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:28
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:27
uint8_t red
Definition color.h:15
uint8_t green
Definition color.h:19
bool is_on() ESPHOME_ALWAYS_INLINE
Definition color.h:46
uint8_t blue
Definition color.h:23
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6