diff --git a/components/ht16k33_7segment/README.md b/components/ht16k33_7segment/README.md new file mode 100644 index 00000000..877155f4 --- /dev/null +++ b/components/ht16k33_7segment/README.md @@ -0,0 +1,50 @@ +# HT16K33 4 character 7-segment display + +This component supports the 4 character (plus colon) 7 segment character display. + +> :warning: If using this component as an external component, you need to include both `ht16k33_7segment` **and** `ht16k33_base` components. +```yaml +external_components: + source: github://ssieb/custom_components/ + components: [ ht16k33_base, ht16k33_7segment ] +``` + +There are no print functions for addressing rows and columns. With such a small display I didn't see any point. +All the print functions without the row and column parameters are available. +A "." will get added to the previous character as the decimal point. +All the same parameters for the i2c display can be used other than the dimensions. +There are also lambda functions `get_brightness` and `set_brightness` for adjusting the brightness of the display. +You can extend the display across multiple units. + +The colon in the middle of the display will be lit if the print string contains a ":" at the 3rd position (e.g. 12:34). + +Example: +```yaml +i2c: + sda: D0 + scl: D1 + +display: + - platform: ht16k33_7segment + address: 0x70 + scroll: true + scroll_speed: 250ms + scroll_dwell: 2s + scroll_delay: 3 + lambda: |- + auto time = id(time_sensor).now(); + it.strftime("%H:%M", time); +``` + +# Optional parameters + +`scroll:` defaults to false + +`scroll_speed:` is the time between each movement, default 250ms + +`scroll_dwell:` is the time to wait at the end before going back to the start, default 2s + +`scroll_delay:` is the number (float, minimum 1) of `scroll_speed` cycles to wait at the beginning before starting to scroll, default 3 + +`secondary_display:` is a list of i2c devices where `address:` is required and `i2c_id:` is optional unless there is more than one i2c bus. + diff --git a/components/ht16k33_7segment/__init__.py b/components/ht16k33_7segment/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/components/ht16k33_7segment/display.py b/components/ht16k33_7segment/display.py new file mode 100644 index 00000000..636cdba5 --- /dev/null +++ b/components/ht16k33_7segment/display.py @@ -0,0 +1,26 @@ +import esphome.codegen as cg +from esphome.const import CONF_ID +from ..ht16k33_base.display import ( + base_to_code, + CONF_SECONDARY_DISPLAYS, + CONFIG_SCHEMA, + ht16k33_ns, + HT16K33BaseDisplay, +) + +AUTO_LOAD = ['ht16k33_base'] + +HT16K337SegmentDisplay = ht16k33_ns.class_("HT16K337SegmentDisplay", HT16K33BaseDisplay) + +async def to_code(config): + instance_var = HT16K337SegmentDisplay.new() + var = cg.Pvariable(config[CONF_ID], instance_var) + await base_to_code(var, config) + + if CONF_SECONDARY_DISPLAYS in config: + for conf in config[CONF_SECONDARY_DISPLAYS]: + instance_disp = HT16K337SegmentDisplay.new() + disp = cg.Pvariable(conf[CONF_ID], instance_disp) + await i2c.register_i2c_device(disp, conf) + cg.add(var.add_secondary_display(disp)) + diff --git a/components/ht16k33_7segment/font.h b/components/ht16k33_7segment/font.h new file mode 100644 index 00000000..35738ae1 --- /dev/null +++ b/components/ht16k33_7segment/font.h @@ -0,0 +1,102 @@ +#pragma once +// based on Adafruit backpack library + +static const uint8_t sevensegfonttable[] PROGMEM = { + + 0b00000000, // (space) + 0b10000110, // ! + 0b00100010, // " + 0b01111110, // # + 0b01101101, // $ + 0b11010010, // % + 0b01000110, // & + 0b00100000, // ' + 0b00101001, // ( + 0b00001011, // ) + 0b00100001, // * + 0b01110000, // + + 0b00010000, // , + 0b01000000, // - + 0b10000000, // . + 0b01010010, // / + 0b00111111, // 0 + 0b00000110, // 1 + 0b01011011, // 2 + 0b01001111, // 3 + 0b01100110, // 4 + 0b01101101, // 5 + 0b01111101, // 6 + 0b00000111, // 7 + 0b01111111, // 8 + 0b01101111, // 9 + 0b00001001, // : + 0b00001101, // ; + 0b01100001, // < + 0b01001000, // = + 0b01000011, // > + 0b11010011, // ? + 0b01011111, // @ + 0b01110111, // A + 0b01111100, // B + 0b00111001, // C + 0b01011110, // D + 0b01111001, // E + 0b01110001, // F + 0b00111101, // G + 0b01110110, // H + 0b00110000, // I + 0b00011110, // J + 0b01110101, // K + 0b00111000, // L + 0b00010101, // M + 0b00110111, // N + 0b00111111, // O + 0b01110011, // P + 0b01101011, // Q + 0b00110011, // R + 0b01101101, // S + 0b01111000, // T + 0b00111110, // U + 0b00111110, // V + 0b00101010, // W + 0b01110110, // X + 0b01101110, // Y + 0b01011011, // Z + 0b00111001, // [ + 0b01100100, // + 0b00001111, // ] + 0b00100011, // ^ + 0b00001000, // _ + 0b00000010, // ` + 0b01011111, // a + 0b01111100, // b + 0b01011000, // c + 0b01011110, // d + 0b01111011, // e + 0b01110001, // f + 0b01101111, // g + 0b01110100, // h + 0b00010000, // i + 0b00001100, // j + 0b01110101, // k + 0b00110000, // l + 0b00010100, // m + 0b01010100, // n + 0b01011100, // o + 0b01110011, // p + 0b01100111, // q + 0b01010000, // r + 0b01101101, // s + 0b01111000, // t + 0b00011100, // u + 0b00011100, // v + 0b00010100, // w + 0b01110110, // x + 0b01101110, // y + 0b01011011, // z + 0b01000110, // { + 0b00110000, // | + 0b01110000, // } + 0b00000001, // ~ + 0b00000000, // del +}; diff --git a/components/ht16k33_7segment/ht16k33_7segment.cpp b/components/ht16k33_7segment/ht16k33_7segment.cpp new file mode 100644 index 00000000..6617baf2 --- /dev/null +++ b/components/ht16k33_7segment/ht16k33_7segment.cpp @@ -0,0 +1,59 @@ +#include "esphome/core/log.h" +#include "esphome/core/hal.h" +#include "ht16k33_7segment.h" +#include "font.h" + +#ifndef USE_ESP8266 + #define pgm_read_word(s) (*s) +#endif + +namespace esphome { +namespace ht16k33 { + +static const char *TAG = "ht16k33"; + +void HT16K337SegmentDisplay::display_() { + constexpr uint8_t size = 10; + uint8_t buffer[size]; + uint8_t src_idx = this->offset_; + for (auto *display : this->displays_) { + for (uint8_t dst_idx = 0; dst_idx < size; dst_idx++) { + if (dst_idx == 4) { + buffer[dst_idx++] = this->show_colon_ ? 0x02 : 0; + buffer[dst_idx] = 0; + } else { + buffer[dst_idx] = this->buffer_[src_idx++]; + } + } + display->write_bytes(DISPLAY_COMMAND_SET_DDRAM_ADDR, buffer, size); + } +} + +//void HT16K337SegmentDisplay::display_() { +// int offset = this->offset_; +// static const uint8_t size = this->display_size_(); +// uint8_t buffer[size]; +// memcpy(buffer, this->buffer_ + offset, 4); +// offset += 4; +// if (this->show_colon_) { +// buffer[4] = 0x02; +// } else { +// buffer[4] = 0; +// } +// buffer[5] = 0; +// memcpy(buffer + 6, this->buffer_ + offset, 4); +// offset += 4; +// +// for (auto *display : this->displays_) { +// display->write_bytes(DISPLAY_COMMAND_SET_DDRAM_ADDR, buffer, size); +// offset += 8; +// } +//} + +uint16_t HT16K337SegmentDisplay::read_character_(uint8_t c) const { + return pgm_read_word(&sevensegfonttable[c - 32]); +} + +} // namespace ht16k33 +} // namespace esphome + diff --git a/components/ht16k33_7segment/ht16k33_7segment.h b/components/ht16k33_7segment/ht16k33_7segment.h new file mode 100644 index 00000000..eccd7dae --- /dev/null +++ b/components/ht16k33_7segment/ht16k33_7segment.h @@ -0,0 +1,17 @@ +#pragma once + +#include "../ht16k33_base/ht16k33_display.h" + +namespace esphome { +namespace ht16k33 { + +class HT16K337SegmentDisplay : public HT16K33BaseDisplay { + protected: + void display_() override; + uint16_t read_character_(uint8_t c) const override; + uint16_t decimal_point_mask_() const override { return 0x80; }; + bool supports_colon_() const override { return true; } +}; + +} // namespace ht16k33 +} // namespace esphome diff --git a/components/ht16k33_alpha/README.md b/components/ht16k33_alpha/README.md index 7b5ce32b..6541253d 100644 --- a/components/ht16k33_alpha/README.md +++ b/components/ht16k33_alpha/README.md @@ -1,5 +1,14 @@ # HT16K33 4 character alphanumeric display +This component supports the 4 character 14 segment alphanumeric display. + +> :warning: If using this component as an external component, you need to include both `ht16k33_alpha` **and** `ht16k33_base` components. +```yaml +external_components: + source: github://ssieb/custom_components/ + components: [ ht16k33_base, ht16k33_alpha ] +``` + There are no print functions for addressing rows and columns. With such a small display I didn't see any point. All the print functions without the row and column parameters are available. A "." will get added to the previous character as the decimal point. @@ -9,7 +18,7 @@ You can extend the display across multiple units. Example: ```yaml -i2c: +i2c: sda: D0 scl: D1 @@ -25,7 +34,6 @@ display: secondary_displays: - address: 0x71 ``` - # Optional parameters `scroll:` defaults to false diff --git a/components/ht16k33_alpha/display.py b/components/ht16k33_alpha/display.py index 34aefd8e..5a7d847f 100644 --- a/components/ht16k33_alpha/display.py +++ b/components/ht16k33_alpha/display.py @@ -1,51 +1,26 @@ import esphome.codegen as cg -import esphome.config_validation as cv -from esphome.components import display, i2c -from esphome.const import CONF_ID, CONF_LAMBDA +from esphome.const import CONF_ID +from ..ht16k33_base.display import ( + base_to_code, + CONF_SECONDARY_DISPLAYS, + CONFIG_SCHEMA, + ht16k33_ns, + HT16K33BaseDisplay, +) -DEPENDENCIES = ['i2c'] +AUTO_LOAD = ['ht16k33_base'] -ht16k33_alpha_ns = cg.esphome_ns.namespace('ht16k33_alpha') -HT16K33AlphaDisplay = ht16k33_alpha_ns.class_('HT16K33AlphaDisplay', cg.PollingComponent, i2c.I2CDevice) - -CONF_SCROLL = "scroll" -CONF_SCROLL_SPEED = "scroll_speed" -CONF_SCROLL_DWELL = "scroll_dwell" -CONF_SCROLL_DELAY = "scroll_delay" -CONF_SECONDARY_DISPLAYS = "secondary_displays" - -CONFIG_SECONDARY = cv.Schema({ - cv.GenerateID(): cv.declare_id(i2c.I2CDevice) -}).extend(i2c.i2c_device_schema(None)) - -CONFIG_SCHEMA = display.BASIC_DISPLAY_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(HT16K33AlphaDisplay), - cv.Optional(CONF_SCROLL, default=False): cv.boolean, - cv.Optional(CONF_SCROLL_SPEED, default='250ms'): cv.positive_time_period_milliseconds, - cv.Optional(CONF_SCROLL_DWELL, default='2s'): cv.positive_time_period_milliseconds, - cv.Optional(CONF_SCROLL_DELAY, default='3'): cv.float_range(min=1), - cv.Optional(CONF_SECONDARY_DISPLAYS): cv.ensure_list(CONFIG_SECONDARY), -}).extend(cv.polling_component_schema('1s')).extend(i2c.i2c_device_schema(0x70)) +HT16K33AlphaDisplay = ht16k33_ns.class_("HT16K33AlphaDisplay", HT16K33BaseDisplay) async def to_code(config): - var = cg.new_Pvariable(config[CONF_ID]) - await cg.register_component(var, config) - await display.register_display(var, config) - await i2c.register_i2c_device(var, config) + instance_var = HT16K33AlphaDisplay.new() + var = cg.Pvariable(config[CONF_ID], instance_var) + await base_to_code(var, config) - if CONF_LAMBDA in config: - lambda_ = await cg.process_lambda(config[CONF_LAMBDA], - [(HT16K33AlphaDisplay.operator('ref'), 'it')], - return_type=cg.void) - cg.add(var.set_writer(lambda_)) - if config[CONF_SCROLL]: - cg.add(var.set_scroll(True)) - cg.add(var.set_scroll_speed(config[CONF_SCROLL_SPEED])) - cg.add(var.set_scroll_dwell(config[CONF_SCROLL_DWELL])) - cg.add(var.set_scroll_delay(int(config[CONF_SCROLL_DELAY] * config[CONF_SCROLL_SPEED].total_milliseconds))) if CONF_SECONDARY_DISPLAYS in config: for conf in config[CONF_SECONDARY_DISPLAYS]: - disp = cg.new_Pvariable(conf[CONF_ID]) + instance_disp = HT16K33AlphaDisplay.new() + disp = cg.Pvariable(conf[CONF_ID], instance_disp) await i2c.register_i2c_device(disp, conf) cg.add(var.add_secondary_display(disp)) diff --git a/components/ht16k33_alpha/font.h b/components/ht16k33_alpha/font.h index 4b783f4f..6caba428 100644 --- a/components/ht16k33_alpha/font.h +++ b/components/ht16k33_alpha/font.h @@ -1,6 +1,7 @@ +#pragma once // based on Adafruit backpack library -static const uint16_t alphafonttable[] PROGMEM = { +static const uint16_t alphafonttable[] PROGMEM = { 0b0000000000000000, // 0 = space 0b0000000000000001, // 1 = seg A 0b0000000000000010, // 2 = seg B diff --git a/components/ht16k33_alpha/ht16k33_alpha.cpp b/components/ht16k33_alpha/ht16k33_alpha.cpp new file mode 100644 index 00000000..617aa41f --- /dev/null +++ b/components/ht16k33_alpha/ht16k33_alpha.cpp @@ -0,0 +1,29 @@ +#include "esphome/core/log.h" +#include "esphome/core/hal.h" +#include "ht16k33_alpha.h" +#include "font.h" + +#ifndef USE_ESP8266 + #define pgm_read_word(s) (*s) +#endif + +namespace esphome { +namespace ht16k33 { + +static const char *TAG = "ht16k33"; + +void HT16K33AlphaDisplay::display_() { + int offset = this->offset_; + for (auto *display : this->displays_) { + display->write_bytes(DISPLAY_COMMAND_SET_DDRAM_ADDR, this->buffer_ + offset, 8); + offset += 8; + } +} + +uint16_t HT16K33AlphaDisplay::read_character_(uint8_t c) const { + return pgm_read_word(&alphafonttable[c]); +} + +} // namespace ht16k33 +} // namespace esphome + diff --git a/components/ht16k33_alpha/ht16k33_alpha.h b/components/ht16k33_alpha/ht16k33_alpha.h new file mode 100644 index 00000000..d302746f --- /dev/null +++ b/components/ht16k33_alpha/ht16k33_alpha.h @@ -0,0 +1,17 @@ +#pragma once + +#include "../ht16k33_base/ht16k33_display.h" + +namespace esphome { +namespace ht16k33 { + +class HT16K33AlphaDisplay : public HT16K33BaseDisplay { + protected: + void display_() override; + uint16_t read_character_(uint8_t c) const override; + uint16_t decimal_point_mask_() const override { return 0x4000; } + bool supports_colon_() const override { return false; } +}; + +} // namespace ht16k33 +} // namespace esphome diff --git a/components/ht16k33_base/README.md b/components/ht16k33_base/README.md new file mode 100644 index 00000000..2d7b8657 --- /dev/null +++ b/components/ht16k33_base/README.md @@ -0,0 +1,4 @@ +# HT16K33 4 character display base component + +This component provides the common functionality for both the 4 character 14 segment alphanumeric display and the 4 character (plus colon) 7 segment character display. It cannot be used as standalone. Use the ``ht16k33_alpha`` or ``ht16k33_7segment`` components instead. + diff --git a/components/ht16k33_base/__init__.py b/components/ht16k33_base/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/components/ht16k33_base/display.py b/components/ht16k33_base/display.py new file mode 100644 index 00000000..6af2242f --- /dev/null +++ b/components/ht16k33_base/display.py @@ -0,0 +1,48 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import display, i2c +from esphome.const import CONF_ID, CONF_LAMBDA +from esphome.const import __version__ as ESPHOME_VERSION + +DEPENDENCIES = ['i2c'] + +ht16k33_ns = cg.esphome_ns.namespace('ht16k33') +HT16K33BaseDisplay = ht16k33_ns.class_('HT16K33BaseDisplay', cg.PollingComponent, i2c.I2CDevice) + +CONF_SCROLL = "scroll" +CONF_SCROLL_SPEED = "scroll_speed" +CONF_SCROLL_DWELL = "scroll_dwell" +CONF_SCROLL_DELAY = "scroll_delay" +CONF_SECONDARY_DISPLAYS = "secondary_displays" + + +CONFIG_SECONDARY = cv.Schema({ + cv.GenerateID(): cv.declare_id(i2c.I2CDevice) +}).extend(i2c.i2c_device_schema(None)) + +CONFIG_SCHEMA = display.BASIC_DISPLAY_SCHEMA.extend({ + cv.GenerateID(): cv.declare_id(HT16K33BaseDisplay), + cv.Optional(CONF_SCROLL, default=False): cv.boolean, + cv.Optional(CONF_SCROLL_SPEED, default='250ms'): cv.positive_time_period_milliseconds, + cv.Optional(CONF_SCROLL_DWELL, default='2s'): cv.positive_time_period_milliseconds, + cv.Optional(CONF_SCROLL_DELAY, default='3'): cv.float_range(min=1), + cv.Optional(CONF_SECONDARY_DISPLAYS): cv.ensure_list(CONFIG_SECONDARY), +}).extend(cv.polling_component_schema('1s')).extend(i2c.i2c_device_schema(0x70)) + +async def base_to_code(var, config): + if cv.Version.parse(ESPHOME_VERSION) < cv.Version.parse("2023.12.0"): + await cg.register_component(var, config) + await display.register_display(var, config) + await i2c.register_i2c_device(var, config) + + if CONF_LAMBDA in config: + lambda_ = await cg.process_lambda(config[CONF_LAMBDA], + [(HT16K33BaseDisplay.operator('ref'), 'it')], + return_type=cg.void) + cg.add(var.set_writer(lambda_)) + if config[CONF_SCROLL]: + cg.add(var.set_scroll(True)) + cg.add(var.set_scroll_speed(config[CONF_SCROLL_SPEED])) + cg.add(var.set_scroll_dwell(config[CONF_SCROLL_DWELL])) + cg.add(var.set_scroll_delay(int(config[CONF_SCROLL_DELAY] * config[CONF_SCROLL_SPEED].total_milliseconds))) + diff --git a/components/ht16k33_alpha/ht16k33_display.cpp b/components/ht16k33_base/ht16k33_display.cpp similarity index 66% rename from components/ht16k33_alpha/ht16k33_display.cpp rename to components/ht16k33_base/ht16k33_display.cpp index 1ce26c19..381279fc 100644 --- a/components/ht16k33_alpha/ht16k33_display.cpp +++ b/components/ht16k33_base/ht16k33_display.cpp @@ -2,25 +2,18 @@ #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "ht16k33_display.h" -#include "font.h" - -#ifndef USE_ESP8266 - #define pgm_read_word(s) (*s) -#endif namespace esphome { -namespace ht16k33_alpha { +namespace ht16k33 { -static const char *TAG = "ht16k33_alpha"; +static const char *TAG = "ht16k33"; -// First set bit determines command, bits after that are the data. -static const uint8_t DISPLAY_COMMAND_SET_DDRAM_ADDR = 0x00; -static const uint8_t DISPLAY_COMMAND_SYSTEM_SETUP = 0x21; -static const uint8_t DISPLAY_COMMAND_DISPLAY_OFF = 0x80; -static const uint8_t DISPLAY_COMMAND_DISPLAY_ON = 0x81; -static const uint8_t DISPLAY_COMMAND_DIMMING = 0xE0; +void HT16K33BaseDisplay::dump_config() { + ESP_LOGCONFIG(TAG, "HT16K33 Display:"); + LOG_I2C_DEVICE(this); +} -void HT16K33AlphaDisplay::setup() { +void HT16K33BaseDisplay::setup() { for (auto *display : this->displays_) { display->write_bytes(DISPLAY_COMMAND_SYSTEM_SETUP, nullptr, 0); display->write_bytes(DISPLAY_COMMAND_DISPLAY_ON, nullptr, 0); @@ -29,7 +22,7 @@ void HT16K33AlphaDisplay::setup() { memset(this->buffer_, 0, 64); } -void HT16K33AlphaDisplay::loop() { +void HT16K33BaseDisplay::loop() { unsigned long now = millis(); int numc = this->displays_.size() * 8; // check if the buffer has shrunk past the current position since last update @@ -55,17 +48,9 @@ void HT16K33AlphaDisplay::loop() { } } -float HT16K33AlphaDisplay::get_setup_priority() const { return setup_priority::PROCESSOR; } +float HT16K33BaseDisplay::get_setup_priority() const { return setup_priority::PROCESSOR; } -void HT16K33AlphaDisplay::display_() { - int offset = this->offset_; - for (auto *display : this->displays_) { - display->write_bytes(DISPLAY_COMMAND_SET_DDRAM_ADDR, this->buffer_ + offset, 8); - offset += 8; - } -} - -void HT16K33AlphaDisplay::update() { +void HT16K33BaseDisplay::update() { memset(this->buffer_, 0, 64); int prev_fill = this->buffer_fill_; this->buffer_fill_ = 0; @@ -77,7 +62,7 @@ void HT16K33AlphaDisplay::update() { this->display_(); } -void HT16K33AlphaDisplay::set_brightness(float level) { +void HT16K33BaseDisplay::set_brightness(float level) { int val = (int) round(level * 16); if (val < 0) val = 0; @@ -94,13 +79,15 @@ void HT16K33AlphaDisplay::set_brightness(float level) { } } -float HT16K33AlphaDisplay::get_brightness() { +float HT16K33BaseDisplay::get_brightness() { return this->brightness_ / 16.0; } -void HT16K33AlphaDisplay::print(const char *str) { +void HT16K33BaseDisplay::print(const char *str) { uint8_t pos = this->buffer_fill_; + uint8_t idx = 1; uint16_t fontc = 0; + this->show_colon_ = false; while (*str != '\0') { if (pos >= 64) { ESP_LOGW(TAG, "output buffer full!"); @@ -111,21 +98,28 @@ void HT16K33AlphaDisplay::print(const char *str) { if (c > 127) fontc = 0; else - fontc = pgm_read_word(&alphafonttable[c]); + fontc = read_character_(c); c = *reinterpret_cast(str); if (c == '.') { - fontc |= 0x4000; + fontc |= decimal_point_mask_(); + str++; + idx++; + } + if (c == ':' && idx == 2 && this->supports_colon_()) { + this->show_colon_ = true; str++; + idx++; } this->buffer_[pos++] = fontc & 0xff; this->buffer_[pos++] = fontc >> 8; + idx++; } this->buffer_fill_ = pos; } -void HT16K33AlphaDisplay::print(const std::string &str) { this->print(str.c_str()); } +void HT16K33BaseDisplay::print(const std::string &str) { this->print(str.c_str()); } -void HT16K33AlphaDisplay::printf(const char *format, ...) { +void HT16K33BaseDisplay::printf(const char *format, ...) { va_list arg; va_start(arg, format); char buffer[64]; @@ -136,7 +130,7 @@ void HT16K33AlphaDisplay::printf(const char *format, ...) { } #ifdef USE_TIME -void HT16K33AlphaDisplay::strftime(const char *format, ESPTime time) { +void HT16K33BaseDisplay::strftime(const char *format, ESPTime time) { char buffer[64]; size_t ret = time.strftime(buffer, sizeof(buffer), format); if (ret > 0) @@ -144,6 +138,6 @@ void HT16K33AlphaDisplay::strftime(const char *format, ESPTime time) { } #endif -} // namespace ht16k33_alpha +} // namespace ht16k33 } // namespace esphome diff --git a/components/ht16k33_alpha/ht16k33_display.h b/components/ht16k33_base/ht16k33_display.h similarity index 67% rename from components/ht16k33_alpha/ht16k33_display.h rename to components/ht16k33_base/ht16k33_display.h index cf983f39..af034a72 100644 --- a/components/ht16k33_alpha/ht16k33_display.h +++ b/components/ht16k33_base/ht16k33_display.h @@ -10,11 +10,19 @@ #endif namespace esphome { -namespace ht16k33_alpha { +namespace ht16k33 { -class HT16K33AlphaDisplay : public PollingComponent, public i2c::I2CDevice { +// First set bit determines command, bits after that are the data. +constexpr uint8_t DISPLAY_COMMAND_SET_DDRAM_ADDR = 0x00; +constexpr uint8_t DISPLAY_COMMAND_SYSTEM_SETUP = 0x21; +constexpr uint8_t DISPLAY_COMMAND_DISPLAY_OFF = 0x80; +constexpr uint8_t DISPLAY_COMMAND_DISPLAY_ON = 0x81; +constexpr uint8_t DISPLAY_COMMAND_DIMMING = 0xE0; + +class HT16K33BaseDisplay : public PollingComponent, public i2c::I2CDevice { public: - void set_writer(std::function &&writer) { this->writer_ = std::move(writer); } + void set_writer(std::function &&writer) { this->writer_ = std::move(writer); } + void dump_config() override; void setup() override; void loop() override; float get_setup_priority() const override; @@ -43,10 +51,14 @@ class HT16K33AlphaDisplay : public PollingComponent, public i2c::I2CDevice { protected: void command_(uint8_t value); void call_writer() { this->writer_(*this); } - void display_(); + + virtual void display_() = 0; + virtual uint16_t read_character_(uint8_t c) const = 0; + virtual uint16_t decimal_point_mask_() const = 0; + virtual bool supports_colon_() const =0; std::vector displays_ {this}; - std::function writer_; + std::function writer_; bool scroll_ {false}; unsigned long scroll_speed_ {250}; unsigned long scroll_dwell_ {2000}; @@ -56,7 +68,8 @@ class HT16K33AlphaDisplay : public PollingComponent, public i2c::I2CDevice { int buffer_fill_ {0}; int offset_ {0}; uint8_t brightness_ = 16; + bool show_colon_ {false}; }; -} // namespace ht16k33_alpha +} // namespace ht16k33 } // namespace esphome