mirror of
https://github.com/esphome/esphome.git
synced 2026-07-10 17:05:36 +00:00
[mipi_spi] Suppress sequence errors when page selection used (#17176)
This commit is contained in:
@@ -120,6 +120,7 @@ CSCON = 0xF0
|
||||
PWCTR6 = 0xF6
|
||||
ADJCTL3 = 0xF7
|
||||
PAGESEL = 0xFE
|
||||
PAGESEL1 = 0xFF
|
||||
|
||||
MADCTL_MY = 0x80 # Bit 7 Bottom to top
|
||||
MADCTL_MX = 0x40 # Bit 6 Right to left
|
||||
|
||||
@@ -17,6 +17,8 @@ from esphome.components.mipi import (
|
||||
MADCTL,
|
||||
MODE_BGR,
|
||||
MODE_RGB,
|
||||
PAGESEL,
|
||||
PAGESEL1,
|
||||
PIXFMT,
|
||||
DriverChip,
|
||||
dimension_schema,
|
||||
@@ -276,14 +278,16 @@ def customise_schema(config):
|
||||
# Check for invalid combinations of MADCTL config
|
||||
if init_sequence := config.get(CONF_INIT_SEQUENCE):
|
||||
commands = [x[0] for x in init_sequence]
|
||||
if MADCTL in commands and CONF_TRANSFORM in config:
|
||||
raise cv.Invalid(
|
||||
f"transform is not supported when MADCTL ({MADCTL:#X}) is in the init sequence"
|
||||
)
|
||||
if PIXFMT in commands:
|
||||
raise cv.Invalid(
|
||||
f"PIXFMT ({PIXFMT:#X}) should not be in the init sequence, it will be set automatically"
|
||||
)
|
||||
# If there is page swapping, we can't rely on recognising common commands
|
||||
if PAGESEL not in commands and PAGESEL1 not in commands:
|
||||
if MADCTL in commands and CONF_TRANSFORM in config:
|
||||
raise cv.Invalid(
|
||||
f"transform is not supported when MADCTL ({MADCTL:#X}) is in the init sequence"
|
||||
)
|
||||
if PIXFMT in commands:
|
||||
raise cv.Invalid(
|
||||
f"PIXFMT ({PIXFMT:#X}) should not be in the init sequence, it will be set automatically"
|
||||
)
|
||||
|
||||
if bus_mode == TYPE_QUAD and CONF_DC_PIN in config:
|
||||
raise cv.Invalid("DC pin is not supported in quad mode")
|
||||
|
||||
@@ -176,7 +176,6 @@ class MipiSpi : public display::Display,
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
auto arg_byte = vec[index];
|
||||
switch (cmd) {
|
||||
case SLEEP_OUT: {
|
||||
// are we ready, boots?
|
||||
@@ -187,13 +186,6 @@ class MipiSpi : public display::Display,
|
||||
}
|
||||
} break;
|
||||
|
||||
case INVERT_ON:
|
||||
this->invert_colors_ = true;
|
||||
break;
|
||||
case BRIGHTNESS:
|
||||
this->brightness_ = arg_byte;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
"""Combined tests for PAGESEL/PAGESEL1 behaviour with MADCTL/PIXFMT.
|
||||
|
||||
Covers both the suppression behaviour (when PAGESEL or PAGESEL1 are present)
|
||||
and the error behaviour when neither page-selection command is present.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome.components.esp32 import KEY_BOARD, KEY_VARIANT, VARIANT_ESP32
|
||||
from esphome.components.mipi import MADCTL, PAGESEL, PAGESEL1, PIXFMT
|
||||
from esphome.components.mipi_spi.display import CONFIG_SCHEMA, FINAL_VALIDATE_SCHEMA
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import PlatformFramework
|
||||
from tests.component_tests.types import SetCoreConfigCallable
|
||||
|
||||
|
||||
def validated_config(config: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Run schema + final validation and return the validated config."""
|
||||
cfg = CONFIG_SCHEMA(config)
|
||||
FINAL_VALIDATE_SCHEMA(cfg)
|
||||
return cfg
|
||||
|
||||
|
||||
def test_madctl_error_suppressed_when_pagesel_present(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""If PAGESEL is present in init_sequence, MADCTL presence must not raise an error."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
|
||||
cfg = {
|
||||
"model": "custom",
|
||||
"dc_pin": 18,
|
||||
"dimensions": {"width": 320, "height": 240},
|
||||
"transform": {"mirror_x": True, "mirror_y": True, "swap_xy": False},
|
||||
"init_sequence": [[PAGESEL, 0x00], [MADCTL, 0x01]],
|
||||
}
|
||||
|
||||
# Should not raise
|
||||
validated = validated_config(cfg)
|
||||
assert validated is not None
|
||||
|
||||
|
||||
def test_pixfmt_error_suppressed_when_pagesel1_present(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""If PAGESEL1 is present in init_sequence, PIXFMT presence must not raise an error."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
|
||||
cfg = {
|
||||
"model": "custom",
|
||||
"dc_pin": 18,
|
||||
"dimensions": {"width": 320, "height": 240},
|
||||
"init_sequence": [[PAGESEL1, 0x00], [PIXFMT, 0x01]],
|
||||
}
|
||||
|
||||
# Should not raise
|
||||
validated = validated_config(cfg)
|
||||
assert validated is not None
|
||||
|
||||
|
||||
def test_madctl_raises_without_pagesel(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""MADCTL in the init_sequence should raise when a transform is configured and
|
||||
no PAGESEL/PAGESEL1 is present.
|
||||
"""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
|
||||
cfg: dict[str, Any] = {
|
||||
"model": "custom",
|
||||
"dc_pin": 18,
|
||||
"dimensions": {"width": 320, "height": 240},
|
||||
"transform": {"mirror_x": True, "mirror_y": True, "swap_xy": False},
|
||||
"init_sequence": [[MADCTL, 0x01]],
|
||||
}
|
||||
|
||||
with pytest.raises(cv.Invalid, match=r"MADCTL .* in the init sequence"):
|
||||
CONFIG_SCHEMA(cfg)
|
||||
|
||||
|
||||
def test_pixfmt_raises_without_pagesel1(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""PIXFMT in the init_sequence should raise when no PAGESEL/PAGESEL1 is present."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
|
||||
cfg: dict[str, Any] = {
|
||||
"model": "custom",
|
||||
"dc_pin": 18,
|
||||
"dimensions": {"width": 320, "height": 240},
|
||||
"init_sequence": [[PIXFMT, 0x01]],
|
||||
}
|
||||
|
||||
with pytest.raises(
|
||||
cv.Invalid, match=r"PIXFMT .* should not be in the init sequence"
|
||||
):
|
||||
CONFIG_SCHEMA(cfg)
|
||||
Reference in New Issue
Block a user