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