mirror of
https://github.com/esphome/esphome.git
synced 2026-01-09 19:50:49 -07:00
[psram] Require mode for S3 (#11470)
Co-authored-by: clydeps <U5yx99dok9>
This commit is contained in:
@@ -4,6 +4,7 @@ from esphome import automation, pins
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import i2c
|
||||
from esphome.components.esp32 import add_idf_component
|
||||
from esphome.components.psram import DOMAIN as psram_domain
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_BRIGHTNESS,
|
||||
@@ -26,10 +27,9 @@ import esphome.final_validate as fv
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
AUTO_LOAD = ["camera"]
|
||||
DEPENDENCIES = ["esp32"]
|
||||
|
||||
AUTO_LOAD = ["camera", "psram"]
|
||||
|
||||
esp32_camera_ns = cg.esphome_ns.namespace("esp32_camera")
|
||||
ESP32Camera = esp32_camera_ns.class_("ESP32Camera", cg.PollingComponent, cg.EntityBase)
|
||||
ESP32CameraImageData = esp32_camera_ns.struct("CameraImageData")
|
||||
@@ -163,6 +163,14 @@ CONF_ON_IMAGE = "on_image"
|
||||
|
||||
camera_range_param = cv.int_range(min=-2, max=2)
|
||||
|
||||
|
||||
def validate_fb_location_(value):
|
||||
validator = cv.enum(ENUM_FB_LOCATION, upper=True)
|
||||
if value.lower() == psram_domain:
|
||||
validator = cv.All(validator, cv.requires_component(psram_domain))
|
||||
return validator(value)
|
||||
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
cv.ENTITY_BASE_SCHEMA.extend(
|
||||
{
|
||||
@@ -236,9 +244,9 @@ CONFIG_SCHEMA = cv.All(
|
||||
cv.framerate, cv.Range(min=0, max=1)
|
||||
),
|
||||
cv.Optional(CONF_FRAME_BUFFER_COUNT, default=1): cv.int_range(min=1, max=2),
|
||||
cv.Optional(CONF_FRAME_BUFFER_LOCATION, default="PSRAM"): cv.enum(
|
||||
ENUM_FB_LOCATION, upper=True
|
||||
),
|
||||
cv.Optional(
|
||||
CONF_FRAME_BUFFER_LOCATION, default="PSRAM"
|
||||
): validate_fb_location_,
|
||||
cv.Optional(CONF_ON_STREAM_START): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||
|
||||
@@ -20,8 +20,7 @@ import esphome.final_validate as fv
|
||||
|
||||
from .const import INKPLATE_10_CUSTOM_WAVEFORMS, WAVEFORMS
|
||||
|
||||
DEPENDENCIES = ["i2c", "esp32"]
|
||||
AUTO_LOAD = ["psram"]
|
||||
DEPENDENCIES = ["i2c", "esp32", "psram"]
|
||||
|
||||
CONF_DISPLAY_DATA_0_PIN = "display_data_0_pin"
|
||||
CONF_DISPLAY_DATA_1_PIN = "display_data_1_pin"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import logging
|
||||
import textwrap
|
||||
|
||||
import esphome.codegen as cg
|
||||
from esphome.components.esp32 import (
|
||||
@@ -104,6 +105,17 @@ def get_config_schema(config):
|
||||
if not speeds:
|
||||
raise cv.Invalid("PSRAM is not supported on this chip")
|
||||
modes = SPIRAM_MODES[variant]
|
||||
if CONF_MODE not in config and len(modes) != 1:
|
||||
raise (
|
||||
cv.Invalid(
|
||||
textwrap.dedent(
|
||||
f"""
|
||||
{variant} requires PSRAM mode selection; one of {", ".join(modes)}
|
||||
Selection of the wrong mode for the board will cause a runtime failure to initialise PSRAM
|
||||
"""
|
||||
)
|
||||
)
|
||||
)
|
||||
return cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(PsramComponent),
|
||||
|
||||
@@ -26,21 +26,12 @@ from esphome.const import (
|
||||
from esphome.core import CORE, HexInt
|
||||
from esphome.core.entity_helpers import inherit_property_from
|
||||
from esphome.external_files import download_content
|
||||
from esphome.types import ConfigType
|
||||
from esphome.final_validate import full_config
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def AUTO_LOAD(config: ConfigType) -> list[str]:
|
||||
load = ["audio"]
|
||||
if (
|
||||
not config
|
||||
or config.get(CONF_TASK_STACK_IN_PSRAM)
|
||||
or config.get(CONF_CODEC_SUPPORT_ENABLED)
|
||||
):
|
||||
return load + ["psram"]
|
||||
return load
|
||||
|
||||
AUTO_LOAD = ["audio"]
|
||||
|
||||
CODEOWNERS = ["@kahrendt", "@synesthesiam"]
|
||||
DOMAIN = "media_player"
|
||||
@@ -226,12 +217,19 @@ def _validate_repeated_speaker(config):
|
||||
return config
|
||||
|
||||
|
||||
def _validate_supported_local_file(config):
|
||||
def _final_validate(config):
|
||||
# Default to using codec if psram is enabled
|
||||
if (use_codec := config.get(CONF_CODEC_SUPPORT_ENABLED)) is None:
|
||||
use_codec = psram.DOMAIN in full_config.get()
|
||||
conf_id = config[CONF_ID].id
|
||||
core_data = CORE.data.setdefault(DOMAIN, {conf_id: {}})
|
||||
core_data[conf_id][CONF_CODEC_SUPPORT_ENABLED] = use_codec
|
||||
|
||||
for file_config in config.get(CONF_FILES, []):
|
||||
_, media_file_type = _read_audio_file_and_type(file_config)
|
||||
if str(media_file_type) == str(audio.AUDIO_FILE_TYPE_ENUM["NONE"]):
|
||||
raise cv.Invalid("Unsupported local media file")
|
||||
if not config[CONF_CODEC_SUPPORT_ENABLED] and str(media_file_type) != str(
|
||||
if not use_codec and str(media_file_type) != str(
|
||||
audio.AUDIO_FILE_TYPE_ENUM["WAV"]
|
||||
):
|
||||
# Only wav files are supported
|
||||
@@ -290,11 +288,11 @@ CONFIG_SCHEMA = cv.All(
|
||||
cv.Optional(CONF_BUFFER_SIZE, default=1000000): cv.int_range(
|
||||
min=4000, max=4000000
|
||||
),
|
||||
cv.Optional(
|
||||
CONF_CODEC_SUPPORT_ENABLED, default=psram.supported()
|
||||
): cv.boolean,
|
||||
cv.Optional(CONF_CODEC_SUPPORT_ENABLED): cv.boolean,
|
||||
cv.Optional(CONF_FILES): cv.ensure_list(MEDIA_FILE_TYPE_SCHEMA),
|
||||
cv.Optional(CONF_TASK_STACK_IN_PSRAM, default=False): cv.boolean,
|
||||
cv.Optional(CONF_TASK_STACK_IN_PSRAM): cv.All(
|
||||
cv.boolean, cv.requires_component(psram.DOMAIN)
|
||||
),
|
||||
cv.Optional(CONF_VOLUME_INCREMENT, default=0.05): cv.percentage,
|
||||
cv.Optional(CONF_VOLUME_INITIAL, default=0.5): cv.percentage,
|
||||
cv.Optional(CONF_VOLUME_MAX, default=1.0): cv.percentage,
|
||||
@@ -317,12 +315,12 @@ FINAL_VALIDATE_SCHEMA = cv.All(
|
||||
},
|
||||
extra=cv.ALLOW_EXTRA,
|
||||
),
|
||||
_validate_supported_local_file,
|
||||
_final_validate,
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
if config[CONF_CODEC_SUPPORT_ENABLED]:
|
||||
if CORE.data[DOMAIN][config[CONF_ID].id][CONF_CODEC_SUPPORT_ENABLED]:
|
||||
# Compile all supported audio codecs and optimize the wifi settings
|
||||
|
||||
cg.add_define("USE_AUDIO_FLAC_SUPPORT", True)
|
||||
@@ -352,8 +350,8 @@ async def to_code(config):
|
||||
|
||||
cg.add(var.set_buffer_size(config[CONF_BUFFER_SIZE]))
|
||||
|
||||
cg.add(var.set_task_stack_in_psram(config[CONF_TASK_STACK_IN_PSRAM]))
|
||||
if config[CONF_TASK_STACK_IN_PSRAM]:
|
||||
if config.get(CONF_TASK_STACK_IN_PSRAM):
|
||||
cg.add(var.set_task_stack_in_psram(True))
|
||||
esp32.add_idf_sdkconfig_option(
|
||||
"CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY", True
|
||||
)
|
||||
|
||||
@@ -34,6 +34,12 @@ SUPPORTED_PSRAM_VARIANTS = [
|
||||
VARIANT_ESP32S3,
|
||||
VARIANT_ESP32P4,
|
||||
]
|
||||
SUPPORTED_PSRAM_MODES = {
|
||||
VARIANT_ESP32: ["quad"],
|
||||
VARIANT_ESP32S2: ["quad"],
|
||||
VARIANT_ESP32S3: ["quad", "octal"],
|
||||
VARIANT_ESP32P4: ["hex"],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -86,7 +92,7 @@ def test_psram_configuration_valid_supported_variants(
|
||||
from esphome.components.psram import CONFIG_SCHEMA, FINAL_VALIDATE_SCHEMA
|
||||
|
||||
# This should not raise an exception
|
||||
config = CONFIG_SCHEMA({})
|
||||
config = CONFIG_SCHEMA({"mode": SUPPORTED_PSRAM_MODES[variant][0]})
|
||||
FINAL_VALIDATE_SCHEMA(config)
|
||||
|
||||
|
||||
@@ -122,7 +128,7 @@ def _setup_psram_final_validation_test(
|
||||
("config", "esp32_config", "expect_error", "error_match"),
|
||||
[
|
||||
pytest.param(
|
||||
{"speed": "120MHz"},
|
||||
{"mode": "quad", "speed": "120MHz"},
|
||||
{"cpu_frequency": "160MHz"},
|
||||
True,
|
||||
r"PSRAM 120MHz requires 240MHz CPU frequency",
|
||||
@@ -143,7 +149,7 @@ def _setup_psram_final_validation_test(
|
||||
id="ecc_only_in_octal_mode",
|
||||
),
|
||||
pytest.param(
|
||||
{"speed": "120MHZ"},
|
||||
{"mode": "quad", "speed": "120MHZ"},
|
||||
{"cpu_frequency": "240MHZ"},
|
||||
False,
|
||||
None,
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
packages:
|
||||
i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml
|
||||
|
||||
psram:
|
||||
mode: quad
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
@@ -9,3 +9,4 @@ display:
|
||||
lvgl:
|
||||
|
||||
psram:
|
||||
mode: quad
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# I2C bus for camera sensor
|
||||
psram:
|
||||
|
||||
i2c:
|
||||
- id: i2c_camera_bus
|
||||
sda: 25
|
||||
|
||||
Reference in New Issue
Block a user