[st7701s] Keep the init sequence in a shared PROGMEM table

This commit is contained in:
J. Nick Koston
2026-10-02 20:55:04 -05:00
parent ebef8390aa
commit 83b38d9cdd
5 changed files with 72 additions and 5 deletions
+2 -1
View File
@@ -181,7 +181,8 @@ async def to_code(config: ConfigType) -> None:
sequence = []
for seq in config[CONF_INIT_SEQUENCE]:
sequence.extend(seq)
cg.add(var.set_init_sequence(sequence))
table = cg.shared_progmem_array("st7701s_init_sequence", cg.uint8, sequence)
cg.add(var.set_init_sequence(table, len(sequence)))
cg.add(var.set_color_mode(COLOR_ORDERS[config[CONF_COLOR_ORDER]]))
cg.add(var.set_invert_colors(config[CONF_INVERT_COLORS]))
cg.add(var.set_hsync_pulse_width(config[CONF_HSYNC_PULSE_WIDTH]))
+2 -2
View File
@@ -144,14 +144,14 @@ void ST7701S::write_sequence_(uint8_t cmd, size_t len, const uint8_t *bytes) {
}
void ST7701S::write_init_sequence_() {
for (size_t i = 0; i != this->init_sequence_.size();) {
for (size_t i = 0; i != this->init_sequence_len_;) {
uint8_t cmd = this->init_sequence_[i++];
size_t len = this->init_sequence_[i++];
if (len == ST7701S_DELAY_FLAG) {
ESP_LOGV(TAG, "Delay %dms", cmd);
delay(cmd);
} else {
this->write_sequence_(cmd, len, &this->init_sequence_[i]);
this->write_sequence_(cmd, len, this->init_sequence_ + i);
i += len;
ESP_LOGV(TAG, "Command %X, %d bytes", cmd, len);
if (cmd == SW_RESET_CMD)
+7 -2
View File
@@ -62,7 +62,10 @@ class ST7701S 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<uint8_t> &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_mirror_x(bool mirror_x) { this->mirror_x_ = mirror_x; }
void set_mirror_y(bool mirror_y) { this->mirror_y_ = mirror_y; }
void set_offsets(int16_t offset_x, int16_t offset_y) {
@@ -95,7 +98,9 @@ class ST7701S final : public display::Display,
uint16_t vsync_pulse_width_ = 10;
uint16_t vsync_back_porch_ = 10;
uint16_t vsync_front_porch_ = 10;
std::vector<uint8_t> init_sequence_;
// Shared PROGMEM table
const uint8_t *init_sequence_{nullptr};
size_t init_sequence_len_{0};
uint32_t pclk_frequency_ = 16 * 1000 * 1000;
bool pclk_inverted_{true};
@@ -0,0 +1,61 @@
"""Tests for the st7701s init sequence codegen."""
from collections.abc import Callable
from pathlib import Path
import re
_YAML = """
esphome:
name: st7701s-test
esp32:
board: esp32-s3-devkitc-1
framework:
type: esp-idf
psram:
mode: octal
spi:
clk_pin: 10
mosi_pin: 11
display:
{displays}
"""
_DISPLAY = """
- platform: st7701s
id: {display_id}
dimensions:
width: 480
height: 480
cs_pin: {cs_pin}
de_pin: 18
hsync_pin: 16
vsync_pin: 17
pclk_pin: 21
init_sequence:
- 1
- [0x23, 0xA, 0xB]
- delay 20ms
data_pins: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 38, 39]
"""
def test_init_sequence_is_progmem_table(
generate_main: Callable[[str | Path], str],
tmp_path: Path,
) -> None:
"""The init sequence is a PROGMEM table instead of a vector copied at boot."""
yaml_file = tmp_path / "st7701s.yaml"
yaml_file.write_text(
_YAML.format(displays=_DISPLAY.format(display_id="panel", cs_pin=44))
)
main_cpp = generate_main(yaml_file)
call = re.search(r"panel->set_init_sequence\((\w+), (\d+)\);", main_cpp)
assert call is not None
table = re.search(
rf"static constexpr uint8_t {call.group(1)}\[\] PROGMEM = \{{([^;]*)\}};",
main_cpp,
)
assert table is not None
assert len(table.group(1).split(",")) == int(call.group(2))