mirror of https://github.com/esphome/esphome.git
Merge 691d41cb55
into f0ec900e48
This commit is contained in:
commit
72e4deb663
|
@ -162,6 +162,7 @@ esphome/components/honeywellabp/* @RubyBailey
|
|||
esphome/components/honeywellabp2_i2c/* @jpfaff
|
||||
esphome/components/host/* @esphome/core
|
||||
esphome/components/hrxl_maxsonar_wr/* @netmikey
|
||||
esphome/components/ht16k33/* @tylerwowen
|
||||
esphome/components/hte501/* @Stock-M
|
||||
esphome/components/htu31d/* @betterengineering
|
||||
esphome/components/hydreon_rgxx/* @functionpointer
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import pins
|
||||
from esphome.components import display, i2c
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_INTENSITY,
|
||||
CONF_LAMBDA,
|
||||
CONF_RESET_PIN,
|
||||
CONF_NUM_CHIPS,
|
||||
)
|
||||
|
||||
CODEOWNERS = ["@tylerwowen"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
CONF_ROTATE_CHIP = "rotate_chip"
|
||||
CONF_FLIP_X = "flip_x"
|
||||
CONF_SCROLL_SPEED = "scroll_speed"
|
||||
CONF_SCROLL_DWELL = "scroll_dwell"
|
||||
CONF_SCROLL_DELAY = "scroll_delay"
|
||||
CONF_SCROLL_ENABLE = "scroll_enable"
|
||||
CONF_SCROLL_MODE = "scroll_mode"
|
||||
CONF_REVERSE_ENABLE = "reverse_enable"
|
||||
CONF_NUM_CHIP_LINES = "num_chip_lines"
|
||||
CONF_CHIP_LINES_STYLE = "chip_lines_style"
|
||||
CONF_BLINK_RATE = "blink_rate"
|
||||
|
||||
ht16k33_ns = cg.esphome_ns.namespace("ht16k33")
|
||||
ChipLinesStyle = ht16k33_ns.enum("ChipLinesStyle")
|
||||
CHIP_LINES_STYLE = {
|
||||
"ZIGZAG": ChipLinesStyle.ZIGZAG,
|
||||
"SNAKE": ChipLinesStyle.SNAKE,
|
||||
}
|
||||
|
||||
ScrollMode = ht16k33_ns.enum("ScrollMode")
|
||||
SCROLL_MODES = {
|
||||
"CONTINUOUS": ScrollMode.CONTINUOUS,
|
||||
"STOP": ScrollMode.STOP,
|
||||
}
|
||||
|
||||
CHIP_MODES = {
|
||||
"0": 0,
|
||||
"90": 1,
|
||||
"180": 2,
|
||||
"270": 3,
|
||||
}
|
||||
|
||||
BLINK_RATES = {
|
||||
"OFF": 0,
|
||||
"2HZ": 1,
|
||||
"1HZ": 2,
|
||||
"0.5HZ": 3,
|
||||
}
|
||||
|
||||
HT16K33Component = ht16k33_ns.class_(
|
||||
"HT16K33Component", i2c.I2CDevice, display.DisplayBuffer, cg.PollingComponent
|
||||
)
|
||||
HT16K33ComponentRef = HT16K33Component.operator("ref")
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
display.BASIC_DISPLAY_SCHEMA.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(HT16K33Component),
|
||||
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
||||
cv.Optional(CONF_NUM_CHIPS, default=1): cv.int_range(min=1, max=8),
|
||||
cv.Optional(CONF_NUM_CHIP_LINES, default=1): cv.int_range(min=1, max=8),
|
||||
cv.Optional(CONF_CHIP_LINES_STYLE, default="SNAKE"): cv.enum(
|
||||
CHIP_LINES_STYLE, upper=True
|
||||
),
|
||||
cv.Optional(CONF_INTENSITY, default=15): cv.int_range(min=0, max=15),
|
||||
cv.Optional(CONF_ROTATE_CHIP, default="0"): cv.enum(CHIP_MODES, upper=True),
|
||||
cv.Optional(CONF_SCROLL_MODE, default="CONTINUOUS"): cv.enum(
|
||||
SCROLL_MODES, upper=True
|
||||
),
|
||||
cv.Optional(CONF_SCROLL_ENABLE, default=True): cv.boolean,
|
||||
cv.Optional(
|
||||
CONF_SCROLL_SPEED, default="250ms"
|
||||
): cv.positive_time_period_milliseconds,
|
||||
cv.Optional(
|
||||
CONF_SCROLL_DELAY, default="1000ms"
|
||||
): cv.positive_time_period_milliseconds,
|
||||
cv.Optional(
|
||||
CONF_SCROLL_DWELL, default="1000ms"
|
||||
): cv.positive_time_period_milliseconds,
|
||||
cv.Optional(CONF_REVERSE_ENABLE, default=False): cv.boolean,
|
||||
cv.Optional(CONF_FLIP_X, default=False): cv.boolean,
|
||||
cv.Optional(CONF_BLINK_RATE, default="OFF"): cv.enum(
|
||||
BLINK_RATES, upper=True
|
||||
),
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("1s"))
|
||||
.extend(i2c.i2c_device_schema(0x70))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await i2c.register_i2c_device(var, config)
|
||||
await display.register_display(var, config)
|
||||
|
||||
cg.add(var.set_num_chips(config[CONF_NUM_CHIPS]))
|
||||
cg.add(var.set_num_chip_lines(config[CONF_NUM_CHIP_LINES]))
|
||||
cg.add(var.set_chip_lines_style(config[CONF_CHIP_LINES_STYLE]))
|
||||
cg.add(var.set_intensity(config[CONF_INTENSITY]))
|
||||
cg.add(var.set_chip_orientation(config[CONF_ROTATE_CHIP]))
|
||||
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(config[CONF_SCROLL_DELAY]))
|
||||
cg.add(var.set_scroll(config[CONF_SCROLL_ENABLE]))
|
||||
cg.add(var.set_scroll_mode(config[CONF_SCROLL_MODE]))
|
||||
cg.add(var.set_reverse(config[CONF_REVERSE_ENABLE]))
|
||||
cg.add(var.set_flip_x(config[CONF_FLIP_X]))
|
||||
cg.add(var.set_blink_rate(config[CONF_BLINK_RATE]))
|
||||
|
||||
if CONF_LAMBDA in config:
|
||||
lambda_ = await cg.process_lambda(
|
||||
config[CONF_LAMBDA], [(HT16K33ComponentRef, "it")], return_type=cg.void
|
||||
)
|
||||
cg.add(var.set_writer(lambda_))
|
||||
if CONF_RESET_PIN in config:
|
||||
reset = await cg.gpio_pin_expression(config[CONF_RESET_PIN])
|
||||
cg.add(var.set_reset_pin(reset))
|
|
@ -0,0 +1,364 @@
|
|||
#include "ht16k33.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/time.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace ht16k33 {
|
||||
|
||||
static const char *const TAG = "ht16k33";
|
||||
|
||||
constexpr uint8_t HT16K33_REGISTER_RAM = 0x00;
|
||||
constexpr uint8_t HT16K33_REGISTER_OSCILLATOR = 0x20;
|
||||
constexpr uint8_t HT16K33_REGISTER_BLINK = 0x80;
|
||||
constexpr uint8_t HT16K33_REGISTER_INTENSITY = 0xE0;
|
||||
|
||||
constexpr uint8_t HT16K33_ON = 0x01;
|
||||
constexpr uint8_t HT16K33_OFF = 0x00;
|
||||
|
||||
constexpr uint8_t HT16K33_BLINK_2HZ = 0x01;
|
||||
constexpr uint8_t HT16K33_BLINK_1HZ = 0x02;
|
||||
constexpr uint8_t HT16K33_BLINK_HALFHZ = 0x03;
|
||||
|
||||
float HT16K33Component::get_setup_priority() const { return setup_priority::PROCESSOR; }
|
||||
|
||||
void HT16K33Component::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up HT16K33...");
|
||||
this->init_reset_();
|
||||
|
||||
delay(10);
|
||||
auto err = this->write(nullptr, 0);
|
||||
if (err != i2c::ERROR_OK) {
|
||||
this->error_code_ = COMMUNICATION_FAILED;
|
||||
this->mark_failed();
|
||||
ESP_LOGE(TAG, "Error in communication with HT16K33 %i", err);
|
||||
return;
|
||||
}
|
||||
base_address_ = this->address_;
|
||||
|
||||
// turn on oscillator
|
||||
this->command_all_(HT16K33_REGISTER_OSCILLATOR | HT16K33_ON);
|
||||
ESP_LOGD(TAG, "HT16K33 oscillator turned on");
|
||||
|
||||
// internal RAM powers up with garbage/random values.
|
||||
// ensure internal RAM is cleared before turning on display
|
||||
// this ensures that no garbage pixels show up on the display
|
||||
// when it is turned on.
|
||||
this->stepsleft_ = 0;
|
||||
for (int chip_line = 0; chip_line < this->num_chip_lines_; chip_line++) {
|
||||
std::vector<uint16_t> vec(1);
|
||||
this->max_displaybuffer_.push_back(vec);
|
||||
// Initialize buffer with 0 for display so all non written pixels are blank
|
||||
this->max_displaybuffer_[chip_line].resize(get_width_internal(), 0);
|
||||
}
|
||||
this->display();
|
||||
ESP_LOGD(TAG, "display cleared");
|
||||
|
||||
this->intensity(this->intensity_);
|
||||
ESP_LOGD(TAG, "intensity set to %u", this->intensity_);
|
||||
|
||||
this->blink_rate(this->blink_rate_);
|
||||
ESP_LOGD(TAG, "blink rate set to off");
|
||||
}
|
||||
|
||||
void HT16K33Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "HT16K33:");
|
||||
LOG_I2C_DEVICE(this);
|
||||
ESP_LOGCONFIG(TAG, " Number of Chips: %u", this->num_chips_);
|
||||
ESP_LOGCONFIG(TAG, " Number of Chips Lines: %u", this->num_chip_lines_);
|
||||
ESP_LOGCONFIG(TAG, " Chips Lines Style : %u", this->chip_lines_style_);
|
||||
ESP_LOGCONFIG(TAG, " Intensity: %u", this->intensity_);
|
||||
ESP_LOGCONFIG(TAG, " Blink rate: %u", this->blink_rate_);
|
||||
ESP_LOGCONFIG(TAG, " Scroll Enabled: %u", this->scroll_);
|
||||
ESP_LOGCONFIG(TAG, " Scroll Mode: %u", this->scroll_mode_);
|
||||
ESP_LOGCONFIG(TAG, " Scroll Speed: %u", this->scroll_speed_);
|
||||
ESP_LOGCONFIG(TAG, " Scroll Dwell: %u", this->scroll_dwell_);
|
||||
ESP_LOGCONFIG(TAG, " Scroll Delay: %u", this->scroll_delay_);
|
||||
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
}
|
||||
|
||||
void HT16K33Component::loop() {
|
||||
uint32_t const now = millis();
|
||||
|
||||
// check if the buffer has shrunk past the current position since last update
|
||||
if ((this->max_displaybuffer_[0].size() >= this->old_buffer_size_ + 3) ||
|
||||
(this->max_displaybuffer_[0].size() <= this->old_buffer_size_ - 3)) {
|
||||
this->stepsleft_ = 0;
|
||||
this->display();
|
||||
this->old_buffer_size_ = this->max_displaybuffer_[0].size();
|
||||
}
|
||||
|
||||
// Reset the counter back to 0 when full string has been displayed.
|
||||
if (this->stepsleft_ > this->max_displaybuffer_[0].size())
|
||||
this->stepsleft_ = 0;
|
||||
|
||||
// Return if there is no need to scroll or scroll is off
|
||||
if (!this->scroll_ || (this->max_displaybuffer_[0].size() <= (size_t) get_width_internal())) {
|
||||
this->display();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((this->stepsleft_ == 0) && (now - this->last_scroll_ < this->scroll_delay_)) {
|
||||
this->display();
|
||||
return;
|
||||
}
|
||||
|
||||
// Dwell time at end of string in case of stop at end
|
||||
if (this->scroll_mode_ == ScrollMode::STOP) {
|
||||
if (this->stepsleft_ >= this->max_displaybuffer_[0].size() - (size_t) get_width_internal() + 1) {
|
||||
if (now - this->last_scroll_ >= this->scroll_dwell_) {
|
||||
this->stepsleft_ = 0;
|
||||
this->last_scroll_ = now;
|
||||
this->display();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Actual call to scroll left action
|
||||
if (now - this->last_scroll_ >= this->scroll_speed_) {
|
||||
this->last_scroll_ = now;
|
||||
this->scroll_left();
|
||||
this->display();
|
||||
}
|
||||
}
|
||||
|
||||
void HT16K33Component::display() {
|
||||
uint16_t pixels[8];
|
||||
// Run this loop for every CHIP (GRID OF 64 leds)
|
||||
// Run this routine for the rows of every chip 8x row 0 top to 7 bottom
|
||||
// Fill the pixel parameter with display data
|
||||
// Send the data to the chip
|
||||
for (uint8_t chip = 0; chip < this->num_chips_ / this->num_chip_lines_; chip++) {
|
||||
for (uint8_t chip_line = 0; chip_line < this->num_chip_lines_; chip_line++) {
|
||||
for (uint8_t j = 0; j < 8; j++) {
|
||||
bool const reverse =
|
||||
chip_line % 2 != 0 && this->chip_lines_style_ == ChipLinesStyle::SNAKE ? !this->reverse_ : this->reverse_;
|
||||
if (reverse) {
|
||||
pixels[j] =
|
||||
this->max_displaybuffer_[chip_line][(this->num_chips_ / this->num_chip_lines_ - chip - 1) * 8 + j];
|
||||
} else {
|
||||
pixels[j] = this->max_displaybuffer_[chip_line][chip * 8 + j];
|
||||
}
|
||||
}
|
||||
if (chip_line % 2 != 0 && this->chip_lines_style_ == ChipLinesStyle::SNAKE)
|
||||
this->orientation_ = orientation_180_();
|
||||
this->send64pixels(chip_line * this->num_chips_ / this->num_chip_lines_ + chip, pixels);
|
||||
if (chip_line % 2 != 0 && this->chip_lines_style_ == ChipLinesStyle::SNAKE)
|
||||
this->orientation_ = orientation_180_();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t HT16K33Component::orientation_180_() {
|
||||
switch (this->orientation_) {
|
||||
case 0:
|
||||
return 2;
|
||||
case 1:
|
||||
return 3;
|
||||
case 2:
|
||||
return 0;
|
||||
case 3:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int HT16K33Component::get_height_internal() { return 8 * this->num_chip_lines_; }
|
||||
|
||||
int HT16K33Component::get_width_internal() { return this->num_chips_ / this->num_chip_lines_ * 8; }
|
||||
|
||||
void HT16K33Component::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||
if (x + 1 > (int) this->max_displaybuffer_[0].size()) { // Extend the display buffer in case required
|
||||
for (int chip_line = 0; chip_line < this->num_chip_lines_; chip_line++) {
|
||||
this->max_displaybuffer_[chip_line].resize(x + 1, color_to_pixel_(this->bckgrnd_));
|
||||
}
|
||||
}
|
||||
|
||||
if ((y >= this->get_height_internal()) || (y < 0) || (x < 0)) // If pixel is outside display then dont draw
|
||||
return;
|
||||
|
||||
uint8_t const pos = x; // X is starting at 0 top left
|
||||
uint8_t const subpos = y; // Y is starting at 0 top left
|
||||
|
||||
int const cl_mask = 1 << subpos % 8;
|
||||
int const ch_mask = 1 << (subpos % 8 + 8);
|
||||
uint16_t *pixel_ptr = &this->max_displaybuffer_[subpos / 8][pos];
|
||||
if (color == CH) {
|
||||
// Turn off cl LED.
|
||||
*pixel_ptr &= ~cl_mask;
|
||||
// Turn on ch LED.
|
||||
*pixel_ptr |= ch_mask;
|
||||
} else if (color == CLH) {
|
||||
// Turn on ch and cl LED.
|
||||
*pixel_ptr |= cl_mask;
|
||||
*pixel_ptr |= ch_mask;
|
||||
} else if (color == Color::BLACK) {
|
||||
// Turn off ch and cl LED.
|
||||
*pixel_ptr &= ~cl_mask;
|
||||
*pixel_ptr &= ~ch_mask;
|
||||
} else {
|
||||
// CH or unrecognized color, treat it as CL
|
||||
// Turn on cl LED.
|
||||
*pixel_ptr |= cl_mask;
|
||||
// Turn off ch LED.
|
||||
*pixel_ptr &= ~ch_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void HT16K33Component::command_(uint8_t value) {
|
||||
auto err = this->write_register(value, nullptr, 0);
|
||||
if (err != i2c::ERROR_OK) {
|
||||
ESP_LOGE(TAG, "Error in communication with HT16K33 %i", err);
|
||||
}
|
||||
}
|
||||
|
||||
void HT16K33Component::command_all_(uint8_t value) {
|
||||
for (uint8_t chip_add = base_address_; chip_add < base_address_ + this->num_chips_; chip_add++) {
|
||||
this->set_i2c_address(chip_add);
|
||||
this->command_(value);
|
||||
}
|
||||
this->set_i2c_address(base_address_);
|
||||
}
|
||||
|
||||
void HT16K33Component::update() {
|
||||
this->update_ = true;
|
||||
this->clear();
|
||||
if (this->writer_.has_value()) // insert Labda function if available
|
||||
(*this->writer_)(*this);
|
||||
}
|
||||
|
||||
bool HT16K33Component::is_on() { return this->is_on_; }
|
||||
|
||||
void HT16K33Component::turn_on() {
|
||||
this->command_all_(HT16K33_REGISTER_BLINK | HT16K33_ON);
|
||||
this->is_on_ = true;
|
||||
}
|
||||
|
||||
void HT16K33Component::turn_off() {
|
||||
this->command_all_(HT16K33_REGISTER_BLINK | HT16K33_OFF);
|
||||
this->is_on_ = false;
|
||||
}
|
||||
|
||||
void HT16K33Component::scroll(bool on_off, ScrollMode mode, uint16_t speed, uint16_t delay, uint16_t dwell) {
|
||||
this->set_scroll(on_off);
|
||||
this->set_scroll_mode(mode);
|
||||
this->set_scroll_speed(speed);
|
||||
this->set_scroll_dwell(dwell);
|
||||
this->set_scroll_delay(delay);
|
||||
}
|
||||
|
||||
void HT16K33Component::scroll(bool on_off, ScrollMode mode) {
|
||||
this->set_scroll(on_off);
|
||||
this->set_scroll_mode(mode);
|
||||
}
|
||||
|
||||
void HT16K33Component::intensity(uint8_t intensity) {
|
||||
this->intensity_ = intensity;
|
||||
this->command_all_(HT16K33_REGISTER_INTENSITY | this->intensity_);
|
||||
}
|
||||
|
||||
void HT16K33Component::blink_rate(uint8_t b) {
|
||||
this->blink_rate_ = b;
|
||||
if (this->blink_rate_ > 3)
|
||||
this->blink_rate_ = 0; // turn off if not sure
|
||||
uint8_t const buffer = HT16K33_ON | (this->blink_rate_ << 1);
|
||||
this->command_all_(HT16K33_REGISTER_BLINK | buffer);
|
||||
}
|
||||
|
||||
void HT16K33Component::scroll(bool on_off) { this->set_scroll(on_off); }
|
||||
|
||||
void HT16K33Component::scroll_left() {
|
||||
for (int chip_line = 0; chip_line < this->num_chip_lines_; chip_line++) {
|
||||
if (this->update_) {
|
||||
this->max_displaybuffer_[chip_line].push_back(color_to_pixel_(this->bckgrnd_));
|
||||
for (uint16_t i = 0; i < this->stepsleft_; i++) {
|
||||
this->max_displaybuffer_[chip_line].push_back(this->max_displaybuffer_[chip_line].front());
|
||||
this->max_displaybuffer_[chip_line].erase(this->max_displaybuffer_[chip_line].begin());
|
||||
}
|
||||
} else {
|
||||
this->max_displaybuffer_[chip_line].push_back(this->max_displaybuffer_[chip_line].front());
|
||||
this->max_displaybuffer_[chip_line].erase(this->max_displaybuffer_[chip_line].begin());
|
||||
}
|
||||
}
|
||||
this->update_ = false;
|
||||
this->stepsleft_++;
|
||||
}
|
||||
|
||||
// send one character (data) to position (chip)
|
||||
void HT16K33Component::send64pixels(uint8_t chip, const uint16_t pixels[8]) {
|
||||
for (uint8_t col = 0; col < 8; col++) { // RUN THIS LOOP 8 times until column is 7
|
||||
uint16_t b = 0; // rotate pixels 90 degrees -- set byte to 0
|
||||
if (this->orientation_ == 0) {
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
// run this loop 8 times for all the pixels[8] received
|
||||
if (this->flip_x_) {
|
||||
b |= ((pixels[i] >> col) & 1) << i; // change the column bits into row bits
|
||||
b |= ((pixels[i] >> (col + 8)) & 1) << (i + 8);
|
||||
} else {
|
||||
b |= ((pixels[i] >> col) & 1) << (7 - i); // change the column bits into row bits
|
||||
b |= ((pixels[i] >> (col + 8)) & 1) << (15 - i);
|
||||
}
|
||||
}
|
||||
} else if (this->orientation_ == 1) {
|
||||
b = pixels[col];
|
||||
} else if (this->orientation_ == 2) {
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if (this->flip_x_) {
|
||||
b |= ((pixels[i] >> (7 - col)) & 1) << (7 - i);
|
||||
b |= ((pixels[i] >> (15 - col)) & 1) << (15 - i);
|
||||
} else {
|
||||
b |= ((pixels[i] >> (7 - col)) & 1) << i;
|
||||
b |= ((pixels[i] >> (15 - col)) & 1) << (i + 8);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
b |= ((pixels[7 - col] >> i) & 1) << (7 - i);
|
||||
b |= ((pixels[7 - col] >> (i + 8)) & 1) << (15 - i);
|
||||
}
|
||||
}
|
||||
b = reverse_bits(b);
|
||||
// send this byte to display at selected chip
|
||||
this->set_i2c_address(base_address_ | chip << 1);
|
||||
this->write_byte_16(HT16K33_REGISTER_RAM | col << 1, b);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t HT16K33Component::color_to_pixel_(Color color) {
|
||||
if (color == CL) {
|
||||
return 0x00FF;
|
||||
} else if (color == CH) {
|
||||
return 0xFF00;
|
||||
} else if (color == Color::BLACK) {
|
||||
return 0x0000;
|
||||
} else {
|
||||
return 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void HT16K33Component::clear() { fill(this->bckgrnd_); }
|
||||
|
||||
void HT16K33Component::fill(Color color) {
|
||||
for (int chip_line = 0; chip_line < this->num_chip_lines_; chip_line++) {
|
||||
this->max_displaybuffer_[chip_line].clear();
|
||||
this->max_displaybuffer_[chip_line].resize(get_width_internal(), color_to_pixel_(color));
|
||||
}
|
||||
}
|
||||
|
||||
void HT16K33Component::init_reset_() {
|
||||
if (this->reset_pin_ != nullptr) {
|
||||
this->reset_pin_->setup();
|
||||
this->reset_pin_->digital_write(true);
|
||||
delay(1);
|
||||
// Trigger Reset
|
||||
this->reset_pin_->digital_write(false);
|
||||
delay(10);
|
||||
// Wake up
|
||||
this->reset_pin_->digital_write(true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ht16k33
|
||||
} // namespace esphome
|
|
@ -0,0 +1,123 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/components/display/display_buffer.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/hal.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace ht16k33 {
|
||||
|
||||
enum ChipLinesStyle {
|
||||
ZIGZAG = 0,
|
||||
SNAKE,
|
||||
};
|
||||
|
||||
enum ScrollMode {
|
||||
CONTINUOUS = 0,
|
||||
STOP,
|
||||
};
|
||||
|
||||
class HT16K33Component;
|
||||
|
||||
const Color CL(255, 0, 0);
|
||||
const Color CH(0, 255, 0);
|
||||
const Color CLH(255, 255, 0);
|
||||
|
||||
using ht16k33_writer_t = std::function<void(HT16K33Component &)>;
|
||||
|
||||
class HT16K33Component : public display::DisplayBuffer, public i2c::I2CDevice {
|
||||
public:
|
||||
void set_writer(ht16k33_writer_t &&writer) { this->writer_ = writer; }
|
||||
|
||||
void setup() override;
|
||||
|
||||
void loop() override;
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
void update() override;
|
||||
|
||||
float get_setup_priority() const override;
|
||||
|
||||
void fill(Color color) override;
|
||||
|
||||
void display();
|
||||
|
||||
bool is_on();
|
||||
void turn_on();
|
||||
void turn_off();
|
||||
|
||||
void draw_absolute_pixel_internal(int x, int y, Color color) override;
|
||||
int get_height_internal() override;
|
||||
int get_width_internal() override;
|
||||
|
||||
void set_intensity(uint8_t intensity) { this->intensity_ = intensity; };
|
||||
void set_num_chips(uint8_t num_chips) { this->num_chips_ = num_chips; };
|
||||
void set_num_chip_lines(uint8_t num_chip_lines) { this->num_chip_lines_ = num_chip_lines; };
|
||||
void set_chip_lines_style(ChipLinesStyle chip_lines_style) { this->chip_lines_style_ = chip_lines_style; };
|
||||
void set_chip_orientation(uint8_t rotate) { this->orientation_ = rotate; };
|
||||
void set_scroll_speed(uint16_t speed) { this->scroll_speed_ = speed; };
|
||||
void set_scroll_dwell(uint16_t dwell) { this->scroll_dwell_ = dwell; };
|
||||
void set_scroll_delay(uint16_t delay) { this->scroll_delay_ = delay; };
|
||||
void set_scroll(bool on_off) { this->scroll_ = on_off; };
|
||||
void set_scroll_mode(ScrollMode mode) { this->scroll_mode_ = mode; };
|
||||
void set_reverse(bool on_off) { this->reverse_ = on_off; };
|
||||
void set_flip_x(bool flip_x) { this->flip_x_ = flip_x; };
|
||||
void set_blink_rate(uint8_t b) { this->blink_rate_ = b; };
|
||||
|
||||
void send64pixels(uint8_t chip, const uint16_t pixels[8]);
|
||||
|
||||
void scroll_left();
|
||||
void scroll(bool on_off, ScrollMode mode, uint16_t speed, uint16_t delay, uint16_t dwell);
|
||||
void scroll(bool on_off, ScrollMode mode);
|
||||
void scroll(bool on_off);
|
||||
void intensity(uint8_t intensity);
|
||||
void blink_rate(uint8_t blink_rate);
|
||||
|
||||
display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; }
|
||||
|
||||
/*!
|
||||
@brief Reset the display to background color.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
protected:
|
||||
void init_reset_();
|
||||
uint8_t orientation_180_();
|
||||
void command_(uint8_t value);
|
||||
void command_all_(uint8_t value);
|
||||
uint16_t color_to_pixel_(Color color);
|
||||
|
||||
uint8_t intensity_{}; // Intensity of the display from 0 to 15 (most)
|
||||
uint8_t num_chips_;
|
||||
uint8_t num_chip_lines_;
|
||||
ChipLinesStyle chip_lines_style_;
|
||||
bool scroll_{};
|
||||
bool reverse_{};
|
||||
bool flip_x_{};
|
||||
bool update_{};
|
||||
uint16_t scroll_speed_;
|
||||
uint16_t scroll_delay_;
|
||||
uint16_t scroll_dwell_;
|
||||
uint16_t old_buffer_size_{0};
|
||||
ScrollMode scroll_mode_;
|
||||
uint8_t orientation_;
|
||||
Color bckgrnd_{Color::BLACK};
|
||||
std::vector<std::vector<uint16_t>> max_displaybuffer_;
|
||||
uint32_t last_scroll_{0};
|
||||
uint16_t stepsleft_{0};
|
||||
optional<ht16k33_writer_t> writer_{};
|
||||
uint8_t blink_rate_{0};
|
||||
|
||||
GPIOPin *reset_pin_{nullptr};
|
||||
enum ErrorCode { NONE = 0, COMMUNICATION_FAILED } error_code_{NONE};
|
||||
|
||||
// internal states
|
||||
uint8_t base_address_{0x70};
|
||||
bool is_on_{false};
|
||||
bool intensity_changed_{}; // True if we need to re-send the intensity
|
||||
};
|
||||
|
||||
} // namespace ht16k33
|
||||
} // namespace esphome
|
|
@ -3528,6 +3528,16 @@ display:
|
|||
it.display_celsius(true);
|
||||
it.printf(1, "%.1f", id(dht_humidity).state);
|
||||
it.display_humidity(true);
|
||||
- platform: ht16k33
|
||||
id: ht16k33_display
|
||||
i2c_id: i2c_bus
|
||||
intensity: 15
|
||||
update_interval: 15s
|
||||
rotate_chip: 90
|
||||
flip_x: true
|
||||
lambda: |-
|
||||
it.filled_rectangle(0, 0, 5, 8, ht16k33::CL);
|
||||
it.filled_rectangle(11, 0, 5, 8, ht16k33::CH);
|
||||
|
||||
tm1651:
|
||||
id: tm1651_battery
|
||||
|
|
Loading…
Reference in New Issue