mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Renaming and extending the ili9341 to the ili9xxx component (#4275)
* - Removed cleaning the screen twice. \Should be handled by `DisplayBuffer::init_internal_();` - Made ili9341::initalize() protected and renamed \ it to ili9341::initalize(). - ili9341::initalize() should only init the display \ and set the width and heigth. * removed to much * clang format fixes * removing trailing underscors for protected virtual methods * removed the "override" on display() * clang fixes * restored old changes * Renamed the ili9341 platform to ili9xxx and added multiple drivers as well. including PR #3848 * fixed most of the clang reported issues * fixed reported issues * last fixes * Setting the right codeowners * missing changes * fixed naming Display() method. * clang again * clang fix * fixes reported by @jesserockz & @gpambrozio * a change to display.py removing an unneeded var * re-introduce **backlight** option. * update the ili9488 initialization * update the ili9488 initialization and fix typo * fixed typo * add missing constants * swap height and width back for the ili9488 * init fixes ili9488 * fixed lint issue testing the init code * oeps * init fixes ili9488 * fixed wrong define * fixed wrong define again * removed some spaces * revert to ili9341 * Remove parts that where used for the switchplate * lint fixes and removing unused function * fix error and introducing 16bit color option * fix error and introducing 16bit color option * fix clang issue * clang fix * clang issue again * is this what clang exprect * clang fix * clang fix * try again * let try again * and again * and the last clang fix * remove the need of wifi * update dimentions * update ili8488 init code. * update dimentions * allow to change height and width * dump color mode config * fix * fix * modify logging * referd back unrelated change * code formatting commit and moving functions around * add missing ; * update code * update code * use the correct write_array for sending uint16_t * fix panic loop * fix panic loop * - update the test file - fixed sending display data * clang fixes * clang fixes * clang fixes again * remove .gitignore items * remove .gitignore items * make sure Update() can can not be called while called * clang correction * adding a test yaml for the ili9341 * Update ili9341 example * Make test ili9xxx/tests only local * restore back old ili9341 driver code * Add a new config for the M5Core * fix clang request * reverd to restore of the old ili9341 there is no proper way to say it is depricated. * Remove the backlight/led pin from the config. You need to use a proper light platform component * Ili9488init changes (#88) Fixed ILI9488 init settings, and adjusted pixel handling code to push pixels in 18 bit format. This does not change the internal 16-bit representation. * fixed some leftover clang issues from the merge. * fixed the slang-tidy request. * remove `backlight_pin` warning. --------- Co-authored-by: JD Steffen <jdsteffen81@gmail.com>
This commit is contained in:
		| @@ -111,6 +111,7 @@ esphome/components/hte501/* @Stock-M | |||||||
| esphome/components/hydreon_rgxx/* @functionpointer | esphome/components/hydreon_rgxx/* @functionpointer | ||||||
| esphome/components/i2c/* @esphome/core | esphome/components/i2c/* @esphome/core | ||||||
| esphome/components/i2s_audio/* @jesserockz | esphome/components/i2s_audio/* @jesserockz | ||||||
|  | esphome/components/ili9xxx/* @nielsnl68 | ||||||
| esphome/components/improv_base/* @esphome/core | esphome/components/improv_base/* @esphome/core | ||||||
| esphome/components/improv_serial/* @esphome/core | esphome/components/improv_serial/* @esphome/core | ||||||
| esphome/components/ina260/* @MrEditor97 | esphome/components/ina260/* @MrEditor97 | ||||||
|   | |||||||
| @@ -1,153 +1,5 @@ | |||||||
| import esphome.codegen as cg |  | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome import core, pins |  | ||||||
| from esphome.components import display, spi | CONFIG_SCHEMA = cv.invalid( | ||||||
| from esphome.const import ( |     "The ili9341 platform component has been renamed to ili9xxx." | ||||||
|     CONF_COLOR_PALETTE, |  | ||||||
|     CONF_DC_PIN, |  | ||||||
|     CONF_ID, |  | ||||||
|     CONF_LAMBDA, |  | ||||||
|     CONF_MODEL, |  | ||||||
|     CONF_PAGES, |  | ||||||
|     CONF_RAW_DATA_ID, |  | ||||||
|     CONF_RESET_PIN, |  | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, HexInt |  | ||||||
|  |  | ||||||
| DEPENDENCIES = ["spi"] |  | ||||||
|  |  | ||||||
| CONF_COLOR_PALETTE_IMAGES = "color_palette_images" |  | ||||||
| CONF_LED_PIN = "led_pin" |  | ||||||
|  |  | ||||||
| ili9341_ns = cg.esphome_ns.namespace("ili9341") |  | ||||||
| ili9341 = ili9341_ns.class_( |  | ||||||
|     "ILI9341Display", cg.PollingComponent, spi.SPIDevice, display.DisplayBuffer |  | ||||||
| ) |  | ||||||
| ILI9341M5Stack = ili9341_ns.class_("ILI9341M5Stack", ili9341) |  | ||||||
| ILI9341TFT24 = ili9341_ns.class_("ILI9341TFT24", ili9341) |  | ||||||
| ILI9341TFT24R = ili9341_ns.class_("ILI9341TFT24R", ili9341) |  | ||||||
|  |  | ||||||
| ILI9341Model = ili9341_ns.enum("ILI9341Model") |  | ||||||
| ILI9341ColorMode = ili9341_ns.enum("ILI9341ColorMode") |  | ||||||
|  |  | ||||||
| MODELS = { |  | ||||||
|     "M5STACK": ILI9341Model.M5STACK, |  | ||||||
|     "TFT_2.4": ILI9341Model.TFT_24, |  | ||||||
|     "TFT_2.4R": ILI9341Model.TFT_24R, |  | ||||||
| } |  | ||||||
|  |  | ||||||
| ILI9341_MODEL = cv.enum(MODELS, upper=True, space="_") |  | ||||||
|  |  | ||||||
| COLOR_PALETTE = cv.one_of("NONE", "GRAYSCALE", "IMAGE_ADAPTIVE") |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def _validate(config): |  | ||||||
|     if config.get(CONF_COLOR_PALETTE) == "IMAGE_ADAPTIVE" and not config.get( |  | ||||||
|         CONF_COLOR_PALETTE_IMAGES |  | ||||||
|     ): |  | ||||||
|         raise cv.Invalid( |  | ||||||
|             "Color palette in IMAGE_ADAPTIVE mode requires at least one 'color_palette_images' entry to generate palette" |  | ||||||
|         ) |  | ||||||
|     if ( |  | ||||||
|         config.get(CONF_COLOR_PALETTE_IMAGES) |  | ||||||
|         and config.get(CONF_COLOR_PALETTE) != "IMAGE_ADAPTIVE" |  | ||||||
|     ): |  | ||||||
|         raise cv.Invalid( |  | ||||||
|             "Providing color palette images requires palette mode to be 'IMAGE_ADAPTIVE'" |  | ||||||
|         ) |  | ||||||
|     return config |  | ||||||
|  |  | ||||||
|  |  | ||||||
| CONFIG_SCHEMA = cv.All( |  | ||||||
|     display.FULL_DISPLAY_SCHEMA.extend( |  | ||||||
|         { |  | ||||||
|             cv.GenerateID(): cv.declare_id(ili9341), |  | ||||||
|             cv.Required(CONF_MODEL): ILI9341_MODEL, |  | ||||||
|             cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, |  | ||||||
|             cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, |  | ||||||
|             cv.Optional(CONF_LED_PIN): pins.gpio_output_pin_schema, |  | ||||||
|             cv.Optional(CONF_COLOR_PALETTE, default="NONE"): COLOR_PALETTE, |  | ||||||
|             cv.Optional(CONF_COLOR_PALETTE_IMAGES, default=[]): cv.ensure_list( |  | ||||||
|                 cv.file_ |  | ||||||
|             ), |  | ||||||
|             cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), |  | ||||||
|         } |  | ||||||
|     ) |  | ||||||
|     .extend(cv.polling_component_schema("1s")) |  | ||||||
|     .extend(spi.spi_device_schema(False)), |  | ||||||
|     cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), |  | ||||||
|     _validate, |  | ||||||
| ) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| async def to_code(config): |  | ||||||
|     if config[CONF_MODEL] == "M5STACK": |  | ||||||
|         lcd_type = ILI9341M5Stack |  | ||||||
|     if config[CONF_MODEL] == "TFT_2.4": |  | ||||||
|         lcd_type = ILI9341TFT24 |  | ||||||
|     if config[CONF_MODEL] == "TFT_2.4R": |  | ||||||
|         lcd_type = ILI9341TFT24R |  | ||||||
|     rhs = lcd_type.new() |  | ||||||
|     var = cg.Pvariable(config[CONF_ID], rhs) |  | ||||||
|  |  | ||||||
|     await cg.register_component(var, config) |  | ||||||
|     await display.register_display(var, config) |  | ||||||
|     await spi.register_spi_device(var, config) |  | ||||||
|     cg.add(var.set_model(config[CONF_MODEL])) |  | ||||||
|     dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) |  | ||||||
|     cg.add(var.set_dc_pin(dc)) |  | ||||||
|  |  | ||||||
|     if CONF_LAMBDA in config: |  | ||||||
|         lambda_ = await cg.process_lambda( |  | ||||||
|             config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void |  | ||||||
|         ) |  | ||||||
|         cg.add(var.set_writer(lambda_)) |  | ||||||
|     if CONF_RESET_PIN in config: |  | ||||||
|         reset = await cg.gpio_pin_expression(config[CONF_RESET_PIN]) |  | ||||||
|         cg.add(var.set_reset_pin(reset)) |  | ||||||
|     if CONF_LED_PIN in config: |  | ||||||
|         led_pin = await cg.gpio_pin_expression(config[CONF_LED_PIN]) |  | ||||||
|         cg.add(var.set_led_pin(led_pin)) |  | ||||||
|  |  | ||||||
|     rhs = None |  | ||||||
|     if config[CONF_COLOR_PALETTE] == "GRAYSCALE": |  | ||||||
|         cg.add(var.set_buffer_color_mode(ILI9341ColorMode.BITS_8_INDEXED)) |  | ||||||
|         rhs = [] |  | ||||||
|         for x in range(256): |  | ||||||
|             rhs.extend([HexInt(x), HexInt(x), HexInt(x)]) |  | ||||||
|     elif config[CONF_COLOR_PALETTE] == "IMAGE_ADAPTIVE": |  | ||||||
|         cg.add(var.set_buffer_color_mode(ILI9341ColorMode.BITS_8_INDEXED)) |  | ||||||
|         from PIL import Image |  | ||||||
|  |  | ||||||
|         def load_image(filename): |  | ||||||
|             path = CORE.relative_config_path(filename) |  | ||||||
|             try: |  | ||||||
|                 return Image.open(path) |  | ||||||
|             except Exception as e: |  | ||||||
|                 raise core.EsphomeError(f"Could not load image file {path}: {e}") |  | ||||||
|  |  | ||||||
|         # make a wide horizontal combined image. |  | ||||||
|         images = [load_image(x) for x in config[CONF_COLOR_PALETTE_IMAGES]] |  | ||||||
|         total_width = sum(i.width for i in images) |  | ||||||
|         max_height = max(i.height for i in images) |  | ||||||
|  |  | ||||||
|         ref_image = Image.new("RGB", (total_width, max_height)) |  | ||||||
|         x = 0 |  | ||||||
|         for i in images: |  | ||||||
|             ref_image.paste(i, (x, 0)) |  | ||||||
|             x = x + i.width |  | ||||||
|  |  | ||||||
|         # reduce the colors on combined image to 256. |  | ||||||
|         converted = ref_image.convert("P", palette=Image.ADAPTIVE, colors=256) |  | ||||||
|         # if you want to verify how the images look use |  | ||||||
|         # ref_image.save("ref_in.png") |  | ||||||
|         # converted.save("ref_out.png") |  | ||||||
|         palette = converted.getpalette() |  | ||||||
|         assert len(palette) == 256 * 3 |  | ||||||
|         rhs = palette |  | ||||||
|     else: |  | ||||||
|         cg.add(var.set_buffer_color_mode(ILI9341ColorMode.BITS_8)) |  | ||||||
|  |  | ||||||
|     if rhs is not None: |  | ||||||
|         prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) |  | ||||||
|         cg.add(var.set_palette(prog_arr)) |  | ||||||
|   | |||||||
| @@ -1,83 +0,0 @@ | |||||||
| #pragma once |  | ||||||
|  |  | ||||||
| namespace esphome { |  | ||||||
| namespace ili9341 { |  | ||||||
|  |  | ||||||
| // Color definitions |  | ||||||
| // clang-format off |  | ||||||
| static const uint8_t MADCTL_MY    = 0x80;   ///< Bit 7 Bottom to top |  | ||||||
| static const uint8_t MADCTL_MX    = 0x40;   ///< Bit 6 Right to left |  | ||||||
| static const uint8_t MADCTL_MV    = 0x20;   ///< Bit 5 Reverse Mode |  | ||||||
| static const uint8_t MADCTL_ML    = 0x10;   ///< Bit 4 LCD refresh Bottom to top |  | ||||||
| static const uint8_t MADCTL_RGB   = 0x00;  ///< Bit 3 Red-Green-Blue pixel order |  | ||||||
| static const uint8_t MADCTL_BGR   = 0x08;  ///< Bit 3 Blue-Green-Red pixel order |  | ||||||
| static const uint8_t MADCTL_MH    = 0x04;   ///< Bit 2 LCD refresh right to left |  | ||||||
| // clang-format on |  | ||||||
|  |  | ||||||
| static const uint16_t ILI9341_TFTWIDTH = 320;   ///< ILI9341 max TFT width |  | ||||||
| static const uint16_t ILI9341_TFTHEIGHT = 240;  ///< ILI9341 max TFT height |  | ||||||
|  |  | ||||||
| // All ILI9341 specific commands some are used by init() |  | ||||||
| static const uint8_t ILI9341_NOP = 0x00; |  | ||||||
| static const uint8_t ILI9341_SWRESET = 0x01; |  | ||||||
| static const uint8_t ILI9341_RDDID = 0x04; |  | ||||||
| static const uint8_t ILI9341_RDDST = 0x09; |  | ||||||
|  |  | ||||||
| static const uint8_t ILI9341_SLPIN = 0x10; |  | ||||||
| static const uint8_t ILI9341_SLPOUT = 0x11; |  | ||||||
| static const uint8_t ILI9341_PTLON = 0x12; |  | ||||||
| static const uint8_t ILI9341_NORON = 0x13; |  | ||||||
|  |  | ||||||
| static const uint8_t ILI9341_RDMODE = 0x0A; |  | ||||||
| static const uint8_t ILI9341_RDMADCTL = 0x0B; |  | ||||||
| static const uint8_t ILI9341_RDPIXFMT = 0x0C; |  | ||||||
| static const uint8_t ILI9341_RDIMGFMT = 0x0A; |  | ||||||
| static const uint8_t ILI9341_RDSELFDIAG = 0x0F; |  | ||||||
|  |  | ||||||
| static const uint8_t ILI9341_INVOFF = 0x20; |  | ||||||
| static const uint8_t ILI9341_INVON = 0x21; |  | ||||||
| static const uint8_t ILI9341_GAMMASET = 0x26; |  | ||||||
| static const uint8_t ILI9341_DISPOFF = 0x28; |  | ||||||
| static const uint8_t ILI9341_DISPON = 0x29; |  | ||||||
|  |  | ||||||
| static const uint8_t ILI9341_CASET = 0x2A; |  | ||||||
| static const uint8_t ILI9341_PASET = 0x2B; |  | ||||||
| static const uint8_t ILI9341_RAMWR = 0x2C; |  | ||||||
| static const uint8_t ILI9341_RAMRD = 0x2E; |  | ||||||
|  |  | ||||||
| static const uint8_t ILI9341_PTLAR = 0x30; |  | ||||||
| static const uint8_t ILI9341_VSCRDEF = 0x33; |  | ||||||
| static const uint8_t ILI9341_MADCTL = 0x36; |  | ||||||
| static const uint8_t ILI9341_VSCRSADD = 0x37; |  | ||||||
| static const uint8_t ILI9341_PIXFMT = 0x3A; |  | ||||||
|  |  | ||||||
| static const uint8_t ILI9341_WRDISBV = 0x51; |  | ||||||
| static const uint8_t ILI9341_RDDISBV = 0x52; |  | ||||||
| static const uint8_t ILI9341_WRCTRLD = 0x53; |  | ||||||
|  |  | ||||||
| static const uint8_t ILI9341_FRMCTR1 = 0xB1; |  | ||||||
| static const uint8_t ILI9341_FRMCTR2 = 0xB2; |  | ||||||
| static const uint8_t ILI9341_FRMCTR3 = 0xB3; |  | ||||||
| static const uint8_t ILI9341_INVCTR = 0xB4; |  | ||||||
| static const uint8_t ILI9341_DFUNCTR = 0xB6; |  | ||||||
|  |  | ||||||
| static const uint8_t ILI9341_PWCTR1 = 0xC0; |  | ||||||
| static const uint8_t ILI9341_PWCTR2 = 0xC1; |  | ||||||
| static const uint8_t ILI9341_PWCTR3 = 0xC2; |  | ||||||
| static const uint8_t ILI9341_PWCTR4 = 0xC3; |  | ||||||
| static const uint8_t ILI9341_PWCTR5 = 0xC4; |  | ||||||
| static const uint8_t ILI9341_VMCTR1 = 0xC5; |  | ||||||
| static const uint8_t ILI9341_VMCTR2 = 0xC7; |  | ||||||
|  |  | ||||||
| static const uint8_t ILI9341_RDID4 = 0xD3; |  | ||||||
| static const uint8_t ILI9341_RDINDEX = 0xD9; |  | ||||||
| static const uint8_t ILI9341_RDID1 = 0xDA; |  | ||||||
| static const uint8_t ILI9341_RDID2 = 0xDB; |  | ||||||
| static const uint8_t ILI9341_RDID3 = 0xDC; |  | ||||||
| static const uint8_t ILI9341_RDIDX = 0xDD;  // TBC |  | ||||||
|  |  | ||||||
| static const uint8_t ILI9341_GMCTRP1 = 0xE0; |  | ||||||
| static const uint8_t ILI9341_GMCTRN1 = 0xE1; |  | ||||||
|  |  | ||||||
| }  // namespace ili9341 |  | ||||||
| }  // namespace esphome |  | ||||||
| @@ -1,308 +0,0 @@ | |||||||
| #include "ili9341_display.h" |  | ||||||
| #include "esphome/core/log.h" |  | ||||||
| #include "esphome/core/application.h" |  | ||||||
| #include "esphome/core/helpers.h" |  | ||||||
| #include "esphome/core/hal.h" |  | ||||||
|  |  | ||||||
| namespace esphome { |  | ||||||
| namespace ili9341 { |  | ||||||
|  |  | ||||||
| static const char *const TAG = "ili9341"; |  | ||||||
|  |  | ||||||
| void ILI9341Display::setup_pins_() { |  | ||||||
|   this->dc_pin_->setup();  // OUTPUT |  | ||||||
|   this->dc_pin_->digital_write(false); |  | ||||||
|   if (this->reset_pin_ != nullptr) { |  | ||||||
|     this->reset_pin_->setup();  // OUTPUT |  | ||||||
|     this->reset_pin_->digital_write(true); |  | ||||||
|   } |  | ||||||
|   if (this->led_pin_ != nullptr) { |  | ||||||
|     this->led_pin_->setup(); |  | ||||||
|     this->led_pin_->digital_write(true); |  | ||||||
|   } |  | ||||||
|   this->spi_setup(); |  | ||||||
|  |  | ||||||
|   this->reset_(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void ILI9341Display::dump_config() { |  | ||||||
|   LOG_DISPLAY("", "ili9341", this); |  | ||||||
|   LOG_PIN("  Reset Pin: ", this->reset_pin_); |  | ||||||
|   LOG_PIN("  DC Pin: ", this->dc_pin_); |  | ||||||
|   LOG_PIN("  Busy Pin: ", this->busy_pin_); |  | ||||||
|   LOG_UPDATE_INTERVAL(this); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| float ILI9341Display::get_setup_priority() const { return setup_priority::HARDWARE; } |  | ||||||
|  |  | ||||||
| void ILI9341Display::command(uint8_t value) { |  | ||||||
|   this->start_command_(); |  | ||||||
|   this->write_byte(value); |  | ||||||
|   this->end_command_(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void ILI9341Display::reset_() { |  | ||||||
|   if (this->reset_pin_ != nullptr) { |  | ||||||
|     this->reset_pin_->digital_write(false); |  | ||||||
|     delay(10); |  | ||||||
|     this->reset_pin_->digital_write(true); |  | ||||||
|     delay(10); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void ILI9341Display::data(uint8_t value) { |  | ||||||
|   this->start_data_(); |  | ||||||
|   this->write_byte(value); |  | ||||||
|   this->end_data_(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void ILI9341Display::send_command(uint8_t command_byte, const uint8_t *data_bytes, uint8_t num_data_bytes) { |  | ||||||
|   this->command(command_byte);  // Send the command byte |  | ||||||
|   this->start_data_(); |  | ||||||
|   this->write_array(data_bytes, num_data_bytes); |  | ||||||
|   this->end_data_(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| uint8_t ILI9341Display::read_command(uint8_t command_byte, uint8_t index) { |  | ||||||
|   uint8_t data = 0x10 + index; |  | ||||||
|   this->send_command(0xD9, &data, 1);  // Set Index Register |  | ||||||
|   uint8_t result; |  | ||||||
|   this->start_command_(); |  | ||||||
|   this->write_byte(command_byte); |  | ||||||
|   this->start_data_(); |  | ||||||
|   do { |  | ||||||
|     result = this->read_byte(); |  | ||||||
|   } while (index--); |  | ||||||
|   this->end_data_(); |  | ||||||
|   return result; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void ILI9341Display::update() { |  | ||||||
|   this->do_update_(); |  | ||||||
|   this->display_(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| 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_(); |  | ||||||
|   for (uint16_t row = 0; row < h; row++) { |  | ||||||
|     uint32_t pos = start_pos + (row * width_); |  | ||||||
|     uint32_t rem = w; |  | ||||||
|  |  | ||||||
|     while (rem > 0) { |  | ||||||
|       uint32_t sz = buffer_to_transfer_(pos, rem); |  | ||||||
|       this->write_array(transfer_buffer_, 2 * sz); |  | ||||||
|       pos += sz; |  | ||||||
|       rem -= sz; |  | ||||||
|       App.feed_wdt(); |  | ||||||
|     } |  | ||||||
|     App.feed_wdt(); |  | ||||||
|   } |  | ||||||
|   this->end_data_(); |  | ||||||
|  |  | ||||||
|   // invalidate watermarks |  | ||||||
|   this->x_low_ = this->width_; |  | ||||||
|   this->y_low_ = this->height_; |  | ||||||
|   this->x_high_ = 0; |  | ||||||
|   this->y_high_ = 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void ILI9341Display::fill(Color color) { |  | ||||||
|   uint8_t color332 = 0; |  | ||||||
|   if (this->buffer_color_mode_ == BITS_8) { |  | ||||||
|     color332 = display::ColorUtil::color_to_332(color); |  | ||||||
|   } else {  // if (this->buffer_color_mode_ == BITS_8_INDEXED) |  | ||||||
|     color332 = display::ColorUtil::color_to_index8_palette888(color, this->palette_); |  | ||||||
|   } |  | ||||||
|   memset(this->buffer_, color332, this->get_buffer_length_()); |  | ||||||
|   this->x_low_ = 0; |  | ||||||
|   this->y_low_ = 0; |  | ||||||
|   this->x_high_ = this->get_width_internal() - 1; |  | ||||||
|   this->y_high_ = this->get_height_internal() - 1; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void ILI9341Display::fill_internal_(uint8_t color) { |  | ||||||
|   memset(transfer_buffer_, color, sizeof(transfer_buffer_)); |  | ||||||
|  |  | ||||||
|   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_(); |  | ||||||
|  |  | ||||||
|   while (rem > 0) { |  | ||||||
|     size_t sz = rem <= sizeof(transfer_buffer_) ? rem : sizeof(transfer_buffer_); |  | ||||||
|     this->write_array(transfer_buffer_, sz); |  | ||||||
|     rem -= sz; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   this->end_data_(); |  | ||||||
|  |  | ||||||
|   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; |  | ||||||
|  |  | ||||||
|   uint32_t pos = (y * width_) + x; |  | ||||||
|   uint8_t new_color; |  | ||||||
|  |  | ||||||
|   if (this->buffer_color_mode_ == BITS_8) { |  | ||||||
|     new_color = display::ColorUtil::color_to_332(color, display::ColorOrder::COLOR_ORDER_RGB); |  | ||||||
|   } else {  // if (this->buffer_color_mode_ == BITS_8_INDEXED) { |  | ||||||
|     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_; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // should return the total size: return this->get_width_internal() * this->get_height_internal() * 2 // 16bit color |  | ||||||
| // values per bit is huge |  | ||||||
| uint32_t ILI9341Display::get_buffer_length_() { return this->get_width_internal() * this->get_height_internal(); } |  | ||||||
|  |  | ||||||
| void ILI9341Display::start_command_() { |  | ||||||
|   this->dc_pin_->digital_write(false); |  | ||||||
|   this->enable(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void ILI9341Display::end_command_() { this->disable(); } |  | ||||||
| void ILI9341Display::start_data_() { |  | ||||||
|   this->dc_pin_->digital_write(true); |  | ||||||
|   this->enable(); |  | ||||||
| } |  | ||||||
| void ILI9341Display::end_data_() { this->disable(); } |  | ||||||
|  |  | ||||||
| void ILI9341Display::init_lcd_(const uint8_t *init_cmd) { |  | ||||||
|   uint8_t cmd, x, num_args; |  | ||||||
|   const uint8_t *addr = init_cmd; |  | ||||||
|   while ((cmd = progmem_read_byte(addr++)) > 0) { |  | ||||||
|     x = progmem_read_byte(addr++); |  | ||||||
|     num_args = x & 0x7F; |  | ||||||
|     send_command(cmd, addr, num_args); |  | ||||||
|     addr += num_args; |  | ||||||
|     if (x & 0x80) |  | ||||||
|       delay(150);  // NOLINT |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void ILI9341Display::set_addr_window_(uint16_t x1, uint16_t y1, uint16_t w, uint16_t h) { |  | ||||||
|   uint16_t x2 = (x1 + w - 1), y2 = (y1 + h - 1); |  | ||||||
|   this->command(ILI9341_CASET);  // Column address set |  | ||||||
|   this->start_data_(); |  | ||||||
|   this->write_byte(x1 >> 8); |  | ||||||
|   this->write_byte(x1); |  | ||||||
|   this->write_byte(x2 >> 8); |  | ||||||
|   this->write_byte(x2); |  | ||||||
|   this->end_data_(); |  | ||||||
|   this->command(ILI9341_PASET);  // Row address set |  | ||||||
|   this->start_data_(); |  | ||||||
|   this->write_byte(y1 >> 8); |  | ||||||
|   this->write_byte(y1); |  | ||||||
|   this->write_byte(y2 >> 8); |  | ||||||
|   this->write_byte(y2); |  | ||||||
|   this->end_data_(); |  | ||||||
|   this->command(ILI9341_RAMWR);  // Write to RAM |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void ILI9341Display::invert_display_(bool invert) { this->command(invert ? ILI9341_INVON : ILI9341_INVOFF); } |  | ||||||
|  |  | ||||||
| int ILI9341Display::get_width_internal() { return this->width_; } |  | ||||||
| int ILI9341Display::get_height_internal() { return this->height_; } |  | ||||||
|  |  | ||||||
| uint32_t ILI9341Display::buffer_to_transfer_(uint32_t pos, uint32_t sz) { |  | ||||||
|   uint8_t *src = buffer_ + pos; |  | ||||||
|   uint8_t *dst = transfer_buffer_; |  | ||||||
|  |  | ||||||
|   if (sz > sizeof(transfer_buffer_) / 2) { |  | ||||||
|     sz = sizeof(transfer_buffer_) / 2; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   for (uint32_t i = 0; i < sz; ++i) { |  | ||||||
|     uint16_t color; |  | ||||||
|     if (this->buffer_color_mode_ == BITS_8) { |  | ||||||
|       color = display::ColorUtil::color_to_565(display::ColorUtil::rgb332_to_color(*src++)); |  | ||||||
|     } else {  //  if (this->buffer_color_mode == BITS_8_INDEXED) { |  | ||||||
|       Color col = display::ColorUtil::index8_to_color_palette888(*src++, this->palette_); |  | ||||||
|       color = display::ColorUtil::color_to_565(col); |  | ||||||
|     } |  | ||||||
|     *dst++ = (uint8_t)(color >> 8); |  | ||||||
|     *dst++ = (uint8_t) color; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return sz; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //   M5Stack display |  | ||||||
| void ILI9341M5Stack::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_M5STACK); |  | ||||||
|   this->width_ = 320; |  | ||||||
|   this->height_ = 240; |  | ||||||
|   this->invert_display_(true); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //   24_TFT display |  | ||||||
| void ILI9341TFT24::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_TFT); |  | ||||||
|   this->width_ = 240; |  | ||||||
|   this->height_ = 320; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //   24_TFT rotated display |  | ||||||
| void ILI9341TFT24R::initialize() { |  | ||||||
|   this->init_lcd_(INITCMD_TFT); |  | ||||||
|   this->width_ = 320; |  | ||||||
|   this->height_ = 240; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| }  // namespace ili9341 |  | ||||||
| }  // namespace esphome |  | ||||||
| @@ -1,70 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "esphome/core/helpers.h" |  | ||||||
|  |  | ||||||
| namespace esphome { |  | ||||||
| namespace ili9341 { |  | ||||||
|  |  | ||||||
| // clang-format off |  | ||||||
| static const uint8_t PROGMEM INITCMD_M5STACK[] = { |  | ||||||
|   0xEF, 3, 0x03, 0x80, 0x02, |  | ||||||
|   0xCF, 3, 0x00, 0xC1, 0x30, |  | ||||||
|   0xED, 4, 0x64, 0x03, 0x12, 0x81, |  | ||||||
|   0xE8, 3, 0x85, 0x00, 0x78, |  | ||||||
|   0xCB, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, |  | ||||||
|   0xF7, 1, 0x20, |  | ||||||
|   0xEA, 2, 0x00, 0x00, |  | ||||||
|   ILI9341_PWCTR1  , 1, 0x23,             // Power control VRH[5:0] |  | ||||||
|   ILI9341_PWCTR2  , 1, 0x10,             // Power control SAP[2:0];BT[3:0] |  | ||||||
|   ILI9341_VMCTR1  , 2, 0x3e, 0x28,       // VCM control |  | ||||||
|   ILI9341_VMCTR2  , 1, 0x86,             // VCM control2 |  | ||||||
|   ILI9341_MADCTL  , 1, MADCTL_BGR,       // Memory Access Control |  | ||||||
|   ILI9341_VSCRSADD, 1, 0x00,             // Vertical scroll zero |  | ||||||
|   ILI9341_PIXFMT  , 1, 0x55, |  | ||||||
|   ILI9341_FRMCTR1 , 2, 0x00, 0x13, |  | ||||||
|   ILI9341_DFUNCTR , 3, 0x08, 0x82, 0x27, // Display Function Control |  | ||||||
|   0xF2, 1, 0x00,                         // 3Gamma Function Disable |  | ||||||
|   ILI9341_GAMMASET , 1, 0x01,             // Gamma curve selected |  | ||||||
|   ILI9341_GMCTRP1 , 15, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, // Set Gamma |  | ||||||
|                         0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, |  | ||||||
|                         0x0E, 0x09, 0x00, |  | ||||||
|   ILI9341_GMCTRN1 , 15, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, // Set Gamma |  | ||||||
|                         0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, |  | ||||||
|                         0x31, 0x36, 0x0F, |  | ||||||
|   ILI9341_SLPOUT  , 0x80,                // Exit Sleep |  | ||||||
|   ILI9341_DISPON  , 0x80,                // Display on |  | ||||||
|   0x00                                   // End of list |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static const uint8_t PROGMEM INITCMD_TFT[] = { |  | ||||||
|   0xEF, 3, 0x03, 0x80, 0x02, |  | ||||||
|   0xCF, 3, 0x00, 0xC1, 0x30, |  | ||||||
|   0xED, 4, 0x64, 0x03, 0x12, 0x81, |  | ||||||
|   0xE8, 3, 0x85, 0x00, 0x78, |  | ||||||
|   0xCB, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, |  | ||||||
|   0xF7, 1, 0x20, |  | ||||||
|   0xEA, 2, 0x00, 0x00, |  | ||||||
|   ILI9341_PWCTR1  , 1, 0x23,             // Power control VRH[5:0] |  | ||||||
|   ILI9341_PWCTR2  , 1, 0x10,             // Power control SAP[2:0];BT[3:0] |  | ||||||
|   ILI9341_VMCTR1  , 2, 0x3e, 0x28,       // VCM control |  | ||||||
|   ILI9341_VMCTR2  , 1, 0x86,             // VCM control2 |  | ||||||
|   ILI9341_MADCTL  , 1, 0x48,             // Memory Access Control |  | ||||||
|   ILI9341_VSCRSADD, 1, 0x00,             // Vertical scroll zero |  | ||||||
|   ILI9341_PIXFMT  , 1, 0x55, |  | ||||||
|   ILI9341_FRMCTR1 , 2, 0x00, 0x18, |  | ||||||
|   ILI9341_DFUNCTR , 3, 0x08, 0x82, 0x27, // Display Function Control |  | ||||||
|   0xF2, 1, 0x00,                         // 3Gamma Function Disable |  | ||||||
|   ILI9341_GAMMASET , 1, 0x01,             // Gamma curve selected |  | ||||||
|   ILI9341_GMCTRP1 , 15, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, // Set Gamma |  | ||||||
|                         0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, |  | ||||||
|                         0x0E, 0x09, 0x00, |  | ||||||
|   ILI9341_GMCTRN1 , 15, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, // Set Gamma |  | ||||||
|                         0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, |  | ||||||
|                         0x31, 0x36, 0x0F, |  | ||||||
|   ILI9341_SLPOUT  , 0x80,                // Exit Sleep |  | ||||||
|   ILI9341_DISPON  , 0x80,                // Display on |  | ||||||
|   0x00                                   // End of list |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| // clang-format on |  | ||||||
| }  // namespace ili9341 |  | ||||||
| }  // namespace esphome |  | ||||||
							
								
								
									
										0
									
								
								esphome/components/ili9xxx/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								esphome/components/ili9xxx/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										159
									
								
								esphome/components/ili9xxx/display.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								esphome/components/ili9xxx/display.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome import core, pins | ||||||
|  | from esphome.components import display, spi | ||||||
|  | from esphome.core import CORE, HexInt | ||||||
|  | from esphome.const import ( | ||||||
|  |     CONF_COLOR_PALETTE, | ||||||
|  |     CONF_DC_PIN, | ||||||
|  |     CONF_ID, | ||||||
|  |     CONF_LAMBDA, | ||||||
|  |     CONF_MODEL, | ||||||
|  |     CONF_RAW_DATA_ID, | ||||||
|  |     CONF_PAGES, | ||||||
|  |     CONF_RESET_PIN, | ||||||
|  |     CONF_DIMENSIONS, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | DEPENDENCIES = ["spi"] | ||||||
|  | AUTO_LOAD = ["psram"] | ||||||
|  |  | ||||||
|  | CODEOWNERS = ["@nielsnl68"] | ||||||
|  |  | ||||||
|  | ili9XXX_ns = cg.esphome_ns.namespace("ili9xxx") | ||||||
|  | ili9XXXSPI = ili9XXX_ns.class_( | ||||||
|  |     "ILI9XXXDisplay", cg.PollingComponent, spi.SPIDevice, display.DisplayBuffer | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | ILI9XXXColorMode = ili9XXX_ns.enum("ILI9XXXColorMode") | ||||||
|  |  | ||||||
|  | MODELS = { | ||||||
|  |     "M5STACK": ili9XXX_ns.class_("ILI9XXXM5Stack", ili9XXXSPI), | ||||||
|  |     "M5CORE": ili9XXX_ns.class_("ILI9XXXM5CORE", ili9XXXSPI), | ||||||
|  |     "TFT_2.4": ili9XXX_ns.class_("ILI9XXXILI9341", ili9XXXSPI), | ||||||
|  |     "TFT_2.4R": ili9XXX_ns.class_("ILI9XXXILI9342", ili9XXXSPI), | ||||||
|  |     "ILI9341": ili9XXX_ns.class_("ILI9XXXILI9341", ili9XXXSPI), | ||||||
|  |     "ILI9342": ili9XXX_ns.class_("ILI9XXXILI9342", ili9XXXSPI), | ||||||
|  |     "ILI9481": ili9XXX_ns.class_("ILI9XXXILI9481", ili9XXXSPI), | ||||||
|  |     "ILI9486": ili9XXX_ns.class_("ILI9XXXILI9486", ili9XXXSPI), | ||||||
|  |     "ILI9488": ili9XXX_ns.class_("ILI9XXXILI9488", ili9XXXSPI), | ||||||
|  |     "ST7796": ili9XXX_ns.class_("ILI9XXXST7796", ili9XXXSPI), | ||||||
|  | } | ||||||
|  |  | ||||||
|  | COLOR_PALETTE = cv.one_of("NONE", "GRAYSCALE", "IMAGE_ADAPTIVE") | ||||||
|  |  | ||||||
|  | CONF_LED_PIN = "led_pin" | ||||||
|  | CONF_COLOR_PALETTE_IMAGES = "color_palette_images" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def _validate(config): | ||||||
|  |     if config.get(CONF_COLOR_PALETTE) == "IMAGE_ADAPTIVE" and not config.get( | ||||||
|  |         CONF_COLOR_PALETTE_IMAGES | ||||||
|  |     ): | ||||||
|  |         raise cv.Invalid( | ||||||
|  |             "Color palette in IMAGE_ADAPTIVE mode requires at least one 'color_palette_images' entry to generate palette" | ||||||
|  |         ) | ||||||
|  |     if ( | ||||||
|  |         config.get(CONF_COLOR_PALETTE_IMAGES) | ||||||
|  |         and config.get(CONF_COLOR_PALETTE) != "IMAGE_ADAPTIVE" | ||||||
|  |     ): | ||||||
|  |         raise cv.Invalid( | ||||||
|  |             "Providing color palette images requires palette mode to be 'IMAGE_ADAPTIVE'" | ||||||
|  |         ) | ||||||
|  |     return config | ||||||
|  |  | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = cv.All( | ||||||
|  |     display.FULL_DISPLAY_SCHEMA.extend( | ||||||
|  |         { | ||||||
|  |             cv.GenerateID(): cv.declare_id(ili9XXXSPI), | ||||||
|  |             cv.Required(CONF_MODEL): cv.enum(MODELS, upper=True, space="_"), | ||||||
|  |             cv.Optional(CONF_DIMENSIONS): cv.dimensions, | ||||||
|  |             cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, | ||||||
|  |             cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, | ||||||
|  |             cv.Optional(CONF_LED_PIN): cv.invalid( | ||||||
|  |                 "This property is removed. To use the backlight use proper light component." | ||||||
|  |             ), | ||||||
|  |             cv.Optional(CONF_COLOR_PALETTE, default="NONE"): COLOR_PALETTE, | ||||||
|  |             cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), | ||||||
|  |             cv.Optional(CONF_COLOR_PALETTE_IMAGES, default=[]): cv.ensure_list( | ||||||
|  |                 cv.file_ | ||||||
|  |             ), | ||||||
|  |         } | ||||||
|  |     ) | ||||||
|  |     .extend(cv.polling_component_schema("1s")) | ||||||
|  |     .extend(spi.spi_device_schema(False)), | ||||||
|  |     cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), | ||||||
|  |     _validate, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def to_code(config): | ||||||
|  |     rhs = MODELS[config[CONF_MODEL]].new() | ||||||
|  |     var = cg.Pvariable(config[CONF_ID], rhs) | ||||||
|  |  | ||||||
|  |     await cg.register_component(var, config) | ||||||
|  |     await display.register_display(var, config) | ||||||
|  |     await spi.register_spi_device(var, config) | ||||||
|  |     dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) | ||||||
|  |     cg.add(var.set_dc_pin(dc)) | ||||||
|  |  | ||||||
|  |     if CONF_LAMBDA in config: | ||||||
|  |         lambda_ = await cg.process_lambda( | ||||||
|  |             config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void | ||||||
|  |         ) | ||||||
|  |         cg.add(var.set_writer(lambda_)) | ||||||
|  |  | ||||||
|  |     if CONF_RESET_PIN in config: | ||||||
|  |         reset = await cg.gpio_pin_expression(config[CONF_RESET_PIN]) | ||||||
|  |         cg.add(var.set_reset_pin(reset)) | ||||||
|  |  | ||||||
|  |     if CONF_DIMENSIONS in config: | ||||||
|  |         cg.add( | ||||||
|  |             var.set_dimentions(config[CONF_DIMENSIONS][0], config[CONF_DIMENSIONS][1]) | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     rhs = None | ||||||
|  |     if config[CONF_COLOR_PALETTE] == "GRAYSCALE": | ||||||
|  |         cg.add(var.set_buffer_color_mode(ILI9XXXColorMode.BITS_8_INDEXED)) | ||||||
|  |         rhs = [] | ||||||
|  |         for x in range(256): | ||||||
|  |             rhs.extend([HexInt(x), HexInt(x), HexInt(x)]) | ||||||
|  |         prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) | ||||||
|  |         cg.add(var.set_palette(prog_arr)) | ||||||
|  |     elif config[CONF_COLOR_PALETTE] == "IMAGE_ADAPTIVE": | ||||||
|  |         cg.add(var.set_buffer_color_mode(ILI9XXXColorMode.BITS_8_INDEXED)) | ||||||
|  |         from PIL import Image | ||||||
|  |  | ||||||
|  |         def load_image(filename): | ||||||
|  |             path = CORE.relative_config_path(filename) | ||||||
|  |             try: | ||||||
|  |                 return Image.open(path) | ||||||
|  |             except Exception as e: | ||||||
|  |                 raise core.EsphomeError(f"Could not load image file {path}: {e}") | ||||||
|  |  | ||||||
|  |         # make a wide horizontal combined image. | ||||||
|  |         images = [load_image(x) for x in config[CONF_COLOR_PALETTE_IMAGES]] | ||||||
|  |         total_width = sum(i.width for i in images) | ||||||
|  |         max_height = max(i.height for i in images) | ||||||
|  |  | ||||||
|  |         ref_image = Image.new("RGB", (total_width, max_height)) | ||||||
|  |         x = 0 | ||||||
|  |         for i in images: | ||||||
|  |             ref_image.paste(i, (x, 0)) | ||||||
|  |             x = x + i.width | ||||||
|  |  | ||||||
|  |         # reduce the colors on combined image to 256. | ||||||
|  |         converted = ref_image.convert("P", palette=Image.ADAPTIVE, colors=256) | ||||||
|  |         # if you want to verify how the images look use | ||||||
|  |         # ref_image.save("ref_in.png") | ||||||
|  |         # converted.save("ref_out.png") | ||||||
|  |         palette = converted.getpalette() | ||||||
|  |         assert len(palette) == 256 * 3 | ||||||
|  |         rhs = palette | ||||||
|  |     else: | ||||||
|  |         cg.add(var.set_buffer_color_mode(ILI9XXXColorMode.BITS_16)) | ||||||
|  |  | ||||||
|  |     if rhs is not None: | ||||||
|  |         prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) | ||||||
|  |         cg.add(var.set_palette(prog_arr)) | ||||||
							
								
								
									
										96
									
								
								esphome/components/ili9xxx/ili9xxx_defines.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								esphome/components/ili9xxx/ili9xxx_defines.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace ili9xxx { | ||||||
|  |  | ||||||
|  | // Color definitions | ||||||
|  | // clang-format off | ||||||
|  | static const uint8_t MADCTL_MY    = 0x80;   ///< Bit 7 Bottom to top | ||||||
|  | static const uint8_t MADCTL_MX    = 0x40;   ///< Bit 6 Right to left | ||||||
|  | static const uint8_t MADCTL_MV    = 0x20;   ///< Bit 5 Reverse Mode | ||||||
|  | static const uint8_t MADCTL_ML    = 0x10;   ///< Bit 4 LCD refresh Bottom to top | ||||||
|  | static const uint8_t MADCTL_RGB   = 0x00;  ///< Bit 3 Red-Green-Blue pixel order | ||||||
|  | static const uint8_t MADCTL_BGR   = 0x08;  ///< Bit 3 Blue-Green-Red pixel order | ||||||
|  | static const uint8_t MADCTL_MH    = 0x04;   ///< Bit 2 LCD refresh right to left | ||||||
|  | // clang-format on | ||||||
|  |  | ||||||
|  | // All ILI9XXX specific commands some are used by init() | ||||||
|  | static const uint8_t ILI9XXX_NOP = 0x00; | ||||||
|  | static const uint8_t ILI9XXX_SWRESET = 0x01; | ||||||
|  | static const uint8_t ILI9XXX_RDDID = 0x04; | ||||||
|  | static const uint8_t ILI9XXX_RDDST = 0x09; | ||||||
|  |  | ||||||
|  | static const uint8_t ILI9XXX_SLPIN = 0x10; | ||||||
|  | static const uint8_t ILI9XXX_SLPOUT = 0x11; | ||||||
|  | static const uint8_t ILI9XXX_PTLON = 0x12; | ||||||
|  | static const uint8_t ILI9XXX_NORON = 0x13; | ||||||
|  |  | ||||||
|  | static const uint8_t ILI9XXX_RDMODE = 0x0A; | ||||||
|  | static const uint8_t ILI9XXX_RDMADCTL = 0x0B; | ||||||
|  | static const uint8_t ILI9XXX_RDPIXFMT = 0x0C; | ||||||
|  | static const uint8_t ILI9XXX_RDIMGFMT = 0x0D; | ||||||
|  | static const uint8_t ILI9XXX_RDSELFDIAG = 0x0F; | ||||||
|  |  | ||||||
|  | static const uint8_t ILI9XXX_INVOFF = 0x20; | ||||||
|  | static const uint8_t ILI9XXX_INVON = 0x21; | ||||||
|  | static const uint8_t ILI9XXX_GAMMASET = 0x26; | ||||||
|  | static const uint8_t ILI9XXX_DISPOFF = 0x28; | ||||||
|  | static const uint8_t ILI9XXX_DISPON = 0x29; | ||||||
|  |  | ||||||
|  | static const uint8_t ILI9XXX_CASET = 0x2A; | ||||||
|  | static const uint8_t ILI9XXX_PASET = 0x2B; | ||||||
|  | static const uint8_t ILI9XXX_RAMWR = 0x2C; | ||||||
|  | static const uint8_t ILI9XXX_RAMRD = 0x2E; | ||||||
|  |  | ||||||
|  | static const uint8_t ILI9XXX_PTLAR = 0x30; | ||||||
|  | static const uint8_t ILI9XXX_VSCRDEF = 0x33; | ||||||
|  | static const uint8_t ILI9XXX_MADCTL = 0x36; | ||||||
|  | static const uint8_t ILI9XXX_VSCRSADD = 0x37; | ||||||
|  | static const uint8_t ILI9XXX_IDMOFF = 0x38; | ||||||
|  | static const uint8_t ILI9XXX_IDMON = 0x39; | ||||||
|  | static const uint8_t ILI9XXX_PIXFMT = 0x3A; | ||||||
|  | static const uint8_t ILI9XXX_COLMOD = 0x3A; | ||||||
|  |  | ||||||
|  | static const uint8_t ILI9XXX_GETSCANLINE = 0x45; | ||||||
|  |  | ||||||
|  | static const uint8_t ILI9XXX_WRDISBV = 0x51; | ||||||
|  | static const uint8_t ILI9XXX_RDDISBV = 0x52; | ||||||
|  | static const uint8_t ILI9XXX_WRCTRLD = 0x53; | ||||||
|  |  | ||||||
|  | static const uint8_t ILI9XXX_IFMODE = 0xB0; | ||||||
|  | static const uint8_t ILI9XXX_FRMCTR1 = 0xB1; | ||||||
|  | static const uint8_t ILI9XXX_FRMCTR2 = 0xB2; | ||||||
|  | static const uint8_t ILI9XXX_FRMCTR3 = 0xB3; | ||||||
|  | static const uint8_t ILI9XXX_INVCTR = 0xB4; | ||||||
|  | static const uint8_t ILI9XXX_DFUNCTR = 0xB6; | ||||||
|  | static const uint8_t ILI9XXX_ETMOD = 0xB7; | ||||||
|  |  | ||||||
|  | static const uint8_t ILI9XXX_PWCTR1 = 0xC0; | ||||||
|  | static const uint8_t ILI9XXX_PWCTR2 = 0xC1; | ||||||
|  | static const uint8_t ILI9XXX_PWCTR3 = 0xC2; | ||||||
|  | static const uint8_t ILI9XXX_PWCTR4 = 0xC3; | ||||||
|  | static const uint8_t ILI9XXX_PWCTR5 = 0xC4; | ||||||
|  | static const uint8_t ILI9XXX_VMCTR1 = 0xC5; | ||||||
|  | static const uint8_t ILI9XXX_IFCTR = 0xC6; | ||||||
|  | static const uint8_t ILI9XXX_VMCTR2 = 0xC7; | ||||||
|  | static const uint8_t ILI9XXX_GMCTR = 0xC8; | ||||||
|  | static const uint8_t ILI9XXX_SETEXTC = 0xC8; | ||||||
|  |  | ||||||
|  | static const uint8_t ILI9XXX_PWSET = 0xD0; | ||||||
|  | static const uint8_t ILI9XXX_VMCTR = 0xD1; | ||||||
|  | static const uint8_t ILI9XXX_PWSETN = 0xD2; | ||||||
|  | static const uint8_t ILI9XXX_RDID4 = 0xD3; | ||||||
|  | static const uint8_t ILI9XXX_RDINDEX = 0xD9; | ||||||
|  | static const uint8_t ILI9XXX_RDID1 = 0xDA; | ||||||
|  | static const uint8_t ILI9XXX_RDID2 = 0xDB; | ||||||
|  | static const uint8_t ILI9XXX_RDID3 = 0xDC; | ||||||
|  | static const uint8_t ILI9XXX_RDIDX = 0xDD;  // TBC | ||||||
|  |  | ||||||
|  | static const uint8_t ILI9XXX_GMCTRP1 = 0xE0; | ||||||
|  | static const uint8_t ILI9XXX_GMCTRN1 = 0xE1; | ||||||
|  |  | ||||||
|  | static const uint8_t ILI9XXX_CSCON = 0xF0; | ||||||
|  | static const uint8_t ILI9XXX_ADJCTL3 = 0xF7; | ||||||
|  |  | ||||||
|  | }  // namespace ili9xxx | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										416
									
								
								esphome/components/ili9xxx/ili9xxx_display.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										416
									
								
								esphome/components/ili9xxx/ili9xxx_display.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,416 @@ | |||||||
|  | #include "ili9xxx_display.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  | #include "esphome/core/application.h" | ||||||
|  | #include "esphome/core/helpers.h" | ||||||
|  | #include "esphome/core/hal.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace ili9xxx { | ||||||
|  |  | ||||||
|  | static const char *const TAG = "ili9xxx"; | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::setup() { | ||||||
|  |   this->setup_pins_(); | ||||||
|  |   this->initialize(); | ||||||
|  |  | ||||||
|  |   this->x_low_ = this->width_; | ||||||
|  |   this->y_low_ = this->height_; | ||||||
|  |   this->x_high_ = 0; | ||||||
|  |   this->y_high_ = 0; | ||||||
|  |   if (this->buffer_color_mode_ == BITS_16) { | ||||||
|  |     this->init_internal_(this->get_buffer_length_() * 2); | ||||||
|  |     if (this->buffer_ != nullptr) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     this->buffer_color_mode_ = BITS_8; | ||||||
|  |   } | ||||||
|  |   this->init_internal_(this->get_buffer_length_()); | ||||||
|  |   if (this->buffer_ == nullptr) { | ||||||
|  |     this->mark_failed(); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::setup_pins_() { | ||||||
|  |   this->dc_pin_->setup();  // OUTPUT | ||||||
|  |   this->dc_pin_->digital_write(false); | ||||||
|  |   if (this->reset_pin_ != nullptr) { | ||||||
|  |     this->reset_pin_->setup();  // OUTPUT | ||||||
|  |     this->reset_pin_->digital_write(true); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this->spi_setup(); | ||||||
|  |  | ||||||
|  |   this->reset_(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::dump_config() { | ||||||
|  |   LOG_DISPLAY("", "ili9xxx", this); | ||||||
|  |   switch (this->buffer_color_mode_) { | ||||||
|  |     case BITS_8_INDEXED: | ||||||
|  |       ESP_LOGCONFIG(TAG, "  Color mode: 8bit Indexed"); | ||||||
|  |       break; | ||||||
|  |     case BITS_16: | ||||||
|  |       ESP_LOGCONFIG(TAG, "  Color mode: 16bit"); | ||||||
|  |       break; | ||||||
|  |     default: | ||||||
|  |       ESP_LOGCONFIG(TAG, "  Color mode: 8bit 332 mode"); | ||||||
|  |       break; | ||||||
|  |   } | ||||||
|  |   if (this->is_18bitdisplay_) { | ||||||
|  |     ESP_LOGCONFIG(TAG, "  18-Bit Mode: YES"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   LOG_PIN("  Reset Pin: ", this->reset_pin_); | ||||||
|  |   LOG_PIN("  DC Pin: ", this->dc_pin_); | ||||||
|  |   LOG_PIN("  Busy Pin: ", this->busy_pin_); | ||||||
|  |  | ||||||
|  |   if (this->is_failed()) { | ||||||
|  |     ESP_LOGCONFIG(TAG, "  => Failed to init Memory: YES!"); | ||||||
|  |   } | ||||||
|  |   LOG_UPDATE_INTERVAL(this); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | float ILI9XXXDisplay::get_setup_priority() const { return setup_priority::HARDWARE; } | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::fill(Color color) { | ||||||
|  |   uint16_t new_color = 0; | ||||||
|  |   this->x_low_ = 0; | ||||||
|  |   this->y_low_ = 0; | ||||||
|  |   this->x_high_ = this->get_width_internal() - 1; | ||||||
|  |   this->y_high_ = this->get_height_internal() - 1; | ||||||
|  |   switch (this->buffer_color_mode_) { | ||||||
|  |     case BITS_8_INDEXED: | ||||||
|  |       new_color = display::ColorUtil::color_to_index8_palette888(color, this->palette_); | ||||||
|  |       break; | ||||||
|  |     case BITS_16: | ||||||
|  |       new_color = display::ColorUtil::color_to_565(color); | ||||||
|  |       for (uint32_t i = 0; i < this->get_buffer_length_() * 2; i = i + 2) { | ||||||
|  |         this->buffer_[i] = (uint8_t)(new_color >> 8); | ||||||
|  |         this->buffer_[i + 1] = (uint8_t) new_color; | ||||||
|  |       } | ||||||
|  |       return; | ||||||
|  |       break; | ||||||
|  |     default: | ||||||
|  |       new_color = display::ColorUtil::color_to_332(color, display::ColorOrder::COLOR_ORDER_RGB); | ||||||
|  |       break; | ||||||
|  |   } | ||||||
|  |   memset(this->buffer_, (uint8_t) new_color, this->get_buffer_length_()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void HOT ILI9XXXDisplay::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; | ||||||
|  |   } | ||||||
|  |   uint32_t pos = (y * width_) + x; | ||||||
|  |   uint16_t new_color; | ||||||
|  |   bool updated = false; | ||||||
|  |   switch (this->buffer_color_mode_) { | ||||||
|  |     case BITS_8_INDEXED: | ||||||
|  |       new_color = display::ColorUtil::color_to_index8_palette888(color, this->palette_); | ||||||
|  |       break; | ||||||
|  |     case BITS_16: | ||||||
|  |       pos = pos * 2; | ||||||
|  |       new_color = display::ColorUtil::color_to_565(color, display::ColorOrder::COLOR_ORDER_RGB); | ||||||
|  |       if (this->buffer_[pos] != (uint8_t)(new_color >> 8)) { | ||||||
|  |         this->buffer_[pos] = (uint8_t)(new_color >> 8); | ||||||
|  |         updated = true; | ||||||
|  |       } | ||||||
|  |       pos = pos + 1; | ||||||
|  |       new_color = new_color & 0xFF; | ||||||
|  |       break; | ||||||
|  |     default: | ||||||
|  |       new_color = display::ColorUtil::color_to_332(color, display::ColorOrder::COLOR_ORDER_RGB); | ||||||
|  |       break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (this->buffer_[pos] != new_color) { | ||||||
|  |     this->buffer_[pos] = new_color; | ||||||
|  |     updated = true; | ||||||
|  |   } | ||||||
|  |   if (updated) { | ||||||
|  |     // 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_; | ||||||
|  |     // ESP_LOGVV(TAG, "=>>> pixel (x:%d, y:%d) (xl:%d, xh:%d, yl:%d, yh:%d", x, y, this->x_low_, this->x_high_, | ||||||
|  |     //           this->y_low_, this->y_high_); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::update() { | ||||||
|  |   if (this->prossing_update_) { | ||||||
|  |     this->need_update_ = true; | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   do { | ||||||
|  |     this->prossing_update_ = true; | ||||||
|  |     this->need_update_ = false; | ||||||
|  |     if (!this->need_update_) { | ||||||
|  |       this->do_update_(); | ||||||
|  |     } | ||||||
|  |   } while (this->need_update_); | ||||||
|  |   this->prossing_update_ = false; | ||||||
|  |   this->display_(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::display_() { | ||||||
|  |   // we will only update the changed window to the display | ||||||
|  |   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 | ||||||
|  |   if ((this->x_high_ < this->x_low_) || (this->y_high_ < this->y_low_)) { | ||||||
|  |     ESP_LOGV(TAG, "Nothing to display"); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   set_addr_window_(this->x_low_, this->y_low_, w, h); | ||||||
|  |  | ||||||
|  |   ESP_LOGV(TAG, | ||||||
|  |            "Start display(xlow:%d, ylow:%d, xhigh:%d, yhigh:%d, width:%d, " | ||||||
|  |            "heigth:%d, start_pos:%d)", | ||||||
|  |            this->x_low_, this->y_low_, this->x_high_, this->y_high_, w, h, start_pos); | ||||||
|  |  | ||||||
|  |   this->start_data_(); | ||||||
|  |   for (uint16_t row = 0; row < h; row++) { | ||||||
|  |     uint32_t pos = start_pos + (row * width_); | ||||||
|  |     uint32_t rem = w; | ||||||
|  |  | ||||||
|  |     while (rem > 0) { | ||||||
|  |       uint32_t sz = std::min(rem, ILI9XXX_TRANSFER_BUFFER_SIZE); | ||||||
|  |       // ESP_LOGVV(TAG, "Send to display(pos:%d, rem:%d, zs:%d)", pos, rem, sz); | ||||||
|  |       buffer_to_transfer_(pos, sz); | ||||||
|  |       if (this->is_18bitdisplay_) { | ||||||
|  |         for (uint32_t i = 0; i < sz; ++i) { | ||||||
|  |           uint16_t color_val = transfer_buffer_[i]; | ||||||
|  |  | ||||||
|  |           uint8_t red = color_val & 0x1F; | ||||||
|  |           uint8_t green = (color_val & 0x7E0) >> 5; | ||||||
|  |           uint8_t blue = (color_val & 0xF800) >> 11; | ||||||
|  |  | ||||||
|  |           uint8_t pass_buff[3]; | ||||||
|  |  | ||||||
|  |           pass_buff[2] = (uint8_t)((red / 32.0) * 64) << 2; | ||||||
|  |           pass_buff[1] = (uint8_t) green << 2; | ||||||
|  |           pass_buff[0] = (uint8_t)((blue / 32.0) * 64) << 2; | ||||||
|  |  | ||||||
|  |           this->write_array(pass_buff, sizeof(pass_buff)); | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|  |         this->write_array16(transfer_buffer_, sz); | ||||||
|  |       } | ||||||
|  |       pos += sz; | ||||||
|  |       rem -= sz; | ||||||
|  |     } | ||||||
|  |     App.feed_wdt(); | ||||||
|  |   } | ||||||
|  |   this->end_data_(); | ||||||
|  |  | ||||||
|  |   // invalidate watermarks | ||||||
|  |   this->x_low_ = this->width_; | ||||||
|  |   this->y_low_ = this->height_; | ||||||
|  |   this->x_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 | ||||||
|  | // values per bit is huge | ||||||
|  | uint32_t ILI9XXXDisplay::get_buffer_length_() { return this->get_width_internal() * this->get_height_internal(); } | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::command(uint8_t value) { | ||||||
|  |   this->start_command_(); | ||||||
|  |   this->write_byte(value); | ||||||
|  |   this->end_command_(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::data(uint8_t value) { | ||||||
|  |   this->start_data_(); | ||||||
|  |   this->write_byte(value); | ||||||
|  |   this->end_data_(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::send_command(uint8_t command_byte, const uint8_t *data_bytes, uint8_t num_data_bytes) { | ||||||
|  |   this->command(command_byte);  // Send the command byte | ||||||
|  |   this->start_data_(); | ||||||
|  |   this->write_array(data_bytes, num_data_bytes); | ||||||
|  |   this->end_data_(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uint8_t ILI9XXXDisplay::read_command(uint8_t command_byte, uint8_t index) { | ||||||
|  |   uint8_t data = 0x10 + index; | ||||||
|  |   this->send_command(0xD9, &data, 1);  // Set Index Register | ||||||
|  |   uint8_t result; | ||||||
|  |   this->start_command_(); | ||||||
|  |   this->write_byte(command_byte); | ||||||
|  |   this->start_data_(); | ||||||
|  |   do { | ||||||
|  |     result = this->read_byte(); | ||||||
|  |   } while (index--); | ||||||
|  |   this->end_data_(); | ||||||
|  |   return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::start_command_() { | ||||||
|  |   this->dc_pin_->digital_write(false); | ||||||
|  |   this->enable(); | ||||||
|  | } | ||||||
|  | void ILI9XXXDisplay::start_data_() { | ||||||
|  |   this->dc_pin_->digital_write(true); | ||||||
|  |   this->enable(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::end_command_() { this->disable(); } | ||||||
|  | void ILI9XXXDisplay::end_data_() { this->disable(); } | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::reset_() { | ||||||
|  |   if (this->reset_pin_ != nullptr) { | ||||||
|  |     this->reset_pin_->digital_write(false); | ||||||
|  |     delay(10); | ||||||
|  |     this->reset_pin_->digital_write(true); | ||||||
|  |     delay(10); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::init_lcd_(const uint8_t *init_cmd) { | ||||||
|  |   uint8_t cmd, x, num_args; | ||||||
|  |   const uint8_t *addr = init_cmd; | ||||||
|  |   while ((cmd = progmem_read_byte(addr++)) > 0) { | ||||||
|  |     x = progmem_read_byte(addr++); | ||||||
|  |     num_args = x & 0x7F; | ||||||
|  |     send_command(cmd, addr, num_args); | ||||||
|  |     addr += num_args; | ||||||
|  |     if (x & 0x80) | ||||||
|  |       delay(150);  // NOLINT | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::set_addr_window_(uint16_t x1, uint16_t y1, uint16_t w, uint16_t h) { | ||||||
|  |   uint16_t x2 = (x1 + w - 1), y2 = (y1 + h - 1); | ||||||
|  |   this->command(ILI9XXX_CASET);  // Column address set | ||||||
|  |   this->start_data_(); | ||||||
|  |   this->write_byte(x1 >> 8); | ||||||
|  |   this->write_byte(x1); | ||||||
|  |   this->write_byte(x2 >> 8); | ||||||
|  |   this->write_byte(x2); | ||||||
|  |   this->end_data_(); | ||||||
|  |   this->command(ILI9XXX_PASET);  // Row address set | ||||||
|  |   this->start_data_(); | ||||||
|  |   this->write_byte(y1 >> 8); | ||||||
|  |   this->write_byte(y1); | ||||||
|  |   this->write_byte(y2 >> 8); | ||||||
|  |   this->write_byte(y2); | ||||||
|  |   this->end_data_(); | ||||||
|  |   this->command(ILI9XXX_RAMWR);  // Write to RAM | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ILI9XXXDisplay::invert_display_(bool invert) { this->command(invert ? ILI9XXX_INVON : ILI9XXX_INVOFF); } | ||||||
|  |  | ||||||
|  | int ILI9XXXDisplay::get_width_internal() { return this->width_; } | ||||||
|  | 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->invert_display_(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->invert_display_(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; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //   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 ILI9XXXST7796::initialize() { | ||||||
|  |   this->init_lcd_(INITCMD_ST7796); | ||||||
|  |   if (this->width_ == 0) { | ||||||
|  |     this->width_ = 320; | ||||||
|  |   } | ||||||
|  |   if (this->height_ == 0) { | ||||||
|  |     this->height_ = 480; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace ili9xxx | ||||||
|  | }  // namespace esphome | ||||||
| @@ -1,27 +1,21 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 |  | ||||||
| #include "esphome/core/component.h" |  | ||||||
| #include "esphome/components/spi/spi.h" | #include "esphome/components/spi/spi.h" | ||||||
| #include "esphome/components/display/display_buffer.h" | #include "esphome/components/display/display_buffer.h" | ||||||
| #include "ili9341_defines.h" | #include "ili9xxx_defines.h" | ||||||
| #include "ili9341_init.h" | #include "ili9xxx_init.h" | ||||||
| #include "esphome/core/log.h" |  | ||||||
| 
 | 
 | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace ili9341 { | namespace ili9xxx { | ||||||
| 
 | 
 | ||||||
| enum ILI9341Model { | const uint32_t ILI9XXX_TRANSFER_BUFFER_SIZE = 64; | ||||||
|   M5STACK = 0, | 
 | ||||||
|   TFT_24, | enum ILI9XXXColorMode { | ||||||
|   TFT_24R, |   BITS_8 = 0x08, | ||||||
|  |   BITS_8_INDEXED = 0x09, | ||||||
|  |   BITS_16 = 0x10, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum ILI9341ColorMode { | class ILI9XXXDisplay : public PollingComponent, | ||||||
|   BITS_8, |  | ||||||
|   BITS_8_INDEXED, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| class ILI9341Display : public PollingComponent, |  | ||||||
|                        public display::DisplayBuffer, |                        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, spi::DATA_RATE_40MHZ> { |                                              spi::CLOCK_PHASE_LEADING, spi::DATA_RATE_40MHZ> { | ||||||
| @@ -29,59 +23,46 @@ class ILI9341Display : public PollingComponent, | |||||||
|   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_led_pin(GPIOPin *led) { this->led_pin_ = led; } |  | ||||||
|   void set_model(ILI9341Model model) { this->model_ = model; } |  | ||||||
|   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(ILI9341ColorMode 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) { | ||||||
|  |     this->height_ = height; | ||||||
|  |     this->width_ = width; | ||||||
|  |   } | ||||||
|   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); | ||||||
|   virtual void initialize() = 0; |  | ||||||
| 
 | 
 | ||||||
|   void update() override; |   void update() override; | ||||||
| 
 | 
 | ||||||
|   void fill(Color color) override; |   void fill(Color color) override; | ||||||
| 
 | 
 | ||||||
|   void dump_config() override; |   void dump_config() override; | ||||||
|   void setup() override { |   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; } |   display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; } | ||||||
| 
 | 
 | ||||||
|  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 init_lcd_(const uint8_t *init_cmd); |   void init_lcd_(const uint8_t *init_cmd); | ||||||
|   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 w, uint16_t h); | ||||||
|   void invert_display_(bool invert); |   void invert_display_(bool invert); | ||||||
|   void reset_(); |   void reset_(); | ||||||
|   void fill_internal_(uint8_t color); |  | ||||||
|   void display_(); |  | ||||||
|   void rotate_my_(uint8_t m); |  | ||||||
| 
 | 
 | ||||||
|   ILI9341Model model_; |   int16_t width_{0};   ///< Display width as modified by current rotation
 | ||||||
|   int16_t width_{320};   ///< Display width as modified by current rotation
 |   int16_t height_{0};  ///< Display height as modified by current rotation
 | ||||||
|   int16_t height_{240};  ///< Display height as modified by current rotation
 |  | ||||||
|   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}; | ||||||
|   uint16_t y_high_{0}; |   uint16_t y_high_{0}; | ||||||
|   const uint8_t *palette_; |   const uint8_t *palette_; | ||||||
| 
 | 
 | ||||||
|   ILI9341ColorMode buffer_color_mode_{BITS_8}; |   ILI9XXXColorMode buffer_color_mode_{BITS_16}; | ||||||
| 
 | 
 | ||||||
|   uint32_t get_buffer_length_(); |   uint32_t get_buffer_length_(); | ||||||
|   int get_width_internal() override; |   int get_width_internal() override; | ||||||
| @@ -92,33 +73,66 @@ class ILI9341Display : public PollingComponent, | |||||||
|   void start_data_(); |   void start_data_(); | ||||||
|   void end_data_(); |   void end_data_(); | ||||||
| 
 | 
 | ||||||
|   uint8_t transfer_buffer_[64]; |   uint16_t transfer_buffer_[ILI9XXX_TRANSFER_BUFFER_SIZE]; | ||||||
| 
 | 
 | ||||||
|   uint32_t buffer_to_transfer_(uint32_t pos, uint32_t sz); |   uint32_t buffer_to_transfer_(uint32_t pos, uint32_t sz); | ||||||
| 
 | 
 | ||||||
|   GPIOPin *reset_pin_{nullptr}; |   GPIOPin *reset_pin_{nullptr}; | ||||||
|   GPIOPin *led_pin_{nullptr}; |   GPIOPin *dc_pin_{nullptr}; | ||||||
|   GPIOPin *dc_pin_; |  | ||||||
|   GPIOPin *busy_pin_{nullptr}; |   GPIOPin *busy_pin_{nullptr}; | ||||||
|  | 
 | ||||||
|  |   bool prossing_update_ = false; | ||||||
|  |   bool need_update_ = false; | ||||||
|  |   bool is_18bitdisplay_ = false; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| //-----------   M5Stack display --------------
 | //-----------   M5Stack display --------------
 | ||||||
| class ILI9341M5Stack : public ILI9341Display { | class ILI9XXXM5Stack : public ILI9XXXDisplay { | ||||||
|  public: |  protected: | ||||||
|   void initialize() override; |   void initialize() override; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| //-----------   ILI9341_24_TFT display --------------
 | //-----------   M5Stack display --------------
 | ||||||
| class ILI9341TFT24 : public ILI9341Display { | class ILI9XXXM5CORE : public ILI9XXXDisplay { | ||||||
|  public: |  protected: | ||||||
|   void initialize() override; |   void initialize() override; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| //-----------   ILI9341_24_TFT rotated display --------------
 | //-----------   ILI9XXX_24_TFT display --------------
 | ||||||
| class ILI9341TFT24R : public ILI9341Display { | class ILI9XXXILI9341 : public ILI9XXXDisplay { | ||||||
|  public: |  protected: | ||||||
|   void initialize() override; |   void initialize() override; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| }  // namespace ili9341
 | //-----------   ILI9XXX_24_TFT rotated display --------------
 | ||||||
|  | class ILI9XXXILI9342 : public ILI9XXXDisplay { | ||||||
|  |  protected: | ||||||
|  |   void initialize() override; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | //-----------   ILI9XXX_??_TFT rotated display --------------
 | ||||||
|  | class ILI9XXXILI9481 : public ILI9XXXDisplay { | ||||||
|  |  protected: | ||||||
|  |   void initialize() override; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | //-----------   ILI9XXX_35_TFT rotated display --------------
 | ||||||
|  | class ILI9XXXILI9486 : public ILI9XXXDisplay { | ||||||
|  |  protected: | ||||||
|  |   void initialize() override; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | //-----------   ILI9XXX_35_TFT rotated display --------------
 | ||||||
|  | class ILI9XXXILI9488 : public ILI9XXXDisplay { | ||||||
|  |  protected: | ||||||
|  |   void initialize() override; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | //-----------   ILI9XXX_35_TFT rotated display --------------
 | ||||||
|  | class ILI9XXXST7796 : public ILI9XXXDisplay { | ||||||
|  |  protected: | ||||||
|  |   void initialize() override; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | }  // namespace ili9xxx
 | ||||||
| }  // namespace esphome
 | }  // namespace esphome
 | ||||||
							
								
								
									
										174
									
								
								esphome/components/ili9xxx/ili9xxx_init.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								esphome/components/ili9xxx/ili9xxx_init.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,174 @@ | |||||||
|  | #pragma once | ||||||
|  | #include "esphome/core/helpers.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace ili9xxx { | ||||||
|  |  | ||||||
|  | // clang-format off | ||||||
|  | static const uint8_t PROGMEM INITCMD_M5STACK[] = { | ||||||
|  |   0xEF, 3, 0x03, 0x80, 0x02, | ||||||
|  |   0xCF, 3, 0x00, 0xC1, 0x30, | ||||||
|  |   0xED, 4, 0x64, 0x03, 0x12, 0x81, | ||||||
|  |   0xE8, 3, 0x85, 0x00, 0x78, | ||||||
|  |   0xCB, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, | ||||||
|  |   0xF7, 1, 0x20, | ||||||
|  |   0xEA, 2, 0x00, 0x00, | ||||||
|  |   ILI9XXX_PWCTR1  , 1, 0x23,             // Power control VRH[5:0] | ||||||
|  |   ILI9XXX_PWCTR2  , 1, 0x10,             // Power control SAP[2:0];BT[3:0] | ||||||
|  |   ILI9XXX_VMCTR1  , 2, 0x3e, 0x28,       // VCM control | ||||||
|  |   ILI9XXX_VMCTR2  , 1, 0x86,             // VCM control2 | ||||||
|  |   ILI9XXX_MADCTL  , 1, MADCTL_BGR,       // Memory Access Control | ||||||
|  |   ILI9XXX_VSCRSADD, 1, 0x00,             // Vertical scroll zero | ||||||
|  |   ILI9XXX_PIXFMT  , 1, 0x55, | ||||||
|  |   ILI9XXX_FRMCTR1 , 2, 0x00, 0x13, | ||||||
|  |   ILI9XXX_DFUNCTR , 3, 0x08, 0x82, 0x27, // Display Function Control | ||||||
|  |   0xF2, 1, 0x00,                         // 3Gamma Function Disable | ||||||
|  |   ILI9XXX_GAMMASET , 1, 0x01,             // Gamma curve selected | ||||||
|  |   ILI9XXX_GMCTRP1 , 15, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, // Set Gamma | ||||||
|  |                         0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, | ||||||
|  |                         0x0E, 0x09, 0x00, | ||||||
|  |   ILI9XXX_GMCTRN1 , 15, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, // Set Gamma | ||||||
|  |                         0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, | ||||||
|  |                         0x31, 0x36, 0x0F, | ||||||
|  |   ILI9XXX_SLPOUT  , 0x80,                // Exit Sleep | ||||||
|  |   ILI9XXX_DISPON  , 0x80,                // Display on | ||||||
|  |   0x00                                   // End of list | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const uint8_t PROGMEM INITCMD_M5CORE[] = { | ||||||
|  |   ILI9XXX_SETEXTC, 3, 0xFF,0x93,0x42,   // Turn on the external command | ||||||
|  |   ILI9XXX_PWCTR1 , 2, 0x12, 0x12, | ||||||
|  |   ILI9XXX_PWCTR2 , 1, 0x03, | ||||||
|  |   ILI9XXX_VMCTR1 , 1, 0xF2, | ||||||
|  |   ILI9XXX_IFMODE , 1, 0xE0, | ||||||
|  |   0xF6           , 3, 0x01, 0x00, 0x00, | ||||||
|  |   ILI9XXX_GMCTRP1,15, 0x00,0x0C,0x11,0x04,0x11,0x08,0x37,0x89,0x4C,0x06,0x0C,0x0A,0x2E,0x34,0x0F, | ||||||
|  |   ILI9XXX_GMCTRN1,15, 0x00,0x0B,0x11,0x05,0x13,0x09,0x33,0x67,0x48,0x07,0x0E,0x0B,0x2E,0x33,0x0F, | ||||||
|  |   ILI9XXX_DFUNCTR, 4, 0x08,0x82,0x1D,0x04, | ||||||
|  |   ILI9XXX_IDMOFF , 0, | ||||||
|  |   ILI9XXX_DISPON , 0x80,                // Display on | ||||||
|  |   ILI9XXX_SLPOUT , 0x80,                // Exit Sleep | ||||||
|  |  | ||||||
|  |   0x00                                   // End of list | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static const uint8_t PROGMEM INITCMD_ILI9341[] = { | ||||||
|  |   0xEF, 3, 0x03, 0x80, 0x02, | ||||||
|  |   0xCF, 3, 0x00, 0xC1, 0x30, | ||||||
|  |   0xED, 4, 0x64, 0x03, 0x12, 0x81, | ||||||
|  |   0xE8, 3, 0x85, 0x00, 0x78, | ||||||
|  |   0xCB, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, | ||||||
|  |   0xF7, 1, 0x20, | ||||||
|  |   0xEA, 2, 0x00, 0x00, | ||||||
|  |   ILI9XXX_PWCTR1  , 1, 0x23,             // Power control VRH[5:0] | ||||||
|  |   ILI9XXX_PWCTR2  , 1, 0x10,             // Power control SAP[2:0];BT[3:0] | ||||||
|  |   ILI9XXX_VMCTR1  , 2, 0x3e, 0x28,       // VCM control | ||||||
|  |   ILI9XXX_VMCTR2  , 1, 0x86,             // VCM control2 | ||||||
|  |   ILI9XXX_MADCTL  , 1, 0x48,             // Memory Access Control | ||||||
|  |   ILI9XXX_VSCRSADD, 1, 0x00,             // Vertical scroll zero | ||||||
|  |   ILI9XXX_PIXFMT  , 1, 0x55, | ||||||
|  |   ILI9XXX_FRMCTR1 , 2, 0x00, 0x18, | ||||||
|  |   ILI9XXX_DFUNCTR , 3, 0x08, 0x82, 0x27, // Display Function Control | ||||||
|  |   0xF2, 1, 0x00,                         // 3Gamma Function Disable | ||||||
|  |   ILI9XXX_GAMMASET , 1, 0x01,             // Gamma curve selected | ||||||
|  |   ILI9XXX_GMCTRP1 , 15, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, // Set Gamma | ||||||
|  |                         0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, | ||||||
|  |                         0x0E, 0x09, 0x00, | ||||||
|  |   ILI9XXX_GMCTRN1 , 15, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, // Set Gamma | ||||||
|  |                         0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, | ||||||
|  |                         0x31, 0x36, 0x0F, | ||||||
|  |   ILI9XXX_SLPOUT  , 0x80,                // Exit Sleep | ||||||
|  |   ILI9XXX_DISPON  , 0x80,                // Display on | ||||||
|  |   0x00                                   // End of list | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const uint8_t PROGMEM INITCMD_ILI9481[] = { | ||||||
|  |   ILI9XXX_SLPOUT ,  0x80,    // Exit sleep mode | ||||||
|  |   ILI9XXX_PWSET  , 3, 0x07, 0x41, 0x1D, | ||||||
|  |   ILI9XXX_VMCTR  , 3, 0x00, 0x1C, 0x1F, | ||||||
|  |   ILI9XXX_PWSETN , 2, 0x01, 0x11, | ||||||
|  |   ILI9XXX_PWCTR1 , 5, 0x10, 0x3B, 0x00, 0x02, 0x11, | ||||||
|  |   ILI9XXX_VMCTR1 , 1, 0x03, | ||||||
|  |   ILI9XXX_IFCTR  , 1, 0x83, | ||||||
|  |   ILI9XXX_GMCTR  ,12, 0x00, 0x26, 0x21, 0x00, 0x00, 0x1F, 0x65, 0x23, 0x77, 0x00, 0x0F, 0x00, | ||||||
|  |   ILI9XXX_IFMODE , 1, 0x00,  // CommandAccessProtect | ||||||
|  |   0xE4        , 1, 0xA0, | ||||||
|  |   ILI9XXX_CSCON , 1, 0x01, | ||||||
|  |   ILI9XXX_DISPON, 0x80,     // Set display on | ||||||
|  |   0x00 // end | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const uint8_t PROGMEM INITCMD_ILI9486[] = { | ||||||
|  |   ILI9XXX_SLPOUT, 0x80, | ||||||
|  |   ILI9XXX_PIXFMT, 1, 0x55, | ||||||
|  |   ILI9XXX_PWCTR3, 1, 0x44, | ||||||
|  |   ILI9XXX_VMCTR1, 4, 0x00, 0x00, 0x00, 0x00, | ||||||
|  |   ILI9XXX_GMCTRP1, 15, 0x0f,0x1f,0x1c,0x0c,0x0f,0x08,0x48,0x98,0x37,0x0a,0x13,0x04,0x11,0x0d,0x00, | ||||||
|  |   ILI9XXX_GMCTRN1, 15, 0x0f,0x32,0x2e,0x0b,0x0d,0x05,0x47,0x75,0x37,0x06,0x10,0x03,0x24,0x20,0x00, | ||||||
|  |   ILI9XXX_INVOFF, 0x80, | ||||||
|  |   ILI9XXX_MADCTL, 1, 0x48, | ||||||
|  |   ILI9XXX_DISPON, 0x80, | ||||||
|  |  | ||||||
|  |   // ILI9XXX_MADCTL, 1, MADCTL_BGR | MADCTL_MV, //hardware rotation | ||||||
|  |   0x00                                   // End of list | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const uint8_t PROGMEM INITCMD_ILI9488[] = { | ||||||
|  |   ILI9XXX_GMCTRP1,15, 0x00, 0x03, 0x09, 0x08, 0x16, 0x0A, 0x3F, 0x78, 0x4C, 0x09, 0x0A, 0x08, 0x16, 0x1A, 0x0F, | ||||||
|  |   ILI9XXX_GMCTRN1,15, 0x00, 0x16, 0x19, 0x03, 0x0F, 0x05, 0x32, 0x45, 0x46, 0x04, 0x0E, 0x0D, 0x35, 0x37, 0x0F, | ||||||
|  |  | ||||||
|  |   ILI9XXX_PWCTR1,  2, 0x17, 0x15,  // VRH1 VRH2 | ||||||
|  |   ILI9XXX_PWCTR2,  1, 0x41,  // VGH, VGL | ||||||
|  |   ILI9XXX_VMCTR1,  3, 0x00, 0x12, 0x80,    // nVM VCM_REG VCM_REG_EN | ||||||
|  |  | ||||||
|  |   ILI9XXX_IFMODE,  1, 0x00, | ||||||
|  |   ILI9XXX_FRMCTR1, 1, 0xA0,  // Frame rate = 60Hz | ||||||
|  |   ILI9XXX_INVCTR,  1, 0x02,  // Display Inversion Control = 2dot | ||||||
|  |  | ||||||
|  |   ILI9XXX_DFUNCTR, 2, 0x02, 0x02, // Nomal scan | ||||||
|  |  | ||||||
|  |   0xE9, 1, 0x00,   // Set Image Functio. Disable 24 bit data | ||||||
|  |  | ||||||
|  |   ILI9XXX_ADJCTL3, 4, 0xA9, 0x51, 0x2C, 0x82,  // Adjust Control 3 | ||||||
|  |  | ||||||
|  |   ILI9XXX_MADCTL,  1, 0x28, | ||||||
|  |   //ILI9XXX_PIXFMT,  1, 0x55,  // Interface Pixel Format = 16bit | ||||||
|  |   ILI9XXX_PIXFMT, 1, 0x66,   //ILI9488 only supports 18-bit pixel format in 4/3 wire SPI mode | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   // 5 frames | ||||||
|  |   //ILI9XXX_ETMOD,   1, 0xC6,  // | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   ILI9XXX_SLPOUT,  0x80,    // Exit sleep mode | ||||||
|  |   //ILI9XXX_INVON  , 0, | ||||||
|  |   ILI9XXX_DISPON,  0x80,    // Set display on | ||||||
|  |   0x00 // end | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const uint8_t PROGMEM INITCMD_ST7796[] = { | ||||||
|  |   // This ST7796S initilization routine was copied from https://github.com/prenticedavid/Adafruit_ST7796S_kbv/blob/master/Adafruit_ST7796S_kbv.cpp | ||||||
|  |   ILI9XXX_SWRESET, 0x80,         // Soft reset, then delay 150 ms | ||||||
|  |   ILI9XXX_CSCON, 1, 0xC3,              // ?? Unlock Manufacturer | ||||||
|  |   ILI9XXX_CSCON, 1, 0x96, | ||||||
|  |   ILI9XXX_VMCTR1, 1, 0x1C,              //VCOM  Control 1 [1C] | ||||||
|  |   ILI9XXX_MADCTL, 1, 0x48,              //Memory Access [00] | ||||||
|  |   ILI9XXX_PIXFMT, 1, 0x55,              //565 | ||||||
|  |   ILI9XXX_IFMODE, 1, 0x80,              //Interface     [00] | ||||||
|  |   ILI9XXX_INVCTR, 1, 0x01,              //Inversion Control [01] | ||||||
|  |   ILI9XXX_DFUNCTR, 3, 0x80, 0x02, 0x3B,  // Display Function Control [80 02 3B] .kbv SS=1, NL=480 | ||||||
|  |   ILI9XXX_ETMOD, 1, 0xC6,              //Entry Mode      [06] | ||||||
|  |  | ||||||
|  |   ILI9XXX_CSCON, 1, 0x69,              //?? lock manufacturer commands | ||||||
|  |   ILI9XXX_CSCON, 1, 0x3C,              // | ||||||
|  |   ILI9XXX_SLPOUT, 0x80, // Exit Sleep, then delay 150 ms | ||||||
|  |   ILI9XXX_DISPON, 0x80, // Main screen turn on, delay 150 ms | ||||||
|  |   0x00                                   // End of list | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // clang-format on | ||||||
|  | }  // namespace ili9xxx | ||||||
|  | }  // namespace esphome | ||||||
| @@ -2693,24 +2693,18 @@ display: | |||||||
|     row_start: 0 |     row_start: 0 | ||||||
|     lambda: |- |     lambda: |- | ||||||
|       it.rectangle(0, 0, it.get_width(), it.get_height()); |       it.rectangle(0, 0, it.get_width(), it.get_height()); | ||||||
|   - platform: ili9341 |   - platform: ili9xxx | ||||||
|     model: TFT 2.4 |     model: TFT 2.4 | ||||||
|     cs_pin: GPIO5 |     cs_pin: GPIO5 | ||||||
|     dc_pin: GPIO4 |     dc_pin: GPIO4 | ||||||
|     reset_pin: GPIO22 |     reset_pin: GPIO22 | ||||||
|     led_pin: |  | ||||||
|       number: GPIO15 |  | ||||||
|       inverted: true |  | ||||||
|     lambda: |- |     lambda: |- | ||||||
|       it.rectangle(0, 0, it.get_width(), it.get_height()); |       it.rectangle(0, 0, it.get_width(), it.get_height()); | ||||||
|   - platform: ili9341 |   - platform: ili9xxx | ||||||
|     model: TFT 2.4 |     model: TFT 2.4 | ||||||
|     cs_pin: GPIO5 |     cs_pin: GPIO5 | ||||||
|     dc_pin: GPIO4 |     dc_pin: GPIO4 | ||||||
|     reset_pin: GPIO22 |     reset_pin: GPIO22 | ||||||
|     led_pin: |  | ||||||
|       number: GPIO15 |  | ||||||
|       inverted: true |  | ||||||
|     auto_clear_enabled: false |     auto_clear_enabled: false | ||||||
|     rotation: 90 |     rotation: 90 | ||||||
|     lambda: |- |     lambda: |- | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user