mirror of
https://github.com/esphome/esphome.git
synced 2026-10-03 09:46:03 +00:00
[mipi][mipi_spi][mipi_dsi][mipi_rgb] Transform cleanup (#17405)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
83aaed71e1
commit
e1719cd85d
@@ -24,6 +24,9 @@ spi:
|
||||
mosi_pin: 6
|
||||
clk_pin: 7
|
||||
|
||||
psram:
|
||||
mode: quad
|
||||
|
||||
display:
|
||||
- platform: mipi_spi
|
||||
id: lcd_display
|
||||
|
||||
@@ -19,6 +19,9 @@ spi:
|
||||
mosi_pin: 6
|
||||
clk_pin: 7
|
||||
|
||||
psram:
|
||||
mode: quad
|
||||
|
||||
display:
|
||||
- platform: mipi_spi
|
||||
id: lcd_display
|
||||
|
||||
@@ -4,6 +4,9 @@ esphome:
|
||||
esp32:
|
||||
board: esp32s3box
|
||||
|
||||
psram:
|
||||
mode: octal
|
||||
|
||||
image:
|
||||
defaults:
|
||||
type: rgb565
|
||||
|
||||
@@ -71,6 +71,18 @@ def test_configuration_errors(set_core_config: SetCoreConfigCallable) -> None:
|
||||
}
|
||||
)
|
||||
|
||||
# DSI displays cannot swap axes; enabling swap_xy reports a clear error.
|
||||
with pytest.raises(cv.Invalid, match="'swap_xy' is not supported by this model"):
|
||||
CONFIG_SCHEMA(
|
||||
{
|
||||
"model": "custom",
|
||||
"init_sequence": [[0xA0, 0x01]],
|
||||
"lane_bit_rate": "1.5Gbps",
|
||||
"dimensions": {"width": 320, "height": 240},
|
||||
"transform": {"mirror_x": True, "mirror_y": True, "swap_xy": True},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def test_configuration_success(set_core_config: SetCoreConfigCallable) -> None:
|
||||
"""Test successful configuration validation."""
|
||||
@@ -116,6 +128,33 @@ def test_configuration_success(set_core_config: SetCoreConfigCallable) -> None:
|
||||
CONFIG_SCHEMA(config)
|
||||
|
||||
|
||||
def test_metadata_records_rotation(set_core_config: SetCoreConfigCallable) -> None:
|
||||
"""A configured display rotation is recorded in the metadata.
|
||||
|
||||
LVGL relies on this to flag a rotation set in the display config (see the
|
||||
mipi_spi tests for the end-to-end LVGL rejection).
|
||||
"""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32-p4-evboard", KEY_VARIANT: VARIANT_ESP32P4},
|
||||
)
|
||||
|
||||
from esphome.components.display import get_display_metadata
|
||||
from esphome.components.mipi_dsi.display import CONFIG_SCHEMA
|
||||
|
||||
base = {
|
||||
"model": "custom",
|
||||
"init_sequence": [[0xA0, 0x01]],
|
||||
"lane_bit_rate": "1.5Gbps",
|
||||
"dimensions": {"width": 320, "height": 240},
|
||||
}
|
||||
config = CONFIG_SCHEMA({**base, "id": "rotated", "rotation": 90})
|
||||
assert get_display_metadata(config["id"]).rotation == 90
|
||||
|
||||
config = CONFIG_SCHEMA({**base, "id": "unrotated"})
|
||||
assert get_display_metadata(config["id"]).rotation == 0
|
||||
|
||||
|
||||
def test_code_generation(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
component_fixture_path: Callable[[str], Path],
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
"""Tests for mipi_rgb configuration validation, in particular the per-model
|
||||
``requires`` component check (see esphome.components.mipi.DriverChip.check_requirements)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome import config_validation as cv
|
||||
from esphome.components.esp32 import KEY_BOARD, KEY_VARIANT, VARIANT_ESP32S3
|
||||
from esphome.components.mipi_rgb.display import CONFIG_SCHEMA, FINAL_VALIDATE_SCHEMA
|
||||
|
||||
# Importing pca9554 registers its pin schema with pins.PIN_SCHEMA_REGISTRY so that
|
||||
# models (e.g. SEEED-INDICATOR-D1) that reference pca9554-backed pins in their
|
||||
# defaults can be validated by the mipi_rgb CONFIG_SCHEMA in this test.
|
||||
import esphome.components.pca9554 # noqa: F401
|
||||
from esphome.const import PlatformFramework
|
||||
from esphome.core import CORE
|
||||
from esphome.types import ConfigType
|
||||
from tests.component_tests.types import SetCoreConfigCallable
|
||||
|
||||
|
||||
def _validated(config: ConfigType) -> ConfigType:
|
||||
"""Run the component config schema followed by the final validation."""
|
||||
config = CONFIG_SCHEMA(config)
|
||||
FINAL_VALIDATE_SCHEMA(config)
|
||||
return config
|
||||
|
||||
|
||||
def test_model_requires_psram(set_core_config: SetCoreConfigCallable) -> None:
|
||||
"""A model known to have PSRAM on its board rejects a config without it.
|
||||
|
||||
RGB parallel displays always need a full framebuffer, so every model in this
|
||||
component is expected to carry ``requires={"psram", ...}``. This board has no
|
||||
other requirements, so its check is exercised in isolation here.
|
||||
"""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32-s3-devkitc-1", KEY_VARIANT: VARIANT_ESP32S3},
|
||||
)
|
||||
CORE.raw_config = {}
|
||||
|
||||
with pytest.raises(
|
||||
cv.Invalid,
|
||||
match=r"ESP32-8048S070 requires component 'psram' to be configured",
|
||||
):
|
||||
_validated({"model": "ESP32-8048S070"})
|
||||
|
||||
|
||||
def test_model_requires_psram_satisfied(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
set_component_config: Any,
|
||||
) -> None:
|
||||
"""The same board model validates once PSRAM is configured."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32-s3-devkitc-1", KEY_VARIANT: VARIANT_ESP32S3},
|
||||
)
|
||||
set_component_config("psram", True)
|
||||
CORE.raw_config = {"psram": True}
|
||||
|
||||
config = _validated({"model": "ESP32-8048S070"})
|
||||
assert config["model"] == "ESP32-8048S070"
|
||||
|
||||
|
||||
def test_model_requires_psram_and_expander(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
set_component_config: Any,
|
||||
) -> None:
|
||||
"""A model that also depends on an I2C GPIO expander lists both when missing."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32-s3-devkitc-1", KEY_VARIANT: VARIANT_ESP32S3},
|
||||
)
|
||||
# Only satisfy one of the two requirements.
|
||||
set_component_config("psram", True)
|
||||
CORE.raw_config = {"psram": True}
|
||||
|
||||
with pytest.raises(
|
||||
cv.Invalid,
|
||||
match=r"SEEED-INDICATOR-D1 requires component 'pca9554' to be configured",
|
||||
):
|
||||
_validated(
|
||||
{
|
||||
"model": "SEEED-INDICATOR-D1",
|
||||
"spi_id": "spi_bus",
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,137 @@
|
||||
"""Tests for mipi_rgb configuration validation."""
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome import config_validation as cv
|
||||
|
||||
# Importing these registers their pin schemas with pins.PIN_SCHEMA_REGISTRY so that
|
||||
# models referencing IO-expander-backed pins in their defaults (e.g. the LilyGO
|
||||
# T-RGB boards via xl9535, SEEED-INDICATOR-D1 via pca9554, or the Waveshare panels
|
||||
# via ch422g) can be validated by the mipi_rgb CONFIG_SCHEMA in this test.
|
||||
import esphome.components.ch422g # noqa: F401
|
||||
from esphome.components.display import get_display_metadata
|
||||
from esphome.components.esp32 import KEY_BOARD, VARIANT_ESP32S3
|
||||
import esphome.components.pca9554 # noqa: F401
|
||||
import esphome.components.xl9535 # noqa: F401
|
||||
from esphome.const import (
|
||||
CONF_BLUE,
|
||||
CONF_DIMENSIONS,
|
||||
CONF_GREEN,
|
||||
CONF_HEIGHT,
|
||||
CONF_INIT_SEQUENCE,
|
||||
CONF_MIRROR_X,
|
||||
CONF_MIRROR_Y,
|
||||
CONF_RED,
|
||||
CONF_SWAP_XY,
|
||||
CONF_WIDTH,
|
||||
KEY_VARIANT,
|
||||
PlatformFramework,
|
||||
)
|
||||
from tests.component_tests.types import SetCoreConfigCallable
|
||||
|
||||
# A generic set of data pins so that models without a default pin assignment
|
||||
# (e.g. CUSTOM and RPI) still validate.
|
||||
DATA_PINS = {
|
||||
CONF_RED: [1, 2, 3, 4, 5],
|
||||
CONF_GREEN: [6, 7, 8, 9, 10, 11],
|
||||
CONF_BLUE: [12, 13, 14, 15, 16],
|
||||
}
|
||||
|
||||
|
||||
def _set_s3(set_core_config: SetCoreConfigCallable) -> None:
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={
|
||||
KEY_BOARD: "esp32-s3-devkitc-1",
|
||||
KEY_VARIANT: VARIANT_ESP32S3,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def test_configuration_success(set_core_config: SetCoreConfigCallable) -> None:
|
||||
"""Every predefined model validates once required defaults are supplied."""
|
||||
_set_s3(set_core_config)
|
||||
|
||||
from esphome.components.mipi_rgb.display import CONFIG_SCHEMA, MODELS
|
||||
|
||||
for name, model in MODELS.items():
|
||||
config = {"model": name, "data_pins": DATA_PINS, "pclk_pin": 21}
|
||||
if model.initsequence is None:
|
||||
config[CONF_INIT_SEQUENCE] = [[0xA0, 0x01]]
|
||||
if not model.get_default(CONF_WIDTH):
|
||||
config[CONF_DIMENSIONS] = {CONF_WIDTH: 480, CONF_HEIGHT: 480}
|
||||
CONFIG_SCHEMA(config)
|
||||
|
||||
|
||||
def test_transform_matches_model_support(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""The transform schema only accepts the axes a model actually supports."""
|
||||
_set_s3(set_core_config)
|
||||
|
||||
from esphome.components.mipi_rgb.display import CONFIG_SCHEMA, MODELS
|
||||
|
||||
# ESP32-8048S070 supports both mirror axes but not swap_xy (RGB displays
|
||||
# never support axis swapping).
|
||||
model = MODELS["ESP32-8048S070"]
|
||||
assert model.transforms == {CONF_MIRROR_X, CONF_MIRROR_Y}
|
||||
|
||||
base = {"model": "ESP32-8048S070", "data_pins": DATA_PINS, "pclk_pin": 21}
|
||||
CONFIG_SCHEMA({**base, "transform": {"mirror_x": True, "mirror_y": False}})
|
||||
|
||||
# An unsupported axis may be explicitly disabled (a harmless no-op)...
|
||||
CONFIG_SCHEMA(
|
||||
{**base, "transform": {"mirror_x": True, "mirror_y": False, "swap_xy": False}}
|
||||
)
|
||||
|
||||
# ...but enabling it reports a clear, model-specific error.
|
||||
with pytest.raises(cv.Invalid, match="'swap_xy' is not supported by this model"):
|
||||
CONFIG_SCHEMA(
|
||||
{
|
||||
**base,
|
||||
"transform": {"mirror_x": True, "mirror_y": False, "swap_xy": True},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def test_st7701s_only_supports_mirror_x(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""ST7701S panels shorter than full height only expose mirror_x.
|
||||
|
||||
mirror_y only works at full height (864px), so the LilyGO 480px panels must
|
||||
reject a mirror_y transform.
|
||||
"""
|
||||
_set_s3(set_core_config)
|
||||
|
||||
from esphome.components.mipi_rgb.display import CONFIG_SCHEMA, MODELS
|
||||
|
||||
model = MODELS["T-RGB-2.1"]
|
||||
assert model.transforms == {CONF_MIRROR_X}
|
||||
assert CONF_SWAP_XY not in model.transforms
|
||||
|
||||
base = {"model": "T-RGB-2.1"}
|
||||
CONFIG_SCHEMA({**base, "transform": {"mirror_x": True}})
|
||||
|
||||
with pytest.raises(cv.Invalid, match="'mirror_y' is not supported by this model"):
|
||||
CONFIG_SCHEMA({**base, "transform": {"mirror_x": True, "mirror_y": True}})
|
||||
|
||||
|
||||
def test_metadata_records_rotation(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""A configured display rotation is recorded in the metadata.
|
||||
|
||||
LVGL relies on this to flag a rotation set in the display config (see the
|
||||
mipi_spi tests for the end-to-end LVGL rejection).
|
||||
"""
|
||||
_set_s3(set_core_config)
|
||||
|
||||
from esphome.components.mipi_rgb.display import CONFIG_SCHEMA
|
||||
|
||||
base = {"model": "ESP32-8048S070", "data_pins": DATA_PINS, "pclk_pin": 21}
|
||||
config = CONFIG_SCHEMA({**base, "id": "rotated", "rotation": 90})
|
||||
assert get_display_metadata(config["id"]).rotation == 90
|
||||
|
||||
config = CONFIG_SCHEMA({**base, "id": "unrotated"})
|
||||
assert get_display_metadata(config["id"]).rotation == 0
|
||||
@@ -3,6 +3,9 @@
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome import config_validation as cv
|
||||
from esphome.components.const import BYTE_ORDER_BIG
|
||||
from esphome.components.display import get_all_display_metadata, get_display_metadata
|
||||
from esphome.components.esp32 import (
|
||||
@@ -13,6 +16,7 @@ from esphome.components.esp32 import (
|
||||
)
|
||||
from esphome.components.mipi_spi.display import CONFIG_SCHEMA, FINAL_VALIDATE_SCHEMA
|
||||
from esphome.const import PlatformFramework
|
||||
from esphome.core import ID
|
||||
from tests.component_tests.types import SetCoreConfigCallable
|
||||
|
||||
|
||||
@@ -23,6 +27,18 @@ def validated_config(config):
|
||||
return config
|
||||
|
||||
|
||||
def _lvgl_config(display_id: str) -> dict:
|
||||
"""Build a minimal LVGL config dict referencing the given display id."""
|
||||
return {
|
||||
"displays": [ID(display_id, True)],
|
||||
"log_level": "WARN",
|
||||
"color_depth": 16,
|
||||
"transparency_key": 0x000400,
|
||||
"draw_rounding": 2,
|
||||
"buffer_size": 0,
|
||||
}
|
||||
|
||||
|
||||
def test_metadata_native_quad_default_test_card(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
@@ -91,7 +107,7 @@ def test_metadata_no_swap_xy_not_full_hardware_rotation(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32-s3-devkitc-1", KEY_VARIANT: VARIANT_ESP32S3},
|
||||
)
|
||||
# JC3248W535 has swap_xy=cv.UNDEFINED -> transforms={mirror_x, mirror_y} only
|
||||
# JC3248W535 has transforms={mirror_x, mirror_y} only
|
||||
config = CONFIG_SCHEMA({"model": "JC3248W535", "id": "jc3248w535"})
|
||||
meta = get_display_metadata(config["id"])
|
||||
assert meta is not None
|
||||
@@ -166,3 +182,69 @@ def test_metadata_via_code_generation_lvgl(
|
||||
assert meta.height == 160
|
||||
assert meta.has_hardware_rotation is True
|
||||
assert meta.byte_order == BYTE_ORDER_BIG
|
||||
|
||||
|
||||
def test_metadata_records_rotation(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""A configured display rotation is recorded in the metadata."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
config = CONFIG_SCHEMA(
|
||||
{"model": "ST7735", "dc_pin": 18, "id": "rotated", "rotation": 90}
|
||||
)
|
||||
meta = get_display_metadata(config["id"])
|
||||
assert meta is not None
|
||||
assert meta.rotation == 90
|
||||
|
||||
|
||||
def test_metadata_rotation_defaults_to_zero(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""A display without a rotation reports rotation 0 in its metadata."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
config = CONFIG_SCHEMA({"model": "ST7735", "dc_pin": 18, "id": "unrotated"})
|
||||
meta = get_display_metadata(config["id"])
|
||||
assert meta is not None
|
||||
assert meta.rotation == 0
|
||||
|
||||
|
||||
def test_rotation_flagged_when_used_with_lvgl(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""A display with a rotation is rejected when driven by LVGL.
|
||||
|
||||
LVGL manages its own rotation, so a rotation set in the display config must be
|
||||
flagged and the user directed to configure it in the LVGL block instead. This
|
||||
exercises the full chain: the mipi_spi schema records the rotation in the
|
||||
display metadata, and LVGL's final validation reports it.
|
||||
"""
|
||||
from esphome.components.lvgl import final_validation
|
||||
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
CONFIG_SCHEMA({"model": "ST7735", "dc_pin": 18, "id": "rotated", "rotation": 90})
|
||||
with pytest.raises(cv.Invalid, match="rotation.*not compatible with LVGL"):
|
||||
final_validation([_lvgl_config("rotated")])
|
||||
|
||||
|
||||
def test_no_rotation_accepted_with_lvgl(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""A display without a rotation validates cleanly when driven by LVGL."""
|
||||
from esphome.components.lvgl import final_validation
|
||||
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
CONFIG_SCHEMA({"model": "ST7735", "dc_pin": 18, "id": "unrotated"})
|
||||
# Should not raise.
|
||||
final_validation([_lvgl_config("unrotated")])
|
||||
|
||||
@@ -6,10 +6,13 @@ from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome import config_validation as cv
|
||||
from esphome.components.display import CONF_SHOW_TEST_CARD
|
||||
from esphome.components.esp32 import KEY_BOARD, KEY_VARIANT, VARIANT_ESP32
|
||||
from esphome.components.mipi import DriverChip
|
||||
from esphome.components.mipi_spi.display import CONFIG_SCHEMA, FINAL_VALIDATE_SCHEMA
|
||||
from esphome.const import CONF_BUFFER_SIZE, PlatformFramework
|
||||
from esphome.core import CORE
|
||||
from esphome.types import ConfigType
|
||||
from tests.component_tests.types import SetCoreConfigCallable
|
||||
|
||||
@@ -183,3 +186,77 @@ def test_buffer_size_selected_when_lvgl_with_test_card(
|
||||
)
|
||||
|
||||
assert config[CONF_BUFFER_SIZE] == pytest.approx(1.0 / 4)
|
||||
|
||||
|
||||
def test_requires_missing_single_component_raises() -> None:
|
||||
"""A model that requires a single component raises when it is absent."""
|
||||
CORE.raw_config = {}
|
||||
chip = DriverChip("TEST-REQUIRES-PSRAM", requires={"psram"})
|
||||
|
||||
with pytest.raises(
|
||||
cv.Invalid,
|
||||
match=r"TEST-REQUIRES-PSRAM requires component 'psram' to be configured",
|
||||
):
|
||||
chip.check_requirements()
|
||||
|
||||
|
||||
def test_requires_missing_multiple_components_raises() -> None:
|
||||
"""A model that requires several components lists all the missing ones, pluralized."""
|
||||
CORE.raw_config = {}
|
||||
chip = DriverChip("TEST-REQUIRES-MULTI", requires={"psram", "pca9554"})
|
||||
|
||||
with pytest.raises(
|
||||
cv.Invalid,
|
||||
match=r"TEST-REQUIRES-MULTI requires components '.*' to be configured",
|
||||
) as excinfo:
|
||||
chip.check_requirements()
|
||||
assert "psram" in str(excinfo.value)
|
||||
assert "pca9554" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_requires_satisfied_does_not_raise() -> None:
|
||||
"""No error is raised once all the required components are configured."""
|
||||
CORE.raw_config = {"psram": True, "pca9554": []}
|
||||
chip = DriverChip("TEST-REQUIRES-SATISFIED", requires={"psram", "pca9554"})
|
||||
|
||||
chip.check_requirements() # Should not raise
|
||||
|
||||
|
||||
def test_requires_absent_does_not_raise() -> None:
|
||||
"""Models without a requires set are unaffected by the check."""
|
||||
CORE.raw_config = {}
|
||||
chip = DriverChip("TEST-REQUIRES-NONE")
|
||||
|
||||
chip.check_requirements() # Should not raise
|
||||
|
||||
|
||||
def test_predefined_model_requires_psram(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""A predefined board model known to have PSRAM rejects a config without it."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
CORE.raw_config = {}
|
||||
|
||||
with pytest.raises(
|
||||
cv.Invalid, match=r"S3BOX requires component 'psram' to be configured"
|
||||
):
|
||||
_validated({"model": "s3box"})
|
||||
|
||||
|
||||
def test_predefined_model_requires_psram_satisfied(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
set_component_config: Any,
|
||||
) -> None:
|
||||
"""The same board model validates once PSRAM is configured."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
set_component_config("psram", True)
|
||||
CORE.raw_config = {"psram": True}
|
||||
|
||||
config = _validated({"model": "s3box"})
|
||||
assert config["model"] == "S3BOX"
|
||||
|
||||
@@ -136,7 +136,7 @@ def test_dimension_validation(
|
||||
"model": "JC3248W535",
|
||||
"transform": {"mirror_x": False, "mirror_y": True, "swap_xy": True},
|
||||
},
|
||||
"Axis swapping not supported by this model",
|
||||
"'swap_xy' is not supported by this model",
|
||||
id="axis_swapping_not_supported",
|
||||
),
|
||||
pytest.param(
|
||||
|
||||
@@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -222,6 +223,7 @@ class TestNewModelVariants:
|
||||
def test_m5core2_with_native_dimensions(
|
||||
self,
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
set_component_config: Callable[[str, Any], None],
|
||||
) -> None:
|
||||
"""Test M5CORE2 variant with reset native_width and native_height."""
|
||||
set_core_config(
|
||||
@@ -231,6 +233,8 @@ class TestNewModelVariants:
|
||||
KEY_VARIANT: VARIANT_ESP32S3,
|
||||
},
|
||||
)
|
||||
# M5CORE2 has PSRAM on board and requires it to be configured
|
||||
set_component_config("psram", True)
|
||||
|
||||
# M5CORE2 should validate successfully
|
||||
config = validated_config({"model": "M5CORE2"})
|
||||
|
||||
@@ -24,6 +24,9 @@ spi:
|
||||
mosi_pin: 6
|
||||
clk_pin: 7
|
||||
|
||||
psram:
|
||||
mode: quad
|
||||
|
||||
display:
|
||||
- platform: mipi_spi
|
||||
id: lcd_display
|
||||
|
||||
@@ -23,6 +23,9 @@ spi:
|
||||
mosi_pin: 6
|
||||
clk_pin: 7
|
||||
|
||||
psram:
|
||||
mode: quad
|
||||
|
||||
display:
|
||||
- platform: mipi_spi
|
||||
id: lcd_display
|
||||
|
||||
Reference in New Issue
Block a user