From f91ac5ed1d3226113957d912b265ca0915ae5c15 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 4 Oct 2026 21:20:56 -0500 Subject: [PATCH] [mipi_dsi] Keep the init sequence in flash (#20091) --- esphome/components/mipi_dsi/display.py | 3 ++- esphome/components/mipi_dsi/mipi_dsi.cpp | 15 ++++++++------- esphome/components/mipi_dsi/mipi_dsi.h | 9 +++++++-- .../mipi_dsi/test_mipi_dsi_config.py | 8 +++++++- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/esphome/components/mipi_dsi/display.py b/esphome/components/mipi_dsi/display.py index b23982655a..6bf94bf364 100644 --- a/esphome/components/mipi_dsi/display.py +++ b/esphome/components/mipi_dsi/display.py @@ -201,7 +201,8 @@ async def to_code(config: ConfigType) -> None: sequence = model.get_sequence(config) cg.add(var.set_model(config[CONF_MODEL])) - cg.add(var.set_init_sequence(sequence)) + table = cg.shared_progmem_array("mipi_dsi_init_sequence", cg.uint8, sequence) + cg.add(var.set_init_sequence(table, len(sequence))) cg.add(var.set_invert_colors(config[CONF_INVERT_COLORS])) cg.add(var.set_hsync_pulse_width(config[CONF_HSYNC_PULSE_WIDTH])) cg.add(var.set_hsync_back_porch(config[CONF_HSYNC_BACK_PORCH])) diff --git a/esphome/components/mipi_dsi/mipi_dsi.cpp b/esphome/components/mipi_dsi/mipi_dsi.cpp index b6612038b6..a27be568f2 100644 --- a/esphome/components/mipi_dsi/mipi_dsi.cpp +++ b/esphome/components/mipi_dsi/mipi_dsi.cpp @@ -121,20 +121,21 @@ void MipiDsi::setup() { return; } size_t index = 0; - auto &vec = this->init_sequence_; - while (index != vec.size()) { - if (vec.size() - index < 2) { + const uint8_t *seq = this->init_sequence_; + const size_t len = this->init_sequence_len_; + while (index != len) { + if (len - index < 2) { this->mark_failed(LOG_STR("Malformed init sequence")); return; } - uint8_t cmd = vec[index++]; - uint8_t x = vec[index++]; + uint8_t cmd = seq[index++]; + uint8_t x = seq[index++]; if (x == DELAY_FLAG) { ESP_LOGD(TAG, "Delay %dms", cmd); delay(cmd); } else { uint8_t num_args = x & 0x7F; - if (vec.size() - index < num_args) { + if (len - index < num_args) { this->mark_failed(LOG_STR("Malformed init sequence")); return; } @@ -145,7 +146,7 @@ void MipiDsi::setup() { delay(duration); } } - const auto *ptr = vec.data() + index; + const auto *ptr = seq + index; #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE char hex_buf[format_hex_pretty_size(MIPI_DSI_MAX_CMD_LOG_BYTES)]; #endif diff --git a/esphome/components/mipi_dsi/mipi_dsi.h b/esphome/components/mipi_dsi/mipi_dsi.h index 7bf2feb73c..4243d3116c 100644 --- a/esphome/components/mipi_dsi/mipi_dsi.h +++ b/esphome/components/mipi_dsi/mipi_dsi.h @@ -55,7 +55,10 @@ class MipiDsi final : public display::Display { void set_vsync_pulse_width(uint16_t vsync_pulse_width) { this->vsync_pulse_width_ = vsync_pulse_width; } void set_vsync_back_porch(uint16_t vsync_back_porch) { this->vsync_back_porch_ = vsync_back_porch; } void set_vsync_front_porch(uint16_t vsync_front_porch) { this->vsync_front_porch_ = vsync_front_porch; } - void set_init_sequence(const std::vector &init_sequence) { this->init_sequence_ = init_sequence; } + void set_init_sequence(const uint8_t *init_sequence, size_t len) { + this->init_sequence_ = init_sequence; + this->init_sequence_len_ = len; + } void set_model(const char *model) { this->model_ = model; } void set_lane_bit_rate(float lane_bit_rate) { this->lane_bit_rate_ = lane_bit_rate; } void set_lanes(uint8_t lanes) { this->lanes_ = lanes; } @@ -91,7 +94,9 @@ class MipiDsi final : public display::Display { uint16_t vsync_back_porch_ = 10; uint16_t vsync_front_porch_ = 10; const char *model_{"Unknown"}; - std::vector init_sequence_{}; + // Shared PROGMEM table + const uint8_t *init_sequence_{nullptr}; + size_t init_sequence_len_{0}; float pclk_frequency_ = 16; // in MHz float lane_bit_rate_{1500}; // in Mbps uint8_t lanes_{2}; // 1, 2, 3 or 4 lanes diff --git a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py index 6259d85184..ac385cc2d8 100644 --- a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py +++ b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py @@ -3,6 +3,7 @@ from collections.abc import Callable import logging from pathlib import Path +import re import pytest @@ -201,7 +202,12 @@ def test_code_generation( "new(p4_nano) mipi_dsi::MipiDsi(800, 1280, display::COLOR_BITNESS_565, 16);" in main_cpp ) - assert "set_init_sequence({224, 1, 0, 225, 1, 147, 226, 1," in main_cpp + seq = re.search(r"p4_nano->set_init_sequence\((\w+), \d+\);", main_cpp) + assert seq is not None + assert ( + f"static constexpr uint8_t {seq.group(1)}[] PROGMEM = " + "{224, 1, 0, 225, 1, 147, 226, 1," in main_cpp + ) assert "p4_nano->set_lane_bit_rate(1500.0f);" in main_cpp assert "p4_nano->set_rotation(display::DISPLAY_ROTATION_90_DEGREES);" in main_cpp assert "p4_86->set_rotation(display::DISPLAY_ROTATION_0_DEGREES);" not in main_cpp