From 30a542e76347880ca77321b2d0480980dc90d630 Mon Sep 17 00:00:00 2001 From: Attila Darazs Date: Mon, 3 Jun 2019 19:36:00 +0200 Subject: [PATCH] Add backlight handling for lcd_pcf8574 (#573) * Add backlight handling for lcd_pcf8574 Switch the backlight on or off by calling id(mydisplay).backlight() or id(mydisplay).no_backlight() in lamda functions (assuming mydisplay is the custom id for the LCD). * Use abstract method Co-authored-by: Attila Darazs Co-authored-by: Otto Winter --- esphome/components/lcd_base/__init__.py | 8 +------- esphome/components/lcd_base/lcd_display.cpp | 2 +- esphome/components/lcd_base/lcd_display.h | 5 +---- esphome/components/lcd_gpio/display.py | 9 ++++++++- esphome/components/lcd_gpio/gpio_lcd_display.h | 4 ++++ esphome/components/lcd_pcf8574/display.py | 8 +++++++- .../components/lcd_pcf8574/pcf8574_display.cpp | 16 ++++++++++++++-- esphome/components/lcd_pcf8574/pcf8574_display.h | 9 +++++++++ 8 files changed, 45 insertions(+), 16 deletions(-) diff --git a/esphome/components/lcd_base/__init__.py b/esphome/components/lcd_base/__init__.py index 27f65f9336..bff194578c 100644 --- a/esphome/components/lcd_base/__init__.py +++ b/esphome/components/lcd_base/__init__.py @@ -1,12 +1,11 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import display -from esphome.const import CONF_DIMENSIONS, CONF_LAMBDA +from esphome.const import CONF_DIMENSIONS from esphome.core import coroutine lcd_base_ns = cg.esphome_ns.namespace('lcd_base') LCDDisplay = lcd_base_ns.class_('LCDDisplay', cg.PollingComponent) -LCDDisplayRef = LCDDisplay.operator('ref') def validate_lcd_dimensions(value): @@ -28,8 +27,3 @@ def setup_lcd_display(var, config): yield cg.register_component(var, config) yield display.register_display(var, config) cg.add(var.set_dimensions(config[CONF_DIMENSIONS][0], config[CONF_DIMENSIONS][1])) - - if CONF_LAMBDA in config: - lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], [(LCDDisplayRef, 'it')], - return_type=cg.void) - cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/lcd_base/lcd_display.cpp b/esphome/components/lcd_base/lcd_display.cpp index af6b8304eb..51541049b1 100644 --- a/esphome/components/lcd_base/lcd_display.cpp +++ b/esphome/components/lcd_base/lcd_display.cpp @@ -107,7 +107,7 @@ void LCDDisplay::update() { for (uint8_t i = 0; i < this->rows_ * this->columns_; i++) this->buffer_[i] = ' '; - this->writer_(*this); + this->call_writer(); this->display(); } void LCDDisplay::command_(uint8_t value) { this->send(value, false); } diff --git a/esphome/components/lcd_base/lcd_display.h b/esphome/components/lcd_base/lcd_display.h index 200600eb9c..791f31ace3 100644 --- a/esphome/components/lcd_base/lcd_display.h +++ b/esphome/components/lcd_base/lcd_display.h @@ -12,11 +12,8 @@ namespace lcd_base { class LCDDisplay; -using lcd_writer_t = std::function; - class LCDDisplay : public PollingComponent { public: - void set_writer(lcd_writer_t &&writer) { this->writer_ = std::move(writer); } void set_dimensions(uint8_t columns, uint8_t rows) { this->columns_ = columns; this->rows_ = rows; @@ -54,11 +51,11 @@ class LCDDisplay : public PollingComponent { virtual void send(uint8_t value, bool rs) = 0; void command_(uint8_t value); + virtual void call_writer() = 0; uint8_t columns_; uint8_t rows_; uint8_t *buffer_{nullptr}; - lcd_writer_t writer_; }; } // namespace lcd_base diff --git a/esphome/components/lcd_gpio/display.py b/esphome/components/lcd_gpio/display.py index 1f98955ece..91498d59c9 100644 --- a/esphome/components/lcd_gpio/display.py +++ b/esphome/components/lcd_gpio/display.py @@ -2,7 +2,8 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import lcd_base -from esphome.const import CONF_DATA_PINS, CONF_ENABLE_PIN, CONF_RS_PIN, CONF_RW_PIN, CONF_ID +from esphome.const import CONF_DATA_PINS, CONF_ENABLE_PIN, CONF_RS_PIN, CONF_RW_PIN, CONF_ID, \ + CONF_LAMBDA AUTO_LOAD = ['lcd_base'] @@ -42,3 +43,9 @@ def to_code(config): if CONF_RW_PIN in config: rw = yield cg.gpio_pin_expression(config[CONF_RW_PIN]) cg.add(var.set_rw_pin(rw)) + + if CONF_LAMBDA in config: + lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], + [(GPIOLCDDisplay.operator('ref'), 'it')], + return_type=cg.void) + cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/lcd_gpio/gpio_lcd_display.h b/esphome/components/lcd_gpio/gpio_lcd_display.h index ed3b0c1137..01f6f95d9a 100644 --- a/esphome/components/lcd_gpio/gpio_lcd_display.h +++ b/esphome/components/lcd_gpio/gpio_lcd_display.h @@ -8,6 +8,7 @@ namespace lcd_gpio { class GPIOLCDDisplay : public lcd_base::LCDDisplay { public: + void set_writer(std::function &&writer) { this->writer_ = std::move(writer); } void setup() override; void set_data_pins(GPIOPin *d0, GPIOPin *d1, GPIOPin *d2, GPIOPin *d3) { this->data_pins_[0] = d0; @@ -36,10 +37,13 @@ class GPIOLCDDisplay : public lcd_base::LCDDisplay { void write_n_bits(uint8_t value, uint8_t n) override; void send(uint8_t value, bool rs) override; + void call_writer() override { this->writer_(*this); } + GPIOPin *rs_pin_{nullptr}; GPIOPin *rw_pin_{nullptr}; GPIOPin *enable_pin_{nullptr}; GPIOPin *data_pins_[8]{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; + std::function writer_; }; } // namespace lcd_gpio diff --git a/esphome/components/lcd_pcf8574/display.py b/esphome/components/lcd_pcf8574/display.py index 2bc04a283f..2bbb3a2f7b 100644 --- a/esphome/components/lcd_pcf8574/display.py +++ b/esphome/components/lcd_pcf8574/display.py @@ -1,7 +1,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import lcd_base, i2c -from esphome.const import CONF_ID +from esphome.const import CONF_ID, CONF_LAMBDA DEPENDENCIES = ['i2c'] AUTO_LOAD = ['lcd_base'] @@ -18,3 +18,9 @@ def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) yield lcd_base.setup_lcd_display(var, config) yield i2c.register_i2c_device(var, config) + + if CONF_LAMBDA in config: + lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], + [(PCF8574LCDDisplay.operator('ref'), 'it')], + return_type=cg.void) + cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/lcd_pcf8574/pcf8574_display.cpp b/esphome/components/lcd_pcf8574/pcf8574_display.cpp index 59491c7d5a..e3002da25d 100644 --- a/esphome/components/lcd_pcf8574/pcf8574_display.cpp +++ b/esphome/components/lcd_pcf8574/pcf8574_display.cpp @@ -6,9 +6,13 @@ namespace lcd_pcf8574 { static const char *TAG = "lcd_pcf8574"; +static const uint8_t LCD_DISPLAY_BACKLIGHT_ON = 0x08; +static const uint8_t LCD_DISPLAY_BACKLIGHT_OFF = 0x00; + void PCF8574LCDDisplay::setup() { ESP_LOGCONFIG(TAG, "Setting up PCF8574 LCD Display..."); - if (!this->write_bytes(0x08, nullptr, 0)) { + this->backlight_value_ = LCD_DISPLAY_BACKLIGHT_ON; + if (!this->write_bytes(this->backlight_value_, nullptr, 0)) { this->mark_failed(); return; } @@ -29,7 +33,7 @@ void PCF8574LCDDisplay::write_n_bits(uint8_t value, uint8_t n) { // Ugly fix: in the super setup() with n == 4 value needs to be shifted left value <<= 4; } - uint8_t data = value | 0x08; // Enable backlight + uint8_t data = value | this->backlight_value_; // Set backlight state this->write_bytes(data, nullptr, 0); // Pulse ENABLE this->write_bytes(data | 0x04, nullptr, 0); @@ -41,6 +45,14 @@ void PCF8574LCDDisplay::send(uint8_t value, bool rs) { this->write_n_bits((value & 0xF0) | rs, 0); this->write_n_bits(((value << 4) & 0xF0) | rs, 0); } +void PCF8574LCDDisplay::backlight() { + this->backlight_value_ = LCD_DISPLAY_BACKLIGHT_ON; + this->write_bytes(this->backlight_value_, nullptr, 0); +} +void PCF8574LCDDisplay::no_backlight() { + this->backlight_value_ = LCD_DISPLAY_BACKLIGHT_OFF; + this->write_bytes(this->backlight_value_, nullptr, 0); +} } // namespace lcd_pcf8574 } // namespace esphome diff --git a/esphome/components/lcd_pcf8574/pcf8574_display.h b/esphome/components/lcd_pcf8574/pcf8574_display.h index 133679c501..4db3afb9b0 100644 --- a/esphome/components/lcd_pcf8574/pcf8574_display.h +++ b/esphome/components/lcd_pcf8574/pcf8574_display.h @@ -9,13 +9,22 @@ namespace lcd_pcf8574 { class PCF8574LCDDisplay : public lcd_base::LCDDisplay, public i2c::I2CDevice { public: + void set_writer(std::function &&writer) { this->writer_ = std::move(writer); } void setup() override; void dump_config() override; + void backlight(); + void no_backlight(); protected: bool is_four_bit_mode() override { return true; } void write_n_bits(uint8_t value, uint8_t n) override; void send(uint8_t value, bool rs) override; + + void call_writer() override { this->writer_(*this); } + + // Stores the current state of the backlight. + uint8_t backlight_value_; + std::function writer_; }; } // namespace lcd_pcf8574