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