mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Add Lilygo T-Embed to st7789v display config. (#5337)
* Add Lilygo T-Embed to st7789v display config. * Move all configuration into the Python code. Add presets for TTGO. All preset configuration can be overridden. * Add Adafruit S2 pin presets * Add test * Add funhouse pins. Co-authored-by: Keith Burzinski <kbx81x@gmail.com> * Keep ordering of options consistent * Remove unused declarations --------- Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
This commit is contained in:
		| @@ -12,6 +12,8 @@ from esphome.const import ( | ||||
|     CONF_RESET_PIN, | ||||
|     CONF_WIDTH, | ||||
|     CONF_POWER_SUPPLY, | ||||
|     CONF_ROTATION, | ||||
|     CONF_CS_PIN, | ||||
| ) | ||||
| from . import st7789v_ns | ||||
|  | ||||
| @@ -26,48 +28,106 @@ DEPENDENCIES = ["spi"] | ||||
| ST7789V = st7789v_ns.class_( | ||||
|     "ST7789V", cg.PollingComponent, spi.SPIDevice, display.DisplayBuffer | ||||
| ) | ||||
| ST7789VRef = ST7789V.operator("ref") | ||||
| ST7789VModel = st7789v_ns.enum("ST7789VModel") | ||||
|  | ||||
| MODEL_PRESETS = "model_presets" | ||||
| REQUIRE_PS = "require_ps" | ||||
|  | ||||
|  | ||||
| def model_spec(require_ps=False, presets=None): | ||||
|     if presets is None: | ||||
|         presets = {} | ||||
|     return {MODEL_PRESETS: presets, REQUIRE_PS: require_ps} | ||||
|  | ||||
|  | ||||
| MODELS = { | ||||
|     "TTGO_TDISPLAY_135X240": ST7789VModel.ST7789V_MODEL_TTGO_TDISPLAY_135_240, | ||||
|     "ADAFRUIT_FUNHOUSE_240X240": ST7789VModel.ST7789V_MODEL_ADAFRUIT_FUNHOUSE_240_240, | ||||
|     "ADAFRUIT_RR_280X240": ST7789VModel.ST7789V_MODEL_ADAFRUIT_RR_280_240, | ||||
|     "ADAFRUIT_S2_TFT_FEATHER_240X135": ST7789VModel.ST7789V_MODEL_ADAFRUIT_S2_TFT_FEATHER_240_135, | ||||
|     "CUSTOM": ST7789VModel.ST7789V_MODEL_CUSTOM, | ||||
|     "TTGO_TDISPLAY_135X240": model_spec( | ||||
|         presets={ | ||||
|             CONF_HEIGHT: 240, | ||||
|             CONF_WIDTH: 135, | ||||
|             CONF_OFFSET_HEIGHT: 52, | ||||
|             CONF_OFFSET_WIDTH: 40, | ||||
|             CONF_CS_PIN: "GPIO5", | ||||
|             CONF_DC_PIN: "GPIO16", | ||||
|             CONF_RESET_PIN: "GPIO23", | ||||
|             CONF_BACKLIGHT_PIN: "GPIO4", | ||||
|         } | ||||
|     ), | ||||
|     "ADAFRUIT_FUNHOUSE_240X240": model_spec( | ||||
|         presets={ | ||||
|             CONF_HEIGHT: 240, | ||||
|             CONF_WIDTH: 240, | ||||
|             CONF_OFFSET_HEIGHT: 0, | ||||
|             CONF_OFFSET_WIDTH: 0, | ||||
|             CONF_CS_PIN: "GPIO40", | ||||
|             CONF_DC_PIN: "GPIO39", | ||||
|             CONF_RESET_PIN: "GPIO41", | ||||
|         } | ||||
|     ), | ||||
|     "ADAFRUIT_RR_280X240": model_spec( | ||||
|         presets={ | ||||
|             CONF_HEIGHT: 280, | ||||
|             CONF_WIDTH: 240, | ||||
|             CONF_OFFSET_HEIGHT: 0, | ||||
|             CONF_OFFSET_WIDTH: 20, | ||||
|         } | ||||
|     ), | ||||
|     "ADAFRUIT_S2_TFT_FEATHER_240X135": model_spec( | ||||
|         require_ps=True, | ||||
|         presets={ | ||||
|             CONF_HEIGHT: 240, | ||||
|             CONF_WIDTH: 135, | ||||
|             CONF_OFFSET_HEIGHT: 52, | ||||
|             CONF_OFFSET_WIDTH: 40, | ||||
|             CONF_CS_PIN: "GPIO7", | ||||
|             CONF_DC_PIN: "GPIO39", | ||||
|             CONF_RESET_PIN: "GPIO40", | ||||
|             CONF_BACKLIGHT_PIN: "GPIO45", | ||||
|         }, | ||||
|     ), | ||||
|     "LILYGO_T-EMBED_170X320": model_spec( | ||||
|         presets={ | ||||
|             CONF_HEIGHT: 320, | ||||
|             CONF_WIDTH: 170, | ||||
|             CONF_OFFSET_HEIGHT: 35, | ||||
|             CONF_OFFSET_WIDTH: 0, | ||||
|             CONF_ROTATION: 270, | ||||
|             CONF_CS_PIN: "GPIO10", | ||||
|             CONF_DC_PIN: "GPIO13", | ||||
|             CONF_RESET_PIN: "GPIO9", | ||||
|             CONF_BACKLIGHT_PIN: "GPIO15", | ||||
|         } | ||||
|     ), | ||||
|     "CUSTOM": model_spec(), | ||||
| } | ||||
|  | ||||
| ST7789V_MODEL = cv.enum(MODELS, upper=True, space="_") | ||||
|  | ||||
|  | ||||
| def validate_st7789v(config): | ||||
|     if config[CONF_MODEL].upper() == "CUSTOM" and ( | ||||
|         CONF_HEIGHT not in config | ||||
|         or CONF_WIDTH not in config | ||||
|         or CONF_OFFSET_HEIGHT not in config | ||||
|         or CONF_OFFSET_WIDTH not in config | ||||
|     ): | ||||
|         raise cv.Invalid( | ||||
|             f'{CONF_HEIGHT}, {CONF_WIDTH}, {CONF_OFFSET_HEIGHT} and {CONF_OFFSET_WIDTH} must be specified when {CONF_MODEL} is "CUSTOM"' | ||||
|         ) | ||||
|     model_data = MODELS[config[CONF_MODEL]] | ||||
|     presets = model_data[MODEL_PRESETS] | ||||
|     for key, value in presets.items(): | ||||
|         if key not in config: | ||||
|             if key.endswith("pin"): | ||||
|                 # All pins are output. | ||||
|                 value = pins.gpio_output_pin_schema(value) | ||||
|             config[key] = value | ||||
|  | ||||
|     if config[CONF_MODEL].upper() != "CUSTOM" and ( | ||||
|         CONF_HEIGHT in config | ||||
|         or CONF_WIDTH in config | ||||
|         or CONF_OFFSET_HEIGHT in config | ||||
|         or CONF_OFFSET_WIDTH in config | ||||
|     ): | ||||
|     if model_data[REQUIRE_PS] and CONF_POWER_SUPPLY not in config: | ||||
|         raise cv.Invalid( | ||||
|             f'Do not specify {CONF_HEIGHT}, {CONF_WIDTH}, {CONF_OFFSET_HEIGHT} or {CONF_OFFSET_WIDTH} when using {CONF_MODEL} that is not "CUSTOM"' | ||||
|             f'{CONF_POWER_SUPPLY} must be specified when {CONF_MODEL} is {config[CONF_MODEL]}"' | ||||
|         ) | ||||
|  | ||||
|     if ( | ||||
|         config[CONF_MODEL].upper() == "ADAFRUIT_S2_TFT_FEATHER_240X135" | ||||
|         and CONF_POWER_SUPPLY not in config | ||||
|         CONF_OFFSET_WIDTH not in config | ||||
|         or CONF_OFFSET_HEIGHT not in config | ||||
|         or CONF_HEIGHT not in config | ||||
|         or CONF_WIDTH not in config | ||||
|     ): | ||||
|         raise cv.Invalid( | ||||
|             f'{CONF_POWER_SUPPLY} must be specified when {CONF_MODEL} is "ADAFRUIT_S2_TFT_FEATHER_240X135"' | ||||
|             f"{CONF_HEIGHT}, {CONF_WIDTH}, {CONF_OFFSET_HEIGHT} and {CONF_OFFSET_WIDTH} must all be specified" | ||||
|         ) | ||||
|     if CONF_DC_PIN not in config or CONF_RESET_PIN not in config: | ||||
|         raise cv.Invalid(f"both {CONF_DC_PIN} and {CONF_RESET_PIN} must be specified") | ||||
|  | ||||
|     return config | ||||
|  | ||||
|  | ||||
| @@ -75,9 +135,9 @@ CONFIG_SCHEMA = cv.All( | ||||
|     display.FULL_DISPLAY_SCHEMA.extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(ST7789V), | ||||
|             cv.Required(CONF_MODEL): ST7789V_MODEL, | ||||
|             cv.Required(CONF_RESET_PIN): pins.gpio_output_pin_schema, | ||||
|             cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, | ||||
|             cv.Required(CONF_MODEL): cv.one_of(*MODELS.keys(), upper=True, space="_"), | ||||
|             cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, | ||||
|             cv.Optional(CONF_DC_PIN): pins.gpio_output_pin_schema, | ||||
|             cv.Optional(CONF_BACKLIGHT_PIN): pins.gpio_output_pin_schema, | ||||
|             cv.Optional(CONF_POWER_SUPPLY): cv.use_id(power_supply.PowerSupply), | ||||
|             cv.Optional(CONF_EIGHTBITCOLOR, default=False): cv.boolean, | ||||
| @@ -99,9 +159,8 @@ async def to_code(config): | ||||
|     await display.register_display(var, config) | ||||
|     await spi.register_spi_device(var, config) | ||||
|  | ||||
|     cg.add(var.set_model(config[CONF_MODEL])) | ||||
|     cg.add(var.set_model_str(config[CONF_MODEL])) | ||||
|  | ||||
|     if config[CONF_MODEL].upper() == "CUSTOM": | ||||
|     cg.add(var.set_height(config[CONF_HEIGHT])) | ||||
|     cg.add(var.set_width(config[CONF_WIDTH])) | ||||
|     cg.add(var.set_offset_height(config[CONF_OFFSET_HEIGHT])) | ||||
|   | ||||
| @@ -122,11 +122,11 @@ void ST7789V::setup() { | ||||
|  | ||||
| void ST7789V::dump_config() { | ||||
|   LOG_DISPLAY("", "SPI ST7789V", this); | ||||
|   ESP_LOGCONFIG(TAG, "  Model: %s", this->model_str_()); | ||||
|   if (this->model_ == ST7789V_MODEL_CUSTOM) { | ||||
|   ESP_LOGCONFIG(TAG, "  Model: %s", this->model_str_); | ||||
|   ESP_LOGCONFIG(TAG, "  Height: %u", this->height_); | ||||
|   ESP_LOGCONFIG(TAG, "  Width: %u", this->width_); | ||||
|   ESP_LOGCONFIG(TAG, "  Height Offset: %u", this->offset_height_); | ||||
|   ESP_LOGCONFIG(TAG, "  Width Offset: %u", this->offset_width_); | ||||
|   } | ||||
|   ESP_LOGCONFIG(TAG, "  8-bit color mode: %s", YESNO(this->eightbitcolor_)); | ||||
|   LOG_PIN("  CS Pin: ", this->cs_); | ||||
|   LOG_PIN("  DC Pin: ", this->dc_pin_); | ||||
| @@ -145,42 +145,7 @@ void ST7789V::update() { | ||||
|   this->write_display_data(); | ||||
| } | ||||
|  | ||||
| void ST7789V::set_model(ST7789VModel model) { | ||||
|   this->model_ = model; | ||||
|  | ||||
|   switch (this->model_) { | ||||
|     case ST7789V_MODEL_TTGO_TDISPLAY_135_240: | ||||
|       this->height_ = 240; | ||||
|       this->width_ = 135; | ||||
|       this->offset_height_ = 52; | ||||
|       this->offset_width_ = 40; | ||||
|       break; | ||||
|  | ||||
|     case ST7789V_MODEL_ADAFRUIT_FUNHOUSE_240_240: | ||||
|       this->height_ = 240; | ||||
|       this->width_ = 240; | ||||
|       this->offset_height_ = 0; | ||||
|       this->offset_width_ = 0; | ||||
|       break; | ||||
|  | ||||
|     case ST7789V_MODEL_ADAFRUIT_RR_280_240: | ||||
|       this->height_ = 280; | ||||
|       this->width_ = 240; | ||||
|       this->offset_height_ = 0; | ||||
|       this->offset_width_ = 20; | ||||
|       break; | ||||
|  | ||||
|     case ST7789V_MODEL_ADAFRUIT_S2_TFT_FEATHER_240_135: | ||||
|       this->height_ = 240; | ||||
|       this->width_ = 135; | ||||
|       this->offset_height_ = 52; | ||||
|       this->offset_width_ = 40; | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       break; | ||||
|   } | ||||
| } | ||||
| void ST7789V::set_model_str(const char *model_str) { this->model_str_ = model_str; } | ||||
|  | ||||
| void ST7789V::write_display_data() { | ||||
|   uint16_t x1 = this->offset_height_; | ||||
| @@ -339,20 +304,5 @@ void HOT ST7789V::draw_absolute_pixel_internal(int x, int y, Color color) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| const char *ST7789V::model_str_() { | ||||
|   switch (this->model_) { | ||||
|     case ST7789V_MODEL_TTGO_TDISPLAY_135_240: | ||||
|       return "TTGO T-Display 135x240"; | ||||
|     case ST7789V_MODEL_ADAFRUIT_FUNHOUSE_240_240: | ||||
|       return "Adafruit Funhouse 240x240"; | ||||
|     case ST7789V_MODEL_ADAFRUIT_RR_280_240: | ||||
|       return "Adafruit Round-Rectangular 280x240"; | ||||
|     case ST7789V_MODEL_ADAFRUIT_S2_TFT_FEATHER_240_135: | ||||
|       return "Adafruit ESP32-S2 TFT Feather"; | ||||
|     default: | ||||
|       return "Custom"; | ||||
|   } | ||||
| } | ||||
|  | ||||
| }  // namespace st7789v | ||||
| }  // namespace esphome | ||||
|   | ||||
| @@ -10,14 +10,6 @@ | ||||
| namespace esphome { | ||||
| namespace st7789v { | ||||
|  | ||||
| enum ST7789VModel { | ||||
|   ST7789V_MODEL_TTGO_TDISPLAY_135_240, | ||||
|   ST7789V_MODEL_ADAFRUIT_FUNHOUSE_240_240, | ||||
|   ST7789V_MODEL_ADAFRUIT_RR_280_240, | ||||
|   ST7789V_MODEL_ADAFRUIT_S2_TFT_FEATHER_240_135, | ||||
|   ST7789V_MODEL_CUSTOM | ||||
| }; | ||||
|  | ||||
| static const uint8_t ST7789_NOP = 0x00;        // No Operation | ||||
| static const uint8_t ST7789_SWRESET = 0x01;    // Software Reset | ||||
| static const uint8_t ST7789_RDDID = 0x04;      // Read Display ID | ||||
| @@ -120,7 +112,7 @@ class ST7789V : public PollingComponent, | ||||
|                 public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING, | ||||
|                                       spi::DATA_RATE_20MHZ> { | ||||
|  public: | ||||
|   void set_model(ST7789VModel model); | ||||
|   void set_model_str(const char *model_str); | ||||
|   void set_dc_pin(GPIOPin *dc_pin) { this->dc_pin_ = dc_pin; } | ||||
|   void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; } | ||||
|   void set_backlight_pin(GPIOPin *backlight_pin) { this->backlight_pin_ = backlight_pin; } | ||||
| @@ -146,7 +138,6 @@ class ST7789V : public PollingComponent, | ||||
|   display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; } | ||||
|  | ||||
|  protected: | ||||
|   ST7789VModel model_{ST7789V_MODEL_TTGO_TDISPLAY_135_240}; | ||||
|   GPIOPin *dc_pin_{nullptr}; | ||||
|   GPIOPin *reset_pin_{nullptr}; | ||||
|   GPIOPin *backlight_pin_{nullptr}; | ||||
| @@ -175,7 +166,7 @@ class ST7789V : public PollingComponent, | ||||
|  | ||||
|   void draw_absolute_pixel_internal(int x, int y, Color color) override; | ||||
|  | ||||
|   const char *model_str_(); | ||||
|   const char *model_str_; | ||||
| }; | ||||
|  | ||||
| }  // namespace st7789v | ||||
|   | ||||
| @@ -710,6 +710,14 @@ interval: | ||||
|     - logger.log: Interval Run | ||||
|  | ||||
| display: | ||||
|   - platform: st7789v | ||||
|     model: LILYGO_T-EMBED_170X320 | ||||
|     height: 320 | ||||
|     width: 170 | ||||
|     offset_height: 35 | ||||
|     offset_width: 0 | ||||
|     dc_pin: GPIO13 | ||||
|     reset_pin: GPIO9 | ||||
|  | ||||
| image: | ||||
|   - id: binary_image | ||||
|   | ||||
		Reference in New Issue
	
	Block a user