Make per-loop display clearing optional (#2626)

Currently, in each loop during DisplayBuffer::update_() the display is
cleared by calling DisplayBuffer::clear().

This prevents more efficient display usages that do not render the
screen in each loop, but only if necessary. This can be helpful, for
example, if images are rendered. This would cause the loop time to be
exceeded frequently.

This change adds a new optional flag "auto_clear" that can be used to
control the clearing behavior. If unset, the DisplayBuffer defaults to
enabled auto clearing, the current behavior and thus backward compatible.

This flag applies to displays that use DisplayBuffer.

Example excerpt:
globals:
  - id: state
    type: bool
    restore_value: no
    initial_value: "false"
  - id: state_processed
    type: bool
    restore_value: no
    initial_value: "false"

switch:
  - platform: template
    name: "State"
    id: state_switch
    lambda: |-
      return id(state);
    turn_on_action:
      - globals.set:
          id: state
          value: "true"
      - globals.set:
          id: state_processed
          value: "false"
    turn_off_action:
      - globals.set:
          id: state
          value: "false"
      - globals.set:
          id: state_processed
          value: "false"

display:
  - platform: ili9341
    # ...
    auto_clear_enabled: false
    lambda: |-
      if (!id(state_processed)) {
        it.fill(COLOR_WHITE);
        if (id(state)) {
          it.image(80, 20, id(image1));
        } else {
          it.image(80, 20, id(image2));
        }
        id(state_processed) = true;
      }

Co-authored-by: Tim Niemueller <timdn@google.com>
This commit is contained in:
Tim Niemueller 2021-11-03 17:56:09 +01:00 committed by GitHub
parent 379c3e98f5
commit 11f1e28139
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 43 additions and 1 deletions

View file

@ -3,6 +3,7 @@ import esphome.config_validation as cv
from esphome import core, automation from esphome import core, automation
from esphome.automation import maybe_simple_id from esphome.automation import maybe_simple_id
from esphome.const import ( from esphome.const import (
CONF_AUTO_CLEAR_ENABLED,
CONF_ID, CONF_ID,
CONF_LAMBDA, CONF_LAMBDA,
CONF_PAGES, CONF_PAGES,
@ -79,6 +80,7 @@ FULL_DISPLAY_SCHEMA = BASIC_DISPLAY_SCHEMA.extend(
cv.Optional(CONF_TO): cv.use_id(DisplayPage), cv.Optional(CONF_TO): cv.use_id(DisplayPage),
} }
), ),
cv.Optional(CONF_AUTO_CLEAR_ENABLED, default=True): cv.boolean,
} }
) )
@ -86,6 +88,10 @@ FULL_DISPLAY_SCHEMA = BASIC_DISPLAY_SCHEMA.extend(
async def setup_display_core_(var, config): async def setup_display_core_(var, config):
if CONF_ROTATION in config: if CONF_ROTATION in config:
cg.add(var.set_rotation(DISPLAY_ROTATIONS[config[CONF_ROTATION]])) cg.add(var.set_rotation(DISPLAY_ROTATIONS[config[CONF_ROTATION]]))
if CONF_AUTO_CLEAR_ENABLED in config:
cg.add(var.set_auto_clear(config[CONF_AUTO_CLEAR_ENABLED]))
if CONF_PAGES in config: if CONF_PAGES in config:
pages = [] pages = []
for conf in config[CONF_PAGES]: for conf in config[CONF_PAGES]:

View file

@ -336,7 +336,9 @@ void DisplayBuffer::show_page(DisplayPage *page) {
void DisplayBuffer::show_next_page() { this->page_->show_next(); } void DisplayBuffer::show_next_page() { this->page_->show_next(); }
void DisplayBuffer::show_prev_page() { this->page_->show_prev(); } void DisplayBuffer::show_prev_page() { this->page_->show_prev(); }
void DisplayBuffer::do_update_() { void DisplayBuffer::do_update_() {
if (this->auto_clear_enabled_) {
this->clear(); this->clear();
}
if (this->page_ != nullptr) { if (this->page_ != nullptr) {
this->page_->get_writer()(*this); this->page_->get_writer()(*this);
} else if (this->writer_.has_value()) { } else if (this->writer_.has_value()) {

View file

@ -333,6 +333,9 @@ class DisplayBuffer {
/// Internal method to set the display rotation with. /// Internal method to set the display rotation with.
void set_rotation(DisplayRotation rotation); void set_rotation(DisplayRotation rotation);
// Internal method to set display auto clearing.
void set_auto_clear(bool auto_clear_enabled) { this->auto_clear_enabled_ = auto_clear_enabled; }
protected: protected:
void vprintf_(int x, int y, Font *font, Color color, TextAlign align, const char *format, va_list arg); void vprintf_(int x, int y, Font *font, Color color, TextAlign align, const char *format, va_list arg);
@ -352,6 +355,7 @@ class DisplayBuffer {
DisplayPage *page_{nullptr}; DisplayPage *page_{nullptr};
DisplayPage *previous_page_{nullptr}; DisplayPage *previous_page_{nullptr};
std::vector<DisplayOnPageChangeTrigger *> on_page_change_triggers_; std::vector<DisplayOnPageChangeTrigger *> on_page_change_triggers_;
bool auto_clear_enabled_{true};
}; };
class DisplayPage { class DisplayPage {

View file

@ -59,6 +59,7 @@ CONF_AT = "at"
CONF_ATTENUATION = "attenuation" CONF_ATTENUATION = "attenuation"
CONF_ATTRIBUTE = "attribute" CONF_ATTRIBUTE = "attribute"
CONF_AUTH = "auth" CONF_AUTH = "auth"
CONF_AUTO_CLEAR_ENABLED = "auto_clear_enabled"
CONF_AUTO_MODE = "auto_mode" CONF_AUTO_MODE = "auto_mode"
CONF_AUTOCONF = "autoconf" CONF_AUTOCONF = "autoconf"
CONF_AUTOMATION_ID = "automation_id" CONF_AUTOMATION_ID = "automation_id"

View file

@ -2214,6 +2214,31 @@ 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
model: "TFT 2.4"
cs_pin: GPIO5
dc_pin: GPIO4
reset_pin: GPIO22
led_pin:
number: GPIO15
inverted: true
lambda: |-
it.rectangle(0, 0, it.get_width(), it.get_height());
- platform: ili9341
model: "TFT 2.4"
cs_pin: GPIO5
dc_pin: GPIO4
reset_pin: GPIO22
led_pin:
number: GPIO15
inverted: true
auto_clear_enabled: false
rotation: 90
lambda: |-
if (!id(glob_bool_processed)) {
it.fill(Color::WHITE);
id(glob_bool_processed) = true;
}
tm1651: tm1651:
id: tm1651_battery id: tm1651_battery
@ -2393,6 +2418,10 @@ globals:
type: std::string type: std::string
restore_value: no restore_value: no
# initial_value: "" # initial_value: ""
- id: glob_bool_processed
type: bool
restore_value: no
initial_value: 'false'
text_sensor: text_sensor:
- platform: mqtt_subscribe - platform: mqtt_subscribe