From 4788a6182e295abc7ee50b30234bf6f893d81479 Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Fri, 2 Sep 2022 05:46:51 +0200 Subject: [PATCH] I found some issue in the ili9341 driver (#3756) --- .../components/ili9341/ili9341_display.cpp | 92 ++++++++++++------- esphome/components/ili9341/ili9341_display.h | 12 ++- 2 files changed, 71 insertions(+), 33 deletions(-) diff --git a/esphome/components/ili9341/ili9341_display.cpp b/esphome/components/ili9341/ili9341_display.cpp index c4fa5f1b10..117de3de89 100644 --- a/esphome/components/ili9341/ili9341_display.cpp +++ b/esphome/components/ili9341/ili9341_display.cpp @@ -10,7 +10,6 @@ namespace ili9341 { static const char *const TAG = "ili9341"; void ILI9341Display::setup_pins_() { - this->init_internal_(this->get_buffer_length_()); this->dc_pin_->setup(); // OUTPUT this->dc_pin_->digital_write(false); if (this->reset_pin_ != nullptr) { @@ -28,15 +27,14 @@ void ILI9341Display::setup_pins_() { void ILI9341Display::dump_config() { LOG_DISPLAY("", "ili9341", this); - ESP_LOGCONFIG(TAG, " Width: %d, Height: %d, Rotation: %d", this->width_, this->height_, this->rotation_); LOG_PIN(" Reset Pin: ", this->reset_pin_); LOG_PIN(" DC Pin: ", this->dc_pin_); LOG_PIN(" Busy Pin: ", this->busy_pin_); - LOG_PIN(" Backlight Pin: ", this->led_pin_); LOG_UPDATE_INTERVAL(this); } -float ILI9341Display::get_setup_priority() const { return setup_priority::PROCESSOR; } +float ILI9341Display::get_setup_priority() const { return setup_priority::HARDWARE; } + void ILI9341Display::command(uint8_t value) { this->start_command_(); this->write_byte(value); @@ -88,10 +86,19 @@ void ILI9341Display::display_() { // we will only update the changed window to the display uint16_t w = this->x_high_ - this->x_low_ + 1; uint16_t h = this->y_high_ - this->y_low_ + 1; + uint32_t start_pos = ((this->y_low_ * this->width_) + x_low_); + + // check if something was displayed + if ((this->x_high_ < this->x_low_) || (this->y_high_ < this->y_low_)) { + return; + } set_addr_window_(this->x_low_, this->y_low_, w, h); + + ESP_LOGVV("ILI9341", "Start ILI9341Display::display_(xl:%d, xh:%d, yl:%d, yh:%d, w:%d, h:%d, start_pos:%d)", + this->x_low_, this->x_high_, this->y_low_, this->y_high_, w, h, start_pos); + this->start_data_(); - uint32_t start_pos = ((this->y_low_ * this->width_) + x_low_); for (uint16_t row = 0; row < h; row++) { uint32_t pos = start_pos + (row * width_); uint32_t rem = w; @@ -101,7 +108,9 @@ void ILI9341Display::display_() { this->write_array(transfer_buffer_, 2 * sz); pos += sz; rem -= sz; + App.feed_wdt(); } + App.feed_wdt(); } this->end_data_(); @@ -121,20 +130,10 @@ void ILI9341Display::fill(Color color) { this->y_high_ = this->get_height_internal() - 1; } -void ILI9341Display::fill_internal_(Color color) { - if (color.raw_32 == Color::BLACK.raw_32) { - memset(transfer_buffer_, 0, sizeof(transfer_buffer_)); - } else { - uint8_t *dst = transfer_buffer_; - auto color565 = display::ColorUtil::color_to_565(color); +void ILI9341Display::fill_internal_(uint8_t color) { + memset(transfer_buffer_, color, sizeof(transfer_buffer_)); - while (dst < transfer_buffer_ + sizeof(transfer_buffer_)) { - *dst++ = (uint8_t)(color565 >> 8); - *dst++ = (uint8_t) color565; - } - } - - uint32_t rem = this->get_width_internal() * this->get_height_internal(); + uint32_t rem = (this->get_buffer_length_() * 2); this->set_addr_window_(0, 0, this->get_width_internal(), this->get_height_internal()); this->start_data_(); @@ -147,26 +146,58 @@ void ILI9341Display::fill_internal_(Color color) { this->end_data_(); - memset(buffer_, 0, (this->get_width_internal()) * (this->get_height_internal())); + memset(buffer_, color, this->get_buffer_length_()); +} + +void ILI9341Display::rotate_my_(uint8_t m) { + uint8_t rotation = m & 3; // can't be higher than 3 + switch (rotation) { + case 0: + m = (MADCTL_MX | MADCTL_BGR); + // _width = ILI9341_TFTWIDTH; + // _height = ILI9341_TFTHEIGHT; + break; + case 1: + m = (MADCTL_MV | MADCTL_BGR); + // _width = ILI9341_TFTHEIGHT; + // _height = ILI9341_TFTWIDTH; + break; + case 2: + m = (MADCTL_MY | MADCTL_BGR); + // _width = ILI9341_TFTWIDTH; + // _height = ILI9341_TFTHEIGHT; + break; + case 3: + m = (MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR); + // _width = ILI9341_TFTHEIGHT; + // _height = ILI9341_TFTWIDTH; + break; + } + + this->command(ILI9341_MADCTL); + this->data(m); } void HOT ILI9341Display::draw_absolute_pixel_internal(int x, int y, Color color) { if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0) return; - // low and high watermark may speed up drawing from buffer - this->x_low_ = (x < this->x_low_) ? x : this->x_low_; - this->y_low_ = (y < this->y_low_) ? y : this->y_low_; - this->x_high_ = (x > this->x_high_) ? x : this->x_high_; - this->y_high_ = (y > this->y_high_) ? y : this->y_high_; - uint32_t pos = (y * width_) + x; + uint8_t new_color; + if (this->buffer_color_mode_ == BITS_8) { - uint8_t color332 = display::ColorUtil::color_to_332(color, display::ColorOrder::COLOR_ORDER_RGB); - buffer_[pos] = color332; + new_color = display::ColorUtil::color_to_332(color, display::ColorOrder::COLOR_ORDER_RGB); } else { // if (this->buffer_color_mode_ == BITS_8_INDEXED) { - uint8_t index = display::ColorUtil::color_to_index8_palette888(color, this->palette_); - buffer_[pos] = index; + new_color = display::ColorUtil::color_to_index8_palette888(color, this->palette_); + } + + if (buffer_[pos] != new_color) { + buffer_[pos] = new_color; + // low and high watermark may speed up drawing from buffer + this->x_low_ = (x < this->x_low_) ? x : this->x_low_; + this->y_low_ = (y < this->y_low_) ? y : this->y_low_; + this->x_high_ = (x > this->x_high_) ? x : this->x_high_; + this->y_high_ = (y > this->y_high_) ? y : this->y_high_; } } @@ -252,7 +283,6 @@ void ILI9341M5Stack::initialize() { this->width_ = 320; this->height_ = 240; this->invert_display_(true); - this->fill_internal_(Color::BLACK); } // 24_TFT display @@ -260,7 +290,6 @@ void ILI9341TFT24::initialize() { this->init_lcd_(INITCMD_TFT); this->width_ = 240; this->height_ = 320; - this->fill_internal_(Color::BLACK); } // 24_TFT rotated display @@ -268,7 +297,6 @@ void ILI9341TFT24R::initialize() { this->init_lcd_(INITCMD_TFT); this->width_ = 320; this->height_ = 240; - this->fill_internal_(Color::BLACK); } } // namespace ili9341 diff --git a/esphome/components/ili9341/ili9341_display.h b/esphome/components/ili9341/ili9341_display.h index 3fbc144ac2..547c608ae8 100644 --- a/esphome/components/ili9341/ili9341_display.h +++ b/esphome/components/ili9341/ili9341_display.h @@ -5,6 +5,7 @@ #include "esphome/components/display/display_buffer.h" #include "ili9341_defines.h" #include "ili9341_init.h" +#include "esphome/core/log.h" namespace esphome { namespace ili9341 { @@ -47,6 +48,14 @@ class ILI9341Display : public PollingComponent, void setup() override { this->setup_pins_(); this->initialize(); + + this->x_low_ = this->width_; + this->y_low_ = this->height_; + this->x_high_ = 0; + this->y_high_ = 0; + + this->init_internal_(this->get_buffer_length_()); + this->fill_internal_(0x00); } display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; } @@ -59,8 +68,9 @@ class ILI9341Display : public PollingComponent, void set_addr_window_(uint16_t x, uint16_t y, uint16_t w, uint16_t h); void invert_display_(bool invert); void reset_(); - void fill_internal_(Color color); + void fill_internal_(uint8_t color); void display_(); + void rotate_my_(uint8_t m); ILI9341Model model_; int16_t width_{320}; ///< Display width as modified by current rotation