From 9816e677a67e16228680fb679a966f1631e44e6c Mon Sep 17 00:00:00 2001 From: Vc <37367415+Valcob@users.noreply.github.com> Date: Mon, 9 Nov 2020 03:53:35 +0200 Subject: [PATCH] add Ili9341 display (#1233) * setup ili9341 framework used epaper-waveshare as start * first version working * added models for now only M5Stack * get_buffer_length is huge * fill, low/high watermark, buffer tests failed. RAM is to small for ili9341 16 bit color mode * removed high/low watermark debug log * added standard 2.4" TFT model * code cleanup * make ledpin optional busy pin is not needed * make bufer 1 byte to avoid the buffer allocation error * gitignore * added backlight pin to dump_config * huge speed increase 8bit color framebuffer (256 colors) lo and high watermark for drawing to screen * fix for images * higher spi data rates * Set spi data rate to 40Mhz Experimental * fixed: formatting fixed: the last row and column being trimmed fixed: namings * Update the code to use Color class * fixed minor color things * fixed linting * #patch minor fixes * fix gitignore too * Update esphome/components/ili9341/ili9341_display.cpp Co-authored-by: Oleg * reverting the changes as it's being fixed in PR-1241 Co-authored-by: Michiel van Turnhout Co-authored-by: Michiel van Turnhout Co-authored-by: Oleg --- .gitignore | 1 + esphome/components/ili9341/__init__.py | 0 esphome/components/ili9341/display.py | 61 +++++ esphome/components/ili9341/ili9341_defines.h | 83 ++++++ .../components/ili9341/ili9341_display.cpp | 240 ++++++++++++++++++ esphome/components/ili9341/ili9341_display.h | 92 +++++++ esphome/components/ili9341/ili9341_init.h | 70 +++++ esphome/components/spi/spi.h | 2 + 8 files changed, 549 insertions(+) create mode 100644 esphome/components/ili9341/__init__.py create mode 100644 esphome/components/ili9341/display.py create mode 100644 esphome/components/ili9341/ili9341_defines.h create mode 100644 esphome/components/ili9341/ili9341_display.cpp create mode 100644 esphome/components/ili9341/ili9341_display.h create mode 100644 esphome/components/ili9341/ili9341_init.h diff --git a/.gitignore b/.gitignore index 11a80a647c..c3f57b15e7 100644 --- a/.gitignore +++ b/.gitignore @@ -119,3 +119,4 @@ config/ tests/build/ tests/.esphome/ /.temp-clang-tidy.cpp +.pio/ diff --git a/esphome/components/ili9341/__init__.py b/esphome/components/ili9341/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/ili9341/display.py b/esphome/components/ili9341/display.py new file mode 100644 index 0000000000..0a3e9e16cc --- /dev/null +++ b/esphome/components/ili9341/display.py @@ -0,0 +1,61 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import pins +from esphome.components import display, spi +from esphome.const import CONF_DC_PIN, \ + CONF_ID, CONF_LAMBDA, CONF_MODEL, CONF_PAGES, CONF_RESET_PIN + +DEPENDENCIES = ['spi'] + +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) + +ILI9341Model = ili9341_ns.enum('ILI9341Model') + +MODELS = { + 'M5STACK': ILI9341Model.M5STACK, + 'TFT_2.4': ILI9341Model.TFT_24, +} + +ILI9341_MODEL = cv.enum(MODELS, upper=True, space="_") + +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, +}).extend(cv.polling_component_schema('1s')).extend(spi.spi_device_schema()), + cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) + + +def to_code(config): + if config[CONF_MODEL] == 'M5STACK': + lcd_type = ILI9341M5Stack + if config[CONF_MODEL] == 'TFT_2.4': + lcd_type = ILI9341TFT24 + rhs = lcd_type.new() + var = cg.Pvariable(config[CONF_ID], rhs) + + yield cg.register_component(var, config) + yield display.register_display(var, config) + yield spi.register_spi_device(var, config) + cg.add(var.set_model(config[CONF_MODEL])) + dc = yield cg.gpio_pin_expression(config[CONF_DC_PIN]) + cg.add(var.set_dc_pin(dc)) + + if CONF_LAMBDA in config: + lambda_ = yield 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 = yield cg.gpio_pin_expression(config[CONF_RESET_PIN]) + cg.add(var.set_reset_pin(reset)) + if CONF_LED_PIN in config: + led_pin = yield cg.gpio_pin_expression(config[CONF_LED_PIN]) + cg.add(var.set_led_pin(led_pin)) diff --git a/esphome/components/ili9341/ili9341_defines.h b/esphome/components/ili9341/ili9341_defines.h new file mode 100644 index 0000000000..6b3d4c0dcf --- /dev/null +++ b/esphome/components/ili9341/ili9341_defines.h @@ -0,0 +1,83 @@ +#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 diff --git a/esphome/components/ili9341/ili9341_display.cpp b/esphome/components/ili9341/ili9341_display.cpp new file mode 100644 index 0000000000..c0e7873284 --- /dev/null +++ b/esphome/components/ili9341/ili9341_display.cpp @@ -0,0 +1,240 @@ +#include "ili9341_display.h" +#include "esphome/core/log.h" +#include "esphome/core/application.h" +#include "esphome/core/helpers.h" + +namespace esphome { +namespace ili9341 { + +static const char *TAG = "ili9341"; + +void ILI9341Display::setup_pins_() { + this->init_internal_(this->get_buffer_length_()); + this->dc_pin_->setup(); // OUTPUT + this->dc_pin_->digital_write(false); + if (this->reset_pin_ != nullptr) { + 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); + ESP_LOGCONFIG(TAG, " Width: %d, Height: %d, Rotation: %d", this->width_, this->height_, this->rotation_); + LOG_PIN(" Reset Pin: ", this->reset_pin_); + LOG_PIN(" DC Pin: ", this->dc_pin_); + LOG_PIN(" Busy Pin: ", this->busy_pin_); + LOG_PIN(" Backlight Pin: ", this->led_pin_); + LOG_UPDATE_INTERVAL(this); +} + +float ILI9341Display::get_setup_priority() const { return setup_priority::PROCESSOR; } +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 + int w = this->x_high_ - this->x_low_ + 1; + int h = this->y_high_ - this->y_low_ + 1; + + set_addr_window_(this->x_low_, this->y_low_, w, h); + this->start_data_(); + uint32_t start_pos = ((this->y_low_ * this->width_) + x_low_); + for (uint16_t row = 0; row < h; row++) { + for (uint16_t col = 0; col < w; col++) { + uint32_t pos = start_pos + (row * width_) + col; + + uint16_t color = convert_to_16bit_color_(buffer_[pos]); + this->write_byte(color >> 8); + this->write_byte(color); + } + } + this->end_data_(); + + // invalidate watermarks + this->x_low_ = this->width_; + this->y_low_ = this->height_; + this->x_high_ = 0; + this->y_high_ = 0; +} + +uint16_t ILI9341Display::convert_to_16bit_color_(uint8_t color_8bit) { + int r = color_8bit >> 5; + int g = (color_8bit >> 2) & 0x07; + int b = color_8bit & 0x03; + uint16_t color = (r * 0x04) << 11; + color |= (g * 0x09) << 5; + color |= (b * 0x0A); + + return color; +} + +uint8_t ILI9341Display::convert_to_8bit_color_(uint16_t color_16bit) { + // convert 16bit color to 8 bit buffer + uint8_t r = color_16bit >> 11; + uint8_t g = (color_16bit >> 5) & 0x3F; + uint8_t b = color_16bit & 0x1F; + + return ((b / 0x0A) | ((g / 0x09) << 2) | ((r / 0x04) << 5)); +} + +void ILI9341Display::fill(Color color) { + auto color565 = color.to_rgb_565(); + memset(this->buffer_, convert_to_8bit_color_(color565), 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_(Color color) { + this->set_addr_window_(0, 0, this->get_width_internal(), this->get_height_internal()); + this->start_data_(); + + auto color565 = color.to_rgb_565(); + for (uint32_t i = 0; i < (this->get_width_internal()) * (this->get_height_internal()); i++) { + this->write_byte(color565 >> 8); + this->write_byte(color565); + buffer_[i] = 0; + } + this->end_data_(); +} + +void HOT ILI9341Display::draw_absolute_pixel_internal(int x, int y, Color color) { + if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0) + return; + + // low and high watermark may speed up drawing from buffer + this->x_low_ = (x < this->x_low_) ? x : this->x_low_; + this->y_low_ = (y < this->y_low_) ? y : this->y_low_; + this->x_high_ = (x > this->x_high_) ? x : this->x_high_; + this->y_high_ = (y > this->y_high_) ? y : this->y_high_; + + uint32_t pos = (y * width_) + x; + auto color565 = color.to_rgb_565(); + buffer_[pos] = convert_to_8bit_color_(color565); +} + +// 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 = pgm_read_byte(addr++)) > 0) { + x = pgm_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_; } + +// M5Stack display +void ILI9341M5Stack::initialize() { + this->init_lcd_(INITCMD_M5STACK); + this->width_ = 320; + this->height_ = 240; + this->invert_display_(true); + this->fill_internal_(COLOR_BLACK); +} + +// 24_TFT display +void ILI9341TFT24::initialize() { + this->init_lcd_(INITCMD_TFT); + this->width_ = 240; + this->height_ = 320; + this->fill_internal_(COLOR_BLACK); +} + +} // namespace ili9341 +} // namespace esphome diff --git a/esphome/components/ili9341/ili9341_display.h b/esphome/components/ili9341/ili9341_display.h new file mode 100644 index 0000000000..2b6ecc6871 --- /dev/null +++ b/esphome/components/ili9341/ili9341_display.h @@ -0,0 +1,92 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/spi/spi.h" +#include "esphome/components/display/display_buffer.h" +#include "ili9341_defines.h" +#include "ili9341_init.h" + +namespace esphome { +namespace ili9341 { + +enum ILI9341Model { + M5STACK = 0, + TFT_24, +}; + +class ILI9341Display : public PollingComponent, + public display::DisplayBuffer, + public spi::SPIDevice { + public: + void set_dc_pin(GPIOPin *dc_pin) { dc_pin_ = dc_pin; } + float get_setup_priority() const override; + 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 command(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); + uint8_t read_command(uint8_t command_byte, uint8_t index); + virtual void initialize() = 0; + + void update() override; + + void fill(Color color) override; + + void dump_config() override; + void setup() override { + this->setup_pins_(); + this->initialize(); + } + + protected: + void draw_absolute_pixel_internal(int x, int y, Color color) override; + void setup_pins_(); + + 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 invert_display_(bool invert); + void reset_(); + void fill_internal_(Color color); + void display_(); + uint16_t convert_to_16bit_color_(uint8_t color_8bit); + uint8_t convert_to_8bit_color_(uint16_t color_16bit); + + ILI9341Model model_; + int16_t width_{320}; ///< Display width as modified by current rotation + int16_t height_{240}; ///< Display height as modified by current rotation + uint16_t x_low_{0}; + uint16_t y_low_{0}; + uint16_t x_high_{0}; + uint16_t y_high_{0}; + + uint32_t get_buffer_length_(); + int get_width_internal() override; + int get_height_internal() override; + + void start_command_(); + void end_command_(); + void start_data_(); + void end_data_(); + + GPIOPin *reset_pin_{nullptr}; + GPIOPin *led_pin_{nullptr}; + GPIOPin *dc_pin_; + GPIOPin *busy_pin_{nullptr}; +}; + +//----------- M5Stack display -------------- +class ILI9341M5Stack : public ILI9341Display { + public: + void initialize() override; +}; + +//----------- ILI9341_24_TFT display -------------- +class ILI9341TFT24 : public ILI9341Display { + public: + void initialize() override; +}; +} // namespace ili9341 +} // namespace esphome diff --git a/esphome/components/ili9341/ili9341_init.h b/esphome/components/ili9341/ili9341_init.h new file mode 100644 index 0000000000..9282895e2e --- /dev/null +++ b/esphome/components/ili9341/ili9341_init.h @@ -0,0 +1,70 @@ +#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 diff --git a/esphome/components/spi/spi.h b/esphome/components/spi/spi.h index ba726f8052..986f85a13b 100644 --- a/esphome/components/spi/spi.h +++ b/esphome/components/spi/spi.h @@ -55,6 +55,8 @@ enum SPIDataRate : uint32_t { DATA_RATE_2MHZ = 2000000, DATA_RATE_4MHZ = 4000000, DATA_RATE_8MHZ = 8000000, + DATA_RATE_20MHZ = 20000000, + DATA_RATE_40MHZ = 40000000, }; class SPIComponent : public Component {