mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Speed up (and fix) ili9xxx display component. (#5406)
This commit is contained in:
		| @@ -2,6 +2,7 @@ import esphome.codegen as cg | |||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome import core, pins | from esphome import core, pins | ||||||
| from esphome.components import display, spi, font | from esphome.components import display, spi, font | ||||||
|  | from esphome.components.display import validate_rotation | ||||||
| from esphome.core import CORE, HexInt | from esphome.core import CORE, HexInt | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_COLOR_PALETTE, |     CONF_COLOR_PALETTE, | ||||||
| @@ -13,6 +14,9 @@ from esphome.const import ( | |||||||
|     CONF_PAGES, |     CONF_PAGES, | ||||||
|     CONF_RESET_PIN, |     CONF_RESET_PIN, | ||||||
|     CONF_DIMENSIONS, |     CONF_DIMENSIONS, | ||||||
|  |     CONF_WIDTH, | ||||||
|  |     CONF_HEIGHT, | ||||||
|  |     CONF_ROTATION, | ||||||
| ) | ) | ||||||
|  |  | ||||||
| DEPENDENCIES = ["spi"] | DEPENDENCIES = ["spi"] | ||||||
| @@ -26,28 +30,35 @@ def AUTO_LOAD(): | |||||||
|  |  | ||||||
| CODEOWNERS = ["@nielsnl68", "@clydebarrow"] | CODEOWNERS = ["@nielsnl68", "@clydebarrow"] | ||||||
|  |  | ||||||
| ili9XXX_ns = cg.esphome_ns.namespace("ili9xxx") | ili9xxx_ns = cg.esphome_ns.namespace("ili9xxx") | ||||||
| ili9XXXSPI = ili9XXX_ns.class_( | ILI9XXXDisplay = ili9xxx_ns.class_( | ||||||
|     "ILI9XXXDisplay", cg.PollingComponent, spi.SPIDevice, display.DisplayBuffer |     "ILI9XXXDisplay", cg.PollingComponent, spi.SPIDevice, display.DisplayBuffer | ||||||
| ) | ) | ||||||
|  |  | ||||||
| ILI9XXXColorMode = ili9XXX_ns.enum("ILI9XXXColorMode") | ILI9XXXColorMode = ili9xxx_ns.enum("ILI9XXXColorMode") | ||||||
|  | ColorOrder = display.display_ns.enum("ColorMode") | ||||||
|  |  | ||||||
| MODELS = { | MODELS = { | ||||||
|     "M5STACK": ili9XXX_ns.class_("ILI9XXXM5Stack", ili9XXXSPI), |     "M5STACK": ili9xxx_ns.class_("ILI9XXXM5Stack", ILI9XXXDisplay), | ||||||
|     "M5CORE": ili9XXX_ns.class_("ILI9XXXM5CORE", ili9XXXSPI), |     "M5CORE": ili9xxx_ns.class_("ILI9XXXM5CORE", ILI9XXXDisplay), | ||||||
|     "TFT_2.4": ili9XXX_ns.class_("ILI9XXXILI9341", ili9XXXSPI), |     "TFT_2.4": ili9xxx_ns.class_("ILI9XXXILI9341", ILI9XXXDisplay), | ||||||
|     "TFT_2.4R": ili9XXX_ns.class_("ILI9XXXILI9342", ili9XXXSPI), |     "TFT_2.4R": ili9xxx_ns.class_("ILI9XXXILI9342", ILI9XXXDisplay), | ||||||
|     "ILI9341": ili9XXX_ns.class_("ILI9XXXILI9341", ili9XXXSPI), |     "ILI9341": ili9xxx_ns.class_("ILI9XXXILI9341", ILI9XXXDisplay), | ||||||
|     "ILI9342": ili9XXX_ns.class_("ILI9XXXILI9342", ili9XXXSPI), |     "ILI9342": ili9xxx_ns.class_("ILI9XXXILI9342", ILI9XXXDisplay), | ||||||
|     "ILI9481": ili9XXX_ns.class_("ILI9XXXILI9481", ili9XXXSPI), |     "ILI9481": ili9xxx_ns.class_("ILI9XXXILI9481", ILI9XXXDisplay), | ||||||
|     "ILI9481-18": ili9XXX_ns.class_("ILI9XXXILI948118", ili9XXXSPI), |     "ILI9481-18": ili9xxx_ns.class_("ILI9XXXILI948118", ILI9XXXDisplay), | ||||||
|     "ILI9486": ili9XXX_ns.class_("ILI9XXXILI9486", ili9XXXSPI), |     "ILI9486": ili9xxx_ns.class_("ILI9XXXILI9486", ILI9XXXDisplay), | ||||||
|     "ILI9488": ili9XXX_ns.class_("ILI9XXXILI9488", ili9XXXSPI), |     "ILI9488": ili9xxx_ns.class_("ILI9XXXILI9488", ILI9XXXDisplay), | ||||||
|     "ILI9488_A": ili9XXX_ns.class_("ILI9XXXILI9488A", ili9XXXSPI), |     "ILI9488_A": ili9xxx_ns.class_("ILI9XXXILI9488A", ILI9XXXDisplay), | ||||||
|     "ST7796": ili9XXX_ns.class_("ILI9XXXST7796", ili9XXXSPI), |     "ST7796": ili9xxx_ns.class_("ILI9XXXST7796", ILI9XXXDisplay), | ||||||
|     "S3BOX": ili9XXX_ns.class_("ILI9XXXS3Box", ili9XXXSPI), |     "ST7789V": ili9xxx_ns.class_("ILI9XXXST7789V", ILI9XXXDisplay), | ||||||
|     "S3BOX_LITE": ili9XXX_ns.class_("ILI9XXXS3BoxLite", ili9XXXSPI), |     "S3BOX": ili9xxx_ns.class_("ILI9XXXS3Box", ILI9XXXDisplay), | ||||||
|  |     "S3BOX_LITE": ili9xxx_ns.class_("ILI9XXXS3BoxLite", ILI9XXXDisplay), | ||||||
|  | } | ||||||
|  |  | ||||||
|  | COLOR_ORDERS = { | ||||||
|  |     "RGB": ColorOrder.COLOR_ORDER_RGB, | ||||||
|  |     "BGR": ColorOrder.COLOR_ORDER_BGR, | ||||||
| } | } | ||||||
|  |  | ||||||
| COLOR_PALETTE = cv.one_of("NONE", "GRAYSCALE", "IMAGE_ADAPTIVE") | COLOR_PALETTE = cv.one_of("NONE", "GRAYSCALE", "IMAGE_ADAPTIVE") | ||||||
| @@ -55,6 +66,14 @@ COLOR_PALETTE = cv.one_of("NONE", "GRAYSCALE", "IMAGE_ADAPTIVE") | |||||||
| CONF_LED_PIN = "led_pin" | CONF_LED_PIN = "led_pin" | ||||||
| CONF_COLOR_PALETTE_IMAGES = "color_palette_images" | CONF_COLOR_PALETTE_IMAGES = "color_palette_images" | ||||||
| CONF_INVERT_DISPLAY = "invert_display" | CONF_INVERT_DISPLAY = "invert_display" | ||||||
|  | CONF_INVERT_COLORS = "invert_colors" | ||||||
|  | CONF_MIRROR_X = "mirror_x" | ||||||
|  | CONF_MIRROR_Y = "mirror_y" | ||||||
|  | CONF_SWAP_XY = "swap_xy" | ||||||
|  | CONF_COLOR_ORDER = "color_order" | ||||||
|  | CONF_OFFSET_HEIGHT = "offset_height" | ||||||
|  | CONF_OFFSET_WIDTH = "offset_width" | ||||||
|  | CONF_TRANSFORM = "transform" | ||||||
|  |  | ||||||
|  |  | ||||||
| def _validate(config): | def _validate(config): | ||||||
| @@ -77,6 +96,7 @@ def _validate(config): | |||||||
|         "TFT_2.4R", |         "TFT_2.4R", | ||||||
|         "ILI9341", |         "ILI9341", | ||||||
|         "ILI9342", |         "ILI9342", | ||||||
|  |         "ST7789V", | ||||||
|     ]: |     ]: | ||||||
|         raise cv.Invalid( |         raise cv.Invalid( | ||||||
|             "Provided model can't run on ESP8266. Use an ESP32 with PSRAM onboard" |             "Provided model can't run on ESP8266. Use an ESP32 with PSRAM onboard" | ||||||
| @@ -88,9 +108,19 @@ CONFIG_SCHEMA = cv.All( | |||||||
|     font.validate_pillow_installed, |     font.validate_pillow_installed, | ||||||
|     display.FULL_DISPLAY_SCHEMA.extend( |     display.FULL_DISPLAY_SCHEMA.extend( | ||||||
|         { |         { | ||||||
|             cv.GenerateID(): cv.declare_id(ili9XXXSPI), |             cv.GenerateID(): cv.declare_id(ILI9XXXDisplay), | ||||||
|             cv.Required(CONF_MODEL): cv.enum(MODELS, upper=True, space="_"), |             cv.Required(CONF_MODEL): cv.enum(MODELS, upper=True, space="_"), | ||||||
|             cv.Optional(CONF_DIMENSIONS): cv.dimensions, |             cv.Optional(CONF_DIMENSIONS): cv.Any( | ||||||
|  |                 cv.dimensions, | ||||||
|  |                 cv.Schema( | ||||||
|  |                     { | ||||||
|  |                         cv.Required(CONF_WIDTH): cv.int_, | ||||||
|  |                         cv.Required(CONF_HEIGHT): cv.int_, | ||||||
|  |                         cv.Optional(CONF_OFFSET_HEIGHT, default=0): cv.int_, | ||||||
|  |                         cv.Optional(CONF_OFFSET_WIDTH, default=0): cv.int_, | ||||||
|  |                     } | ||||||
|  |                 ), | ||||||
|  |             ), | ||||||
|             cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, |             cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, | ||||||
|             cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, |             cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, | ||||||
|             cv.Optional(CONF_LED_PIN): cv.invalid( |             cv.Optional(CONF_LED_PIN): cv.invalid( | ||||||
| @@ -101,7 +131,19 @@ CONFIG_SCHEMA = cv.All( | |||||||
|             cv.Optional(CONF_COLOR_PALETTE_IMAGES, default=[]): cv.ensure_list( |             cv.Optional(CONF_COLOR_PALETTE_IMAGES, default=[]): cv.ensure_list( | ||||||
|                 cv.file_ |                 cv.file_ | ||||||
|             ), |             ), | ||||||
|             cv.Optional(CONF_INVERT_DISPLAY): cv.boolean, |             cv.Optional(CONF_INVERT_DISPLAY): cv.invalid( | ||||||
|  |                 "'invert_display' has been replaced by 'invert_colors'" | ||||||
|  |             ), | ||||||
|  |             cv.Optional(CONF_INVERT_COLORS): cv.boolean, | ||||||
|  |             cv.Optional(CONF_COLOR_ORDER): cv.one_of(*COLOR_ORDERS.keys(), upper=True), | ||||||
|  |             cv.Exclusive(CONF_ROTATION, CONF_ROTATION): validate_rotation, | ||||||
|  |             cv.Exclusive(CONF_TRANSFORM, CONF_ROTATION): cv.Schema( | ||||||
|  |                 { | ||||||
|  |                     cv.Optional(CONF_SWAP_XY, default=False): cv.boolean, | ||||||
|  |                     cv.Optional(CONF_MIRROR_X, default=False): cv.boolean, | ||||||
|  |                     cv.Optional(CONF_MIRROR_Y, default=False): cv.boolean, | ||||||
|  |                 } | ||||||
|  |             ), | ||||||
|         } |         } | ||||||
|     ) |     ) | ||||||
|     .extend(cv.polling_component_schema("1s")) |     .extend(cv.polling_component_schema("1s")) | ||||||
| @@ -119,6 +161,13 @@ async def to_code(config): | |||||||
|     await spi.register_spi_device(var, config) |     await spi.register_spi_device(var, config) | ||||||
|     dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) |     dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) | ||||||
|     cg.add(var.set_dc_pin(dc)) |     cg.add(var.set_dc_pin(dc)) | ||||||
|  |     if CONF_COLOR_ORDER in config: | ||||||
|  |         cg.add(var.set_color_order(COLOR_ORDERS[config[CONF_COLOR_ORDER]])) | ||||||
|  |     if CONF_TRANSFORM in config: | ||||||
|  |         transform = config[CONF_TRANSFORM] | ||||||
|  |         cg.add(var.set_swap_xy(transform[CONF_SWAP_XY])) | ||||||
|  |         cg.add(var.set_mirror_x(transform[CONF_MIRROR_X])) | ||||||
|  |         cg.add(var.set_mirror_y(transform[CONF_MIRROR_Y])) | ||||||
|  |  | ||||||
|     if CONF_LAMBDA in config: |     if CONF_LAMBDA in config: | ||||||
|         lambda_ = await cg.process_lambda( |         lambda_ = await cg.process_lambda( | ||||||
| @@ -131,9 +180,17 @@ async def to_code(config): | |||||||
|         cg.add(var.set_reset_pin(reset)) |         cg.add(var.set_reset_pin(reset)) | ||||||
|  |  | ||||||
|     if CONF_DIMENSIONS in config: |     if CONF_DIMENSIONS in config: | ||||||
|         cg.add( |         dimensions = config[CONF_DIMENSIONS] | ||||||
|             var.set_dimentions(config[CONF_DIMENSIONS][0], config[CONF_DIMENSIONS][1]) |         if isinstance(dimensions, dict): | ||||||
|         ) |             cg.add(var.set_dimensions(dimensions[CONF_WIDTH], dimensions[CONF_HEIGHT])) | ||||||
|  |             cg.add( | ||||||
|  |                 var.set_offsets( | ||||||
|  |                     dimensions[CONF_OFFSET_WIDTH], dimensions[CONF_OFFSET_HEIGHT] | ||||||
|  |                 ) | ||||||
|  |             ) | ||||||
|  |         else: | ||||||
|  |             (width, height) = dimensions | ||||||
|  |             cg.add(var.set_dimensions(width, height)) | ||||||
|  |  | ||||||
|     rhs = None |     rhs = None | ||||||
|     if config[CONF_COLOR_PALETTE] == "GRAYSCALE": |     if config[CONF_COLOR_PALETTE] == "GRAYSCALE": | ||||||
| @@ -178,5 +235,5 @@ async def to_code(config): | |||||||
|         prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) |         prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) | ||||||
|         cg.add(var.set_palette(prog_arr)) |         cg.add(var.set_palette(prog_arr)) | ||||||
|  |  | ||||||
|     if CONF_INVERT_DISPLAY in config: |     if CONF_INVERT_COLORS in config: | ||||||
|         cg.add(var.invert_display(config[CONF_INVERT_DISPLAY])) |         cg.add(var.invert_colors(config[CONF_INVERT_COLORS])) | ||||||
|   | |||||||
| @@ -8,11 +8,31 @@ namespace esphome { | |||||||
| namespace ili9xxx { | namespace ili9xxx { | ||||||
|  |  | ||||||
| static const char *const TAG = "ili9xxx"; | static const char *const TAG = "ili9xxx"; | ||||||
|  | static const uint16_t SPI_SETUP_US = 100;         // estimated fixed overhead in microseconds for an SPI write | ||||||
|  | static const uint16_t SPI_MAX_BLOCK_SIZE = 4092;  // Max size of continuous SPI transfer | ||||||
|  |  | ||||||
|  | // store a 16 bit value in a buffer, big endian. | ||||||
|  | static inline void put16_be(uint8_t *buf, uint16_t value) { | ||||||
|  |   buf[0] = value >> 8; | ||||||
|  |   buf[1] = value; | ||||||
|  | } | ||||||
|  |  | ||||||
| void ILI9XXXDisplay::setup() { | void ILI9XXXDisplay::setup() { | ||||||
|  |   ESP_LOGD(TAG, "Setting up ILI9xxx"); | ||||||
|  |  | ||||||
|   this->setup_pins_(); |   this->setup_pins_(); | ||||||
|   this->initialize(); |   this->init_lcd_(); | ||||||
|   this->command(this->pre_invertdisplay_ ? ILI9XXX_INVON : ILI9XXX_INVOFF); |  | ||||||
|  |   this->command(this->pre_invertcolors_ ? ILI9XXX_INVON : ILI9XXX_INVOFF); | ||||||
|  |   // custom x/y transform and color order | ||||||
|  |   uint8_t mad = this->color_order_ == display::COLOR_ORDER_BGR ? MADCTL_BGR : MADCTL_RGB; | ||||||
|  |   if (this->swap_xy_) | ||||||
|  |     mad |= MADCTL_MV; | ||||||
|  |   if (this->mirror_x_) | ||||||
|  |     mad |= MADCTL_MX; | ||||||
|  |   if (this->mirror_y_) | ||||||
|  |     mad |= MADCTL_MY; | ||||||
|  |   this->send_command(ILI9XXX_MADCTL, &mad, 1); | ||||||
|  |  | ||||||
|   this->x_low_ = this->width_; |   this->x_low_ = this->width_; | ||||||
|   this->y_low_ = this->height_; |   this->y_low_ = this->height_; | ||||||
| @@ -47,6 +67,8 @@ void ILI9XXXDisplay::setup_pins_() { | |||||||
|  |  | ||||||
| void ILI9XXXDisplay::dump_config() { | void ILI9XXXDisplay::dump_config() { | ||||||
|   LOG_DISPLAY("", "ili9xxx", this); |   LOG_DISPLAY("", "ili9xxx", this); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Width Offset: %u", this->offset_x_); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Height Offset: %u", this->offset_y_); | ||||||
|   switch (this->buffer_color_mode_) { |   switch (this->buffer_color_mode_) { | ||||||
|     case BITS_8_INDEXED: |     case BITS_8_INDEXED: | ||||||
|       ESP_LOGCONFIG(TAG, "  Color mode: 8bit Indexed"); |       ESP_LOGCONFIG(TAG, "  Color mode: 8bit Indexed"); | ||||||
| @@ -64,8 +86,12 @@ void ILI9XXXDisplay::dump_config() { | |||||||
|   ESP_LOGCONFIG(TAG, "  Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000)); |   ESP_LOGCONFIG(TAG, "  Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000)); | ||||||
|  |  | ||||||
|   LOG_PIN("  Reset Pin: ", this->reset_pin_); |   LOG_PIN("  Reset Pin: ", this->reset_pin_); | ||||||
|  |   LOG_PIN("  CS Pin: ", this->cs_); | ||||||
|   LOG_PIN("  DC Pin: ", this->dc_pin_); |   LOG_PIN("  DC Pin: ", this->dc_pin_); | ||||||
|   LOG_PIN("  Busy Pin: ", this->busy_pin_); |   LOG_PIN("  Busy Pin: ", this->busy_pin_); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Swap_xy: %s", YESNO(this->swap_xy_)); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Mirror_x: %s", YESNO(this->mirror_x_)); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Mirror_y: %s", YESNO(this->mirror_y_)); | ||||||
|  |  | ||||||
|   if (this->is_failed()) { |   if (this->is_failed()) { | ||||||
|     ESP_LOGCONFIG(TAG, "  => Failed to init Memory: YES!"); |     ESP_LOGCONFIG(TAG, "  => Failed to init Memory: YES!"); | ||||||
| @@ -141,12 +167,14 @@ void HOT ILI9XXXDisplay::draw_absolute_pixel_internal(int x, int y, Color color) | |||||||
|   } |   } | ||||||
|   if (updated) { |   if (updated) { | ||||||
|     // low and high watermark may speed up drawing from buffer |     // low and high watermark may speed up drawing from buffer | ||||||
|     this->x_low_ = (x < this->x_low_) ? x : this->x_low_; |     if (x < this->x_low_) | ||||||
|     this->y_low_ = (y < this->y_low_) ? y : this->y_low_; |       this->x_low_ = x; | ||||||
|     this->x_high_ = (x > this->x_high_) ? x : this->x_high_; |     if (y < this->y_low_) | ||||||
|     this->y_high_ = (y > this->y_high_) ? y : this->y_high_; |       this->y_low_ = y; | ||||||
|     // ESP_LOGVV(TAG, "=>>> pixel (x:%d, y:%d) (xl:%d, xh:%d, yl:%d, yh:%d", x, y, this->x_low_, this->x_high_, |     if (x > this->x_high_) | ||||||
|     //           this->y_low_, this->y_high_); |       this->x_high_ = x; | ||||||
|  |     if (y > this->y_high_) | ||||||
|  |       this->y_high_ = y; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -165,59 +193,82 @@ void ILI9XXXDisplay::update() { | |||||||
| } | } | ||||||
|  |  | ||||||
| void ILI9XXXDisplay::display_() { | void ILI9XXXDisplay::display_() { | ||||||
|   // we will only update the changed window to the display |   uint8_t transfer_buffer[ILI9XXX_TRANSFER_BUFFER_SIZE]; | ||||||
|   uint16_t w = this->x_high_ - this->x_low_ + 1;  // NOLINT |  | ||||||
|   uint16_t h = this->y_high_ - this->y_low_ + 1;  // NOLINT |  | ||||||
|   uint32_t start_pos = ((this->y_low_ * this->width_) + x_low_); |  | ||||||
|  |  | ||||||
|   // check if something was displayed |   // check if something was displayed | ||||||
|   if ((this->x_high_ < this->x_low_) || (this->y_high_ < this->y_low_)) { |   if ((this->x_high_ < this->x_low_) || (this->y_high_ < this->y_low_)) { | ||||||
|     ESP_LOGV(TAG, "Nothing to display"); |     ESP_LOGV(TAG, "Nothing to display"); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   set_addr_window_(this->x_low_, this->y_low_, w, h); |   // we will only update the changed rows to the display | ||||||
|  |   size_t const w = this->x_high_ - this->x_low_ + 1; | ||||||
|  |   size_t const h = this->y_high_ - this->y_low_ + 1; | ||||||
|  |  | ||||||
|  |   size_t mhz = this->data_rate_ / 1000000; | ||||||
|  |   // estimate time for a single write | ||||||
|  |   size_t sw_time = this->width_ * h * 16 / mhz + this->width_ * h * 2 / SPI_MAX_BLOCK_SIZE * SPI_SETUP_US * 2; | ||||||
|  |   // estimate time for multiple writes | ||||||
|  |   size_t mw_time = (w * h * 16) / mhz + w * h * 2 / ILI9XXX_TRANSFER_BUFFER_SIZE * SPI_SETUP_US; | ||||||
|   ESP_LOGV(TAG, |   ESP_LOGV(TAG, | ||||||
|            "Start display(xlow:%d, ylow:%d, xhigh:%d, yhigh:%d, width:%d, " |            "Start display(xlow:%d, ylow:%d, xhigh:%d, yhigh:%d, width:%d, " | ||||||
|            "heigth:%d, start_pos:%" PRId32 ")", |            "height:%d, mode=%d, 18bit=%d, sw_time=%dus, mw_time=%dus)", | ||||||
|            this->x_low_, this->y_low_, this->x_high_, this->y_high_, w, h, start_pos); |            this->x_low_, this->y_low_, this->x_high_, this->y_high_, w, h, this->buffer_color_mode_, | ||||||
|  |            this->is_18bitdisplay_, sw_time, mw_time); | ||||||
|   this->start_data_(); |   auto now = millis(); | ||||||
|   for (uint16_t row = 0; row < h; row++) { |   this->enable(); | ||||||
|     uint32_t pos = start_pos + (row * width_); |   if (this->buffer_color_mode_ == BITS_16 && !this->is_18bitdisplay_ && sw_time < mw_time) { | ||||||
|     uint32_t rem = w; |     // 16 bit mode maps directly to display format | ||||||
|  |     ESP_LOGV(TAG, "Doing single write of %d bytes", this->width_ * h * 2); | ||||||
|     while (rem > 0) { |     set_addr_window_(0, this->y_low_, this->width_ - 1, this->y_high_); | ||||||
|       uint32_t sz = std::min(rem, ILI9XXX_TRANSFER_BUFFER_SIZE); |     this->write_array(this->buffer_ + this->y_low_ * this->width_ * 2, h * this->width_ * 2); | ||||||
|       // ESP_LOGVV(TAG, "Send to display(pos:%d, rem:%d, zs:%d)", pos, rem, sz); |   } else { | ||||||
|       buffer_to_transfer_(pos, sz); |     ESP_LOGV(TAG, "Doing multiple write"); | ||||||
|       if (this->is_18bitdisplay_) { |     size_t rem = h * w;  // remaining number of pixels to write | ||||||
|         for (uint32_t i = 0; i < sz; ++i) { |     set_addr_window_(this->x_low_, this->y_low_, this->x_high_, this->y_high_); | ||||||
|           uint16_t color_val = transfer_buffer_[i]; |     size_t idx = 0;    // index into transfer_buffer | ||||||
|  |     size_t pixel = 0;  // pixel number offset | ||||||
|           uint8_t red = color_val & 0x1F; |     size_t pos = this->y_low_ * this->width_ + this->x_low_; | ||||||
|           uint8_t green = (color_val & 0x7E0) >> 5; |     while (rem-- != 0) { | ||||||
|           uint8_t blue = (color_val & 0xF800) >> 11; |       uint16_t color_val; | ||||||
|  |       switch (this->buffer_color_mode_) { | ||||||
|           uint8_t pass_buff[3]; |         case BITS_8: | ||||||
|  |           color_val = display::ColorUtil::color_to_565(display::ColorUtil::rgb332_to_color(this->buffer_[pos++])); | ||||||
|           pass_buff[2] = (uint8_t) ((red / 32.0) * 64) << 2; |           break; | ||||||
|           pass_buff[1] = (uint8_t) green << 2; |         case BITS_8_INDEXED: | ||||||
|           pass_buff[0] = (uint8_t) ((blue / 32.0) * 64) << 2; |           color_val = display::ColorUtil::color_to_565( | ||||||
|  |               display::ColorUtil::index8_to_color_palette888(this->buffer_[pos++], this->palette_)); | ||||||
|           this->write_array(pass_buff, sizeof(pass_buff)); |           break; | ||||||
|         } |         default:  // case BITS_16: | ||||||
|       } else { |           color_val = (buffer_[pos * 2] << 8) + buffer_[pos * 2 + 1]; | ||||||
|         this->write_array16(transfer_buffer_, sz); |           pos++; | ||||||
|  |           break; | ||||||
|  |       } | ||||||
|  |       if (this->is_18bitdisplay_) { | ||||||
|  |         transfer_buffer[idx++] = (uint8_t) ((color_val & 0xF800) >> 8);  // Blue | ||||||
|  |         transfer_buffer[idx++] = (uint8_t) ((color_val & 0x7E0) >> 3);   // Green | ||||||
|  |         transfer_buffer[idx++] = (uint8_t) (color_val << 3);             // Red | ||||||
|  |       } else { | ||||||
|  |         put16_be(transfer_buffer + idx, color_val); | ||||||
|  |         idx += 2; | ||||||
|  |       } | ||||||
|  |       if (idx == ILI9XXX_TRANSFER_BUFFER_SIZE) { | ||||||
|  |         this->write_array(transfer_buffer, idx); | ||||||
|  |         idx = 0; | ||||||
|  |         App.feed_wdt(); | ||||||
|  |       } | ||||||
|  |       // end of line? Skip to the next. | ||||||
|  |       if (++pixel == w) { | ||||||
|  |         pixel = 0; | ||||||
|  |         pos += this->width_ - w; | ||||||
|       } |       } | ||||||
|       pos += sz; |  | ||||||
|       rem -= sz; |  | ||||||
|     } |     } | ||||||
|     App.feed_wdt(); |     // flush any balance. | ||||||
|  |     if (idx != 0) { | ||||||
|  |       this->write_array(transfer_buffer, idx); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|   this->end_data_(); |   this->disable(); | ||||||
|  |   ESP_LOGV(TAG, "Data write took %dms", (unsigned) (millis() - now)); | ||||||
|   // invalidate watermarks |   // invalidate watermarks | ||||||
|   this->x_low_ = this->width_; |   this->x_low_ = this->width_; | ||||||
|   this->y_low_ = this->height_; |   this->y_low_ = this->height_; | ||||||
| @@ -225,26 +276,6 @@ void ILI9XXXDisplay::display_() { | |||||||
|   this->y_high_ = 0; |   this->y_high_ = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| uint32_t ILI9XXXDisplay::buffer_to_transfer_(uint32_t pos, uint32_t sz) { |  | ||||||
|   for (uint32_t i = 0; i < sz; ++i) { |  | ||||||
|     switch (this->buffer_color_mode_) { |  | ||||||
|       case BITS_8_INDEXED: |  | ||||||
|         transfer_buffer_[i] = display::ColorUtil::color_to_565( |  | ||||||
|             display::ColorUtil::index8_to_color_palette888(this->buffer_[pos + i], this->palette_)); |  | ||||||
|         break; |  | ||||||
|       case BITS_16: |  | ||||||
|         transfer_buffer_[i] = ((uint16_t) this->buffer_[(pos + i) * 2] << 8) | this->buffer_[((pos + i) * 2) + 1]; |  | ||||||
|         continue; |  | ||||||
|         break; |  | ||||||
|       default: |  | ||||||
|         transfer_buffer_[i] = |  | ||||||
|             display::ColorUtil::color_to_565(display::ColorUtil::rgb332_to_color(this->buffer_[pos + i])); |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return sz; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // should return the total size: return this->get_width_internal() * this->get_height_internal() * 2 // 16bit color | // should return the total size: return this->get_width_internal() * this->get_height_internal() * 2 // 16bit color | ||||||
| // values per bit is huge | // values per bit is huge | ||||||
| uint32_t ILI9XXXDisplay::get_buffer_length_() { return this->get_width_internal() * this->get_height_internal(); } | uint32_t ILI9XXXDisplay::get_buffer_length_() { return this->get_width_internal() * this->get_height_internal(); } | ||||||
| @@ -303,11 +334,11 @@ void ILI9XXXDisplay::reset_() { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void ILI9XXXDisplay::init_lcd_(const uint8_t *init_cmd) { | void ILI9XXXDisplay::init_lcd_() { | ||||||
|   uint8_t cmd, x, num_args; |   uint8_t cmd, x, num_args; | ||||||
|   const uint8_t *addr = init_cmd; |   const uint8_t *addr = this->init_sequence_; | ||||||
|   while ((cmd = progmem_read_byte(addr++)) > 0) { |   while ((cmd = *addr++) > 0) { | ||||||
|     x = progmem_read_byte(addr++); |     x = *addr++; | ||||||
|     num_args = x & 0x7F; |     num_args = x & 0x7F; | ||||||
|     send_command(cmd, addr, num_args); |     send_command(cmd, addr, num_args); | ||||||
|     addr += num_args; |     addr += num_args; | ||||||
| @@ -316,27 +347,29 @@ void ILI9XXXDisplay::init_lcd_(const uint8_t *init_cmd) { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void ILI9XXXDisplay::set_addr_window_(uint16_t x1, uint16_t y1, uint16_t w, uint16_t h) { | // Tell the display controller where we want to draw pixels. | ||||||
|   uint16_t x2 = (x1 + w - 1), y2 = (y1 + h - 1); | // when called, the SPI should have already been enabled, only the D/C pin will be toggled here. | ||||||
|   this->command(ILI9XXX_CASET);  // Column address set | void ILI9XXXDisplay::set_addr_window_(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { | ||||||
|   this->start_data_(); |   uint8_t buf[4]; | ||||||
|   this->write_byte(x1 >> 8); |   this->dc_pin_->digital_write(false); | ||||||
|   this->write_byte(x1); |   this->write_byte(ILI9XXX_CASET);  // Column address set | ||||||
|   this->write_byte(x2 >> 8); |   put16_be(buf, x1 + this->offset_x_); | ||||||
|   this->write_byte(x2); |   put16_be(buf + 2, x2 + this->offset_x_); | ||||||
|   this->end_data_(); |   this->dc_pin_->digital_write(true); | ||||||
|   this->command(ILI9XXX_PASET);  // Row address set |   this->write_array(buf, sizeof buf); | ||||||
|   this->start_data_(); |   this->dc_pin_->digital_write(false); | ||||||
|   this->write_byte(y1 >> 8); |   this->write_byte(ILI9XXX_PASET);  // Row address set | ||||||
|   this->write_byte(y1); |   put16_be(buf, y1 + this->offset_y_); | ||||||
|   this->write_byte(y2 >> 8); |   put16_be(buf + 2, y2 + this->offset_y_); | ||||||
|   this->write_byte(y2); |   this->dc_pin_->digital_write(true); | ||||||
|   this->end_data_(); |   this->write_array(buf, sizeof buf); | ||||||
|   this->command(ILI9XXX_RAMWR);  // Write to RAM |   this->dc_pin_->digital_write(false); | ||||||
|  |   this->write_byte(ILI9XXX_RAMWR);  // Write to RAM | ||||||
|  |   this->dc_pin_->digital_write(true); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ILI9XXXDisplay::invert_display(bool invert) { | void ILI9XXXDisplay::invert_colors(bool invert) { | ||||||
|   this->pre_invertdisplay_ = invert; |   this->pre_invertcolors_ = invert; | ||||||
|   if (is_ready()) { |   if (is_ready()) { | ||||||
|     this->command(invert ? ILI9XXX_INVON : ILI9XXX_INVOFF); |     this->command(invert ? ILI9XXX_INVON : ILI9XXX_INVOFF); | ||||||
|   } |   } | ||||||
| @@ -345,132 +378,5 @@ void ILI9XXXDisplay::invert_display(bool invert) { | |||||||
| int ILI9XXXDisplay::get_width_internal() { return this->width_; } | int ILI9XXXDisplay::get_width_internal() { return this->width_; } | ||||||
| int ILI9XXXDisplay::get_height_internal() { return this->height_; } | int ILI9XXXDisplay::get_height_internal() { return this->height_; } | ||||||
|  |  | ||||||
| //   M5Stack display |  | ||||||
| void ILI9XXXM5Stack::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_M5STACK); |  | ||||||
|   if (this->width_ == 0) |  | ||||||
|     this->width_ = 320; |  | ||||||
|   if (this->height_ == 0) |  | ||||||
|     this->height_ = 240; |  | ||||||
|   this->pre_invertdisplay_ = true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //   M5CORE display // Based on the configuration settings of M5stact's M5GFX code. |  | ||||||
| void ILI9XXXM5CORE::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_M5CORE); |  | ||||||
|   if (this->width_ == 0) |  | ||||||
|     this->width_ = 320; |  | ||||||
|   if (this->height_ == 0) |  | ||||||
|     this->height_ = 240; |  | ||||||
|   this->pre_invertdisplay_ = true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //   24_TFT display |  | ||||||
| void ILI9XXXILI9341::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_ILI9341); |  | ||||||
|   if (this->width_ == 0) |  | ||||||
|     this->width_ = 240; |  | ||||||
|   if (this->height_ == 0) |  | ||||||
|     this->height_ = 320; |  | ||||||
| } |  | ||||||
| //   24_TFT rotated display |  | ||||||
| void ILI9XXXILI9342::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_ILI9341); |  | ||||||
|   if (this->width_ == 0) { |  | ||||||
|     this->width_ = 320; |  | ||||||
|   } |  | ||||||
|   if (this->height_ == 0) { |  | ||||||
|     this->height_ = 240; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //   35_TFT display |  | ||||||
| void ILI9XXXILI9481::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_ILI9481); |  | ||||||
|   if (this->width_ == 0) { |  | ||||||
|     this->width_ = 480; |  | ||||||
|   } |  | ||||||
|   if (this->height_ == 0) { |  | ||||||
|     this->height_ = 320; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void ILI9XXXILI948118::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_ILI9481_18); |  | ||||||
|   if (this->width_ == 0) { |  | ||||||
|     this->width_ = 320; |  | ||||||
|   } |  | ||||||
|   if (this->height_ == 0) { |  | ||||||
|     this->height_ = 480; |  | ||||||
|   } |  | ||||||
|   this->is_18bitdisplay_ = true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //   35_TFT display |  | ||||||
| void ILI9XXXILI9486::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_ILI9486); |  | ||||||
|   if (this->width_ == 0) { |  | ||||||
|     this->width_ = 480; |  | ||||||
|   } |  | ||||||
|   if (this->height_ == 0) { |  | ||||||
|     this->height_ = 320; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| //    40_TFT display |  | ||||||
| void ILI9XXXILI9488::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_ILI9488); |  | ||||||
|   if (this->width_ == 0) { |  | ||||||
|     this->width_ = 480; |  | ||||||
|   } |  | ||||||
|   if (this->height_ == 0) { |  | ||||||
|     this->height_ = 320; |  | ||||||
|   } |  | ||||||
|   this->is_18bitdisplay_ = true; |  | ||||||
| } |  | ||||||
| //    40_TFT display |  | ||||||
| void ILI9XXXILI9488A::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_ILI9488_A); |  | ||||||
|   if (this->width_ == 0) { |  | ||||||
|     this->width_ = 480; |  | ||||||
|   } |  | ||||||
|   if (this->height_ == 0) { |  | ||||||
|     this->height_ = 320; |  | ||||||
|   } |  | ||||||
|   this->is_18bitdisplay_ = true; |  | ||||||
| } |  | ||||||
| //    40_TFT display |  | ||||||
| void ILI9XXXST7796::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_ST7796); |  | ||||||
|   if (this->width_ == 0) { |  | ||||||
|     this->width_ = 320; |  | ||||||
|   } |  | ||||||
|   if (this->height_ == 0) { |  | ||||||
|     this->height_ = 480; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //   24_TFT rotated display |  | ||||||
| void ILI9XXXS3Box::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_S3BOX); |  | ||||||
|   if (this->width_ == 0) { |  | ||||||
|     this->width_ = 320; |  | ||||||
|   } |  | ||||||
|   if (this->height_ == 0) { |  | ||||||
|     this->height_ = 240; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //   24_TFT rotated display |  | ||||||
| void ILI9XXXS3BoxLite::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_S3BOXLITE); |  | ||||||
|   if (this->width_ == 0) { |  | ||||||
|     this->width_ = 320; |  | ||||||
|   } |  | ||||||
|   if (this->height_ == 0) { |  | ||||||
|     this->height_ = 240; |  | ||||||
|   } |  | ||||||
|   this->pre_invertdisplay_ = true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| }  // namespace ili9xxx | }  // namespace ili9xxx | ||||||
| }  // namespace esphome | }  // namespace esphome | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace ili9xxx { | namespace ili9xxx { | ||||||
|  |  | ||||||
| const uint32_t ILI9XXX_TRANSFER_BUFFER_SIZE = 64; | const size_t ILI9XXX_TRANSFER_BUFFER_SIZE = 126;  // ensure this is divisible by 6 | ||||||
|  |  | ||||||
| enum ILI9XXXColorMode { | enum ILI9XXXColorMode { | ||||||
|   BITS_8 = 0x08, |   BITS_8 = 0x08, | ||||||
| @@ -23,20 +23,47 @@ class ILI9XXXDisplay : public display::DisplayBuffer, | |||||||
|                        public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, |                        public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, | ||||||
|                                              spi::CLOCK_PHASE_LEADING, ILI9XXXDisplay_DATA_RATE> { |                                              spi::CLOCK_PHASE_LEADING, ILI9XXXDisplay_DATA_RATE> { | ||||||
|  public: |  public: | ||||||
|  |   ILI9XXXDisplay() = default; | ||||||
|  |   ILI9XXXDisplay(uint8_t const *init_sequence, int16_t width, int16_t height, bool invert_colors) | ||||||
|  |       : init_sequence_{init_sequence}, width_{width}, height_{height}, pre_invertcolors_{invert_colors} { | ||||||
|  |     uint8_t cmd, num_args, bits; | ||||||
|  |     const uint8_t *addr = init_sequence; | ||||||
|  |     while ((cmd = *addr++) != 0) { | ||||||
|  |       num_args = *addr++ & 0x7F; | ||||||
|  |       if (cmd == ILI9XXX_MADCTL) { | ||||||
|  |         bits = *addr; | ||||||
|  |         this->swap_xy_ = (bits & MADCTL_MV) != 0; | ||||||
|  |         this->mirror_x_ = (bits & MADCTL_MX) != 0; | ||||||
|  |         this->mirror_y_ = (bits & MADCTL_MY) != 0; | ||||||
|  |         this->color_order_ = (bits & MADCTL_BGR) ? display::COLOR_ORDER_BGR : display::COLOR_ORDER_RGB; | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|  |       addr += num_args; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   void set_dc_pin(GPIOPin *dc_pin) { dc_pin_ = dc_pin; } |   void set_dc_pin(GPIOPin *dc_pin) { dc_pin_ = dc_pin; } | ||||||
|   float get_setup_priority() const override; |   float get_setup_priority() const override; | ||||||
|   void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; } |   void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; } | ||||||
|   void set_palette(const uint8_t *palette) { this->palette_ = palette; } |   void set_palette(const uint8_t *palette) { this->palette_ = palette; } | ||||||
|   void set_buffer_color_mode(ILI9XXXColorMode color_mode) { this->buffer_color_mode_ = color_mode; } |   void set_buffer_color_mode(ILI9XXXColorMode color_mode) { this->buffer_color_mode_ = color_mode; } | ||||||
|   void set_dimentions(int16_t width, int16_t height) { |   void set_dimensions(int16_t width, int16_t height) { | ||||||
|     this->height_ = height; |     this->height_ = height; | ||||||
|     this->width_ = width; |     this->width_ = width; | ||||||
|   } |   } | ||||||
|   void invert_display(bool invert); |   void set_offsets(int16_t offset_x, int16_t offset_y) { | ||||||
|  |     this->offset_x_ = offset_x; | ||||||
|  |     this->offset_y_ = offset_y; | ||||||
|  |   } | ||||||
|  |   void invert_colors(bool invert); | ||||||
|   void command(uint8_t value); |   void command(uint8_t value); | ||||||
|   void data(uint8_t value); |   void data(uint8_t value); | ||||||
|   void send_command(uint8_t command_byte, const uint8_t *data_bytes, uint8_t num_data_bytes); |   void send_command(uint8_t command_byte, const uint8_t *data_bytes, uint8_t num_data_bytes); | ||||||
|   uint8_t read_command(uint8_t command_byte, uint8_t index); |   uint8_t read_command(uint8_t command_byte, uint8_t index); | ||||||
|  |   void set_color_order(display::ColorOrder color_order) { this->color_order_ = color_order; } | ||||||
|  |   void set_swap_xy(bool swap_xy) { this->swap_xy_ = swap_xy; } | ||||||
|  |   void set_mirror_x(bool mirror_x) { this->mirror_x_ = mirror_x; } | ||||||
|  |   void set_mirror_y(bool mirror_y) { this->mirror_y_ = mirror_y; } | ||||||
|  |  | ||||||
|   void update() override; |   void update() override; | ||||||
|  |  | ||||||
| @@ -50,16 +77,17 @@ class ILI9XXXDisplay : public display::DisplayBuffer, | |||||||
|  protected: |  protected: | ||||||
|   void draw_absolute_pixel_internal(int x, int y, Color color) override; |   void draw_absolute_pixel_internal(int x, int y, Color color) override; | ||||||
|   void setup_pins_(); |   void setup_pins_(); | ||||||
|   virtual void initialize() = 0; |  | ||||||
|  |  | ||||||
|   void display_(); |   void display_(); | ||||||
|   void init_lcd_(const uint8_t *init_cmd); |   void init_lcd_(); | ||||||
|   void set_addr_window_(uint16_t x, uint16_t y, uint16_t w, uint16_t h); |   void set_addr_window_(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2); | ||||||
|  |  | ||||||
|   void reset_(); |   void reset_(); | ||||||
|  |  | ||||||
|  |   uint8_t const *init_sequence_{}; | ||||||
|   int16_t width_{0};   ///< Display width as modified by current rotation |   int16_t width_{0};   ///< Display width as modified by current rotation | ||||||
|   int16_t height_{0};  ///< Display height as modified by current rotation |   int16_t height_{0};  ///< Display height as modified by current rotation | ||||||
|  |   int16_t offset_x_{0}; | ||||||
|  |   int16_t offset_y_{0}; | ||||||
|   uint16_t x_low_{0}; |   uint16_t x_low_{0}; | ||||||
|   uint16_t y_low_{0}; |   uint16_t y_low_{0}; | ||||||
|   uint16_t x_high_{0}; |   uint16_t x_high_{0}; | ||||||
| @@ -77,10 +105,6 @@ class ILI9XXXDisplay : public display::DisplayBuffer, | |||||||
|   void start_data_(); |   void start_data_(); | ||||||
|   void end_data_(); |   void end_data_(); | ||||||
|  |  | ||||||
|   uint16_t transfer_buffer_[ILI9XXX_TRANSFER_BUFFER_SIZE]; |  | ||||||
|  |  | ||||||
|   uint32_t buffer_to_transfer_(uint32_t pos, uint32_t sz); |  | ||||||
|  |  | ||||||
|   GPIOPin *reset_pin_{nullptr}; |   GPIOPin *reset_pin_{nullptr}; | ||||||
|   GPIOPin *dc_pin_{nullptr}; |   GPIOPin *dc_pin_{nullptr}; | ||||||
|   GPIOPin *busy_pin_{nullptr}; |   GPIOPin *busy_pin_{nullptr}; | ||||||
| @@ -88,77 +112,87 @@ class ILI9XXXDisplay : public display::DisplayBuffer, | |||||||
|   bool prossing_update_ = false; |   bool prossing_update_ = false; | ||||||
|   bool need_update_ = false; |   bool need_update_ = false; | ||||||
|   bool is_18bitdisplay_ = false; |   bool is_18bitdisplay_ = false; | ||||||
|   bool pre_invertdisplay_ = false; |   bool pre_invertcolors_ = false; | ||||||
|  |   display::ColorOrder color_order_{}; | ||||||
|  |   bool swap_xy_{}; | ||||||
|  |   bool mirror_x_{}; | ||||||
|  |   bool mirror_y_{}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| //-----------   M5Stack display -------------- | //-----------   M5Stack display -------------- | ||||||
| class ILI9XXXM5Stack : public ILI9XXXDisplay { | class ILI9XXXM5Stack : public ILI9XXXDisplay { | ||||||
|  protected: |  public: | ||||||
|   void initialize() override; |   ILI9XXXM5Stack() : ILI9XXXDisplay(INITCMD_M5STACK, 320, 240, true) {} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| //-----------   M5Stack display -------------- | //-----------   M5Stack display -------------- | ||||||
| class ILI9XXXM5CORE : public ILI9XXXDisplay { | class ILI9XXXM5CORE : public ILI9XXXDisplay { | ||||||
|  protected: |  public: | ||||||
|   void initialize() override; |   ILI9XXXM5CORE() : ILI9XXXDisplay(INITCMD_M5CORE, 320, 240, true) {} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | //-----------   ST7789V display -------------- | ||||||
|  | class ILI9XXXST7789V : public ILI9XXXDisplay { | ||||||
|  |  public: | ||||||
|  |   ILI9XXXST7789V() : ILI9XXXDisplay(INITCMD_ST7789V, 240, 320, false) {} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| //-----------   ILI9XXX_24_TFT display -------------- | //-----------   ILI9XXX_24_TFT display -------------- | ||||||
| class ILI9XXXILI9341 : public ILI9XXXDisplay { | class ILI9XXXILI9341 : public ILI9XXXDisplay { | ||||||
|  protected: |  public: | ||||||
|   void initialize() override; |   ILI9XXXILI9341() : ILI9XXXDisplay(INITCMD_ILI9341, 240, 320, false) {} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| //-----------   ILI9XXX_24_TFT rotated display -------------- | //-----------   ILI9XXX_24_TFT rotated display -------------- | ||||||
| class ILI9XXXILI9342 : public ILI9XXXDisplay { | class ILI9XXXILI9342 : public ILI9XXXDisplay { | ||||||
|  protected: |  public: | ||||||
|   void initialize() override; |   ILI9XXXILI9342() : ILI9XXXDisplay(INITCMD_ILI9341, 320, 240, false) {} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| //-----------   ILI9XXX_??_TFT rotated display -------------- | //-----------   ILI9XXX_??_TFT rotated display -------------- | ||||||
| class ILI9XXXILI9481 : public ILI9XXXDisplay { | class ILI9XXXILI9481 : public ILI9XXXDisplay { | ||||||
|  protected: |  public: | ||||||
|   void initialize() override; |   ILI9XXXILI9481() : ILI9XXXDisplay(INITCMD_ILI9481, 480, 320, false) {} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| //-----------   ILI9481 in 18 bit mode -------------- | //-----------   ILI9481 in 18 bit mode -------------- | ||||||
| class ILI9XXXILI948118 : public ILI9XXXDisplay { | class ILI9XXXILI948118 : public ILI9XXXDisplay { | ||||||
|  protected: |  public: | ||||||
|   void initialize() override; |   ILI9XXXILI948118() : ILI9XXXDisplay(INITCMD_ILI9481_18, 320, 480, true) {} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| //-----------   ILI9XXX_35_TFT rotated display -------------- | //-----------   ILI9XXX_35_TFT rotated display -------------- | ||||||
| class ILI9XXXILI9486 : public ILI9XXXDisplay { | class ILI9XXXILI9486 : public ILI9XXXDisplay { | ||||||
|  protected: |  public: | ||||||
|   void initialize() override; |   ILI9XXXILI9486() : ILI9XXXDisplay(INITCMD_ILI9486, 480, 320, false) {} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| //-----------   ILI9XXX_35_TFT rotated display -------------- | //-----------   ILI9XXX_35_TFT rotated display -------------- | ||||||
| class ILI9XXXILI9488 : public ILI9XXXDisplay { | class ILI9XXXILI9488 : public ILI9XXXDisplay { | ||||||
|  protected: |  public: | ||||||
|   void initialize() override; |   ILI9XXXILI9488() : ILI9XXXDisplay(INITCMD_ILI9488, 480, 320, true) {} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| //-----------   ILI9XXX_35_TFT origin colors rotated display -------------- | //-----------   ILI9XXX_35_TFT origin colors rotated display -------------- | ||||||
| class ILI9XXXILI9488A : public ILI9XXXDisplay { | class ILI9XXXILI9488A : public ILI9XXXDisplay { | ||||||
|  protected: |  public: | ||||||
|   void initialize() override; |   ILI9XXXILI9488A() : ILI9XXXDisplay(INITCMD_ILI9488_A, 480, 320, true) {} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| //-----------   ILI9XXX_35_TFT rotated display -------------- | //-----------   ILI9XXX_35_TFT rotated display -------------- | ||||||
| class ILI9XXXST7796 : public ILI9XXXDisplay { | class ILI9XXXST7796 : public ILI9XXXDisplay { | ||||||
|  protected: |  public: | ||||||
|   void initialize() override; |   ILI9XXXST7796() : ILI9XXXDisplay(INITCMD_ST7796, 320, 480, false) {} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class ILI9XXXS3Box : public ILI9XXXDisplay { | class ILI9XXXS3Box : public ILI9XXXDisplay { | ||||||
|  protected: |  public: | ||||||
|   void initialize() override; |   ILI9XXXS3Box() : ILI9XXXDisplay(INITCMD_S3BOX, 320, 240, false) {} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class ILI9XXXS3BoxLite : public ILI9XXXDisplay { | class ILI9XXXS3BoxLite : public ILI9XXXDisplay { | ||||||
|  protected: |  public: | ||||||
|   void initialize() override; |   ILI9XXXS3BoxLite() : ILI9XXXDisplay(INITCMD_S3BOXLITE, 320, 240, true) {} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace ili9xxx | }  // namespace ili9xxx | ||||||
|   | |||||||
| @@ -289,6 +289,33 @@ static const uint8_t PROGMEM INITCMD_S3BOXLITE[] = { | |||||||
|   0x00                                   // End of list |   0x00                                   // End of list | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | static const uint8_t PROGMEM INITCMD_ST7789V[] = { | ||||||
|  |   ILI9XXX_SLPOUT  , 0x80,                // Exit Sleep | ||||||
|  |   ILI9XXX_DISPON  , 0x80,                // Display on | ||||||
|  |   ILI9XXX_MADCTL  , 1, 0x08,             // Memory Access Control, BGR | ||||||
|  |   ILI9XXX_DFUNCTR, 2, 0x0A, 0x82, | ||||||
|  |   ILI9XXX_PIXFMT  , 1, 0x55, | ||||||
|  |   ILI9XXX_FRMCTR2, 5, 0x0C, 0x0C, 0x00, 0x33, 0x33, | ||||||
|  |   ILI9XXX_ETMOD, 1, 0x35, 0xBB, 1, 0x28, | ||||||
|  |   ILI9XXX_PWCTR1  , 1, 0x0C,             // Power control VRH[5:0] | ||||||
|  |   ILI9XXX_PWCTR3  , 2, 0x01, 0xFF, | ||||||
|  |   ILI9XXX_PWCTR4  , 1, 0x10, | ||||||
|  |   ILI9XXX_PWCTR5  , 1, 0x20, | ||||||
|  |   ILI9XXX_IFCTR  , 1, 0x0F, | ||||||
|  |   ILI9XXX_PWSET, 2, 0xA4, 0xA1, | ||||||
|  |   ILI9XXX_GMCTRP1 , 14, | ||||||
|  |   0xd0, 0x00, 0x02, 0x07, 0x0a, | ||||||
|  |   0x28, 0x32, 0x44, 0x42, 0x06, 0x0e, | ||||||
|  |   0x12, 0x14, 0x17, | ||||||
|  |   ILI9XXX_GMCTRN1 , 14, | ||||||
|  |   0xd0, 0x00, 0x02, 0x07, 0x0a, | ||||||
|  |   0x28, 0x31, 0x54, 0x47, | ||||||
|  |   0x0e, 0x1c, 0x17, 0x1b, | ||||||
|  |   0x1e, | ||||||
|  |   ILI9XXX_DISPON  , 0x80,                // Display on | ||||||
|  |   0x00                                   // End of list | ||||||
|  | }; | ||||||
|  |  | ||||||
| // clang-format on | // clang-format on | ||||||
| }  // namespace ili9xxx | }  // namespace ili9xxx | ||||||
| }  // namespace esphome | }  // namespace esphome | ||||||
|   | |||||||
| @@ -1554,6 +1554,8 @@ sensor: | |||||||
|       memory_address: 0x7d |       memory_address: 0x7d | ||||||
|       name: Adres sensor |       name: Adres sensor | ||||||
|  |  | ||||||
|  | psram: | ||||||
|  |  | ||||||
| esp32_touch: | esp32_touch: | ||||||
|   setup_mode: false |   setup_mode: false | ||||||
|   iir_filter: 10ms |   iir_filter: 10ms | ||||||
| @@ -2992,6 +2994,12 @@ display: | |||||||
|     lambda: |- |     lambda: |- | ||||||
|       it.rectangle(0, 0, it.get_width(), it.get_height()); |       it.rectangle(0, 0, it.get_width(), it.get_height()); | ||||||
|   - platform: ili9xxx |   - platform: ili9xxx | ||||||
|  |     invert_colors: true | ||||||
|  |     dimensions: 320x240 | ||||||
|  |     transform: | ||||||
|  |       swap_xy: true | ||||||
|  |       mirror_x: true | ||||||
|  |       mirror_y: false | ||||||
|     model: TFT 2.4 |     model: TFT 2.4 | ||||||
|     cs_pin: GPIO5 |     cs_pin: GPIO5 | ||||||
|     dc_pin: GPIO4 |     dc_pin: GPIO4 | ||||||
| @@ -3000,6 +3008,11 @@ display: | |||||||
|     lambda: |- |     lambda: |- | ||||||
|       it.rectangle(0, 0, it.get_width(), it.get_height()); |       it.rectangle(0, 0, it.get_width(), it.get_height()); | ||||||
|   - platform: ili9xxx |   - platform: ili9xxx | ||||||
|  |     dimensions: | ||||||
|  |       width: 320 | ||||||
|  |       height: 240 | ||||||
|  |       offset_width: 20 | ||||||
|  |       offset_height: 10 | ||||||
|     model: TFT 2.4 |     model: TFT 2.4 | ||||||
|     cs_pin: GPIO5 |     cs_pin: GPIO5 | ||||||
|     dc_pin: GPIO4 |     dc_pin: GPIO4 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user