Inkplate 6 PLUS (#3013)

This commit is contained in:
Jesse Hills 2022-02-08 22:56:56 +13:00 committed by GitHub
parent 4aeacfd16e
commit c66d0550e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 281 additions and 208 deletions

View file

@ -47,6 +47,7 @@ InkplateModel = inkplate6_ns.enum("InkplateModel")
MODELS = {
"inkplate_6": InkplateModel.INKPLATE_6,
"inkplate_10": InkplateModel.INKPLATE_10,
"inkplate_6_plus": InkplateModel.INKPLATE_6_PLUS,
}
CONFIG_SCHEMA = cv.All(

View file

@ -13,6 +13,11 @@ namespace inkplate6 {
static const char *const TAG = "inkplate";
void Inkplate6::setup() {
for (uint32_t i = 0; i < 256; i++) {
this->pin_lut_[i] = ((i & 0b00000011) << 4) | (((i & 0b00001100) >> 2) << 18) | (((i & 0b00010000) >> 4) << 23) |
(((i & 0b11100000) >> 5) << 25);
}
this->initialize_();
this->vcom_pin_->setup();
@ -38,11 +43,21 @@ void Inkplate6::setup() {
this->display_data_6_pin_->setup();
this->display_data_7_pin_->setup();
this->clean();
this->display();
this->wakeup_pin_->digital_write(true);
delay(1);
this->write_bytes(0x09, {
0b00011011, // Power up seq.
0b00000000, // Power up delay (3mS per rail)
0b00011011, // Power down seq.
0b00000000, // Power down delay (6mS per rail)
});
delay(1);
this->wakeup_pin_->digital_write(false);
}
void Inkplate6::initialize_() {
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
ExternalRAMAllocator<uint32_t> allocator32(ExternalRAMAllocator<uint32_t>::ALLOW_FAILURE);
uint32_t buffer_size = this->get_buffer_length_();
if (buffer_size == 0)
return;
@ -53,6 +68,10 @@ void Inkplate6::initialize_() {
allocator.deallocate(this->partial_buffer_2_, buffer_size * 2);
if (this->buffer_ != nullptr)
allocator.deallocate(this->buffer_, buffer_size);
if (this->glut_ != nullptr)
allocator32.deallocate(this->glut_, 256 * (this->model_ == INKPLATE_6_PLUS ? 9 : 8));
if (this->glut2_ != nullptr)
allocator32.deallocate(this->glut2_, 256 * (this->model_ == INKPLATE_6_PLUS ? 9 : 8));
this->buffer_ = allocator.allocate(buffer_size);
if (this->buffer_ == nullptr) {
@ -60,7 +79,34 @@ void Inkplate6::initialize_() {
this->mark_failed();
return;
}
if (!this->greyscale_) {
if (this->greyscale_) {
uint8_t glut_size = (this->model_ == INKPLATE_6_PLUS ? 9 : 8);
this->glut_ = allocator32.allocate(256 * glut_size);
if (this->glut_ == nullptr) {
ESP_LOGE(TAG, "Could not allocate glut!");
this->mark_failed();
return;
}
this->glut2_ = allocator32.allocate(256 * glut_size);
if (this->glut2_ == nullptr) {
ESP_LOGE(TAG, "Could not allocate glut2!");
this->mark_failed();
return;
}
for (int i = 0; i < glut_size; i++) {
for (uint32_t j = 0; j < 256; j++) {
uint8_t z = (waveform3Bit[j & 0x07][i] << 2) | (waveform3Bit[(j >> 4) & 0x07][i]);
this->glut_[i * 256 + j] = ((z & 0b00000011) << 4) | (((z & 0b00001100) >> 2) << 18) |
(((z & 0b00010000) >> 4) << 23) | (((z & 0b11100000) >> 5) << 25);
z = ((waveform3Bit[j & 0x07][i] << 2) | (waveform3Bit[(j >> 4) & 0x07][i])) << 4;
this->glut2_[i * 256 + j] = ((z & 0b00000011) << 4) | (((z & 0b00001100) >> 2) << 18) |
(((z & 0b00010000) >> 4) << 23) | (((z & 0b11100000) >> 5) << 25);
}
}
} else {
this->partial_buffer_ = allocator.allocate(buffer_size);
if (this->partial_buffer_ == nullptr) {
ESP_LOGE(TAG, "Could not allocate partial buffer for display!");
@ -73,13 +119,16 @@ void Inkplate6::initialize_() {
this->mark_failed();
return;
}
memset(this->partial_buffer_, 0, buffer_size);
memset(this->partial_buffer_2_, 0, buffer_size * 2);
}
memset(this->buffer_, 0, buffer_size);
}
float Inkplate6::get_setup_priority() const { return setup_priority::PROCESSOR; }
size_t Inkplate6::get_buffer_length_() {
if (this->greyscale_) {
return size_t(this->get_width_internal()) * size_t(this->get_height_internal()) / 2u;
@ -87,6 +136,7 @@ size_t Inkplate6::get_buffer_length_() {
return size_t(this->get_width_internal()) * size_t(this->get_height_internal()) / 8u;
}
}
void Inkplate6::update() {
this->do_update_();
@ -96,6 +146,7 @@ void Inkplate6::update() {
this->display();
}
void HOT Inkplate6::draw_absolute_pixel_internal(int x, int y, Color color) {
if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
return;
@ -121,6 +172,7 @@ void HOT Inkplate6::draw_absolute_pixel_internal(int x, int y, Color color) {
this->partial_buffer_[pos] = (~pixelMaskLUT[x_sub] & current) | (color.is_on() ? 0 : pixelMaskLUT[x_sub]);
}
}
void Inkplate6::dump_config() {
LOG_DISPLAY("", "Inkplate", this);
ESP_LOGCONFIG(TAG, " Greyscale: %s", YESNO(this->greyscale_));
@ -150,44 +202,51 @@ void Inkplate6::dump_config() {
LOG_UPDATE_INTERVAL(this);
}
void Inkplate6::eink_off_() {
ESP_LOGV(TAG, "Eink off called");
if (panel_on_ == 0)
if (!panel_on_)
return;
panel_on_ = 0;
this->gmod_pin_->digital_write(false);
panel_on_ = false;
this->oe_pin_->digital_write(false);
this->gmod_pin_->digital_write(false);
GPIO.out &= ~(get_data_pin_mask_() | (1 << this->cl_pin_->get_pin()) | (1 << this->le_pin_->get_pin()));
GPIO.out &= ~(this->get_data_pin_mask_() | (1 << this->cl_pin_->get_pin()) | (1 << this->le_pin_->get_pin()));
this->ckv_pin_->digital_write(false);
this->sph_pin_->digital_write(false);
this->spv_pin_->digital_write(false);
this->powerup_pin_->digital_write(false);
this->wakeup_pin_->digital_write(false);
this->vcom_pin_->digital_write(false);
this->write_byte(0x01, 0x6F); // Put TPS65186 into standby mode
delay(100); // NOLINT
this->write_byte(0x01, 0x4f); // Disable 3V3 to the panel
if (this->model_ != INKPLATE_6_PLUS)
this->wakeup_pin_->digital_write(false);
pins_z_state_();
}
void Inkplate6::eink_on_() {
ESP_LOGV(TAG, "Eink on called");
if (panel_on_ == 1)
if (panel_on_)
return;
panel_on_ = 1;
pins_as_outputs_();
this->panel_on_ = true;
this->pins_as_outputs_();
this->wakeup_pin_->digital_write(true);
this->powerup_pin_->digital_write(true);
this->vcom_pin_->digital_write(true);
this->write_byte(0x01, 0x3F);
delay(40);
this->write_byte(0x0D, 0x80);
delay(2);
this->read_register(0x00, nullptr, 0);
this->write_byte(0x01, 0b00101111); // Enable all rails
delay(1);
this->write_byte(0x01, 0b10101111); // Switch TPS65186 into active mode
this->le_pin_->digital_write(false);
this->oe_pin_->digital_write(false);
@ -196,8 +255,33 @@ void Inkplate6::eink_on_() {
this->gmod_pin_->digital_write(true);
this->spv_pin_->digital_write(true);
this->ckv_pin_->digital_write(false);
this->oe_pin_->digital_write(false);
uint32_t timer = millis();
do {
delay(1);
} while (!this->read_power_status_() && ((millis() - timer) < 250));
if ((millis() - timer) >= 250) {
ESP_LOGW(TAG, "Power supply not detected");
this->wakeup_pin_->digital_write(false);
this->vcom_pin_->digital_write(false);
this->powerup_pin_->digital_write(false);
this->panel_on_ = false;
return;
}
this->oe_pin_->digital_write(true);
}
bool Inkplate6::read_power_status_() {
uint8_t data;
auto err = this->read_register(0x0F, &data, 1);
if (err == i2c::ERROR_OK) {
return data == 0b11111010;
}
return false;
}
void Inkplate6::fill(Color color) {
ESP_LOGV(TAG, "Fill called");
uint32_t start_time = millis();
@ -212,6 +296,7 @@ void Inkplate6::fill(Color color) {
ESP_LOGV(TAG, "Fill finished (%ums)", millis() - start_time);
}
void Inkplate6::display() {
ESP_LOGV(TAG, "Display called");
uint32_t start_time = millis();
@ -227,201 +312,185 @@ void Inkplate6::display() {
}
ESP_LOGV(TAG, "Display finished (full) (%ums)", millis() - start_time);
}
void Inkplate6::display1b_() {
ESP_LOGV(TAG, "Display1b called");
uint32_t start_time = millis();
memcpy(this->buffer_, this->partial_buffer_, this->get_buffer_length_());
uint32_t send;
uint8_t data;
uint8_t buffer_value;
const uint8_t *buffer_ptr;
eink_on_();
if (this->model_ == INKPLATE_6_PLUS) {
clean_fast_(0, 1);
clean_fast_(1, 5);
clean_fast_(1, 15);
clean_fast_(2, 1);
clean_fast_(0, 5);
clean_fast_(2, 1);
clean_fast_(1, 12);
clean_fast_(1, 15);
} else {
clean_fast_(0, 1);
clean_fast_(1, 21);
clean_fast_(2, 1);
clean_fast_(0, 11);
clean_fast_(0, 12);
clean_fast_(2, 1);
clean_fast_(1, 21);
clean_fast_(2, 1);
clean_fast_(0, 12);
}
uint32_t clock = (1 << this->cl_pin_->get_pin());
uint32_t data_mask = this->get_data_pin_mask_();
ESP_LOGV(TAG, "Display1b start loops (%ums)", millis() - start_time);
for (int k = 0; k < 3; k++) {
for (int k = 0; k < 4; k++) {
buffer_ptr = &this->buffer_[this->get_buffer_length_() - 1];
vscan_start_();
for (int i = 0; i < this->get_height_internal(); i++) {
for (int i = 0, im = this->get_height_internal(); i < im; i++) {
buffer_value = *(buffer_ptr--);
data = LUTB[(buffer_value >> 4) & 0x0F];
send = ((data & 0b00000011) << 4) | (((data & 0b00001100) >> 2) << 18) | (((data & 0b00010000) >> 4) << 23) |
(((data & 0b11100000) >> 5) << 25);
hscan_start_(send);
data = LUTB[buffer_value & 0x0F];
send = ((data & 0b00000011) << 4) | (((data & 0b00001100) >> 2) << 18) | (((data & 0b00010000) >> 4) << 23) |
(((data & 0b11100000) >> 5) << 25) | clock;
GPIO.out_w1ts = send;
GPIO.out_w1tc = send;
data = this->model_ == INKPLATE_6_PLUS ? LUTW[(~buffer_value >> 4) & 0x0F] : LUTB[(buffer_value >> 4) & 0x0F];
hscan_start_(this->pin_lut_[data]);
data = this->model_ == INKPLATE_6_PLUS ? LUTW[(~buffer_value) & 0x0F] : LUTB[buffer_value & 0x0F];
GPIO.out_w1ts = this->pin_lut_[data] | clock;
GPIO.out_w1tc = data_mask | clock;
for (int j = 0, jm = (this->get_width_internal() / 8) - 1; j < jm; j++) {
buffer_value = *(buffer_ptr--);
data = LUTB[(buffer_value >> 4) & 0x0F];
send = ((data & 0b00000011) << 4) | (((data & 0b00001100) >> 2) << 18) | (((data & 0b00010000) >> 4) << 23) |
(((data & 0b11100000) >> 5) << 25) | clock;
GPIO.out_w1ts = send;
GPIO.out_w1tc = send;
data = LUTB[buffer_value & 0x0F];
send = ((data & 0b00000011) << 4) | (((data & 0b00001100) >> 2) << 18) | (((data & 0b00010000) >> 4) << 23) |
(((data & 0b11100000) >> 5) << 25) | clock;
GPIO.out_w1ts = send;
GPIO.out_w1tc = send;
data = this->model_ == INKPLATE_6_PLUS ? LUTW[(~buffer_value >> 4) & 0x0F] : LUTB[(buffer_value >> 4) & 0x0F];
GPIO.out_w1ts = this->pin_lut_[data] | clock;
GPIO.out_w1tc = data_mask | clock;
data = this->model_ == INKPLATE_6_PLUS ? LUTW[(~buffer_value) & 0x0F] : LUTB[buffer_value & 0x0F];
GPIO.out_w1ts = this->pin_lut_[data] | clock;
GPIO.out_w1tc = data_mask | clock;
}
GPIO.out_w1ts = send;
GPIO.out_w1tc = get_data_pin_mask_() | clock;
GPIO.out_w1ts = clock;
GPIO.out_w1tc = data_mask | clock;
vscan_end_();
}
delayMicroseconds(230);
}
ESP_LOGV(TAG, "Display1b first loop x %d (%ums)", 3, millis() - start_time);
ESP_LOGV(TAG, "Display1b first loop x %d (%ums)", 4, millis() - start_time);
buffer_ptr = &this->buffer_[this->get_buffer_length_() - 1];
vscan_start_();
for (int i = 0; i < this->get_height_internal(); i++) {
for (int i = 0, im = this->get_height_internal(); i < im; i++) {
buffer_value = *(buffer_ptr--);
data = LUT2[(buffer_value >> 4) & 0x0F];
send = ((data & 0b00000011) << 4) | (((data & 0b00001100) >> 2) << 18) | (((data & 0b00010000) >> 4) << 23) |
(((data & 0b11100000) >> 5) << 25);
hscan_start_(send);
data = LUT2[buffer_value & 0x0F];
send = ((data & 0b00000011) << 4) | (((data & 0b00001100) >> 2) << 18) | (((data & 0b00010000) >> 4) << 23) |
(((data & 0b11100000) >> 5) << 25) | clock;
GPIO.out_w1ts = send;
GPIO.out_w1tc = send;
data = this->model_ == INKPLATE_6_PLUS ? LUTB[(buffer_value >> 4) & 0x0F] : LUT2[(buffer_value >> 4) & 0x0F];
hscan_start_(this->pin_lut_[data] | clock);
data = this->model_ == INKPLATE_6_PLUS ? LUTB[buffer_value & 0x0F] : LUT2[buffer_value & 0x0F];
GPIO.out_w1ts = this->pin_lut_[data] | clock;
GPIO.out_w1tc = data_mask | clock;
for (int j = 0, jm = (this->get_width_internal() / 8) - 1; j < jm; j++) {
buffer_value = *(buffer_ptr--);
data = LUT2[(buffer_value >> 4) & 0x0F];
send = ((data & 0b00000011) << 4) | (((data & 0b00001100) >> 2) << 18) | (((data & 0b00010000) >> 4) << 23) |
(((data & 0b11100000) >> 5) << 25) | clock;
GPIO.out_w1ts = send;
GPIO.out_w1tc = send;
data = LUT2[buffer_value & 0x0F];
send = ((data & 0b00000011) << 4) | (((data & 0b00001100) >> 2) << 18) | (((data & 0b00010000) >> 4) << 23) |
(((data & 0b11100000) >> 5) << 25) | clock;
GPIO.out_w1ts = send;
GPIO.out_w1tc = send;
data = this->model_ == INKPLATE_6_PLUS ? LUTB[(buffer_value >> 4) & 0x0F] : LUT2[(buffer_value >> 4) & 0x0F];
GPIO.out_w1ts = this->pin_lut_[data] | clock;
GPIO.out_w1tc = data_mask | clock;
data = this->model_ == INKPLATE_6_PLUS ? LUTB[buffer_value & 0x0F] : LUT2[buffer_value & 0x0F];
GPIO.out_w1ts = this->pin_lut_[data] | clock;
GPIO.out_w1tc = data_mask | clock;
}
GPIO.out_w1ts = send;
GPIO.out_w1tc = get_data_pin_mask_() | clock;
GPIO.out_w1ts = clock;
GPIO.out_w1tc = data_mask | clock;
vscan_end_();
}
delayMicroseconds(230);
ESP_LOGV(TAG, "Display1b second loop (%ums)", millis() - start_time);
if (this->model_ == INKPLATE_6_PLUS) {
clean_fast_(2, 2);
clean_fast_(3, 1);
} else {
uint32_t send = this->pin_lut_[0];
vscan_start_();
for (int i = 0; i < this->get_height_internal(); i++) {
data = 0b00000000;
send = ((data & 0b00000011) << 4) | (((data & 0b00001100) >> 2) << 18) | (((data & 0b00010000) >> 4) << 23) |
(((data & 0b11100000) >> 5) << 25);
for (int i = 0, im = this->get_height_internal(); i < im; i++) {
hscan_start_(send);
send |= clock;
GPIO.out_w1ts = send;
GPIO.out_w1tc = send;
for (int j = 0; j < (this->get_width_internal() / 8) - 1; j++) {
GPIO.out_w1ts = send;
GPIO.out_w1tc = send;
GPIO.out_w1ts = send;
GPIO.out_w1tc = send;
GPIO.out_w1ts = send | clock;
GPIO.out_w1tc = data_mask | clock;
for (int j = 0, jm = (this->get_width_internal() / 8) - 1; j < jm; j++) {
GPIO.out_w1ts = send | clock;
GPIO.out_w1tc = data_mask | clock;
GPIO.out_w1ts = send | clock;
GPIO.out_w1tc = data_mask | clock;
}
GPIO.out_w1ts = clock;
GPIO.out_w1tc = get_data_pin_mask_() | clock;
GPIO.out_w1ts = send | clock;
GPIO.out_w1tc = data_mask | clock;
vscan_end_();
}
delayMicroseconds(230);
ESP_LOGV(TAG, "Display1b third loop (%ums)", millis() - start_time);
}
vscan_start_();
eink_off_();
this->block_partial_ = false;
this->partial_updates_ = 0;
ESP_LOGV(TAG, "Display1b finished (%ums)", millis() - start_time);
}
void Inkplate6::display3b_() {
ESP_LOGV(TAG, "Display3b called");
uint32_t start_time = millis();
eink_on_();
if (this->model_ == INKPLATE_6_PLUS) {
clean_fast_(0, 1);
clean_fast_(1, 12);
clean_fast_(1, 15);
clean_fast_(2, 1);
clean_fast_(0, 11);
clean_fast_(0, 5);
clean_fast_(2, 1);
clean_fast_(1, 12);
clean_fast_(1, 15);
} else {
clean_fast_(0, 1);
clean_fast_(1, 21);
clean_fast_(2, 1);
clean_fast_(0, 11);
clean_fast_(0, 12);
clean_fast_(2, 1);
clean_fast_(1, 21);
clean_fast_(2, 1);
clean_fast_(0, 12);
}
uint32_t clock = (1 << this->cl_pin_->get_pin());
for (int k = 0; k < 8; k++) {
const uint8_t *buffer_ptr = &this->buffer_[this->get_buffer_length_() - 1];
uint32_t send;
uint8_t pix1;
uint8_t pix2;
uint8_t pix3;
uint8_t pix4;
uint8_t pixel;
uint8_t pixel2;
uint32_t data_mask = this->get_data_pin_mask_();
uint32_t pos;
uint32_t data;
uint8_t glut_size = this->model_ == INKPLATE_6_PLUS ? 9 : 8;
for (int k = 0; k < glut_size; k++) {
pos = this->get_buffer_length_();
vscan_start_();
for (int i = 0; i < this->get_height_internal(); i++) {
pix1 = (*buffer_ptr--);
pix2 = (*buffer_ptr--);
pix3 = (*buffer_ptr--);
pix4 = (*buffer_ptr--);
pixel = (waveform3Bit[pix1 & 0x07][k] << 6) | (waveform3Bit[(pix1 >> 4) & 0x07][k] << 4) |
(waveform3Bit[pix2 & 0x07][k] << 2) | (waveform3Bit[(pix2 >> 4) & 0x07][k] << 0);
pixel2 = (waveform3Bit[pix3 & 0x07][k] << 6) | (waveform3Bit[(pix3 >> 4) & 0x07][k] << 4) |
(waveform3Bit[pix4 & 0x07][k] << 2) | (waveform3Bit[(pix4 >> 4) & 0x07][k] << 0);
data = this->glut2_[k * 256 + this->buffer_[--pos]];
data |= this->glut_[k * 256 + this->buffer_[--pos]];
hscan_start_(data);
data = this->glut2_[k * 256 + this->buffer_[--pos]];
data |= this->glut_[k * 256 + this->buffer_[--pos]];
GPIO.out_w1ts = data | clock;
GPIO.out_w1tc = data_mask | clock;
send = ((pixel & 0b00000011) << 4) | (((pixel & 0b00001100) >> 2) << 18) | (((pixel & 0b00010000) >> 4) << 23) |
(((pixel & 0b11100000) >> 5) << 25);
hscan_start_(send);
send = ((pixel2 & 0b00000011) << 4) | (((pixel2 & 0b00001100) >> 2) << 18) |
(((pixel2 & 0b00010000) >> 4) << 23) | (((pixel2 & 0b11100000) >> 5) << 25) | clock;
GPIO.out_w1ts = send;
GPIO.out_w1tc = send;
for (int j = 0, jm = (this->get_width_internal() / 8) - 1; j < jm; j++) {
pix1 = (*buffer_ptr--);
pix2 = (*buffer_ptr--);
pix3 = (*buffer_ptr--);
pix4 = (*buffer_ptr--);
pixel = (waveform3Bit[pix1 & 0x07][k] << 6) | (waveform3Bit[(pix1 >> 4) & 0x07][k] << 4) |
(waveform3Bit[pix2 & 0x07][k] << 2) | (waveform3Bit[(pix2 >> 4) & 0x07][k] << 0);
pixel2 = (waveform3Bit[pix3 & 0x07][k] << 6) | (waveform3Bit[(pix3 >> 4) & 0x07][k] << 4) |
(waveform3Bit[pix4 & 0x07][k] << 2) | (waveform3Bit[(pix4 >> 4) & 0x07][k] << 0);
send = ((pixel & 0b00000011) << 4) | (((pixel & 0b00001100) >> 2) << 18) | (((pixel & 0b00010000) >> 4) << 23) |
(((pixel & 0b11100000) >> 5) << 25) | clock;
GPIO.out_w1ts = send;
GPIO.out_w1tc = send;
send = ((pixel2 & 0b00000011) << 4) | (((pixel2 & 0b00001100) >> 2) << 18) |
(((pixel2 & 0b00010000) >> 4) << 23) | (((pixel2 & 0b11100000) >> 5) << 25) | clock;
GPIO.out_w1ts = send;
GPIO.out_w1tc = send;
for (int j = 0; j < (this->get_width_internal() / 8) - 1; j++) {
data = this->glut2_[k * 256 + this->buffer_[--pos]];
data |= this->glut_[k * 256 + this->buffer_[--pos]];
GPIO.out_w1ts = data | clock;
GPIO.out_w1tc = data_mask | clock;
data = this->glut2_[k * 256 + this->buffer_[--pos]];
data |= this->glut_[k * 256 + this->buffer_[--pos]];
GPIO.out_w1ts = data | clock;
GPIO.out_w1tc = data_mask | clock;
}
GPIO.out_w1ts = send;
GPIO.out_w1tc = get_data_pin_mask_() | clock;
GPIO.out_w1ts = clock;
GPIO.out_w1tc = data_mask | clock;
vscan_end_();
}
delayMicroseconds(230);
}
clean_fast_(2, 1);
clean_fast_(3, 1);
vscan_start_();
eink_off_();
ESP_LOGV(TAG, "Display3b finished (%ums)", millis() - start_time);
}
bool Inkplate6::partial_update_() {
ESP_LOGV(TAG, "Partial update called");
uint32_t start_time = millis();
@ -432,16 +501,15 @@ bool Inkplate6::partial_update_() {
this->partial_updates_++;
uint16_t pos = this->get_buffer_length_() - 1;
uint32_t send;
uint32_t pos = this->get_buffer_length_() - 1;
uint8_t data;
uint8_t diffw, diffb;
uint32_t n = (this->get_buffer_length_() * 2) - 1;
for (int i = 0, im = this->get_height_internal(); i < im; i++) {
for (int j = 0, jm = (this->get_width_internal() / 8); j < jm; j++) {
diffw = (this->buffer_[pos] ^ this->partial_buffer_[pos]) & ~(this->partial_buffer_[pos]);
diffb = (this->buffer_[pos] ^ this->partial_buffer_[pos]) & this->partial_buffer_[pos];
diffw = this->buffer_[pos] & ~(this->partial_buffer_[pos]);
diffb = ~(this->buffer_[pos]) & this->partial_buffer_[pos];
pos--;
this->partial_buffer_2_[n--] = LUTW[diffw >> 4] & LUTB[diffb >> 4];
this->partial_buffer_2_[n--] = LUTW[diffw & 0x0F] & LUTB[diffb & 0x0F];
@ -451,23 +519,20 @@ bool Inkplate6::partial_update_() {
eink_on_();
uint32_t clock = (1 << this->cl_pin_->get_pin());
uint32_t data_mask = this->get_data_pin_mask_();
for (int k = 0; k < 5; k++) {
vscan_start_();
const uint8_t *data_ptr = &this->partial_buffer_2_[(this->get_buffer_length_() * 2) - 1];
for (int i = 0; i < this->get_height_internal(); i++) {
data = *(data_ptr--);
send = ((data & 0b00000011) << 4) | (((data & 0b00001100) >> 2) << 18) | (((data & 0b00010000) >> 4) << 23) |
(((data & 0b11100000) >> 5) << 25);
hscan_start_(send);
hscan_start_(this->pin_lut_[data]);
for (int j = 0, jm = (this->get_width_internal() / 4) - 1; j < jm; j++) {
data = *(data_ptr--);
send = ((data & 0b00000011) << 4) | (((data & 0b00001100) >> 2) << 18) | (((data & 0b00010000) >> 4) << 23) |
(((data & 0b11100000) >> 5) << 25) | clock;
GPIO.out_w1ts = send;
GPIO.out_w1tc = send;
GPIO.out_w1ts = this->pin_lut_[data] | clock;
GPIO.out_w1tc = data_mask | clock;
}
GPIO.out_w1ts = send;
GPIO.out_w1tc = get_data_pin_mask_() | clock;
GPIO.out_w1ts = clock;
GPIO.out_w1tc = data_mask | clock;
vscan_end_();
}
delayMicroseconds(230);
@ -482,6 +547,7 @@ bool Inkplate6::partial_update_() {
ESP_LOGV(TAG, "Partial update finished (%ums)", millis() - start_time);
return true;
}
void Inkplate6::vscan_start_() {
this->ckv_pin_->digital_write(true);
delayMicroseconds(7);
@ -505,30 +571,23 @@ void Inkplate6::vscan_start_() {
delayMicroseconds(0);
this->ckv_pin_->digital_write(true);
}
void Inkplate6::vscan_write_() {
this->ckv_pin_->digital_write(false);
this->le_pin_->digital_write(true);
this->le_pin_->digital_write(false);
delayMicroseconds(0);
void Inkplate6::hscan_start_(uint32_t d) {
uint8_t clock = (1 << this->cl_pin_->get_pin());
this->sph_pin_->digital_write(false);
this->cl_pin_->digital_write(true);
this->cl_pin_->digital_write(false);
GPIO.out_w1ts = d | clock;
GPIO.out_w1tc = this->get_data_pin_mask_() | clock;
this->sph_pin_->digital_write(true);
this->ckv_pin_->digital_write(true);
}
void Inkplate6::hscan_start_(uint32_t d) {
this->sph_pin_->digital_write(false);
GPIO.out_w1ts = (d) | (1 << this->cl_pin_->get_pin());
GPIO.out_w1tc = get_data_pin_mask_() | (1 << this->cl_pin_->get_pin());
this->sph_pin_->digital_write(true);
}
void Inkplate6::vscan_end_() {
this->ckv_pin_->digital_write(false);
this->le_pin_->digital_write(true);
this->le_pin_->digital_write(false);
delayMicroseconds(1);
this->ckv_pin_->digital_write(true);
delayMicroseconds(0);
}
void Inkplate6::clean() {
ESP_LOGV(TAG, "Clean called");
uint32_t start_time = millis();
@ -542,6 +601,7 @@ void Inkplate6::clean() {
clean_fast_(1, 10); // White to White
ESP_LOGV(TAG, "Clean finished (%ums)", millis() - start_time);
}
void Inkplate6::clean_fast_(uint8_t c, uint8_t rep) {
ESP_LOGV(TAG, "Clean fast called with: (%d, %d)", c, rep);
uint32_t start_time = millis();
@ -568,14 +628,14 @@ void Inkplate6::clean_fast_(uint8_t c, uint8_t rep) {
hscan_start_(send);
GPIO.out_w1ts = send | clock;
GPIO.out_w1tc = clock;
for (int j = 0, jm = this->get_width_internal() / 8; j < jm; j++) {
for (int j = 0; j < (this->get_width_internal() / 8) - 1; j++) {
GPIO.out_w1ts = clock;
GPIO.out_w1tc = clock;
GPIO.out_w1ts = clock;
GPIO.out_w1tc = clock;
}
GPIO.out_w1ts = clock;
GPIO.out_w1tc = get_data_pin_mask_() | clock;
GPIO.out_w1ts = send | clock;
GPIO.out_w1tc = clock;
vscan_end_();
}
delayMicroseconds(230);
@ -583,7 +643,10 @@ void Inkplate6::clean_fast_(uint8_t c, uint8_t rep) {
}
ESP_LOGV(TAG, "Clean fast finished (%ums)", millis() - start_time);
}
void Inkplate6::pins_z_state_() {
this->cl_pin_->pin_mode(gpio::FLAG_INPUT);
this->le_pin_->pin_mode(gpio::FLAG_INPUT);
this->ckv_pin_->pin_mode(gpio::FLAG_INPUT);
this->sph_pin_->pin_mode(gpio::FLAG_INPUT);
@ -600,7 +663,10 @@ void Inkplate6::pins_z_state_() {
this->display_data_6_pin_->pin_mode(gpio::FLAG_INPUT);
this->display_data_7_pin_->pin_mode(gpio::FLAG_INPUT);
}
void Inkplate6::pins_as_outputs_() {
this->cl_pin_->pin_mode(gpio::FLAG_OUTPUT);
this->le_pin_->pin_mode(gpio::FLAG_OUTPUT);
this->ckv_pin_->pin_mode(gpio::FLAG_OUTPUT);
this->sph_pin_->pin_mode(gpio::FLAG_OUTPUT);

View file

@ -13,32 +13,28 @@ namespace inkplate6 {
enum InkplateModel : uint8_t {
INKPLATE_6 = 0,
INKPLATE_10 = 1,
INKPLATE_6_PLUS = 2,
};
class Inkplate6 : public PollingComponent, public display::DisplayBuffer, public i2c::I2CDevice {
public:
const uint8_t LUT2[16] = {0b10101010, 0b10101001, 0b10100110, 0b10100101, 0b10011010, 0b10011001,
0b10010110, 0b10010101, 0b01101010, 0b01101001, 0b01100110, 0b01100101,
0b01011010, 0b01011001, 0b01010110, 0b01010101};
const uint8_t LUTW[16] = {0b11111111, 0b11111110, 0b11111011, 0b11111010, 0b11101111, 0b11101110,
0b11101011, 0b11101010, 0b10111111, 0b10111110, 0b10111011, 0b10111010,
0b10101111, 0b10101110, 0b10101011, 0b10101010};
const uint8_t LUTB[16] = {0b11111111, 0b11111101, 0b11110111, 0b11110101, 0b11011111, 0b11011101,
0b11010111, 0b11010101, 0b01111111, 0b01111101, 0b01110111, 0b01110101,
0b01011111, 0b01011101, 0b01010111, 0b01010101};
const uint8_t pixelMaskLUT[8] = {0b00000001, 0b00000010, 0b00000100, 0b00001000,
0b00010000, 0b00100000, 0b01000000, 0b10000000};
const uint8_t pixelMaskGLUT[2] = {0b00001111, 0b11110000};
const uint8_t waveform3Bit[8][8] = {{0, 0, 0, 0, 1, 1, 1, 0}, {1, 2, 2, 2, 1, 1, 1, 0}, {0, 1, 2, 1, 1, 2, 1, 0},
{0, 2, 1, 2, 1, 2, 1, 0}, {0, 0, 0, 1, 1, 1, 2, 0}, {2, 1, 1, 1, 2, 1, 2, 0},
const uint8_t LUT2[16] = {0xAA, 0xA9, 0xA6, 0xA5, 0x9A, 0x99, 0x96, 0x95,
0x6A, 0x69, 0x66, 0x65, 0x5A, 0x59, 0x56, 0x55};
const uint8_t LUTW[16] = {0xFF, 0xFE, 0xFB, 0xFA, 0xEF, 0xEE, 0xEB, 0xEA,
0xBF, 0xBE, 0xBB, 0xBA, 0xAF, 0xAE, 0xAB, 0xAA};
const uint8_t LUTB[16] = {0xFF, 0xFD, 0xF7, 0xF5, 0xDF, 0xDD, 0xD7, 0xD5,
0x7F, 0x7D, 0x77, 0x75, 0x5F, 0x5D, 0x57, 0x55};
const uint8_t pixelMaskLUT[8] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
const uint8_t pixelMaskGLUT[2] = {0x0F, 0xF0};
const uint8_t waveform3Bit[8][8] = {{0, 1, 1, 0, 0, 1, 1, 0}, {0, 1, 2, 1, 1, 2, 1, 0}, {1, 1, 1, 2, 2, 1, 0, 0},
{0, 0, 0, 1, 1, 1, 2, 0}, {2, 1, 1, 1, 2, 1, 2, 0}, {2, 2, 1, 1, 2, 1, 2, 0},
{1, 1, 1, 2, 1, 2, 2, 0}, {0, 0, 0, 0, 0, 0, 2, 0}};
const uint32_t waveform[50] = {
0x00000008, 0x00000008, 0x00200408, 0x80281888, 0x60a81898, 0x60a8a8a8, 0x60a8a8a8, 0x6068a868, 0x6868a868,
0x6868a868, 0x68686868, 0x6a686868, 0x5a686868, 0x5a686868, 0x5a586a68, 0x5a5a6a68, 0x5a5a6a68, 0x55566a68,
0x55565a64, 0x55555654, 0x55555556, 0x55555556, 0x55555556, 0x55555516, 0x55555596, 0x15555595, 0x95955595,
0x95959595, 0x95949495, 0x94949495, 0x94949495, 0xa4949494, 0x9494a4a4, 0x84a49494, 0x84948484, 0x84848484,
0x84848484, 0x84848484, 0xa5a48484, 0xa9a4a4a8, 0xa9a8a8a8, 0xa5a9a9a4, 0xa5a5a5a4, 0xa1a5a5a1, 0xa9a9a9a9,
0xa9a9a9a9, 0xa9a9a9a9, 0xa9a9a9a9, 0x15151515, 0x11111111};
const uint8_t waveform3Bit6Plus[8][9] = {{0, 0, 0, 0, 0, 2, 1, 1, 0}, {0, 0, 2, 1, 1, 1, 2, 1, 0},
{0, 2, 2, 2, 1, 1, 2, 1, 0}, {0, 0, 2, 2, 2, 1, 2, 1, 0},
{0, 0, 0, 0, 2, 2, 2, 1, 0}, {0, 0, 2, 1, 2, 1, 1, 2, 0},
{0, 0, 2, 2, 2, 1, 1, 2, 0}, {0, 0, 0, 0, 2, 2, 2, 2, 0}};
void set_greyscale(bool greyscale) {
this->greyscale_ = greyscale;
@ -88,6 +84,8 @@ class Inkplate6 : public PollingComponent, public display::DisplayBuffer, public
bool get_partial_updating() { return this->partial_updating_; }
uint8_t get_temperature() { return this->temperature_; }
void block_partial() { this->block_partial_ = true; }
protected:
void draw_absolute_pixel_internal(int x, int y, Color color) override;
void display1b_();
@ -99,10 +97,10 @@ class Inkplate6 : public PollingComponent, public display::DisplayBuffer, public
void hscan_start_(uint32_t d);
void vscan_end_();
void vscan_start_();
void vscan_write_();
void eink_off_();
void eink_on_();
bool read_power_status_();
void setup_pins_();
void pins_z_state_();
@ -113,6 +111,8 @@ class Inkplate6 : public PollingComponent, public display::DisplayBuffer, public
return 800;
} else if (this->model_ == INKPLATE_10) {
return 1200;
} else if (this->model_ == INKPLATE_6_PLUS) {
return 1024;
}
return 0;
}
@ -122,6 +122,8 @@ class Inkplate6 : public PollingComponent, public display::DisplayBuffer, public
return 600;
} else if (this->model_ == INKPLATE_10) {
return 825;
} else if (this->model_ == INKPLATE_6_PLUS) {
return 758;
}
return 0;
}
@ -141,16 +143,20 @@ class Inkplate6 : public PollingComponent, public display::DisplayBuffer, public
return data;
}
uint8_t panel_on_ = 0;
bool panel_on_{false};
uint8_t temperature_;
uint8_t *partial_buffer_{nullptr};
uint8_t *partial_buffer_2_{nullptr};
uint32_t *glut_{nullptr};
uint32_t *glut2_{nullptr};
uint32_t pin_lut_[256];
uint32_t full_update_every_;
uint32_t partial_updates_{0};
bool block_partial_;
bool block_partial_{true};
bool greyscale_;
bool partial_updating_;