Merge branch 'dev' into hbridge-switch

This commit is contained in:
David Woodhouse 2024-09-10 08:25:07 +01:00 committed by GitHub
commit 051de1cf46
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 268 additions and 85 deletions

View file

@ -47,6 +47,9 @@ runs:
- name: Build and push to ghcr by digest
id: build-ghcr
uses: docker/build-push-action@v6.7.0
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
with:
context: .
file: ./docker/Dockerfile
@ -70,6 +73,9 @@ runs:
- name: Build and push to dockerhub by digest
id: build-dockerhub
uses: docker/build-push-action@v6.7.0
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
with:
context: .
file: ./docker/Dockerfile

View file

@ -49,7 +49,7 @@ RUN \
zlib1g-dev=1:1.2.13.dfsg-1 \
libjpeg-dev=1:2.1.5-2 \
libfreetype-dev=2.12.1+dfsg-5+deb12u3 \
libssl-dev=3.0.14-1~deb12u1 \
libssl-dev=3.0.14-1~deb12u2 \
libffi-dev=3.4.4-1 \
libopenjp2-7=2.5.0-2 \
libtiff6=4.5.0-6+deb12u1 \
@ -96,14 +96,19 @@ RUN \
# First install requirements to leverage caching when requirements don't change
# tmpfs is for https://github.com/rust-lang/cargo/issues/8719
COPY requirements.txt requirements_optional.txt script/platformio_install_deps.py platformio.ini /
COPY requirements.txt requirements_optional.txt /
RUN --mount=type=tmpfs,target=/root/.cargo if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \
curl -L https://www.piwheels.org/cp311/cryptography-43.0.0-cp37-abi3-linux_armv7l.whl -o /tmp/cryptography-43.0.0-cp37-abi3-linux_armv7l.whl \
&& pip3 install --break-system-packages --no-cache-dir /tmp/cryptography-43.0.0-cp37-abi3-linux_armv7l.whl \
&& rm /tmp/cryptography-43.0.0-cp37-abi3-linux_armv7l.whl \
&& export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \
fi; \
CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse CARGO_HOME=/root/.cargo \
pip3 install \
--break-system-packages --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \
&& /platformio_install_deps.py /platformio.ini --libraries
--break-system-packages --no-cache-dir -r /requirements.txt -r /requirements_optional.txt
COPY script/platformio_install_deps.py platformio.ini /
RUN /platformio_install_deps.py /platformio.ini --libraries
# Avoid unsafe git error when container user and file config volume permissions don't match
RUN git config --system --add safe.directory '*'

View file

@ -137,7 +137,8 @@ void BL0942::setup() {
}
this->write_reg_(BL0942_REG_USR_WRPROT, BL0942_REG_USR_WRPROT_MAGIC);
this->write_reg_(BL0942_REG_SOFT_RESET, BL0942_REG_SOFT_RESET_MAGIC);
if (this->reset_)
this->write_reg_(BL0942_REG_SOFT_RESET, BL0942_REG_SOFT_RESET_MAGIC);
uint32_t mode = BL0942_REG_MODE_DEFAULT;
mode |= BL0942_REG_MODE_RMS_UPDATE_SEL; /* 800ms refresh time */
@ -196,6 +197,7 @@ void BL0942::received_package_(DataPacket *data) {
void BL0942::dump_config() { // NOLINT(readability-function-cognitive-complexity)
ESP_LOGCONFIG(TAG, "BL0942:");
ESP_LOGCONFIG(TAG, " Reset: %s", TRUEFALSE(this->reset_));
ESP_LOGCONFIG(TAG, " Address: %d", this->address_);
ESP_LOGCONFIG(TAG, " Nominal line frequency: %d Hz", this->line_freq_);
ESP_LOGCONFIG(TAG, " Current reference: %f", this->current_reference_);

View file

@ -93,6 +93,7 @@ class BL0942 : public PollingComponent, public uart::UARTDevice {
void set_frequency_sensor(sensor::Sensor *frequency_sensor) { frequency_sensor_ = frequency_sensor; }
void set_line_freq(LineFrequency freq) { this->line_freq_ = freq; }
void set_address(uint8_t address) { this->address_ = address; }
void set_reset(bool reset) { this->reset_ = reset; }
void set_current_reference(float current_ref) {
this->current_reference_ = current_ref;
this->current_reference_set_ = true;
@ -137,6 +138,7 @@ class BL0942 : public PollingComponent, public uart::UARTDevice {
float energy_reference_ = BL0942_EREF;
bool energy_reference_set_ = false;
uint8_t address_ = 0;
bool reset_ = false;
LineFrequency line_freq_ = LINE_FREQUENCY_50HZ;
uint32_t rx_start_ = 0;
uint32_t prev_cf_cnt_ = 0;

View file

@ -27,6 +27,7 @@ from esphome.const import (
CONF_CURRENT_REFERENCE = "current_reference"
CONF_ENERGY_REFERENCE = "energy_reference"
CONF_POWER_REFERENCE = "power_reference"
CONF_RESET = "reset"
CONF_VOLTAGE_REFERENCE = "voltage_reference"
DEPENDENCIES = ["uart"]
@ -58,19 +59,19 @@ CONFIG_SCHEMA = (
),
cv.Optional(CONF_POWER): sensor.sensor_schema(
unit_of_measurement=UNIT_WATT,
accuracy_decimals=0,
accuracy_decimals=1,
device_class=DEVICE_CLASS_POWER,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_ENERGY): sensor.sensor_schema(
unit_of_measurement=UNIT_KILOWATT_HOURS,
accuracy_decimals=0,
accuracy_decimals=3,
device_class=DEVICE_CLASS_ENERGY,
state_class=STATE_CLASS_TOTAL_INCREASING,
),
cv.Optional(CONF_FREQUENCY): sensor.sensor_schema(
unit_of_measurement=UNIT_HERTZ,
accuracy_decimals=0,
accuracy_decimals=2,
device_class=DEVICE_CLASS_FREQUENCY,
state_class=STATE_CLASS_MEASUREMENT,
),
@ -82,6 +83,7 @@ CONFIG_SCHEMA = (
),
),
cv.Optional(CONF_ADDRESS, default=0): cv.int_range(min=0, max=3),
cv.Optional(CONF_RESET, default=True): cv.boolean,
cv.Optional(CONF_CURRENT_REFERENCE): cv.float_,
cv.Optional(CONF_ENERGY_REFERENCE): cv.float_,
cv.Optional(CONF_POWER_REFERENCE): cv.float_,
@ -115,6 +117,7 @@ async def to_code(config):
cg.add(var.set_frequency_sensor(sens))
cg.add(var.set_line_freq(config[CONF_LINE_FREQUENCY]))
cg.add(var.set_address(config[CONF_ADDRESS]))
cg.add(var.set_reset(config[CONF_RESET]))
if (current_reference := config.get(CONF_CURRENT_REFERENCE, None)) is not None:
cg.add(var.set_current_reference(current_reference))
if (voltage_reference := config.get(CONF_VOLTAGE_REFERENCE, None)) is not None:

View file

@ -22,8 +22,9 @@ from esphome.helpers import write_file_if_changed
from . import defines as df, helpers, lv_validation as lvalid
from .automation import disp_update, focused_widgets, update_to_code
from .defines import CONF_ADJUSTABLE, CONF_SKIP
from .defines import add_define
from .encoders import ENCODERS_CONFIG, encoders_to_code, initial_focus_to_code
from .gradient import GRADIENT_SCHEMA, gradients_to_code
from .lv_validation import lv_bool, lv_images_used
from .lvcode import LvContext, LvglComponent
from .schemas import (
@ -128,17 +129,6 @@ for w_type in WIDGET_TYPES.values():
)(update_to_code)
lv_defines = {} # Dict of #defines to provide as build flags
def add_define(macro, value="1"):
if macro in lv_defines and lv_defines[macro] != value:
LOGGER.error(
"Redefinition of %s - was %s now %s", macro, lv_defines[macro], value
)
lv_defines[macro] = value
def as_macro(macro, value):
if value is None:
return f"#define {macro}"
@ -153,14 +143,14 @@ LV_CONF_H_FORMAT = """\
def generate_lv_conf_h():
definitions = [as_macro(m, v) for m, v in lv_defines.items()]
definitions = [as_macro(m, v) for m, v in df.lv_defines.items()]
definitions.sort()
return LV_CONF_H_FORMAT.format("\n".join(definitions))
def final_validation(config):
if pages := config.get(CONF_PAGES):
if all(p[CONF_SKIP] for p in pages):
if all(p[df.CONF_SKIP] for p in pages):
raise cv.Invalid("At least one page must not be skipped")
global_config = full_config.get()
for display_id in config[df.CONF_DISPLAYS]:
@ -185,7 +175,7 @@ def final_validation(config):
for w in focused_widgets:
path = global_config.get_path_for_id(w)
widget_conf = global_config.get_config_for_path(path[:-1])
if CONF_ADJUSTABLE in widget_conf and not widget_conf[CONF_ADJUSTABLE]:
if df.CONF_ADJUSTABLE in widget_conf and not widget_conf[df.CONF_ADJUSTABLE]:
raise cv.Invalid(
"A non adjustable arc may not be focused",
path,
@ -268,6 +258,7 @@ async def to_code(config):
await encoders_to_code(lv_component, config)
await theme_to_code(config)
await styles_to_code(config)
await gradients_to_code(config)
await set_obj_properties(lv_scr_act, config)
await add_widgets(lv_scr_act, config)
await add_pages(lv_component, config)
@ -351,6 +342,7 @@ CONFIG_SCHEMA = (
cv.Optional(df.CONF_THEME): cv.Schema(
{cv.Optional(name): obj_schema(w) for name, w in WIDGET_TYPES.items()}
),
cv.Optional(df.CONF_GRADIENTS): GRADIENT_SCHEMA,
cv.Optional(df.CONF_TOUCHSCREENS, default=None): touchscreen_schema,
cv.Optional(df.CONF_ENCODERS, default=None): ENCODERS_CONFIG,
cv.GenerateID(df.CONF_DEFAULT_GROUP): cv.declare_id(lv_group_t),

View file

@ -4,6 +4,8 @@ Constants already defined in esphome.const are not duplicated here and must be i
"""
import logging
from esphome import codegen as cg, config_validation as cv
from esphome.const import CONF_ITEMS
from esphome.core import Lambda
@ -13,8 +15,19 @@ from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
from .helpers import requires_component
LOGGER = logging.getLogger(__name__)
lvgl_ns = cg.esphome_ns.namespace("lvgl")
lv_defines = {} # Dict of #defines to provide as build flags
def add_define(macro, value="1"):
if macro in lv_defines and lv_defines[macro] != value:
LOGGER.error(
"Redefinition of %s - was %s now %s", macro, lv_defines[macro], value
)
lv_defines[macro] = value
def literal(arg):
if isinstance(arg, str):
@ -173,6 +186,9 @@ LV_ANIM = LvConstant(
"OUT_BOTTOM",
)
LV_GRAD_DIR = LvConstant("LV_GRAD_DIR_", "NONE", "HOR", "VER")
LV_DITHER = LvConstant("LV_DITHER_", "NONE", "ORDERED", "ERR_DIFF")
LOG_LEVELS = (
"TRACE",
"INFO",
@ -406,6 +422,7 @@ CONF_FLEX_ALIGN_TRACK = "flex_align_track"
CONF_FLEX_GROW = "flex_grow"
CONF_FREEZE = "freeze"
CONF_FULL_REFRESH = "full_refresh"
CONF_GRADIENTS = "gradients"
CONF_GRID_CELL_ROW_POS = "grid_cell_row_pos"
CONF_GRID_CELL_COLUMN_POS = "grid_cell_column_pos"
CONF_GRID_CELL_ROW_SPAN = "grid_cell_row_span"

View file

@ -0,0 +1,61 @@
from esphome import config_validation as cv
import esphome.codegen as cg
from esphome.const import (
CONF_COLOR,
CONF_DIRECTION,
CONF_DITHER,
CONF_ID,
CONF_POSITION,
)
from esphome.cpp_generator import MockObj
from .defines import CONF_GRADIENTS, LV_DITHER, LV_GRAD_DIR, add_define
from .lv_validation import lv_color, lv_fraction
from .lvcode import lv_assign
from .types import lv_gradient_t
CONF_STOPS = "stops"
def min_stops(value):
if len(value) < 2:
raise cv.Invalid("Must have at least 2 stops")
return value
GRADIENT_SCHEMA = cv.ensure_list(
cv.Schema(
{
cv.GenerateID(CONF_ID): cv.declare_id(lv_gradient_t),
cv.Optional(CONF_DIRECTION, default="NONE"): LV_GRAD_DIR.one_of,
cv.Optional(CONF_DITHER, default="NONE"): LV_DITHER.one_of,
cv.Required(CONF_STOPS): cv.All(
[
cv.Schema(
{
cv.Required(CONF_COLOR): lv_color,
cv.Required(CONF_POSITION): lv_fraction,
}
)
],
min_stops,
),
}
)
)
async def gradients_to_code(config):
max_stops = 2
for gradient in config.get(CONF_GRADIENTS, ()):
var = MockObj(cg.new_Pvariable(gradient[CONF_ID]), "->")
max_stops = max(max_stops, len(gradient[CONF_STOPS]))
lv_assign(var.dir, await LV_GRAD_DIR.process(gradient[CONF_DIRECTION]))
lv_assign(var.dither, await LV_DITHER.process(gradient[CONF_DITHER]))
lv_assign(var.stops_count, len(gradient[CONF_STOPS]))
for index, stop in enumerate(gradient[CONF_STOPS]):
lv_assign(var.stops[index].color, await lv_color.process(stop[CONF_COLOR]))
lv_assign(
var.stops[index].frac, await lv_fraction.process(stop[CONF_POSITION])
)
add_define("LV_GRADIENT_MAX_STOPS", max_stops)

View file

@ -1,12 +1,19 @@
from typing import Union
import esphome.codegen as cg
from esphome.components.color import ColorStruct
from esphome.components.color import CONF_HEX, ColorStruct, from_rgbw
from esphome.components.font import Font
from esphome.components.image import Image_
import esphome.config_validation as cv
from esphome.const import CONF_ARGS, CONF_COLOR, CONF_FORMAT, CONF_TIME, CONF_VALUE
from esphome.core import HexInt, Lambda
from esphome.const import (
CONF_ARGS,
CONF_COLOR,
CONF_FORMAT,
CONF_ID,
CONF_TIME,
CONF_VALUE,
)
from esphome.core import CORE, ID, Lambda
from esphome.cpp_generator import MockObj
from esphome.cpp_types import ESPTime, uint32
from esphome.helpers import cpp_string_escape
@ -23,14 +30,9 @@ from .defines import (
call_lambda,
literal,
)
from .helpers import (
esphome_fonts_used,
lv_fonts_used,
lvgl_components_required,
requires_component,
)
from .helpers import esphome_fonts_used, lv_fonts_used, requires_component
from .lvcode import lv_expr
from .types import lv_font_t, lv_img_t
from .types import lv_font_t, lv_gradient_t, lv_img_t
opacity_consts = LvConstant("LV_OPA_", "TRANSP", "COVER")
@ -59,11 +61,17 @@ def color_retmapper(value):
if isinstance(value, cv.Lambda):
return cv.returning_lambda(value)
if isinstance(value, int):
hexval = HexInt(value)
return lv_expr.color_hex(hexval)
# Must be an id
lvgl_components_required.add(CONF_COLOR)
return lv_expr.color_from(MockObj(value))
return literal(
f"lv_color_make({(value >> 16) & 0xFF}, {(value >> 8) & 0xFF}, {value & 0xFF})"
)
if isinstance(value, ID):
cval = [x for x in CORE.config[CONF_COLOR] if x[CONF_ID] == value][0]
if CONF_HEX in cval:
r, g, b = cval[CONF_HEX]
else:
r, g, b, _ = from_rgbw(cval)
return literal(f"lv_color_make({r}, {g}, {b})")
assert False
def option_string(value):
@ -132,7 +140,7 @@ radius_consts = LvConstant("LV_RADIUS_", "CIRCLE")
@schema_extractor("one_of")
def radius_validator(value):
def fraction_validator(value):
if value == SCHEMA_EXTRACT:
return radius_consts.choices
value = cv.Any(size, cv.percentage, radius_consts.one_of)(value)
@ -141,7 +149,7 @@ def radius_validator(value):
return value
radius = LValidator(radius_validator, uint32, retmapper=literal)
lv_fraction = LValidator(fraction_validator, uint32, retmapper=literal)
def id_name(value):
@ -242,6 +250,21 @@ lv_int = LValidator(cv.int_, cg.int_)
lv_brightness = LValidator(cv.percentage, cg.float_, retmapper=lambda x: int(x * 255))
def gradient_mapper(value):
return MockObj(value)
def gradient_validator(value):
return cv.use_id(lv_gradient_t)(value)
lv_gradient = LValidator(
validator=gradient_validator,
rtype=lv_gradient_t,
retmapper=gradient_mapper,
)
def is_lv_font(font):
return isinstance(font, str) and font.lower() in LV_FONTS

View file

@ -184,8 +184,9 @@ class LvContext(LambdaContext):
self.lv_component = lv_component
async def add_init_lambda(self):
cg.add(self.lv_component.add_init_lambda(await self.get_lambda()))
LvContext.added_lambda_count += 1
if self.code_list:
cg.add(self.lv_component.add_init_lambda(await self.get_lambda()))
LvContext.added_lambda_count += 1
async def __aexit__(self, exc_type, exc_val, exc_tb):
await super().__aexit__(exc_type, exc_val, exc_tb)

View file

@ -42,9 +42,6 @@ extern lv_event_code_t lv_api_event; // NOLINT
extern lv_event_code_t lv_update_event; // NOLINT
extern std::string lv_event_code_name_for(uint8_t event_code);
extern bool lv_is_pre_initialise();
#ifdef USE_LVGL_COLOR
inline lv_color_t lv_color_from(Color color) { return lv_color_make(color.red, color.green, color.blue); }
#endif // USE_LVGL_COLOR
#if LV_COLOR_DEPTH == 16
static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_565;
#elif LV_COLOR_DEPTH == 32

View file

@ -17,9 +17,9 @@ from esphome.core import TimePeriod
from esphome.schema_extractors import SCHEMA_EXTRACT
from . import defines as df, lv_validation as lvalid
from .defines import CONF_TIME_FORMAT
from .defines import CONF_TIME_FORMAT, LV_GRAD_DIR
from .helpers import add_lv_use, requires_component, validate_printf
from .lv_validation import lv_color, lv_font, lv_image
from .lv_validation import lv_color, lv_font, lv_gradient, lv_image
from .lvcode import LvglComponent, lv_event_t_ptr
from .types import (
LVEncoderListener,
@ -94,9 +94,10 @@ STYLE_PROPS = {
"arc_width": cv.positive_int,
"anim_time": lvalid.lv_milliseconds,
"bg_color": lvalid.lv_color,
"bg_grad": lv_gradient,
"bg_grad_color": lvalid.lv_color,
"bg_dither_mode": df.LvConstant("LV_DITHER_", "NONE", "ORDERED", "ERR_DIFF").one_of,
"bg_grad_dir": df.LvConstant("LV_GRAD_DIR_", "NONE", "HOR", "VER").one_of,
"bg_grad_dir": LV_GRAD_DIR.one_of,
"bg_grad_stop": lvalid.stop_value,
"bg_image_opa": lvalid.opacity,
"bg_image_recolor": lvalid.lv_color,
@ -160,7 +161,7 @@ STYLE_PROPS = {
"max_width": lvalid.pixels_or_percent,
"min_height": lvalid.pixels_or_percent,
"min_width": lvalid.pixels_or_percent,
"radius": lvalid.radius,
"radius": lvalid.lv_fraction,
"width": lvalid.size,
"x": lvalid.pixels_or_percent,
"y": lvalid.pixels_or_percent,

View file

@ -59,6 +59,7 @@ LVEncoderListener = lvgl_ns.class_("LVEncoderListener")
lv_obj_t = LvType("lv_obj_t")
lv_page_t = LvType("LvPageType", parents=(LvCompound,))
lv_img_t = LvType("lv_img_t")
lv_gradient_t = LvType("lv_grad_dsc_t")
LV_EVENT = MockObj(base="LV_EVENT_", op="")
LV_STATE = MockObj(base="LV_STATE_", op="")

View file

@ -5,6 +5,7 @@ from esphome.const import (
CONF_COLOR,
CONF_COUNT,
CONF_ID,
CONF_ITEMS,
CONF_LENGTH,
CONF_LOCAL,
CONF_RANGE_FROM,
@ -17,6 +18,7 @@ from esphome.const import (
from ..automation import action_to_code
from ..defines import (
CONF_END_VALUE,
CONF_INDICATOR,
CONF_MAIN,
CONF_PIVOT_X,
CONF_PIVOT_Y,
@ -165,7 +167,12 @@ METER_SCHEMA = {cv.Optional(CONF_SCALES): cv.ensure_list(SCALE_SCHEMA)}
class MeterType(WidgetType):
def __init__(self):
super().__init__(CONF_METER, lv_meter_t, (CONF_MAIN,), METER_SCHEMA)
super().__init__(
CONF_METER,
lv_meter_t,
(CONF_MAIN, CONF_INDICATOR, CONF_TICKS, CONF_ITEMS),
METER_SCHEMA,
)
async def to_code(self, w: Widget, config):
"""For a meter object, create and set parameters"""

View file

@ -1,13 +1,7 @@
import esphome.codegen as cg
from esphome.components.esp32 import add_idf_sdkconfig_option
import esphome.config_validation as cv
from esphome.const import (
CONF_ENABLE_IPV6,
CONF_MIN_IPV6_ADDR_COUNT,
PLATFORM_ESP32,
PLATFORM_ESP8266,
PLATFORM_RP2040,
)
from esphome.const import CONF_ENABLE_IPV6, CONF_MIN_IPV6_ADDR_COUNT
from esphome.core import CORE
CODEOWNERS = ["@esphome/core"]
@ -26,7 +20,12 @@ CONFIG_SCHEMA = cv.Schema(
): cv.All(
cv.boolean,
cv.Any(
cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040]),
cv.require_framework_version(
esp_idf=cv.Version(0, 0, 0),
esp32_arduino=cv.Version(0, 0, 0),
esp8266_arduino=cv.Version(0, 0, 0),
rp2040_arduino=cv.Version(0, 0, 0),
),
cv.boolean_false,
),
),

View file

@ -1,31 +1,28 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins
import esphome.codegen as cg
from esphome.components import display
from esphome.components.esp32 import const, only_on_variant
import esphome.config_validation as cv
from esphome.const import (
CONF_ENABLE_PIN,
CONF_HSYNC_PIN,
CONF_RESET_PIN,
CONF_BLUE,
CONF_COLOR_ORDER,
CONF_DATA_PINS,
CONF_DIMENSIONS,
CONF_ENABLE_PIN,
CONF_GREEN,
CONF_HEIGHT,
CONF_HSYNC_PIN,
CONF_ID,
CONF_IGNORE_STRAPPING_WARNING,
CONF_DIMENSIONS,
CONF_VSYNC_PIN,
CONF_WIDTH,
CONF_HEIGHT,
CONF_INVERT_COLORS,
CONF_LAMBDA,
CONF_COLOR_ORDER,
CONF_RED,
CONF_GREEN,
CONF_BLUE,
CONF_NUMBER,
CONF_OFFSET_HEIGHT,
CONF_OFFSET_WIDTH,
CONF_INVERT_COLORS,
)
from esphome.components.esp32 import (
only_on_variant,
const,
CONF_RED,
CONF_RESET_PIN,
CONF_VSYNC_PIN,
CONF_WIDTH,
)
DEPENDENCIES = ["esp32"]

View file

@ -6,9 +6,14 @@ namespace esphome {
namespace rpi_dpi_rgb {
void RpiDpiRgb::setup() {
esph_log_config(TAG, "Setting up RPI_DPI_RGB");
ESP_LOGCONFIG(TAG, "Setting up RPI_DPI_RGB");
this->reset_display_();
esp_lcd_rgb_panel_config_t config{};
config.flags.fb_in_psram = 1;
#if ESP_IDF_VERSION_MAJOR >= 5
config.bounce_buffer_size_px = this->width_ * 10;
config.num_fbs = 1;
#endif // ESP_IDF_VERSION_MAJOR
config.timings.h_res = this->width_;
config.timings.v_res = this->height_;
config.timings.hsync_pulse_width = this->hsync_pulse_width_;
@ -20,7 +25,6 @@ void RpiDpiRgb::setup() {
config.timings.flags.pclk_active_neg = this->pclk_inverted_;
config.timings.pclk_hz = this->pclk_frequency_;
config.clk_src = LCD_CLK_SRC_PLL160M;
config.sram_trans_align = 64;
config.psram_trans_align = 64;
size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]);
for (size_t i = 0; i != data_pin_count; i++) {
@ -34,11 +38,19 @@ void RpiDpiRgb::setup() {
config.pclk_gpio_num = this->pclk_pin_->get_pin();
esp_err_t err = esp_lcd_new_rgb_panel(&config, &this->handle_);
if (err != ESP_OK) {
esph_log_e(TAG, "lcd_new_rgb_panel failed: %s", esp_err_to_name(err));
ESP_LOGE(TAG, "lcd_new_rgb_panel failed: %s", esp_err_to_name(err));
this->mark_failed();
return;
}
ESP_ERROR_CHECK(esp_lcd_panel_reset(this->handle_));
ESP_ERROR_CHECK(esp_lcd_panel_init(this->handle_));
esph_log_config(TAG, "RPI_DPI_RGB setup complete");
ESP_LOGCONFIG(TAG, "RPI_DPI_RGB setup complete");
}
void RpiDpiRgb::loop() {
#if ESP_IDF_VERSION_MAJOR >= 5
if (this->handle_ != nullptr)
esp_lcd_rgb_panel_restart(this->handle_);
#endif // ESP_IDF_VERSION_MAJOR
}
void RpiDpiRgb::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order,
@ -53,7 +65,7 @@ void RpiDpiRgb::draw_pixels_at(int x_start, int y_start, int w, int h, const uin
}
x_start += this->offset_x_;
y_start += this->offset_y_;
esp_err_t err;
esp_err_t err = ESP_OK;
// x_ and y_offset are offsets into the source buffer, unrelated to our own offsets into the display.
if (x_offset == 0 && x_pad == 0 && y_offset == 0) {
// we could deal here with a non-zero y_offset, but if x_offset is zero, y_offset probably will be so don't bother
@ -69,7 +81,7 @@ void RpiDpiRgb::draw_pixels_at(int x_start, int y_start, int w, int h, const uin
}
}
if (err != ESP_OK)
esph_log_e(TAG, "lcd_lcd_panel_draw_bitmap failed: %s", esp_err_to_name(err));
ESP_LOGE(TAG, "lcd_lcd_panel_draw_bitmap failed: %s", esp_err_to_name(err));
}
void RpiDpiRgb::draw_pixel_at(int x, int y, Color color) {

View file

@ -23,6 +23,7 @@ class RpiDpiRgb : public display::Display {
public:
void update() override { this->do_update_(); }
void setup() override;
void loop() override;
void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order,
display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) override;
void draw_pixel_at(int x, int y, Color color) override;

View file

@ -2045,6 +2045,7 @@ def require_framework_version(
esp32_arduino=None,
esp8266_arduino=None,
rp2040_arduino=None,
bk72xx_libretiny=None,
host=None,
max_version=False,
extra_message=None,
@ -2059,6 +2060,13 @@ def require_framework_version(
msg += f". {extra_message}"
raise Invalid(msg)
required = esp_idf
elif CORE.is_bk72xx and framework == "arduino":
if bk72xx_libretiny is None:
msg = "This feature is incompatible with BK72XX"
if extra_message:
msg += f". {extra_message}"
raise Invalid(msg)
required = bk72xx_libretiny
elif CORE.is_esp32 and framework == "arduino":
if esp32_arduino is None:
msg = "This feature is incompatible with ESP32 using arduino framework"

View file

@ -10,6 +10,7 @@ sensor:
- platform: bl0942
address: 0
line_frequency: 50Hz
reset: false
voltage:
name: BL0942 Voltage
current:

View file

@ -8,6 +8,7 @@ uart:
sensor:
- platform: bl0942
reset: true
voltage:
name: BL0942 Voltage
current:

View file

@ -1,12 +1,32 @@
lvgl:
log_level: TRACE
bg_color: light_blue
disp_bg_color: 0xffff00
disp_bg_color: color_id
disp_bg_image: cat_image
theme:
obj:
border_width: 1
gradients:
- id: color_bar
direction: hor
dither: err_diff
stops:
- color: 0xFF0000
position: 0
- color: 0xFFFF00
position: 42
- color: 0x00FF00
position: 84
- color: 0x00FFFF
position: 127
- color: 0x0000FF
position: 169
- color: 0xFF00FF
position: 212
- color: 0xFF0000
position: 255
style_definitions:
- id: style_test
bg_color: 0x2F8CD8
@ -31,7 +51,7 @@ lvgl:
- id: date_style
text_font: roboto10
align: center
text_color: 0x000000
text_color: color_id2
bg_opa: cover
radius: 4
pad_all: 2
@ -386,6 +406,22 @@ lvgl:
- id: page2
widgets:
- slider:
min_value: 0
max_value: 255
bg_opa: cover
bg_grad: color_bar
radius: 0
indicator:
bg_opa: transp
knob:
radius: 1
width: 4
height: 10%
bg_color: 0x000000
width: 100%
height: 10%
align: top_mid
- button:
styles: spin_button
id: spin_up
@ -586,3 +622,13 @@ image:
color:
- id: light_blue
hex: "3340FF"
- id: color_id
red: 0.5
green: 0.5
blue: 0.5
white: 0.5
- id: color_id2
red_int: 0xFF
green_int: 123
blue_int: 64
white_int: 255